27 #include <openssl/x509_vfy.h>
28 #include <openssl/dh.h>
29 #include <openssl/bn.h>
39 err_cert = X509_STORE_CTX_get_current_cert(ctx);
40 err = X509_STORE_CTX_get_error(ctx);
41 depth = X509_STORE_CTX_get_error_depth(ctx);
46 if (!preverify_ok && err == X509_V_ERR_UNABLE_TO_GET_CRL) {
47 _sx_debug(
ZONE,
"ignoring verify error:num=%d:%s:depth=%d:%s\n", err,
48 X509_verify_cert_error_string(err), depth, buf);
56 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
60 X509_verify_cert_error_string(err), depth, buf);
71 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
73 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
82 strncpy(buf, (
char *)(password), size);
87 #define DECLARE_sx_ssl_getparams(name, type) \
88 static type *sx_ssl_get_##name(const char *file) { \
91 if ((bio = BIO_new_file(file, "r")) == NULL) \
93 ret = PEM_read_bio_##name(bio, NULL, NULL, NULL); \
101 BIGNUM *(*
const get_prime)(BIGNUM *);
103 const unsigned minlen;
105 { get_rfc3526_prime_8192, NULL, 6145 },
106 { get_rfc3526_prime_6144, NULL, 4097 },
107 { get_rfc3526_prime_4096, NULL, 3073 },
108 { get_rfc3526_prime_3072, NULL, 2049 },
109 { get_rfc3526_prime_2048, NULL, 1025 },
110 { get_rfc2409_prime_1024, NULL, 0 }
118 dh->p = get_prime(NULL);
119 BN_dec2bn(&dh->g, gen);
120 if (!dh->p || !dh->g) {
136 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
137 int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
140 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA)
141 keylen = EVP_PKEY_bits(pkey);
175 char *ns = NULL, *to = NULL, *from = NULL, *version = NULL;
193 _sx_debug(
ZONE,
"starttls requested on already encrypted channel, dropping packet");
199 _sx_debug(
ZONE,
"starttls requested on already compressed channel, dropping packet");
222 if(s->
ns != NULL) ns = strdup(s->
ns);
237 if(ns != NULL) free(ns);
238 if(to != NULL) free(to);
239 if(from != NULL) free(from);
240 if(version != NULL) free(version);
253 if( ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password != NULL )
259 _sx_debug(
ZONE,
"server can't handle ssl, business as usual");
294 X509_NAME_ENTRY *entry;
296 X509_EXTENSION *extension;
297 STACK_OF(GENERAL_NAME) *altnames;
298 GENERAL_NAME *altname;
299 OTHERNAME *othername;
302 int id_on_xmppAddr_nid;
303 ASN1_OBJECT *id_on_xmppAddr_obj;
305 int i, j, count,
id = 0, len;
308 if ((cert = SSL_get_peer_certificate(sc->ssl) ) == NULL)
313 id_on_xmppAddr_nid = OBJ_create(
"1.3.6.1.5.5.7.8.5",
"id-on-xmppAddr",
"XMPP Address Identity");
314 id_on_xmppAddr_obj = OBJ_nid2obj(id_on_xmppAddr_nid);
315 _sx_debug(
ZONE,
"external_id: Created id-on-xmppAddr SSL object");
318 for (i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
320 i = X509_get_ext_by_NID(cert, NID_subject_alt_name, i)) {
322 if ((extension = X509_get_ext(cert, i)) == NULL) {
323 _sx_debug(
ZONE,
"external_id: Can't get subjectAltName. Possibly malformed cert.");
327 if ((altnames = X509V3_EXT_d2i(extension)) == NULL) {
328 _sx_debug(
ZONE,
"external_id: Can't get all AltNames. Possibly malformed cert.");
332 count = sk_GENERAL_NAME_num(altnames);
333 for (j = 0; j < count; j++) {
334 if ((altname = sk_GENERAL_NAME_value(altnames, j)) == NULL) {
335 _sx_debug(
ZONE,
"external_id: Can't get AltName. Possibly malformed cert.");
339 if (altname->type == GEN_OTHERNAME &&
340 OBJ_cmp(altname->d.otherName->type_id, id_on_xmppAddr_obj) == 0) {
341 othername = altname->d.otherName;
342 len = ASN1_STRING_to_UTF8((
unsigned char **) &buff, othername->value->value.utf8string);
345 sc->external_id[id] = (
char *) malloc(
sizeof(
char) * (len + 1));
346 memcpy(sc->external_id[
id], buff, len);
347 sc->external_id[id][len] =
'\0';
348 _sx_debug(
ZONE,
"external_id: Found(%d) subjectAltName/id-on-xmppAddr: '%s'",
id, sc->external_id[
id]);
351 }
else if (altname->type == GEN_DNS) {
352 len = ASN1_STRING_length(altname->d.dNSName);
353 sc->external_id[id] = (
char *) malloc(
sizeof(
char) * (len + 1));
354 memcpy(sc->external_id[
id], ASN1_STRING_data(altname->d.dNSName), len);
355 sc->external_id[id][len] =
'\0';
356 _sx_debug(
ZONE,
"external_id: Found(%d) subjectAltName/dNSName: '%s'",
id, sc->external_id[
id]);
361 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
366 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
369 name = X509_get_subject_name(cert);
370 for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
372 i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
374 if ((entry = X509_NAME_get_entry(name, i)) == NULL) {
375 _sx_debug(
ZONE,
"external_id: Can't get commonName(%d). Possibly malformed cert. Continuing.", i);
379 len = ASN1_STRING_to_UTF8((
unsigned char **) &buff, X509_NAME_ENTRY_get_data(entry));
383 sc->external_id[id] = (
char *) malloc(
sizeof(
char) * (len + 1));
384 memcpy(sc->external_id[
id], buff, len);
385 sc->external_id[id][len] =
'\0';
386 _sx_debug(
ZONE,
"external_id: Found(%d) commonName: '%s'",
id, sc->external_id[
id]);
404 while(!SSL_is_init_finished(sc->ssl)) {
405 _sx_debug(
ZONE,
"secure channel not established, handshake in progress");
408 if(sc->last_state == SX_SSL_STATE_WANT_READ && BIO_pending(sc->rbio) == 0)
413 ret = SSL_connect(sc->ssl);
415 ret = SSL_accept(sc->ssl);
420 sc->last_state = SX_SSL_STATE_NONE;
422 s->
ssf = SSL_get_cipher_bits(sc->ssl, NULL);
424 _sx_debug(
ZONE,
"using cipher %s (%d bits)", SSL_get_cipher_name(sc->ssl), s->
ssf);
432 err = SSL_get_error(sc->ssl, ret);
434 if(err == SSL_ERROR_WANT_READ)
435 sc->last_state = SX_SSL_STATE_WANT_READ;
436 else if(err == SSL_ERROR_WANT_WRITE)
437 sc->last_state = SX_SSL_STATE_WANT_WRITE;
441 sc->last_state = SX_SSL_STATE_ERROR;
443 errstring = ERR_error_string(ERR_get_error(), NULL);
473 if(sc->last_state == SX_SSL_STATE_ERROR)
500 ret = SSL_write(sc->ssl, wbuf->data, wbuf->len);
506 jqueue_push(sc->wq, wbuf, (sc->wq->front != NULL) ? sc->wq->front->priority + 1 : 0);
509 err = SSL_get_error(sc->ssl, ret);
511 if(err == SSL_ERROR_ZERO_RETURN) {
516 if(err == SSL_ERROR_WANT_READ) {
519 sc->last_state = SX_SSL_STATE_WANT_READ;
523 sc->last_state = SX_SSL_STATE_ERROR;
526 errstring = ERR_error_string(ERR_get_error(), NULL);
546 if(BIO_pending(sc->wbio) > 0) {
547 int bytes_pending = BIO_pending(sc->wbio);
548 assert(buf->
len == 0);
550 BIO_read(sc->wbio, buf->
data, bytes_pending);
551 buf->
len += bytes_pending;
555 buf->
notify = wbuf->notify;
564 if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
572 int est, ret, err, pending;
577 if(sc->last_state == SX_SSL_STATE_ERROR)
586 BIO_write(sc->rbio, buf->
data, buf->
len);
599 pending = SSL_pending(sc->ssl);
601 pending = BIO_pending(sc->rbio);
604 while((pending = SSL_pending(sc->ssl)) > 0 || (pending = BIO_pending(sc->rbio)) > 0) {
607 ret = SSL_read(sc->ssl, &(buf->
data[buf->
len]), pending);
617 if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)
628 err = SSL_get_error(sc->ssl, ret);
633 if(err == SSL_ERROR_ZERO_RETURN) {
644 err = SSL_get_error(sc->ssl, ret);
647 if(err == SSL_ERROR_WANT_READ) {
648 sc->last_state = SX_SSL_STATE_WANT_READ;
659 sc->last_state = SX_SSL_STATE_ERROR;
661 errstring = ERR_error_string(ERR_get_error(), NULL);
683 if(BIO_pending(sc->wbio) > 0 || (est > 0 &&
jqueue_size(sc->wq) > 0))
687 if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
699 char *pemfile = NULL;
701 char *pemfile_password = NULL;
717 assert((
int) (ctx != NULL));
719 sc = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
722 sc->rbio = BIO_new(BIO_s_mem());
723 sc->wbio = BIO_new(BIO_s_mem());
726 sc->ssl = SSL_new(ctx);
727 SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
728 SSL_set_connect_state(sc->ssl);
730 #ifdef ENABLE_EXPERIMENTAL
731 SSL_set_ssl_method(sc->ssl, TLSv1_2_client_method());
733 SSL_set_ssl_method(sc->ssl, TLSv1_client_method());
738 sc->external_id[i] = NULL;
747 pemfile_password = ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password;
751 if(pemfile != NULL) {
753 ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
755 _sx_debug(
ZONE,
"couldn't load alternate certificate from %s", pemfile);
763 SSL_CTX_set_default_passwd_cb_userdata(sc->ssl->ctx, (
void *)pemfile_password);
767 ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
769 _sx_debug(
ZONE,
"couldn't load alternate private key from %s", pemfile);
777 ret = SSL_check_private_key(sc->ssl);
779 _sx_debug(
ZONE,
"private key does not match certificate public key");
819 assert((
int) (ctx != NULL));
821 sc = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
824 sc->rbio = BIO_new(BIO_s_mem());
825 sc->wbio = BIO_new(BIO_s_mem());
828 sc->ssl = SSL_new(ctx);
829 SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
830 SSL_set_accept_state(sc->ssl);
831 SSL_set_options(sc->ssl, SSL_OP_NO_SSLv3);
835 sc->external_id[i] = NULL;
863 if(sc->external_id[i] != NULL)
864 free(sc->external_id[i]);
868 if(sc->pemfile != NULL) free(sc->pemfile);
870 if(sc->private_key_password != NULL) free(sc->private_key_password);
872 if(sc->ssl != NULL) SSL_free(sc->ssl);
893 SSL_CTX_free((SSL_CTX *) ctx);
905 const char *name, *pemfile, *cachain, *password, *ciphers;
911 name = va_arg(args,
const char *);
912 pemfile = va_arg(args,
const char *);
919 cachain = va_arg(args,
const char *);
920 mode = va_arg(args,
int);
921 password = va_arg(args,
char *);
922 ciphers = va_arg(args,
char *);
927 if(!sx_openssl_initialized) {
929 SSL_load_error_strings();
931 sx_openssl_initialized = 1;
957 STACK_OF(X509_NAME) *cert_names;
961 EC_KEY *eckey = NULL;
964 if(!sx_openssl_initialized) {
979 #ifdef ENABLE_EXPERIMENTAL
980 ctx = SSL_CTX_new(TLSv1_2_method());
982 ctx = SSL_CTX_new(SSLv23_method());
985 _sx_debug(
ZONE,
"ssl context creation failed; %s", ERR_error_string(ERR_get_error(), NULL));
991 ciphers =
"!aNULL:!eNULL:!EXP:" SSL_DEFAULT_CIPHER_LIST;
993 if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
994 _sx_debug(
ZONE,
"Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
1000 if (cachain != NULL) {
1001 ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
1003 _sx_debug(
ZONE,
"WARNING: couldn't load CA chain: %s; %s", cachain, ERR_error_string(ERR_get_error(), NULL));
1005 _sx_debug(
ZONE,
"Loaded CA verify location chain: %s", cachain);
1007 cert_names = SSL_load_client_CA_file(cachain);
1008 if (cert_names != NULL) {
1009 SSL_CTX_set_client_CA_list(ctx, cert_names);
1012 _sx_debug(
ZONE,
"WARNING: couldn't load client CA chain: %s", cachain);
1020 SSL_CTX_set_default_verify_paths(ctx);
1021 _sx_debug(
ZONE,
"No CA chain specified. Loading SSL default CA certs: /etc/ssl/certs");
1024 store = SSL_CTX_get_cert_store(ctx);
1027 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
1030 ret = SSL_CTX_use_certificate_chain_file(ctx, pemfile);
1032 _sx_debug(
ZONE,
"couldn't load certificate from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1038 SSL_CTX_set_default_passwd_cb_userdata(ctx, (
void *)password);
1042 ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
1044 _sx_debug(
ZONE,
"couldn't load private key from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1050 ret = SSL_CTX_check_private_key(ctx);
1052 _sx_debug(
ZONE,
"private key does not match certificate public key; %s", ERR_error_string(ERR_get_error(), NULL));
1057 _sx_debug(
ZONE,
"setting ssl context '%s' verify mode to %02x", name, mode);
1063 if((dhparams = sx_ssl_get_DHparams(pemfile))) {
1064 SSL_CTX_set_tmp_dh(ctx, dhparams);
1065 _sx_debug(
ZONE,
"custom DH parameters loaded from certificate", BN_num_bits(dhparams->p));
1069 if((ecparams = sx_ssl_get_ECPKParameters(pemfile)) && (nid = EC_GROUP_get_curve_name(ecparams)) && (eckey = EC_KEY_new_by_curve_name(nid))) {
1070 SSL_CTX_set_tmp_ecdh(ctx, eckey);
1071 _sx_debug(
ZONE,
"custom ECDH curve %s loaded from certificate", OBJ_nid2sn(nid));
1074 #if defined(SSL_set_ecdh_auto)
1076 SSL_CTX_set_ecdh_auto(ctx, 1);
1080 eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1081 SSL_CTX_set_tmp_ecdh(ctx, eckey);
1087 if(contexts == NULL) {
1089 p->
private = (
void *) contexts;
1092 if(!(name[0] ==
'*' && name[1] == 0)) {
1104 _sx_debug(
ZONE,
"ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile);
1109 SSL_CTX_free((SSL_CTX *) tmp);
1117 assert((
int) (p != NULL));
1118 assert((
int) (s != NULL));
1122 _sx_debug(
ZONE,
"wrong conn type or state for client starttls");
1135 if(pemfile != NULL) {
1136 s->
plugin_data[p->
index] = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
1140 if(private_key_password != NULL)
1141 ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password = strdup(private_key_password);
#define stream_err_UNDEFINED_CONDITION
void(* free)(sx_t s, sx_plugin_t p)
#define _sx_event(s, e, data)
void(* server)(sx_t s, sx_plugin_t p)
static DH * _sx_ssl_tmp_dh_callback(SSL *ssl, int export, int keylen)
static int _sx_pem_passwd_callback(char *buf, int size, int rwflag, void *password)
void(* unload)(sx_plugin_t p)
int jqueue_size(jqueue_t q)
void(* features)(sx_t s, sx_plugin_t p, nad_t nad)
error info for event_ERROR
int sx_ssl_server_addcert(sx_plugin_t p, const char *name, const char *pemfile, const char *cachain, int mode, const char *password, const char *ciphers)
args: name, pemfile, cachain, mode
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
void sx_server_init(sx_t s, unsigned int flags)
static int _sx_ssl_process(sx_t s, sx_plugin_t p, nad_t nad)
void _sx_chain_io_plugin(sx_t s, sx_plugin_t p)
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
void nad_free(nad_t nad)
free that nad
int xhash_iter_next(xht h)
static void _sx_ssl_starttls_notify_proceed(sx_t s, void *arg)
#define SX_ERR_SSL
error codes
static void _sx_ssl_features(sx_t s, sx_plugin_t p, nad_t nad)
void jqueue_free(jqueue_t q)
void _sx_buffer_alloc_margin(sx_buf_t buf, int before, int after)
utility: ensure a certain amount of allocated space adjacent to buf->data
static DH * sx_ssl_make_dh_params(BIGNUM *(*const get_prime)(BIGNUM *), const char *gen)
holds the state for a single stream
#define SX_SSL_MAGIC
magic numbers, so plugins can find each other
void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version)
#define NAD_ENAME_L(N, E)
void jqueue_push(jqueue_t q, void *data, int priority)
#define NAD_NURI_L(N, NS)
static int _sx_ssl_wio(sx_t s, sx_plugin_t p, sx_buf_t buf)
void xhash_put(xht h, const char *key, void *val)
static void _sx_ssl_server(sx_t s, sx_plugin_t p)
#define SX_SSL_STARTTLS_OFFER
void _sx_buffer_free(sx_buf_t buf)
utility: kill a buffer
sx_buf_t _sx_buffer_new(const char *data, int len, _sx_notify_t notify, void *notify_arg)
utility: make a new buffer if len>0 but data is NULL, the buffer will contain that many bytes of garb...
static void sx_ssl_free_dh_params(void)
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
static void _sx_ssl_unload(sx_plugin_t p)
#define SX_ERR_STARTTLS_FAILURE
static int _sx_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
this plugin implements the traditional SSL "wrappermode" streams and STARTTLS extension documented in...
static void _sx_ssl_client(sx_t s, sx_plugin_t p)
#define SX_SSL_STARTTLS_REQUIRE
static void _sx_ssl_get_external_id(sx_t s, _sx_ssl_conn_t sc)
void sx_error(sx_t s, int err, const char *text)
void _sx_reset(sx_t s)
utility; reset stream state
int sx_openssl_initialized
void _sx_close(sx_t s)
close a stream
void * jqueue_pull(jqueue_t q)
int xhash_iter_first(xht h)
iteration
jqueue_t jqueue_new(void)
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
#define DECLARE_sx_ssl_getparams(name, type)
int(* wio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
void _sx_buffer_clear(sx_buf_t buf)
utility: clear out a buffer, but don't deallocate it
void * xhash_get(xht h, const char *key)
#define SX_SSL_WRAPPER
sx stream flags
#define _sx_gen_error(e, c, g, s)
helper macro to populate this struct
int(* process)(sx_t s, sx_plugin_t p, nad_t nad)
int(* rio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
static int _sx_ssl_handshake(sx_t s, _sx_ssl_conn_t sc)
#define SX_CONN_EXTERNAL_ID_MAX_COUNT
int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password)
void(* client)(sx_t s, sx_plugin_t p)
static void _sx_ssl_free(sx_t s, sx_plugin_t p)
cleanup
static int _sx_ssl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf)
#define SX_COMPRESS_WRAPPER