How SVN deals with Server Certs This is a description of a design for issue #1330, which is one of the last "enhancements" for pre-1.0 subversion, scheduled for svn 0.31. The goal here is to essentially toss the existing server-certificate validation code, and replace it with a totally new system that allows permanent server-cert disk caching, just like a web browser. ------------------------------------------------------------------- CURRENT SYSTEM ============== * neon gets a server cert, signed by some CA. * neon tries to verify it against trusted CAs that were loaded earlier (either the 'default' system CAs, or specific ones listed in the 'servers' file.) * if FAILURE, neon calls libsvn_ra_dav/session.c:server_ssl_callback(): * this function receives the server cert and the reason for failure. the reason can be: {untrusted CA, expired, not yet valid, mismatched name.} * our implementation of the callback currently calls the svn auth system, looking for a specific "SERVER_SSL" kind of credential from the user. This credential is a set of flags indicating what failures the user will allow. - the callback (implicitly) passes the failure information to our credential providers. - the first 'provider' checks the servers file for specifics. - if that fails, the 2nd provider prompts the user, describing the kind of failure(s). * the returned credential is compared to the actual set of failures, and the callback either returns "ok" or "not ok" to neon. ---------------------------------------------------------------------- NEW PROPOSED SYSTEM =================== 1. Toss the old SERVER_SSL cred-kind, and both providers. 2. Create a completely new cred-kind, with two fields: { const char *server_cert; /* stringified somehow */ svn_boolean_t trust_forever; } 3. Write a disk provider for the new cred-kind: - get_cred() takes a realmstring as input, as always. The realmstring (key) is based on the certificate fingerprint. It then searches the auth caching area in ~/.subversion/auth/, and returns a server cert credential, with trust_forever=TRUE. - save_cred() writes the server_cert into the auth caching area, with filename equal to the realmstring. There's no point in saving the 'trust_forever' field in the disk cache. :-) 4. Write a prompt provider for the new cred-kind: - "The server cert could not be trusted, due to problem XXXXX. The server cert is YYYYY. [probably print a fingerprint] Trust (t)emporarily, (f)orever, (n)ot at all?" - this provider assumes the auth_baton hash contains XXXX and YYYY already. (the caller places the info there.) - if XXXXX is 'unknown CA', then give the (f)orever or (t)emporary options. if XXXXX is 'invalid date' or 'host mismatch', *only* give (t)emporary option. - if the user answers (t) or (f), return a credential struct with YYYY as the first field, and trust_forever={true|false} set accordingly. 5. When to call the new providers: Put new logic into the main server_ssl_callback(). * Put the server-cert into the auth_baton hash, so providers can see it, along with the error type. * call svn_auth_first_creds with properly constructed realmstring: * if we get a credential back from the disk provider, match it to the current fingerprint of the incoming server cert. if they match, we have success. tell neon it's ok to proceed. * if we get nothing back, call svn_auth_next_creds(), which should invoke the prompt provider. If a cred comes back, we know the fingerprint will match, instant success for neon. Also, if trust_forever=true, call svn_auth_save_creds(), which will cause the disk provider's save function to kick in. 6. Destroy all three of the ssl-ignore-* variables in ~/.subversion/servers. We no longer need them. For unknown-CA errors, we give users the option to cache the cert permanently. For invalid-date or host-mismatch errors, we give users the option to ignore temporarily. The subversion client will behave the same way a web browser does, which is Good.