* During SSL initialization, create the "keys" directory if it does not
[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
40
41 #ifdef HAVE_OPENSSL
42 SSL_CTX *ssl_ctx;               /* SSL context */
43 pthread_mutex_t **SSLCritters;  /* Things needing locking */
44
45 static unsigned long id_callback(void)
46 {
47         return (unsigned long) pthread_self();
48 }
49
50  /*
51   * Set up the cert things on the server side. We do need both the
52   * private key (in key_file) and the cert (in cert_file).
53   * Both files may be identical.
54   *
55   * This function is taken from OpenSSL apps/s_cb.c
56   */
57
58 static int ctdl_install_certificate(SSL_CTX * ctx,
59                           const char *cert_file, const char *key_file)
60 {
61         if (cert_file != NULL) {
62                 if (SSL_CTX_use_certificate_file(ctx, cert_file,
63                                                  SSL_FILETYPE_PEM) <= 0) {
64                         lprintf(3, "unable to get certificate from '%s'",
65                                 cert_file);
66                         return (0);
67                 }
68                 if (key_file == NULL)
69                         key_file = cert_file;
70                 if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
71                                                 SSL_FILETYPE_PEM) <= 0) {
72                         lprintf(3, "unable to get private key from '%s'",
73                                 key_file);
74                         return (0);
75                 }
76                 /* Now we know that a key and cert have been set against
77                  * the SSL context */
78                 if (!SSL_CTX_check_private_key(ctx)) {
79                         lprintf(3,
80                                 "Private key does not match the certificate public key");
81                         return (0);
82                 }
83         }
84         return (1);
85 }
86
87
88 void init_ssl(void)
89 {
90         SSL_METHOD *ssl_method;
91         DH *dh;
92         RSA *rsa=NULL;
93         FILE *fp;
94
95         if (!access("/var/run/egd-pool", F_OK))
96                 RAND_egd("/var/run/egd-pool");
97
98         if (!RAND_status()) {
99                 lprintf(2,
100                         "PRNG not adequately seeded, won't do SSL/TLS\n");
101                 return;
102         }
103         SSLCritters =
104             mallok(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
105         if (!SSLCritters) {
106                 lprintf(1, "citserver: can't allocate memory!!\n");
107                 /* Nothing's been initialized, just die */
108                 exit(1);
109         } else {
110                 int a;
111
112                 for (a = 0; a < CRYPTO_num_locks(); a++) {
113                         SSLCritters[a] = mallok(sizeof(pthread_mutex_t));
114                         if (!SSLCritters[a]) {
115                                 lprintf(1,
116                                         "citserver: can't allocate memory!!\n");
117                                 /* Nothing's been initialized, just die */
118                                 exit(1);
119                         }
120                         pthread_mutex_init(SSLCritters[a], NULL);
121                 }
122         }
123
124         /*
125          * Initialize SSL transport layer
126          */
127         SSL_library_init();
128         SSL_load_error_strings();
129         ssl_method = SSLv23_server_method();
130         if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
131                 lprintf(2, "SSL_CTX_new failed: %s\n",
132                         ERR_reason_error_string(ERR_get_error()));
133                 return;
134         }
135         if (!(SSL_CTX_set_cipher_list(ssl_ctx, CIT_CIPHERS))) {
136                 lprintf(2, "SSL: No ciphers available\n");
137                 SSL_CTX_free(ssl_ctx);
138                 ssl_ctx = NULL;
139                 return;
140         }
141 #if 0
142 #if SSLEAY_VERSION_NUMBER >= 0x00906000L
143         SSL_CTX_set_mode(ssl_ctx, SSL_CTX_get_mode(ssl_ctx) |
144                          SSL_MODE_AUTO_RETRY);
145 #endif
146 #endif
147
148         CRYPTO_set_locking_callback(ssl_lock);
149         CRYPTO_set_id_callback(id_callback);
150
151         /* Load DH parameters into the context */
152         dh = DH_new();
153         if (!dh) {
154                 lprintf(2, "init_ssl() can't allocate a DH object: %s\n",
155                         ERR_reason_error_string(ERR_get_error()));
156                 SSL_CTX_free(ssl_ctx);
157                 ssl_ctx = NULL;
158                 return;
159         }
160         if (!(BN_hex2bn(&(dh->p), DH_P))) {
161                 lprintf(2, "init_ssl() can't assign DH_P: %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->g), DH_G))) {
168                 lprintf(2, "init_ssl() can't assign DH_G: %s\n",
169                         ERR_reason_error_string(ERR_get_error()));
170                 SSL_CTX_free(ssl_ctx);
171                 ssl_ctx = NULL;
172                 return;
173         }
174         dh->length = DH_L;
175         SSL_CTX_set_tmp_dh(ssl_ctx, dh);
176         DH_free(dh);
177
178         /* Get our certificates in order.
179          * First, create the key/cert directory if it's not there already...
180          */
181         mkdir(CTDL_CRYPTO_DIR, 0700);
182
183         /*
184          * Generate a key pair if we don't have one.
185          */
186         if (access(CTDL_KEY_PATH, R_OK) != 0) {
187                 lprintf(3, "Generating RSA key pair.\n");
188                 rsa = RSA_generate_key(1024,    /* modulus size */
189                                         65537,  /* exponent */
190                                         NULL,   /* no callback */
191                                         NULL);  /* no callback */
192                 if (rsa == NULL) {
193                         lprintf(2, "Key generation failed: %s\n",
194                                 ERR_reason_error_string(ERR_get_error()));
195                 }
196                 if (rsa != NULL) {
197                         fp = fopen(CTDL_KEY_PATH, "w");
198                         if (fp != NULL) {
199                                 chmod(CTDL_KEY_PATH, 0600);
200                                 if (PEM_write_RSAPrivateKey(fp, /* the file */
201                                                         rsa,    /* the key */
202                                                         NULL,   /* no enc */
203                                                         NULL,   /* no passphr */
204                                                         0,      /* no passphr */
205                                                         NULL,   /* no callbk */
206                                                         NULL    /* no callbk */
207                                 ) != 1) {
208                                         lprintf(2, "Cannot write key: %s\n",
209                                                 ERR_reason_error_string(ERR_get_error()));
210                                         unlink(CTDL_KEY_PATH);
211                                 }
212                                 fclose(fp);
213                         }
214                         RSA_free(rsa);
215                 }
216         }
217
218         /*
219          * Now try to bind to the key and certificate.
220          */
221         if (ctdl_install_certificate(ssl_ctx,
222                         CTDL_CER_PATH,
223                         CTDL_KEY_PATH) != 1)
224         {
225                 lprintf(2, "Cannot install certificate: %s\n",
226                                 ERR_reason_error_string(ERR_get_error()));
227         }
228
229         /* Finally let the server know we're here */
230         CtdlRegisterProtoHook(cmd_stls, "STLS", "Start SSL/TLS session");
231         CtdlRegisterProtoHook(cmd_gtls, "GTLS",
232                               "Get SSL/TLS session status");
233         CtdlRegisterSessionHook(endtls, EVT_STOP);
234 }
235
236
237 /*
238  * client_write_ssl() Send binary data to the client encrypted.
239  */
240 void client_write_ssl(char *buf, int nbytes)
241 {
242         int retval;
243         int nremain;
244         char junk[1];
245
246         nremain = nbytes;
247
248         while (nremain > 0) {
249                 if (SSL_want_write(CC->ssl)) {
250                         if ((SSL_read(CC->ssl, junk, 0)) < 1) {
251                                 lprintf(9, "SSL_read in client_write:\n");
252                                 ERR_print_errors_fp(stderr);
253                         }
254                 }
255                 retval =
256                     SSL_write(CC->ssl, &buf[nbytes - nremain], nremain);
257                 if (retval < 1) {
258                         long errval;
259
260                         errval = SSL_get_error(CC->ssl, retval);
261                         if (errval == SSL_ERROR_WANT_READ ||
262                             errval == SSL_ERROR_WANT_WRITE) {
263                                 sleep(1);
264                                 continue;
265                         }
266                         lprintf(9, "SSL_write got error %ld, ret %d\n", errval, retval);
267                         if (retval == -1)
268                                 lprintf(9, "errno is %d\n", errno);
269                         endtls();
270                         client_write(&buf[nbytes - nremain], nremain);
271                         return;
272                 }
273                 nremain -= retval;
274         }
275 }
276
277
278 /*
279  * client_read_ssl() - read data from the encrypted layer.
280  */
281 int client_read_ssl(char *buf, int bytes, int timeout)
282 {
283 #if 0
284         fd_set rfds;
285         struct timeval tv;
286         int retval;
287         int s;
288 #endif
289         int len, rlen;
290         char junk[1];
291
292         len = 0;
293         while (len < bytes) {
294 #if 0
295                 /*
296                  * This code is disabled because we don't need it when
297                  * using blocking reads (which we are). -IO
298                  */
299                 FD_ZERO(&rfds);
300                 s = BIO_get_fd(CC->ssl->rbio, NULL);
301                 FD_SET(s, &rfds);
302                 tv.tv_sec = timeout;
303                 tv.tv_usec = 0;
304
305                 retval = select(s + 1, &rfds, NULL, NULL, &tv);
306
307                 if (FD_ISSET(s, &rfds) == 0) {
308                         return (0);
309                 }
310
311 #endif
312                 if (SSL_want_read(CC->ssl)) {
313                         if ((SSL_write(CC->ssl, junk, 0)) < 1) {
314                                 lprintf(9, "SSL_write in client_read:\n");
315                                 ERR_print_errors_fp(stderr);
316                         }
317                 }
318                 rlen = SSL_read(CC->ssl, &buf[len], bytes - len);
319                 if (rlen < 1) {
320                         long errval;
321
322                         errval = SSL_get_error(CC->ssl, rlen);
323                         if (errval == SSL_ERROR_WANT_READ ||
324                             errval == SSL_ERROR_WANT_WRITE) {
325                                 sleep(1);
326                                 continue;
327                         }
328                         lprintf(9, "SSL_read got error %ld\n", errval);
329                         endtls();
330                         return (client_read_to
331                                 (&buf[len], bytes - len, timeout));
332                 }
333                 len += rlen;
334         }
335         return (1);
336 }
337
338
339 /*
340  * CtdlStartTLS() starts SSL/TLS encryption for the current session.  It
341  * must be supplied with pre-generated strings for responses of "ok," "no
342  * support for TLS," and "error" so that we can use this in any protocol.
343  */
344 void CtdlStartTLS(char *ok_response, char *nosup_response,
345                         char *error_response) {
346
347         int retval, bits, alg_bits;
348
349         if (!ssl_ctx) {
350                 cprintf("%s", nosup_response);
351                 return;
352         }
353         if (!(CC->ssl = SSL_new(ssl_ctx))) {
354                 lprintf(2, "SSL_new failed: %s\n",
355                                 ERR_reason_error_string(ERR_get_error()));
356                 cprintf("%s", error_response);
357                 return;
358         }
359         if (!(SSL_set_fd(CC->ssl, CC->client_socket))) {
360                 lprintf(2, "SSL_set_fd failed: %s\n",
361                         ERR_reason_error_string(ERR_get_error()));
362                 SSL_free(CC->ssl);
363                 CC->ssl = NULL;
364                 cprintf("%s", error_response);
365                 return;
366         }
367         cprintf("%s", ok_response);
368         retval = SSL_accept(CC->ssl);
369         if (retval < 1) {
370                 /*
371                  * Can't notify the client of an error here; they will
372                  * discover the problem at the SSL layer and should
373                  * revert to unencrypted communications.
374                  */
375                 long errval;
376
377                 errval = SSL_get_error(CC->ssl, retval);
378                 lprintf(2, "SSL_accept failed: %s\n",
379                         ERR_reason_error_string(ERR_get_error()));
380                 SSL_free(CC->ssl);
381                 CC->ssl = NULL;
382                 return;
383         }
384         BIO_set_close(CC->ssl->rbio, BIO_NOCLOSE);
385         bits =
386             SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl),
387                                 &alg_bits);
388         lprintf(3, "SSL/TLS using %s on %s (%d of %d bits)\n",
389                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
390                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
391                 bits, alg_bits);
392         CC->redirect_ssl = 1;
393 }
394
395
396 /*
397  * cmd_stls() starts SSL/TLS encryption for the current session
398  */
399 void cmd_stls(char *params)
400 {
401         char ok_response[SIZ];
402         char nosup_response[SIZ];
403         char error_response[SIZ];
404
405         sprintf(ok_response,
406                 "%d Begin TLS negotiation now\n",
407                 CIT_OK);
408         sprintf(nosup_response,
409                 "%d TLS not supported here\n",
410                 ERROR + CMD_NOT_SUPPORTED);
411         sprintf(error_response,
412                 "%d TLS negotiation error\n",
413                 ERROR + INTERNAL_ERROR);
414
415         CtdlStartTLS(ok_response, nosup_response, error_response);
416 }
417
418
419 /*
420  * cmd_gtls() returns status info about the TLS connection
421  */
422 void cmd_gtls(char *params)
423 {
424         int bits, alg_bits;
425
426         if (!CC->ssl || !CC->redirect_ssl) {
427                 cprintf("%d Session is not encrypted.\n", ERROR);
428                 return;
429         }
430         bits =
431             SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl),
432                                 &alg_bits);
433         cprintf("%d %s|%s|%d|%d\n", CIT_OK,
434                 SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)),
435                 SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)),
436                 alg_bits, bits);
437 }
438
439
440 /*
441  * endtls() shuts down the TLS connection
442  *
443  * WARNING:  This may make your session vulnerable to a known plaintext
444  * attack in the current implmentation.
445  */
446 void endtls(void)
447 {
448         lprintf(7, "Ending SSL/TLS\n");
449
450         if (!CC->ssl) {
451                 CC->redirect_ssl = 0;
452                 return;
453         }
454
455         SSL_shutdown(CC->ssl);
456         SSL_free(CC->ssl);
457         CC->ssl = NULL;
458         CC->redirect_ssl = 0;
459 }
460
461
462 /*
463  * ssl_lock() callback for OpenSSL mutex locks
464  */
465 void ssl_lock(int mode, int n, const char *file, int line)
466 {
467         if (mode & CRYPTO_LOCK)
468                 pthread_mutex_lock(SSLCritters[n]);
469         else
470                 pthread_mutex_unlock(SSLCritters[n]);
471 }
472 #endif                          /* HAVE_OPENSSL */