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