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