CMP: fix status held in OSSL_CMP_CTX, in particular for genp messages
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Tue, 13 Sep 2022 13:43:59 +0000 (15:43 +0200)
committerDr. David von Oheimb <dev@ddvo.net>
Thu, 24 Nov 2022 13:00:46 +0000 (14:00 +0100)
On this occasion, replace magic constants by mnemonic ones; update doc

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Todd Short <todd.short@me.com>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/19205)

apps/cmp.c
crypto/cmp/cmp_client.c
crypto/cmp/cmp_ctx.c
crypto/cmp/cmp_msg.c
crypto/cmp/cmp_server.c
crypto/cmp/cmp_status.c
doc/man3/OSSL_CMP_CTX_new.pod
doc/man3/OSSL_CMP_exec_certreq.pod
include/openssl/cmp.h.in

index 24672144fe771ebaff51785434c48a337505940e..bc446a4654c03afb3e0b69ef0fc1a232d673c617 100644 (file)
@@ -2731,7 +2731,7 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx)
             (void)OSSL_CMP_CTX_set1_senderNonce(srv_cmp_ctx, NULL);
         }
         if (!ret || !keep_alive
-            || OSSL_CMP_CTX_get_status(srv_cmp_ctx) == -1
+            || OSSL_CMP_CTX_get_status(srv_cmp_ctx) != OSSL_CMP_PKISTATUS_trans
             /* transaction closed by OSSL_CMP_CTX_server_perform() */) {
             BIO_free_all(cbio);
             cbio = NULL;
@@ -2744,6 +2744,35 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx)
 }
 #endif
 
+static void print_status(void)
+{
+    /* print PKIStatusInfo */
+    int status = OSSL_CMP_CTX_get_status(cmp_ctx);
+    char *buf = app_malloc(OSSL_CMP_PKISI_BUFLEN, "PKIStatusInfo buf");
+    const char *string =
+        OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf, OSSL_CMP_PKISI_BUFLEN);
+    const char *from = "", *server = "";
+
+#ifndef OPENSSL_NO_SOCK
+    if (opt_server != NULL) {
+        from = " from ";
+        server = opt_server;
+    }
+#endif
+    CMP_print(bio_err,
+              status == OSSL_CMP_PKISTATUS_accepted
+              ? OSSL_CMP_LOG_INFO :
+              status == OSSL_CMP_PKISTATUS_rejection
+              || status == OSSL_CMP_PKISTATUS_waiting
+              ? OSSL_CMP_LOG_ERR : OSSL_CMP_LOG_WARNING,
+              status == OSSL_CMP_PKISTATUS_accepted ? "info" :
+              status == OSSL_CMP_PKISTATUS_rejection ? "server error" :
+              status == OSSL_CMP_PKISTATUS_waiting ? "internal error"
+              : "warning", "received%s%s %s", from, server,
+              string != NULL ? string : "<unknown PKIStatus>");
+    OPENSSL_free(buf);
+}
+
 int cmp_main(int argc, char **argv)
 {
     char *configfile = NULL;
@@ -2982,39 +3011,10 @@ int cmp_main(int argc, char **argv)
         default:
             break;
         }
-        if (OSSL_CMP_CTX_get_status(cmp_ctx) < 0)
+        if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted)
             goto err; /* we got no response, maybe even did not send request */
 
-        {
-            /* print PKIStatusInfo */
-            int status = OSSL_CMP_CTX_get_status(cmp_ctx);
-            char *buf = app_malloc(OSSL_CMP_PKISI_BUFLEN, "PKIStatusInfo buf");
-            const char *string =
-                OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf,
-                                               OSSL_CMP_PKISI_BUFLEN);
-            const char *from = "", *server = "";
-
-#ifndef OPENSSL_NO_SOCK
-            if (opt_server != NULL) {
-                from = " from ";
-                server = opt_server;
-            }
-#endif
-            CMP_print(bio_err,
-                      status == OSSL_CMP_PKISTATUS_accepted
-                      ? OSSL_CMP_LOG_INFO :
-                      status == OSSL_CMP_PKISTATUS_rejection
-                      || status == OSSL_CMP_PKISTATUS_waiting
-                      ? OSSL_CMP_LOG_ERR : OSSL_CMP_LOG_WARNING,
-                      status == OSSL_CMP_PKISTATUS_accepted ? "info" :
-                      status == OSSL_CMP_PKISTATUS_rejection ? "server error" :
-                      status == OSSL_CMP_PKISTATUS_waiting ? "internal error"
-                                                           : "warning",
-                      "received%s%s %s", from, server,
-                      string != NULL ? string : "<unknown PKIStatus>");
-            OPENSSL_free(buf);
-        }
-
+        print_status();
         if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx),
                             opt_extracertsout, "extra") < 0)
             ret = 0;
