jabberd2  2.2.16
sx/ssl.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00026 #include "sx.h"
00027 #include <openssl/x509_vfy.h>
00028 
00029 
00030 /* code stolen from SSL_CTX_set_verify(3) */
00031 static int _sx_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
00032 {
00033     char    buf[256];
00034     X509   *err_cert;
00035     int     err, depth;
00036     SSL    *ssl;
00037 
00038     err_cert = X509_STORE_CTX_get_current_cert(ctx);
00039     err = X509_STORE_CTX_get_error(ctx);
00040     depth = X509_STORE_CTX_get_error_depth(ctx);
00041 
00042     /*
00043      * Ignore errors when we can't get CRLs in the certificate
00044      */
00045     if (!preverify_ok && err == X509_V_ERR_UNABLE_TO_GET_CRL) {
00046         _sx_debug(ZONE, "ignoring verify error:num=%d:%s:depth=%d:%s\n", err,
00047                          X509_verify_cert_error_string(err), depth, buf);
00048         preverify_ok = 1;
00049     }
00050 
00051     /*
00052      * Retrieve the pointer to the SSL of the connection currently treated
00053      * and the application specific data stored into the SSL object.
00054      */
00055     ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
00056     X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
00057 
00058     if (!preverify_ok) {
00059         _sx_debug(ZONE, "verify error:num=%d:%s:depth=%d:%s\n", err,
00060                  X509_verify_cert_error_string(err), depth, buf);
00061     }
00062     else
00063     {
00064         _sx_debug(ZONE, "OK! depth=%d:%s", depth, buf);
00065     }
00066 
00067     /*
00068      * At this point, err contains the last verification error. We can use
00069      * it for something special
00070      */
00071     if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
00072     {
00073       X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
00074       _sx_debug(ZONE, "issuer= %s\n", buf);
00075     }
00076 
00077     return preverify_ok;
00078  }
00079 
00080 static void _sx_ssl_starttls_notify_proceed(sx_t s, void *arg) {
00081     char *to = NULL;
00082     _sx_debug(ZONE, "preparing for starttls");
00083 
00084     /* store the destination so we can select an ssl context */
00085     if(s->req_to != NULL) to = strdup(s->req_to);
00086 
00087     _sx_reset(s);
00088 
00089     /* restore destination */
00090     if(s->req_to == NULL)
00091         s->req_to = to;
00092     else /* ? */
00093         free(to);
00094 
00095     /* start listening */
00096     sx_server_init(s, s->flags | SX_SSL_WRAPPER);
00097 }
00098 
00099 static int _sx_ssl_process(sx_t s, sx_plugin_t p, nad_t nad) {
00100     int flags;
00101     char *ns = NULL, *to = NULL, *from = NULL, *version = NULL;
00102     sx_error_t sxe;
00103 
00104     /* not interested if we're a server and we never offered it */
00105     if(s->type == type_SERVER && !(s->flags & SX_SSL_STARTTLS_OFFER))
00106         return 1;
00107 
00108     /* only want tls packets */
00109     if(NAD_ENS(nad, 0) < 0 || NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_TLS) || strncmp(NAD_NURI(nad, NAD_ENS(nad, 0)), uri_TLS, strlen(uri_TLS)) != 0)
00110         return 1;
00111 
00112     /* starttls from client */
00113     if(s->type == type_SERVER) {
00114         if(NAD_ENAME_L(nad, 0) == 8 && strncmp(NAD_ENAME(nad, 0), "starttls", 8) == 0) {
00115             nad_free(nad);
00116 
00117             /* can't go on if we've been here before */
00118             if(s->ssf > 0) {
00119                 _sx_debug(ZONE, "starttls requested on already encrypted channel, dropping packet");
00120                 return 0;
00121             }
00122 
00123             /* can't go on if we're on compressed stream */
00124             if(s->compressed > 0) {
00125                 _sx_debug(ZONE, "starttls requested on already compressed channel, dropping packet");
00126                 return 0;
00127             }
00128 
00129             _sx_debug(ZONE, "starttls requested, setting up");
00130 
00131             /* go ahead */
00132             jqueue_push(s->wbufq, _sx_buffer_new("<proceed xmlns='" uri_TLS "'/>", strlen(uri_TLS) + 19, _sx_ssl_starttls_notify_proceed, NULL), 0);
00133             s->want_write = 1;
00134 
00135             /* handled the packet */
00136             return 0;
00137         }
00138     }
00139 
00140     else if(s->type == type_CLIENT) {
00141         /* kick off the handshake */
00142         if(NAD_ENAME_L(nad, 0) == 7 && strncmp(NAD_ENAME(nad, 0), "proceed", 7) == 0) {
00143             nad_free(nad);
00144 
00145             /* save interesting bits */
00146             flags = s->flags;
00147 
00148             if(s->ns != NULL) ns = strdup(s->ns);
00149 
00150             if(s->req_to != NULL) to = strdup(s->req_to);
00151             if(s->req_from != NULL) from = strdup(s->req_from);
00152             if(s->req_version != NULL) version = strdup(s->req_version);
00153 
00154             /* reset state */
00155             _sx_reset(s);
00156 
00157             _sx_debug(ZONE, "server ready for ssl, starting");
00158 
00159             /* second time round */
00160             sx_client_init(s, flags | SX_SSL_WRAPPER, ns, to, from, version);
00161 
00162             /* free bits */
00163             if(ns != NULL) free(ns);
00164             if(to != NULL) free(to);
00165             if(from != NULL) free(from);
00166             if(version != NULL) free(version);
00167 
00168             return 0;
00169         }
00170 
00171         /* busted server */
00172         if(NAD_ENAME_L(nad, 0) == 7 && strncmp(NAD_ENAME(nad, 0), "failure", 7) == 0) {
00173             nad_free(nad);
00174 
00175             /* free the pemfile arg */
00176             if(s->plugin_data[p->index] != NULL) {
00177                 if( ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile != NULL )
00178                     free(((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile);
00179                 free(s->plugin_data[p->index]);
00180                 s->plugin_data[p->index] = NULL;
00181             }
00182 
00183             _sx_debug(ZONE, "server can't handle ssl, business as usual");
00184 
00185             _sx_gen_error(sxe, SX_ERR_STARTTLS_FAILURE, "STARTTLS failure", "Server was unable to prepare for the TLS handshake");
00186             _sx_event(s, event_ERROR, (void *) &sxe);
00187 
00188             return 0;
00189         }
00190     }
00191 
00192     _sx_debug(ZONE, "unknown starttls namespace element '%.*s', dropping packet", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0));
00193     nad_free(nad);
00194     return 0;
00195 }
00196 
00197 static void _sx_ssl_features(sx_t s, sx_plugin_t p, nad_t nad) {
00198     int ns;
00199 
00200     /* if the session is already encrypted, or the app told us not to,
00201      * or session is compressed then we don't offer anything */
00202     if(s->state > state_STREAM || s->ssf > 0 || !(s->flags & SX_SSL_STARTTLS_OFFER) || s->compressed)
00203         return;
00204 
00205     _sx_debug(ZONE, "offering starttls");
00206 
00207     ns = nad_add_namespace(nad, uri_TLS, NULL);
00208     nad_append_elem(nad, ns, "starttls", 1);
00209 
00210     if(s->flags & SX_SSL_STARTTLS_REQUIRE)
00211         nad_append_elem(nad, ns, "required", 2);
00212 }
00213 
00214 /* Extract id-on-xmppAddr from the certificate */
00215 static void _sx_ssl_get_external_id(sx_t s, _sx_ssl_conn_t sc) {
00216     X509 *cert;
00217     X509_NAME *name;
00218     X509_NAME_ENTRY *entry;
00219     // subjectAltName parsing
00220     X509_EXTENSION *extension;
00221     STACK_OF(GENERAL_NAME) *altnames;
00222     GENERAL_NAME *altname;
00223     OTHERNAME *othername;
00224     char * buff;
00225     // new object identifiers
00226     int id_on_xmppAddr_nid;
00227     ASN1_OBJECT *id_on_xmppAddr_obj;
00228     //  iterators
00229     int i, j, count,  id = 0, len;
00230 
00231     /* If there's not peer cert, quit */
00232     if ((cert = SSL_get_peer_certificate(sc->ssl) ) == NULL)
00233         return;
00234     _sx_debug(ZONE, "external_id: Got peer certificate");
00235 
00236     /* Allocate new id-on-xmppAddr object. See rfc3921bis 15.2.1.2 */
00237     id_on_xmppAddr_nid = OBJ_create("1.3.6.1.5.5.7.8.5", "id-on-xmppAddr", "XMPP Address Identity");
00238     id_on_xmppAddr_obj = OBJ_nid2obj(id_on_xmppAddr_nid);
00239     _sx_debug(ZONE, "external_id: Created id-on-xmppAddr SSL object");
00240 
00241     /* Iterate through all subjectAltName x509v3 extensions. Get id-on-xmppAddr and dDnsName */
00242     for (i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
00243          i != -1;
00244          i = X509_get_ext_by_NID(cert, NID_subject_alt_name, i)) {
00245         // Get this subjectAltName x509v3 extension
00246         if ((extension = X509_get_ext(cert, i)) == NULL) {
00247             _sx_debug(ZONE, "external_id: Can't get subjectAltName. Possibly malformed cert.");
00248             goto end;
00249         }
00250         // Get the collection of AltNames
00251         if ((altnames = X509V3_EXT_d2i(extension)) == NULL) {
00252             _sx_debug(ZONE, "external_id: Can't get all AltNames. Possibly malformed cert.");
00253             goto end;
00254         }
00255         /* Iterate through all altNames and get id-on-xmppAddr and dNSName */
00256         count = sk_GENERAL_NAME_num(altnames);
00257         for (j = 0; j < count; j++) {
00258             if ((altname = sk_GENERAL_NAME_value(altnames, j)) == NULL) {
00259                 _sx_debug(ZONE, "external_id: Can't get AltName. Possibly malformed cert.");
00260                 goto end;
00261             }
00262             /* Check if its otherName id-on-xmppAddr */
00263             if (altname->type == GEN_OTHERNAME &&
00264                 OBJ_cmp(altname->d.otherName->type_id, id_on_xmppAddr_obj) == 0) {
00265                 othername = altname->d.otherName;
00266                 len = ASN1_STRING_to_UTF8((unsigned char **) &buff, othername->value->value.utf8string);
00267                 if (len <= 0)
00268                     continue;
00269                 sc->external_id[id] = (char *) malloc(sizeof(char) *  (len + 1));
00270                 memcpy(sc->external_id[id], buff, len);
00271                 sc->external_id[id][len] = '\0'; // just to make sure
00272                 _sx_debug(ZONE, "external_id: Found(%d) subjectAltName/id-on-xmppAddr: '%s'", id, sc->external_id[id]);
00273                 id++;
00274                 OPENSSL_free(buff);
00275             } else if (altname->type == GEN_DNS) {
00276                 len = ASN1_STRING_length(altname->d.dNSName);
00277                 sc->external_id[id] = (char *) malloc(sizeof(char) *  (len + 1));
00278                 memcpy(sc->external_id[id], ASN1_STRING_data(altname->d.dNSName), len);
00279                 sc->external_id[id][len] = '\0'; // just to make sure
00280                 _sx_debug(ZONE, "external_id: Found(%d) subjectAltName/dNSName: '%s'", id, sc->external_id[id]);
00281                 id++;
00282             }
00283             /* Check if we're not out of space */
00284             if (id == SX_CONN_EXTERNAL_ID_MAX_COUNT) {
00285                 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
00286                 goto end;
00287             }
00288         }
00289 
00290         sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
00291     }
00292     /* Get CNs */
00293     name = X509_get_subject_name(cert);
00294     for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
00295          i != -1;
00296          i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
00297         // Get the commonName entry
00298         if ((entry = X509_NAME_get_entry(name, i)) == NULL) {
00299             _sx_debug(ZONE, "external_id: Can't get commonName(%d). Possibly malformed cert. Continuing.", i);
00300             continue;
00301         }
00302         // Get the commonName as UTF8 string
00303         len = ASN1_STRING_to_UTF8((unsigned char **) &buff, X509_NAME_ENTRY_get_data(entry));
00304         if (len <= 0) {
00305             continue;
00306         }
00307         sc->external_id[id] = (char *) malloc(sizeof(char) *  (len + 1));
00308         memcpy(sc->external_id[id], buff, len);
00309         sc->external_id[id][len] = '\0'; // just to make sure
00310         _sx_debug(ZONE, "external_id: Found(%d) commonName: '%s'", id, sc->external_id[id]);
00311         OPENSSL_free(buff);
00312         /* Check if we're not out of space */
00313         if (id == SX_CONN_EXTERNAL_ID_MAX_COUNT)
00314             goto end;
00315     }
00316 
00317 end:
00318     X509_free(cert);
00319     return;
00320 }
00321 
00322 static int _sx_ssl_handshake(sx_t s, _sx_ssl_conn_t sc) {
00323     int ret, err;
00324     char *errstring;
00325     sx_error_t sxe;
00326 
00327     /* work on establishing the channel */
00328     while(!SSL_is_init_finished(sc->ssl)) {
00329         _sx_debug(ZONE, "secure channel not established, handshake in progress");
00330 
00331         /* we can't handshake if they want to read, but there's nothing to read */
00332         if(sc->last_state == SX_SSL_STATE_WANT_READ && BIO_pending(sc->rbio) == 0)
00333             return 0;
00334 
00335         /* more handshake */
00336         if(s->type == type_CLIENT)
00337             ret = SSL_connect(sc->ssl);
00338         else
00339             ret = SSL_accept(sc->ssl);
00340 
00341         /* check if we're done */
00342         if(ret == 1) {
00343             _sx_debug(ZONE, "secure channel established");
00344             sc->last_state = SX_SSL_STATE_NONE;
00345 
00346             s->ssf = SSL_get_cipher_bits(sc->ssl, NULL);
00347 
00348             _sx_debug(ZONE, "using cipher %s (%d bits)", SSL_get_cipher_name(sc->ssl), s->ssf);
00349             _sx_ssl_get_external_id(s, sc);
00350 
00351             return 1;
00352         }
00353 
00354         /* error checking */
00355         else if(ret <= 0) {
00356             err = SSL_get_error(sc->ssl, ret);
00357 
00358             if(err == SSL_ERROR_WANT_READ)
00359                 sc->last_state = SX_SSL_STATE_WANT_READ;
00360             else if(err == SSL_ERROR_WANT_WRITE)
00361                 sc->last_state = SX_SSL_STATE_WANT_WRITE;
00362 
00363             else {
00364                 /* fatal error */
00365                 sc->last_state = SX_SSL_STATE_ERROR;
00366 
00367                 errstring = ERR_error_string(ERR_get_error(), NULL);
00368                 _sx_debug(ZONE, "openssl error: %s", errstring);
00369 
00370                 /* do not throw an error if in wrapper mode and pre-stream */
00371                 if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
00372                     _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
00373                     _sx_event(s, event_ERROR, (void *) &sxe);
00374                     sx_error(s, stream_err_UNDEFINED_CONDITION, errstring);
00375                 }
00376 
00377                 sx_close(s);
00378 
00379                 /* !!! drop queue */
00380 
00381                 return -1;
00382             }
00383         }
00384     }
00385 
00386     return 1;
00387 }
00388 
00389 static int _sx_ssl_wio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
00390     _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
00391     int est, ret, err;
00392     sx_buf_t wbuf;
00393     char *errstring;
00394     sx_error_t sxe;
00395 
00396     /* do not encrypt when error */
00397     if(sc->last_state == SX_SSL_STATE_ERROR)
00398         return 1;
00399 
00400     _sx_debug(ZONE, "in _sx_ssl_wio");
00401 
00402     /* queue the buffer */
00403     if(buf->len > 0) {
00404         _sx_debug(ZONE, "queueing buffer for write");
00405 
00406         jqueue_push(sc->wq, _sx_buffer_new(buf->data, buf->len, buf->notify, buf->notify_arg), 0);
00407         _sx_buffer_clear(buf);
00408         buf->notify = NULL;
00409         buf->notify_arg = NULL;
00410     }
00411 
00412     /* handshake */
00413     est = _sx_ssl_handshake(s, sc);
00414     if(est < 0)
00415         return -2;  /* fatal error */
00416 
00417     /* channel established, do some real writing */
00418     wbuf = NULL;
00419     if(est > 0 && jqueue_size(sc->wq) > 0) {
00420         _sx_debug(ZONE, "preparing queued buffer for write");
00421 
00422         wbuf = jqueue_pull(sc->wq);
00423 
00424         ret = SSL_write(sc->ssl, wbuf->data, wbuf->len);
00425         if(ret <= 0) {
00426             /* something's wrong */
00427             _sx_debug(ZONE, "write failed, requeuing buffer");
00428 
00429             /* requeue the buffer */
00430             jqueue_push(sc->wq, wbuf, (sc->wq->front != NULL) ? sc->wq->front->priority + 1 : 0);
00431 
00432             /* error checking */
00433             err = SSL_get_error(sc->ssl, ret);
00434 
00435             if(err == SSL_ERROR_ZERO_RETURN) {
00436                 /* ssl channel closed, we're done */
00437                 _sx_close(s);
00438             }
00439 
00440             if(err == SSL_ERROR_WANT_READ) {
00441                 /* we'll be renegotiating next time */
00442                 _sx_debug(ZONE, "renegotiation started");
00443                 sc->last_state = SX_SSL_STATE_WANT_READ;
00444             }
00445 
00446             else {
00447                 sc->last_state = SX_SSL_STATE_ERROR;
00448 
00449                 /* something very bad */
00450                 errstring = ERR_error_string(ERR_get_error(), NULL);
00451                 _sx_debug(ZONE, "openssl error: %s", errstring);
00452 
00453                 /* do not throw an error if in wrapper mode and pre-stream */
00454                 if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
00455                     _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
00456                     _sx_event(s, event_ERROR, (void *) &sxe);
00457                     sx_error(s, stream_err_UNDEFINED_CONDITION, errstring);
00458                 }
00459 
00460                 sx_close(s);
00461 
00462                 /* !!! drop queue */
00463 
00464                 return -2;  /* fatal */
00465             }
00466         }
00467     }
00468 
00469     /* prepare the buffer with stuff to write */
00470     if(BIO_pending(sc->wbio) > 0) {
00471         int bytes_pending = BIO_pending(sc->wbio);
00472         assert(buf->len == 0);
00473         _sx_buffer_alloc_margin(buf, 0, bytes_pending);
00474         BIO_read(sc->wbio, buf->data, bytes_pending);
00475         buf->len += bytes_pending;
00476 
00477         /* restore notify and clean up */
00478         if(wbuf != NULL) {
00479             buf->notify = wbuf->notify;
00480             buf->notify_arg = wbuf->notify_arg;
00481             _sx_buffer_free(wbuf);
00482         }
00483 
00484         _sx_debug(ZONE, "prepared %d ssl bytes for write", buf->len);
00485     }
00486 
00487     /* flag if we want to read */
00488     if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
00489         s->want_read = 1;
00490 
00491     return 1;
00492 }
00493 
00494 static int _sx_ssl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
00495     _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
00496     int est, ret, err, pending;
00497     char *errstring;
00498     sx_error_t sxe;
00499 
00500     /* sanity */
00501     if(sc->last_state == SX_SSL_STATE_ERROR)
00502         return -1;
00503 
00504     _sx_debug(ZONE, "in _sx_ssl_rio");
00505 
00506     /* move the data into the ssl read buffer */
00507     if(buf->len > 0) {
00508         _sx_debug(ZONE, "loading %d bytes into ssl read buffer", buf->len);
00509 
00510         BIO_write(sc->rbio, buf->data, buf->len);
00511 
00512         _sx_buffer_clear(buf);
00513     }
00514 
00515     /* handshake */
00516     est = _sx_ssl_handshake(s, sc);
00517     if(est < 0)
00518         return -1;  /* fatal error */
00519 
00520     /* channel is up, slurp up the read buffer */
00521     if(est > 0) {
00522 
00523         pending = SSL_pending(sc->ssl);
00524         if(pending == 0)
00525             pending = BIO_pending(sc->rbio);
00526 
00527         /* get it all */
00528         while((pending = SSL_pending(sc->ssl)) > 0 || (pending = BIO_pending(sc->rbio)) > 0) {
00529             _sx_buffer_alloc_margin(buf, 0, pending);
00530 
00531             ret = SSL_read(sc->ssl, &(buf->data[buf->len]), pending);
00532 
00533             if (ret == 0)
00534             {
00535                 /* ret will equal zero if the SSL stream was closed.
00536                    (See the SSL_read manpage.) */
00537 
00538                 /* If the SSL Shutdown happened properly,
00539                    (i.e. we got an SSL "close notify")
00540                    then proccess the last packet recieved. */
00541                 if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)
00542                 {
00543                   _sx_close(s);
00544                   break;
00545                 }
00546 
00547                 /* If the SSL stream was just closed and not shutdown,
00548                    drop the last packet recieved.
00549                    WARNING: This may cause clients that use SSLv2 and
00550                    earlier to not log out properly. */
00551 
00552                 err = SSL_get_error(sc->ssl, ret);
00553 
00554                 _sx_buffer_clear(buf);
00555 
00556 
00557                 if(err == SSL_ERROR_ZERO_RETURN) {
00558                     /* ssl channel closed, we're done */
00559                     _sx_close(s);
00560                 }
00561 
00562                 return -1;
00563             }
00564             else if(ret < 0) {
00565                 /* ret will be negative if the SSL stream needs
00566                    more data, or if there was a SSL error.
00567                    (See the SSL_read manpage.) */
00568                 err = SSL_get_error(sc->ssl, ret);
00569 
00570                 /* ssl block incomplete, need more */
00571                 if(err == SSL_ERROR_WANT_READ) {
00572                     sc->last_state = SX_SSL_STATE_WANT_READ;
00573 
00574                     break;
00575                 }
00576 
00577                 /* something's wrong */
00578                 _sx_buffer_clear(buf);
00579 
00580 
00581                 /* !!! need checks for renegotiation */
00582 
00583                 sc->last_state = SX_SSL_STATE_ERROR;
00584 
00585                 errstring = ERR_error_string(ERR_get_error(), NULL);
00586                 _sx_debug(ZONE, "openssl error: %s", errstring);
00587 
00588                 /* do not throw an error if in wrapper mode and pre-stream */
00589                 if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
00590                     _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
00591                     _sx_event(s, event_ERROR, (void *) &sxe);
00592                     sx_error(s, stream_err_UNDEFINED_CONDITION, errstring);
00593                 }
00594 
00595                 sx_close(s);
00596 
00597                 /* !!! drop queue */
00598 
00599                 return -1;
00600             }
00601 
00602             buf->len += ret;
00603         }
00604     }
00605 
00606     /* flag if stuff to write */
00607     if(BIO_pending(sc->wbio) > 0 || (est > 0 && jqueue_size(sc->wq) > 0))
00608         s->want_write = 1;
00609 
00610     /* flag if we want to read */
00611     if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
00612         s->want_read = 1;
00613 
00614     if(buf->len == 0)
00615         return 0;
00616 
00617     return 1;
00618 }
00619 
00620 static void _sx_ssl_client(sx_t s, sx_plugin_t p) {
00621     _sx_ssl_conn_t sc;
00622     SSL_CTX *ctx;
00623     char *pemfile = NULL;
00624     int ret, i;
00625 
00626     /* only bothering if they asked for wrappermode */
00627     if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
00628         return;
00629 
00630     _sx_debug(ZONE, "preparing for ssl connect for %d from %s", s->tag, s->req_from);
00631 
00632     /* find the ssl context for this source */
00633     ctx = xhash_get((xht) p->private, s->req_from);
00634     if(ctx == NULL) {
00635         _sx_debug(ZONE, "using default ssl context for %d", s->tag);
00636         ctx = xhash_get((xht) p->private, "*");
00637     } else {
00638         _sx_debug(ZONE, "using configured ssl context for %d", s->tag);
00639     }
00640     assert((int) (ctx != NULL));
00641 
00642     sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
00643 
00644     /* create the buffers */
00645     sc->rbio = BIO_new(BIO_s_mem());
00646     sc->wbio = BIO_new(BIO_s_mem());
00647 
00648     /* new ssl conn */
00649     sc->ssl = SSL_new(ctx);
00650     SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
00651     SSL_set_connect_state(sc->ssl);
00652     SSL_set_ssl_method(sc->ssl, TLSv1_client_method());
00653     SSL_set_options(sc->ssl, SSL_OP_NO_TICKET);
00654 
00655     /* empty external_id */
00656     for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
00657         sc->external_id[i] = NULL;
00658 
00659     /* alternate pemfile */
00660     /* !!! figure out how to error correctly here - just returning will cause
00661      *     us to send a normal unencrypted stream start while the server is
00662      *     waiting for ClientHelo. the server will flag an error, but it won't
00663      *     help the admin at all to figure out what happened */
00664     if(s->plugin_data[p->index] != NULL) {
00665         pemfile = ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile;
00666         free(s->plugin_data[p->index]);
00667         s->plugin_data[p->index] = NULL;
00668     }
00669     if(pemfile != NULL) {
00670         /* load the certificate */
00671         ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
00672         if(ret != 1) {
00673             _sx_debug(ZONE, "couldn't load alternate certificate from %s", pemfile);
00674             SSL_free(sc->ssl);
00675             free(sc);
00676             free(pemfile);
00677             return;
00678         }
00679 
00680         /* load the private key */
00681         ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
00682         if(ret != 1) {
00683             _sx_debug(ZONE, "couldn't load alternate private key from %s", pemfile);
00684             SSL_free(sc->ssl);
00685             free(sc);
00686             free(pemfile);
00687             return;
00688         }
00689 
00690         /* check the private key matches the certificate */
00691         ret = SSL_check_private_key(sc->ssl);
00692         if(ret != 1) {
00693             _sx_debug(ZONE, "private key does not match certificate public key");
00694             SSL_free(sc->ssl);
00695             free(sc);
00696             free(pemfile);
00697             return;
00698         }
00699 
00700         _sx_debug(ZONE, "loaded alternate pemfile %s", pemfile);
00701 
00702         free(pemfile);
00703     }
00704 
00705     /* buffer queue */
00706     sc->wq = jqueue_new();
00707 
00708     s->plugin_data[p->index] = (void *) sc;
00709 
00710     /* bring the plugin online */
00711     _sx_chain_io_plugin(s, p);
00712 }
00713 
00714 static void _sx_ssl_server(sx_t s, sx_plugin_t p) {
00715     _sx_ssl_conn_t sc;
00716     SSL_CTX *ctx;
00717     int i;
00718 
00719     /* only bothering if they asked for wrappermode */
00720     if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
00721         return;
00722 
00723     _sx_debug(ZONE, "preparing for ssl accept for %d to %s", s->tag, s->req_to);
00724 
00725     /* find the ssl context for this destination */
00726     ctx = xhash_get((xht) p->private, s->req_to);
00727     if(ctx == NULL) {
00728         _sx_debug(ZONE, "using default ssl context for %d", s->tag);
00729         ctx = xhash_get((xht) p->private, "*");
00730     } else {
00731         _sx_debug(ZONE, "using configured ssl context for %d", s->tag);
00732     }
00733     assert((int) (ctx != NULL));
00734 
00735     sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
00736 
00737     /* create the buffers */
00738     sc->rbio = BIO_new(BIO_s_mem());
00739     sc->wbio = BIO_new(BIO_s_mem());
00740 
00741     /* new ssl conn */
00742     sc->ssl = SSL_new(ctx);
00743     SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
00744     SSL_set_accept_state(sc->ssl);
00745 
00746     /* empty external_id */
00747     for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
00748         sc->external_id[i] = NULL;
00749 
00750     /* buffer queue */
00751     sc->wq = jqueue_new();
00752 
00753     s->plugin_data[p->index] = (void *) sc;
00754 
00755     /* bring the plugin online */
00756     _sx_chain_io_plugin(s, p);
00757 }
00758 
00760 static void _sx_ssl_free(sx_t s, sx_plugin_t p) {
00761     _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
00762     sx_buf_t buf;
00763     int i;
00764 
00765     if(sc == NULL)
00766         return;
00767 
00768     log_debug(ZONE, "cleaning up conn state");
00769 
00770     if(s->type == type_NONE) {
00771         free(sc);
00772         return;
00773     }
00774 
00775     for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
00776         if(sc->external_id[i] != NULL)
00777             free(sc->external_id[i]);
00778         else
00779             break;
00780 
00781     if(sc->pemfile != NULL) free(sc->pemfile);
00782 
00783     if(sc->ssl != NULL) SSL_free(sc->ssl);      /* frees wbio and rbio too */
00784 
00785     if(sc->wq != NULL) {
00786         while((buf = jqueue_pull(sc->wq)) != NULL)
00787             _sx_buffer_free(buf);
00788 
00789         jqueue_free(sc->wq);
00790     }
00791 
00792     free(sc);
00793 
00794     s->plugin_data[p->index] = NULL;
00795 }
00796 
00797 static void _sx_ssl_unload(sx_plugin_t p) {
00798     xht contexts = (xht) p->private;
00799     void *ctx;
00800 
00801     if(xhash_iter_first(contexts))
00802         do {
00803             xhash_iter_get(contexts, NULL, NULL, &ctx);
00804             SSL_CTX_free((SSL_CTX *) ctx);
00805         } while(xhash_iter_next(contexts));
00806 
00807     xhash_free(contexts);
00808 }
00809 
00810 int sx_openssl_initialized = 0;
00811 
00813 int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) {
00814     char *name, *pemfile, *cachain;
00815     int ret;
00816     int mode;
00817 
00818     _sx_debug(ZONE, "initialising ssl plugin");
00819 
00820     name = va_arg(args, char *);
00821     pemfile = va_arg(args, char *);
00822     if(pemfile == NULL)
00823         return 1;
00824 
00825     if(p->private != NULL)
00826         return 1;
00827 
00828     cachain = va_arg(args, char *);
00829     mode = va_arg(args, int);
00830 
00831     /* !!! output openssl error messages to the debug log */
00832 
00833     /* openssl startup */
00834     if(!sx_openssl_initialized) {
00835         SSL_library_init();
00836         SSL_load_error_strings();
00837     }
00838     sx_openssl_initialized = 1;
00839 
00840     ret = sx_ssl_server_addcert(p, name, pemfile, cachain, mode);
00841     if(ret)
00842         return 1;
00843 
00844     p->magic = SX_SSL_MAGIC;
00845 
00846     p->unload = _sx_ssl_unload;
00847 
00848     p->client = _sx_ssl_client;
00849     p->server = _sx_ssl_server;
00850     p->rio = _sx_ssl_rio;
00851     p->wio = _sx_ssl_wio;
00852     p->features = _sx_ssl_features;
00853     p->process = _sx_ssl_process;
00854     p->free = _sx_ssl_free;
00855 
00856     return 0;
00857 }
00858 
00860 int sx_ssl_server_addcert(sx_plugin_t p, char *name, char *pemfile, char *cachain, int mode) {
00861     xht contexts = (xht) p->private;
00862     SSL_CTX *ctx;
00863     SSL_CTX *tmp;
00864     STACK_OF(X509_NAME) *cert_names;
00865     X509_STORE * store;
00866     int ret;
00867 
00868     if(!sx_openssl_initialized) {
00869         _sx_debug(ZONE, "ssl plugin not initialised");
00870         return 1;
00871     }
00872 
00873     if(name == NULL)
00874         name = "*";
00875 
00876     if(pemfile == NULL)
00877         return 1;
00878 
00879     /* begin with fresh error stack */
00880     ERR_clear_error();
00881 
00882     /* create the context */
00883     ctx = SSL_CTX_new(SSLv23_method());
00884     if(ctx == NULL) {
00885         _sx_debug(ZONE, "ssl context creation failed; %s", ERR_error_string(ERR_get_error(), NULL));
00886         return 1;
00887     }
00888 
00889     // Set allowed ciphers
00890     if (SSL_CTX_set_cipher_list(ctx, "ALL:!LOW:!SSLv2:!EXP:!aNULL") != 1) {
00891         _sx_debug(ZONE, "Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
00892         SSL_CTX_free(ctx);
00893         return 1;
00894     }
00895 
00896     /* Load the CA chain, if configured */
00897     if (cachain != NULL) {
00898         ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
00899         if(ret != 1) {
00900             _sx_debug(ZONE, "WARNING: couldn't load CA chain: %s; %s", cachain, ERR_error_string(ERR_get_error(), NULL));
00901         } else {
00902             _sx_debug(ZONE, "Loaded CA verify location chain: %s", cachain);
00903         }
00904         cert_names = SSL_load_client_CA_file(cachain);
00905         if (cert_names != NULL) {
00906             SSL_CTX_set_client_CA_list(ctx, cert_names);
00907             _sx_debug(ZONE, "Loaded client CA chain: %s", cachain);
00908         } else {
00909             _sx_debug(ZONE, "WARNING: couldn't load client CA chain: %s", cachain);
00910         }
00911     } else {
00912         /* Load the default OpenlSSL certs from /etc/ssl/certs
00913          We must assume that the client certificate's CA is there
00914 
00915          Note: We don't send client_CA_list here. Will possibly break some clients.
00916          */
00917         SSL_CTX_set_default_verify_paths(ctx);
00918         _sx_debug(ZONE, "No CA chain specified. Loading SSL default CA certs: /etc/ssl/certs");
00919     }
00920     /* Add server CRL verificaition */
00921     store = SSL_CTX_get_cert_store(ctx);
00922     // Not sure if this should be X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL
00923     // or only X509_V_FLAG_CRL_CHECK
00924     X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
00925 
00926     /* load the certificate */
00927     ret = SSL_CTX_use_certificate_chain_file(ctx, pemfile);
00928     if(ret != 1) {
00929         _sx_debug(ZONE, "couldn't load certificate from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
00930         SSL_CTX_free(ctx);
00931         return 1;
00932     }
00933 
00934     /* load the private key */
00935     ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
00936     if(ret != 1) {
00937         _sx_debug(ZONE, "couldn't load private key from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
00938         SSL_CTX_free(ctx);
00939         return 1;
00940     }
00941 
00942     /* check the private key matches the certificate */
00943     ret = SSL_CTX_check_private_key(ctx);
00944     if(ret != 1) {
00945         _sx_debug(ZONE, "private key does not match certificate public key; %s", ERR_error_string(ERR_get_error(), NULL));
00946         SSL_CTX_free(ctx);
00947         return 1;
00948     }
00949 
00950     _sx_debug(ZONE, "setting ssl context '%s' verify mode to %02x", name, mode);
00951     SSL_CTX_set_verify(ctx, mode, _sx_ssl_verify_callback);
00952 
00953     /* create hash and create default context */
00954     if(contexts == NULL) {
00955         contexts = xhash_new(1021);
00956         p->private = (void *) contexts;
00957 
00958         /* this is the first context, if it's not the default then make a copy of it as the default */
00959         if(!(name[0] == '*' && name[1] == 0)) {
00960             int ret = sx_ssl_server_addcert(p, "*", pemfile, cachain, mode);
00961 
00962             if(ret) {
00963                 /* uh-oh */
00964                 xhash_free(contexts);
00965                 p->private = NULL;
00966                 return 1;
00967             }
00968         }
00969     }
00970 
00971     _sx_debug(ZONE, "ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile);
00972 
00973     /* remove an existing context with the same name before replacing it */
00974     tmp = xhash_get(contexts, name);
00975     if(tmp != NULL)
00976         SSL_CTX_free((SSL_CTX *) tmp);
00977 
00978     xhash_put(contexts, name, ctx);
00979 
00980     return 0;
00981 }
00982 
00983 int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, char *pemfile) {
00984     assert((int) (p != NULL));
00985     assert((int) (s != NULL));
00986 
00987     /* sanity */
00988     if(s->type != type_CLIENT || s->state != state_STREAM) {
00989         _sx_debug(ZONE, "wrong conn type or state for client starttls");
00990         return 1;
00991     }
00992 
00993     /* check if we're already encrypted or compressed */
00994     if(s->ssf > 0 || s->compressed) {
00995         _sx_debug(ZONE, "encrypted channel already established");
00996         return 1;
00997     }
00998 
00999     _sx_debug(ZONE, "initiating starttls sequence");
01000 
01001     /* save the given pemfile for later */
01002     if(pemfile != NULL) {
01003         s->plugin_data[p->index] = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
01004         ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile = strdup(pemfile);
01005     }
01006 
01007     /* go */
01008     jqueue_push(s->wbufq, _sx_buffer_new("<starttls xmlns='" uri_TLS "'/>", strlen(uri_TLS) + 20, NULL, NULL), 0);
01009     s->want_write = 1;
01010     _sx_event(s, event_WANT_WRITE, NULL);
01011 
01012     return 0;
01013 }