Certificate chains are a key feature of the entire SSL/TLS concept: a root Certificate Authority (CA) issues certificates for sub CAs, which in turn issue certificates for other sub CAs or end systems such as servers. The Sub CAs are often local departments, branch offices etc. and issuing a certificate for a sub CA, which indicates that this CA is allowed to issue certificates on its own, effectively corresponds to the concept of delegation of competence.
When a client receives a certificate, say for frankfurt.foo.bar, it has to know how to validate the certificate. Validation is done by tracing the signature on the certificate back to a previously known root certificate. “Previously known” means that the software validating the certificate has some sort of bundle of trusted root certificates somewhere. For example, Windows has a built-in certificate store accessible using the Microsoft Management Console (mmc) whereas with OpenSSL installations usually use one file per certificate stored in a location such as /etc/ssl/certs/. Web browsers such as Firefox also come with their own select list of trusted root certificates (try Preferences -> Advanced -> Encryption -> Show certificates -> Certificate Authorities). A certificate that is not signed by one of the CAs in this list will trigger an explicit warning, the Firefox dialog shown in this case nearly scares the user away from such Websites by intent.
Now the case for certificates signed by those root CAs is quite clear, but what happens with a certificate chain such as MyRootCA -> Frankfurt Ops CA -> frankfurt.foo.bar? Frankfurt Ops CA would be what is called an intermediate certificate. The leaf certificate for frankfurt.foo.bar would have been issued by this intermediate CA, for which the client does not have a known certificate. Because of this reason, frankfurt.foo.bar must send all certificates along with its own certificate so that the client can perform validation. This is what Apache’s SSLCertificateChainFile option is used for.
But what does this do with the client? Actually, client behaviour differs. If you use openssl s_client -showcerts -connect host:port, for instance, you will get a result such as Verify return code: 20 (unable to get local issuer certificate). This is because the s_client utility ignores the supplied certs even if they trace back to a locally known root certificate.
Firefox, by contrast, does something actually quite intelligent: any intermediate certificates issued by trusted root CAs and referenced by validated leaf certificates are automagically added to the internal list of trusted Certificate Authorities. And that’s why it is sufficient to add a custom root CA once and have all leaf certificates validated without adding the required intermediate certificates.