Use safer sizeof variant in malloc
[openssl.git] / ssl / ssl_conf.c
index cfed40ddc2bd4fa4d754c579a3c6fc32f4b92777..a14f564f246f4cb1b780bfd297c92df955ac7179 100644 (file)
@@ -119,6 +119,8 @@ struct ssl_conf_ctx_st {
     SSL *ssl;
     /* Pointer to SSL or SSL_CTX options field or NULL if none */
     unsigned long *poptions;
+    /* Certificate filenames for each type */
+    char *cert_filename[SSL_PKEY_NUM];
     /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
     unsigned int *pcert_flags;
     /* Current flag table being worked on */
@@ -190,6 +192,7 @@ static int ssl_set_option_list(const char *elem, int len, void *usr)
 /* Single command line switches with no argument e.g. -no_ssl3 */
 static int ctrl_str_option(SSL_CONF_CTX *cctx, const char *cmd)
 {
+    /* See apps/apps.h if you change this table. */
     static const ssl_flag_tbl ssl_option_single[] = {
         SSL_FLAG_TBL("no_ssl3", SSL_OP_NO_SSLv3),
         SSL_FLAG_TBL("no_tls1", SSL_OP_NO_TLSv1),
@@ -217,7 +220,7 @@ static int ctrl_str_option(SSL_CONF_CTX *cctx, const char *cmd)
 #endif
     };
     cctx->tbl = ssl_option_single;
-    cctx->ntbl = sizeof(ssl_option_single) / sizeof(ssl_flag_tbl);
+    cctx->ntbl = OSSL_NELEM(ssl_option_single);
     return ssl_set_option_list(cmd, -1, cctx);
 }
 
@@ -332,7 +335,7 @@ static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value)
     if (!(cctx->flags & SSL_CONF_FLAG_FILE))
         return -2;
     cctx->tbl = ssl_protocol_list;
-    cctx->ntbl = sizeof(ssl_protocol_list) / sizeof(ssl_flag_tbl);
+    cctx->ntbl = OSSL_NELEM(ssl_protocol_list);
     return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
 }
 
@@ -357,19 +360,32 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
     if (value == NULL)
         return -3;
     cctx->tbl = ssl_option_list;
-    cctx->ntbl = sizeof(ssl_option_list) / sizeof(ssl_flag_tbl);
+    cctx->ntbl = OSSL_NELEM(ssl_option_list);
     return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
 }
 
 static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
 {
     int rv = 1;
+    CERT *c = NULL;
     if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
         return -2;
-    if (cctx->ctx)
+    if (cctx->ctx) {
         rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
-    if (cctx->ssl)
+        c = cctx->ctx->cert;
+    }
+    if (cctx->ssl) {
         rv = SSL_use_certificate_file(cctx->ssl, value, SSL_FILETYPE_PEM);
+        c = cctx->ssl->cert;
+    }
+    if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+        char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
+        OPENSSL_free(*pfilename);
+        *pfilename = BUF_strdup(value);
+        if (!*pfilename)
+            rv = 0;
+    }
+
     return rv > 0;
 }
 
@@ -421,10 +437,8 @@ static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
     if (cctx->ssl)
         rv = SSL_set_tmp_dh(cctx->ssl, dh);
  end:
-    if (dh)
-        DH_free(dh);
-    if (in)
-        BIO_free(in);
+    DH_free(dh);
+    BIO_free(in);
     return rv > 0;
 }
 #endif
@@ -443,6 +457,7 @@ typedef struct {
 #define SSL_CONF_CMD_STRING(name, cmdopt) \
         SSL_CONF_CMD(name, cmdopt, SSL_CONF_TYPE_STRING)
 
+/* See apps/apps.h if you change this table. */
 static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
     SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs"),
     SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs"),
@@ -493,8 +508,7 @@ static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
         return NULL;
 
     /* Look for matching parameter name in table */
-    for (i = 0, t = ssl_conf_cmds;
-         i < sizeof(ssl_conf_cmds) / sizeof(ssl_conf_cmd_tbl); i++, t++) {
+    for (i = 0, t = ssl_conf_cmds; i < OSSL_NELEM(ssl_conf_cmds); i++, t++) {
         if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
             if (t->str_cmdline && !strcmp(t->str_cmdline, cmd))
                 return t;
@@ -595,8 +609,9 @@ int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
 
 SSL_CONF_CTX *SSL_CONF_CTX_new(void)
 {
-    SSL_CONF_CTX *ret;
-    ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX));
+    SSL_CONF_CTX *ret = OPENSSL_malloc(sizeof(*ret));
+    size_t i;
+
     if (ret) {
         ret->flags = 0;
         ret->prefix = NULL;
@@ -607,20 +622,44 @@ SSL_CONF_CTX *SSL_CONF_CTX_new(void)
         ret->pcert_flags = NULL;
         ret->tbl = NULL;
         ret->ntbl = 0;
+        for (i = 0; i < SSL_PKEY_NUM; i++)
+            ret->cert_filename[i] = NULL;
     }
     return ret;
 }
 
 int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
 {
+    /* See if any certificates are missing private keys */
+    size_t i;
+    CERT *c = NULL;
+    if (cctx->ctx)
+        c = cctx->ctx->cert;
+    else if (cctx->ssl)
+        c = cctx->ssl->cert;
+    if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+        for (i = 0; i < SSL_PKEY_NUM; i++) {
+            const char *p = cctx->cert_filename[i];
+            /*
+             * If missing private key try to load one from certificate file
+             */
+            if (p && !c->pkeys[i].privatekey) {
+                if (!cmd_PrivateKey(cctx, p))
+                    return 0;
+            }
+        }
+    }
     return 1;
 }
 
 void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
 {
     if (cctx) {
-        if (cctx->prefix)
-            OPENSSL_free(cctx->prefix);
+        size_t i;
+        for (i = 0; i < SSL_PKEY_NUM; i++) {
+            OPENSSL_free(cctx->cert_filename[i]);
+        }
+        OPENSSL_free(cctx->prefix);
         OPENSSL_free(cctx);
     }
 }
@@ -645,8 +684,7 @@ int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre)
         if (tmp == NULL)
             return 0;
     }
-    if (cctx->prefix)
-        OPENSSL_free(cctx->prefix);
+    OPENSSL_free(cctx->prefix);
     cctx->prefix = tmp;
     if (tmp)
         cctx->prefixlen = strlen(tmp);