index cffd258f18e00330f03bf500d8fd6b9f3036e1aa..25f179e107f0c902d6a70130d2817a621dc44d91 100644 (file)
@@ -93,7 +93,8 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
     if (!ossl_assert(ctx != NULL && si != NULL))
         return 0;
 
-    if ((ctx->status = ossl_cmp_pkisi_get_status(si)) < 0)
+    ctx->status = ossl_cmp_pkisi_get_status(si);
+    if (ctx->status < OSSL_CMP_PKISTATUS_accepted)
         return 0;
 
     ctx->failInfoCode = 0;
@@ -356,7 +357,10 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
     return 0;
 }
 
-/* Send certConf for IR, CR or KUR sequences and check response */
+/*
+ * Send certConf for IR, CR or KUR sequences and check response,
+ * not modifying ctx->status during the certConf exchange
+ */
 int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
                                const char *txt)
 {
@@ -385,6 +389,7 @@ int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
     OSSL_CMP_MSG *PKIconf = NULL;
     int res = 0;
 
+    /* not overwriting ctx->status on error exchange */
     if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL)
         goto err;
     /* ossl_cmp_error_new() also checks if all necessary options are set */
@@ -643,7 +648,7 @@ static int initial_certreq(OSSL_CMP_CTX *ctx,
     OSSL_CMP_MSG *req;
     int res;
 
-    ctx->status = -1;
+    ctx->status = OSSL_CMP_PKISTATUS_request;
     if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
         return 0;
 
@@ -654,6 +659,7 @@ static int initial_certreq(OSSL_CMP_CTX *ctx,
     if ((req = ossl_cmp_certreq_new(ctx, req_type, crm)) == NULL)
         return 0;
 
+    ctx->status = OSSL_CMP_PKISTATUS_trans;
     res = send_receive_check(ctx, req, p_rep, rep_type);
     OSSL_CMP_MSG_free(req);
     return res;
@@ -742,16 +748,17 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
         ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
         return 0;
     }
+    ctx->status = OSSL_CMP_PKISTATUS_request;
     if (ctx->oldCert == NULL && ctx->p10CSR == NULL) {
         ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
         return 0;
     }
-    ctx->status = -1;
 
     /* OSSL_CMP_rr_new() also checks if all necessary options are set */
     if ((rr = ossl_cmp_rr_new(ctx)) == NULL)
         goto end;
 
+    ctx->status = OSSL_CMP_PKISTATUS_trans;
     if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
         goto end;
 
@@ -861,27 +868,31 @@ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
 {
     OSSL_CMP_MSG *genm;
     OSSL_CMP_MSG *genp = NULL;
-    STACK_OF(OSSL_CMP_ITAV) *rcvd_itavs = NULL;
+    STACK_OF(OSSL_CMP_ITAV) *itavs = NULL;
 
     if (ctx == NULL) {
         ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
-        return 0;
+        return NULL;
     }
-    ctx->status = -1;
+    ctx->status = OSSL_CMP_PKISTATUS_request;
 
     if ((genm = ossl_cmp_genm_new(ctx)) == NULL)
         goto err;
 
+    ctx->status = OSSL_CMP_PKISTATUS_trans;
     if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
         goto err;
+    ctx->status = OSSL_CMP_PKISTATUS_accepted;
 
+    itavs = genp->body->value.genp;
+    if (itavs == NULL)
+        itavs = sk_OSSL_CMP_ITAV_new_null();
     /* received stack of itavs not to be freed with the genp */
-    rcvd_itavs = genp->body->value.genp;
     genp->body->value.genp = NULL;
 
  err:
     OSSL_CMP_MSG_free(genm);
     OSSL_CMP_MSG_free(genp);
 
-    return rcvd_itavs; /* recv_itavs == NULL indicates an error */
+    return itavs; /* NULL indicates error case */
 }
index eb0cf35f8407763b1fce09990144b3e54370bc62..fd71ba099b5fc092ce451a46ead7101cb5737702 100644 (file)
@@ -118,7 +118,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
 
     ctx->log_verbosity = OSSL_CMP_LOG_INFO;
 
-    ctx->status = -1;
+    ctx->status = OSSL_CMP_PKISTATUS_unspecified;
     ctx->failInfoCode = -1;
 
     ctx->keep_alive = 1;
@@ -161,7 +161,7 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
         ossl_cmp_debug(ctx, "disconnected from CMP server");
         ctx->http_ctx = NULL;
     }
