42f9610b44c1f9d780d895106000ab72f997c299
[umurmur.git] / ssl.c
1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2009, 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 <openssl/x509v3.h>
32 #include <openssl/ssl.h>
33 #include <openssl/err.h>
34 #include <openssl/safestack.h>
35 #include <string.h>
36
37 #include "conf.h"
38 #include "log.h"
39 #include "ssl.h"
40
41 static X509 *x509;
42 static RSA *rsa;
43 static SSL_CTX *context;
44 static EVP_PKEY *pkey;
45
46 static int SSL_add_ext(X509 * crt, int nid, char *value) {
47         X509_EXTENSION *ex;
48         X509V3_CTX ctx;
49         X509V3_set_ctx_nodb(&ctx);
50         X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
51         ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
52         if (!ex)
53                 return 0;
54
55         X509_add_ext(crt, ex, -1);
56         X509_EXTENSION_free(ex);
57         return 1;
58 }
59
60 static X509 *SSL_readcert(char *certfile)
61 {
62         FILE *fp;
63         X509 *x509;
64                         
65         /* open the private key file */
66         fp = fopen(certfile, "r");
67         if (fp == NULL) {
68                 Log_warn("Unable to open the X509 file %s for reading.", certfile);
69                 return NULL;
70         }
71         
72         /* allocate memory for the cert structure */    
73         x509 = X509_new();
74         
75         if (PEM_read_X509(fp, &x509, NULL, NULL) == 0) {
76                 /* error reading the x509 information - check the error stack */
77                 Log_warn("Error trying to read X509 info.");
78                 fclose(fp);
79                 X509_free(x509);
80                 return NULL;
81         }
82         fclose(fp);
83         return x509;
84 }
85
86 static RSA *SSL_readprivatekey(char *keyfile)
87 {
88         FILE *fp;
89         RSA *rsa;
90
91 /* open the private key file for reading */
92         fp = fopen(keyfile, "r");
93         if (fp == NULL) {
94                 Log_warn("Unable to open the private key file %s for reading.", keyfile);
95                 return NULL;
96         }
97         
98 /* allocate memory for the RSA structure */
99         rsa = RSA_new();
100         
101         /* assign a callback function for the password */
102         
103         /* read a private key from file */      
104         if (PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) <= 0) {
105                 /* error reading the key - check the error stack */
106                 Log_warn("Error trying to read private key.");
107                 RSA_free(rsa);
108                 fclose(fp);
109                 return NULL;
110         }
111         fclose(fp);
112         return rsa;
113 }
114
115 void SSL_writecert(char *certfile, X509 *x509)
116 {
117         FILE *fp;
118         BIO *err_output;
119         
120         /* prepare a BIO for outputting error messages */
121         
122         err_output = BIO_new_fp(stderr,BIO_NOCLOSE);
123         
124         /* open the private key file */
125         fp = fopen(certfile, "w");
126         if (fp == NULL) {
127                 BIO_printf(err_output, "Unable to open the X509 file for writing.\n");
128                 BIO_free(err_output);
129                 return;
130         }
131                 
132         if (PEM_write_X509(fp, x509) == 0) {
133                 BIO_printf(err_output, "Error trying to write X509 info.\n");
134                 ERR_print_errors(err_output);
135         }
136         fclose(fp);
137 }
138
139 void SSL_writekey(char *keyfile, RSA *rsa)
140 {
141         FILE *fp;
142         BIO *err_output;
143         /* prepare a BIO for outputing error messages */        
144         err_output = BIO_new_fp(stderr, BIO_NOCLOSE);
145         
146         /* open the private key file for reading */
147         fp = fopen(keyfile, "w");
148         if (fp == NULL) {
149                 BIO_printf(err_output, "Unable to open the private key file %s for writing.\n", keyfile);
150                 BIO_free(err_output);
151                 return;
152         }
153         
154         if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
155                 /* error reading the key - check the error stack */
156                 BIO_printf(err_output, "Error trying to write private key\n");
157                 ERR_print_errors(err_output);
158         }
159         fclose(fp);
160 }
161
162 void SSL_initializeCert() {
163         char *crt, *key, *pass;
164         
165         crt = (char *)getStrConf(CERTIFICATE);
166         key = (char *)getStrConf(KEY);
167         pass = (char *)getStrConf(PASSPHRASE);
168
169         x509 = SSL_readcert(crt);
170         rsa = SSL_readprivatekey(key);
171         if (rsa != NULL) {
172                 pkey = EVP_PKEY_new();
173                 EVP_PKEY_assign_RSA(pkey, rsa);
174         }               
175         
176 #if 0
177         /* Later ... */
178         if (key && !x509) {             
179                 qscCert = QSslCertificate(key);
180                 if (! qscCert.isNull()) {
181                         logthis("Using certificate from key.");
182                 }
183         }
184
185         if (! qscCert.isNull()) {
186                 QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
187                 /* Fetch algorith from cert */
188                 if (! key.isEmpty()) {
189                         /* get key */
190                         qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
191                         if (qskKey.isNull()) {
192                                 logthis("Failed to parse key.");
193                         }
194                 }
195
196                 if (! crt.isEmpty() && qskKey.isNull()) {
197                         /* get key from certificate */
198                         qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
199                         if (! qskKey.isNull()) {
200                                 logthis("Using key from certificate.");
201                         }
202                 }
203
204         }
205 #endif
206         
207         if (!rsa || !x509) {
208                 logthis("Generating new server certificate.");
209
210                 BIO *bio_err;
211                 
212                 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
213                 
214                 bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
215                 
216                 x509 = X509_new();
217                 pkey = EVP_PKEY_new();
218                 rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
219                 EVP_PKEY_assign_RSA(pkey, rsa);
220                 
221                 X509_set_version(x509, 2);
222                 ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
223                 X509_gmtime_adj(X509_get_notBefore(x509),0);
224                 X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
225                 X509_set_pubkey(x509, pkey);
226                 
227                 X509_NAME *name=X509_get_subject_name(x509);
228                 
229                 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
230                 X509_set_issuer_name(x509, name);
231                 SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
232                 SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
233                 SSL_add_ext(x509, NID_subject_key_identifier, "hash");
234                 SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
235                 
236                 X509_sign(x509, pkey, EVP_md5());
237                 
238                 SSL_writecert(crt, x509);
239                 SSL_writekey(key, rsa);
240         }
241
242 }
243
244 void SSL_getdigest(char *s, int l)
245 {
246         unsigned char md[EVP_MAX_MD_SIZE];
247         unsigned int n;
248         int j;
249         
250         if (!X509_digest (x509, EVP_md5(), md, &n))
251         {
252                 snprintf (s, l, "[unable to calculate]");
253         }
254         else
255         {
256                 for (j = 0; j < (int) n; j++)
257                 {
258                         char ch[8];
259                         snprintf(ch, 8, "%02X%s", md[j], (j % 2 ? " " : ""));
260                         strcat(s, ch);
261                 }
262         }
263 }
264
265 void SSL_init(void)
266 {
267         SSL_METHOD *method;
268         SSL *ssl;
269         int i, offset = 0;
270         STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
271         SSL_CIPHER *cipher;
272         char cipherstring[1024];
273                 
274         SSL_library_init();
275     OpenSSL_add_all_algorithms();               /* load & register all cryptos, etc. */
276     SSL_load_error_strings();                   /* load all error messages */
277     ERR_load_crypto_strings();                  /* load all error messages */
278     method = SSLv23_server_method();            /* create new server-method instance */
279     context = SSL_CTX_new(method);                      /* create new context from method */
280     if (context == NULL)
281     {
282         ERR_print_errors_fp(stderr);
283         abort();
284     }
285         SSL_initializeCert();
286         if (SSL_CTX_use_certificate(context, x509) <= 0)
287                 Log_fatal("Failed to initialize cert");
288         if (SSL_CTX_use_PrivateKey(context, pkey) <= 0) {
289                 ERR_print_errors_fp(stderr);
290                 Log_fatal("Failed to initialize private key");
291         }
292
293         /* Set cipher list */
294         ssl = SSL_new(context); 
295         cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);
296         cipherlist_new = (STACK_OF(SSL_CIPHER) *) sk_SSL_CIPHER_new_null();
297         
298         for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist, i)) != NULL; i++) {
299                 if (SSL_CIPHER_get_bits(cipher, NULL) >= 128) {
300                         sk_SSL_CIPHER_push(cipherlist_new, cipher);
301                 }
302         }
303         Log_info("List of ciphers:");
304         if (cipherlist_new) {
305                 for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
306                         Log_info("%s", SSL_CIPHER_get_name(cipher));
307                         offset += snprintf(cipherstring + offset, 1024 - offset, "%s:", SSL_CIPHER_get_name(cipher));
308                 }
309                 cipherstring[offset - 1] = '\0';
310         }
311         
312         if (cipherlist_new)
313                 sk_SSL_CIPHER_free(cipherlist_new);
314         
315         if (strlen(cipherstring) == 0)
316                 Log_fatal("No suitable ciphers found!");
317         
318         if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
319                 Log_fatal("Failed to set cipher list!");
320                 
321         
322         SSL_free(ssl);
323 }
324
325 void SSL_deinit(void)
326 {
327         SSL_CTX_free(context);
328         EVP_cleanup();
329 }
330
331 int SSL_nonblockaccept(SSL *ssl, bool_t *SSLready)
332 {
333         int rc;
334         rc = SSL_accept(ssl);
335         if (rc < 0) {
336                 if (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ ||
337                         SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE) {
338                         Log_debug("SSL not ready");
339                         return 0;
340                 } else {
341                         Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
342                         return -1;
343                 }
344         }
345         *SSLready = true;
346         return 0;
347 }
348
349 SSL *SSL_newconnection(int fd, bool_t *SSLready)
350 {
351         SSL *ssl;
352         
353         *SSLready = false;
354         ssl = SSL_new(context);
355         SSL_set_fd(ssl, fd);
356         if (SSL_nonblockaccept(ssl, SSLready) < 0) {
357                 SSL_free(ssl);
358                 return NULL;
359         }
360         return ssl;
361 }
362
363 void SSL_closeconnection(SSL *ssl)
364 {
365         SSL_free(ssl);
366 }
367
368