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.
43 #include <openssl/x509v3.h>
44 #include <openssl/ssl.h>
45 #include <openssl/err.h>
46 #include <openssl/safestack.h>
49 static SSL_CTX *context;
50 static EVP_PKEY *pkey;
52 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
54 static int SSL_add_ext(X509 * crt, int nid, char *value) {
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);
63 X509_add_ext(crt, ex, -1);
64 X509_EXTENSION_free(ex);
68 static X509 *SSL_readcert(char *certfile)
73 /* open the certificate file */
74 fp = fopen(certfile, "r");
76 Log_warn("Unable to open the X509 file %s for reading.", certfile);
80 /* allocate memory for the cert structure */
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.");
94 static RSA *SSL_readprivatekey(char *keyfile)
99 /* open the private key file for reading */
100 fp = fopen(keyfile, "r");
102 Log_warn("Unable to open the private key file %s for reading.", keyfile);
106 /* allocate memory for the RSA structure */
109 /* assign a callback function for the password */
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.");
123 static void SSL_writecert(char *certfile, X509 *x509)
127 /* open the private key file */
128 fp = fopen(certfile, "w");
130 Log_warn("Unable to open the X509 file %s for writing", certfile);
133 if (PEM_write_X509(fp, x509) == 0) {
134 Log_warn("Error trying to write X509 info.");
139 static void SSL_writekey(char *keyfile, RSA *rsa)
143 /* open the private key file for reading */
144 fp = fopen(keyfile, "w");
146 Log_warn("Unable to open the private key file %s for writing.", keyfile);
150 if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
151 Log_warn("Error trying to write private key");
156 static void SSL_initializeCert() {
158 char *crt, *key, *pass;
160 crt = (char *)getStrConf(CERTIFICATE);
161 key = (char *)getStrConf(KEY);
162 pass = (char *)getStrConf(PASSPHRASE);
164 x509 = SSL_readcert(crt);
165 rsa = SSL_readprivatekey(key);
167 pkey = EVP_PKEY_new();
168 EVP_PKEY_assign_RSA(pkey, rsa);
175 qscCert = QSslCertificate(key);
176 if (! qscCert.isNull()) {
177 logthis("Using certificate from key.");
181 if (! qscCert.isNull()) {
182 QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
183 /* Fetch algorith from cert */
184 if (! key.isEmpty()) {
186 qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
187 if (qskKey.isNull()) {
188 logthis("Failed to parse key.");
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.");
204 Log_info("Generating new server certificate.");
207 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
210 pkey = EVP_PKEY_new();
211 rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
212 EVP_PKEY_assign_RSA(pkey, rsa);
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);
220 X509_NAME *name=X509_get_subject_name(x509);
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");
229 X509_sign(x509, pkey, EVP_md5());
231 SSL_writecert(crt, x509);
232 SSL_writekey(key, rsa);
239 const SSL_METHOD *method;
241 int i, offset = 0, cipherstringlen = 0;
242 STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
244 char *cipherstring, tempstring[128];
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 */
254 ERR_print_errors_fp(stderr);
258 char* sslCAPath = getStrConf(CAPATH);
259 if(sslCAPath != NULL)
261 SSL_CTX_load_verify_locations(context, NULL, sslCAPath);
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");
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();
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);
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;
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));
297 sk_SSL_CIPHER_free(cipherlist_new);
299 if (strlen(cipherstring) == 0)
300 Log_fatal("No suitable ciphers found!");
302 if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
303 Log_fatal("Failed to set cipher list!");
307 SSL_CTX_set_verify(context, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
311 Log_info("OpenSSL library initialized");
315 void SSLi_deinit(void)
317 SSL_CTX_free(context);
321 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
324 rc = SSL_accept(ssl);
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");
331 Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
339 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
344 ssl = SSL_new(context);
345 SSL_set_fd(ssl, *fd);
346 if (SSLi_nonblockaccept(ssl, SSLready) < 0) {
353 /* Create SHA1 of last certificate in the peer's chain. */
354 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
360 x509 = SSL_get_peer_certificate(ssl);
365 len = i2d_X509(x509, NULL);
374 SHA1(buf, len, hash);
379 void SSLi_closeconnection(SSL_handle_t *ssl)
384 void SSLi_shutdown(SSL_handle_t *ssl)
389 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
391 return SSL_read(ssl, buf, len);
394 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
396 return SSL_write(ssl, buf, len);
399 int SSLi_get_error(SSL_handle_t *ssl, int code)
401 return SSL_get_error(ssl, code);
404 bool_t SSLi_data_pending(SSL_handle_t *ssl)
406 return SSL_pending(ssl);
409 void SSLi_free(SSL_handle_t *ssl)
414 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
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);
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);
430 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
431 X509_STORE_CTX_set_error(ctx, err);
434 Log_warn("SSL: verify error:num=%d:%s:depth=%d:%s\n", err,
435 X509_verify_cert_error_string(err), depth, buf);
438 * At this point, err contains the last verification error. We can use
439 * it for something special
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);