There's going to be a lot of ignorance in this question so please bear with:
My understanding of a standard browser-client to server SSL connection involves:
- Browser connects to server via HTTPS
- Browser requests server SSL certificate
- Browser verifies certificate against the third party CA (certificate authority) that issued it.
- Browser and server speak over an open SSL-connection, and certificate is not needed/downloaded again until a new connection is established (i.e. the next postback).
If I've already mangled it, correct me so far, but now I'm trying to wrap my head around what happens when an SSL-connection is made from one server acting as a client to another server acting as server, and PHP is making the call. Is it essentially the same process? Does the client-server go through the same steps as the browser-client?
In an apache environment, does the the client-server need to be set up in a certain way?
You've got the process, essentially. The specifics of how your PHP code will act in verifying the server's certificate is going to depend on the method you're using to access the server. The PHP cURL library, for example, has a 'CURLOPT_SSL_VERIFYPEER' option that you can set to make the library verify the peer's certificate.
The only difference is that you're going to be writing the code rather than say, Mozilla. So if you want, you can decide that non-valid certificates will still work. But yes, the same principle applies. "Server" is just a misnomer. Your server is the client in the connection it opens to that other server. So the difference revolves around the fact that you're writing the client code rather than using it.
Since you explicitly invited pedantry:
This is incorrect. The browser connects to the server (almost always) via TCP, (almost always) on the HTTPS port, 443. This entire process could be considered as the browser connecting via HTTPS, but then the rest of the process is redundant.
This is correct; more specifically, the browser sends a ClientHello, which consists of a protocol version number, a randomly-generated nonce, an SSL session ID (unrelated to things like PHPSESSID; this is essentially a hack to avoid costly secret key regeneration), the supported cipher suites of the client (see
openssl ciphers
), and an unused field originally intended to support compression.The server then responds with a ServerHello, its certificate, an optional nonce key, and an optional request for the client's certificate (very rarely used). It then sends a Done to let the browser know it's waiting for its response.
The browser may also use additional certificates in the chain, either locally cached or provided along with the server certificate, in order to chain back to a trusted CA. Each certificate is checked for permissions, as well--just because I have a certificate for somesite.com doesn't mean I can use that certificate to sign a cert for anothersite.com; my somesite.com cert has a constraint saying that it's not allowed to sign subordinate certs.
There are actually two (and a half) more exchanges; the client has to prove its possession of the ClientCert, and it has to propose a premaster secret, which it will send to the server, encrypted by the server's public key. Since only the holder of the private key associated with the certificate sent by the server is able to decrypt this key, the client is assured that only its intended recipient has the premaster secret it has selected. The client also confirms that it's ready to start sending actual, encrypted data, and hashes all the data up to this point so the server can know it was talking to the same client all along. Finally, the server confirms that they're about to start speaking using the mutually-known (but secret to an eavesdropper) symmetric key, and hashes all its data to prove to the client that everyone's on the same page. After that, HTTP happens as normal, going over the Record stream, which chops it up and encrypts it, while a separate Alert stream is used to manage the session itself.
Back on topic, in your specific case, the fact that the server issuing the request is, itself, a server, is immaterial. From the standpoint of the server to which it's connecting, it's just another client. The only weird point is that the server-client doesn't have the ability to interactively handle certificate authentication errors, so you'll need to make sure you've handled them ahead of time, either by disabling authentication of the certificate entirely (for testing, not for production, of course!), or by ensuring that appropriate CA certificates are available to the HTTPS connection method you've chosen.