jabberd2  2.3.6
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  OPENSSL_free(buff);
388  /* Check if we're not out of space */
390  goto end;
391  }
392 
393 end:
394  X509_free(cert);
395  return;
396 }
397 
398 static int _sx_ssl_handshake(sx_t s, _sx_ssl_conn_t sc) {
399  int ret, err;
400  char *errstring;
401  sx_error_t sxe;
402 
403  /* work on establishing the channel */
404  while(!SSL_is_init_finished(sc->ssl)) {
405  _sx_debug(ZONE, "secure channel not established, handshake in progress");
406 
407  /* we can't handshake if they want to read, but there's nothing to read */
408  if(sc->last_state == SX_SSL_STATE_WANT_READ && BIO_pending(sc->rbio) == 0)
409  return 0;
410 
411  /* more handshake */
412  if(s->type == type_CLIENT)
413  ret = SSL_connect(sc->ssl);
414  else
415  ret = SSL_accept(sc->ssl);
416 
417  /* check if we're done */
418  if(ret == 1) {
419  _sx_debug(ZONE, "secure channel established");
420  sc->last_state = SX_SSL_STATE_NONE;
421 
422  s->ssf = SSL_get_cipher_bits(sc->ssl, NULL);
423 
424  _sx_debug(ZONE, "using cipher %s (%d bits)", SSL_get_cipher_name(sc->ssl), s->ssf);
426 
427  return 1;
428  }
429 
430  /* error checking */
431  else if(ret <= 0) {
432  err = SSL_get_error(sc->ssl, ret);
433 
434  if(err == SSL_ERROR_WANT_READ)
435  sc->last_state = SX_SSL_STATE_WANT_READ;
436  else if(err == SSL_ERROR_WANT_WRITE)
437  sc->last_state = SX_SSL_STATE_WANT_WRITE;
438 
439  else {
440  /* fatal error */
441  sc->last_state = SX_SSL_STATE_ERROR;
442 
443  errstring = ERR_error_string(ERR_get_error(), NULL);
444  _sx_debug(ZONE, "openssl error: %s", errstring);
445 
446  /* do not throw an error if in wrapper mode and pre-stream */
447  if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
448  _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
449  _sx_event(s, event_ERROR, (void *) &sxe);
451  }
452 
453  sx_close(s);
454 
455  /* !!! drop queue */
456 
457  return -1;
458  }
459  }
460  }
461 
462  return 1;
463 }
464 
465 static int _sx_ssl_wio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
466  _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
467  int est, ret, err;
468  sx_buf_t wbuf;
469  char *errstring;
470  sx_error_t sxe;
471 
472  /* do not encrypt when error */
473  if(sc->last_state == SX_SSL_STATE_ERROR)
474  return 1;
475 
476  _sx_debug(ZONE, "in _sx_ssl_wio");
477 
478  /* queue the buffer */
479  if(buf->len > 0) {
480  _sx_debug(ZONE, "queueing buffer for write");
481 
482  jqueue_push(sc->wq, _sx_buffer_new(buf->data, buf->len, buf->notify, buf->notify_arg), 0);
483  _sx_buffer_clear(buf);
484  buf->notify = NULL;
485  buf->notify_arg = NULL;
486  }
487 
488  /* handshake */
489  est = _sx_ssl_handshake(s, sc);
490  if(est < 0)
491  return -2; /* fatal error */
492 
493  /* channel established, do some real writing */
494  wbuf = NULL;
495  if(est > 0 && jqueue_size(sc->wq) > 0) {
496  _sx_debug(ZONE, "preparing queued buffer for write");
497 
498  wbuf = jqueue_pull(sc->wq);
499 
500  ret = SSL_write(sc->ssl, wbuf->data, wbuf->len);
501  if(ret <= 0) {
502  /* something's wrong */
503  _sx_debug(ZONE, "write failed, requeuing buffer");
504 
505  /* requeue the buffer */
506  jqueue_push(sc->wq, wbuf, (sc->wq->front != NULL) ? sc->wq->front->priority + 1 : 0);
507 
508  /* error checking */
509  err = SSL_get_error(sc->ssl, ret);
510 
511  if(err == SSL_ERROR_ZERO_RETURN) {
512  /* ssl channel closed, we're done */
513  _sx_close(s);
514  }
515 
516  if(err == SSL_ERROR_WANT_READ) {
517  /* we'll be renegotiating next time */
518  _sx_debug(ZONE, "renegotiation started");
519  sc->last_state = SX_SSL_STATE_WANT_READ;
520  }
521 
522  else {
523  sc->last_state = SX_SSL_STATE_ERROR;
524 
525  /* something very bad */
526  errstring = ERR_error_string(ERR_get_error(), NULL);
527  _sx_debug(ZONE, "openssl error: %s", errstring);
528 
529  /* do not throw an error if in wrapper mode and pre-stream */
530  if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
531  _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
532  _sx_event(s, event_ERROR, (void *) &sxe);
534  }
535 
536  sx_close(s);
537 
538  /* !!! drop queue */
539 
540  return -2; /* fatal */
541  }
542  }
543  }
544 
545  /* prepare the buffer with stuff to write */
546  if(BIO_pending(sc->wbio) > 0) {
547  int bytes_pending = BIO_pending(sc->wbio);
548  assert(buf->len == 0);
549  _sx_buffer_alloc_margin(buf, 0, bytes_pending);
550  BIO_read(sc->wbio, buf->data, bytes_pending);
551  buf->len += bytes_pending;
552 
553  /* restore notify and clean up */
554  if(wbuf != NULL) {
555  buf->notify = wbuf->notify;
556  buf->notify_arg = wbuf->notify_arg;
557  _sx_buffer_free(wbuf);
558  }
559 
560  _sx_debug(ZONE, "prepared %d ssl bytes for write", buf->len);
561  }
562 
563  /* flag if we want to read */
564  if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
565  s->want_read = 1;
566 
567  return 1;
568 }
569 
570 static int _sx_ssl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
571  _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
572  int est, ret, err, pending;
573  char *errstring;
574  sx_error_t sxe;
575 
576  /* sanity */
577  if(sc->last_state == SX_SSL_STATE_ERROR)
578  return -1;
579 
580  _sx_debug(ZONE, "in _sx_ssl_rio");
581 
582  /* move the data into the ssl read buffer */
583  if(buf->len > 0) {
584  _sx_debug(ZONE, "loading %d bytes into ssl read buffer", buf->len);
585 
586  BIO_write(sc->rbio, buf->data, buf->len);
587 
588  _sx_buffer_clear(buf);
589  }
590 
591  /* handshake */
592  est = _sx_ssl_handshake(s, sc);
593  if(est < 0)
594  return -1; /* fatal error */
595 
596  /* channel is up, slurp up the read buffer */
597  if(est > 0) {
598 
599  pending = SSL_pending(sc->ssl);
600  if(pending == 0)
601  pending = BIO_pending(sc->rbio);
602 
603  /* get it all */
604  while((pending = SSL_pending(sc->ssl)) > 0 || (pending = BIO_pending(sc->rbio)) > 0) {
605  _sx_buffer_alloc_margin(buf, 0, pending);
606 
607  ret = SSL_read(sc->ssl, &(buf->data[buf->len]), pending);
608 
609  if (ret == 0)
610  {
611  /* ret will equal zero if the SSL stream was closed.
612  (See the SSL_read manpage.) */
613 
614  /* If the SSL Shutdown happened properly,
615  (i.e. we got an SSL "close notify")
616  then proccess the last packet recieved. */
617  if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)
618  {
619  _sx_close(s);
620  break;
621  }
622 
623  /* If the SSL stream was just closed and not shutdown,
624  drop the last packet recieved.
625  WARNING: This may cause clients that use SSLv2 and
626  earlier to not log out properly. */
627 
628  err = SSL_get_error(sc->ssl, ret);
629 
630  _sx_buffer_clear(buf);
631 
632 
633  if(err == SSL_ERROR_ZERO_RETURN) {
634  /* ssl channel closed, we're done */
635  _sx_close(s);
636  }
637 
638  return -1;
639  }
640  else if(ret < 0) {
641  /* ret will be negative if the SSL stream needs
642  more data, or if there was a SSL error.
643  (See the SSL_read manpage.) */
644  err = SSL_get_error(sc->ssl, ret);
645 
646  /* ssl block incomplete, need more */
647  if(err == SSL_ERROR_WANT_READ) {
648  sc->last_state = SX_SSL_STATE_WANT_READ;
649 
650  break;
651  }
652 
653  /* something's wrong */
654  _sx_buffer_clear(buf);
655 
656 
657  /* !!! need checks for renegotiation */
658 
659  sc->last_state = SX_SSL_STATE_ERROR;
660 
661  errstring = ERR_error_string(ERR_get_error(), NULL);
662  _sx_debug(ZONE, "openssl error: %s", errstring);
663 
664  /* do not throw an error if in wrapper mode and pre-stream */
665  if(!(s->state < state_STREAM && s->flags & SX_SSL_WRAPPER)) {
666  _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);
667  _sx_event(s, event_ERROR, (void *) &sxe);
669  }
670 
671  sx_close(s);
672 
673  /* !!! drop queue */
674 
675  return -1;
676  }
677 
678  buf->len += ret;
679  }
680  }
681 
682  /* flag if stuff to write */
683  if(BIO_pending(sc->wbio) > 0 || (est > 0 && jqueue_size(sc->wq) > 0))
684  s->want_write = 1;
685 
686  /* flag if we want to read */
687  if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)
688  s->want_read = 1;
689 
690  if(buf->len == 0)
691  return 0;
692 
693  return 1;
694 }
695 
696 static void _sx_ssl_client(sx_t s, sx_plugin_t p) {
697  _sx_ssl_conn_t sc;
698  SSL_CTX *ctx;
699  char *pemfile = NULL;
700  int ret, i;
701  char *pemfile_password = NULL;
702 
703  /* only bothering if they asked for wrappermode */
704  if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
705  return;
706 
707  _sx_debug(ZONE, "preparing for ssl connect for %d from %s", s->tag, s->req_from);
708 
709  /* find the ssl context for this source */
710  ctx = xhash_get((xht) p->private, s->req_from);
711  if(ctx == NULL) {
712  _sx_debug(ZONE, "using default ssl context for %d", s->tag);
713  ctx = xhash_get((xht) p->private, "*");
714  } else {
715  _sx_debug(ZONE, "using configured ssl context for %d", s->tag);
716  }
717  assert((int) (ctx != NULL));
718 
719  sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
720 
721  /* create the buffers */
722  sc->rbio = BIO_new(BIO_s_mem());
723  sc->wbio = BIO_new(BIO_s_mem());
724 
725  /* new ssl conn */
726  sc->ssl = SSL_new(ctx);
727  SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
728  SSL_set_connect_state(sc->ssl);
729  SSL_set_options(sc->ssl, SSL_OP_NO_TICKET);
730 #ifdef ENABLE_EXPERIMENTAL
731  SSL_set_ssl_method(sc->ssl, TLSv1_2_client_method());
732 #else
733  SSL_set_ssl_method(sc->ssl, TLSv1_client_method());
734 #endif
735 
736  /* empty external_id */
737  for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
738  sc->external_id[i] = NULL;
739 
740  /* alternate pemfile */
741  /* !!! figure out how to error correctly here - just returning will cause
742  * us to send a normal unencrypted stream start while the server is
743  * waiting for ClientHelo. the server will flag an error, but it won't
744  * help the admin at all to figure out what happened */
745  if(s->plugin_data[p->index] != NULL) {
746  pemfile = ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile;
747  pemfile_password = ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password;
748  free(s->plugin_data[p->index]);
749  s->plugin_data[p->index] = NULL;
750  }
751  if(pemfile != NULL) {
752  /* load the certificate */
753  ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
754  if(ret != 1) {
755  _sx_debug(ZONE, "couldn't load alternate certificate from %s", pemfile);
756  SSL_free(sc->ssl);
757  free(sc);
758  free(pemfile);
759  return;
760  }
761 
762  /* set callback giving a password for pemfile */
763  SSL_CTX_set_default_passwd_cb_userdata(sc->ssl->ctx, (void *)pemfile_password);
764  SSL_CTX_set_default_passwd_cb(sc->ssl->ctx, &_sx_pem_passwd_callback);
765 
766  /* load the private key */
767  ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);
768  if(ret != 1) {
769  _sx_debug(ZONE, "couldn't load alternate private key from %s", pemfile);
770  SSL_free(sc->ssl);
771  free(sc);
772  free(pemfile);
773  return;
774  }
775 
776  /* check the private key matches the certificate */
777  ret = SSL_check_private_key(sc->ssl);
778  if(ret != 1) {
779  _sx_debug(ZONE, "private key does not match certificate public key");
780  SSL_free(sc->ssl);
781  free(sc);
782  free(pemfile);
783  return;
784  }
785 
786  _sx_debug(ZONE, "loaded alternate pemfile %s", pemfile);
787 
788  free(pemfile);
789  }
790 
791  /* buffer queue */
792  sc->wq = jqueue_new();
793 
794  s->plugin_data[p->index] = (void *) sc;
795 
796  /* bring the plugin online */
797  _sx_chain_io_plugin(s, p);
798 }
799 
800 static void _sx_ssl_server(sx_t s, sx_plugin_t p) {
801  _sx_ssl_conn_t sc;
802  SSL_CTX *ctx;
803  int i;
804 
805  /* only bothering if they asked for wrappermode */
806  if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)
807  return;
808 
809  _sx_debug(ZONE, "preparing for ssl accept for %d to %s", s->tag, s->req_to);
810 
811  /* find the ssl context for this destination */
812  ctx = xhash_get((xht) p->private, s->req_to);
813  if(ctx == NULL) {
814  _sx_debug(ZONE, "using default ssl context for %d", s->tag);
815  ctx = xhash_get((xht) p->private, "*");
816  } else {
817  _sx_debug(ZONE, "using configured ssl context for %d", s->tag);
818  }
819  assert((int) (ctx != NULL));
820 
821  sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
822 
823  /* create the buffers */
824  sc->rbio = BIO_new(BIO_s_mem());
825  sc->wbio = BIO_new(BIO_s_mem());
826 
827  /* new ssl conn */
828  sc->ssl = SSL_new(ctx);
829  SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);
830  SSL_set_accept_state(sc->ssl);
831  SSL_set_options(sc->ssl, SSL_OP_NO_SSLv3);
832 
833  /* empty external_id */
834  for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
835  sc->external_id[i] = NULL;
836 
837  /* buffer queue */
838  sc->wq = jqueue_new();
839 
840  s->plugin_data[p->index] = (void *) sc;
841 
842  /* bring the plugin online */
843  _sx_chain_io_plugin(s, p);
844 }
845 
847 static void _sx_ssl_free(sx_t s, sx_plugin_t p) {
848  _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];
849  sx_buf_t buf;
850  int i;
851 
852  if(sc == NULL)
853  return;
854 
855  log_debug(ZONE, "cleaning up conn state");
856 
857  if(s->type == type_NONE) {
858  free(sc);
859  return;
860  }
861 
862  for (i = 0; i < SX_CONN_EXTERNAL_ID_MAX_COUNT; i++)
863  if(sc->external_id[i] != NULL)
864  free(sc->external_id[i]);
865  else
866  break;
867 
868  if(sc->pemfile != NULL) free(sc->pemfile);
869 
870  if(sc->private_key_password != NULL) free(sc->private_key_password);
871 
872  if(sc->ssl != NULL) SSL_free(sc->ssl); /* frees wbio and rbio too */
873 
874  if(sc->wq != NULL) {
875  while((buf = jqueue_pull(sc->wq)) != NULL)
876  _sx_buffer_free(buf);
877 
878  jqueue_free(sc->wq);
879  }
880 
881  free(sc);
882 
883  s->plugin_data[p->index] = NULL;
884 }
885 
886 static void _sx_ssl_unload(sx_plugin_t p) {
887  xht contexts = (xht) p->private;
888  void *ctx;
889 
890  if(xhash_iter_first(contexts))
891  do {
892  xhash_iter_get(contexts, NULL, NULL, &ctx);
893  SSL_CTX_free((SSL_CTX *) ctx);
894  } while(xhash_iter_next(contexts));
895 
896  xhash_free(contexts);
897 
899 }
900 
902 
904 int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) {
905  const char *name, *pemfile, *cachain, *password, *ciphers;
906  int ret;
907  int mode;
908 
909  _sx_debug(ZONE, "initialising ssl plugin");
910 
911  name = va_arg(args, const char *);
912  pemfile = va_arg(args, const char *);
913  if(pemfile == NULL)
914  return 1;
915 
916  if(p->private != NULL)
917  return 1;
918 
919  cachain = va_arg(args, const char *);
920  mode = va_arg(args, int);
921  password = va_arg(args, char *);
922  ciphers = va_arg(args, char *);
923 
924  /* !!! output openssl error messages to the debug log */
925 
926  /* openssl startup */
927  if(!sx_openssl_initialized) {
928  SSL_library_init();
929  SSL_load_error_strings();
930  }
931  sx_openssl_initialized = 1;
932 
933  ret = sx_ssl_server_addcert(p, name, pemfile, cachain, mode, password, ciphers);
934  if(ret)
935  return 1;
936 
937  p->magic = SX_SSL_MAGIC;
938 
939  p->unload = _sx_ssl_unload;
940 
941  p->client = _sx_ssl_client;
942  p->server = _sx_ssl_server;
943  p->rio = _sx_ssl_rio;
944  p->wio = _sx_ssl_wio;
947  p->free = _sx_ssl_free;
948 
949  return 0;
950 }
951 
953 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) {
954  xht contexts = (xht) p->private;
955  SSL_CTX *ctx;
956  SSL_CTX *tmp;
957  STACK_OF(X509_NAME) *cert_names;
958  X509_STORE * store;
959  DH *dhparams;
960  EC_GROUP *ecparams;
961  EC_KEY *eckey = NULL;
962  int ret, nid;
963 
964  if(!sx_openssl_initialized) {
965  _sx_debug(ZONE, "ssl plugin not initialised");
966  return 1;
967  }
968 
969  if(name == NULL)
970  name = "*";
971 
972  if(pemfile == NULL)
973  return 1;
974 
975  /* begin with fresh error stack */
976  ERR_clear_error();
977 
978  /* create the context */
979 #ifdef ENABLE_EXPERIMENTAL
980  ctx = SSL_CTX_new(TLSv1_2_method());
981 #else
982  ctx = SSL_CTX_new(SSLv23_method());
983 #endif
984  if(ctx == NULL) {
985  _sx_debug(ZONE, "ssl context creation failed; %s", ERR_error_string(ERR_get_error(), NULL));
986  return 1;
987  }
988 
989  // Set allowed ciphers. if non set, at least always disable NULL and export
990  if (!ciphers)
991  ciphers = "!aNULL:!eNULL:!EXP:" SSL_DEFAULT_CIPHER_LIST;
992  _sx_debug(ZONE, "Restricting TLS ciphers to %s", ciphers);
993  if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
994  _sx_debug(ZONE, "Can't set cipher list for SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
995  SSL_CTX_free(ctx);
996  return 1;
997  }
998 
999  /* Load the CA chain, if configured */
1000  if (cachain != NULL) {
1001  ret = SSL_CTX_load_verify_locations (ctx, cachain, NULL);
1002  if(ret != 1) {
1003  _sx_debug(ZONE, "WARNING: couldn't load CA chain: %s; %s", cachain, ERR_error_string(ERR_get_error(), NULL));
1004  } else {
1005  _sx_debug(ZONE, "Loaded CA verify location chain: %s", cachain);
1006  }
1007  cert_names = SSL_load_client_CA_file(cachain);
1008  if (cert_names != NULL) {
1009  SSL_CTX_set_client_CA_list(ctx, cert_names);
1010  _sx_debug(ZONE, "Loaded client CA chain: %s", cachain);
1011  } else {
1012  _sx_debug(ZONE, "WARNING: couldn't load client CA chain: %s", cachain);
1013  }
1014  } else {
1015  /* Load the default OpenlSSL certs from /etc/ssl/certs
1016  We must assume that the client certificate's CA is there
1017 
1018  Note: We don't send client_CA_list here. Will possibly break some clients.
1019  */
1020  SSL_CTX_set_default_verify_paths(ctx);
1021  _sx_debug(ZONE, "No CA chain specified. Loading SSL default CA certs: /etc/ssl/certs");
1022  }
1023  /* Add server CRL verificaition */
1024  store = SSL_CTX_get_cert_store(ctx);
1025  // Not sure if this should be X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL
1026  // or only X509_V_FLAG_CRL_CHECK
1027  X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
1028 
1029  /* load the certificate */
1030  ret = SSL_CTX_use_certificate_chain_file(ctx, pemfile);
1031  if(ret != 1) {
1032  _sx_debug(ZONE, "couldn't load certificate from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1033  SSL_CTX_free(ctx);
1034  return 1;
1035  }
1036 
1037  /* set callback giving a password for pemfile */
1038  SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)password);
1039  SSL_CTX_set_default_passwd_cb(ctx, &_sx_pem_passwd_callback);
1040 
1041  /* load the private key */
1042  ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);
1043  if(ret != 1) {
1044  _sx_debug(ZONE, "couldn't load private key from %s; %s", pemfile, ERR_error_string(ERR_get_error(), NULL));
1045  SSL_CTX_free(ctx);
1046  return 1;
1047  }
1048 
1049  /* check the private key matches the certificate */
1050  ret = SSL_CTX_check_private_key(ctx);
1051  if(ret != 1) {
1052  _sx_debug(ZONE, "private key does not match certificate public key; %s", ERR_error_string(ERR_get_error(), NULL));
1053  SSL_CTX_free(ctx);
1054  return 1;
1055  }
1056 
1057  _sx_debug(ZONE, "setting ssl context '%s' verify mode to %02x", name, mode);
1058  SSL_CTX_set_verify(ctx, mode, _sx_ssl_verify_callback);
1059 
1060  SSL_CTX_set_tmp_dh_callback(ctx, _sx_ssl_tmp_dh_callback);
1061 
1062  /* try to read DH params from pem file */
1063  if((dhparams = sx_ssl_get_DHparams(pemfile))) {
1064  SSL_CTX_set_tmp_dh(ctx, dhparams);
1065  _sx_debug(ZONE, "custom DH parameters loaded from certificate", BN_num_bits(dhparams->p));
1066  }
1067 
1068  /* try to read ECDH params from pem file */
1069  if((ecparams = sx_ssl_get_ECPKParameters(pemfile)) && (nid = EC_GROUP_get_curve_name(ecparams)) && (eckey = EC_KEY_new_by_curve_name(nid))) {
1070  SSL_CTX_set_tmp_ecdh(ctx, eckey);
1071  _sx_debug(ZONE, "custom ECDH curve %s loaded from certificate", OBJ_nid2sn(nid));
1072  }
1073  else {
1074 #if defined(SSL_set_ecdh_auto)
1075  /* otherwise configure auto curve */
1076  SSL_CTX_set_ecdh_auto(ctx, 1);
1077 #else
1078  /* ..or NIST P-256 */
1079  _sx_debug(ZONE, "nist curve enabled");
1080  eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1081  SSL_CTX_set_tmp_ecdh(ctx, eckey);
1082 #endif
1083  }
1084  EC_KEY_free(eckey);
1085 
1086  /* create hash and create default context */
1087  if(contexts == NULL) {
1088  contexts = xhash_new(1021);
1089  p->private = (void *) contexts;
1090 
1091  /* this is the first context, if it's not the default then make a copy of it as the default */
1092  if(!(name[0] == '*' && name[1] == 0)) {
1093  int ret = sx_ssl_server_addcert(p, "*", pemfile, cachain, mode, password, NULL);
1094 
1095  if(ret) {
1096  /* uh-oh */
1097  xhash_free(contexts);
1098  p->private = NULL;
1099  return 1;
1100  }
1101  }
1102  }
1103 
1104  _sx_debug(ZONE, "ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile);
1105 
1106  /* remove an existing context with the same name before replacing it */
1107  tmp = xhash_get(contexts, name);
1108  if(tmp != NULL)
1109  SSL_CTX_free((SSL_CTX *) tmp);
1110 
1111  xhash_put(contexts, name, ctx);
1112 
1113  return 0;
1114 }
1115 
1116 int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password) {
1117  assert((int) (p != NULL));
1118  assert((int) (s != NULL));
1119 
1120  /* sanity */
1121  if(s->type != type_CLIENT || s->state != state_STREAM) {
1122  _sx_debug(ZONE, "wrong conn type or state for client starttls");
1123  return 1;
1124  }
1125 
1126  /* check if we're already encrypted or compressed */
1127  if(s->ssf > 0 || (s->flags & SX_COMPRESS_WRAPPER)) {
1128  _sx_debug(ZONE, "encrypted channel already established");
1129  return 1;
1130  }
1131 
1132  _sx_debug(ZONE, "initiating starttls sequence");
1133 
1134  /* save the given pemfile for later */
1135  if(pemfile != NULL) {
1136  s->plugin_data[p->index] = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st));
1137  ((_sx_ssl_conn_t)s->plugin_data[p->index])->pemfile = strdup(pemfile);
1138 
1139  /* save the given password for later */
1140  if(private_key_password != NULL)
1141  ((_sx_ssl_conn_t)s->plugin_data[p->index])->private_key_password = strdup(private_key_password);
1142  }
1143 
1144  /* go */
1145  jqueue_push(s->wbufq, _sx_buffer_new("<starttls xmlns='" uri_TLS "'/>", strlen(uri_TLS) + 20, NULL, NULL), 0);
1146  s->want_write = 1;
1147  _sx_event(s, event_WANT_WRITE, NULL);
1148 
1149  return 0;
1150 }
#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:354
Definition: sx.h:113
_sx_state_t state
Definition: sx.h:316
#define _sx_event(s, e, data)
Definition: sx.h:392
void(* server)(sx_t s, sx_plugin_t p)
Definition: sx.h:357
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:375
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:370
an environment
Definition: sx.h:379
error info for event_ERROR
Definition: sx.h:99
int magic
Definition: sx.h:347
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:953
#define uri_TLS
Definition: uri.h:40
a plugin
Definition: sx.h:344
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:762
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:695
const char * ns
Definition: sx.h:279
void nad_free(nad_t nad)
free that nad
Definition: nad.c:178
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:465
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:800
#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:498
Definition: sx.h:81
static void _sx_ssl_unload(sx_plugin_t p)
Definition: ssl.c:886
#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:696
#define _sx_debug
Definition: sx.h:405
#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:901
void _sx_close(sx_t s)
close a stream
Definition: io.c:485
const char * req_from
Definition: sx.h:283
Definition: sx.h:83
int ssf
Definition: sx.h:340
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:351
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
Definition: ssl.c:904
#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:360
void _sx_buffer_clear(sx_buf_t buf)
utility: clear out a buffer, but don'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:373
int(* rio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
Definition: sx.h:361
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:398
int index
Definition: sx.h:349
int want_write
Definition: sx.h:306
#define SX_CONN_EXTERNAL_ID_MAX_COUNT
Definition: plugins.h:49
void ** plugin_data
Definition: sx.h:327
int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password)
Definition: ssl.c:1116
void(* client)(sx_t s, sx_plugin_t p)
Definition: sx.h:356
static void _sx_ssl_free(sx_t s, sx_plugin_t p)
cleanup
Definition: ssl.c:847
static int _sx_ssl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf)
Definition: ssl.c:570
#define NAD_ENS(N, E)
Definition: nad.h:196
#define SX_COMPRESS_WRAPPER
Definition: plugins.h:31