1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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.
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.
42 #include <openssl/x509v3.h>
43 #include <openssl/ssl.h>
44 #include <openssl/err.h>
45 #include <openssl/safestack.h>
48 static SSL_CTX *context;
49 static EVP_PKEY *pkey;
51 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
53 static int SSL_add_ext(X509 * crt, int nid, char *value) {
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);
62 X509_add_ext(crt, ex, -1);
63 X509_EXTENSION_free(ex);
67 static X509 *SSL_readcert(char *certfile)
72 /* open the certificate file */
73 fp = fopen(certfile, "r");
75 Log_warn("Unable to open the X509 file %s for reading.", certfile);
79 /* allocate memory for the cert structure */
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.");
93 static RSA *SSL_readprivatekey(char *keyfile)
98 /* open the private key file for reading */
99 fp = fopen(keyfile, "r");
101 Log_warn("Unable to open the private key file %s for reading.", keyfile);
105 /* allocate memory for the RSA structure */
108 /* assign a callback function for the password */
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.");
122 static void SSL_writecert(char *certfile, X509 *x509)
126 /* open the private key file */
127 fp = fopen(certfile, "w");
129 Log_warn("Unable to open the X509 file %s for writing", certfile);
132 if (PEM_write_X509(fp, x509) == 0) {
133 Log_warn("Error trying to write X509 info.");
138 static void SSL_writekey(char *keyfile, RSA *rsa)
142 /* open the private key file for reading */
143 fp = fopen(keyfile, "w");
145 Log_warn("Unable to open the private key file %s for writing.", keyfile);
149 if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
150 Log_warn("Error trying to write private key");
155 static void SSL_initializeCert() {
157 char *crt, *key, *pass;
159 crt = (char *)getStrConf(CERTIFICATE);
160 key = (char *)getStrConf(KEY);
161 pass = (char *)getStrConf(PASSPHRASE);
163 x509 = SSL_readcert(crt);
164 rsa = SSL_readprivatekey(key);
166 pkey = EVP_PKEY_new();
167 EVP_PKEY_assign_RSA(pkey, rsa);
174 qscCert = QSslCertificate(key);
175 if (! qscCert.isNull()) {
176 logthis("Using certificate from key.");
180 if (! qscCert.isNull()) {
181 QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
182 /* Fetch algorith from cert */
183 if (! key.isEmpty()) {
185 qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
186 if (qskKey.isNull()) {
187 logthis("Failed to parse key.");
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.");
203 Log_info("Generating new server certificate.");
206 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
209 pkey = EVP_PKEY_new();
210 rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
211 EVP_PKEY_assign_RSA(pkey, rsa);
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);
219 X509_NAME *name=X509_get_subject_name(x509);
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");
228 X509_sign(x509, pkey, EVP_md5());
230 SSL_writecert(crt, x509);
231 SSL_writekey(key, rsa);
240 int i, offset = 0, cipherstringlen = 0;
241 STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
243 char *cipherstring, tempstring[128];
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 */
253 ERR_print_errors_fp(stderr);
257 char const * sslCAPath = getStrConf(CAPATH);
258 if(sslCAPath != NULL)
260 SSL_CTX_load_verify_locations(context, NULL, sslCAPath);
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");
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();
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);
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;
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));
296 sk_SSL_CIPHER_free(cipherlist_new);
298 if (strlen(cipherstring) == 0)
299 Log_fatal("No suitable ciphers found!");
301 if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
302 Log_fatal("Failed to set cipher list!");
306 SSL_CTX_set_verify(context, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
310 Log_info("OpenSSL library initialized");
314 void SSLi_deinit(void)
316 SSL_CTX_free(context);
320 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
323 rc = SSL_accept(ssl);
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");
330 Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
338 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
343 ssl = SSL_new(context);
344 SSL_set_fd(ssl, *fd);
345 if (SSLi_nonblockaccept(ssl, SSLready) < 0) {
352 /* Create SHA1 of last certificate in the peer's chain. */
353 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
359 x509 = SSL_get_peer_certificate(ssl);
364 len = i2d_X509(x509, NULL);
373 SHA1(buf, len, hash);
378 void SSLi_closeconnection(SSL_handle_t *ssl)
383 void SSLi_shutdown(SSL_handle_t *ssl)
388 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
390 return SSL_read(ssl, buf, len);
393 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
395 return SSL_write(ssl, buf, len);
398 int SSLi_get_error(SSL_handle_t *ssl, int code)
400 return SSL_get_error(ssl, code);
403 bool_t SSLi_data_pending(SSL_handle_t *ssl)
405 return SSL_pending(ssl);
408 void SSLi_free(SSL_handle_t *ssl)
413 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
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);
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);
429 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
430 X509_STORE_CTX_set_error(ctx, err);
433 Log_warn("SSL: verify error:num=%d:%s:depth=%d:%s\n", err,
434 X509_verify_cert_error_string(err), depth, buf);
437 * At this point, err contains the last verification error. We can use
438 * it for something special
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);