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