add OSSL_STACK_OF_X509_free() for commonly used pattern
[openssl.git] / apps / cmp.c
index e35626ebb2faad9160ada6698a482cbec003edc2..0f810129b3924cc0e55b8fbbcfbbdfa85c13c823 100644 (file)
@@ -161,7 +161,7 @@ static char *opt_rspin = NULL;
 static char *opt_rspout = NULL;
 static int opt_use_mock_srv = 0;
 
-/* server-side debugging */
+/* mock server */
 #ifndef OPENSSL_NO_SOCK
 static char *opt_port = NULL;
 static int opt_max_msgs = 0;
@@ -287,7 +287,7 @@ const OPTIONS cmp_options[] = {
     {"subject", OPT_SUBJECT, 's',
      "Distinguished Name (DN) of subject to use in the requested cert template"},
     {OPT_MORE_STR, 0, 0,
-     "For kur, default is subject of -csr arg or else of reference cert (see -oldcert)"},
+     "For kur, default is subject of -csr arg or reference cert (see -oldcert)"},
     {OPT_MORE_STR, 0, 0,
      "this default is used for ir and cr only if no Subject Alt Names are set"},
     {"issuer", OPT_ISSUER, 's',
@@ -336,7 +336,7 @@ const OPTIONS cmp_options[] = {
     {OPT_MORE_STR, 0, 0,
      "also used as reference (defaulting to -cert) for subject DN and SANs."},
     {OPT_MORE_STR, 0, 0,
-     "Its issuer is used as recipient unless -recipient, -srvcert, or -issuer given"},
+     "Issuer is used as recipient unless -recipient, -srvcert, or -issuer given"},
     {"revreason", OPT_REVREASON, 'n',
      "Reason code to include in revocation request (rr); possible values:"},
     {OPT_MORE_STR, 0, 0,
@@ -470,14 +470,16 @@ const OPTIONS cmp_options[] = {
      "Process sequence of CMP responses provided in file(s), skipping server"},
     {"rspout", OPT_RSPOUT, 's', "Save sequence of CMP responses to file(s)"},
 
-    {"use_mock_srv", OPT_USE_MOCK_SRV, '-', "Use mock server at API level, bypassing HTTP"},
+    {"use_mock_srv", OPT_USE_MOCK_SRV, '-',
+     "Use internal mock server at API level, bypassing socket-based HTTP"},
 
     OPT_SECTION("Mock server"),
 #ifdef OPENSSL_NO_SOCK
     {OPT_MORE_STR, 0, 0,
      "NOTE: -port and -max_msgs not supported due to no-sock build"},
 #else
-    {"port", OPT_PORT, 's', "Act as HTTP mock server listening on given port"},
+    {"port", OPT_PORT, 's',
+     "Act as HTTP-based mock server listening on given port"},
     {"max_msgs", OPT_MAX_MSGS, 'N',
      "max number of messages handled by HTTP mock server. Default: 0 = unlimited"},
 #endif
@@ -789,8 +791,7 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
     OSSL_CMP_PKIHEADER *hdr;
     const char *prev_opt_rspin = opt_rspin;
 
-    if (req != NULL && opt_reqout != NULL
-            && !write_PKIMESSAGE(req, &opt_reqout))
+    if (opt_reqout != NULL && !write_PKIMESSAGE(req, &opt_reqout))
         goto err;
     if (opt_reqin != NULL && opt_rspin == NULL) {
         if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL)
@@ -932,7 +933,7 @@ static int setup_certs(char *files, const char *desc, void *ctx,
     if ((certs = load_certs_multifile(files, opt_otherpass, desc, vpm)) == NULL)
         return 0;
     ok = (*set1_fn)(ctx, certs);
-    sk_X509_pop_free(certs, X509_free);
+    OSSL_STACK_OF_X509_free(certs);
     return ok;
 }
 
@@ -1001,7 +1002,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     if (opt_srv_ref == NULL) {
         if (opt_srv_cert == NULL) {
             /* opt_srv_cert should determine the sender */
-            CMP_err("must give -srv_ref for server if no -srv_cert given");
+            CMP_err("must give -srv_ref for mock server if no -srv_cert given");
             goto err;
         }
     } else {
@@ -1012,7 +1013,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
 
     if (opt_srv_secret != NULL) {
         int res;
-        char *pass_str = get_passwd(opt_srv_secret, "PBMAC secret of server");
+        char *pass_str = get_passwd(opt_srv_secret, "PBMAC secret of mock server");
 
         if (pass_str != NULL) {
             cleanse(opt_srv_secret);
@@ -1023,10 +1024,10 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
                 goto err;
         }
     } else if (opt_srv_cert == NULL) {
-        CMP_err("server credentials must be given if -use_mock_srv or -port is used");
+        CMP_err("mock server credentials must be given if -use_mock_srv or -port is used");
         goto err;
     } else {
-        CMP_warn("server will not be able to handle PBM-protected requests since -srv_secret is not given");
+        CMP_warn("mock server will not be able to handle PBM-protected requests since -srv_secret is not given");
     }
 
     if (opt_srv_secret == NULL
@@ -1036,7 +1037,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     }
     if (opt_srv_cert != NULL) {
         X509 *srv_cert = load_cert_pwd(opt_srv_cert, opt_srv_keypass,
-                                       "certificate of the server");
+                                       "certificate of the mock server");
 
         if (srv_cert == NULL || !OSSL_CMP_CTX_set1_cert(ctx, srv_cert)) {
             X509_free(srv_cert);
@@ -1047,7 +1048,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     if (opt_srv_key != NULL) {
         EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform,
                                       opt_srv_keypass,
-                                      engine, "private key for server cert");
+                                      engine, "private key for mock server cert");
 
         if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
             EVP_PKEY_free(pkey);
@@ -1059,14 +1060,14 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
 
     if (opt_srv_trusted != NULL) {
         X509_STORE *ts =
-            load_trusted(opt_srv_trusted, 0, "certs trusted by server");
+            load_trusted(opt_srv_trusted, 0, "certs trusted by mock server");
 
         if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
             X509_STORE_free(ts);
             goto err;
         }
     } else {
-        CMP_warn("server will not be able to handle signature-protected requests since -srv_trusted is not given");
+        CMP_warn("mock server will not be able to handle signature-protected requests since -srv_trusted is not given");
     }
     if (!setup_certs(opt_srv_untrusted,
                      "untrusted certificates for mock server", ctx,
@@ -1074,8 +1075,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
         goto err;
 
     if (opt_rsp_cert == NULL) {
-        CMP_err("must give -rsp_cert for mock server");
-        goto err;
+        CMP_warn("no -rsp_cert given for mock server");
     } else {
         X509 *cert = load_cert_pwd(opt_rsp_cert, opt_keypass,
                                    "cert to be returned by the mock server");
@@ -1262,7 +1262,7 @@ static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host,
         if (!ok || !SSL_CTX_set0_chain(ssl_ctx, certs)) {
             CMP_err1("unable to use client TLS certificate file '%s'",
                      opt_tls_cert);
-            sk_X509_pop_free(certs, X509_free);
+            OSSL_STACK_OF_X509_free(certs);
             goto err;
         }
         for (i = 0; i < sk_X509_num(untrusted); i++) {
@@ -1441,7 +1441,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
             ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs);
         }
         X509_STORE_free(own_trusted);
-        sk_X509_pop_free(certs, X509_free);
+        OSSL_STACK_OF_X509_free(certs);
         if (!ok)
             return 0;
     } else if (opt_own_trusted != NULL) {
@@ -1805,13 +1805,31 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     static char server_port[32] = { '\0' };
     const char *proxy_host = NULL;
 #endif
-    char server_buf[200] = { '\0' };
-    char proxy_buf[200] = { '\0' };
+    char server_buf[200] = "mock server";
+    char proxy_buf[200] = "";
 
+    if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */
 #ifndef OPENSSL_NO_SOCK
-    if (opt_server == NULL) {
-        CMP_err("missing -server option");
+        if (opt_server == NULL) {
+            CMP_err("missing -server or -use_mock_srv or -rspin option");
+            goto err;
+        }
+#else
+        CMP_err("missing -use_mock_srv or -rspin option; -server option is not supported due to no-sock build");
         goto err;
+#endif
+    }
+#ifndef OPENSSL_NO_SOCK
+    if (opt_server == NULL) {
+        if (opt_proxy != NULL)
+            CMP_warn("ignoring -proxy option since -server is not given");
+        if (opt_no_proxy != NULL)
+            CMP_warn("ignoring -no_proxy option since -server is not given");
+        if (opt_tls_used) {
+            CMP_warn("ignoring -tls_used option since -server is not given");
+            opt_tls_used = 0;
+        }
+        goto set_path;
     }
     if (!OSSL_HTTP_parse_url(opt_server, &ssl, NULL /* user */, &host, &port,
                              &portnum, &path, NULL /* q */, NULL /* frag */)) {
@@ -1841,6 +1859,7 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     if (proxy_host != NULL)
         (void)BIO_snprintf(proxy_buf, sizeof(proxy_buf), " via %s", proxy_host);
 
+ set_path:
 #endif
 
     if (!OSSL_CMP_CTX_set1_serverPath(ctx, used_path))
@@ -1886,11 +1905,6 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         (void)OSSL_CMP_CTX_set_transfer_cb(ctx, read_write_req_resp);
 
 #ifndef OPENSSL_NO_SOCK
-    if ((opt_tls_cert != NULL || opt_tls_key != NULL
-         || opt_tls_keypass != NULL || opt_tls_extra != NULL
-         || opt_tls_trusted != NULL || opt_tls_host != NULL)
-            && !opt_tls_used)
-        CMP_warn("TLS options(s) given but not -tls_used");
     if (opt_tls_used) {
         APP_HTTP_TLS_INFO *info;
 
@@ -1904,10 +1918,6 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
                 goto err;
             }
         }
-        if (opt_use_mock_srv) {
-            CMP_err("cannot use TLS options together with -use_mock_srv");
-            goto err;
-        }
         if ((info = OPENSSL_zalloc(sizeof(*info))) == NULL)
             goto err;
         (void)OSSL_CMP_CTX_set_http_cb_arg(ctx, info);
@@ -1938,7 +1948,10 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         goto err;
 
     /* not printing earlier, to minimize confusion in case setup fails before */
-    CMP_info2("will contact %s%s", server_buf, proxy_buf);
+    if (opt_rspin != NULL)
+        CMP_info("will not contact any server since -rspin is given");
+    else
+        CMP_info2("will contact %s%s", server_buf, proxy_buf);
 
     ret = 1;
 
@@ -2007,7 +2020,7 @@ static int save_free_certs(OSSL_CMP_CTX *ctx,
 
  end:
     BIO_free(bio);
-    sk_X509_pop_free(certs, X509_free);
+    OSSL_STACK_OF_X509_free(certs);
     return n;
 }
 
@@ -2690,9 +2703,6 @@ int cmp_main(int argc, char **argv)
     int i;
     X509 *newcert = NULL;
     ENGINE *engine = NULL;
-#ifndef OPENSSL_NO_SOCK
-    char mock_server[] = "mock server:1";
-#endif
     OSSL_CMP_CTX *srv_cmp_ctx = NULL;
     int ret = 0; /* default: failure */
 
@@ -2783,27 +2793,41 @@ int cmp_main(int argc, char **argv)
         }
     }
 
+    cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
+    if (cmp_ctx == NULL)
+        goto err;
+    OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity);
+    if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) {
+        CMP_err1("cannot set up error reporting and logging for %s", prog);
+        goto err;
+    }
+
 #ifndef OPENSSL_NO_SOCK
