e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#ifndef IOSTREAM_OPENSSL_H
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#define IOSTREAM_OPENSSL_H
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen#include "iostream-ssl-private.h"
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#include <openssl/ssl.h>
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
13479101da29577f7789d6f61faa1da3e2f7434aTimo Sirainen#ifndef HAVE_ASN1_STRING_GET0_DATA
13479101da29577f7789d6f61faa1da3e2f7434aTimo Sirainen# define ASN1_STRING_get0_data(str) ASN1_STRING_data(str)
13479101da29577f7789d6f61faa1da3e2f7434aTimo Sirainen#endif
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomienum openssl_iostream_sync_type {
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi OPENSSL_IOSTREAM_SYNC_TYPE_FIRST_READ,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi OPENSSL_IOSTREAM_SYNC_TYPE_CONTINUE_READ,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi OPENSSL_IOSTREAM_SYNC_TYPE_WRITE,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi};
13479101da29577f7789d6f61faa1da3e2f7434aTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstruct ssl_iostream_context {
96359599bbd4a2d704c3f343ff4c2fcd03f0dd02Timo Sirainen int refcount;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen SSL_CTX *ssl_ctx;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen pool_t pool;
319bc5ff46e9c941efb573b1e00f85fdeb08942dTimo Sirainen struct ssl_iostream_settings set;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
c5b7a9068c637195bae4751f965fc33c203a72d6Timo Sirainen DH *dh_512, *dh_default;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen int username_nid;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool client_ctx:1;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen};
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstruct ssl_iostream {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen int refcount;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_iostream_context *ctx;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen SSL *ssl;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen BIO *bio_ext;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct istream *plain_input;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ostream *plain_output;
87da941c0b0a0671997f592a52ee2c0b35d0e41eTimo Sirainen struct istream *ssl_input;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ostream *ssl_output;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
d185226aa3dc88a9ee9f16b4c8b2e38000ac8b96Timo Sirainen /* SSL clients: host where we connected to */
d185226aa3dc88a9ee9f16b4c8b2e38000ac8b96Timo Sirainen char *connected_host;
d185226aa3dc88a9ee9f16b4c8b2e38000ac8b96Timo Sirainen /* SSL servers: host requested by the client via SNI */
d185226aa3dc88a9ee9f16b4c8b2e38000ac8b96Timo Sirainen char *sni_host;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen char *last_error;
3b4bd183cc469f70eb91d82a7f01f60ffc24ca5bTimo Sirainen char *log_prefix;
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen char *plain_stream_errstr;
c2c0c1e5d2e97ae114ad83d8cb486b0aab23ac38Timo Sirainen int plain_stream_errno;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen /* copied settings */
095481fee84040436ce2dccca472c9bb1df4d5bbTimo Sirainen bool verbose, verbose_invalid_cert, allow_invalid_cert;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen int username_nid;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
ac645fe16c0619771c0a961db91df16485513c52Timo Sirainen ssl_iostream_handshake_callback_t *handshake_callback;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen void *handshake_context;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen ssl_iostream_sni_callback_t *sni_callback;
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen void *sni_context;
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool handshaked:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool handshake_failed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool cert_received:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool cert_broken:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool want_read:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool ostream_flush_waiting_input:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool closed:1;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen};
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenextern int dovecot_ssl_extdata_index;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenstruct istream *openssl_i_stream_create_ssl(struct ssl_iostream *ssl_io);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenstruct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainenint openssl_iostream_global_init(const struct ssl_iostream_settings *set,
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen const char **error_r);
15aa67e8a9dd7fc631d58ce13c54fe004bb4d0c1Timo Sirainen
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainenint openssl_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 openssl_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 openssl_iostream_context_ref(struct ssl_iostream_context *ctx);
96359599bbd4a2d704c3f343ff4c2fcd03f0dd02Timo Sirainenvoid openssl_iostream_context_unref(struct ssl_iostream_context *ctx);
b4f4552697bdc8e467955e262ae446dbe2914c14Timo Sirainenvoid openssl_iostream_global_deinit(void);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen
9f7ba3807f77209a65e0faa56cac8545b06cd116Aki Tuomiint openssl_iostream_load_key(const struct ssl_iostream_cert *set,
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen EVP_PKEY **pkey_r, const char **error_r);
bbafd34da224c399700956db6819643e1d3b3ce7Timo Sirainenbool openssl_cert_match_name(SSL *ssl, const char *verify_name,
bbafd34da224c399700956db6819643e1d3b3ce7Timo Sirainen const char **reason_r);
6a4212e6d7c41de83bcac63edec3118e6a7a0f68Timo Sirainen#define OPENSSL_ALL_PROTOCOL_OPTIONS \
6a4212e6d7c41de83bcac63edec3118e6a7a0f68Timo Sirainen (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1)
976dee5384c4827dc648c9bc53825390521c388eMartti Rannanjärvi/* opt_r is used with SSL_set_options() and version_r is used with
976dee5384c4827dc648c9bc53825390521c388eMartti Rannanjärvi SSL_set_min_proto_version(). Using either method should enable the same SSL
976dee5384c4827dc648c9bc53825390521c388eMartti Rannanjärvi protocol versions. */
976dee5384c4827dc648c9bc53825390521c388eMartti Rannanjärviint openssl_min_protocol_to_options(const char *min_protocol, long *opt_r,
976dee5384c4827dc648c9bc53825390521c388eMartti Rannanjärvi int *version_r) ATTR_NULL(2,3);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen/* Sync plain_input/plain_output streams with BIOs. Returns TRUE if at least
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen one byte was read/written. */
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomibool openssl_iostream_bio_sync(struct ssl_iostream *ssl_io,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi enum openssl_iostream_sync_type type);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen/* Call when there's more data available in plain_input/plain_output.
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen Returns 1 if it's ok to continue with SSL_read/SSL_write, 0 if not
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen (still handshaking), -1 if error occurred. */
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomiint openssl_iostream_more(struct ssl_iostream *ssl_io,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi enum openssl_iostream_sync_type type);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen/* Returns 1 if the operation should be retried (we read/wrote more data),
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen 0 if the operation should retried later once more data has been
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen read/written, -1 if a fatal error occurred (errno is set). */
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenint openssl_iostream_handle_error(struct ssl_iostream *ssl_io, int ret,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi enum openssl_iostream_sync_type type,
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen const char *func_name);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen
14a07d2bb34f1d52fce3e3218799f271f118d501Timo Sirainenvoid openssl_iostream_set_error(struct ssl_iostream *ssl_io, const char *str);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenconst char *openssl_iostream_error(void);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenconst char *openssl_iostream_key_load_error(void);
8b5d186ec2f8b56ded72a7f45a70b7542caad9d0Timo Sirainenconst char *
8b5d186ec2f8b56ded72a7f45a70b7542caad9d0Timo Sirainenopenssl_iostream_use_certificate_error(const char *cert, const char *set_name);
78c27af9d04b830afe3df6495d7a1efee556ecb8Timo Sirainenvoid openssl_iostream_clear_errors(void);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen
ecc2fb34641f1bd39e10c774192ca18527ecb953Timo Sirainenvoid ssl_iostream_openssl_init(void);
ecc2fb34641f1bd39e10c774192ca18527ecb953Timo Sirainenvoid ssl_iostream_openssl_deinit(void);
fe4058e6f01bf0e104c44815b6df7cfefb80634cTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#endif