27 #include <openssl/x509_vfy.h>
37 err_cert = X509_STORE_CTX_get_current_cert(ctx);
38 err = X509_STORE_CTX_get_error(ctx);
39 depth = X509_STORE_CTX_get_error_depth(ctx);
44 if (!preverify_ok && err == X509_V_ERR_UNABLE_TO_GET_CRL) {
45 _sx_debug(
ZONE,
"ignoring verify error:num=%d:%s:depth=%d:%s\n", err,
46 X509_verify_cert_error_string(err), depth, buf);
54 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
58 X509_verify_cert_error_string(err), depth, buf);
69 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
71 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
80 strncpy(buf, (
char *)(password), size);
106 char *ns = NULL, *to = NULL, *from = NULL, *version = NULL;
124 _sx_debug(
ZONE,
"starttls requested on already encrypted channel, dropping packet");
130 _sx_debug(
ZONE,
"starttls requested on already compressed channel, dropping packet");
153 if(s->
ns != NULL) ns = strdup(s->
ns);
168 if(ns != NULL) free(ns);
169 if(to != NULL) free(to);
170 if(from != NULL) free(from);
171 if(version != NULL) free(version);
184 if( ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password != NULL )
190 _sx_debug(
ZONE,
"server can't handle ssl, business as usual");
225 X509_NAME_ENTRY *entry;
227 X509_EXTENSION *extension;
228 STACK_OF(GENERAL_NAME) *altnames;
229 GENERAL_NAME *altname;
230 OTHERNAME *othername;
233 int id_on_xmppAddr_nid;
234 ASN1_OBJECT *id_on_xmppAddr_obj;
236 int i, j, count,
id = 0, len;
239 if ((cert = SSL_get_peer_certificate(sc->ssl) ) == NULL)
244 id_on_xmppAddr_nid = OBJ_create(
"1.3.6.1.5.5.7.8.5",
"id-on-xmppAddr",
"XMPP Address Identity");
245 id_on_xmppAddr_obj = OBJ_nid2obj(id_on_xmppAddr_nid);
246 _sx_debug(
ZONE,
"external_id: Created id-on-xmppAddr SSL object");
249 for (i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
251 i = X509_get_ext_by_NID(cert, NID_subject_alt_name, i)) {
253 if ((extension = X509_get_ext(cert, i)) == NULL) {
254 _sx_debug(
ZONE,
"external_id: Can't get subjectAltName. Possibly malformed cert.");
258 if ((altnames = X509V3_EXT_d2i(extension)) == NULL) {
259 _sx_debug(
ZONE,
"external_id: Can't get all AltNames. Possibly malformed cert.");
263 count = sk_GENERAL_NAME_num(altnames);
264 for (j = 0; j < count; j++) {
265 if ((altname = sk_GENERAL_NAME_value(altnames, j)) == NULL) {
266 _sx_debug(
ZONE,
"external_id: Can't get AltName. Possibly malformed cert.");
270 if (altname->type == GEN_OTHERNAME &&
271 OBJ_cmp(altname->d.otherName->type_id, id_on_xmppAddr_obj) == 0) {
272 othername = altname->d.otherName;
273 len = ASN1_STRING_to_UTF8((
unsigned char **) &buff, othername->value->value.utf8string);
276 sc->external_id[id] = (
char *) malloc(
sizeof(
char) * (len + 1));
277 memcpy(sc->external_id[
id], buff, len);
278 sc->external_id[id][len] =
'\0';
279 _sx_debug(
ZONE,
"external_id: Found(%d) subjectAltName/id-on-xmppAddr: '%s'",
id, sc->external_id[
id]);
282 }
else if (altname->type == GEN_DNS) {
283 len = ASN1_STRING_length(altname->d.dNSName);
284 sc->external_id[id] = (
char *) malloc(
sizeof(
char) * (len + 1));
285 memcpy(sc->external_id[
id], ASN1_STRING_data(altname->d.dNSName), len);
286 sc->external_id[id][len] =
'\0';
287 _sx_debug(
ZONE,
"external_id: Found(%d) subjectAltName/dNSName: '%s'",
id, sc->external_id[
id]);
292 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
297 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
300 name = X509_get_subject_name(cert);
301 for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
303 i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
305 if ((entry = X509_NAME_get_entry(name, i)) == NULL) {
306 _sx_debug(
ZONE,
"external_id: Can't get commonName(%d). Possibly malformed cert. Continuing.", i);
310 len = ASN1_STRING_to_UTF8((
unsigned char **) &buff, X509_NAME_ENTRY_get_data(entry));
314 sc->external_id[id] = (
char *) malloc(
sizeof(
char) * (len + 1));
315 memcpy(sc->external_id[
id], buff, len);
316 sc->external_id[id][len] =
'\0';
317 _sx_debug(
ZONE,
"external_id: Found(%d) commonName: '%s'",
id, sc->external_id[
id]);
335 while(!SSL_is_init_finished(sc->ssl)) {
336 _sx_debug(
ZONE,
"secure channel not established, handshake in progress");
339 if(sc->last_state == SX_SSL_STATE_WANT_READ && BIO_pending(sc->rbio) == 0)
344 ret = SSL_connect(sc->ssl);
346 ret = SSL_accept(sc->ssl);
351 sc->last_state = SX_SSL_STATE_NONE;
353 s->
ssf = SSL_get_cipher_bits(sc->ssl, NULL);
355 _sx_debug(
ZONE,
"using cipher %s (%d bits)", SSL_get_cipher_name(sc->ssl), s->
ssf);
363 err = SSL_get_error(sc->ssl, ret);
365 if(err == SSL_ERROR_WANT_READ)
366 sc->last_state = SX_SSL_STATE_WANT_READ;
367 else if(err == SSL_ERROR_WANT_WRITE)
368 sc->last_state = SX_SSL_STATE_WANT_WRITE;
372 sc->last_state = SX_SSL_STATE_ERROR;
374 errstring = ERR_error_string(ERR_get_error(), NULL);
404 if(sc->last_state == SX_SSL_STATE_ERROR)
431 ret = SSL_write(sc->ssl, wbuf->data, wbuf->len);
437 jqueue_push(sc->wq, wbuf, (sc->wq->front != NULL) ? sc->wq->front->priority + 1 : 0);
440 err = SSL_get_error(sc->ssl, ret);
442 if(err == SSL_ERROR_ZERO_RETURN) {
447 if(err == SSL_ERROR_WANT_READ) {
450 sc->last_state = SX_SSL_STATE_WANT_READ;
454 sc->last_state = SX_SSL_STATE_ERROR;
457 errstring = ERR_error_string(ERR_get_error(), NULL);
477 if(BIO_pending(sc->wbio) > 0) {
478 int bytes_pending = BIO_pending(sc->wbio);
479 assert(buf->
len == 0);
481 BIO_read(sc->wbio, buf->
data, bytes_pending);
482 buf->
len += bytes_pending;
486 buf->
notify = wbuf->notify;
495 if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
503 int est, ret, err, pending;
508 if(sc->last_state == SX_SSL_STATE_ERROR)
517 BIO_write(sc->rbio, buf->
data, buf->
len);
530 pending = SSL_pending(sc->ssl);
532 pending = BIO_pending(sc->rbio);
535 while((pending = SSL_pending(sc->ssl)) > 0 || (pending = BIO_pending(sc->rbio)) > 0) {
538 ret = SSL_read(sc->ssl, &(buf->
data[buf->
len]), pending);
548 if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)
559 err = SSL_get_error(sc->ssl, ret);
564 if(err == SSL_ERROR_ZERO_RETURN) {
575 err = SSL_get_error(sc->ssl, ret);
578 if(err == SSL_ERROR_WANT_READ) {
579 sc->last_state = SX_SSL_STATE_WANT_READ;
590 sc->last_state = SX_SSL_STATE_ERROR;
592 errstring = ERR_error_string(ERR_get_error(), NULL);
614 if(BIO_pending(sc->wbio) > 0 || (est > 0 &&
jqueue_size(sc->wq) > 0))
618 if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
630 char *pemfile = NULL;
632 char *pemfile_password = NULL;
648 assert((
int) (ctx != NULL));
650 sc = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
653 sc->rbio = BIO_new(BIO_s_mem());
654 sc->wbio = BIO_new(BIO_s_mem());
657 sc->ssl = SSL_new(ctx);
658 SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
659 SSL_set_connect_state(sc->ssl);
661 #ifdef ENABLE_EXPERIMENTAL
662 SSL_set_ssl_method(sc->ssl, TLSv1_2_client_method());
664 SSL_set_ssl_method(sc->ssl, TLSv1_client_method());
669 sc->external_id[i] = NULL;
678 pemfile_password = ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password;
682 if(pemfile != NULL) {
684 ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
686 _sx_debug(
ZONE,
"couldn't load alternate certificate from %s", pemfile);
694 SSL_CTX_set_default_passwd_cb_userdata(sc->ssl->ctx, (
void *)pemfile_password);
698 ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
700 _sx_debug(
ZONE,
"couldn't load alternate private key from %s", pemfile);
708 ret = SSL_check_private_key(sc->ssl);
710 _sx_debug(
ZONE,
"private key does not match certificate public key");
750 assert((
int) (ctx != NULL));
752 sc = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
755 sc->rbio = BIO_new(BIO_s_mem());
756 sc->wbio = BIO_new(BIO_s_mem());
759 sc->ssl = SSL_new(ctx);
760 SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
761 SSL_set_accept_state(sc->ssl);
762 SSL_set_options(sc->ssl, SSL_OP_NO_SSLv3);
766 sc->external_id[i] = NULL;
794 if(sc->external_id[i] != NULL)
795 free(sc->external_id[i]);
799 if(sc->pemfile != NULL) free(sc->pemfile);
801 if(sc->private_key_password != NULL) free(sc->private_key_password);
803 if(sc->ssl != NULL) SSL_free(sc->ssl);
824 SSL_CTX_free((SSL_CTX *) ctx);
834 const char *name, *pemfile, *cachain, *password;
840 name = va_arg(args,
const char *);
841 pemfile = va_arg(args,
const char *);
848 cachain = va_arg(args,
const char *);
849 mode = va_arg(args,
int);
850 password = va_arg(args,
char *);
857 SSL_load_error_strings();
885 STACK_OF(X509_NAME) *cert_names;
904 #ifdef ENABLE_EXPERIMENTAL
905 ctx = SSL_CTX_new(TLSv1_2_method());
907 ctx = SSL_CTX_new(SSLv23_method());
910 _sx_debug(
ZONE,
"ssl context creation failed; %s", ERR_error_string(ERR_get_error(), NULL));
915 if (SSL_CTX_set_cipher_list(ctx,
"ALL:!LOW:!SSLv2:!EXP:!aNULL") != 1) {
916 _sx_debug(
ZONE,
"Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
922 if (cachain != NULL) {
923 ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
925 _sx_debug(
ZONE,
"WARNING: couldn't load CA chain: %s; %s", cachain, ERR_error_string(ERR_get_error(), NULL));
927 _sx_debug(
ZONE,
"Loaded CA verify location chain: %s", cachain);
929 cert_names = SSL_load_client_CA_file(cachain);
930 if (cert_names != NULL) {
931 SSL_CTX_set_client_CA_list(ctx, cert_names);
934 _sx_debug(
ZONE,
"WARNING: couldn't load client CA chain: %s", cachain);
942 SSL_CTX_set_default_verify_paths(ctx);
943 _sx_debug(
ZONE,
"No CA chain specified. Loading SSL default CA certs: /etc/ssl/certs");
946 store = SSL_CTX_get_cert_store(ctx);
949 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
952 ret = SSL_CTX_use_certificate_chain_file(ctx, pemfile);
954 _sx_debug(
ZONE,
"couldn't load certificate from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
960 SSL_CTX_set_default_passwd_cb_userdata(ctx, (
void *)password);
964 ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
966 _sx_debug(
ZONE,
"couldn't load private key from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
972 ret = SSL_CTX_check_private_key(ctx);
974 _sx_debug(
ZONE,
"private key does not match certificate public key; %s", ERR_error_string(ERR_get_error(), NULL));
979 _sx_debug(
ZONE,
"setting ssl context '%s' verify mode to %02x", name, mode);
983 if(contexts == NULL) {
985 p->
private = (
void *) contexts;
988 if(!(name[0] ==
'*' && name[1] == 0)) {
1000 _sx_debug(
ZONE,
"ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile);
1005 SSL_CTX_free((SSL_CTX *) tmp);
1013 assert((
int) (p != NULL));
1014 assert((
int) (s != NULL));
1018 _sx_debug(
ZONE,
"wrong conn type or state for client starttls");
1031 if(pemfile != NULL) {
1032 s->
plugin_data[p->
index] = (_sx_ssl_conn_t) calloc(1,
sizeof(
struct _sx_ssl_conn_st));
1036 if(private_key_password != NULL)
1037 ((_sx_ssl_conn_t)s->
plugin_data[p->
index])->private_key_password = strdup(private_key_password);
#define stream_err_UNDEFINED_CONDITION
int sx_ssl_server_addcert(sx_plugin_t p, const char *name, const char *pemfile, const char *cachain, int mode, const char *password)
args: name, pemfile, cachain, mode
#define _sx_event(s, e, data)
static int _sx_pem_passwd_callback(char *buf, int size, int rwflag, void *password)
int jqueue_size(jqueue_t q)
error info for event_ERROR
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)
void(* free)(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(* 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
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...
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
void(* server)(sx_t s, sx_plugin_t p)
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
int(* rio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
void * jqueue_pull(jqueue_t q)
int xhash_iter_first(xht h)
iteration
jqueue_t jqueue_new(void)
void(* unload)(sx_plugin_t p)
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
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)
int(* wio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
#define SX_SSL_WRAPPER
sx stream flags
#define _sx_gen_error(e, c, g, s)
helper macro to populate this struct
static int _sx_ssl_handshake(sx_t s, _sx_ssl_conn_t sc)
#define SX_CONN_EXTERNAL_ID_MAX_COUNT
void(* client)(sx_t s, sx_plugin_t p)
int(* process)(sx_t s, sx_plugin_t p, nad_t nad)
int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password)
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)