+    if ((opt_tls_cert != NULL || opt_tls_key != NULL
+         || opt_tls_keypass != NULL || opt_tls_extra != NULL
+         || opt_tls_trusted != NULL || opt_tls_host != NULL)
+            && !opt_tls_used)
+        CMP_warn("Ingnoring TLS options(s) since -tls_used is not given");
     if (opt_port != NULL) {
-        if (opt_use_mock_srv) {
-            CMP_err("cannot use both -port and -use_mock_srv options");
+        if (opt_tls_used) {
+            CMP_err("-tls_used option not supported with -port option");
             goto err;
         }
-        if (opt_server != NULL) {
-            CMP_err("cannot use both -port and -server options");
+        if (opt_use_mock_srv || opt_server != NULL || opt_rspin != NULL) {
+            CMP_err("cannot use -port with -use_mock_srv, -server, or -rspin options");
             goto err;
         }
     }
-#endif
-
-    cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
-    if (cmp_ctx == NULL)
+    if (opt_server != NULL && opt_use_mock_srv) {
+        CMP_err("cannot use both -server and -use_mock_srv options");
         goto err;
-    OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity);
-    if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) {
-        CMP_err1("cannot set up error reporting and logging for %s", prog);
+    }
+#endif
+    if (opt_rspin != NULL && opt_use_mock_srv) {
+        CMP_err("cannot use both -rspin and -use_mock_srv options");
         goto err;
     }
+
     if (opt_use_mock_srv
 #ifndef OPENSSL_NO_SOCK
         || opt_port != NULL
@@ -2822,29 +2846,26 @@ int cmp_main(int argc, char **argv)
         OSSL_CMP_CTX_set_log_verbosity(srv_cmp_ctx, opt_verbosity);
     }
 
-
 #ifndef OPENSSL_NO_SOCK
+    if (opt_tls_used && (opt_use_mock_srv || opt_rspin != NULL)) {
+        CMP_warn("ignoring -tls_used option since -use_mock_srv or -rspin is given");
+        opt_tls_used = 0;
+    }
+
     if (opt_port != NULL) { /* act as very basic CMP HTTP server */
         ret = cmp_server(srv_cmp_ctx);
         goto err;
     }
-#endif
-    /* else act as CMP client */
 
-    if (opt_use_mock_srv) {
-#ifndef OPENSSL_NO_SOCK
-        if (opt_server != NULL) {
-            CMP_err("cannot use both -use_mock_srv and -server options");
-            goto err;
-        }
-        if (opt_proxy != NULL) {
-            CMP_err("cannot use both -use_mock_srv and -proxy options");
-            goto err;
+    /* act as CMP client, possibly using internal mock server */
+
+    if (opt_server != NULL) {
+        if (opt_rspin != NULL) {
+            CMP_warn("ignoring -server option since -rspin is given");
+            opt_server = NULL;
         }
-        opt_server = mock_server;
-        opt_proxy = "API";
-#endif
     }
+#endif
 
     if (!setup_client_ctx(cmp_ctx, engine)) {
         CMP_err("cannot set up CMP context");