MAKE WEBCIT GREAT AGAIN!
[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                 return;
63         }
64
65         syslog(LOG_INFO, "crypto: generating RSA key pair");
66  
67         // generate rsa key
68         bne = BN_new();
69         ret = BN_set_word(bne,e);
70         if (ret != 1) {
71                 goto free_all;
72         }
73  
74         rsa = RSA_new();
75         ret = RSA_generate_key_ex(rsa, bits, bne, NULL);
76         if (ret != 1) {
77                 goto free_all;
78         }
79
80         // write the key file
81         fp = fopen(keyfilename, "w");
82         if (fp != NULL) {
83                 chmod(keyfilename, 0600);
84                 if (PEM_write_RSAPrivateKey(fp, /* the file */
85                                         rsa,    /* the key */
86                                         NULL,   /* no enc */
87                                         NULL,   /* no passphr */
88                                         0,      /* no passphr */
89                                         NULL,   /* no callbk */
90                                         NULL    /* no callbk */
91                 ) != 1) {
92                         syslog(LOG_ERR, "crypto: cannot write key: %s", ERR_reason_error_string(ERR_get_error()));
93                         unlink(keyfilename);
94                 }
95                 fclose(fp);
96         }
97
98     // 4. free
99 free_all:
100     RSA_free(rsa);
101     BN_free(bne);
102 }
103
104
105 /*
106  * Initialize ssl engine, load certs and initialize openssl internals
107  */
108 void init_ssl(void)
109 {
110         const SSL_METHOD *ssl_method;
111         RSA *rsa=NULL;
112         X509_REQ *req = NULL;
113         X509 *cer = NULL;
114         EVP_PKEY *pk = NULL;
115         EVP_PKEY *req_pkey = NULL;
116         X509_NAME *name = NULL;
117         FILE *fp;
118         char buf[SIZ];
119         int rv = 0;
120
121         SSLCritters = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
122         if (!SSLCritters) {
123                 syslog(LOG_ERR, "citserver: can't allocate memory!!");
124                 exit(1);
125         } else {
126                 int a;
127
128                 for (a = 0; a < CRYPTO_num_locks(); a++) {
129                         SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
130                         if (!SSLCritters[a]) {
131                                 syslog(LOG_INFO, "citserver: can't allocate memory!!");
132                                 exit(1);
133                         }
134                         pthread_mutex_init(SSLCritters[a], NULL);
135                 }
136         }
137
138         /*
139          * Initialize SSL transport layer
140          */
141         SSL_library_init();
142         SSL_load_error_strings();
143         ssl_method = SSLv23_server_method();
144         if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
145                 syslog(LOG_WARNING, "SSL_CTX_new failed: %s", ERR_reason_error_string(ERR_get_error()));
146                 return;
147         }
148
149         syslog(LOG_INFO, "Requesting cipher list: %s", ssl_cipher_list);
150         if (!(SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list))) {
151                 syslog(LOG_WARNING, "SSL_CTX_set_cipher_list failed: %s", ERR_reason_error_string(ERR_get_error()));
152                 return;
153         }
154
155         CRYPTO_set_locking_callback(ssl_lock);
156         CRYPTO_set_id_callback(id_callback);
157
158         /*
159          * Get our certificates in order.
160          * First, create the key/cert directory if it's not there already...
161          */
162         mkdir(CTDL_CRYPTO_DIR, 0700);
163
164         /*
165          * If we still don't have a private key, generate one.
166          */
167         generate_key(CTDL_KEY_PATH);
168
169         /*
170          * If there is no certificate file on disk, we will be generating a self-signed certificate
171          * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
172          * the CSR in this step so that the next step may commence.
173          */
174         if ( (access(CTDL_CER_PATH, R_OK) != 0) && (access(CTDL_CSR_PATH, R_OK) != 0) ) {
175                 syslog(LOG_INFO, "Generating a certificate signing request.");
176
177                 /*
178                  * Read our key from the file.  No, we don't just keep this
179                  * in memory from the above key-generation function, because
180                  * there is the possibility that the key was already on disk
181                  * and we didn't just generate it now.
182                  */
183                 fp = fopen(CTDL_KEY_PATH, "r");
184                 if (fp) {
185                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
186                         fclose(fp);
187                 }
188
189                 if (rsa) {
190
191                         /* Create a public key from the private key */
192                         if (pk=EVP_PKEY_new(), pk != NULL) {
193                                 EVP_PKEY_assign_RSA(pk, rsa);
194                                 if (req = X509_REQ_new(), req != NULL) {
195                                         const char *env;
196                                         /* Set the public key */
197                                         X509_REQ_set_pubkey(req, pk);
198                                         X509_REQ_set_version(req, 0L);
199                                         name = X509_REQ_get_subject_name(req);
200                                         X509_NAME_add_entry_by_txt(
201                                                 name, "O", MBSTRING_ASC,
202                                                 (unsigned char*)"Citadel Server",
203                                                 -1, -1, 0
204                                         );
205                                         X509_NAME_add_entry_by_txt(
206                                                 name, "OU", MBSTRING_ASC,
207                                                 (unsigned char*)"Default Certificate PLEASE CHANGE",
208                                                 -1, -1, 0
209                                         );
210                                         X509_NAME_add_entry_by_txt(
211                                                 name, "CN",
212                                                 MBSTRING_ASC, 
213                                                 (unsigned char*)"*",
214                                                 -1, -1, 0
215                                         );
216                                 
217                                         X509_REQ_set_subject_name(req, name);
218
219                                         /* Sign the CSR */
220                                         if (!X509_REQ_sign(req, pk, EVP_md5())) {
221                                                 syslog(LOG_WARNING, "X509_REQ_sign(): error");
222                                         }
223                                         else {
224                                                 /* Write it to disk. */ 
225                                                 fp = fopen(CTDL_CSR_PATH, "w");
226                                                 if (fp != NULL) {
227                                                         chmod(CTDL_CSR_PATH, 0600);
228                                                         PEM_write_X509_REQ(fp, req);
229                                                         fclose(fp);
230                                                 }
231                                                 else {
232                                                         syslog(LOG_WARNING, "Cannot write key: %s", CTDL_CSR_PATH);
233                                                         exit(1);
234                                                 }
235                                         }
236
237                                         X509_REQ_free(req);
238                                 }
239                         }
240
241                         RSA_free(rsa);
242                 }
243
244                 else {
245                         syslog(LOG_WARNING, "Unable to read private key.");
246                 }
247         }
248
249
250         /*
251          * Generate a self-signed certificate if we don't have one.
252          */
253         if (access(CTDL_CER_PATH, R_OK) != 0) {
254                 syslog(LOG_INFO, "Generating a self-signed certificate.");
255
256                 /* Same deal as before: always read the key from disk because
257                  * it may or may not have just been generated.
258                  */
259                 fp = fopen(CTDL_KEY_PATH, "r");
260                 if (fp) {
261                         rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
262                         fclose(fp);
263                 }
264
265                 /* This also holds true for the CSR. */
266                 req = NULL;
267                 cer = NULL;
268                 pk = NULL;
269                 if (rsa) {
270                         if (pk=EVP_PKEY_new(), pk != NULL) {
271                                 EVP_PKEY_assign_RSA(pk, rsa);
272                         }
273
274                         fp = fopen(CTDL_CSR_PATH, "r");
275                         if (fp) {
276                                 req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
277                                 fclose(fp);
278                         }
279
280                         if (req) {
281                                 if (cer = X509_new(), cer != NULL) {
282
283                                         ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
284                                         X509_set_issuer_name(cer, X509_REQ_get_subject_name(req));
285                                         X509_set_subject_name(cer, X509_REQ_get_subject_name(req));
286                                         X509_gmtime_adj(X509_get_notBefore(cer), 0);
287                                         X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
288
289                                         req_pkey = X509_REQ_get_pubkey(req);
290                                         X509_set_pubkey(cer, req_pkey);
291                                         EVP_PKEY_free(req_pkey);
292                                         
293                                         /* Sign the cert */
294                                         if (!X509_sign(cer, pk, EVP_md5())) {
295                                                 syslog(LOG_WARNING, "X509_sign(): error");
296                                         }
297                                         else {
298                                                 /* Write it to disk. */ 
299                                                 fp = fopen(CTDL_CER_PATH, "w");
300                                                 if (fp != NULL) {
301                                                         chmod(CTDL_CER_PATH, 0600);
302                                                         PEM_write_X509(fp, cer);
303                                                         fclose(fp);
304                                                 }
305                                                 else {
306                                                         syslog(LOG_WARNING, "Cannot write key: %s", CTDL_CER_PATH);
307                                                         exit(1);
308                                                 }
309                                         }
310                                         X509_free(cer);
311                                 }
312                         }
313
314                         RSA_free(rsa);
315                 }
316         }
317
318         /*
319          * Now try to bind to the key and certificate.
320          * Note that we use SSL_CTX_use_certificate_chain_file() which allows
321          * the certificate file to contain intermediate certificates.
322          */
323         SSL_CTX_use_certificate_chain_file(ssl_ctx, CTDL_CER_PATH);
324         SSL_CTX_use_PrivateKey_file(ssl_ctx, CTDL_KEY_PATH, SSL_FILETYPE_PEM);
325         if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
326                 syslog(LOG_WARNING, "Cannot install certificate: %s", ERR_reason_error_string(ERR_get_error()));
327         }
328         
329 }
330
331
332 /*
333  * starts SSL/TLS encryption for the current session.
334  */
335 void starttls(struct client_handle *ch) {
336         int retval, bits, alg_bits;
337
338         if (!ssl_ctx) {
339                 return;
340         }
341         if (!(ch->ssl_handle = SSL_new(ssl_ctx))) {
342                 syslog(LOG_WARNING, "SSL_new failed: %s", ERR_reason_error_string(ERR_get_error()));
343                 return;
344         }
345         if (!(SSL_set_fd(ch->ssl_handle, ch->sock))) {
346                 syslog(LOG_WARNING, "SSL_set_fd failed: %s", ERR_reason_error_string(ERR_get_error()));
347                 SSL_free(ch->ssl_handle);
348                 return;
349         }
350         retval = SSL_accept(ch->ssl_handle);
351         if (retval < 1) {
352                 long errval;
353                 const char *ssl_error_reason = NULL;
354
355                 errval = SSL_get_error(ch->ssl_handle, retval);
356                 ssl_error_reason = ERR_reason_error_string(ERR_get_error());
357                 if (ssl_error_reason == NULL) {
358                         syslog(LOG_WARNING, "SSL_accept failed: errval=%ld, retval=%d %s", errval, retval, strerror(errval));
359                 }
360                 else {
361                         syslog(LOG_WARNING, "SSL_accept failed: %s\n", ssl_error_reason);
362                 }
363                 sleep(1);
364                 retval = SSL_accept(ch->ssl_handle);
365         }
366         if (retval < 1) {
367                 long errval;
368                 const char *ssl_error_reason = NULL;
369
370                 errval = SSL_get_error(ch->ssl_handle, retval);
371                 ssl_error_reason = ERR_reason_error_string(ERR_get_error());
372                 if (ssl_error_reason == NULL) {
373                         syslog(LOG_WARNING, "SSL_accept failed: errval=%ld, retval=%d (%s)", errval, retval, strerror(errval));
374                 }
375                 else {
376                         syslog(LOG_WARNING, "SSL_accept failed: %s", ssl_error_reason);
377                 }
378                 SSL_free(ch->ssl_handle);
379                 ch->ssl_handle = NULL;
380                 return;
381         }
382         else {
383                 syslog(LOG_INFO, "SSL_accept success");
384         }
385         bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(ch->ssl_handle), &alg_bits);
386         syslog(LOG_INFO, "SSL/TLS using %s on %s (%d of %d bits)",
387                 SSL_CIPHER_get_name(SSL_get_current_cipher(ch->ssl_handle)),
388                 SSL_CIPHER_get_version(SSL_get_current_cipher(ch->ssl_handle)),
389                 bits, alg_bits);
390
391         syslog(LOG_INFO, "SSL started");
392 }
393
394
395 /*
396  * shuts down the TLS connection
397  */
398 void endtls(struct client_handle *ch)
399 {
400         syslog(LOG_INFO, "Ending SSL/TLS");
401         if (ch->ssl_handle != NULL) {
402                 SSL_shutdown(ch->ssl_handle);
403                 SSL_get_SSL_CTX(ch->ssl_handle);
404                 SSL_free(ch->ssl_handle);
405         }
406         ch->ssl_handle = NULL;
407 }
408
409
410 /*
411  * Send binary data to the client encrypted.
412  */
413 int client_write_ssl(struct client_handle *ch, char *buf, int nbytes)
414 {
415         int retval;
416         int nremain;
417         char junk[1];
418
419         if (ch->ssl_handle == NULL) return(-1);
420
421         nremain = nbytes;
422         while (nremain > 0) {
423                 if (SSL_want_write(ch->ssl_handle)) {
424                         if ((SSL_read(ch->ssl_handle, junk, 0)) < 1) {
425                                 syslog(LOG_WARNING, "SSL_read in client_write: %s", ERR_reason_error_string(ERR_get_error()));
426                         }
427                 }
428                 retval = SSL_write(ch->ssl_handle, &buf[nbytes - nremain], nremain);
429                 if (retval < 1) {
430                         long errval;
431
432                         errval = SSL_get_error(ch->ssl_handle, retval);
433                         if (errval == SSL_ERROR_WANT_READ || errval == SSL_ERROR_WANT_WRITE) {
434                                 sleep(1);
435                                 continue;
436                         }
437                         syslog(LOG_WARNING, "SSL_write got error %ld, ret %d", errval, retval);
438                         if (retval == -1) {
439                                 syslog(LOG_WARNING, "errno is %d", errno);
440                                 endtls(ch);
441                         }
442                         return -1;
443                 }
444                 nremain -= retval;
445         }
446         return 0;
447 }
448
449
450 /*
451  * read data from the encrypted layer.
452  */
453 int client_read_ssl(struct client_handle *ch, char *buf, int nbytes)
454 {
455         int bytes_read = 0;
456         int rlen = 0;
457         char junk[1];
458
459         if (ch->ssl_handle == NULL) return(-1);
460
461         while (bytes_read < nbytes) {
462                 if (SSL_want_read(ch->ssl_handle)) {
463                         if ((SSL_write(ch->ssl_handle, junk, 0)) < 1) {
464                                 syslog(LOG_WARNING, "SSL_write in client_read");
465                         }
466                 }
467                 rlen = SSL_read(ch->ssl_handle, &buf[bytes_read], nbytes-bytes_read);
468                 if (rlen < 1) {
469                         long errval;
470
471                         errval = SSL_get_error(ch->ssl_handle, rlen);
472                         if (errval == SSL_ERROR_WANT_READ || errval == SSL_ERROR_WANT_WRITE) {
473                                 sleep(1);
474                                 continue;
475                         }
476                         syslog(LOG_WARNING, "SSL_read error %ld", errval);
477                         endtls(ch);
478                         return (-1);
479                 }
480                 bytes_read += rlen;
481         }
482         return(bytes_read);
483 }