chiark / gitweb /
Merge branch 'master' of login.chiark.greenend.org.uk:public-git/inn-innduct
[inn-innduct.git] / nnrpd / tls.c
1 /* tls.c --- TLSv1 functions
2    Copyright (C) 2000 Kenichi Okada <okada@opaopa.org>
3
4    Author: Kenichi Okada <okada@opaopa.org>
5    Created: 2000-02-22
6
7    Keywords: TLS, OpenSSL
8
9    Commentary:
10
11    [RFC 2246] "The TLS Protocol Version 1.0"
12         by Christopher Allen <callen@certicom.com> and
13         Tim Dierks <tdierks@certicom.com> (1999/01)
14
15    [RFC 2595] "Using TLS with IMAP, POP3 and ACAP"
16         by Chris Newman <chris.newman@innosoft.com> (1999/06)
17
18 */
19
20 #include <sys/types.h>
21 #include "config.h"
22 #include "nnrpd.h"
23
24 #ifdef HAVE_SSL
25
26 /* System library. */
27
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <sys/stat.h>
33 #include <sys/uio.h>
34
35 #endif
36
37 /* outside the ifdef so `make depend` works even ifndef HAVE_SSL */
38 #include "tls.h"
39 #include "sasl_config.h"
40
41 #ifdef HAVE_SSL
42
43 /* We must keep some of the info available */
44 static const char hexcodes[] = "0123456789ABCDEF";
45
46 static bool tls_initialized = false;
47
48 static int verify_depth;
49 static int verify_error = X509_V_OK;
50 static int do_dump = 0;
51 static SSL_CTX *CTX = NULL;
52 SSL *tls_conn = NULL;
53
54 #define CCERT_BUFSIZ 256
55
56 int     tls_serverengine = 0;
57 int     tls_serveractive = 0;   /* available or not */
58 char   *tls_peer_subject = NULL;
59 char   *tls_peer_issuer = NULL;
60 char   *tls_peer_fingerprint = NULL;
61
62 int     tls_clientactive = 0;   /* available or not */
63 char   *tls_peer_CN = NULL;
64 char   *tls_issuer_CN = NULL;
65
66 const char   *tls_protocol = NULL;
67 const char   *tls_cipher_name = NULL;
68 int     tls_cipher_usebits = 0;
69 int     tls_cipher_algbits = 0;
70
71
72 int tls_loglevel = 0;
73
74
75 /* taken from OpenSSL apps/s_cb.c 
76  * tim - this seems to just be giving logging messages
77  */
78
79 static void apps_ssl_info_callback(SSL * s, int where, int ret)
80 {
81     const char  *str;
82     int         w;
83
84     if (tls_loglevel==0) return;
85
86     w = where & ~SSL_ST_MASK;
87
88     if (w & SSL_ST_CONNECT)
89         str = "SSL_connect";
90     else if (w & SSL_ST_ACCEPT)
91         str = "SSL_accept";
92     else
93         str = "undefined";
94
95     if (where & SSL_CB_LOOP) {
96         if (tls_serverengine && (tls_loglevel >= 2))
97             Printf("%s:%s", str, SSL_state_string_long(s));
98     } else if (where & SSL_CB_ALERT) {
99         str = (where & SSL_CB_READ) ? "read" : "write";
100         if ((tls_serverengine && (tls_loglevel >= 2)) ||
101             ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY))
102           Printf("SSL3 alert %s:%s:%s", str,
103                  SSL_alert_type_string_long(ret),
104                  SSL_alert_desc_string_long(ret));
105     } else if (where & SSL_CB_EXIT) {
106         if (ret == 0)
107             Printf("%s:failed in %s",
108                      str, SSL_state_string_long(s));
109         else if (ret < 0) {
110             Printf("%s:error in %s",
111                      str, SSL_state_string_long(s));
112         }
113     }
114 }
115
116
117 /*
118  *      Hardcoded DH parameter files, from OpenSSL.
119  *      For information on how these files were generated, see
120  *      "Assigned Number for SKIP Protocols" 
121  *      (http://www.skip-vpn.org/spec/numbers.html.
122  */
123 static const char file_dh512[] =
124 "-----BEGIN DH PARAMETERS-----\n\
125 MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
126 XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
127 -----END DH PARAMETERS-----\n";
128
129 static const char file_dh1024[] =
130 "-----BEGIN DH PARAMETERS-----\n\
131 MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
132 jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
133 ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
134 -----END DH PARAMETERS-----\n";
135
136 static const char file_dh2048[] =
137 "-----BEGIN DH PARAMETERS-----\n\
138 MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
139 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
140 T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
141 zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
142 Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
143 CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
144 -----END DH PARAMETERS-----\n";
145
146 static const char file_dh4096[] =
147 "-----BEGIN DH PARAMETERS-----\n\
148 MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
149 l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
150 Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
151 Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
152 VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
153 alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
154 sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
155 ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
156 OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
157 AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
158 KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
159 -----END DH PARAMETERS-----\n";
160
161 /*
162  *      Load hardcoded DH parameters.
163  */
164 static DH *
165 load_dh_buffer (const char *buffer, size_t len)
166 {
167         BIO *bio;
168         DH *dh = NULL;
169
170         bio = BIO_new_mem_buf((char *) buffer, len);
171         if (bio == NULL)
172                 return NULL;
173         dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
174 /*      if (dh == NULL) log error */
175         BIO_free(bio);
176
177         return dh;
178 }
179
180 /*
181  *      Generate empheral DH key.  Because this can take a long
182  *      time to compute, we use precomputed parameters of the
183  *      common key sizes.
184  *
185  *      These values can be static (once loaded or computed) since
186  *      the OpenSSL library can effectively generate random keys
187  *      from the information provided.
188  *
189  *      EDH keying is slightly less efficient than static RSA keying,
190  *      but it offers Perfect Forward Secrecy (PFS).
191  *
192  *      FIXME: support user-specified files, to eliminate risk of
193  *      "small group" attacks.
194  */
195 static DH *tmp_dh_cb(SSL *s UNUSED, int export UNUSED, int keylength)
196 {
197         DH *r = NULL;
198         static DH *dh = NULL;
199         static DH *dh512 = NULL;
200         static DH *dh1024 = NULL;
201         static DH *dh2048 = NULL;
202         static DH *dh4096 = NULL;
203
204         switch (keylength)
205         {
206         case 512:
207                 if (dh512 == NULL)
208                         dh512 = load_dh_buffer(file_dh512, sizeof file_dh512);
209                 r = dh512;
210                 break;
211         case 1024:
212                 if (dh1024 == NULL)
213                         dh1024 = load_dh_buffer(file_dh1024, sizeof file_dh1024);
214                 r = dh1024;
215                 break;
216         case 2048:
217                 if (dh2048 == NULL)
218                         dh2048 = load_dh_buffer(file_dh2048, sizeof file_dh2048);
219                 r = dh2048;
220                 break;
221         case 4096:
222                 if (dh4096 == NULL)
223                         dh4096 = load_dh_buffer(file_dh4096, sizeof file_dh4096);
224                 r = dh4096;
225                 break;
226         default:
227                 /* we should check current keylength vs. requested keylength */
228                 /* also, this is an extremely expensive operation! */
229                 dh = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
230                 r = dh;
231         }
232
233         return r;
234 }
235
236 /* taken from OpenSSL apps/s_cb.c */
237
238 static int verify_callback(int ok, X509_STORE_CTX * ctx)
239 {
240     char    buf[256];
241     X509   *err_cert;
242     int     err;
243     int     depth;
244
245     syslog(L_NOTICE,"Doing a peer verify");
246
247     err_cert = X509_STORE_CTX_get_current_cert(ctx);
248     err = X509_STORE_CTX_get_error(ctx);
249     depth = X509_STORE_CTX_get_error_depth(ctx);
250
251     X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
252     if ((tls_serveractive) && (tls_loglevel >= 1))
253       Printf("Peer cert verify depth=%d %s", depth, buf);
254     if (ok==0)
255     {
256       syslog(L_NOTICE, "verify error:num=%d:%s", err,
257              X509_verify_cert_error_string(err));
258       
259         if (verify_depth >= depth) {
260             ok = 1;
261             verify_error = X509_V_OK;
262         } else {
263             ok = 0;
264             verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
265         }
266     }
267     switch (ctx->error) {
268     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
269         X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
270         syslog(L_NOTICE, "issuer= %s", buf);
271         break;
272     case X509_V_ERR_CERT_NOT_YET_VALID:
273     case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
274         syslog(L_NOTICE, "cert not yet valid");
275         break;
276     case X509_V_ERR_CERT_HAS_EXPIRED:
277     case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
278         syslog(L_NOTICE, "cert has expired");
279         break;
280     }
281     if ((tls_serveractive) && (tls_loglevel >= 1))
282       Printf("verify return:%d", ok);
283
284     return (ok);
285 }
286
287
288 /*
289  * taken from OpenSSL crypto/bio/b_dump.c, modified to save a lot of strcpy
290  * and strcat by Matti Aarnio.
291  */
292
293 #define TRUNCATE
294 #define DUMP_WIDTH      16
295
296 static int tls_dump(const char *s, int len)
297 {
298     int     ret = 0;
299     char    buf[160 + 1];
300     char    *ss;
301     int     i;
302     int     j;
303     int     rows;
304     int     trunc;
305     unsigned char ch;
306
307     trunc = 0;
308
309
310 #ifdef TRUNCATE
311     for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--)
312         trunc++;
313 #endif
314
315     rows = (len / DUMP_WIDTH);
316     if ((rows * DUMP_WIDTH) < len)
317         rows++;
318
319     for (i = 0; i < rows; i++) {
320         buf[0] = '\0';                          /* start with empty string */
321         ss = buf;
322
323         sprintf(ss, "%04x ", i * DUMP_WIDTH);
324         ss += strlen(ss);
325         for (j = 0; j < DUMP_WIDTH; j++) {
326             if (((i * DUMP_WIDTH) + j) >= len) {
327                 strcpy(ss, "   ");
328             } else {
329                 ch = ((unsigned char) *((const char *)(s) + i * DUMP_WIDTH + j))
330                     & 0xff;
331                 sprintf(ss, "%02x%c", ch, j == 7 ? '|' : ' ');
332                 ss += 3;
333             }
334         }
335         ss += strlen(ss);
336         *ss+= ' ';
337         for (j = 0; j < DUMP_WIDTH; j++) {
338             if (((i * DUMP_WIDTH) + j) >= len)
339                 break;
340             ch = ((unsigned char) *((const char *)(s) + i * DUMP_WIDTH + j))
341                 & 0xff;
342             *ss+= (((ch >= ' ') && (ch <= '~')) ? ch : '.');
343             if (j == 7) *ss+= ' ';
344         }
345         *ss = 0;
346         /* 
347          * if this is the last call then update the ddt_dump thing so that
348          * we will move the selection point in the debug window
349          */     
350         if (tls_loglevel>0)
351           Printf("%s", buf);
352         ret += strlen(buf);
353     }
354 #ifdef TRUNCATE
355     if (trunc > 0) {
356         snprintf(buf, sizeof(buf), "%04x - <SPACES/NULS>\n", len+ trunc);
357         if (tls_loglevel>0)
358           Printf("%s", buf);
359         ret += strlen(buf);
360     }
361 #endif
362     return (ret);
363 }
364
365  /*
366   * Set up the cert things on the server side. We do need both the
367   * private key (in key_file) and the cert (in cert_file).
368   * Both files may be identical.
369   *
370   * This function is taken from OpenSSL apps/s_cb.c
371   */
372
373 static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
374 {
375     struct stat buf;
376
377     if (cert_file != NULL) {
378         if (SSL_CTX_use_certificate_file(ctx, cert_file,
379                                          SSL_FILETYPE_PEM) <= 0) {
380             syslog(L_ERROR, "unable to get certificate from '%s'", cert_file);
381             return (0);
382         }
383         if (key_file == NULL)
384             key_file = cert_file;
385
386         /* check ownership and permissions of key file */
387         if (lstat(key_file, &buf) == -1) {
388             syslog(L_ERROR, "unable to stat private key '%s'", key_file);
389             return (0);
390         }
391         if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) != 0 ||
392             buf.st_uid != getuid()) {
393             syslog(L_ERROR, "bad ownership or permissions on private key"
394                    " '%s': private key must be mode 600 and owned by "
395                    NEWSUSER, cert_file);
396             return (0);
397         }
398
399         if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
400                                         SSL_FILETYPE_PEM) <= 0) {
401             syslog(L_ERROR, "unable to get private key from '%s'", key_file);
402             return (0);
403         }
404         /* Now we know that a key and cert have been set against
405          * the SSL context */
406         if (!SSL_CTX_check_private_key(ctx)) {
407             syslog(L_ERROR, "Private key does not match the certificate public key");
408             return (0);
409         }
410     }
411     return (1);
412 }
413
414
415
416  /*
417   * This is the setup routine for the SSL server. As smtpd might be called
418   * more than once, we only want to do the initialization one time.
419   *
420   * The skeleton of this function is taken from OpenSSL apps/s_server.c.
421
422   * returns -1 on error
423   */
424
425 int tls_init_serverengine(int verifydepth,
426                           int askcert,
427                           int requirecert,
428                           char *tls_CAfile,
429                           char *tls_CApath,
430                           char *tls_cert_file,
431                           char *tls_key_file
432                           )
433 {
434     int     off = 0;
435     int     verify_flags = SSL_VERIFY_NONE;
436     char   *CApath;
437     char   *CAfile;
438     char   *s_cert_file;
439     char   *s_key_file;
440     struct stat buf;
441
442     if (tls_serverengine)
443       return (0);                               /* already running */
444
445     if (tls_loglevel >= 2)
446       Printf("starting TLS engine");
447
448     SSL_load_error_strings();
449     SSLeay_add_ssl_algorithms();
450
451     CTX = SSL_CTX_new(SSLv23_server_method());
452     if (CTX == NULL) {
453       return (-1);
454     };
455
456     off |= SSL_OP_ALL;          /* Work around all known bugs */
457     SSL_CTX_set_options(CTX, off);
458     SSL_CTX_set_info_callback(CTX, apps_ssl_info_callback);
459     SSL_CTX_sess_set_cache_size(CTX, 128);
460
461     if (strlen(tls_CAfile) == 0)
462       CAfile = NULL;
463     else
464       CAfile = tls_CAfile;
465     if (strlen(tls_CApath) == 0)
466       CApath = NULL;
467     else
468       CApath = tls_CApath;
469
470     if ((!SSL_CTX_load_verify_locations(CTX, CAfile, CApath)) ||
471         (!SSL_CTX_set_default_verify_paths(CTX))) {
472       if (tls_loglevel >= 2)
473         Printf("TLS engine: cannot load CA data\n");
474       return (-1);
475     }
476     
477     if (strlen(tls_cert_file) == 0)
478       s_cert_file = NULL;
479     else
480       s_cert_file = tls_cert_file;
481     if (strlen(tls_key_file) == 0)
482       s_key_file = NULL;
483     else
484       s_key_file = tls_key_file;
485     
486     if (!set_cert_stuff(CTX, s_cert_file, s_key_file)) {
487       if (tls_loglevel >= 2)
488         Printf("TLS engine: cannot load cert/key data\n");
489       return (-1);
490     }
491
492     /* load some randomization data from /dev/urandom, if it exists */
493     /* FIXME: should also check for ".rand" file, update it on exit */
494     if (stat("/dev/urandom", &buf) == 0)
495       RAND_load_file("/dev/urandom", 16 * 1024);
496
497     SSL_CTX_set_tmp_dh_callback(CTX, tmp_dh_cb);
498     SSL_CTX_set_options(CTX, SSL_OP_SINGLE_DH_USE);
499
500     verify_depth = verifydepth;
501     if (askcert!=0)
502         verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
503     if (requirecert)
504         verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
505             | SSL_VERIFY_CLIENT_ONCE;
506     SSL_CTX_set_verify(CTX, verify_flags, verify_callback);
507
508     SSL_CTX_set_client_CA_list(CTX, SSL_load_client_CA_file(CAfile));
509
510     tls_serverengine = 1;
511     return (0);
512 }
513
514
515 /*
516 **  The function called by nnrpd to initialize the TLS support.  Calls
517 **  tls_init_server_engine and checks the result.  On any sort of failure,
518 **  nnrpd will exit.
519 */
520 void
521 tls_init(void)
522 {
523     int ssl_result;
524
525     if (tls_initialized)
526         return;
527     sasl_config_read();
528     ssl_result = tls_init_serverengine(5,        /* depth to verify */
529                                        0,        /* can client auth? */
530                                        0,        /* required client to auth? */
531                                        (char *)sasl_config_getstring("tls_ca_file", ""),
532                                        (char *)sasl_config_getstring("tls_ca_path", ""),
533                                        (char *)sasl_config_getstring("tls_cert_file", ""),
534                                        (char *)sasl_config_getstring("tls_key_file", ""));
535     if (ssl_result == -1) {
536         Reply("%d Error initializing TLS\r\n", NNTP_STARTTLS_BAD_VAL);
537         syslog(L_ERROR, "error initializing TLS: "
538                "[CA_file: %s] [CA_path: %s] [cert_file: %s] [key_file: %s]",
539                sasl_config_getstring("tls_ca_file", ""),
540                sasl_config_getstring("tls_ca_path", ""),
541                sasl_config_getstring("tls_cert_file", ""),
542                sasl_config_getstring("tls_key_file", ""));
543         ExitWithStats(1, false);
544     }
545     tls_initialized = true;
546 }
547
548
549 /* taken from OpenSSL apps/s_cb.c */
550
551 static long bio_dump_cb(BIO * bio, int cmd, const char *argp, int argi,
552                         long argl UNUSED, long ret)
553 {
554     if (!do_dump)
555         return (ret);
556
557     if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
558         Printf("read from %08X [%08lX] (%d bytes => %ld (0x%X))", (unsigned int) bio, (long unsigned int) argp,
559                  argi, ret, (unsigned int) ret);
560         tls_dump(argp, (int) ret);
561         return (ret);
562     } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
563         Printf("write to %08X [%08lX] (%d bytes => %ld (0x%X))", (unsigned int) bio, (long unsigned int)argp,
564                  argi, ret, (unsigned int) ret);
565         tls_dump(argp, (int) ret);
566     }
567     return (ret);
568 }
569
570  /*
571   * This is the actual startup routine for the connection. We expect
572   * that the buffers are flushed and the "220 Ready to start TLS" was
573   * send to the client, so that we can immediately can start the TLS
574   * handshake process.
575   *
576   * layerbits and authid are filled in on sucess. authid is only
577   * filled in if the client authenticated
578   * 
579   */
580 int tls_start_servertls(int readfd, int writefd)
581 {
582     int     sts;
583     int     keepalive;
584     SSL_SESSION *session;
585     SSL_CIPHER *cipher;
586
587     if (!tls_serverengine)
588     {           
589       /* should never happen */
590       syslog(L_ERROR, "tls_engine not running");
591       return (-1);
592     }
593     if (tls_loglevel >= 1)
594         Printf("setting up TLS connection");
595
596     if (tls_conn == NULL)
597     {
598         tls_conn = (SSL *) SSL_new(CTX);
599     }
600     if (tls_conn == NULL)
601     {
602         return (-1);
603     }
604     SSL_clear(tls_conn);
605
606 #if     defined(SOL_SOCKET) && defined(SO_KEEPALIVE)
607     /* Set KEEPALIVE to catch broken socket connections. */
608     keepalive = 1;
609     if (setsockopt(readfd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0)
610         syslog(L_ERROR, "fd %d can't setsockopt(KEEPALIVE) %m", readfd);
611     if (setsockopt(writefd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0)
612         syslog(L_ERROR, "fd %d can't setsockopt(KEEPALIVE) %m", writefd);
613 #endif /* SOL_SOCKET && SO_KEEPALIVE */
614     
615     /* set the file descriptors for SSL to use */
616     if (SSL_set_rfd(tls_conn, readfd)==0)
617     {
618       return (-1);
619     }
620
621     if (SSL_set_wfd(tls_conn, writefd)==0)
622     {
623       return (-1);
624     }
625     
626     /*
627      * This is the actual handshake routine. It will do all the negotiations
628      * and will check the client cert etc.
629      */
630     SSL_set_accept_state(tls_conn);
631
632     /*
633      * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
634      * Well there is a BIO below the SSL routines that is automatically
635      * created for us, so we can use it for debugging purposes.
636      */
637     if (tls_loglevel >= 3)
638         BIO_set_callback(SSL_get_rbio(tls_conn), bio_dump_cb);
639
640     /* Dump the negotiation for loglevels 3 and 4*/
641     if (tls_loglevel >= 3)
642         do_dump = 1;
643
644       if ((sts = SSL_accept(tls_conn)) <= 0) { /* xxx <= 0 */
645         session = SSL_get_session(tls_conn);
646
647         if (session) {
648           SSL_CTX_remove_session(CTX, session);
649         }
650         if (tls_conn)
651           SSL_free(tls_conn);
652         tls_conn = NULL;
653         return (-1);
654       }
655       /* Only loglevel==4 dumps everything */
656       if (tls_loglevel < 4)
657         do_dump = 0;
658
659     tls_protocol = SSL_get_version(tls_conn);
660     cipher = SSL_get_current_cipher(tls_conn);
661
662     tls_cipher_name = SSL_CIPHER_get_name(cipher);
663     tls_cipher_usebits = SSL_CIPHER_get_bits(cipher,
664                                                  &tls_cipher_algbits);
665     tls_serveractive = 1;
666
667     syslog(L_NOTICE, "starttls: %s with cipher %s (%d/%d bits) no authentication", tls_protocol, tls_cipher_name,
668            tls_cipher_usebits, tls_cipher_algbits);
669
670     return (0);
671 }
672
673 ssize_t
674 SSL_writev (ssl, vector, count)
675      SSL *ssl;
676      const struct iovec *vector;
677      int count;
678 {
679   static char *buffer = NULL;
680   static size_t allocsize = 0;
681   char *bp;
682   size_t bytes, to_copy;
683   int i;
684   /* Find the total number of bytes to be written.  */
685   bytes = 0;
686   for (i = 0; i < count; ++i)
687     bytes += vector[i].iov_len;
688   /* Allocate a buffer to hold the data.  */
689   if (NULL == buffer) {
690     buffer = (char *) xmalloc(bytes);
691     allocsize = bytes;
692   } else if (bytes > allocsize) {
693     buffer = (char *) xrealloc (buffer, bytes);
694     allocsize = bytes;
695   }
696   /* Copy the data into BUFFER.  */
697   to_copy = bytes;
698   bp = buffer;
699   for (i = 0; i < count; ++i)
700     {
701 #define min(a, b)       ((a) > (b) ? (b) : (a))
702       size_t copy = min (vector[i].iov_len, to_copy);
703       memcpy (bp, vector[i].iov_base, copy);
704       bp += copy;
705       to_copy -= copy;
706       if (to_copy == 0)
707         break;
708     }
709   return SSL_write (ssl, buffer, bytes);
710 }
711
712
713 #endif /* HAVE_SSL */