blob: 6118ff7938b4eca1776bd41d83c090246ce7c724 [file] [log] [blame]
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.