Moved to new module init structure.
[citadel.git] / citadel / 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                 lprintf(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                 lprintf(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                                 lprintf(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                 lprintf(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                 lprintf(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                 lprintf(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                 lprintf(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                 lprintf(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                 lprintf(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                         lprintf(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                                         lprintf(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          * Generate a CSR if we don't have one.
202          */
203         if (access(file_crpt_file_csr, R_OK) != 0) {
204                 lprintf(CTDL_INFO, "Generating a certificate signing request.\n");
205
206                 /*
207                  * Read our key from the file.  No, we don't just keep this
208                  * in memory from the above key-generation function, because
209                  * there is the possibility that the key was already on disk
210                  * and we didn't just generate it now.
211                  */
212                 fp = fopen(file_crpt_file_key, "r");
213                 if (fp) {
214                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
215                         fclose(fp);
216                 }
217
218                 if (rsa) {
219
220                         /* Create a public key from the private key */
221                         if (pk=EVP_PKEY_new(), pk != NULL) {
222                                 EVP_PKEY_assign_RSA(pk, rsa);
223                                 if (req = X509_REQ_new(), req != NULL) {
224
225                                         /* Set the public key */
226                                         X509_REQ_set_pubkey(req, pk);
227                                         X509_REQ_set_version(req, 0L);
228
229                                         name = X509_REQ_get_subject_name(req);
230
231                                         /* Tell it who we are */
232
233                                         /*
234                                         X509_NAME_add_entry_by_txt(name, "C",
235                                                 MBSTRING_ASC, "US", -1, -1, 0);
236
237                                         X509_NAME_add_entry_by_txt(name, "ST",
238                                                 MBSTRING_ASC, "New York", -1, -1, 0);
239
240                                         X509_NAME_add_entry_by_txt(name, "L",
241                                                 MBSTRING_ASC, "Mount Kisco", -1, -1, 0);
242                                         */
243
244                                         X509_NAME_add_entry_by_txt(name, "O",
245                                                 MBSTRING_ASC, config.c_humannode, -1, -1, 0);
246
247                                         X509_NAME_add_entry_by_txt(name, "OU",
248                                                 MBSTRING_ASC, "Citadel server", -1, -1, 0);
249
250                                         /* X509_NAME_add_entry_by_txt(name, "CN",
251                                                 MBSTRING_ASC, config.c_fqdn, -1, -1, 0);
252                                         */
253
254                                         X509_NAME_add_entry_by_txt(name, "CN",
255                                                 MBSTRING_ASC, "*", -1, -1, 0);
256                                 
257                                         X509_REQ_set_subject_name(req, name);
258
259                                         /* Sign the CSR */
260                                         if (!X509_REQ_sign(req, pk, EVP_md5())) {
261                                                 lprintf(CTDL_CRIT, "X509_REQ_sign(): error\n");
262                                         }
263                                         else {
264                                                 /* Write it to disk. */ 
265                                                 fp = fopen(file_crpt_file_csr, "w");
266                                                 if (fp != NULL) {
267                                                         chmod(file_crpt_file_csr, 0600);
268                                                         PEM_write_X509_REQ(fp, req);
269                                                         fclose(fp);
270                                                 }
271                                         }
272
273                                         X509_REQ_free(req);
274                                 }
275                         }
276
277                         RSA_free(rsa);
278                 }
279
280                 else {
281                         lprintf(CTDL_CRIT, "Unable to read private key.\n");
282                 }
283         }
284
285
286
287         /*
288          * Generate a self-signed certificate if we don't have one.
289          */
290         if (access(file_crpt_file_cer, R_OK) != 0) {
291                 lprintf(CTDL_INFO, "Generating a self-signed certificate.\n");
292
293                 /* Same deal as before: always read the key from disk because
294                  * it may or may not have just been generated.
295                  */
296                 fp = fopen(file_crpt_file_key, "r");
297                 if (fp) {
298                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
299                         fclose(fp);
300                 }
301
302                 /* This also holds true for the CSR. */
303                 req = NULL;
304                 cer = NULL;
305                 pk = NULL;
306                 if (rsa) {
307                         if (pk=EVP_PKEY_new(), pk != NULL) {
308                                 EVP_PKEY_assign_RSA(pk, rsa);
309                         }
310
311                         fp = fopen(file_crpt_file_csr, "r");
312                         if (fp) {
313                                 req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
314                                 fclose(fp);
315                         }
316
317                         if (req) {
318                                 if (cer = X509_new(), cer != NULL) {
319
320                                         ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
321                                         X509_set_issuer_name(cer, req->req_info->subject);
322                                         X509_set_subject_name(cer, req->req_info->subject);
323                                         X509_gmtime_adj(X509_get_notBefore(cer),0);
324                                         X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
325                                         req_pkey = X509_REQ_get_pubkey(req);
326                                         X509_set_pubkey(cer, req_pkey);
327                                         EVP_PKEY_free(req_pkey);
328                                         
329                                         /* Sign the cert */
330                                         if (!X509_sign(cer, pk, EVP_md5())) {
331                                                 lprintf(CTDL_CRIT, "X509_sign(): error\n");
332                                         }
333                                         else {
334                                                 /* Write it to disk. */ 
335                                                 fp = fopen(file_crpt_file_cer, "w");
336                                                 if (fp != NULL) {
337                                                         chmod(file_crpt_file_cer, 0600);
338                                                         PEM_write_X509(fp, cer);
339                                                         fclose(fp);
340                                                 }
341                                         }
342                                         X509_free(cer);
343                                 }
344                         }
345
346                         RSA_free(rsa);
347                 }
348         }
349
350
351         /*
352          * Now try to bind to the key and certificate.
353          */
354         SSL_CTX_use_certificate_chain_file(ssl_ctx, file_crpt_file_cer);
355         SSL_CTX_use_PrivateKey_file(ssl_ctx, file_crpt_file_key, SSL_FILETYPE_PEM);
356         if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
357                 lprintf(CTDL_CRIT, "Cannot install certificate: %s\n",
358                                 ERR_reason_error_string(ERR_get_error()));
359         }
360
361         /* Finally let the server know we're here */
362         CtdlRegisterProtoHook(cmd_stls, "STLS", "Start SSL/TLS session");
363         CtdlRegisterProtoHook(cmd_gtls, "GTLS",
364                               "Get SSL/TLS session status");
365         CtdlRegisterSessionHook(endtls, EVT_STOP);
366 }
367
368
369 /*
370  * client_write_ssl() Send binary data to the client encrypted.
371  */
372 void client_write_ssl(char *buf, int nbytes)
373 {
374         int retval;
375         int nremain;
376         char junk[1];
377
378         nremain = nbytes;
379
380         while (nremain > 0) {
381                 if (SSL_want_write(CC->ssl)) {
382                         if ((SSL_read(CC->ssl, junk, 0)) < 1) {
383                                 lprintf(CTDL_DEBUG, "SSL_read in client_write: %s\n", ERR_reason_error_string(ERR_get_error()));
384                         }
385                 }
386                 retval =
387                     SSL_write(CC->ssl, &buf[nbytes - nremain], nremain);
388                 if (retval < 1) {
389                         long errval;
390
391                         errval = SSL_get_error(CC->ssl, retval);
392                         if (errval == SSL_ERROR_WANT_READ ||
393                             errval == SSL_ERROR_WANT_WRITE) {
394                                 sleep(1);
395                                 continue;
396                         }
397                         lprintf(CTDL_DEBUG, "SSL_write got error %ld, ret %d\n", errval, retval);
398                         if (retval == -1)
399                                 lprintf(CTDL_DEBUG, "errno is %d\n", errno);
400                         endtls();
401                         client_write(&buf[nbytes - nremain], nremain);
402                         return;
403                 }
404                 nremain -= retval;
405         }
406 }
407
408
409 /*
410  * client_read_ssl() - read data from the encrypted layer.
411  */
412 int client_read_ssl(char *buf, int bytes, int timeout)
413 {
414 #if 0
415         fd_set rfds;
416         struct timeval tv;
417         int retval;
418         int s;
419 #endif
420         int len, rlen;
421         char junk[1];
422
423         len = 0;
424         while (len < bytes) {
425 #if 0
426                 /*
427                  * This code is disabled because we don't need it when
428                  * using blocking reads (which we are). -IO
429                  */
430                 FD_ZERO(&rfds);
431                 s = BIO_get_fd(CC->ssl->rbio, NULL);
432                 FD_SET(s, &rfds);
433                 tv.tv_sec = timeout;
434                 tv.tv_usec = 0;
435
436                 retval = select(s + 1, &rfds, NULL, NULL, &tv);
437
438                 if (FD_ISSET(s, &rfds) == 0) {
439                         return (0);
440                 }
441
442 #endif
443                 if (SSL_want_read(CC->ssl)) {
444                         if ((SSL_write(CC->ssl, junk, 0)) < 1) {
445                                 lprintf(CTDL_DEBUG, "SSL_write in client_read: %s\n", ERR_reason_error_string(ERR_get_error()));
446                         }
447                 }
448                 rlen = SSL_read(CC->ssl, &buf[len], bytes - len);
449                 if (rlen < 1) {
450                         long errval;
451
452                         errval = SSL_get_error(CC->ssl, rlen);
453                         if (errval == SSL_ERROR_WANT_READ ||
454                             errval == SSL_ERROR_WANT_WRITE) {
455                                 sleep(1);
456                                 continue;
457                         }
458                         lprintf(CTDL_DEBUG, "SSL_read got error %ld\n", errval);
459                         endtls();
460                         return (client_read_to
461                                 (&buf[len], bytes - len, timeout));
462                 }
463                 len += rlen;
464         }
465         return (1);
466 }
467
468
469 /*
470  * CtdlStartTLS() starts SSL/TLS encryption for the current session.  It
471  * must be supplied with pre-generated strings for responses of "ok," "no
472  * support for TLS," and "error" so that we can use this in any protocol.
473  */
474 void CtdlStartTLS(char *ok_response, char *nosup_response,
475                         char *error_response) {
476
477         int retval, bits, alg_bits;
478
479         if (!ssl_ctx) {
480                 lprintf(CTDL_CRIT, "SSL failed: no ssl_ctx exists?\n");
481                 if (nosup_response != NULL) cprintf("%s", nosup_response);
482                 return;
483         }
484         if (!(CC->ssl = SSL_new(ssl_ctx))) {
485                 lprintf(CTDL_CRIT, "SSL_new failed: %s\n",
486                                 ERR_reason_error_string(ERR_get_error()));
487                 if (error_response != NULL) cprintf("%s", error_response);
488                 return;
489         }
490         if (!(SSL_set_fd(CC->ssl, CC->client_socket))) {
491                 lprintf(CTDL_CRIT, "SSL_set_fd failed: %s\n",
492                         ERR_reason_error_string(ERR_get_error()));
493                 SSL_free(CC->ssl);
494                 CC->ssl = NULL;
495                 if (error_response != NULL) cprintf("%s", error_response);
496                 return;
497         }
498         if (ok_response != NULL) cprintf("%s", ok_response);
499         retval = SSL_accept(CC->ssl);
500         if (retval < 1) {
501                 /*
502                  * Can't notify the client of an error here; they will
503                  * discover the problem at the SSL layer and should
504                  * revert to unencrypted communications.
505                  */
506                 long errval;
507                 char error_string[128];
508
509                 errval = SSL_get_error(CC->ssl, retval);
510                 lprintf(CTDL_CRIT, "SSL_accept failed: retval=%d, errval=%ld, err=%s\n",
511                         retval,
512                         errval,
513                         ERR_error_string(errval, error_string)
514                 );
515                 SSL_free(CC->ssl);
516                 CC->ssl = NULL;
517                 return;
518         }
519         BIO_set_close(CC->ssl->rbio, BIO_NOCLOSE);
520         bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), &alg_bits);
521         lprintf(CTDL_INFO, "SSL/TLS using %s on %s (%d of %d bits)\n",
522                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
523                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
524                 bits, alg_bits);
525         CC->redirect_ssl = 1;
526 }
527
528
529 /*
530  * cmd_stls() starts SSL/TLS encryption for the current session
531  */
532 void cmd_stls(char *params)
533 {
534         char ok_response[SIZ];
535         char nosup_response[SIZ];
536         char error_response[SIZ];
537
538         unbuffer_output();
539
540         sprintf(ok_response,
541                 "%d Begin TLS negotiation now\n",
542                 CIT_OK);
543         sprintf(nosup_response,
544                 "%d TLS not supported here\n",
545                 ERROR + CMD_NOT_SUPPORTED);
546         sprintf(error_response,
547                 "%d TLS negotiation error\n",
548                 ERROR + INTERNAL_ERROR);
549
550         CtdlStartTLS(ok_response, nosup_response, error_response);
551 }
552
553
554 /*
555  * cmd_gtls() returns status info about the TLS connection
556  */
557 void cmd_gtls(char *params)
558 {
559         int bits, alg_bits;
560
561         if (!CC->ssl || !CC->redirect_ssl) {
562                 cprintf("%d Session is not encrypted.\n", ERROR);
563                 return;
564         }
565         bits =
566             SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl),
567                                 &alg_bits);
568         cprintf("%d %s|%s|%d|%d\n", CIT_OK,
569                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
570                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
571                 alg_bits, bits);
572 }
573
574
575 /*
576  * endtls() shuts down the TLS connection
577  *
578  * WARNING:  This may make your session vulnerable to a known plaintext
579  * attack in the current implmentation.
580  */
581 void endtls(void)
582 {
583         if (!CC->ssl) {
584                 CC->redirect_ssl = 0;
585                 return;
586         }
587
588         lprintf(CTDL_INFO, "Ending SSL/TLS\n");
589         SSL_shutdown(CC->ssl);
590         SSL_free(CC->ssl);
591         CC->ssl = NULL;
592         CC->redirect_ssl = 0;
593 }
594
595
596 /*
597  * ssl_lock() callback for OpenSSL mutex locks
598  */
599 void ssl_lock(int mode, int n, const char *file, int line)
600 {
601         if (mode & CRYPTO_LOCK)
602                 pthread_mutex_lock(SSLCritters[n]);
603         else
604                 pthread_mutex_unlock(SSLCritters[n]);
605 }
606 #endif                          /* HAVE_OPENSSL */