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