ssl.c - change style
[citadel.git] / webcit-ng / ssl.c
1 /*
2  * Functions in this module handle SSL encryption when WebCit is running
3  * as an HTTPS server.
4  *
5  * Copyright (c) 1996-2018 by the citadel.org team
6  *
7  * This program is open source software.  You can redistribute it and/or
8  * modify it under the terms of the GNU General Public License, version 3.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include "webcit.h"
17
18 SSL_CTX *ssl_ctx;               /* SSL context */
19 pthread_mutex_t **SSLCritters;  /* Things needing locking */
20 char *ssl_cipher_list = DEFAULT_SSL_CIPHER_LIST;
21 void ssl_lock(int mode, int n, const char *file, int line);
22
23
24 /*
25  * OpenSSL wants a callback function to identify the currently running thread.
26  * Since we are a pthreads program, we convert the output of pthread_self() to a long.
27  */
28 static unsigned long id_callback(void)
29 {
30         return (unsigned long) pthread_self();
31 }
32
33
34 /*
35  * OpenSSL wants a callback function to set and clear various types of locks.
36  * Since we are a pthreads program, we use mutexes.
37  */
38 void ssl_lock(int mode, int n, const char *file, int line)
39 {
40         if (mode & CRYPTO_LOCK) {
41                 pthread_mutex_lock(SSLCritters[n]);
42         }
43         else {
44                 pthread_mutex_unlock(SSLCritters[n]);
45         }
46 }
47
48
49 /*
50  * Generate a private key for SSL
51  */
52 void generate_key(char *keyfilename)
53 {
54         int ret = 0;
55         RSA *rsa = NULL;
56         BIGNUM *bne = NULL;
57         int bits = 2048;
58         unsigned long e = RSA_F4;
59         FILE *fp;
60
61         if (access(keyfilename, R_OK) == 0)
62         {
63                 return;
64         }
65
66         syslog(LOG_INFO, "crypto: generating RSA key pair");
67  
68         // generate rsa key
69         bne = BN_new();
70         ret = BN_set_word(bne,e);
71         if (ret != 1)
72         {
73                 goto free_all;
74         }
75  
76         rsa = RSA_new();
77         ret = RSA_generate_key_ex(rsa, bits, bne, NULL);
78         if (ret != 1)
79         {
80                 goto free_all;
81         }
82
83         // write the key file
84         fp = fopen(keyfilename, "w");
85         if (fp != NULL)
86         {
87                 chmod(keyfilename, 0600);
88                 if (PEM_write_RSAPrivateKey(fp, /* the file */
89                                         rsa,    /* the key */
90                                         NULL,   /* no enc */
91                                         NULL,   /* no passphr */
92                                         0,      /* no passphr */
93                                         NULL,   /* no callbk */
94                                         NULL    /* no callbk */
95                 ) != 1)
96                 {
97                         syslog(LOG_ERR, "crypto: cannot write key: %s", ERR_reason_error_string(ERR_get_error()));
98                         unlink(keyfilename);
99                 }
100                 fclose(fp);
101         }
102
103     // 4. free
104 free_all:
105     RSA_free(rsa);
106     BN_free(bne);
107 }
108
109
110 /*
111  * Initialize ssl engine, load certs and initialize openssl internals
112  */
113 void init_ssl(void)
114 {
115         const SSL_METHOD *ssl_method;
116         RSA *rsa=NULL;
117         X509_REQ *req = NULL;
118         X509 *cer = NULL;
119         EVP_PKEY *pk = NULL;
120         EVP_PKEY *req_pkey = NULL;
121         X509_NAME *name = NULL;
122         FILE *fp;
123         char buf[SIZ];
124         int rv = 0;
125
126         SSLCritters = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
127         if (!SSLCritters)
128         {
129                 syslog(LOG_ERR, "citserver: can't allocate memory!!");
130                 exit(1);
131         }
132         else
133         {
134                 int a;
135                 for (a = 0; a < CRYPTO_num_locks(); a++)
136                 {
137                         SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
138                         if (!SSLCritters[a])
139                         {
140                                 syslog(LOG_INFO, "citserver: can't allocate memory!!");
141                                 exit(1);
142                         }
143                         pthread_mutex_init(SSLCritters[a], NULL);
144                 }
145         }
146
147         /*
148          * Initialize SSL transport layer
149          */
150         SSL_library_init();
151         SSL_load_error_strings();
152         ssl_method = SSLv23_server_method();
153         if (!(ssl_ctx = SSL_CTX_new(ssl_method)))
154         {
155                 syslog(LOG_WARNING, "SSL_CTX_new failed: %s", ERR_reason_error_string(ERR_get_error()));
156                 return;
157         }
158
159         syslog(LOG_INFO, "Requesting cipher list: %s", ssl_cipher_list);
160         if (!(SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list)))
161         {
162                 syslog(LOG_WARNING, "SSL_CTX_set_cipher_list failed: %s", ERR_reason_error_string(ERR_get_error()));
163                 return;
164         }
165
166         CRYPTO_set_locking_callback(ssl_lock);
167         CRYPTO_set_id_callback(id_callback);
168
169         /*
170          * Get our certificates in order.
171          * First, create the key/cert directory if it's not there already...
172          */
173         mkdir(CTDL_CRYPTO_DIR, 0700);
174
175         /*
176          * If we still don't have a private key, generate one.
177          */
178         generate_key(CTDL_KEY_PATH);
179
180         /*
181          * If there is no certificate file on disk, we will be generating a self-signed certificate
182          * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
183          * the CSR in this step so that the next step may commence.
184          */
185         if ( (access(CTDL_CER_PATH, R_OK) != 0) && (access(CTDL_CSR_PATH, R_OK) != 0) )
186         {
187                 syslog(LOG_INFO, "Generating a certificate signing request.");
188
189                 /*
190                  * Read our key from the file.  No, we don't just keep this
191                  * in memory from the above key-generation function, because
192                  * there is the possibility that the key was already on disk
193                  * and we didn't just generate it now.
194                  */
195                 fp = fopen(CTDL_KEY_PATH, "r");
196                 if (fp)
197                 {
198                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
199                         fclose(fp);
200                 }
201
202                 if (rsa)
203                 {
204                         /* Create a public key from the private key */
205                         if (pk=EVP_PKEY_new(), pk != NULL)
206                         {
207                                 EVP_PKEY_assign_RSA(pk, rsa);
208                                 if (req = X509_REQ_new(), req != NULL)
209                                 {
210                                         const char *env;
211                                         /* Set the public key */
212                                         X509_REQ_set_pubkey(req, pk);
213                                         X509_REQ_set_version(req, 0L);
214                                         name = X509_REQ_get_subject_name(req);
215                                         X509_NAME_add_entry_by_txt(
216                                                 name, "O", MBSTRING_ASC,
217                                                 (unsigned char*)"Citadel Server",
218                                                 -1, -1, 0
219                                         );
220                                         X509_NAME_add_entry_by_txt(
221                                                 name, "OU", MBSTRING_ASC,
222                                                 (unsigned char*)"Default Certificate PLEASE CHANGE",
223                                                 -1, -1, 0
224                                         );
225                                         X509_NAME_add_entry_by_txt(
226                                                 name, "CN",
227                                                 MBSTRING_ASC, 
228                                                 (unsigned char*)"*",
229                                                 -1, -1, 0
230                                         );
231                                 
232                                         X509_REQ_set_subject_name(req, name);
233
234                                         /* Sign the CSR */
235                                         if (!X509_REQ_sign(req, pk, EVP_md5()))
236                                         {
237                                                 syslog(LOG_WARNING, "X509_REQ_sign(): error");
238                                         }
239                                         else
240                                         {
241                                                 /* Write it to disk. */ 
242                                                 fp = fopen(CTDL_CSR_PATH, "w");
243                                                 if (fp != NULL)
244                                                 {
245                                                         chmod(CTDL_CSR_PATH, 0600);
246                                                         PEM_write_X509_REQ(fp, req);
247                                                         fclose(fp);
248                                                 }
249                                                 else
250                                                 {
251                                                         syslog(LOG_WARNING, "Cannot write key: %s", CTDL_CSR_PATH);
252                                                         exit(1);
253                                                 }
254                                         }
255                                         X509_REQ_free(req);
256                                 }
257                         }
258                         RSA_free(rsa);
259                 }
260                 else
261                 {
262                         syslog(LOG_WARNING, "Unable to read private key.");
263                 }
264         }
265
266         /*
267          * Generate a self-signed certificate if we don't have one.
268          */
269         if (access(CTDL_CER_PATH, R_OK) != 0)
270         {
271                 syslog(LOG_INFO, "Generating a self-signed certificate.");
272
273                 /* Same deal as before: always read the key from disk because
274                  * it may or may not have just been generated.
275                  */
276                 fp = fopen(CTDL_KEY_PATH, "r");
277                 if (fp)
278                 {
279                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
280                         fclose(fp);
281                 }
282
283                 /* This also holds true for the CSR. */
284                 req = NULL;
285                 cer = NULL;
286                 pk = NULL;
287                 if (rsa)
288                 {
289                         if (pk=EVP_PKEY_new(), pk != NULL)
290                         {
291                                 EVP_PKEY_assign_RSA(pk, rsa);
292                         }
293
294                         fp = fopen(CTDL_CSR_PATH, "r");
295                         if (fp)
296                         {
297                                 req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
298                                 fclose(fp);
299                         }
300
301                         if (req)
302                         {
303                                 if (cer = X509_new(), cer != NULL)
304                                 {
305                                         ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
306                                         X509_set_issuer_name(cer, X509_REQ_get_subject_name(req));
307                                         X509_set_subject_name(cer, X509_REQ_get_subject_name(req));
308                                         X509_gmtime_adj(X509_get_notBefore(cer), 0);
309                                         X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
310
311                                         req_pkey = X509_REQ_get_pubkey(req);
312                                         X509_set_pubkey(cer, req_pkey);
313                                         EVP_PKEY_free(req_pkey);
314                                         
315                                         /* Sign the cert */
316                                         if (!X509_sign(cer, pk, EVP_md5()))
317                                         {
318                                                 syslog(LOG_WARNING, "X509_sign(): error");
319                                         }
320                                         else
321                                         {       /* Write it to disk. */
322                                                 fp = fopen(CTDL_CER_PATH, "w");
323                                                 if (fp != NULL)
324                                                 {
325                                                         chmod(CTDL_CER_PATH, 0600);
326                                                         PEM_write_X509(fp, cer);
327                                                         fclose(fp);
328                                                 }
329                                                 else
330                                                 {
331                                                         syslog(LOG_WARNING, "Cannot write key: %s", CTDL_CER_PATH);
332                                                         exit(1);
333                                                 }
334                                         }
335                                         X509_free(cer);
336                                 }
337                         }
338                         RSA_free(rsa);
339                 }
340         }
341
342         /*
343          * Now try to bind to the key and certificate.
344          * Note that we use SSL_CTX_use_certificate_chain_file() which allows
345          * the certificate file to contain intermediate certificates.
346          */
347         SSL_CTX_use_certificate_chain_file(ssl_ctx, CTDL_CER_PATH);
348         SSL_CTX_use_PrivateKey_file(ssl_ctx, CTDL_KEY_PATH, SSL_FILETYPE_PEM);
349         if ( !SSL_CTX_check_private_key(ssl_ctx) )
350         {
351                 syslog(LOG_WARNING, "Cannot install certificate: %s", ERR_reason_error_string(ERR_get_error()));
352         }
353         
354 }
355
356
357 /*
358  * starts SSL/TLS encryption for the current session.
359  */
360 void starttls(struct client_handle *ch)
361 {
362         int retval, bits, alg_bits;
363
364         if (!ssl_ctx)
365         {
366                 return;
367         }
368         if (!(ch->ssl_handle = SSL_new(ssl_ctx)))
369         {
370                 syslog(LOG_WARNING, "SSL_new failed: %s", ERR_reason_error_string(ERR_get_error()));
371                 return;
372         }
373         if (!(SSL_set_fd(ch->ssl_handle, ch->sock)))
374         {
375                 syslog(LOG_WARNING, "SSL_set_fd failed: %s", ERR_reason_error_string(ERR_get_error()));
376                 SSL_free(ch->ssl_handle);
377                 return;
378         }
379         retval = SSL_accept(ch->ssl_handle);
380         if (retval < 1)
381         {
382                 long errval;
383                 const char *ssl_error_reason = NULL;
384
385                 errval = SSL_get_error(ch->ssl_handle, retval);
386                 ssl_error_reason = ERR_reason_error_string(ERR_get_error());
387                 if (ssl_error_reason == NULL)
388                 {
389                         syslog(LOG_WARNING, "SSL_accept failed: errval=%ld, retval=%d %s", errval, retval, strerror(errval));
390                 }
391                 else
392                 {
393                         syslog(LOG_WARNING, "SSL_accept failed: %s\n", ssl_error_reason);
394                 }
395                 sleep(1);
396                 retval = SSL_accept(ch->ssl_handle);
397         }
398         if (retval < 1)
399         {
400                 long errval;
401                 const char *ssl_error_reason = NULL;
402
403                 errval = SSL_get_error(ch->ssl_handle, retval);
404                 ssl_error_reason = ERR_reason_error_string(ERR_get_error());
405                 if (ssl_error_reason == NULL)
406                 {
407                         syslog(LOG_WARNING, "SSL_accept failed: errval=%ld, retval=%d (%s)", errval, retval, strerror(errval));
408                 }
409                 else
410                 {
411                         syslog(LOG_WARNING, "SSL_accept failed: %s", ssl_error_reason);
412                 }
413                 SSL_free(ch->ssl_handle);
414                 ch->ssl_handle = NULL;
415                 return;
416         }
417         else
418         {
419                 syslog(LOG_INFO, "SSL_accept success");
420         }
421         bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(ch->ssl_handle), &alg_bits);
422         syslog(LOG_INFO, "SSL/TLS using %s on %s (%d of %d bits)",
423                 SSL_CIPHER_get_name(SSL_get_current_cipher(ch->ssl_handle)),
424                 SSL_CIPHER_get_version(SSL_get_current_cipher(ch->ssl_handle)),
425                 bits, alg_bits);
426
427         syslog(LOG_INFO, "SSL started");
428 }
429
430
431 /*
432  * shuts down the TLS connection
433  */
434 void endtls(struct client_handle *ch)
435 {
436         syslog(LOG_INFO, "Ending SSL/TLS");
437         if (ch->ssl_handle != NULL)
438         {
439                 SSL_shutdown(ch->ssl_handle);
440                 SSL_get_SSL_CTX(ch->ssl_handle);
441                 SSL_free(ch->ssl_handle);
442         }
443         ch->ssl_handle = NULL;
444 }
445
446
447 /*
448  * Send binary data to the client encrypted.
449  */
450 int client_write_ssl(struct client_handle *ch, char *buf, int nbytes)
451 {
452         int retval;
453         int nremain;
454         char junk[1];
455
456         if (ch->ssl_handle == NULL) return(-1);
457
458         nremain = nbytes;
459         while (nremain > 0)
460         {
461                 if (SSL_want_write(ch->ssl_handle))
462                 {
463                         if ((SSL_read(ch->ssl_handle, junk, 0)) < 1)
464                         {
465                                 syslog(LOG_WARNING, "SSL_read in client_write: %s", ERR_reason_error_string(ERR_get_error()));
466                         }
467                 }
468                 retval = SSL_write(ch->ssl_handle, &buf[nbytes - nremain], nremain);
469                 if (retval < 1)
470                 {
471                         long errval;
472
473                         errval = SSL_get_error(ch->ssl_handle, retval);
474                         if (errval == SSL_ERROR_WANT_READ || errval == SSL_ERROR_WANT_WRITE)
475                         {
476                                 sleep(1);
477                                 continue;
478                         }
479                         syslog(LOG_WARNING, "SSL_write got error %ld, ret %d", errval, retval);
480                         if (retval == -1)
481                         {
482                                 syslog(LOG_WARNING, "errno is %d", errno);
483                                 endtls(ch);
484                         }
485                         return -1;
486                 }
487                 nremain -= retval;
488         }
489         return 0;
490 }
491
492
493 /*
494  * read data from the encrypted layer.
495  */
496 int client_read_ssl(struct client_handle *ch, char *buf, int nbytes)
497 {
498         int bytes_read = 0;
499         int rlen = 0;
500         char junk[1];
501
502         if (ch->ssl_handle == NULL) return(-1);
503
504         while (bytes_read < nbytes)
505         {
506                 if (SSL_want_read(ch->ssl_handle))
507                 {
508                         if ((SSL_write(ch->ssl_handle, junk, 0)) < 1)
509                         {
510                                 syslog(LOG_WARNING, "SSL_write in client_read");
511                         }
512                 }
513                 rlen = SSL_read(ch->ssl_handle, &buf[bytes_read], nbytes-bytes_read);
514                 if (rlen < 1)
515                 {
516                         long errval;
517                         errval = SSL_get_error(ch->ssl_handle, rlen);
518                         if (errval == SSL_ERROR_WANT_READ || errval == SSL_ERROR_WANT_WRITE)
519                         {
520                                 sleep(1);
521                                 continue;
522                         }
523                         syslog(LOG_WARNING, "SSL_read error %ld", errval);
524                         endtls(ch);
525                         return (-1);
526                 }
527                 bytes_read += rlen;
528         }
529         return(bytes_read);
530 }