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