jabberd2  2.7.0
ssl.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
26 #include "sx.h"
27 #include <openssl/x509_vfy.h>
28 #include <openssl/dh.h>
29 #include <openssl/bn.h>
30 
31 
32 /* code stolen from SSL_CTX_set_verify(3) */
33 static int _sx_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
34 {
35  char buf[256];
36  X509 *err_cert;
37  int err, depth;
38 
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);
42 
43  /*
44  * Ignore errors when we can't get CRLs in the certificate
45  */
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);
49  preverify_ok = 1;
50  }
51 
52  /*
53  * Retrieve the pointer to the SSL of the connection currently treated
54  * and the application specific data stored into the SSL object.
55  */
56  X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
57 
58  if (!preverify_ok) {
59  _sx_debug(ZONE, "verify error:num=%d:%s:depth=%d:%s\n", err,
60  X509_verify_cert_error_string(err), depth, buf);
61  }
62  else
63  {
64  _sx_debug(ZONE, "OK! depth=%d:%s", depth, buf);
65  }
66 
67  /*
68  * At this point, err contains the last verification error. We can use
69  * it for something special
70  */
71  if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
72  {
73  X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
74  _sx_debug(ZONE, "issuer= %s\n", buf);
75  }
76 
77  return preverify_ok;
78  }
79 
80 static int _sx_pem_passwd_callback(char *buf, int size, int rwflag, void *password)
81 {
82  strncpy(buf, (char *)(password), size);
83  buf[size - 1] = '\0';
84  return(strlen(buf));
85 }
86 
87 #define DECLARE_sx_ssl_getparams(name, type) \
88  static type *sx_ssl_get_##name(const char *file) { \
89  type *ret; \
90  BIO *bio; \
91  if ((bio = BIO_new_file(file, "r")) == NULL) \
92  return NULL; \
93  ret = PEM_read_bio_##name(bio, NULL, NULL, NULL); \
94  BIO_free(bio); \
95  return ret; \
96  }
98 DECLARE_sx_ssl_getparams(ECPKParameters, EC_GROUP)
99 
100 static struct {
101  BIGNUM *(*const get_prime)(BIGNUM *);
102  DH *dh;
103  const unsigned minlen;
104 } dhparams[] = {
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 }
111 };
112 
113 static DH *sx_ssl_make_dh_params(BIGNUM *(*const get_prime)(BIGNUM *), const char *gen) {
114  DH *dh = DH_new();
115  if (!dh)
116  return NULL;
117 
118 #if OPENSSL_VERSION_NUMBER < 0x10100005L
119  dh->p = get_prime(NULL);
120  BN_dec2bn(&dh->g, gen);
121  if (!dh->p || !dh->g) {
122  DH_free(dh);
123  return NULL;
124  }
125 #else
126  {
127  BIGNUM *p, *g = NULL;
128  p = get_prime(NULL);
129  BN_dec2bn(&g, gen);
130 
131  if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
132  DH_free(dh);
133  BN_free(p);
134  BN_free(g);
135  return NULL;
136  }
137  }
138 #endif
139  return dh;
140 }
141 
142 static void sx_ssl_free_dh_params(void) {
143  unsigned i;
144  for (i = 0; i < sizeof(dhparams)/sizeof(dhparams[0]); i++) {
145  DH_free(dhparams[i].dh);
146  dhparams[i].dh = NULL;
147  }
148 }
149 
150 static DH *_sx_ssl_tmp_dh_callback(SSL *ssl, int export, int keylen) {
151  EVP_PKEY *pkey = SSL_get_privatekey(ssl);
152  int type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
153  unsigned i;
154 
155  if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA)
156  keylen = EVP_PKEY_bits(pkey);
157 
158  for (i = 0; i < sizeof(dhparams)/sizeof(dhparams[0]); i++) {
159  if (keylen >= dhparams[i].minlen) {
160  if (dhparams[i].dh == NULL)
161  dhparams[i].dh = sx_ssl_make_dh_params(dhparams[i].get_prime, "2");
162  return dhparams[i].dh;
163  }
164  }
165 
166  return NULL;
167 }
168 
169 static void _sx_ssl_starttls_notify_proceed(sx_t s, void *arg) {
170  char *to = NULL;
171  _sx_debug(ZONE, "preparing for starttls");
172 
173  /* store the destination so we can select an ssl context */
174  if(s->req_to != NULL) to = strdup(s->req_to);
175 
176  _sx_reset(s);
177 
178  /* restore destination */
179  if(s->req_to == NULL)
180  s->req_to = to;
181  else /* ? */
182  free(to);
183 
184  /* start listening */
186 }
187 
188 static int _sx_ssl_process(sx_t s, sx_plugin_t p, nad_t nad) {
189  int flags;
190  char *ns = NULL, *to = NULL, *from = NULL, *version = NULL;
191  sx_error_t sxe;
192 
193  /* not interested if we're a server and we never offered it */
194  if(s->type == type_SERVER && !(s->flags & SX_SSL_STARTTLS_OFFER))
195  return 1;
196 
197  /* only want tls packets */
198  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)
199  return 1;
200 
201  /* starttls from client */
202  if(s->type == type_SERVER) {
203  if(NAD_ENAME_L(nad, 0) == 8 && strncmp(NAD_ENAME(nad, 0), "starttls", 8) == 0) {
204  nad_free(nad);
205 
206  /* can't go on if we've been here before */
207  if(s->ssf > 0) {
208  _sx_debug(ZONE, "starttls requested on already encrypted channel, dropping packet");
209  return 0;
210  }
211 
212  /* can't go on if we're on compressed stream */
213  if(s->flags & SX_COMPRESS_WRAPPER) {
214  _sx_debug(ZONE, "starttls requested on already compressed channel, dropping packet");
215  return 0;
216  }
217 
218  _sx_debug(ZONE, "starttls requested, setting up");
219 
220  /* go ahead */
221  jqueue_push(s->wbufq, _sx_buffer_new("<proceed xmlns='" uri_TLS "'/>", strlen(uri_TLS) + 19, _sx_ssl_starttls_notify_proceed, NULL), 0);
222  s->want_write = 1;
223 
224  /* handled the packet */
225  return 0;
226  }
227  }
228 
229  else if(s->type == type_CLIENT) {
230  /* kick off the handshake */
231  if(NAD_ENAME_L(nad, 0) == 7 && strncmp(NAD_ENAME(nad, 0), "proceed", 7) == 0) {
232  nad_free(nad);
233 
234  /* save interesting bits */
235  flags = s->flags;
236 
237  if(s->ns != NULL) ns = strdup(s->ns);
238 
239  if(s->req_to != NULL) to = strdup(s->req_to);
240  if(s->req_from != NULL) from = strdup(s->req_from);
241  if(s->req_version != NULL) version = strdup(s->req_version);
242 
243  /* reset state */
244  _sx_reset(s);
245 
246  _sx_debug(ZONE, "server ready for ssl, starting");
247 
248  /* second time round */
249  sx_client_init(s, flags | SX_SSL_WRAPPER, ns, to, from, version);
250 
251  /* free bits */
252  if(ns != NULL) free(ns);
253  if(to != NULL) free(to);
254  if(from != NULL) free(from);
255  if(version != NULL) free(version);
256 
257  return 0;
258  }
259 
260  /* busted server */
261  if(NAD_ENAME_L(nad, 0) == 7 && strncmp(NAD_ENAME(nad, 0), "failure", 7) == 0) {
262  nad_free(nad);
263 
264  /* free the pemfile arg */
265  if(s->plugin_data[p->index] != NULL) {
266  if( ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile != NULL )
267  free(((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile);
268  if( ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password != NULL )
269  free(((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password);
270  free(s->plugin_data[p->index]);
271  s->plugin_data[p->index] = NULL;
272  }
273 
274  _sx_debug(ZONE, "server can't handle ssl, business as usual");
275 
276  _sx_gen_error(sxe, SX_ERR_STARTTLS_FAILURE, "STARTTLS failure", "Server was unable to prepare for the TLS handshake");
277  _sx_event(s, event_ERROR, (void *) &sxe);
278 
279  return 0;
280  }
281  }
282 
283  _sx_debug(ZONE, "unknown starttls namespace element '%.*s', dropping packet", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0));
284  nad_free(nad);
285  return 0;
286 }
287 
288 static void _sx_ssl_features(sx_t s, sx_plugin_t p, nad_t nad) {
289  int ns;
290 
291  /* if the session is already encrypted, or the app told us not to,
292  * or session is compressed then we don't offer anything */
293  if(s->state > state_STREAM || s->ssf > 0 || !(s->flags & SX_SSL_STARTTLS_OFFER) || (s->flags & SX_COMPRESS_WRAPPER))
294  return;
295 
296  _sx_debug(ZONE, "offering starttls");
297 
298  ns = nad_add_namespace(nad, uri_TLS, NULL);
299  nad_append_elem(nad, ns, "starttls", 1);
300 
302  nad_append_elem(nad, ns, "required", 2);
303 }
304 
305 /* Extract id-on-xmppAddr from the certificate */
306 static void _sx_ssl_get_external_id(sx_t s, _sx_ssl_conn_t sc) {
307  X509 *cert;
308  X509_NAME *name;
309  X509_NAME_ENTRY *entry;
310  // subjectAltName parsing
311  X509_EXTENSION *extension;
312  STACK_OF(GENERAL_NAME) *altnames;
313  GENERAL_NAME *altname;
314  OTHERNAME *othername;
315  char * buff;
316  // new object identifiers
317  int id_on_xmppAddr_nid;
318  ASN1_OBJECT *id_on_xmppAddr_obj;
319  // iterators
320  int i, j, count, id = 0, len;
321 
322  /* If there's not peer cert, quit */
323  if ((cert = SSL_get_peer_certificate(sc->ssl) ) == NULL)
324  return;
325  _sx_debug(ZONE, "external_id: Got peer certificate");
326 
327  /* Allocate new id-on-xmppAddr object. See rfc3921bis 15.2.1.2 */
328  id_on_xmppAddr_nid = OBJ_create("1.3.6.1.5.5.7.8.5", "id-on-xmppAddr", "XMPP Address Identity");
329  id_on_xmppAddr_obj = OBJ_nid2obj(id_on_xmppAddr_nid);
330  _sx_debug(ZONE, "external_id: Created id-on-xmppAddr SSL object");
331 
332  /* Iterate through all subjectAltName x509v3 extensions. Get id-on-xmppAddr and dDnsName */
333  for (i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
334  i != -1;
335  i = X509_get_ext_by_NID(cert, NID_subject_alt_name, i)) {
336  // Get this subjectAltName x509v3 extension
337  if ((extension = X509_get_ext(cert, i)) == NULL) {
338  _sx_debug(ZONE, "external_id: Can't get subjectAltName. Possibly malformed cert.");
339  goto end;
340  }
341  // Get the collection of AltNames
342  if ((altnames = X509V3_EXT_d2i(extension)) == NULL) {
343  _sx_debug(ZONE, "external_id: Can't get all AltNames. Possibly malformed cert.");
344  goto end;
345  }
346  /* Iterate through all altNames and get id-on-xmppAddr and dNSName */
347  count = sk_GENERAL_NAME_num(altnames);
348  for (j = 0; j < count; j++) {
349  if ((altname = sk_GENERAL_NAME_value(altnames, j)) == NULL) {
350  _sx_debug(ZONE, "external_id: Can't get AltName. Possibly malformed cert.");
351  goto end;
352  }
353  /* Check if its otherName id-on-xmppAddr */
354  if (altname->type == GEN_OTHERNAME &&
355  OBJ_cmp(altname->d.otherName->type_id, id_on_xmppAddr_obj) == 0) {
356  othername = altname->d.otherName;
357  len = ASN1_STRING_to_UTF8((unsigned char **) &buff, othername->value->value.utf8string);
358  if (len <= 0)
359  continue;
360  sc->external_id[id] = (char *) malloc(sizeof(char) * (len + 1));
361  memcpy(sc->external_id[id], buff, len);
362  sc->external_id[id][len] = '\0'; // just to make sure
363  _sx_debug(ZONE, "external_id: Found(%d) subjectAltName/id-on-xmppAddr: '%s'", id, sc->external_id[id]);
364  id++;
365  OPENSSL_free(buff);
366  } else if (altname->type == GEN_DNS) {
367  len = ASN1_STRING_length(altname->d.dNSName);
368  sc->external_id[id] = (char *) malloc(sizeof(char) * (len + 1));
369 #if OPENSSL_VERSION_NUMBER < 0x10100005L
370  memcpy(sc->external_id[id], ASN1_STRING_data(altname->d.dNSName), len);
371 #else
372  memcpy(sc->external_id[id], ASN1_STRING_get0_data(altname->d.dNSName), len);
373 #endif
374  sc->external_id[id][len] = '\0'; // just to make sure
375  _sx_debug(ZONE, "external_id: Found(%d) subjectAltName/dNSName: '%s'", id, sc->external_id[id]);
376  id++;
377  }
378  /* Check if we're not out of space */
379  if (id == SX_CONN_EXTERNAL_ID_MAX_COUNT) {
380  sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
381  goto end;
382  }
383  }
384 
385  sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
386  }
387  /* Get CNs */
388  name = X509_get_subject_name(cert);
389  for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
390  i != -1;
391  i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
392  // Get the commonName entry
393  if ((entry = X509_NAME_get_entry(name, i)) == NULL) {
394  _sx_debug(ZONE, "external_id: Can't get commonName(%d). Possibly malformed cert. Continuing.", i);
395  continue;
396  }
397  // Get the commonName as UTF8 string
398  len = ASN1_STRING_to_UTF8((unsigned char **) &buff, X509_NAME_ENTRY_get_data(entry));
399  if (len <= 0) {
400  continue;
401  }
402  sc->external_id[id] = (char *) malloc(sizeof(char) * (len + 1));
403  memcpy(sc->external_id[id], buff, len);
404  sc->external_id[id][len] = '\0'; // just to make sure
405  _sx_debug(ZONE, "external_id: Found(%d) commonName: '%s'", id, sc->external_id[id]);
406  id++;
407  OPENSSL_free(buff);
408  /* Check if we're not out of space */
410  goto end;
411  }
412 
413 end:
414  X509_free(cert);
415  return;
416 }
417 
418 static int _sx_ssl_handshake(sx_t s, _sx_ssl_conn_t sc) {
419  int ret, err;
420  char *errstring;
421  sx_error_t sxe;
422 
423  /* work on establishing the channel */
424  while(!SSL_is_init_finished(sc->ssl)) {
425  _sx_debug(ZONE, "secure channel not established, handshake in progress");
426 
427  /* we can't handshake if they want to read, but there's nothing to read */
428  if(sc->last_state == SX_SSL_STATE_WANT_READ && BIO_pending(sc->rbio) == 0)
429  return 0;
430 
431  /* more handshake */
432  if(s->type == type_CLIENT)
433  ret = SSL_connect(sc->ssl);
434  else
435  ret = SSL_accept(sc->ssl);
436 
437  /* check if we're done */
438  if(ret == 1) {
439  _sx_debug(ZONE, "secure channel established");
440  sc->last_state = SX_SSL_STATE_NONE;
441 
442  s->ssf = SSL_get_cipher_bits(sc->ssl, NULL);
443 
444  _sx_debug(ZONE, "using cipher %s (%d bits)", SSL_get_cipher_name(sc->ssl), s->ssf);
446 
447  return 1;
448  }
449 
450  /* error checking */
451  else if(ret <= 0) {
452  err = SSL_get_error(sc->ssl, ret);
453 
454  if(err == SSL_ERROR_WANT_READ)
455  sc->last_state = SX_SSL_STATE_WANT_READ;
456  else if(err == SSL_ERROR_WANT_WRITE)
457  sc->last_state = SX_SSL_STATE_WANT_WRITE;
458 
459  else {
460  /* fatal error */
461  sc->last_state = SX_SSL_STATE_ERROR;
462 
463  errstring = ERR_error_string(ERR_get_error(), NULL);
464  _sx_debug(ZONE, "openssl error: %s", errstring);
465 
466  /* do not throw an error if in wrapper mode and pre-stream */
467  if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
468  _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
469  _sx_event(s, event_ERROR, (void *) &sxe);
471  }
472 
473  sx_close(s);
474 
475  /* !!! drop queue */
476 
477  return -1;
478  }
479  }
480  }
481 
482  return 1;
483 }
484 
485 static int _sx_ssl_wio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
486  _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
487  int est, ret, err;
488  sx_buf_t wbuf;
489  char *errstring;
490  sx_error_t sxe;
491 
492  /* do not encrypt when error */
493  if(sc->last_state == SX_SSL_STATE_ERROR)
494  return 1;
495 
496  _sx_debug(ZONE, "in _sx_ssl_wio");
497 
498  /* queue the buffer */
499  if(buf->len > 0) {
500  _sx_debug(ZONE, "queueing buffer for write");
501 
502  jqueue_push(sc->wq, _sx_buffer_new(buf->data, buf->len, buf->notify, buf->notify_arg), 0);
503  _sx_buffer_clear(buf);
504  buf->notify = NULL;
505  buf->notify_arg = NULL;
506  }
507 
508  /* handshake */
509  est = _sx_ssl_handshake(s, sc);
510  if(est < 0)
511  return -2; /* fatal error */
512 
513  /* channel established, do some real writing */
514  wbuf = NULL;
515  if(est > 0 && jqueue_size(sc->wq) > 0) {
516  _sx_debug(ZONE, "preparing queued buffer for write");
517 
518  wbuf = jqueue_pull(sc->wq);
519 
520  ret = SSL_write(sc->ssl, wbuf->data, wbuf->len);
521  if(ret <= 0) {
522  /* something's wrong */
523  _sx_debug(ZONE, "write failed, requeuing buffer");
524 
525  /* requeue the buffer */
526  jqueue_push(sc->wq, wbuf, (sc->wq->front != NULL) ? sc->wq->front->priority + 1 : 0);
527 
528  /* error checking */
529  err = SSL_get_error(sc->ssl, ret);
530 
531  if(err == SSL_ERROR_ZERO_RETURN) {
532  /* ssl channel closed, we're done */
533  _sx_close(s);
534  }
535 
536  if(err == SSL_ERROR_WANT_READ) {
537  /* we'll be renegotiating next time */
538  _sx_debug(ZONE, "renegotiation started");
539  sc->last_state = SX_SSL_STATE_WANT_READ;
540  }
541 
542  else {
543  sc->last_state = SX_SSL_STATE_ERROR;
544 
545  /* something very bad */
546  errstring = ERR_error_string(ERR_get_error(), NULL);
547  _sx_debug(ZONE, "openssl error: %s", errstring);
548 
549  /* do not throw an error if in wrapper mode and pre-stream */
550  if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
551  _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
552  _sx_event(s, event_ERROR, (void *) &sxe);
554  }
555 
556  sx_close(s);
557 
558  /* !!! drop queue */
559 
560  return -2; /* fatal */
561  }
562  }
563  }
564 
565  /* prepare the buffer with stuff to write */
566  if(BIO_pending(sc->wbio) > 0) {
567  int bytes_pending = BIO_pending(sc->wbio);
568  assert(buf->len == 0);
569  _sx_buffer_alloc_margin(buf, 0, bytes_pending);
570  BIO_read(sc->wbio, buf->data, bytes_pending);
571  buf->len += bytes_pending;
572 
573  /* restore notify and clean up */
574  if(wbuf != NULL) {
575  buf->notify = wbuf->notify;
576  buf->notify_arg = wbuf->notify_arg;
577  _sx_buffer_free(wbuf);
578  }
579 
580  _sx_debug(ZONE, "prepared %d ssl bytes for write", buf->len);
581  }
582 
583  /* flag if we want to read */
584  if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
585  s->want_read = 1;
586 
587  return 1;
588 }
589 
590 static int _sx_ssl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
591  _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
592  int est, ret, err, pending;
593  char *errstring;
594  sx_error_t sxe;
595 
596  /* sanity */
597  if(sc->last_state == SX_SSL_STATE_ERROR)
598  return -1;
599 
600  _sx_debug(ZONE, "in _sx_ssl_rio");
601 
602  /* move the data into the ssl read buffer */
603  if(buf->len > 0) {
604  _sx_debug(ZONE, "loading %d bytes into ssl read buffer", buf->len);
605 
606  BIO_write(sc->rbio, buf->data, buf->len);
607 
608  _sx_buffer_clear(buf);
609  }
610 
611  /* handshake */
612  est = _sx_ssl_handshake(s, sc);
613  if(est < 0)
614  return -1; /* fatal error */
615 
616  /* channel is up, slurp up the read buffer */
617  if(est > 0) {
618 
619  pending = SSL_pending(sc->ssl);
620  if(pending == 0)
621  pending = BIO_pending(sc->rbio);
622 
623  /* get it all */
624  while((pending = SSL_pending(sc->ssl)) > 0 || (pending = BIO_pending(sc->rbio)) > 0) {
625  _sx_buffer_alloc_margin(buf, 0, pending);
626 
627  ret = SSL_read(sc->ssl, &(buf->data[buf->len]), pending);
628 
629  if (ret == 0)
630  {
631  /* ret will equal zero if the SSL stream was closed.
632  (See the SSL_read manpage.) */
633 
634  /* If the SSL Shutdown happened properly,
635  (i.e. we got an SSL "close notify")
636  then proccess the last packet recieved. */
637  if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)
638  {
639  _sx_close(s);
640  break;
641  }
642 
643  /* If the SSL stream was just closed and not shutdown,
644  drop the last packet recieved.
645  WARNING: This may cause clients that use SSLv2 and
646  earlier to not log out properly. */
647 
648  err = SSL_get_error(sc->ssl, ret);
649 
650  _sx_buffer_clear(buf);
651 
652 
653  if(err == SSL_ERROR_ZERO_RETURN) {
654  /* ssl channel closed, we're done */
655  _sx_close(s);
656  }
657 
658  return -1;
659  }
660  else if(ret < 0) {
661  /* ret will be negative if the SSL stream needs
662  more data, or if there was a SSL error.
663  (See the SSL_read manpage.) */
664  err = SSL_get_error(sc->ssl, ret);
665 
666  /* ssl block incomplete, need more */
667  if(err == SSL_ERROR_WANT_READ) {
668  sc->last_state = SX_SSL_STATE_WANT_READ;
669 
670  break;
671  }
672 
673  /* something's wrong */
674  _sx_buffer_clear(buf);
675 
676 
677  /* !!! need checks for renegotiation */
678 
679  sc->last_state = SX_SSL_STATE_ERROR;
680 
681  errstring = ERR_error_string(ERR_get_error(), NULL);
682  _sx_debug(ZONE, "openssl error: %s", errstring);
683 
684  /* do not throw an error if in wrapper mode and pre-stream */
685  if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
686  _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
687  _sx_event(s, event_ERROR, (void *) &sxe);
689  }
690 
691  sx_close(s);
692 
693  /* !!! drop queue */
694 
695  return -1;
696  }
697 
698  buf->len += ret;
699  }
700  }
701 
702  /* flag if stuff to write */
703  if(BIO_pending(sc->wbio) > 0 || (est > 0 && jqueue_size(sc->wq) > 0))
704  s->want_write = 1;
705 
706  /* flag if we want to read */
707  if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
708  s->want_read = 1;
709 
710  if(buf->len == 0)
711  return 0;
712 
713  return 1;
714 }
715 
716 static void _sx_ssl_client(sx_t s, sx_plugin_t p) {
717  _sx_ssl_conn_t sc;
718  SSL_CTX *ctx;
719  char *pemfile = NULL;
720  int ret, i;
721  char *pemfile_password = NULL;
722 
723  /* only bothering if they asked for wrappermode */
724  if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
725  return;
726 
727  _sx_debug(ZONE, "preparing for ssl connect for %d from %s", s->tag, s->req_from);
728 
729  /* find the ssl context for this source */
730  ctx = xhash_get((xht) p->private, s->req_from);
731  if(ctx == NULL) {
732  _sx_debug(ZONE, "using default ssl context for %d", s->tag);
733  ctx = xhash_get((xht) p->private, "*");
734  } else {
735  _sx_debug(ZONE, "using configured ssl context for %d", s->tag);
736  }
737  assert((int) (ctx != NULL));
738 
739  sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
740 
741  /* create the buffers */
742  sc->rbio = BIO_new(BIO_s_mem());
743  sc->wbio = BIO_new(BIO_s_mem());
744 
745  /* new ssl conn */
746  sc->ssl = SSL_new(ctx);
747  SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
748  SSL_set_connect_state(sc->ssl);
749  SSL_set_options(sc->ssl, SSL_OP_NO_TICKET);
750 #if OPENSSL_VERSION_NUMBER < 0x10100005L
751 #ifdef ENABLE_EXPERIMENTAL
752  SSL_set_ssl_method(sc->ssl, TLSv1_2_client_method());
753 #else
754  SSL_set_ssl_method(sc->ssl, TLSv1_client_method());
755 #endif
756 #else
757  SSL_set_ssl_method(sc->ssl, TLS_client_method());
758 #endif
759 
760  /* empty external_id */
761  for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
762  sc->external_id[i] = NULL;
763 
764  /* alternate pemfile */
765  /* !!! figure out how to error correctly here - just returning will cause
766  * us to send a normal unencrypted stream start while the server is
767  * waiting for ClientHelo. the server will flag an error, but it won't
768  * help the admin at all to figure out what happened */
769  if(s->plugin_data[p->index] != NULL) {
770  pemfile = ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile;
771  pemfile_password = ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password;
772  free(s->plugin_data[p->index]);
773  s->plugin_data[p->index] = NULL;
774  }
775  if(pemfile != NULL) {
776  /* load the certificate */
777  ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
778  if(ret != 1) {
779  _sx_debug(ZONE, "couldn't load alternate certificate from %s", pemfile);
780  SSL_free(sc->ssl);
781  free(sc);
782  free(pemfile);
783  return;
784  }
785 
786  /* set callback giving a password for pemfile */
787  SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)pemfile_password);
788  SSL_CTX_set_default_passwd_cb(ctx, &_sx_pem_passwd_callback);
789 
790  /* load the private key */
791  ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
792  if(ret != 1) {
793  _sx_debug(ZONE, "couldn't load alternate private key from %s", pemfile);
794  SSL_free(sc->ssl);
795  free(sc);
796  free(pemfile);
797  return;
798  }
799 
800  /* check the private key matches the certificate */
801  ret = SSL_check_private_key(sc->ssl);
802  if(ret != 1) {
803  _sx_debug(ZONE, "private key does not match certificate public key");
804  SSL_free(sc->ssl);
805  free(sc);
806  free(pemfile);
807  return;
808  }
809 
810  _sx_debug(ZONE, "loaded alternate pemfile %s", pemfile);
811 
812  free(pemfile);
813  }
814 
815  /* buffer queue */
816  sc->wq = jqueue_new();
817 
818  s->plugin_data[p->index] = (void *) sc;
819 
820  /* bring the plugin online */
821  _sx_chain_io_plugin(s, p);
822 }
823 
824 static void _sx_ssl_server(sx_t s, sx_plugin_t p) {
825  _sx_ssl_conn_t sc;
826  SSL_CTX *ctx;
827  int i;
828 
829  /* only bothering if they asked for wrappermode */
830  if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
831  return;
832 
833  _sx_debug(ZONE, "preparing for ssl accept for %d to %s", s->tag, s->req_to);
834 
835  /* find the ssl context for this destination */
836  ctx = xhash_get((xht) p->private, s->req_to);
837  if(ctx == NULL) {
838  _sx_debug(ZONE, "using default ssl context for %d", s->tag);
839  ctx = xhash_get((xht) p->private, "*");
840  } else {
841  _sx_debug(ZONE, "using configured ssl context for %d", s->tag);
842  }
843  assert((int) (ctx != NULL));
844 
845  sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
846 
847  /* create the buffers */
848  sc->rbio = BIO_new(BIO_s_mem());
849  sc->wbio = BIO_new(BIO_s_mem());
850 
851  /* new ssl conn */
852  sc->ssl = SSL_new(ctx);
853  SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
854  SSL_set_accept_state(sc->ssl);
855  SSL_set_options(sc->ssl, SSL_OP_NO_SSLv3);
856 
857  /* empty external_id */
858  for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
859  sc->external_id[i] = NULL;
860 
861  /* buffer queue */
862  sc->wq = jqueue_new();
863 
864  s->plugin_data[p->index] = (void *) sc;
865 
866  /* bring the plugin online */
867  _sx_chain_io_plugin(s, p);
868 }
869 
871 static void _sx_ssl_free(sx_t s, sx_plugin_t p) {
872  _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
873  sx_buf_t buf;
874  int i;
875 
876  if(sc == NULL)
877  return;
878 
879  log_debug(ZONE, "cleaning up conn state");
880 
881  if(s->type == type_NONE) {
882  free(sc);
883  return;
884  }
885 
886  for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
887  if(sc->external_id[i] != NULL)
888  free(sc->external_id[i]);
889  else
890  break;
891 
892  if(sc->pemfile != NULL) free(sc->pemfile);
893 
894  if(sc->private_key_password != NULL) free(sc->private_key_password);
895 
896  if(sc->ssl != NULL) SSL_free(sc->ssl); /* frees wbio and rbio too */
897 
898  if(sc->wq != NULL) {
899  while((buf = jqueue_pull(sc->wq)) != NULL)
900  _sx_buffer_free(buf);
901 
902  jqueue_free(sc->wq);
903  }
904 
905  free(sc);
906 
907  s->plugin_data[p->index] = NULL;
908 }
909 
910 static void _sx_ssl_unload(sx_plugin_t p) {
911  xht contexts = (xht) p->private;
912  void *ctx;
913 
914  if(xhash_iter_first(contexts))
915  do {
916  xhash_iter_get(contexts, NULL, NULL, &ctx);
917  SSL_CTX_free((SSL_CTX *) ctx);
918  } while(xhash_iter_next(contexts));
919 
920  xhash_free(contexts);
921 
923 }
924 
926 
928 int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) {
929  const char *name, *pemfile, *cachain, *password, *ciphers;
930  int ret;
931  int mode;
932 
933  _sx_debug(ZONE, "initialising ssl plugin");
934 
935  name = va_arg(args, const char *);
936  pemfile = va_arg(args, const char *);
937  if(pemfile == NULL)
938  return 1;
939 
940  if(p->private != NULL)
941  return 1;
942 
943  cachain = va_arg(args, const char *);
944  mode = va_arg(args, int);
945  password = va_arg(args, char *);
946  ciphers = va_arg(args, char *);
947 
948  /* !!! output openssl error messages to the debug log */
949 
950  /* openssl startup */
952  SSL_library_init();
953  SSL_load_error_strings();
954  }
956 
957  ret = sx_ssl_server_addcert(p, name, pemfile, cachain, mode, password, ciphers);
958  if(ret)
959  return 1;
960 
961  p->magic = SX_SSL_MAGIC;
962 
963  p->unload = _sx_ssl_unload;
964 
965  p->client = _sx_ssl_client;
966  p->server = _sx_ssl_server;
967  p->rio = _sx_ssl_rio;
968  p->wio = _sx_ssl_wio;
971  p->free = _sx_ssl_free;
972 
973  return 0;
974 }
975 
977 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) {
978  xht contexts = (xht) p->private;
979  SSL_CTX *ctx;
980  SSL_CTX *tmp;
981  STACK_OF(X509_NAME) *cert_names;
982  X509_STORE * store;
983  DH *dhparams;
984  EC_GROUP *ecparams;
985  EC_KEY *eckey = NULL;
986  int ret, nid;
987 
989  _sx_debug(ZONE, "ssl plugin not initialised");
990  return 1;
991  }
992 
993  if(name == NULL)
994  name = "*";
995 
996  if(pemfile == NULL)
997  return 1;
998 
999  /* begin with fresh error stack */
1000  ERR_clear_error();
1001 
1002  /* create the context */
1003 #if OPENSSL_VERSION_NUMBER < 0x10100005L
1004 #ifdef ENABLE_EXPERIMENTAL
1005  ctx = SSL_CTX_new(TLSv1_2_method());
1006 #else
1007  ctx = SSL_CTX_new(SSLv23_method());
1008 #endif
1009 #else
1010  ctx = SSL_CTX_new(TLS_method());
1011 #endif
1012  if(ctx == NULL) {
1013  _sx_debug(ZONE, "ssl context creation failed; %s", ERR_error_string(ERR_get_error(), NULL));
1014  return 1;
1015  }
1016 
1017  // Set allowed ciphers. if non set, at least always disable NULL and export
1018  if (!ciphers)
1019  ciphers = "!aNULL:!eNULL:!EXP:" SSL_DEFAULT_CIPHER_LIST;
1020  _sx_debug(ZONE, "Restricting TLS ciphers to %s", ciphers);
1021  if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
1022  _sx_debug(ZONE, "Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
1023  SSL_CTX_free(ctx);
1024  return 1;
1025  }
1026 
1027  /* Load the CA chain, if configured */
1028  if (cachain != NULL) {
1029  ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
1030  if(ret != 1) {
1031  _sx_debug(ZONE, "WARNING: couldn't load CA chain: %s; %s", cachain, ERR_error_string(ERR_get_error(), NULL));
1032  } else {
1033  _sx_debug(ZONE, "Loaded CA verify location chain: %s", cachain);
1034  }
1035  cert_names = SSL_load_client_CA_file(cachain);
1036  if (cert_names != NULL) {
1037  SSL_CTX_set_client_CA_list(ctx, cert_names);
1038  _sx_debug(ZONE, "Loaded client CA chain: %s", cachain);
1039  } else {
1040  _sx_debug(ZONE, "WARNING: couldn't load client CA chain: %s", cachain);
1041  }
1042  } else {
1043  /* Load the default OpenlSSL certs from /etc/ssl/certs
1044  We must assume that the client certificate's CA is there
1045 
1046  Note: We don't send client_CA_list here. Will possibly break some clients.
1047  */
1048  SSL_CTX_set_default_verify_paths(ctx);
1049  _sx_debug(ZONE, "No CA chain specified. Loading SSL default CA certs: /etc/ssl/certs");
1050  }
1051  /* Add server CRL verificaition */
1052  store = SSL_CTX_get_cert_store(ctx);
1053  // Not sure if this should be X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL
1054  // or only X509_V_FLAG_CRL_CHECK
1055  X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
1056 
1057  /* load the certificate */
1058  ret = SSL_CTX_use_certificate_chain_file(ctx, pemfile);
1059  if(ret != 1) {
1060  _sx_debug(ZONE, "couldn't load certificate from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1061  SSL_CTX_free(ctx);
1062  return 1;
1063  }
1064 
1065  /* set callback giving a password for pemfile */
1066  SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)password);
1067  SSL_CTX_set_default_passwd_cb(ctx, &_sx_pem_passwd_callback);
1068 
1069  /* load the private key */
1070  ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
1071  if(ret != 1) {
1072  _sx_debug(ZONE, "couldn't load private key from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1073  SSL_CTX_free(ctx);
1074  return 1;
1075  }
1076 
1077  /* check the private key matches the certificate */
1078  ret = SSL_CTX_check_private_key(ctx);
1079  if(ret != 1) {
1080  _sx_debug(ZONE, "private key does not match certificate public key; %s", ERR_error_string(ERR_get_error(), NULL));
1081  SSL_CTX_free(ctx);
1082  return 1;
1083  }
1084 
1085  _sx_debug(ZONE, "setting ssl context '%s' verify mode to %02x", name, mode);
1086  SSL_CTX_set_verify(ctx, mode, _sx_ssl_verify_callback);
1087 
1088  SSL_CTX_set_tmp_dh_callback(ctx, _sx_ssl_tmp_dh_callback);
1089 
1090  /* try to read DH params from pem file */
1091  if((dhparams = sx_ssl_get_DHparams(pemfile))) {
1092  SSL_CTX_set_tmp_dh(ctx, dhparams);
1093 #if OPENSSL_VERSION_NUMBER < 0x10100005L
1094  _sx_debug(ZONE, "custom DH parameters loaded from certificate", BN_num_bits(dhparams->p));
1095 #else
1096  _sx_debug(ZONE, "custom DH parameters loaded from certificate", DH_bits(dhparams));
1097 #endif
1098  }
1099 
1100  /* try to read ECDH params from pem file */
1101  if((ecparams = sx_ssl_get_ECPKParameters(pemfile)) && (nid = EC_GROUP_get_curve_name(ecparams)) && (eckey = EC_KEY_new_by_curve_name(nid))) {
1102  SSL_CTX_set_tmp_ecdh(ctx, eckey);
1103  _sx_debug(ZONE, "custom ECDH curve %s loaded from certificate", OBJ_nid2sn(nid));
1104  }
1105  else {
1106 #if defined(SSL_set_ecdh_auto)
1107  /* otherwise configure auto curve */
1108  SSL_CTX_set_ecdh_auto(ctx, 1);
1109 #else
1110  /* ..or NIST P-256 */
1111  _sx_debug(ZONE, "nist curve enabled");
1112  eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1113  SSL_CTX_set_tmp_ecdh(ctx, eckey);
1114 #endif
1115  }
1116  EC_KEY_free(eckey);
1117 
1118  /* create hash and create default context */
1119  if(contexts == NULL) {
1120  contexts = xhash_new(1021);
1121  p->private = (void *) contexts;
1122 
1123  /* this is the first context, if it's not the default then make a copy of it as the default */
1124  if(!(name[0] == '*' && name[1] == 0)) {
1125  int ret = sx_ssl_server_addcert(p, "*", pemfile, cachain, mode, password, NULL);
1126 
1127  if(ret) {
1128  /* uh-oh */
1129  xhash_free(contexts);
1130  p->private = NULL;
1131  return 1;
1132  }
1133  }
1134  }
1135 
1136  _sx_debug(ZONE, "ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile);
1137 
1138  /* remove an existing context with the same name before replacing it */
1139  tmp = xhash_get(contexts, name);
1140  if(tmp != NULL)
1141  SSL_CTX_free((SSL_CTX *) tmp);
1142 
1143  xhash_put(contexts, name, ctx);
1144 
1145  return 0;
1146 }
1147 
1148 int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password) {
1149  assert((int) (p != NULL));
1150  assert((int) (s != NULL));
1151 
1152  /* sanity */
1153  if(s->type != type_CLIENT || s->state != state_STREAM) {
1154  _sx_debug(ZONE, "wrong conn type or state for client starttls");
1155  return 1;
1156  }
1157 
1158  /* check if we're already encrypted or compressed */
1159  if(s->ssf > 0 || (s->flags & SX_COMPRESS_WRAPPER)) {
1160  _sx_debug(ZONE, "encrypted channel already established");
1161  return 1;
1162  }
1163 
1164  _sx_debug(ZONE, "initiating starttls sequence");
1165 
1166  /* save the given pemfile for later */
1167  if(pemfile != NULL) {
1168  s->plugin_data[p->index] = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
1169  ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile = strdup(pemfile);
1170 
1171  /* save the given password for later */
1172  if(private_key_password != NULL)
1173  ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password = strdup(private_key_password);
1174  }
1175 
1176  /* go */
1177  jqueue_push(s->wbufq, _sx_buffer_new("<starttls xmlns='" uri_TLS "'/>", strlen(uri_TLS) + 20, NULL, NULL), 0);
1178  s->want_write = 1;
1179  _sx_event(s, event_WANT_WRITE, NULL);
1180 
1181  return 0;
1182 }
#define SSL_OP_NO_TICKET
Definition: util_compat.h:105
#define stream_err_UNDEFINED_CONDITION
Definition: sx.h:143
struct xht_struct * xht
Definition: nad.h:93
void(* free)(sx_t s, sx_plugin_t p)
Definition: sx.h:357
Definition: sx.h:113
_sx_state_t state
Definition: sx.h:319
#define _sx_event(s, e, data)
Definition: sx.h:395
void(* server)(sx_t s, sx_plugin_t p)
Definition: sx.h:360
dhparams[]
Definition: ssl.c:104
unsigned int flags
Definition: sx.h:276
static DH * _sx_ssl_tmp_dh_callback(SSL *ssl, int export, int keylen)
Definition: ssl.c:150
void xhash_free(xht h)
Definition: xhash.c:241
const char * req_to
Definition: sx.h:282
jqueue_t wbufq
Definition: sx.h:301
static int _sx_pem_passwd_callback(char *buf, int size, int rwflag, void *password)
Definition: ssl.c:80
void(* unload)(sx_plugin_t p)
Definition: sx.h:378
Definition: sx.h:65
int jqueue_size(jqueue_t q)
Definition: jqueue.c:126
void(* features)(sx_t s, sx_plugin_t p, nad_t nad)
Definition: sx.h:373
an environment
Definition: sx.h:382
error info for event_ERROR
Definition: sx.h:99
int magic
Definition: sx.h:350
int tag
Definition: sx.h:258
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
Definition: ssl.c:977
#define uri_TLS
Definition: uri.h:40
a plugin
Definition: sx.h:347
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:778
void sx_server_init(sx_t s, unsigned int flags)
Definition: server.c:248
static int _sx_ssl_process(sx_t s, sx_plugin_t p, nad_t nad)
Definition: ssl.c:188
#define NAD_ENAME(N, E)
Definition: nad.h:183
void _sx_chain_io_plugin(sx_t s, sx_plugin_t p)
Definition: chain.c:25
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
Definition: nad.c:711
const char * ns
Definition: sx.h:279
void nad_free(nad_t nad)
free that nad
Definition: nad.c:180
int xhash_iter_next(xht h)
Definition: xhash.c:320
static void _sx_ssl_starttls_notify_proceed(sx_t s, void *arg)
Definition: ssl.c:169
#define SX_ERR_SSL
error codes
Definition: plugins.h:42
static void _sx_ssl_features(sx_t s, sx_plugin_t p, nad_t nad)
Definition: ssl.c:288
void jqueue_free(jqueue_t q)
Definition: jqueue.c:38
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
Definition: sx.c:262
static DH * sx_ssl_make_dh_params(BIGNUM *(*const get_prime)(BIGNUM *), const char *gen)
Definition: ssl.c:113
holds the state for a single stream
Definition: sx.h:253
#define SX_SSL_MAGIC
magic numbers, so plugins can find each other
Definition: plugins.h:37
char * data
Definition: sx.h:114
void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version)
Definition: client.c:111
#define NAD_ENAME_L(N, E)
Definition: nad.h:184
void jqueue_push(jqueue_t q, void *data, int priority)
Definition: jqueue.c:44
#define NAD_NURI_L(N, NS)
Definition: nad.h:192
static int _sx_ssl_wio(sx_t s, sx_plugin_t p, sx_buf_t buf)
Definition: ssl.c:485
Definition: sx.h:82
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
static void _sx_ssl_server(sx_t s, sx_plugin_t p)
Definition: ssl.c:824
#define SX_SSL_STARTTLS_OFFER
Definition: plugins.h:26
void _sx_buffer_free(sx_buf_t buf)
utility: kill a buffer
Definition: sx.c:244
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...
Definition: sx.c:220
static void sx_ssl_free_dh_params(void)
Definition: ssl.c:142
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
void sx_close(sx_t s)
Definition: io.c:512
Definition: sx.h:81
static void _sx_ssl_unload(sx_plugin_t p)
Definition: ssl.c:910
#define SX_ERR_STARTTLS_FAILURE
Definition: plugins.h:43
#define log_debug(...)
Definition: log.h:65
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...
Definition: ssl.c:33
static void _sx_ssl_client(sx_t s, sx_plugin_t p)
Definition: ssl.c:716
#define _sx_debug
Definition: sx.h:408
#define SX_SSL_STARTTLS_REQUIRE
Definition: plugins.h:27
static void _sx_ssl_get_external_id(sx_t s, _sx_ssl_conn_t sc)
Definition: ssl.c:306
void sx_error(sx_t s, int err, const char *text)
Definition: error.c:94
_sx_type_t type
Definition: sx.h:273
_sx_notify_t notify
Definition: sx.h:119
void _sx_reset(sx_t s)
utility; reset stream state
Definition: sx.c:154
const char * req_version
Definition: sx.h:284
int sx_openssl_initialized
Definition: ssl.c:925
void _sx_close(sx_t s)
close a stream
Definition: io.c:499
const char * req_from
Definition: sx.h:283
Definition: sx.h:83
int ssf
Definition: sx.h:343
void * jqueue_pull(jqueue_t q)
Definition: jqueue.c:96
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
jqueue_t jqueue_new(void)
Definition: jqueue.c:25
unsigned int len
Definition: sx.h:115
void * private
Definition: sx.h:354
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
Definition: ssl.c:928
int(* wio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
Definition: sx.h:363
void _sx_buffer_clear(sx_buf_t buf)
utility: clear out a buffer, but don&#39;t deallocate it
Definition: sx.c:252
#define DECLARE_sx_ssl_getparams(name, type)
Definition: ssl.c:87
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
#define SX_SSL_WRAPPER
sx stream flags
Definition: plugins.h:25
#define _sx_gen_error(e, c, g, s)
helper macro to populate this struct
Definition: sx.h:106
#define ZONE
Definition: mio_impl.h:76
int want_read
Definition: sx.h:306
#define NAD_NURI(N, NS)
Definition: nad.h:191
int(* process)(sx_t s, sx_plugin_t p, nad_t nad)
Definition: sx.h:376
int(* rio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
Definition: sx.h:364
xht xhash_new(int prime)
Definition: xhash.c:96
void * notify_arg
Definition: sx.h:120
static int _sx_ssl_handshake(sx_t s, _sx_ssl_conn_t sc)
Definition: ssl.c:418
int index
Definition: sx.h:352
int want_write
Definition: sx.h:306
#define SX_CONN_EXTERNAL_ID_MAX_COUNT
Definition: plugins.h:49
void ** plugin_data
Definition: sx.h:330
int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password)
Definition: ssl.c:1148
void(* client)(sx_t s, sx_plugin_t p)
Definition: sx.h:359
static void _sx_ssl_free(sx_t s, sx_plugin_t p)
cleanup
Definition: ssl.c:871
static int _sx_ssl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf)
Definition: ssl.c:590
#define NAD_ENS(N, E)
Definition: nad.h:196
#define SX_COMPRESS_WRAPPER
Definition: plugins.h:31