|  | 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. | 
|  |  |