0542bff3441934fc710566cc16b2d5a13ca40ffd
[umurmur.git] / src / ssli_openssl.c
1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <stdlib.h>
32 #include <fcntl.h>
33
34 #include "conf.h"
35 #include "log.h"
36 #include "ssl.h"
37
38 /*
39  * OpenSSL interface
40  */
41
42 #include <openssl/x509v3.h>
43 #include <openssl/ssl.h>
44 #include <openssl/err.h>
45 #include <openssl/safestack.h>
46 static X509 *x509;
47 static RSA *rsa;
48 static SSL_CTX *context;
49 static EVP_PKEY *pkey;
50
51 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
52
53 static int SSL_add_ext(X509 * crt, int nid, char *value) {
54         X509_EXTENSION *ex;
55         X509V3_CTX ctx;
56         X509V3_set_ctx_nodb(&ctx);
57         X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
58         ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
59         if (!ex)
60                 return 0;
61
62         X509_add_ext(crt, ex, -1);
63         X509_EXTENSION_free(ex);
64         return 1;
65 }
66
67 static X509 *SSL_readcert(char *certfile)
68 {
69         FILE *fp;
70         X509 *x509;
71
72         /* open the certificate file */
73         fp = fopen(certfile, "r");
74         if (fp == NULL) {
75                 Log_warn("Unable to open the X509 file %s for reading.", certfile);
76                 return NULL;
77         }
78
79         /* allocate memory for the cert structure */
80         x509 = X509_new();
81
82         if (PEM_read_X509(fp, &x509, NULL, NULL) == 0) {
83                 /* error reading the x509 information - check the error stack */
84                 Log_warn("Error trying to read X509 info.");
85                 fclose(fp);
86                 X509_free(x509);
87                 return NULL;
88         }
89         fclose(fp);
90         return x509;
91 }
92
93 static RSA *SSL_readprivatekey(char *keyfile)
94 {
95         FILE *fp;
96         RSA *rsa;
97
98 /* open the private key file for reading */
99         fp = fopen(keyfile, "r");
100         if (fp == NULL) {
101                 Log_warn("Unable to open the private key file %s for reading.", keyfile);
102                 return NULL;
103         }
104
105 /* allocate memory for the RSA structure */
106         rsa = RSA_new();
107
108         /* assign a callback function for the password */
109
110         /* read a private key from file */
111         if (PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) <= 0) {
112                 /* error reading the key - check the error stack */
113                 Log_warn("Error trying to read private key.");
114                 RSA_free(rsa);
115                 fclose(fp);
116                 return NULL;
117         }
118         fclose(fp);
119         return rsa;
120 }
121
122 static void SSL_writecert(char *certfile, X509 *x509)
123 {
124         FILE *fp;
125
126         /* open the private key file */
127         fp = fopen(certfile, "w");
128         if (fp == NULL) {
129                 Log_warn("Unable to open the X509 file %s for writing", certfile);
130                 return;
131         }
132         if (PEM_write_X509(fp, x509) == 0) {
133                 Log_warn("Error trying to write X509 info.");
134         }
135         fclose(fp);
136 }
137
138 static void SSL_writekey(char *keyfile, RSA *rsa)
139 {
140         FILE *fp;
141
142         /* open the private key file for reading */
143         fp = fopen(keyfile, "w");
144         if (fp == NULL) {
145                 Log_warn("Unable to open the private key file %s for writing.", keyfile);
146                 return;
147         }
148
149         if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
150                 Log_warn("Error trying to write private key");
151         }
152         fclose(fp);
153 }
154
155 static void SSL_initializeCert() {
156
157         char *crt, *key, *pass;
158
159         crt = (char *)getStrConf(CERTIFICATE);
160         key = (char *)getStrConf(KEY);
161         pass = (char *)getStrConf(PASSPHRASE);
162
163         x509 = SSL_readcert(crt);
164         rsa = SSL_readprivatekey(key);
165         if (rsa != NULL) {
166                 pkey = EVP_PKEY_new();
167                 EVP_PKEY_assign_RSA(pkey, rsa);
168         }
169
170
171 #if 0
172         /* Later ... */
173         if (key && !x509) {
174                 qscCert = QSslCertificate(key);
175                 if (! qscCert.isNull()) {
176                         logthis("Using certificate from key.");
177                 }
178         }
179
180         if (! qscCert.isNull()) {
181                 QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
182                 /* Fetch algorith from cert */
183                 if (! key.isEmpty()) {
184                         /* get key */
185                         qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
186                         if (qskKey.isNull()) {
187                                 logthis("Failed to parse key.");
188                         }
189                 }
190
191                 if (! crt.isEmpty() && qskKey.isNull()) {
192                         /* get key from certificate */
193                         qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
194                         if (! qskKey.isNull()) {
195                                 logthis("Using key from certificate.");
196                         }
197                 }
198
199         }
200 #endif
201
202         if (!rsa || !x509) {
203                 Log_info("Generating new server certificate.");
204
205
206                 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
207
208                 x509 = X509_new();
209                 pkey = EVP_PKEY_new();
210                 rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
211                 EVP_PKEY_assign_RSA(pkey, rsa);
212
213                 X509_set_version(x509, 2);
214                 ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
215                 X509_gmtime_adj(X509_get_notBefore(x509),0);
216                 X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
217                 X509_set_pubkey(x509, pkey);
218
219                 X509_NAME *name=X509_get_subject_name(x509);
220
221                 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
222                 X509_set_issuer_name(x509, name);
223                 SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
224                 SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
225                 SSL_add_ext(x509, NID_subject_key_identifier, "hash");
226                 SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
227
228                 X509_sign(x509, pkey, EVP_md5());
229
230                 SSL_writecert(crt, x509);
231                 SSL_writekey(key, rsa);
232         }
233
234 }
235
236 void SSLi_init(void)
237 {
238         SSL_METHOD *method;
239         SSL *ssl;
240         int i, offset = 0, cipherstringlen = 0;
241         STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
242         SSL_CIPHER *cipher;
243         char *cipherstring, tempstring[128];
244
245         SSL_library_init();
246         OpenSSL_add_all_algorithms();           /* load & register all cryptos, etc. */
247         SSL_load_error_strings();                       /* load all error messages */
248         ERR_load_crypto_strings();                      /* load all error messages */
249         method = SSLv23_server_method();                /* create new server-method instance */
250         context = SSL_CTX_new(method);                  /* create new context from method */
251         if (context == NULL)
252         {
253                 ERR_print_errors_fp(stderr);
254                 abort();
255         }
256
257         char const * sslCAPath = getStrConf(CAPATH);
258         if(sslCAPath != NULL)
259         {
260                 SSL_CTX_load_verify_locations(context, NULL, sslCAPath);
261         }
262
263         SSL_initializeCert();
264         if (SSL_CTX_use_certificate(context, x509) <= 0)
265                 Log_fatal("Failed to initialize cert");
266         if (SSL_CTX_use_PrivateKey(context, pkey) <= 0) {
267                 ERR_print_errors_fp(stderr);
268                 Log_fatal("Failed to initialize private key");
269         }
270
271         /* Set cipher list */
272         ssl = SSL_new(context);
273         cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);
274         cipherlist_new = (STACK_OF(SSL_CIPHER) *) sk_SSL_CIPHER_new_null();
275
276         for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist, i)) != NULL; i++) {
277                 if (SSL_CIPHER_get_bits(cipher, NULL) >= 128) {
278                         sk_SSL_CIPHER_push(cipherlist_new, cipher);
279                 }
280         }
281         Log_debug("List of ciphers:");
282         if (cipherlist_new) {
283                 for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
284                         Log_debug("%s", SSL_CIPHER_get_name(cipher));
285                         cipherstringlen += strlen(SSL_CIPHER_get_name(cipher)) + 1;
286                 }
287                 cipherstring = malloc(cipherstringlen + 1);
288                 if (cipherstring == NULL)
289                         Log_fatal("Out of memory");
290                 for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
291                         offset += sprintf(cipherstring + offset, "%s:", SSL_CIPHER_get_name(cipher));
292                 }
293         }
294
295         if (cipherlist_new)
296                 sk_SSL_CIPHER_free(cipherlist_new);
297
298         if (strlen(cipherstring) == 0)
299                 Log_fatal("No suitable ciphers found!");
300
301         if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
302                 Log_fatal("Failed to set cipher list!");
303
304         free(cipherstring);
305
306         SSL_CTX_set_verify(context, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
307                            verify_callback);
308
309         SSL_free(ssl);
310         Log_info("OpenSSL library initialized");
311
312 }
313
314 void SSLi_deinit(void)
315 {
316         SSL_CTX_free(context);
317         EVP_cleanup();
318 }
319
320 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
321 {
322         int rc;
323         rc = SSL_accept(ssl);
324         if (rc < 0) {
325                 if (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ ||
326                         SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE) {
327                         Log_debug("SSL not ready");
328                         return 0;
329                 } else {
330                         Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
331                         return -1;
332                 }
333         }
334         *SSLready = true;
335         return 0;
336 }
337
338 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
339 {
340         SSL *ssl;
341
342         *SSLready = false;
343         ssl = SSL_new(context);
344         SSL_set_fd(ssl, *fd);
345         if (SSLi_nonblockaccept(ssl, SSLready) < 0) {
346                 SSL_free(ssl);
347                 return NULL;
348         }
349         return ssl;
350 }
351
352 /* Create SHA1 of last certificate in the peer's chain. */
353 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
354 {
355         X509 *x509;
356         uint8_t *buf, *p;
357         int len;
358
359         x509 = SSL_get_peer_certificate(ssl);
360         if (!x509) {
361                 return false;
362         }
363
364         len = i2d_X509(x509, NULL);
365         buf = malloc(len);
366         if (buf == NULL) {
367                 Log_fatal("malloc");
368         }
369
370         p = buf;
371         i2d_X509(x509, &p);
372
373         SHA1(buf, len, hash);
374         free(buf);
375         return true;
376 }
377
378 void SSLi_closeconnection(SSL_handle_t *ssl)
379 {
380         SSL_free(ssl);
381 }
382
383 void SSLi_shutdown(SSL_handle_t *ssl)
384 {
385         SSL_shutdown(ssl);
386 }
387
388 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
389 {
390         return SSL_read(ssl, buf, len);
391 }
392
393 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
394 {
395         return SSL_write(ssl, buf, len);
396 }
397
398 int SSLi_get_error(SSL_handle_t *ssl, int code)
399 {
400         return SSL_get_error(ssl, code);
401 }
402
403 bool_t SSLi_data_pending(SSL_handle_t *ssl)
404 {
405         return SSL_pending(ssl);
406 }
407
408 void SSLi_free(SSL_handle_t *ssl)
409 {
410         SSL_free(ssl);
411 }
412
413 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
414 {
415         char    buf[256];
416         X509   *err_cert;
417         int     err, depth;
418         SSL    *ssl;
419
420     err_cert = X509_STORE_CTX_get_current_cert(ctx);
421     err = X509_STORE_CTX_get_error(ctx);
422     depth = X509_STORE_CTX_get_error_depth(ctx);
423
424     ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
425     X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
426
427     if (depth > 5) {
428         preverify_ok = 0;
429         err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
430         X509_STORE_CTX_set_error(ctx, err);
431     }
432     if (!preverify_ok) {
433             Log_warn("SSL: verify error:num=%d:%s:depth=%d:%s\n", err,
434                      X509_verify_cert_error_string(err), depth, buf);
435     }
436     /*
437      * At this point, err contains the last verification error. We can use
438      * it for something special
439      */
440     if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
441             X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
442             Log_warn("issuer= %s", buf);
443     }
444     return 1;
445 }