-    ctx->status = -1;
+    ctx->status = OSSL_CMP_PKISTATUS_unspecified;
     ctx->failInfoCode = -1;
 
     return ossl_cmp_ctx_set0_statusString(ctx, NULL)
index dc33d8d0b3ec1fcf425bb2383bb24d4a0068c7cc..6a6f30c1a1eeec091fd8bd518fcdb584de8f6abb 100644 (file)
@@ -462,7 +462,7 @@ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
     OSSL_CMP_MSG *msg = NULL;
     OSSL_CMP_CERTREPMESSAGE *repMsg = NULL;
     OSSL_CMP_CERTRESPONSE *resp = NULL;
-    int status = -1;
+    int status = OSSL_CMP_PKISTATUS_unspecified;
 
     if (!ossl_assert(ctx != NULL && si != NULL))
         return NULL;
index bf5c5fdb57488b407fb758ca8a4ea0630e7ab0d9..83bf4ac15744d426dbbf897c2c7f963187883f80 100644 (file)
@@ -338,7 +338,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
     num = sk_OSSL_CMP_CERTSTATUS_num(ccc);
 
     if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1
-            || ctx->status != -2 /* transaction not open */) {
+            || ctx->status != OSSL_CMP_PKISTATUS_trans) {
         ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_UNEXPECTED_CERTCONF);
         return NULL;
     }
@@ -359,8 +359,8 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
         if (!srv_ctx->process_certConf(srv_ctx, req, certReqId, certHash, si))
             return NULL; /* reason code may be: CMP_R_CERTHASH_UNMATCHED */
 
