Fix const-correctness warnings in OpenSSL's SSLi_init().
[umurmur.git] / src / ssli_openssl.c
index 0542bff3441934fc710566cc16b2d5a13ca40ffd..c35e1f82b4ef64338c7e4b6267d8b08a3463635c 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "conf.h"
 #include "log.h"
+#include "memory.h"
 #include "ssl.h"
 
 /*
@@ -48,6 +49,8 @@ static RSA *rsa;
 static SSL_CTX *context;
 static EVP_PKEY *pkey;
 
+static char const * ciphers = "EECDH+CHACHA20:EECDH+AESGCM:EECDH+AES+TLSv1.2:EECDH+AES:AESGCM:AES:!aNULL:!DHE:!kECDH";
+
 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
 
 static int SSL_add_ext(X509 * crt, int nid, char *value) {
@@ -64,32 +67,6 @@ static int SSL_add_ext(X509 * crt, int nid, char *value) {
        return 1;
 }
 
-static X509 *SSL_readcert(char *certfile)
-{
-       FILE *fp;
-       X509 *x509;
-
-       /* open the certificate file */
-       fp = fopen(certfile, "r");
-       if (fp == NULL) {
-               Log_warn("Unable to open the X509 file %s for reading.", certfile);
-               return NULL;
-       }
-
-       /* allocate memory for the cert structure */
-       x509 = X509_new();
-
-       if (PEM_read_X509(fp, &x509, NULL, NULL) == 0) {
-               /* error reading the x509 information - check the error stack */
-               Log_warn("Error trying to read X509 info.");
-               fclose(fp);
-               X509_free(x509);
-               return NULL;
-       }
-       fclose(fp);
-       return x509;
-}
-
 static RSA *SSL_readprivatekey(char *keyfile)
 {
        FILE *fp;
@@ -154,106 +131,87 @@ static void SSL_writekey(char *keyfile, RSA *rsa)
 
 static void SSL_initializeCert() {
 
-       char *crt, *key, *pass;
+       char *crt = (char *)getStrConf(CERTIFICATE);
+       char *key = (char *)getStrConf(KEY);
 
-       crt = (char *)getStrConf(CERTIFICATE);
-       key = (char *)getStrConf(KEY);
-       pass = (char *)getStrConf(PASSPHRASE);
+       if (context) {
+               bool_t did_load_cert = SSL_CTX_use_certificate_chain_file(context, crt);
+               rsa = SSL_readprivatekey(key);
 
-       x509 = SSL_readcert(crt);
-       rsa = SSL_readprivatekey(key);
-       if (rsa != NULL) {
-               pkey = EVP_PKEY_new();
-               EVP_PKEY_assign_RSA(pkey, rsa);
-       }
-
-
-#if 0
-       /* Later ... */
-       if (key && !x509) {
-               qscCert = QSslCertificate(key);
-               if (! qscCert.isNull()) {
-                       logthis("Using certificate from key.");
-               }
-       }
-
-       if (! qscCert.isNull()) {
-               QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
-               /* Fetch algorith from cert */
-               if (! key.isEmpty()) {
-                       /* get key */
-                       qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
-                       if (qskKey.isNull()) {
-                               logthis("Failed to parse key.");
-                       }
-               }
+               if (!rsa || !did_load_cert) {
+                       Log_info("Generating new server certificate.");
 
-               if (! crt.isEmpty() && qskKey.isNull()) {
-                       /* get key from certificate */
-                       qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
-                       if (! qskKey.isNull()) {
-                               logthis("Using key from certificate.");
-                       }
-               }
 
-       }
-#endif
+                       CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-       if (!rsa || !x509) {
-               Log_info("Generating new server certificate.");
+                       x509 = X509_new();
+                       pkey = EVP_PKEY_new();
+                       rsa = RSA_generate_key(4096,RSA_F4,NULL,NULL);
+                       EVP_PKEY_assign_RSA(pkey, rsa);
 
+                       X509_set_version(x509, 2);
+                       ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
+                       X509_gmtime_adj(X509_get_notBefore(x509),0);
+                       X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
+                       X509_set_pubkey(x509, pkey);
 
-               CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+                       X509_NAME *name=X509_get_subject_name(x509);
 
-               x509 = X509_new();
-               pkey = EVP_PKEY_new();
-               rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
-               EVP_PKEY_assign_RSA(pkey, rsa);
+                       X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
+                       X509_set_issuer_name(x509, name);
+                       SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
+                       SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
+                       SSL_add_ext(x509, NID_subject_key_identifier, "hash");
+                       SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
 
-               X509_set_version(x509, 2);
-               ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
-               X509_gmtime_adj(X509_get_notBefore(x509),0);
-               X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
-               X509_set_pubkey(x509, pkey);
+                       X509_sign(x509, pkey, EVP_md5());
 
-               X509_NAME *name=X509_get_subject_name(x509);
+                       SSL_writecert(crt, x509);
+                       SSL_writekey(key, rsa);
 
-               X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
-               X509_set_issuer_name(x509, name);
-               SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
-               SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
-               SSL_add_ext(x509, NID_subject_key_identifier, "hash");
-               SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
+                       SSL_CTX_use_certificate(context, x509);
+               } else {
+                 pkey = EVP_PKEY_new();
+                 EVP_PKEY_assign_RSA(pkey, rsa);
+               }
 
-               X509_sign(x509, pkey, EVP_md5());
+               SSL_CTX_use_PrivateKey(context, pkey);
 
-               SSL_writecert(crt, x509);
-               SSL_writekey(key, rsa);
+       } else {
+               Log_fatal("Failed to initialize TLS context.");
        }
 
 }
 
 void SSLi_init(void)
 {
-       SSL_METHOD *method;
        SSL *ssl;
        int i, offset = 0, cipherstringlen = 0;
        STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
-       SSL_CIPHER *cipher;
-       char *cipherstring, tempstring[128];
+       const SSL_CIPHER *cipher;
+       char *cipherstring = NULL;
 
        SSL_library_init();
-       OpenSSL_add_all_algorithms();           /* load & register all cryptos, etc. */
-       SSL_load_error_strings();                       /* load all error messages */
-       ERR_load_crypto_strings();                      /* load all error messages */
-       method = SSLv23_server_method();                /* create new server-method instance */
-       context = SSL_CTX_new(method);                  /* create new context from method */
+       OpenSSL_add_all_algorithms();
+       SSL_load_error_strings();
+       ERR_load_crypto_strings();
+
+       context = SSL_CTX_new(SSLv23_server_method());
+       SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
+       SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);
+       SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
        if (context == NULL)
        {
                ERR_print_errors_fp(stderr);
                abort();
        }
 
+       SSL_CTX_set_cipher_list(context, ciphers);
+
+       EC_KEY *ecdhkey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+       SSL_CTX_set_tmp_ecdh(context, ecdhkey);
+       EC_KEY_free(ecdhkey);
+
        char const * sslCAPath = getStrConf(CAPATH);
        if(sslCAPath != NULL)
        {
@@ -261,12 +219,6 @@ void SSLi_init(void)
        }
 
        SSL_initializeCert();
-       if (SSL_CTX_use_certificate(context, x509) <= 0)
-               Log_fatal("Failed to initialize cert");
-       if (SSL_CTX_use_PrivateKey(context, pkey) <= 0) {
-               ERR_print_errors_fp(stderr);
-               Log_fatal("Failed to initialize private key");
-       }
 
        /* Set cipher list */
        ssl = SSL_new(context);
@@ -284,9 +236,7 @@ void SSLi_init(void)
                        Log_debug("%s", SSL_CIPHER_get_name(cipher));
                        cipherstringlen += strlen(SSL_CIPHER_get_name(cipher)) + 1;
                }
-               cipherstring = malloc(cipherstringlen + 1);
-               if (cipherstring == NULL)
-                       Log_fatal("Out of memory");
+               cipherstring = Memory_safeMalloc(1, cipherstringlen + 1);
                for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
                        offset += sprintf(cipherstring + offset, "%s:", SSL_CIPHER_get_name(cipher));
                }
@@ -295,7 +245,7 @@ void SSLi_init(void)
        if (cipherlist_new)
                sk_SSL_CIPHER_free(cipherlist_new);
 
-       if (strlen(cipherstring) == 0)
+       if (!cipherstring || !*cipherstring)
                Log_fatal("No suitable ciphers found!");
 
        if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
@@ -362,10 +312,7 @@ bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
        }
 
        len = i2d_X509(x509, NULL);
-       buf = malloc(len);
-       if (buf == NULL) {
-               Log_fatal("malloc");
-       }
+       buf = Memory_safeMalloc(1, len);
 
        p = buf;
        i2d_X509(x509, &p);
@@ -438,7 +385,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
      * it for something special
      */
     if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
-           X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
+           X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
            Log_warn("issuer= %s", buf);
     }
     return 1;