e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#ifndef IOSTREAM_SSL_H
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#define IOSTREAM_SSL_H
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstruct ssl_iostream;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstruct ssl_iostream_context;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomistruct ssl_iostream_cert {
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomi const char *cert;
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomi const char *key;
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomi const char *key_password;
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomi};
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomi
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstruct ssl_iostream_settings {
25aa88dd96482cb1a135d3e962b7936500dcaab5Timo Sirainen /* NOTE: when updating, remember to update:
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen ssl_iostream_settings_string_offsets[],
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen ssl_iostream_settings_drop_stream_only() */
976dee5384c4827dc648c9bc53825390521c388eMartti Rannanjärvi const char *min_protocol; /* both */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen const char *cipher_list; /* both */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen const char *curve_list; /* both */
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen const char *ca, *ca_file, *ca_dir; /* context-only */
0577701d04beea222fc49a7318851ddcea3b99d3Aki Tuomi /* alternative cert is for providing certificate using
0577701d04beea222fc49a7318851ddcea3b99d3Aki Tuomi different key algorithm */
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomi struct ssl_iostream_cert cert; /* both */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen struct ssl_iostream_cert alt_cert; /* both */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen const char *dh; /* context-only */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen const char *cert_username_field; /* both */
6a4212e6d7c41de83bcac63edec3118e6a7a0f68Timo Sirainen const char *crypto_device; /* context-only */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
6a4212e6d7c41de83bcac63edec3118e6a7a0f68Timo Sirainen bool verbose, verbose_invalid_cert; /* stream-only */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen bool skip_crl_check; /* context-only */
6a4212e6d7c41de83bcac63edec3118e6a7a0f68Timo Sirainen bool verify_remote_cert; /* neither/both */
095481fee84040436ce2dccca472c9bb1df4d5bbTimo Sirainen bool allow_invalid_cert; /* stream-only */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen bool prefer_server_ciphers; /* both */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen bool compression; /* context-only */
4c21d44ce3ccbd4f9851a9b87b0b93c5f6e8cf5eTimo Sirainen bool tickets; /* context-only */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen};
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
997b30e4099704d2dbe3402b890a892b71b1d640Aki Tuomi/* Load SSL module */
997b30e4099704d2dbe3402b890a892b71b1d640Aki Tuomiint ssl_module_load(const char **error_r);
997b30e4099704d2dbe3402b890a892b71b1d640Aki Tuomi
ac645fe16c0619771c0a961db91df16485513c52Timo Sirainen/* Returns 0 if ok, -1 and sets error_r if failed. The returned error string
4584a00276941db3f64c4db1a1bed91fe107af81Timo Sirainen becomes available via ssl_iostream_get_last_error(). The callback most
4584a00276941db3f64c4db1a1bed91fe107af81Timo Sirainen likely should be calling ssl_iostream_check_cert_validity(). */
ac645fe16c0619771c0a961db91df16485513c52Timo Sirainentypedef int
ac645fe16c0619771c0a961db91df16485513c52Timo Sirainenssl_iostream_handshake_callback_t(const char **error_r, void *context);
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen/* Called when TLS SNI becomes available. */
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainentypedef int ssl_iostream_sni_callback_t(const char *name, const char **error_r,
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen void *context);
ac645fe16c0619771c0a961db91df16485513c52Timo Sirainen
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen/* Explicitly initialize SSL library globally. This is also done automatically
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen when the first SSL connection is created, but it may be useful to call it
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen earlier in case of chrooting. After the initialization is successful, any
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen further calls will just be ignored. Returns 0 on success, -1 on error. */
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainenint io_stream_ssl_global_init(const struct ssl_iostream_settings *set,
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen const char **error_r);
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainenint io_stream_create_ssl_client(struct ssl_iostream_context *ctx, const char *host,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen const struct ssl_iostream_settings *set,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen struct istream **input, struct ostream **output,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen struct ssl_iostream **iostream_r,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen const char **error_r);
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainenint io_stream_create_ssl_server(struct ssl_iostream_context *ctx,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen const struct ssl_iostream_settings *set,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen struct istream **input, struct ostream **output,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen struct ssl_iostream **iostream_r,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen const char **error_r);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen/* returned input and output streams must also be unreferenced */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid ssl_iostream_unref(struct ssl_iostream **ssl_io);
38f1423a23f6c9a37c01152595ce3ca8a0a65121Timo Sirainen/* shutdown SSL connection and unreference ssl iostream */
38f1423a23f6c9a37c01152595ce3ca8a0a65121Timo Sirainenvoid ssl_iostream_destroy(struct ssl_iostream **ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen/* If verbose logging is enabled, use the specified log prefix */
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainenvoid ssl_iostream_set_log_prefix(struct ssl_iostream *ssl_io,
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen const char *prefix);
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenint ssl_iostream_handshake(struct ssl_iostream *ssl_io);
4584a00276941db3f64c4db1a1bed91fe107af81Timo Sirainen/* Call the given callback when SSL handshake finishes. The callback must
4584a00276941db3f64c4db1a1bed91fe107af81Timo Sirainen verify whether the certificate and its hostname is valid. If there is no
4584a00276941db3f64c4db1a1bed91fe107af81Timo Sirainen callback, the default is to use ssl_iostream_check_cert_validity() with the
4584a00276941db3f64c4db1a1bed91fe107af81Timo Sirainen same host as given to io_stream_create_ssl_client() */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenvoid ssl_iostream_set_handshake_callback(struct ssl_iostream *ssl_io,
ac645fe16c0619771c0a961db91df16485513c52Timo Sirainen ssl_iostream_handshake_callback_t *callback,
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen void *context);
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen/* Call the given callback when client sends SNI. The callback can change the
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen ssl_iostream's context (with different certificates) by using
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen ssl_iostream_change_context(). */
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainenvoid ssl_iostream_set_sni_callback(struct ssl_iostream *ssl_io,
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen ssl_iostream_sni_callback_t *callback,
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen void *context);
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainenvoid ssl_iostream_change_context(struct ssl_iostream *ssl_io,
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen struct ssl_iostream_context *ctx);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenbool ssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io);
71b60849a773dd68bdc015cb6a8ea1664d16b359Timo Sirainen/* Returns TRUE if the remote cert is invalid, or handshake callback returned
71b60849a773dd68bdc015cb6a8ea1664d16b359Timo Sirainen failure. */
71b60849a773dd68bdc015cb6a8ea1664d16b359Timo Sirainenbool ssl_iostream_has_handshake_failed(const struct ssl_iostream *ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenbool ssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenbool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io);
b4d850a0ffd519c1c745557568daf7d48e18c820Timo Sirainenint ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io,
b4d850a0ffd519c1c745557568daf7d48e18c820Timo Sirainen const char *host, const char **error_r);
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainen/* Returns TRUE if the given name matches the SSL stream's certificate.
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainen The returned reason is a human-readable string explaining what exactly
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainen matched the name, or why nothing matched. Note that this function works
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainen only if the certificate was valid - using it when certificate is invalid
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainen will always return FALSE before even checking the hostname. */
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainenbool ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name,
6315f87da1b28578d2deb4d51aa624dc178efb0aTimo Sirainen const char **reason_r);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenconst char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io);
48e243933060ae3e77abbdc9c0fd0bc2143be26eAki Tuomiconst char *ssl_iostream_get_compression(struct ssl_iostream *ssl_io);
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainenconst char *ssl_iostream_get_server_name(struct ssl_iostream *ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenconst char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io);
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi/* Returns SSL context's current used cipher algorithm. Returns NULL
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi if SSL handshake has not been performed.
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi This returns values like 'AESGCM'
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi*/
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomiconst char *ssl_iostream_get_cipher(struct ssl_iostream *ssl_io,
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi unsigned int *bits_r);
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi/* Returns currently used forward secrecy algorithm, if available.
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi Returns NULL if handshake not done yet, empty string if missing.
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi This returns values like 'DH', 'ECDH' etc..
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi*/
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomiconst char *ssl_iostream_get_pfs(struct ssl_iostream *ssl_io);
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi/* Returns currently used SSL protocol name. Returns NULL if handshake
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi has not yet been made.
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi This returns values like SSLv3, TLSv1, TLSv1.1, TLSv1.2
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi*/
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomiconst char *ssl_iostream_get_protocol_name(struct ssl_iostream *ssl_io);
33631b9b711b95ee47bd4ddbdb419f46a12cebe4Aki Tuomi
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenconst char *ssl_iostream_get_last_error(struct ssl_iostream *ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainenint ssl_iostream_context_init_client(const struct ssl_iostream_settings *set,
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen struct ssl_iostream_context **ctx_r,
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen const char **error_r);
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainenint ssl_iostream_context_init_server(const struct ssl_iostream_settings *set,
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen struct ssl_iostream_context **ctx_r,
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen const char **error_r);
96359599bbd4a2d704c3f343ff4c2fcd03f0dd02Timo Sirainenvoid ssl_iostream_context_ref(struct ssl_iostream_context *ctx);
15d19d6e4daf460d8d2c82b981e23996dbdf7ba5Timo Sirainenvoid ssl_iostream_context_unref(struct ssl_iostream_context **ctx);
cfa1edd025234945720dfd2834710a8bbb24d906Timo Sirainen
173d1d74736ec822158165bef66d312bb62f2152Martti Rannanjärvistruct ssl_iostream_settings *ssl_iostream_settings_dup(pool_t pool,
173d1d74736ec822158165bef66d312bb62f2152Martti Rannanjärvi const struct ssl_iostream_settings *old_set);
cfa1edd025234945720dfd2834710a8bbb24d906Timo Sirainenvoid ssl_iostream_settings_init_from(pool_t pool,
25aa88dd96482cb1a135d3e962b7936500dcaab5Timo Sirainen struct ssl_iostream_settings *dest,
25aa88dd96482cb1a135d3e962b7936500dcaab5Timo Sirainen const struct ssl_iostream_settings *src);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen/* Persistent cache of ssl_iostream_contexts. The context is permanently stored
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen until ssl_iostream_context_cache_free() is called. The returned context
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen must be unreferenced by the caller. */
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainenint ssl_iostream_client_context_cache_get(const struct ssl_iostream_settings *set,
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen struct ssl_iostream_context **ctx_r,
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen const char **error_r);
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainenint ssl_iostream_server_context_cache_get(const struct ssl_iostream_settings *set,
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen struct ssl_iostream_context **ctx_r,
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen const char **error_r);
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainenvoid ssl_iostream_context_cache_free(void);
86cc86047bee861a6f7fc3a9cfdb8600b984732eTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#endif