-        if (si != NULL && ossl_cmp_pkisi_get_status(si)
-            != OSSL_CMP_PKISTATUS_accepted) {
+        if (si != NULL
+            && ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_accepted) {
             int pki_status = ossl_cmp_pkisi_get_status(si);
             const char *str = ossl_cmp_PKIStatus_to_string(pki_status);
 
@@ -593,8 +593,8 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
     else
         ossl_cmp_log(ERR, ctx, "cannot send proper CMP response");
 
-    /* possibly close the transaction */
-    ctx->status = -2; /* this indicates transaction is open */
+    /* determine whether to keep the transaction open or not */
+    ctx->status = OSSL_CMP_PKISTATUS_trans;
     switch (rsp_type) {
     case OSSL_CMP_PKIBODY_IP:
     case OSSL_CMP_PKIBODY_CP:
@@ -609,7 +609,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
     case OSSL_CMP_PKIBODY_ERROR:
         (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL);
         (void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL);
-        ctx->status = -1; /* transaction closed */
+        ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */
 
     default: /* not closing transaction in other cases */
         break;
index bb93ac9389dd0f8a064fdaa21169a02276dab745..176c546f9c99ccece3dcb34b521c552a49653419 100644 (file)
@@ -189,7 +189,10 @@ char *snprint_PKIStatusInfo_parts(int status, int fail_info,
     printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string);
     ADVANCE_BUFFER;
 
-    /* failInfo is optional and may be empty */
+    /*
+     * failInfo is optional and may be empty;
+     * if present, print failInfo before statusString because it is more concise
+     */
     if (fail_info != 0) {
         printed_chars = BIO_snprintf(write_ptr, bufsize, "; PKIFailureInfo: ");
         ADVANCE_BUFFER;
index bc027cab1b8a40900f38dc53893479c5274e8655..1949a60910e13882fec3ed2a8f10fa40ce0fc9f5 100644 (file)
@@ -632,9 +632,29 @@ OSSL_CMP_CTX_get_certConf_cb_arg() gets the argument, respectively the pointer
 to a structure containing arguments, previously set by
 OSSL_CMP_CTX_set_certConf_cb_arg(), or NULL if unset.
 
-OSSL_CMP_CTX_get_status() returns the PKIstatus from the last received
-CertRepMessage or Revocation Response or error message, or -1 if unset.
-For server contexts it returns -2 if a transaction is open, else -1.
+OSSL_CMP_CTX_get_status() returns for client contexts the PKIstatus from
+the last received CertRepMessage or Revocation Response or error message:
+=item B<OSSL_CMP_PKISTATUS_accepted> on sucessful receipt of a GENP message:
+
+=over 4
+
+=item B<OSSL_CMP_PKISTATUS_request>
+
+if an IR/CR/KUR/RR/GENM request message could not be produced,
+
+=item B<OSSL_CMP_PKISTATUS_trans>
+
+on a transmission error or transaction error for this type of request, and
+
+=item B<OSSL_CMP_PKISTATUS_unspecified>
+
+if no such request was attempted or OSSL_CMP_CTX_reinit() has been called.
+
+=back
+
+For server contexts it returns
+B<OSSL_CMP_PKISTATUS_trans> if a transaction is open,
+otherwise B<OSSL_CMP_PKISTATUS_unspecified>.
 
 OSSL_CMP_CTX_get0_statusString() returns the statusString from the last received
 CertRepMessage or Revocation Response or error message, or NULL if unset.
index 60e2cf0f226862ea1a494d24881fdc4b06a4a941..b0d81c7c41a96894d96f91e72c3119c2b4b889ca 100644 (file)
@@ -109,8 +109,9 @@ make no sense for revocation and thus are treated as an error as well.
 
 OSSL_CMP_exec_GENM_ses() sends a general message containing the sequence of
 infoType and infoValue pairs (InfoTypeAndValue; short: B<ITAV>)
-provided in the I<ctx> using L<OSSL_CMP_CTX_push0_genm_ITAV(3)>.
-It returns the list of B<ITAV>s received in the GenRep.
+optionally provided in the I<ctx> using L<OSSL_CMP_CTX_push0_genm_ITAV(3)>.
+On success it records in I<ctx> the status B<OSSL_CMP_PKISTATUS_accepted>
+and returns the list of B<ITAV>s received in the GENP message.
 This can be used, for instance, to poll for CRLs or CA Key Updates.
 See RFC 4210 section 5.3.19 and appendix E.5 for details.
 
@@ -139,8 +140,8 @@ assign the received value unless I<checkAfter> is NULL.
 
 OSSL_CMP_exec_RR_ses() returns 1 on success, 0 on error.
 
-OSSL_CMP_exec_GENM_ses() returns a
-pointer to the received B<ITAV> sequence on success, NULL on error.
+OSSL_CMP_exec_GENM_ses() returns NULL on error,
+otherwise a pointer to the sequence of B<ITAV> received, which may be empty.
 This pointer must be freed by the caller.
 
 =head1 EXAMPLES
index 1125ef2133addb2c5639f5b6b4cf46f95c53ca34..79c9414e30dfed1663cf24a9651738d5d5a6dc4f 100644 (file)
@@ -196,13 +196,16 @@ typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
  *       -- CertReqMsg
  *   }
  */
-#  define OSSL_CMP_PKISTATUS_accepted 0
-#  define OSSL_CMP_PKISTATUS_grantedWithMods 1
-#  define OSSL_CMP_PKISTATUS_rejection 2
-#  define OSSL_CMP_PKISTATUS_waiting 3
-#  define OSSL_CMP_PKISTATUS_revocationWarning 4
+#  define OSSL_CMP_PKISTATUS_request                -3
+#  define OSSL_CMP_PKISTATUS_trans                  -2
+#  define OSSL_CMP_PKISTATUS_unspecified            -1
+#  define OSSL_CMP_PKISTATUS_accepted               0
+#  define OSSL_CMP_PKISTATUS_grantedWithMods        1
+#  define OSSL_CMP_PKISTATUS_rejection              2
+#  define OSSL_CMP_PKISTATUS_waiting                3
+#  define OSSL_CMP_PKISTATUS_revocationWarning      4
 #  define OSSL_CMP_PKISTATUS_revocationNotification 5
-#  define OSSL_CMP_PKISTATUS_keyUpdateWarning 6
+#  define OSSL_CMP_PKISTATUS_keyUpdateWarning       6
 
 typedef ASN1_INTEGER OSSL_CMP_PKISTATUS;
 DECLARE_ASN1_ITEM(OSSL_CMP_PKISTATUS)