return ssl_io->last_error;
}
+static const char *
+openssl_iostream_get_cipher(struct ssl_iostream *ssl_io, unsigned int *bits_r)
+{
+ if (!ssl_io->handshaked)
+ return NULL;
+
+ const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_io->ssl);
+ *bits_r = SSL_CIPHER_get_bits(cipher, NULL);
+ return SSL_CIPHER_get_name(cipher);
+}
+
+static const char *
+openssl_iostream_get_pfs(struct ssl_iostream *ssl_io)
+{
+ if (!ssl_io->handshaked)
+ return NULL;
+
+ const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_io->ssl);
+#if defined(HAVE_SSL_CIPHER_get_kx_nid)
+ int nid = SSL_CIPHER_get_kx_nid(cipher);
+ return OBJ_nid2sn(nid);
+#else
+ char buf[128];
+ const char *desc, *ptr;
+ if ((desc = SSL_CIPHER_description(cipher, buf, sizeof(buf)))==NULL ||
+ (ptr = strstr(desc, "Kx=")) == NULL)
+ return "";
+ return t_strcut(ptr+3, ' ');
+#endif
+}
+
+static const char *
+openssl_iostream_get_protocol_name(struct ssl_iostream *ssl_io)
+{
+ if (!ssl_io->handshaked)
+ return NULL;
+ return SSL_get_version(ssl_io->ssl);
+}
+
+
static const struct iostream_ssl_vfuncs ssl_vfuncs = {
.global_init = openssl_iostream_global_init,
.context_init_client = openssl_iostream_context_init_client,
.get_compression = openssl_iostream_get_compression,
.get_security_string = openssl_iostream_get_security_string,
.get_last_error = openssl_iostream_get_last_error,
+ .get_cipher = openssl_iostream_get_cipher,
+ .get_pfs = openssl_iostream_get_pfs,
+ .get_protocol_name = openssl_iostream_get_protocol_name,
};
void ssl_iostream_openssl_init(void)
const char *(*get_compression)(struct ssl_iostream *ssl_io);
const char *(*get_security_string)(struct ssl_iostream *ssl_io);
const char *(*get_last_error)(struct ssl_iostream *ssl_io);
+ const char *(*get_cipher)(struct ssl_iostream *ssl_io, unsigned int *bits_r);
+ const char *(*get_pfs)(struct ssl_iostream *ssl_io);
+ const char *(*get_protocol_name)(struct ssl_iostream *ssl_io);
};
void iostream_ssl_module_init(const struct iostream_ssl_vfuncs *vfuncs);
set->verbose_invalid_cert = FALSE;
set->allow_invalid_cert = FALSE;
}
+
+const char *ssl_iostream_get_cipher(struct ssl_iostream *ssl_io,
+ unsigned int *bits_r)
+{
+ return ssl_vfuncs->get_cipher(ssl_io, bits_r);
+}
+
+const char *ssl_iostream_get_pfs(struct ssl_iostream *ssl_io)
+{
+ return ssl_vfuncs->get_pfs(ssl_io);
+}
+
+const char *ssl_iostream_get_protocol_name(struct ssl_iostream *ssl_io)
+{
+ return ssl_vfuncs->get_protocol_name(ssl_io);
+}
const char *ssl_iostream_get_compression(struct ssl_iostream *ssl_io);
const char *ssl_iostream_get_server_name(struct ssl_iostream *ssl_io);
const char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io);
+/* Returns SSL context's current used cipher algorithm. Returns NULL
+ if SSL handshake has not been performed.
+
+ This returns values like 'AESGCM'
+*/
+const char *ssl_iostream_get_cipher(struct ssl_iostream *ssl_io,
+ unsigned int *bits_r);
+/* Returns currently used forward secrecy algorithm, if available.
+ Returns NULL if handshake not done yet, empty string if missing.
+
+ This returns values like 'DH', 'ECDH' etc..
+*/
+const char *ssl_iostream_get_pfs(struct ssl_iostream *ssl_io);
+/* Returns currently used SSL protocol name. Returns NULL if handshake
+ has not yet been made.
+
+ This returns values like SSLv3, TLSv1, TLSv1.1, TLSv1.2
+*/
+const char *ssl_iostream_get_protocol_name(struct ssl_iostream *ssl_io);
+
const char *ssl_iostream_get_last_error(struct ssl_iostream *ssl_io);
int ssl_iostream_context_init_client(const struct ssl_iostream_settings *set,