Some of this will apply to #PySVN as well.
# SSL Certificate Trust
## Certificate Representations
* Fingerprints seem to be SHA1 (but may depend on the certificate?)
libsvn defines this in `svn_auth.h`:
```c
typedef struct svn_auth_ssl_server_cert_info_t
{
/** Primary CN */
const char *hostname;
/** ASCII fingerprint */
const char *fingerprint;
/** ASCII date from which the certificate is valid */
const char *valid_from;
/** ASCII date until which the certificate is valid */
const char *valid_until;
/** DN of the certificate issuer */
const char *issuer_dname;
/** Base-64 encoded DER certificate representation */
const char *ascii_cert;
} svn_auth_ssl_server_cert_info_t;
```
PySVN's representation looks like:
```json
{
'failures': <int>,
'hostname': <str>,
'finger_print': <SHA1 ':'-separated str>,
'valid_from': <ISO8601 timestamp>,
'valid_until': <ISO8601 timestamp>,
'issuer_dname': '<hostname>, <entity>, <city>, <state>, <country>',
'realm': 'https://<hostname>:<port>'
}
```
E.g.,
```json
{
'failures': 8,
'hostname': '*.badssl.com',
'finger_print': '1D:B8:69:1E:B3:C4:52:9E:6A:BE:E4:1B:F3:54:74:A5:C7:A3:BA:8E',
'valid_from': 'Jul 21 21:56:12 2023 GMT',
'valid_until': 'Jul 20 21:56:12 2025 GMT',
'issuer_dname': '*.badssl.com, BadSSL, San Francisco, California, US',
'realm': 'https://self-signed.badssl.com:443'
}
```
## Callback handlers/providers
In libsvn, all the functions below return a "provider" (`svn_auth_provider_object_t*`) that can be used when authenticating (`svn_auth_open()`). Not all of the below provide configuration options or callbacks.
### SSL Client Cert File Provider
* Used to look up local client certificates when requested by the server for certificate-based authentication (see https://subgit.com/documentation/auth-book.html#ssl)
* This does not provide any configuration.
**libsvn:** `svn_auth_get_ssl_server_trust_file_provider`
```c
// Signatures
void
svn_auth_get_ssl_server_trust_file_provider(
svn_auth_provider_object_t** provider,
apr_pool_t* pool);
// Usage
svn_auth_provider_object_t* provider = NULL;
svn_auth_get_ssl_client_trust_file_provider(
&provider,
pool);
```
**PySVN:** None (handled internally)
### SSL Client Cert Prompt Provider
* Used to prompt for a certificate file when using certificate-based authentication.
**libsvn:** `svn_auth_get_ssl_client_cert_prompt_provider`
```c
// Signatures
typedef struct {
const char* cert_file;
svn_boolean_t may_save;
} svn_auth_cred_ssl_cilent_cert_t;
typedef svn_eror_t*(*svn_auth_ssl_client_cert_prompt_func_t)(
svn_auth_cred_ssl_client_cert_t** cred,
void* baton,
const char* realm,
svn_boolean_t may_save,
apr_pool_t* pool);
void
svn_auth_get_ssl_client_cert_prompt_provider(
svn_auth_provider_object_t** provider,
svn_auth_ssl_client_cert_prompt_func_t prompt_func,
void* prompt_baton,
int retry_limit,
apr_pool_t* pool);
// Usage
svn_error_t*
_ssl_client_cert_prompt(
svn_auth_cred_ssl_client_cert_t** cred,
void* baton,
const char* realm,
svn_boolean_t may_save,
apr_pool_t* pool)
{
// Set `cred`
}
svn_auth_provider_object_t* provider = NULL;
svn_auth_get_ssl_client_cert_prompt_provider(
&provider,
_ssl_client_cert_prompt,
customCallbackData, // The "baton"
retry_limit,
pool);
```
**PySVN:** `Client.callback_ssl_client_cert_prompt`
```python
def _ssl_client_cert_prompt(
```
### SSL Client Cert Password Prompt Provider
* Used to prompt for a password for a certificate.
* There are two versions of this in libsvn. Only documenting the first.
**libsvn:** `svn_auth_get_ssl_client_cert_pw_file_provider2`
**PySVN:** None (not available)
### SSL Server Trust File Provider
* Used to look up trust information from the Subversion trust.
* This does not provide any configuration.
**libsvn:** `svn_auth_get_ssl_server_trust_file_provider`
```c
svn_auth_provider_object_t* provider = NULL;
svn_auth_get_ssl_server_trust_file_provider(
&provider,
pool);
```
**PySVN:** None (handled internally)
### SSL Server Trust Prompt Provider
* Used to determine if a certificate is valid (for implementing verification or a custom trust store).
* Can optionally tell Subversion to save the verification for the trust dictionary via `may_save`.
**libsvn:** `svn_auth_get_ssl_server_trust_prompt_provider`
```c
typedef struct {
svn_boolean_t may_save;
apr_uint32_t accepted_failures;
} svn_auth_cred_ssl_server_trust_t;
svn_error_t*
_ssl_server_trust_prompt(
svn_auth_cred_ssl_sever_trust_t** cred,
void* baton,
const char* realm,
apr_uint32_t failures,
const svn_auth_ssl_server_cert_info_t* cert_info,
svn_boolean_t may_save,
apr_pool_t* pool)
{
// Set `cred`
}
svn_auth_provider_object_t* provider = NULL;
svn_auth_get_ssl_server_trust_prompt_provider(
&provider,
_ssl_server_trust_prompt,
customCallbackData, // The "baton"
pool);
```
* https://subversion.apache.org/docs/api/1.7/svn__auth_8h.html#a204388c3be43bff3c51e4490d7f40f43
**PySVN:** `Client.callback_ssl_server_trust_prompt`
```python
class TrustDict(TypedDict):
failures: int
finger_print: str
hostname: str
issuer_dname: str
realm: str
valid_from: str
valid_until: str
def _ssl_server_trust_prompt(
trust_data: TrustDict.
) -> Tuple[bool, int, bool]:
# Return (verified, failures, may_save).
...
client.callback_ssl_server_trust_prompt = _ssl_server_trust_prompt
```