cb12d318570517ed3f37221f207795dc77ac0dae
[citadel.git] / citadel / modules / crypto / serv_crypto.c
1 /*
2  * Copyright (c) 1987-2015 by the citadel.org team
3  *
4  * This program is open source software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 3.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  */
12
13 #include <string.h>
14 #include <unistd.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include "sysdep.h"
18
19 #ifdef HAVE_OPENSSL
20 #include <openssl/ssl.h>
21 #include <openssl/err.h>
22 #include <openssl/rand.h>
23 #endif
24
25 #if TIME_WITH_SYS_TIME
26 # include <sys/time.h>
27 # include <time.h>
28 #else
29 # if HAVE_SYS_TIME_H
30 #  include <sys/time.h>
31 # else
32 #  include <time.h>
33 # endif
34 #endif
35
36 #ifdef HAVE_PTHREAD_H
37 #include <pthread.h>
38 #endif
39
40 #ifdef HAVE_SYS_SELECT_H
41 #include <sys/select.h>
42 #endif
43
44 #include <stdio.h>
45 #include <libcitadel.h>
46 #include "server.h"
47 #include "serv_crypto.h"
48 #include "sysdep_decls.h"
49 #include "citadel.h"
50 #include "config.h"
51
52
53 #include "ctdl_module.h"
54 /* TODO: should we use the standard module init stuff to start this? */
55 /* TODO: should we register an event handler to call destruct_ssl? */
56
57 #ifdef HAVE_OPENSSL
58 SSL_CTX *ssl_ctx;               /* SSL context */
59 pthread_mutex_t **SSLCritters;  /* Things needing locking */
60
61 static unsigned long id_callback(void)
62 {
63         return (unsigned long) pthread_self();
64 }
65
66 void destruct_ssl(void)
67 {
68         int a;
69         for (a = 0; a < CRYPTO_num_locks(); a++) 
70                 free(SSLCritters[a]);
71         free (SSLCritters);
72 }
73
74 void init_ssl(void)
75 {
76         const SSL_METHOD *ssl_method;
77         DH *dh;
78         RSA *rsa=NULL;
79         X509_REQ *req = NULL;
80         X509 *cer = NULL;
81         EVP_PKEY *pk = NULL;
82         EVP_PKEY *req_pkey = NULL;
83         X509_NAME *name = NULL;
84         FILE *fp;
85
86         if (!access(EGD_POOL, F_OK))
87                 RAND_egd(EGD_POOL);
88
89         if (!RAND_status()) {
90                 syslog(LOG_CRIT,
91                         "PRNG not adequately seeded, won't do SSL/TLS\n");
92                 return;
93         }
94         SSLCritters =
95             malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
96         if (!SSLCritters) {
97                 syslog(LOG_EMERG, "citserver: can't allocate memory!!\n");
98                 /* Nothing's been initialized, just die */
99                 exit(1);
100         } else {
101                 int a;
102
103                 for (a = 0; a < CRYPTO_num_locks(); a++) {
104                         SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
105                         if (!SSLCritters[a]) {
106                                 syslog(LOG_EMERG,
107                                         "citserver: can't allocate memory!!\n");
108                                 /* Nothing's been initialized, just die */
109                                 exit(1);
110                         }
111                         pthread_mutex_init(SSLCritters[a], NULL);
112                 }
113         }
114
115         /*
116          * Initialize SSL transport layer
117          */
118         SSL_library_init();
119         SSL_load_error_strings();
120         ssl_method = SSLv23_server_method();
121         if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
122                 syslog(LOG_CRIT, "SSL_CTX_new failed: %s\n",
123                         ERR_reason_error_string(ERR_get_error()));
124                 return;
125         }
126         if (!(SSL_CTX_set_cipher_list(ssl_ctx, CIT_CIPHERS))) {
127                 syslog(LOG_CRIT, "SSL: No ciphers available\n");
128                 SSL_CTX_free(ssl_ctx);
129                 ssl_ctx = NULL;
130                 return;
131         }
132 #if 0
133 #if SSLEAY_VERSION_NUMBER >= 0x00906000L
134         SSL_CTX_set_mode(ssl_ctx, SSL_CTX_get_mode(ssl_ctx) |
135                          SSL_MODE_AUTO_RETRY);
136 #endif
137 #endif
138
139         CRYPTO_set_locking_callback(ssl_lock);
140         CRYPTO_set_id_callback(id_callback);
141
142         /* Load DH parameters into the context */
143         dh = DH_new();
144         if (!dh) {
145                 syslog(LOG_CRIT, "init_ssl() can't allocate a DH object: %s\n",
146                         ERR_reason_error_string(ERR_get_error()));
147                 SSL_CTX_free(ssl_ctx);
148                 ssl_ctx = NULL;
149                 return;
150         }
151         if (!(BN_hex2bn(&(dh->p), DH_P))) {
152                 syslog(LOG_CRIT, "init_ssl() can't assign DH_P: %s\n",
153                         ERR_reason_error_string(ERR_get_error()));
154                 SSL_CTX_free(ssl_ctx);
155                 ssl_ctx = NULL;
156                 return;
157         }
158         if (!(BN_hex2bn(&(dh->g), DH_G))) {
159                 syslog(LOG_CRIT, "init_ssl() can't assign DH_G: %s\n",
160                         ERR_reason_error_string(ERR_get_error()));
161                 SSL_CTX_free(ssl_ctx);
162                 ssl_ctx = NULL;
163                 return;
164         }
165         dh->length = DH_L;
166         SSL_CTX_set_tmp_dh(ssl_ctx, dh);
167         DH_free(dh);
168
169         /* Get our certificates in order.
170          * First, create the key/cert directory if it's not there already...
171          */
172         mkdir(ctdl_key_dir, 0700);
173
174         /*
175          * Generate a key pair if we don't have one.
176          */
177         if (access(file_crpt_file_key, R_OK) != 0) {
178                 syslog(LOG_INFO, "Generating RSA key pair.\n");
179                 rsa = RSA_generate_key(1024,    /* modulus size */
180                                         65537,  /* exponent */
181                                         NULL,   /* no callback */
182                                         NULL);  /* no callback */
183                 if (rsa == NULL) {
184                         syslog(LOG_CRIT, "Key generation failed: %s\n",
185                                 ERR_reason_error_string(ERR_get_error()));
186                 }
187                 if (rsa != NULL) {
188                         fp = fopen(file_crpt_file_key, "w");
189                         if (fp != NULL) {
190                                 chmod(file_crpt_file_key, 0600);
191                                 if (PEM_write_RSAPrivateKey(fp, /* the file */
192                                                         rsa,    /* the key */
193                                                         NULL,   /* no enc */
194                                                         NULL,   /* no passphr */
195                                                         0,      /* no passphr */
196                                                         NULL,   /* no callbk */
197                                                         NULL    /* no callbk */
198                                 ) != 1) {
199                                         syslog(LOG_CRIT, "Cannot write key: %s\n",
200                                                 ERR_reason_error_string(ERR_get_error()));
201                                         unlink(file_crpt_file_key);
202                                 }
203                                 fclose(fp);
204                         }
205                         RSA_free(rsa);
206                 }
207         }
208
209         /*
210          * If there is no certificate file on disk, we will be generating a self-signed certificate
211          * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
212          * the CSR in this step so that the next step may commence.
213          */
214         if ( (access(file_crpt_file_cer, R_OK) != 0) && (access(file_crpt_file_csr, R_OK) != 0) ) {
215                 syslog(LOG_INFO, "Generating a certificate signing request.\n");
216
217                 /*
218                  * Read our key from the file.  No, we don't just keep this
219                  * in memory from the above key-generation function, because
220                  * there is the possibility that the key was already on disk
221                  * and we didn't just generate it now.
222                  */
223                 fp = fopen(file_crpt_file_key, "r");
224                 if (fp) {
225                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
226                         fclose(fp);
227                 }
228
229                 if (rsa) {
230
231                         /* Create a public key from the private key */
232                         if (pk=EVP_PKEY_new(), pk != NULL) {
233                                 EVP_PKEY_assign_RSA(pk, rsa);
234                                 if (req = X509_REQ_new(), req != NULL) {
235
236                                         /* Set the public key */
237                                         X509_REQ_set_pubkey(req, pk);
238                                         X509_REQ_set_version(req, 0L);
239
240                                         name = X509_REQ_get_subject_name(req);
241
242                                         /* Tell it who we are */
243
244                                         /*
245                                         X509_NAME_add_entry_by_txt(name, "C",
246                                                 MBSTRING_ASC, "US", -1, -1, 0);
247
248                                         X509_NAME_add_entry_by_txt(name, "ST",
249                                                 MBSTRING_ASC, "New York", -1, -1, 0);
250
251                                         X509_NAME_add_entry_by_txt(name, "L",
252                                                 MBSTRING_ASC, "Mount Kisco", -1, -1, 0);
253                                         */
254
255                                         X509_NAME_add_entry_by_txt(name, "O",
256                                                                    MBSTRING_ASC, 
257                                                                    (unsigned char*) CtdlGetConfigStr("c_humannode"),
258                                                                    -1, -1, 0);
259
260                                         X509_NAME_add_entry_by_txt(name, "OU",
261                                                                    MBSTRING_ASC, 
262                                                                    (unsigned const char*)"Citadel server",
263                                                                    -1, -1, 0);
264
265                                         /* X509_NAME_add_entry_by_txt(name, "CN",
266                                                 MBSTRING_ASC, CtdlGetConfigStr("c_fqdn"), -1, -1, 0);
267                                         */
268
269                                         X509_NAME_add_entry_by_txt(name, 
270                                                                    "CN",
271                                                                    MBSTRING_ASC, 
272                                                                    (const unsigned char *)"*", -1, -1, 0);
273                                 
274                                         X509_REQ_set_subject_name(req, name);
275
276                                         /* Sign the CSR */
277                                         if (!X509_REQ_sign(req, pk, EVP_md5())) {
278                                                 syslog(LOG_CRIT, "X509_REQ_sign(): error\n");
279                                         }
280                                         else {
281                                                 /* Write it to disk. */ 
282                                                 fp = fopen(file_crpt_file_csr, "w");
283                                                 if (fp != NULL) {
284                                                         chmod(file_crpt_file_csr, 0600);
285                                                         PEM_write_X509_REQ(fp, req);
286                                                         fclose(fp);
287                                                 }
288                                         }
289
290                                         X509_REQ_free(req);
291                                 }
292                         }
293
294                         RSA_free(rsa);
295                 }
296
297                 else {
298                         syslog(LOG_CRIT, "Unable to read private key.\n");
299                 }
300         }
301
302
303
304         /*
305          * Generate a self-signed certificate if we don't have one.
306          */
307         if (access(file_crpt_file_cer, R_OK) != 0) {
308                 syslog(LOG_INFO, "Generating a self-signed certificate.\n");
309
310                 /* Same deal as before: always read the key from disk because
311                  * it may or may not have just been generated.
312                  */
313                 fp = fopen(file_crpt_file_key, "r");
314                 if (fp) {
315                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
316                         fclose(fp);
317                 }
318
319                 /* This also holds true for the CSR. */
320                 req = NULL;
321                 cer = NULL;
322                 pk = NULL;
323                 if (rsa) {
324                         if (pk=EVP_PKEY_new(), pk != NULL) {
325                                 EVP_PKEY_assign_RSA(pk, rsa);
326                         }
327
328                         fp = fopen(file_crpt_file_csr, "r");
329                         if (fp) {
330                                 req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
331                                 fclose(fp);
332                         }
333
334                         if (req) {
335                                 if (cer = X509_new(), cer != NULL) {
336
337                                         ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
338                                         X509_set_issuer_name(cer, req->req_info->subject);
339                                         X509_set_subject_name(cer, req->req_info->subject);
340                                         X509_gmtime_adj(X509_get_notBefore(cer),0);
341                                         X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
342                                         req_pkey = X509_REQ_get_pubkey(req);
343                                         X509_set_pubkey(cer, req_pkey);
344                                         EVP_PKEY_free(req_pkey);
345                                         
346                                         /* Sign the cert */
347                                         if (!X509_sign(cer, pk, EVP_md5())) {
348                                                 syslog(LOG_CRIT, "X509_sign(): error\n");
349                                         }
350                                         else {
351                                                 /* Write it to disk. */ 
352                                                 fp = fopen(file_crpt_file_cer, "w");
353                                                 if (fp != NULL) {
354                                                         chmod(file_crpt_file_cer, 0600);
355                                                         PEM_write_X509(fp, cer);
356                                                         fclose(fp);
357                                                 }
358                                         }
359                                         X509_free(cer);
360                                 }
361                         }
362
363                         RSA_free(rsa);
364                 }
365         }
366
367
368         /*
369          * Now try to bind to the key and certificate.
370          */
371         SSL_CTX_use_certificate_chain_file(ssl_ctx, file_crpt_file_cer);
372         SSL_CTX_use_PrivateKey_file(ssl_ctx, file_crpt_file_key, SSL_FILETYPE_PEM);
373         if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
374                 syslog(LOG_CRIT, "Cannot install certificate: %s\n",
375                                 ERR_reason_error_string(ERR_get_error()));
376         }
377
378         /* Finally let the server know we're here */
379         CtdlRegisterProtoHook(cmd_stls, "STLS", "Start SSL/TLS session");
380         CtdlRegisterProtoHook(cmd_gtls, "GTLS",
381                               "Get SSL/TLS session status");
382         CtdlRegisterSessionHook(endtls, EVT_STOP, PRIO_STOP + 10);
383 }
384
385
386 /*
387  * client_write_ssl() Send binary data to the client encrypted.
388  */
389 void client_write_ssl(const char *buf, int nbytes)
390 {
391         int retval;
392         int nremain;
393         char junk[1];
394
395         nremain = nbytes;
396
397         while (nremain > 0) {
398                 if (SSL_want_write(CC->ssl)) {
399                         if ((SSL_read(CC->ssl, junk, 0)) < 1) {
400                                 syslog(LOG_DEBUG, "SSL_read in client_write: %s\n", ERR_reason_error_string(ERR_get_error()));
401                         }
402                 }
403                 retval =
404                     SSL_write(CC->ssl, &buf[nbytes - nremain], nremain);
405                 if (retval < 1) {
406                         long errval;
407
408                         errval = SSL_get_error(CC->ssl, retval);
409                         if (errval == SSL_ERROR_WANT_READ ||
410                             errval == SSL_ERROR_WANT_WRITE) {
411                                 sleep(1);
412                                 continue;
413                         }
414                         syslog(LOG_DEBUG, "SSL_write got error %ld, ret %d\n", errval, retval);
415                         if (retval == -1)
416                                 syslog(LOG_DEBUG, "errno is %d\n", errno);
417                         endtls();
418                         client_write(&buf[nbytes - nremain], nremain);
419                         return;
420                 }
421                 nremain -= retval;
422         }
423 }
424
425
426 /*
427  * read data from the encrypted layer.
428  */
429 int client_read_sslbuffer(StrBuf *buf, int timeout)
430 {
431         char sbuf[16384]; /* OpenSSL communicates in 16k blocks, so let's speak its native tongue. */
432         int rlen;
433         char junk[1];
434         SSL *pssl = CC->ssl;
435
436         if (pssl == NULL) return(-1);
437
438         while (1) {
439                 if (SSL_want_read(pssl)) {
440                         if ((SSL_write(pssl, junk, 0)) < 1) {
441                                 syslog(LOG_DEBUG, "SSL_write in client_read\n");
442                         }
443                 }
444                 rlen = SSL_read(pssl, sbuf, sizeof(sbuf));
445                 if (rlen < 1) {
446                         long errval;
447
448                         errval = SSL_get_error(pssl, rlen);
449                         if (errval == SSL_ERROR_WANT_READ || errval == SSL_ERROR_WANT_WRITE) {
450                                 sleep(1);
451                                 continue;
452                         }
453                         syslog(LOG_DEBUG, "SSL_read got error %ld\n", errval);
454                         endtls();
455                         return (-1);
456                 }
457                 StrBufAppendBufPlain(buf, sbuf, rlen, 0);
458                 return rlen;
459         }
460         return (0);
461 }
462
463 int client_readline_sslbuffer(StrBuf *Line, StrBuf *IOBuf, const char **Pos, int timeout)
464 {
465         CitContext *CCC = CC;
466         const char *pos = NULL;
467         const char *pLF;
468         int len, rlen;
469         int nSuccessLess = 0;
470         const char *pch = NULL;
471         
472         if ((Line == NULL) ||
473             (Pos == NULL) ||
474             (IOBuf == NULL))
475         {
476                 if (Pos != NULL)
477                         *Pos = NULL;
478 //              *Error = ErrRBLF_PreConditionFailed;
479                 return -1;
480         }
481
482         pos = *Pos;
483         if ((StrLength(IOBuf) > 0) && 
484             (pos != NULL) && 
485             (pos < ChrPtr(IOBuf) + StrLength(IOBuf))) 
486         {
487                 pch = pos;
488                 pch = strchr(pch, '\n');
489                 
490                 if (pch == NULL) {
491                         StrBufAppendBufPlain(Line, pos, 
492                                              StrLength(IOBuf) - (pos - ChrPtr(IOBuf)), 0);
493                         FlushStrBuf(IOBuf);
494                         *Pos = NULL;
495                 }
496                 else {
497                         int n = 0;
498                         if ((pch > ChrPtr(IOBuf)) && 
499                             (*(pch - 1) == '\r')) {
500                                 n = 1;
501                         }
502                         StrBufAppendBufPlain(Line, pos, 
503                                              (pch - pos - n), 0);
504
505                         if (StrLength(IOBuf) <= (pch - ChrPtr(IOBuf) + 1)) {
506                                 FlushStrBuf(IOBuf);
507                                 *Pos = NULL;
508                         }
509                         else 
510                                 *Pos = pch + 1;
511                         return StrLength(Line);
512                 }
513         }
514
515         pLF = NULL;
516         while ((nSuccessLess < timeout) && 
517                (pLF == NULL) &&
518                (CCC->ssl != NULL)) {
519
520                 rlen = client_read_sslbuffer(IOBuf, timeout);
521                 if (rlen < 1) {
522 //                      *Error = strerror(errno);
523 //                      close(*fd);
524 //                      *fd = -1;
525                         return -1;
526                 }
527                 else if (rlen > 0) {
528                         pLF = strchr(ChrPtr(IOBuf), '\n');
529                 }
530         }
531         *Pos = NULL;
532         if (pLF != NULL) {
533                 pos = ChrPtr(IOBuf);
534                 len = pLF - pos;
535                 if (len > 0 && (*(pLF - 1) == '\r') )
536                         len --;
537                 StrBufAppendBufPlain(Line, pos, len, 0);
538                 if (pLF + 1 >= ChrPtr(IOBuf) + StrLength(IOBuf))
539                 {
540                         FlushStrBuf(IOBuf);
541                 }
542                 else 
543                         *Pos = pLF + 1;
544                 return StrLength(Line);
545         }
546 //      *Error = ErrRBLF_NotEnoughSentFromServer;
547         return -1;
548 }
549
550
551
552 int client_read_sslblob(StrBuf *Target, long bytes, int timeout)
553 {
554         long baselen;
555         long RemainRead;
556         int retval = 0;
557         CitContext *CCC = CC;
558
559         baselen = StrLength(Target);
560
561         if (StrLength(CCC->RecvBuf.Buf) > 0)
562         {
563                 long RemainLen;
564                 long TotalLen;
565                 const char *pchs;
566
567                 if (CCC->RecvBuf.ReadWritePointer == NULL)
568                         CCC->RecvBuf.ReadWritePointer = ChrPtr(CCC->RecvBuf.Buf);
569                 pchs = ChrPtr(CCC->RecvBuf.Buf);
570                 TotalLen = StrLength(CCC->RecvBuf.Buf);
571                 RemainLen = TotalLen - (pchs - CCC->RecvBuf.ReadWritePointer);
572                 if (RemainLen > bytes)
573                         RemainLen = bytes;
574                 if (RemainLen > 0)
575                 {
576                         StrBufAppendBufPlain(Target, 
577                                              CCC->RecvBuf.ReadWritePointer, 
578                                              RemainLen, 0);
579                         CCC->RecvBuf.ReadWritePointer += RemainLen;
580                 }
581                 if ((ChrPtr(CCC->RecvBuf.Buf) + StrLength(CCC->RecvBuf.Buf)) <= CCC->RecvBuf.ReadWritePointer)
582                 {
583                         CCC->RecvBuf.ReadWritePointer = NULL;
584                         FlushStrBuf(CCC->RecvBuf.Buf);
585                 }
586         }
587
588         if (StrLength(Target) >= bytes + baselen)
589                 return 1;
590
591         CCC->RecvBuf.ReadWritePointer = NULL;
592
593         while ((StrLength(Target) < bytes + baselen) &&
594                (retval >= 0))
595         {
596                 retval = client_read_sslbuffer(CCC->RecvBuf.Buf, timeout);
597                 if (retval >= 0) {
598                         RemainRead = bytes - (StrLength (Target) - baselen);
599                         if (RemainRead < StrLength(CCC->RecvBuf.Buf))
600                         {
601                                 StrBufAppendBufPlain(
602                                         Target, 
603                                         ChrPtr(CCC->RecvBuf.Buf), 
604                                         RemainRead, 0);
605                                 CCC->RecvBuf.ReadWritePointer = ChrPtr(CCC->RecvBuf.Buf) + RemainRead;
606                                 break;
607                         }
608                         StrBufAppendBuf(Target, CCC->RecvBuf.Buf, 0); /* todo: Buf > bytes? */
609                         FlushStrBuf(CCC->RecvBuf.Buf);
610                 }
611                 else 
612                 {
613                         FlushStrBuf(CCC->RecvBuf.Buf);
614                         return -1;
615         
616                 }
617         }
618         return 1;
619 }
620
621
622 /*
623  * CtdlStartTLS() starts SSL/TLS encryption for the current session.  It
624  * must be supplied with pre-generated strings for responses of "ok," "no
625  * support for TLS," and "error" so that we can use this in any protocol.
626  */
627 void CtdlStartTLS(char *ok_response, char *nosup_response,
628                         char *error_response) {
629
630         int retval, bits, alg_bits;
631
632         if (!ssl_ctx) {
633                 syslog(LOG_CRIT, "SSL failed: no ssl_ctx exists?\n");
634                 if (nosup_response != NULL) cprintf("%s", nosup_response);
635                 return;
636         }
637         if (!(CC->ssl = SSL_new(ssl_ctx))) {
638                 syslog(LOG_CRIT, "SSL_new failed: %s\n",
639                                 ERR_reason_error_string(ERR_get_error()));
640                 if (error_response != NULL) cprintf("%s", error_response);
641                 return;
642         }
643         if (!(SSL_set_fd(CC->ssl, CC->client_socket))) {
644                 syslog(LOG_CRIT, "SSL_set_fd failed: %s\n",
645                         ERR_reason_error_string(ERR_get_error()));
646                 SSL_free(CC->ssl);
647                 CC->ssl = NULL;
648                 if (error_response != NULL) cprintf("%s", error_response);
649                 return;
650         }
651         if (ok_response != NULL) cprintf("%s", ok_response);
652         retval = SSL_accept(CC->ssl);
653         if (retval < 1) {
654                 /*
655                  * Can't notify the client of an error here; they will
656                  * discover the problem at the SSL layer and should
657                  * revert to unencrypted communications.
658                  */
659                 long errval;
660                 char error_string[128];
661
662                 errval = SSL_get_error(CC->ssl, retval);
663                 syslog(LOG_CRIT, "SSL_accept failed: retval=%d, errval=%ld, err=%s\n",
664                         retval,
665                         errval,
666                         ERR_error_string(errval, error_string)
667                 );
668                 SSL_free(CC->ssl);
669                 CC->ssl = NULL;
670                 return;
671         }
672         BIO_set_close(CC->ssl->rbio, BIO_NOCLOSE);
673         bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), &alg_bits);
674         syslog(LOG_INFO, "SSL/TLS using %s on %s (%d of %d bits)\n",
675                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
676                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
677                 bits, alg_bits);
678         CC->redirect_ssl = 1;
679 }
680
681
682 /*
683  * cmd_stls() starts SSL/TLS encryption for the current session
684  */
685 void cmd_stls(char *params)
686 {
687         char ok_response[SIZ];
688         char nosup_response[SIZ];
689         char error_response[SIZ];
690
691         unbuffer_output();
692
693         sprintf(ok_response,
694                 "%d Begin TLS negotiation now\n",
695                 CIT_OK);
696         sprintf(nosup_response,
697                 "%d TLS not supported here\n",
698                 ERROR + CMD_NOT_SUPPORTED);
699         sprintf(error_response,
700                 "%d TLS negotiation error\n",
701                 ERROR + INTERNAL_ERROR);
702
703         CtdlStartTLS(ok_response, nosup_response, error_response);
704 }
705
706
707 /*
708  * cmd_gtls() returns status info about the TLS connection
709  */
710 void cmd_gtls(char *params)
711 {
712         int bits, alg_bits;
713
714         if (!CC->ssl || !CC->redirect_ssl) {
715                 cprintf("%d Session is not encrypted.\n", ERROR);
716                 return;
717         }
718         bits =
719             SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl),
720                                 &alg_bits);
721         cprintf("%d %s|%s|%d|%d\n", CIT_OK,
722                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
723                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
724                 alg_bits, bits);
725 }
726
727
728 /*
729  * endtls() shuts down the TLS connection
730  *
731  * WARNING:  This may make your session vulnerable to a known plaintext
732  * attack in the current implmentation.
733  */
734 void endtls(void)
735 {
736         if (!CC->ssl) {
737                 CC->redirect_ssl = 0;
738                 return;
739         }
740
741         syslog(LOG_INFO, "Ending SSL/TLS\n");
742         SSL_shutdown(CC->ssl);
743         SSL_free(CC->ssl);
744         CC->ssl = NULL;
745         CC->redirect_ssl = 0;
746 }
747
748
749 /*
750  * ssl_lock() callback for OpenSSL mutex locks
751  */
752 void ssl_lock(int mode, int n, const char *file, int line)
753 {
754         if (mode & CRYPTO_LOCK)
755                 pthread_mutex_lock(SSLCritters[n]);
756         else
757                 pthread_mutex_unlock(SSLCritters[n]);
758 }
759 #endif                          /* HAVE_OPENSSL */