General lighting can be very complicated. A light bulb is not a single point of light but rather a surface from which light is emitted. To find the net effect at a given point in space we would have to integrate all the contributions on the surface. To simplify life, we generally model light as a point source, a spot light with a preferential range of angles, or a light direction. (Think of the sun as an example of the latter.) Also, light should fall off with the square of the distance from the source, but this is rather expensive to calculate. OpenGL supports quadratic, linear, or constant light attenuation; constant is the default (for greatest speed).
We will use the Phong shading model. Light comes in ambient, diffuse, and specular flavors. Ambient light is just a cheap way to bring up the house lights  we illuminate everything uniformly. (Actually, we will specify coefficents for different materials which specify the fractions of ambient, diffuse and specular light reflected, so we don't have to make everything uniform with ambient light.) Diffuse light models the effect of rough surfaces  light is scattered equally in all directions, and depends only on the angle between the light vector and the normal vector. It works well to make the diffuse light proportional to the cosine of the angle between the light vector l and the normal vector n, which is just l * n if the two vectors are normalized.
The specular light models the shiny patches that indicate a surface to be hard and reflective, like chrome. Ideally we would find the cosine of the angle between the reflected vector (which makes the same angle with the normal that the light vector does, and which lies in the plane of the light and normal vectors), and raise this to some power (to create a rapid falloff) to get the specular component. It is computationally more effecient to take the cosine of half this angle, since it is the angle between the normal and the "halfway vector" h which is the average of the light and viewer vectors. If we normalize h, we can raise n * h to a smaller power to obtain the same effect very cheaply.
It is important to realize how OpenGL uses these three components. The normals, light vectors and view vector are used at each polygon vertex to calculate proper colors at the vertices. Then these colors are simply linearly interpolated between vertices, a process called Gouraud shading (or smooth shading). If we interpolated the normals to recalculate the color at each point we would be using Phong shading  a much more expensive prospect (but appropriate for creating one frame at a time for later sequencing). To get the shiny patches we associate with metal surfaces in OpenGL we must use lots of small polygons  we won't get the effect in a large polygon.
To illustrate, the following program recursively subdivides a cube to approximate a sphere. A quadrilateral is simply drawn if the recursion level is down to zero, otherwise it is carved into 4 pieces (with the vertices of each piece rescaled to be the same distance, sqrt(3), as the original 8 vertices of the cube) and these are drawn with recursion level one less. We specify specular, diffuse and ambient compenents of the light and material. A keypress increases the recursion depth. Here are the first few images:
Depth 0 

Depth 1 

Depth 2 

Depth 3 

Depth 4 

Depth 5 
And here is the source code:
// recursive subdivision of cubeNote that if the surface normal is not specified, by simply commenting out the line
glNormal3fv(n);in drawFace, then we get a much less interesting picture: