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]);
405 while(!SSL_is_init_finished(sc->ssl)) {
406 _sx_debug(
ZONE,
"secure channel not established, handshake in progress");
409 if(sc->last_state == SX_SSL_STATE_WANT_READ && BIO_pending(sc->rbio) == 0)
414 ret = SSL_connect(sc->ssl);
416 ret = SSL_accept(sc->ssl);
421 sc->last_state = SX_SSL_STATE_NONE;
423 s->
ssf = SSL_get_cipher_bits(sc->ssl, NULL);
425 _sx_debug(
ZONE,
"using cipher %s (%d bits)", SSL_get_cipher_name(sc->ssl), s->
ssf);
433 err = SSL_get_error(sc->ssl, ret);
435 if(err == SSL_ERROR_WANT_READ)
436 sc->last_state = SX_SSL_STATE_WANT_READ;
437 else if(err == SSL_ERROR_WANT_WRITE)
438 sc->last_state = SX_SSL_STATE_WANT_WRITE;
442 sc->last_state = SX_SSL_STATE_ERROR;
444 errstring = ERR_error_string(ERR_get_error(), NULL);
474 if(sc->last_state == SX_SSL_STATE_ERROR)
501 ret = SSL_write(sc->ssl, wbuf->data, wbuf->len);
507 jqueue_push(sc->wq, wbuf, (sc->wq->front != NULL) ? sc->wq->front->priority + 1 : 0);
510 err = SSL_get_error(sc->ssl, ret);
512 if(err == SSL_ERROR_ZERO_RETURN) {
517 if(err == SSL_ERROR_WANT_READ) {
520 sc->last_state = SX_SSL_STATE_WANT_READ;
524 sc->last_state = SX_SSL_STATE_ERROR;
527 errstring = ERR_error_string(ERR_get_error(), NULL);
547 if(BIO_pending(sc->wbio) > 0) {
548 int bytes_pending = BIO_pending(sc->wbio);
549 assert(buf->
len == 0);
551 BIO_read(sc->wbio, buf->
data, bytes_pending);
552 buf->
len += bytes_pending;
556 buf->
notify = wbuf->notify;
565 if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
573 int est, ret, err, pending;
578 if(sc->last_state == SX_SSL_STATE_ERROR)
587 BIO_write(sc->rbio, buf->
data, buf->
len);
600 pending = SSL_pending(sc->ssl);
602 pending = BIO_pending(sc->rbio);
605 while((pending = SSL_pending(sc->ssl)) > 0 || (pending = BIO_pending(sc->rbio)) > 0) {
608 ret = SSL_read(sc->ssl, &(buf->
data[buf->
len]), pending);
618 if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)
629 err = SSL_get_error(sc->ssl, ret);
634 if(err == SSL_ERROR_ZERO_RETURN) {
645 err = SSL_get_error(sc->ssl, ret);
648 if(err == SSL_ERROR_WANT_READ) {
649 sc->last_state = SX_SSL_STATE_WANT_READ;
660 sc->last_state = SX_SSL_STATE_ERROR;
662 errstring = ERR_error_string(ERR_get_error(), NULL);
684 if(BIO_pending(sc->wbio) > 0 || (est > 0 &&
jqueue_size(sc->wq) > 0))
688 if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
700 char *pemfile = NULL;
702 char *pemfile_password = NULL;
718 assert((
int) (ctx != NULL));
720 sc = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
723 sc->rbio = BIO_new(BIO_s_mem());
724 sc->wbio = BIO_new(BIO_s_mem());
727 sc->ssl = SSL_new(ctx);
728 SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
729 SSL_set_connect_state(sc->ssl);
731 #ifdef ENABLE_EXPERIMENTAL 732 SSL_set_ssl_method(sc->ssl, TLSv1_2_client_method());
734 SSL_set_ssl_method(sc->ssl, TLSv1_client_method());
739 sc->external_id[i] = NULL;
748 pemfile_password = ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password;
752 if(pemfile != NULL) {
754 ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
756 _sx_debug(
ZONE,
"couldn't load alternate certificate from %s", pemfile);
764 SSL_CTX_set_default_passwd_cb_userdata(sc->ssl->ctx, (
void *)pemfile_password);
768 ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
770 _sx_debug(
ZONE,
"couldn't load alternate private key from %s", pemfile);
778 ret = SSL_check_private_key(sc->ssl);
780 _sx_debug(
ZONE,
"private key does not match certificate public key");
820 assert((
int) (ctx != NULL));
822 sc = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
825 sc->rbio = BIO_new(BIO_s_mem());
826 sc->wbio = BIO_new(BIO_s_mem());
829 sc->ssl = SSL_new(ctx);
830 SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
831 SSL_set_accept_state(sc->ssl);
832 SSL_set_options(sc->ssl, SSL_OP_NO_SSLv3);
836 sc->external_id[i] = NULL;
864 if(sc->external_id[i] != NULL)
865 free(sc->external_id[i]);
869 if(sc->pemfile != NULL) free(sc->pemfile);
871 if(sc->private_key_password != NULL) free(sc->private_key_password);
873 if(sc->ssl != NULL) SSL_free(sc->ssl);
894 SSL_CTX_free((SSL_CTX *) ctx);
906 const char *name, *pemfile, *cachain, *password, *ciphers;
912 name = va_arg(args,
const char *);
913 pemfile = va_arg(args,
const char *);
920 cachain = va_arg(args,
const char *);
921 mode = va_arg(args,
int);
922 password = va_arg(args,
char *);
923 ciphers = va_arg(args,
char *);
928 if(!sx_openssl_initialized) {
930 SSL_load_error_strings();
932 sx_openssl_initialized = 1;
958 STACK_OF(X509_NAME) *cert_names;
962 EC_KEY *eckey = NULL;
965 if(!sx_openssl_initialized) {
980 #ifdef ENABLE_EXPERIMENTAL 981 ctx = SSL_CTX_new(TLSv1_2_method());
983 ctx = SSL_CTX_new(SSLv23_method());
986 _sx_debug(
ZONE,
"ssl context creation failed; %s", ERR_error_string(ERR_get_error(), NULL));
992 ciphers =
"!aNULL:!eNULL:!EXP:" SSL_DEFAULT_CIPHER_LIST;
994 if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
995 _sx_debug(
ZONE,
"Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
1001 if (cachain != NULL) {
1002 ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
1004 _sx_debug(
ZONE,
"WARNING: couldn't load CA chain: %s; %s", cachain, ERR_error_string(ERR_get_error(), NULL));
1006 _sx_debug(
ZONE,
"Loaded CA verify location chain: %s", cachain);
1008 cert_names = SSL_load_client_CA_file(cachain);
1009 if (cert_names != NULL) {
1010 SSL_CTX_set_client_CA_list(ctx, cert_names);
1013 _sx_debug(
ZONE,
"WARNING: couldn't load client CA chain: %s", cachain);
1021 SSL_CTX_set_default_verify_paths(ctx);
1022 _sx_debug(
ZONE,
"No CA chain specified. Loading SSL default CA certs: /etc/ssl/certs");
1025 store = SSL_CTX_get_cert_store(ctx);
1028 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
1031 ret = SSL_CTX_use_certificate_chain_file(ctx, pemfile);
1033 _sx_debug(
ZONE,
"couldn't load certificate from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1039 SSL_CTX_set_default_passwd_cb_userdata(ctx, (
void *)password);
1043 ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
1045 _sx_debug(
ZONE,
"couldn't load private key from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1051 ret = SSL_CTX_check_private_key(ctx);
1053 _sx_debug(
ZONE,
"private key does not match certificate public key; %s", ERR_error_string(ERR_get_error(), NULL));
1058 _sx_debug(
ZONE,
"setting ssl context '%s' verify mode to %02x", name, mode);
1064 if((dhparams = sx_ssl_get_DHparams(pemfile))) {
1065 SSL_CTX_set_tmp_dh(ctx, dhparams);
1066 _sx_debug(
ZONE,
"custom DH parameters loaded from certificate", BN_num_bits(dhparams->p));
1070 if((ecparams = sx_ssl_get_ECPKParameters(pemfile)) && (nid = EC_GROUP_get_curve_name(ecparams)) && (eckey = EC_KEY_new_by_curve_name(nid))) {
1071 SSL_CTX_set_tmp_ecdh(ctx, eckey);
1072 _sx_debug(
ZONE,
"custom ECDH curve %s loaded from certificate", OBJ_nid2sn(nid));
1075 #if defined(SSL_set_ecdh_auto) 1077 SSL_CTX_set_ecdh_auto(ctx, 1);
1081 eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1082 SSL_CTX_set_tmp_ecdh(ctx, eckey);
1088 if(contexts == NULL) {
1090 p->
private = (
void *) contexts;
1093 if(!(name[0] ==
'*' && name[1] == 0)) {
1105 _sx_debug(
ZONE,
"ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile);
1110 SSL_CTX_free((SSL_CTX *) tmp);
1118 assert((
int) (p != NULL));
1119 assert((
int) (s != NULL));
1123 _sx_debug(
ZONE,
"wrong conn type or state for client starttls");
1136 if(pemfile != NULL) {
1137 s->
plugin_data[p->
index] = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
1141 if(private_key_password != NULL)
1142 ((_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
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
#define DECLARE_sx_ssl_getparams(name, type)
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