mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-04-28 10:44:38 +00:00
Add OSSL_CMP_CTX_get1_newChain() and related CLI option -chainout
Also simplify certificate saving in apps/cmp.c Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/12790)
This commit is contained in:
parent
09e76c5dd3
commit
39082af2fa
69
apps/cmp.c
69
apps/cmp.c
@ -129,6 +129,7 @@ static char *opt_out_trusted = NULL;
|
||||
static int opt_implicit_confirm = 0;
|
||||
static int opt_disable_confirm = 0;
|
||||
static char *opt_certout = NULL;
|
||||
static char *opt_chainout = NULL;
|
||||
|
||||
/* certificate enrollment and revocation */
|
||||
static char *opt_oldcert = NULL;
|
||||
@ -205,7 +206,7 @@ typedef enum OPTION_choice {
|
||||
OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL,
|
||||
OPT_POPO, OPT_CSR,
|
||||
OPT_OUT_TRUSTED, OPT_IMPLICIT_CONFIRM, OPT_DISABLE_CONFIRM,
|
||||
OPT_CERTOUT,
|
||||
OPT_CERTOUT, OPT_CHAINOUT,
|
||||
|
||||
OPT_OLDCERT, OPT_REVREASON,
|
||||
|
||||
@ -314,6 +315,8 @@ const OPTIONS cmp_options[] = {
|
||||
"confirmation. WARNING: This leads to behavior violating RFC 4210"},
|
||||
{"certout", OPT_CERTOUT, 's',
|
||||
"File to save newly enrolled certificate"},
|
||||
{"chainout", OPT_CHAINOUT, 's',
|
||||
"File to save the chain of newly enrolled certificate"},
|
||||
|
||||
OPT_SECTION("Certificate enrollment and revocation"),
|
||||
|
||||
@ -521,7 +524,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
|
||||
{(char **)&opt_popo}, {&opt_csr},
|
||||
{&opt_out_trusted},
|
||||
{(char **)&opt_implicit_confirm}, {(char **)&opt_disable_confirm},
|
||||
{&opt_certout},
|
||||
{&opt_certout}, {&opt_chainout},
|
||||
|
||||
{&opt_oldcert}, {(char **)&opt_revreason},
|
||||
|
||||
@ -2066,18 +2069,21 @@ static int write_cert(BIO *bio, X509 *cert)
|
||||
}
|
||||
|
||||
/*
|
||||
* writes out a stack of certs to the given file.
|
||||
* If destFile != NULL writes out a stack of certs to the given file.
|
||||
* In any case frees the certs.
|
||||
* Depending on options use either PEM or DER format,
|
||||
* where DER does not make much sense for writing more than one cert!
|
||||
* Returns number of written certificates on success, 0 on error.
|
||||
* Returns number of written certificates on success, -1 on error.
|
||||
*/
|
||||
static int save_certs(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *certs, char *destFile, char *desc)
|
||||
static int save_free_certs(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *certs, char *destFile, char *desc)
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
int i;
|
||||
int n = sk_X509_num(certs);
|
||||
|
||||
if (destFile == NULL)
|
||||
goto end;
|
||||
CMP_info3("received %d %s certificate(s), saving to file '%s'",
|
||||
n, desc, destFile);
|
||||
if (n > 1 && opt_certform != FORMAT_PEM)
|
||||
@ -2087,19 +2093,20 @@ static int save_certs(OSSL_CMP_CTX *ctx,
|
||||
|| !BIO_write_filename(bio, (char *)destFile)) {
|
||||
CMP_err1("could not open file '%s' for writing", destFile);
|
||||
n = -1;
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!write_cert(bio, sk_X509_value(certs, i))) {
|
||||
CMP_err1("cannot write certificate to file '%s'", destFile);
|
||||
n = -1;
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
end:
|
||||
BIO_free(bio);
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -2511,6 +2518,9 @@ static int get_opts(int argc, char **argv)
|
||||
case OPT_CERTOUT:
|
||||
opt_certout = opt_str("certout");
|
||||
break;
|
||||
case OPT_CHAINOUT:
|
||||
opt_chainout = opt_str("chainout");
|
||||
break;
|
||||
case OPT_OLDCERT:
|
||||
opt_oldcert = opt_str("oldcert");
|
||||
break;
|
||||
@ -2935,39 +2945,26 @@ int cmp_main(int argc, char **argv)
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
|
||||
if (opt_cacertsout != NULL) {
|
||||
STACK_OF(X509) *certs = OSSL_CMP_CTX_get1_caPubs(cmp_ctx);
|
||||
|
||||
if (sk_X509_num(certs) > 0
|
||||
&& save_certs(cmp_ctx, certs, opt_cacertsout, "CA") < 0) {
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
goto err;
|
||||
}
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
}
|
||||
|
||||
if (opt_extracertsout != NULL) {
|
||||
STACK_OF(X509) *certs = OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx);
|
||||
if (sk_X509_num(certs) > 0
|
||||
&& save_certs(cmp_ctx, certs, opt_extracertsout,
|
||||
"extra") < 0) {
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
goto err;
|
||||
}
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
}
|
||||
|
||||
if (opt_certout != NULL && newcert != NULL) {
|
||||
if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_caPubs(cmp_ctx),
|
||||
opt_cacertsout, "CA") < 0)
|
||||
goto err;
|
||||
if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx),
|
||||
opt_extracertsout, "extra") < 0)
|
||||
goto err;
|
||||
if (newcert != NULL) {
|
||||
STACK_OF(X509) *certs = sk_X509_new_null();
|
||||
|
||||
if (certs == NULL || !sk_X509_push(certs, newcert)
|
||||
|| save_certs(cmp_ctx, certs, opt_certout,
|
||||
"enrolled") < 0) {
|
||||
if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) {
|
||||
sk_X509_free(certs);
|
||||
goto err;
|
||||
}
|
||||
sk_X509_free(certs);
|
||||
if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0)
|
||||
goto err;
|
||||
}
|
||||
if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx),
|
||||
opt_chainout, "chain") < 0)
|
||||
goto err;
|
||||
|
||||
if (!OSSL_CMP_CTX_reinit(cmp_ctx))
|
||||
goto err;
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
|
||||
|
||||
return ossl_cmp_ctx_set0_statusString(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set0_newCert(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set1_newChain(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set1_caPubs(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL)
|
||||
@ -216,6 +217,7 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
|
||||
|
||||
sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
|
||||
X509_free(ctx->newCert);
|
||||
sk_X509_pop_free(ctx->newChain, X509_free);
|
||||
sk_X509_pop_free(ctx->caPubs, X509_free);
|
||||
sk_X509_pop_free(ctx->extraCertsIn, X509_free);
|
||||
|
||||
@ -459,6 +461,34 @@ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns the cert chain computed by OSSL_CMP_certConf_cb(), NULL on error */
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
if (ctx->newChain == NULL)
|
||||
return sk_X509_new_null();
|
||||
return X509_chain_up_ref(ctx->newChain);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies any given stack of inbound X509 certificates to newChain
|
||||
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
|
||||
*/
|
||||
int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
|
||||
sk_X509_pop_free(ctx->newChain, X509_free);
|
||||
ctx->newChain= NULL;
|
||||
if (newChain == NULL)
|
||||
return 1;
|
||||
return (ctx->newChain = X509_chain_up_ref(newChain)) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the stack of certificates received in a response message.
|
||||
* The stack is duplicated so the caller must handle freeing it!
|
||||
|
@ -120,6 +120,7 @@ struct ossl_cmp_ctx_st {
|
||||
/* TODO: this should be a stack since there could be more than one */
|
||||
X509 *newCert; /* newly enrolled cert received from the CA */
|
||||
/* TODO: this should be a stack since there could be more than one */
|
||||
STACK_OF(X509) *newChain; /* chain of newly enrolled cert received */
|
||||
STACK_OF(X509) *caPubs; /* CA certs received from server (in IP message) */
|
||||
STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */
|
||||
|
||||
@ -780,6 +781,7 @@ int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
|
||||
OSSL_CMP_PKIFREETEXT *text);
|
||||
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info);
|
||||
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert);
|
||||
int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain);
|
||||
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs);
|
||||
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *extraCertsIn);
|
||||
|
@ -63,6 +63,7 @@ B<openssl> B<cmp>
|
||||
[B<-implicit_confirm>]
|
||||
[B<-disable_confirm>]
|
||||
[B<-certout> I<filename>]
|
||||
[B<-chainout> I<filename>]
|
||||
|
||||
[B<-oldcert> I<filename>]
|
||||
[B<-revreason> I<number>]
|
||||
@ -378,6 +379,10 @@ B<WARNING:> This leads to behavior violating RFC 4210.
|
||||
|
||||
The file where the newly enrolled certificate should be saved.
|
||||
|
||||
=item B<-chainout> I<filename>
|
||||
|
||||
The file where the chain of the newly enrolled certificate should be saved.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
|
@ -54,6 +54,7 @@ OSSL_CMP_CTX_get_status,
|
||||
OSSL_CMP_CTX_get0_statusString,
|
||||
OSSL_CMP_CTX_get_failInfoCode,
|
||||
OSSL_CMP_CTX_get0_newCert,
|
||||
OSSL_CMP_CTX_get1_newChain,
|
||||
OSSL_CMP_CTX_get1_caPubs,
|
||||
OSSL_CMP_CTX_get1_extraCertsIn,
|
||||
OSSL_CMP_CTX_set1_transactionID,
|
||||
@ -144,6 +145,7 @@ OSSL_CMP_CTX_set1_senderNonce
|
||||
int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx);
|
||||
|
||||
X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
|
||||
|
||||
@ -170,7 +172,7 @@ OSSL_CMP_CTX_free() deallocates an OSSL_CMP_CTX structure.
|
||||
|
||||
OSSL_CMP_CTX_reinit() prepares the given B<ctx> for a further transaction by
|
||||
clearing the internal CMP transaction (aka session) status, PKIStatusInfo,
|
||||
and any previous results (newCert, caPubs, and extraCertsIn)
|
||||
and any previous results (newCert, newChain, caPubs, and extraCertsIn)
|
||||
from the last executed transaction.
|
||||
All other field values (i.e., CMP options) are retained for potential re-use.
|
||||
|
||||
@ -579,6 +581,10 @@ OSSL_CMP_CTX_FAILINFO_badAlg. Returns -1 if the failInfoCode field is unset.
|
||||
OSSL_CMP_CTX_get0_newCert() returns the pointer to the newly obtained
|
||||
certificate in case it is available, else NULL.
|
||||
|
||||
OSSL_CMP_CTX_get1_newChain() returns a pointer to a duplicate of the stack of
|
||||
X.509 certificates computed by OSSL_CMP_certConf_cb() (if this function has
|
||||
been called) on the last received certificate response message IP/CP/KUP.
|
||||
|
||||
OSSL_CMP_CTX_get1_caPubs() returns a pointer to a duplicate of the stack of
|
||||
X.509 certificates received in the caPubs field of last received certificate
|
||||
response message IP/CP/KUP.
|
||||
@ -611,6 +617,7 @@ OSSL_CMP_CTX_get0_newPkey(),
|
||||
OSSL_CMP_CTX_get_certConf_cb_arg(),
|
||||
OSSL_CMP_CTX_get0_statusString(),
|
||||
OSSL_CMP_CTX_get0_newCert(),
|
||||
OSSL_CMP_CTX_get0_newChain(),
|
||||
OSSL_CMP_CTX_get1_caPubs(), and
|
||||
OSSL_CMP_CTX_get1_extraCertsIn()
|
||||
return the intended pointer value as described above or NULL on error.
|
||||
|
@ -331,6 +331,7 @@ OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx);
|
||||
# define OSSL_CMP_PKISI_BUFLEN 1024
|
||||
X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
|
||||
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
|
||||
|
@ -76,6 +76,7 @@ static int execute_CTX_reinit_test(OSSL_CMP_CTX_TEST_FIXTURE *fixture)
|
||||
if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null())
|
||||
|| !ossl_cmp_ctx_set0_newCert(ctx, X509_new())
|
||||
|| !TEST_ptr(certs = sk_X509_new_1())
|
||||
|| !ossl_cmp_ctx_set1_newChain(ctx, certs)
|
||||
|| !ossl_cmp_ctx_set1_caPubs(ctx, certs)
|
||||
|| !ossl_cmp_ctx_set1_extraCertsIn(ctx, certs)
|
||||
|| !ossl_cmp_ctx_set0_validatedSrvCert(ctx, X509_new())
|
||||
@ -93,6 +94,7 @@ static int execute_CTX_reinit_test(OSSL_CMP_CTX_TEST_FIXTURE *fixture)
|
||||
&& ctx->failInfoCode == -1
|
||||
&& ctx->statusString == NULL
|
||||
&& ctx->newCert == NULL
|
||||
&& ctx->newChain == NULL
|
||||
&& ctx->caPubs == NULL
|
||||
&& ctx->extraCertsIn == NULL
|
||||
&& ctx->validatedSrvCert == NULL
|
||||
@ -780,6 +782,7 @@ DEFINE_SET_GET_INT_TEST(ossl_cmp, ctx, status)
|
||||
DEFINE_SET_GET_SK_TEST(ossl_cmp, ctx, 0, 0, statusString, ASN1_UTF8STRING)
|
||||
DEFINE_SET_GET_INT_TEST(ossl_cmp, ctx, failInfoCode)
|
||||
DEFINE_SET_GET_TEST(ossl_cmp, ctx, 0, 0, 0, newCert, X509)
|
||||
DEFINE_SET_GET_SK_X509_TEST(ossl_cmp, ctx, 1, 1, newChain)
|
||||
DEFINE_SET_GET_SK_X509_TEST(ossl_cmp, ctx, 1, 1, caPubs)
|
||||
DEFINE_SET_GET_SK_X509_TEST(ossl_cmp, ctx, 1, 1, extraCertsIn)
|
||||
|
||||
@ -869,6 +872,7 @@ int setup_tests(void)
|
||||
ADD_TEST(test_CTX_set0_get0_statusString);
|
||||
ADD_TEST(test_CTX_set_get_failInfoCode);
|
||||
ADD_TEST(test_CTX_set0_get0_newCert);
|
||||
ADD_TEST(test_CTX_set1_get1_newChain);
|
||||
ADD_TEST(test_CTX_set1_get1_caPubs);
|
||||
ADD_TEST(test_CTX_set1_get1_extraCertsIn);
|
||||
/* exported for testing and debugging purposes: */
|
||||
|
@ -4797,6 +4797,7 @@ OSSL_CMP_CTX_get_status ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_get0_statusString ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_get_failInfoCode ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_get0_newCert ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_get1_newChain ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_get1_caPubs ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_get1_extraCertsIn ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_CTX_set1_transactionID ? 3_0_0 EXIST::FUNCTION:CMP
|
||||
|
Loading…
x
Reference in New Issue
Block a user