Did away with lprintf all together now its called CtdlLogPrintf()
[citadel.git] / citadel / modules / crypto / serv_crypto.c
1 /* $Id$ */
2
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7 #include "sysdep.h"
8
9 #ifdef HAVE_OPENSSL
10 #include <openssl/ssl.h>
11 #include <openssl/err.h>
12 #include <openssl/rand.h>
13 #endif
14
15 #if TIME_WITH_SYS_TIME
16 # include <sys/time.h>
17 # include <time.h>
18 #else
19 # if HAVE_SYS_TIME_H
20 #  include <sys/time.h>
21 # else
22 #  include <time.h>
23 # endif
24 #endif
25
26 #ifdef HAVE_PTHREAD_H
27 #include <pthread.h>
28 #endif
29
30 #ifdef HAVE_SYS_SELECT_H
31 #include <sys/select.h>
32 #endif
33
34 #include <stdio.h>
35 #include "server.h"
36 #include "serv_crypto.h"
37 #include "sysdep_decls.h"
38 #include "citadel.h"
39 #include "config.h"
40
41
42 #include "ctdl_module.h"
43 /* TODO: should we use the standard module init stuff to start this? */
44 /* TODO: should we register an event handler to call destruct_ssl? */
45
46 #ifdef HAVE_OPENSSL
47 SSL_CTX *ssl_ctx;               /* SSL context */
48 pthread_mutex_t **SSLCritters;  /* Things needing locking */
49
50 static unsigned long id_callback(void)
51 {
52         return (unsigned long) pthread_self();
53 }
54
55 void destruct_ssl(void)
56 {
57         int a;
58         CtdlUnregisterProtoHook(cmd_stls, "STLS");
59         CtdlUnregisterProtoHook(cmd_gtls, "GTLS");
60         for (a = 0; a < CRYPTO_num_locks(); a++) 
61                 free(SSLCritters[a]);
62         free (SSLCritters);
63 }
64
65 void init_ssl(void)
66 {
67         SSL_METHOD *ssl_method;
68         DH *dh;
69         RSA *rsa=NULL;
70         X509_REQ *req = NULL;
71         X509 *cer = NULL;
72         EVP_PKEY *pk = NULL;
73         EVP_PKEY *req_pkey = NULL;
74         X509_NAME *name = NULL;
75         FILE *fp;
76
77         if (!access(EGD_POOL, F_OK))
78                 RAND_egd(EGD_POOL);
79
80         if (!RAND_status()) {
81                 CtdlLogPrintf(CTDL_CRIT,
82                         "PRNG not adequately seeded, won't do SSL/TLS\n");
83                 return;
84         }
85         SSLCritters =
86             malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
87         if (!SSLCritters) {
88                 CtdlLogPrintf(CTDL_EMERG, "citserver: can't allocate memory!!\n");
89                 /* Nothing's been initialized, just die */
90                 exit(1);
91         } else {
92                 int a;
93
94                 for (a = 0; a < CRYPTO_num_locks(); a++) {
95                         SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
96                         if (!SSLCritters[a]) {
97                                 CtdlLogPrintf(CTDL_EMERG,
98                                         "citserver: can't allocate memory!!\n");
99                                 /* Nothing's been initialized, just die */
100                                 exit(1);
101                         }
102                         pthread_mutex_init(SSLCritters[a], NULL);
103                 }
104         }
105
106         /*
107          * Initialize SSL transport layer
108          */
109         SSL_library_init();
110         SSL_load_error_strings();
111         ssl_method = SSLv23_server_method();
112         if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
113                 CtdlLogPrintf(CTDL_CRIT, "SSL_CTX_new failed: %s\n",
114                         ERR_reason_error_string(ERR_get_error()));
115                 return;
116         }
117         if (!(SSL_CTX_set_cipher_list(ssl_ctx, CIT_CIPHERS))) {
118                 CtdlLogPrintf(CTDL_CRIT, "SSL: No ciphers available\n");
119                 SSL_CTX_free(ssl_ctx);
120                 ssl_ctx = NULL;
121                 return;
122         }
123 #if 0
124 #if SSLEAY_VERSION_NUMBER >= 0x00906000L
125         SSL_CTX_set_mode(ssl_ctx, SSL_CTX_get_mode(ssl_ctx) |
126                          SSL_MODE_AUTO_RETRY);
127 #endif
128 #endif
129
130         CRYPTO_set_locking_callback(ssl_lock);
131         CRYPTO_set_id_callback(id_callback);
132
133         /* Load DH parameters into the context */
134         dh = DH_new();
135         if (!dh) {
136                 CtdlLogPrintf(CTDL_CRIT, "init_ssl() can't allocate a DH object: %s\n",
137                         ERR_reason_error_string(ERR_get_error()));
138                 SSL_CTX_free(ssl_ctx);
139                 ssl_ctx = NULL;
140                 return;
141         }
142         if (!(BN_hex2bn(&(dh->p), DH_P))) {
143                 CtdlLogPrintf(CTDL_CRIT, "init_ssl() can't assign DH_P: %s\n",
144                         ERR_reason_error_string(ERR_get_error()));
145                 SSL_CTX_free(ssl_ctx);
146                 ssl_ctx = NULL;
147                 return;
148         }
149         if (!(BN_hex2bn(&(dh->g), DH_G))) {
150                 CtdlLogPrintf(CTDL_CRIT, "init_ssl() can't assign DH_G: %s\n",
151                         ERR_reason_error_string(ERR_get_error()));
152                 SSL_CTX_free(ssl_ctx);
153                 ssl_ctx = NULL;
154                 return;
155         }
156         dh->length = DH_L;
157         SSL_CTX_set_tmp_dh(ssl_ctx, dh);
158         DH_free(dh);
159
160         /* Get our certificates in order.
161          * First, create the key/cert directory if it's not there already...
162          */
163         mkdir(ctdl_key_dir, 0700);
164
165         /*
166          * Generate a key pair if we don't have one.
167          */
168         if (access(file_crpt_file_key, R_OK) != 0) {
169                 CtdlLogPrintf(CTDL_INFO, "Generating RSA key pair.\n");
170                 rsa = RSA_generate_key(1024,    /* modulus size */
171                                         65537,  /* exponent */
172                                         NULL,   /* no callback */
173                                         NULL);  /* no callback */
174                 if (rsa == NULL) {
175                         CtdlLogPrintf(CTDL_CRIT, "Key generation failed: %s\n",
176                                 ERR_reason_error_string(ERR_get_error()));
177                 }
178                 if (rsa != NULL) {
179                         fp = fopen(file_crpt_file_key, "w");
180                         if (fp != NULL) {
181                                 chmod(file_crpt_file_key, 0600);
182                                 if (PEM_write_RSAPrivateKey(fp, /* the file */
183                                                         rsa,    /* the key */
184                                                         NULL,   /* no enc */
185                                                         NULL,   /* no passphr */
186                                                         0,      /* no passphr */
187                                                         NULL,   /* no callbk */
188                                                         NULL    /* no callbk */
189                                 ) != 1) {
190                                         CtdlLogPrintf(CTDL_CRIT, "Cannot write key: %s\n",
191                                                 ERR_reason_error_string(ERR_get_error()));
192                                         unlink(file_crpt_file_key);
193                                 }
194                                 fclose(fp);
195                         }
196                         RSA_free(rsa);
197                 }
198         }
199
200         /*
201          * If there is no certificate file on disk, we will be generating a self-signed certificate
202          * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
203          * the CSR in this step so that the next step may commence.
204          */
205         if ( (access(file_crpt_file_cer, R_OK) != 0) && (access(file_crpt_file_csr, R_OK) != 0) ) {
206                 CtdlLogPrintf(CTDL_INFO, "Generating a certificate signing request.\n");
207
208                 /*
209                  * Read our key from the file.  No, we don't just keep this
210                  * in memory from the above key-generation function, because
211                  * there is the possibility that the key was already on disk
212                  * and we didn't just generate it now.
213                  */
214                 fp = fopen(file_crpt_file_key, "r");
215                 if (fp) {
216                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
217                         fclose(fp);
218                 }
219
220                 if (rsa) {
221
222                         /* Create a public key from the private key */
223                         if (pk=EVP_PKEY_new(), pk != NULL) {
224                                 EVP_PKEY_assign_RSA(pk, rsa);
225                                 if (req = X509_REQ_new(), req != NULL) {
226
227                                         /* Set the public key */
228                                         X509_REQ_set_pubkey(req, pk);
229                                         X509_REQ_set_version(req, 0L);
230
231                                         name = X509_REQ_get_subject_name(req);
232
233                                         /* Tell it who we are */
234
235                                         /*
236                                         X509_NAME_add_entry_by_txt(name, "C",
237                                                 MBSTRING_ASC, "US", -1, -1, 0);
238
239                                         X509_NAME_add_entry_by_txt(name, "ST",
240                                                 MBSTRING_ASC, "New York", -1, -1, 0);
241
242                                         X509_NAME_add_entry_by_txt(name, "L",
243                                                 MBSTRING_ASC, "Mount Kisco", -1, -1, 0);
244                                         */
245
246                                         X509_NAME_add_entry_by_txt(name, "O",
247                                                 MBSTRING_ASC, config.c_humannode, -1, -1, 0);
248
249                                         X509_NAME_add_entry_by_txt(name, "OU",
250                                                 MBSTRING_ASC, "Citadel server", -1, -1, 0);
251
252                                         /* X509_NAME_add_entry_by_txt(name, "CN",
253                                                 MBSTRING_ASC, config.c_fqdn, -1, -1, 0);
254                                         */
255
256                                         X509_NAME_add_entry_by_txt(name, "CN",
257                                                 MBSTRING_ASC, "*", -1, -1, 0);
258                                 
259                                         X509_REQ_set_subject_name(req, name);
260
261                                         /* Sign the CSR */
262                                         if (!X509_REQ_sign(req, pk, EVP_md5())) {
263                                                 CtdlLogPrintf(CTDL_CRIT, "X509_REQ_sign(): error\n");
264                                         }
265                                         else {
266                                                 /* Write it to disk. */ 
267                                                 fp = fopen(file_crpt_file_csr, "w");
268                                                 if (fp != NULL) {
269                                                         chmod(file_crpt_file_csr, 0600);
270                                                         PEM_write_X509_REQ(fp, req);
271                                                         fclose(fp);
272                                                 }
273                                         }
274
275                                         X509_REQ_free(req);
276                                 }
277                         }
278
279                         RSA_free(rsa);
280                 }
281
282                 else {
283                         CtdlLogPrintf(CTDL_CRIT, "Unable to read private key.\n");
284                 }
285         }
286
287
288
289         /*
290          * Generate a self-signed certificate if we don't have one.
291          */
292         if (access(file_crpt_file_cer, R_OK) != 0) {
293                 CtdlLogPrintf(CTDL_INFO, "Generating a self-signed certificate.\n");
294
295                 /* Same deal as before: always read the key from disk because
296                  * it may or may not have just been generated.
297                  */
298                 fp = fopen(file_crpt_file_key, "r");
299                 if (fp) {
300                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
301                         fclose(fp);
302                 }
303
304                 /* This also holds true for the CSR. */
305                 req = NULL;
306                 cer = NULL;
307                 pk = NULL;
308                 if (rsa) {
309                         if (pk=EVP_PKEY_new(), pk != NULL) {
310                                 EVP_PKEY_assign_RSA(pk, rsa);
311                         }
312
313                         fp = fopen(file_crpt_file_csr, "r");
314                         if (fp) {
315                                 req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
316                                 fclose(fp);
317                         }
318
319                         if (req) {
320                                 if (cer = X509_new(), cer != NULL) {
321
322                                         ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
323                                         X509_set_issuer_name(cer, req->req_info->subject);
324                                         X509_set_subject_name(cer, req->req_info->subject);
325                                         X509_gmtime_adj(X509_get_notBefore(cer),0);
326                                         X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
327                                         req_pkey = X509_REQ_get_pubkey(req);
328                                         X509_set_pubkey(cer, req_pkey);
329                                         EVP_PKEY_free(req_pkey);
330                                         
331                                         /* Sign the cert */
332                                         if (!X509_sign(cer, pk, EVP_md5())) {
333                                                 CtdlLogPrintf(CTDL_CRIT, "X509_sign(): error\n");
334                                         }
335                                         else {
336                                                 /* Write it to disk. */ 
337                                                 fp = fopen(file_crpt_file_cer, "w");
338                                                 if (fp != NULL) {
339                                                         chmod(file_crpt_file_cer, 0600);
340                                                         PEM_write_X509(fp, cer);
341                                                         fclose(fp);
342                                                 }
343                                         }
344                                         X509_free(cer);
345                                 }
346                         }
347
348                         RSA_free(rsa);
349                 }
350         }
351
352
353         /*
354          * Now try to bind to the key and certificate.
355          */
356         SSL_CTX_use_certificate_chain_file(ssl_ctx, file_crpt_file_cer);
357         SSL_CTX_use_PrivateKey_file(ssl_ctx, file_crpt_file_key, SSL_FILETYPE_PEM);
358         if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
359                 CtdlLogPrintf(CTDL_CRIT, "Cannot install certificate: %s\n",
360                                 ERR_reason_error_string(ERR_get_error()));
361         }
362
363         /* Finally let the server know we're here */
364         CtdlRegisterProtoHook(cmd_stls, "STLS", "Start SSL/TLS session");
365         CtdlRegisterProtoHook(cmd_gtls, "GTLS",
366                               "Get SSL/TLS session status");
367         CtdlRegisterSessionHook(endtls, EVT_STOP);
368 }
369
370
371 /*
372  * client_write_ssl() Send binary data to the client encrypted.
373  */
374 void client_write_ssl(char *buf, int nbytes)
375 {
376         int retval;
377         int nremain;
378         char junk[1];
379
380         nremain = nbytes;
381
382         while (nremain > 0) {
383                 if (SSL_want_write(CC->ssl)) {
384                         if ((SSL_read(CC->ssl, junk, 0)) < 1) {
385                                 CtdlLogPrintf(CTDL_DEBUG, "SSL_read in client_write: %s\n", ERR_reason_error_string(ERR_get_error()));
386                         }
387                 }
388                 retval =
389                     SSL_write(CC->ssl, &buf[nbytes - nremain], nremain);
390                 if (retval < 1) {
391                         long errval;
392
393                         errval = SSL_get_error(CC->ssl, retval);
394                         if (errval == SSL_ERROR_WANT_READ ||
395                             errval == SSL_ERROR_WANT_WRITE) {
396                                 sleep(1);
397                                 continue;
398                         }
399                         CtdlLogPrintf(CTDL_DEBUG, "SSL_write got error %ld, ret %d\n", errval, retval);
400                         if (retval == -1)
401                                 CtdlLogPrintf(CTDL_DEBUG, "errno is %d\n", errno);
402                         endtls();
403                         client_write(&buf[nbytes - nremain], nremain);
404                         return;
405                 }
406                 nremain -= retval;
407         }
408 }
409
410
411 /*
412  * client_read_ssl() - read data from the encrypted layer.
413  */
414 int client_read_ssl(char *buf, int bytes, int timeout)
415 {
416 #if 0
417         fd_set rfds;
418         struct timeval tv;
419         int retval;
420         int s;
421 #endif
422         int len, rlen;
423         char junk[1];
424
425         len = 0;
426         while (len < bytes) {
427 #if 0
428                 /*
429                  * This code is disabled because we don't need it when
430                  * using blocking reads (which we are). -IO
431                  */
432                 FD_ZERO(&rfds);
433                 s = BIO_get_fd(CC->ssl->rbio, NULL);
434                 FD_SET(s, &rfds);
435                 tv.tv_sec = timeout;
436                 tv.tv_usec = 0;
437
438                 retval = select(s + 1, &rfds, NULL, NULL, &tv);
439
440                 if (FD_ISSET(s, &rfds) == 0) {
441                         return (0);
442                 }
443
444 #endif
445                 if (SSL_want_read(CC->ssl)) {
446                         if ((SSL_write(CC->ssl, junk, 0)) < 1) {
447                                 CtdlLogPrintf(CTDL_DEBUG, "SSL_write in client_read: %s\n", ERR_reason_error_string(ERR_get_error()));
448                         }
449                 }
450                 rlen = SSL_read(CC->ssl, &buf[len], bytes - len);
451                 if (rlen < 1) {
452                         long errval;
453
454                         errval = SSL_get_error(CC->ssl, rlen);
455                         if (errval == SSL_ERROR_WANT_READ ||
456                             errval == SSL_ERROR_WANT_WRITE) {
457                                 sleep(1);
458                                 continue;
459                         }
460                         CtdlLogPrintf(CTDL_DEBUG, "SSL_read got error %ld\n", errval);
461                         endtls();
462                         return (client_read_to
463                                 (&buf[len], bytes - len, timeout));
464                 }
465                 len += rlen;
466         }
467         return (1);
468 }
469
470
471 /*
472  * CtdlStartTLS() starts SSL/TLS encryption for the current session.  It
473  * must be supplied with pre-generated strings for responses of "ok," "no
474  * support for TLS," and "error" so that we can use this in any protocol.
475  */
476 void CtdlStartTLS(char *ok_response, char *nosup_response,
477                         char *error_response) {
478
479         int retval, bits, alg_bits;
480
481         if (!ssl_ctx) {
482                 CtdlLogPrintf(CTDL_CRIT, "SSL failed: no ssl_ctx exists?\n");
483                 if (nosup_response != NULL) cprintf("%s", nosup_response);
484                 return;
485         }
486         if (!(CC->ssl = SSL_new(ssl_ctx))) {
487                 CtdlLogPrintf(CTDL_CRIT, "SSL_new failed: %s\n",
488                                 ERR_reason_error_string(ERR_get_error()));
489                 if (error_response != NULL) cprintf("%s", error_response);
490                 return;
491         }
492         if (!(SSL_set_fd(CC->ssl, CC->client_socket))) {
493                 CtdlLogPrintf(CTDL_CRIT, "SSL_set_fd failed: %s\n",
494                         ERR_reason_error_string(ERR_get_error()));
495                 SSL_free(CC->ssl);
496                 CC->ssl = NULL;
497                 if (error_response != NULL) cprintf("%s", error_response);
498                 return;
499         }
500         if (ok_response != NULL) cprintf("%s", ok_response);
501         retval = SSL_accept(CC->ssl);
502         if (retval < 1) {
503                 /*
504                  * Can't notify the client of an error here; they will
505                  * discover the problem at the SSL layer and should
506                  * revert to unencrypted communications.
507                  */
508                 long errval;
509                 char error_string[128];
510
511                 errval = SSL_get_error(CC->ssl, retval);
512                 CtdlLogPrintf(CTDL_CRIT, "SSL_accept failed: retval=%d, errval=%ld, err=%s\n",
513                         retval,
514                         errval,
515                         ERR_error_string(errval, error_string)
516                 );
517                 SSL_free(CC->ssl);
518                 CC->ssl = NULL;
519                 return;
520         }
521         BIO_set_close(CC->ssl->rbio, BIO_NOCLOSE);
522         bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), &alg_bits);
523         CtdlLogPrintf(CTDL_INFO, "SSL/TLS using %s on %s (%d of %d bits)\n",
524                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
525                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
526                 bits, alg_bits);
527         CC->redirect_ssl = 1;
528 }
529
530
531 /*
532  * cmd_stls() starts SSL/TLS encryption for the current session
533  */
534 void cmd_stls(char *params)
535 {
536         char ok_response[SIZ];
537         char nosup_response[SIZ];
538         char error_response[SIZ];
539
540         unbuffer_output();
541
542         sprintf(ok_response,
543                 "%d Begin TLS negotiation now\n",
544                 CIT_OK);
545         sprintf(nosup_response,
546                 "%d TLS not supported here\n",
547                 ERROR + CMD_NOT_SUPPORTED);
548         sprintf(error_response,
549                 "%d TLS negotiation error\n",
550                 ERROR + INTERNAL_ERROR);
551
552         CtdlStartTLS(ok_response, nosup_response, error_response);
553 }
554
555
556 /*
557  * cmd_gtls() returns status info about the TLS connection
558  */
559 void cmd_gtls(char *params)
560 {
561         int bits, alg_bits;
562
563         if (!CC->ssl || !CC->redirect_ssl) {
564                 cprintf("%d Session is not encrypted.\n", ERROR);
565                 return;
566         }
567         bits =
568             SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl),
569                                 &alg_bits);
570         cprintf("%d %s|%s|%d|%d\n", CIT_OK,
571                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
572                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
573                 alg_bits, bits);
574 }
575
576
577 /*
578  * endtls() shuts down the TLS connection
579  *
580  * WARNING:  This may make your session vulnerable to a known plaintext
581  * attack in the current implmentation.
582  */
583 void endtls(void)
584 {
585         if (!CC->ssl) {
586                 CC->redirect_ssl = 0;
587                 return;
588         }
589
590         CtdlLogPrintf(CTDL_INFO, "Ending SSL/TLS\n");
591         SSL_shutdown(CC->ssl);
592         SSL_free(CC->ssl);
593         CC->ssl = NULL;
594         CC->redirect_ssl = 0;
595 }
596
597
598 /*
599  * ssl_lock() callback for OpenSSL mutex locks
600  */
601 void ssl_lock(int mode, int n, const char *file, int line)
602 {
603         if (mode & CRYPTO_LOCK)
604                 pthread_mutex_lock(SSLCritters[n]);
605         else
606                 pthread_mutex_unlock(SSLCritters[n]);
607 }
608 #endif                          /* HAVE_OPENSSL */