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