pki: Optimize certificate download for --scep and --est
This commit is contained in:
+44
-26
@@ -35,10 +35,11 @@ static int est()
|
|||||||
{
|
{
|
||||||
char *arg, *url = NULL, *file = NULL, *error = NULL;
|
char *arg, *url = NULL, *file = NULL, *error = NULL;
|
||||||
char *client_cert_file = NULL, *client_key_file = NULL;
|
char *client_cert_file = NULL, *client_key_file = NULL;
|
||||||
|
char *user_pass = NULL;
|
||||||
cred_encoding_type_t form = CERT_ASN1_DER;
|
cred_encoding_type_t form = CERT_ASN1_DER;
|
||||||
chunk_t pkcs10_encoding = chunk_empty, est_response = chunk_empty;
|
chunk_t pkcs10_encoding = chunk_empty, est_response = chunk_empty;
|
||||||
certificate_t *pkcs10 = NULL, *client_cert = NULL, *cacert = NULL;
|
certificate_t *pkcs10 = NULL, *client_cert = NULL, *cacert = NULL;
|
||||||
mem_cred_t *creds = NULL;
|
mem_cred_t *creds = NULL, *client_creds = NULL;
|
||||||
private_key_t *client_key = NULL;
|
private_key_t *client_key = NULL;
|
||||||
est_op_t est_op = EST_SIMPLE_ENROLL;
|
est_op_t est_op = EST_SIMPLE_ENROLL;
|
||||||
est_tls_t *est_tls;
|
est_tls_t *est_tls;
|
||||||
@@ -55,30 +56,33 @@ static int est()
|
|||||||
{
|
{
|
||||||
switch (command_getopt(&arg))
|
switch (command_getopt(&arg))
|
||||||
{
|
{
|
||||||
case 'h':
|
case 'h': /* --help */
|
||||||
goto usage;
|
goto usage;
|
||||||
case 'u':
|
case 'u': /* --url */
|
||||||
url = arg;
|
url = arg;
|
||||||
continue;
|
continue;
|
||||||
case 'i':
|
case 'i': /* --in */
|
||||||
file = arg;
|
file = arg;
|
||||||
continue;
|
continue;
|
||||||
case 'c':
|
case 'c': /* --cacert */
|
||||||
cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||||
CERT_X509, BUILD_FROM_FILE, arg, BUILD_END);
|
CERT_X509, BUILD_FROM_FILE, arg, BUILD_END);
|
||||||
if (!cacert)
|
if (!cacert)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "could not load cacert file '%s'", arg);
|
DBG1(DBG_APP, "could not load cacert file '%s'", arg);
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
creds->add_cert(creds, TRUE, cacert);
|
creds->add_cert(creds, TRUE, cacert);
|
||||||
continue;
|
continue;
|
||||||
case 'o':
|
case 'o': /* --cert */
|
||||||
client_cert_file = arg;
|
client_cert_file = arg;
|
||||||
continue;
|
continue;
|
||||||
case 'k':
|
case 'k': /* --key */
|
||||||
client_key_file = arg;
|
client_key_file = arg;
|
||||||
continue;
|
continue;
|
||||||
|
case 'p': /* --userpass */
|
||||||
|
user_pass = arg;
|
||||||
|
continue;
|
||||||
case 't': /* --pollinterval */
|
case 't': /* --pollinterval */
|
||||||
poll_interval = atoi(arg);
|
poll_interval = atoi(arg);
|
||||||
if (poll_interval <= 0)
|
if (poll_interval <= 0)
|
||||||
@@ -90,7 +94,7 @@ static int est()
|
|||||||
case 'm': /* --maxpolltime */
|
case 'm': /* --maxpolltime */
|
||||||
max_poll_time = atoi(arg);
|
max_poll_time = atoi(arg);
|
||||||
continue;
|
continue;
|
||||||
case 'f':
|
case 'f': /* --force */
|
||||||
if (!get_form(arg, &form, CRED_CERTIFICATE))
|
if (!get_form(arg, &form, CRED_CERTIFICATE))
|
||||||
{
|
{
|
||||||
error = "invalid certificate output format";
|
error = "invalid certificate output format";
|
||||||
@@ -134,7 +138,7 @@ static int est()
|
|||||||
{
|
{
|
||||||
DBG1(DBG_APP, "reading PKCS#10 certificate request failed: %s\n",
|
DBG1(DBG_APP, "reading PKCS#10 certificate request failed: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
pkcs10 = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
pkcs10 = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||||
CERT_PKCS10_REQUEST,
|
CERT_PKCS10_REQUEST,
|
||||||
@@ -144,15 +148,21 @@ static int est()
|
|||||||
if (!pkcs10)
|
if (!pkcs10)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "parsing certificate request failed");
|
DBG1(DBG_APP, "parsing certificate request failed");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate PKCS#10 encoding */
|
/* generate PKCS#10 encoding */
|
||||||
if (!pkcs10->get_encoding(pkcs10, CERT_ASN1_DER, &pkcs10_encoding))
|
if (!pkcs10->get_encoding(pkcs10, CERT_ASN1_DER, &pkcs10_encoding))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "encoding certificate request failed");
|
DBG1(DBG_APP, "encoding certificate request failed");
|
||||||
goto end;
|
pkcs10->destroy(pkcs10);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
pkcs10->destroy(pkcs10);
|
||||||
|
|
||||||
|
/* create a separate set for the old client credentials */
|
||||||
|
client_creds = mem_cred_create();
|
||||||
|
lib->credmgr->add_set(lib->credmgr, &client_creds->set);
|
||||||
|
|
||||||
if (client_cert_file)
|
if (client_cert_file)
|
||||||
{
|
{
|
||||||
@@ -164,7 +174,7 @@ static int est()
|
|||||||
DBG1(DBG_APP, "could not load client cert file '%s'", client_cert_file);
|
DBG1(DBG_APP, "could not load client cert file '%s'", client_cert_file);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
creds->add_cert(creds, FALSE, client_cert->get_ref(client_cert));
|
client_creds->add_cert(client_creds, FALSE, client_cert);
|
||||||
|
|
||||||
/* load old client private key */
|
/* load old client private key */
|
||||||
client_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
|
client_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
|
||||||
@@ -174,11 +184,11 @@ static int est()
|
|||||||
DBG1(DBG_APP, "parsing client private key failed");
|
DBG1(DBG_APP, "parsing client private key failed");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
creds->add_key(creds, client_key->get_ref(client_key));
|
client_creds->add_key(client_creds, client_key);
|
||||||
est_op = EST_SIMPLE_REENROLL;
|
est_op = EST_SIMPLE_REENROLL;
|
||||||
}
|
}
|
||||||
|
|
||||||
est_tls = est_tls_create(url, client_cert, NULL);
|
est_tls = est_tls_create(url, client_cert, user_pass);
|
||||||
if (!est_tls)
|
if (!est_tls)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "TLS connection to EST server was not established");
|
DBG1(DBG_APP, "TLS connection to EST server was not established");
|
||||||
@@ -187,6 +197,7 @@ static int est()
|
|||||||
if (!est_tls->request(est_tls, est_op, pkcs10_encoding, &est_response,
|
if (!est_tls->request(est_tls, est_op, pkcs10_encoding, &est_response,
|
||||||
&http_code, &retry_after))
|
&http_code, &retry_after))
|
||||||
{
|
{
|
||||||
|
est_tls->destroy(est_tls);
|
||||||
DBG1(DBG_APP, "EST request failed: HTTP %u", http_code);
|
DBG1(DBG_APP, "EST request failed: HTTP %u", http_code);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@@ -213,6 +224,9 @@ static int est()
|
|||||||
|
|
||||||
while (http_code == EST_HTTP_CODE_ACCEPTED)
|
while (http_code == EST_HTTP_CODE_ACCEPTED)
|
||||||
{
|
{
|
||||||
|
chunk_free(&est_response);
|
||||||
|
est_tls->destroy(est_tls);
|
||||||
|
|
||||||
if (max_poll_time > 0 &&
|
if (max_poll_time > 0 &&
|
||||||
(time_monotonic(NULL) - poll_start) >= max_poll_time)
|
(time_monotonic(NULL) - poll_start) >= max_poll_time)
|
||||||
{
|
{
|
||||||
@@ -221,10 +235,8 @@ static int est()
|
|||||||
}
|
}
|
||||||
DBG1(DBG_APP, " going to sleep for %d seconds", poll_interval);
|
DBG1(DBG_APP, " going to sleep for %d seconds", poll_interval);
|
||||||
sleep(poll_interval);
|
sleep(poll_interval);
|
||||||
chunk_free(&est_response);
|
|
||||||
|
|
||||||
est_tls->destroy(est_tls);
|
est_tls = est_tls_create(url, client_cert, user_pass);
|
||||||
est_tls = est_tls_create(url, client_cert, NULL);
|
|
||||||
if (!est_tls)
|
if (!est_tls)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "TLS connection to EST server was not established");
|
DBG1(DBG_APP, "TLS connection to EST server was not established");
|
||||||
@@ -234,22 +246,26 @@ static int est()
|
|||||||
&http_code, &retry_after))
|
&http_code, &retry_after))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "EST request failed: HTTP %u", http_code);
|
DBG1(DBG_APP, "EST request failed: HTTP %u", http_code);
|
||||||
|
est_tls->destroy(est_tls);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
est_tls->destroy(est_tls);
|
||||||
|
|
||||||
|
end:
|
||||||
|
/* remove the old client certificate before extracting the new one */
|
||||||
|
lib->credmgr->remove_set(lib->credmgr, &client_creds->set);
|
||||||
|
client_creds->destroy(client_creds);
|
||||||
|
|
||||||
if (http_code == EST_HTTP_CODE_OK)
|
if (http_code == EST_HTTP_CODE_OK)
|
||||||
{
|
{
|
||||||
status = pki_cert_extract_cert(est_response, form, creds) ? 0 : 1;
|
status = pki_cert_extract_cert(est_response, form) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
err:
|
||||||
|
/* cleanup */
|
||||||
lib->credmgr->remove_set(lib->credmgr, &creds->set);
|
lib->credmgr->remove_set(lib->credmgr, &creds->set);
|
||||||
creds->destroy(creds);
|
creds->destroy(creds);
|
||||||
DESTROY_IF(est_tls);
|
|
||||||
DESTROY_IF(client_cert);
|
|
||||||
DESTROY_IF(client_key);
|
|
||||||
DESTROY_IF(pkcs10);
|
|
||||||
chunk_free(&pkcs10_encoding);
|
chunk_free(&pkcs10_encoding);
|
||||||
chunk_free(&est_response);
|
chunk_free(&est_response);
|
||||||
|
|
||||||
@@ -271,14 +287,16 @@ static void __attribute__ ((constructor))reg()
|
|||||||
est, 'E', "est",
|
est, 'E', "est",
|
||||||
"Enroll an X.509 certificate with an EST server",
|
"Enroll an X.509 certificate with an EST server",
|
||||||
{"--url url [--in file] [--cacert file]+ [--cert file --key file]",
|
{"--url url [--in file] [--cacert file]+ [--cert file --key file]",
|
||||||
"[--interval time] [--maxpolltime time] [--outform der|pem]"},
|
"[-userpass username:password] [--interval time] [--maxpolltime time]",
|
||||||
|
"[--outform der|pem]"},
|
||||||
{
|
{
|
||||||
{"help", 'h', 0, "show usage information"},
|
{"help", 'h', 0, "show usage information"},
|
||||||
{"url", 'u', 1, "URL of the EST server"},
|
{"url", 'u', 1, "URL of the EST server"},
|
||||||
{"in", 'i', 1, "PKCS#10 input file, default: stdin"},
|
{"in", 'i', 1, "PKCS#10 input file, default: stdin"},
|
||||||
{"cacert", 'c', 1, "CA certificate"},
|
{"cacert", 'c', 1, "CA certificate"},
|
||||||
{"cert", 'o', 1, "Old certificate about to be renewed"},
|
{"cert", 'o', 1, "Old certificate about to be renewed"},
|
||||||
{"key", 'k', 1, "Old RSA private key about to be replaced"},
|
{"key", 'k', 1, "Old private key about to be replaced"},
|
||||||
|
{"userpass", 'p', 1, "username:password for http basic auth"},
|
||||||
{"interval", 't', 1, "poll interval, default: 60s"},
|
{"interval", 't', 1, "poll interval, default: 60s"},
|
||||||
{"maxpolltime", 'm', 1, "maximum poll time, default: 0 (no limit)"},
|
{"maxpolltime", 'm', 1, "maximum poll time, default: 0 (no limit)"},
|
||||||
{"outform", 'f', 1, "encoding of stored certificates, default: der"},
|
{"outform", 'f', 1, "encoding of stored certificates, default: der"},
|
||||||
|
|||||||
+50
-36
@@ -61,7 +61,7 @@ static int scep()
|
|||||||
certificate_t *x509_ca_sig = NULL, *x509_ca_enc = NULL;
|
certificate_t *x509_ca_sig = NULL, *x509_ca_enc = NULL;
|
||||||
identification_t *subject = NULL, *issuer = NULL;
|
identification_t *subject = NULL, *issuer = NULL;
|
||||||
container_t *container = NULL;
|
container_t *container = NULL;
|
||||||
mem_cred_t *creds = NULL;
|
mem_cred_t *creds = NULL, *client_creds = NULL;
|
||||||
scep_msg_t scep_msg_type;
|
scep_msg_t scep_msg_type;
|
||||||
scep_attributes_t attrs = empty_scep_attributes;
|
scep_attributes_t attrs = empty_scep_attributes;
|
||||||
uint32_t caps_flags;
|
uint32_t caps_flags;
|
||||||
@@ -127,7 +127,7 @@ static int scep()
|
|||||||
if (!cert)
|
if (!cert)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "could not load cacert file '%s'", arg);
|
DBG1(DBG_APP, "could not load cacert file '%s'", arg);
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
creds->add_cert(creds, TRUE, cert);
|
creds->add_cert(creds, TRUE, cert);
|
||||||
continue;
|
continue;
|
||||||
@@ -236,7 +236,7 @@ static int scep()
|
|||||||
if (subject->get_type(subject) != ID_DER_ASN1_DN)
|
if (subject->get_type(subject) != ID_DER_ASN1_DN)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "supplied --dn is not a distinguished name");
|
DBG1(DBG_APP, "supplied --dn is not a distinguished name");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load RSA private key from file or stdin */
|
/* load RSA private key from file or stdin */
|
||||||
@@ -253,7 +253,7 @@ static int scep()
|
|||||||
if (!chunk_from_fd(0, &chunk))
|
if (!chunk_from_fd(0, &chunk))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "reading private key failed: %s", strerror(errno));
|
DBG1(DBG_APP, "reading private key failed: %s", strerror(errno));
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
||||||
BUILD_BLOB, chunk, BUILD_END);
|
BUILD_BLOB, chunk, BUILD_END);
|
||||||
@@ -262,7 +262,7 @@ static int scep()
|
|||||||
if (!private)
|
if (!private)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "parsing private key failed");
|
DBG1(DBG_APP, "parsing private key failed");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
public = private->get_public_key(private);
|
public = private->get_public_key(private);
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ static int scep()
|
|||||||
&scep_response, &http_code))
|
&scep_response, &http_code))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "did not receive a valid scep response: HTTP %u", http_code);
|
DBG1(DBG_APP, "did not receive a valid scep response: HTTP %u", http_code);
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
caps_flags = scep_parse_caps(scep_response);
|
caps_flags = scep_parse_caps(scep_response);
|
||||||
chunk_free(&scep_response);
|
chunk_free(&scep_response);
|
||||||
@@ -302,7 +302,7 @@ static int scep()
|
|||||||
{
|
{
|
||||||
DBG1(DBG_APP, "%N digest algorithm not supported by CA",
|
DBG1(DBG_APP, "%N digest algorithm not supported by CA",
|
||||||
hash_algorithm_short_names, digest_alg);
|
hash_algorithm_short_names, digest_alg);
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check support of selected encryption algorithm */
|
/* check support of selected encryption algorithm */
|
||||||
@@ -322,7 +322,7 @@ static int scep()
|
|||||||
{
|
{
|
||||||
DBG1(DBG_APP, "%N encryption algorithm not supported by CA",
|
DBG1(DBG_APP, "%N encryption algorithm not supported by CA",
|
||||||
encryption_algorithm_names, cipher);
|
encryption_algorithm_names, cipher);
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
DBG2(DBG_APP, "%N digest and %N encryption algorithm supported by CA",
|
DBG2(DBG_APP, "%N digest and %N encryption algorithm supported by CA",
|
||||||
hash_algorithm_short_names, digest_alg,
|
hash_algorithm_short_names, digest_alg,
|
||||||
@@ -340,7 +340,7 @@ static int scep()
|
|||||||
if (!scheme)
|
if (!scheme)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "no signature scheme found");
|
DBG1(DBG_APP, "no signature scheme found");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate PKCS#10 certificate request */
|
/* generate PKCS#10 certificate request */
|
||||||
@@ -355,32 +355,46 @@ static int scep()
|
|||||||
if (!pkcs10)
|
if (!pkcs10)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "generating certificate request failed");
|
DBG1(DBG_APP, "generating certificate request failed");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate PKCS#10 encoding */
|
/* generate PKCS#10 encoding */
|
||||||
if (!pkcs10->get_encoding(pkcs10, CERT_ASN1_DER, &pkcs10_encoding))
|
if (!pkcs10->get_encoding(pkcs10, CERT_ASN1_DER, &pkcs10_encoding))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "encoding certificate request failed");
|
DBG1(DBG_APP, "encoding certificate request failed");
|
||||||
goto end;
|
pkcs10->destroy(pkcs10);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
pkcs10->destroy(pkcs10);
|
||||||
|
|
||||||
if (!scep_generate_transaction_id(public, &transID, &serialNumber))
|
if (!scep_generate_transaction_id(public, &transID, &serialNumber))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "generating transaction ID failed");
|
DBG1(DBG_APP, "generating transaction ID failed");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
DBG1(DBG_APP, "transaction ID: %.*s", (int)transID.len, transID.ptr);
|
DBG1(DBG_APP, "transaction ID: %.*s", (int)transID.len, transID.ptr);
|
||||||
|
|
||||||
if (old_cert_file)
|
if (old_cert_file)
|
||||||
{
|
{
|
||||||
|
/* check support of Renewal Operation */
|
||||||
|
if (!(caps_flags & SCEP_CAPS_RENEWAL))
|
||||||
|
{
|
||||||
|
DBG1(DBG_APP, "Renewal operation not supported by SCEP server");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
DBG2(DBG_APP, "SCEP Renewal operation supported");
|
||||||
|
|
||||||
|
/* set message type for SCEP renewal request */
|
||||||
|
scep_msg_type = renewal_via_pkcs_req ? SCEP_PKCSReq_MSG :
|
||||||
|
SCEP_RenewalReq_MSG;
|
||||||
|
|
||||||
/* load old client certificate */
|
/* load old client certificate */
|
||||||
x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||||
BUILD_FROM_FILE, old_cert_file, BUILD_END);
|
BUILD_FROM_FILE, old_cert_file, BUILD_END);
|
||||||
if (!x509_signer)
|
if (!x509_signer)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "could not load old cert file '%s'", old_cert_file);
|
DBG1(DBG_APP, "could not load old cert file '%s'", old_cert_file);
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load old RSA private key */
|
/* load old RSA private key */
|
||||||
@@ -389,20 +403,8 @@ static int scep()
|
|||||||
if (!priv_signer)
|
if (!priv_signer)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "parsing old private key failed");
|
DBG1(DBG_APP, "parsing old private key failed");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check support of Renewal Operation */
|
|
||||||
if (!(caps_flags & SCEP_CAPS_RENEWAL))
|
|
||||||
{
|
|
||||||
DBG1(DBG_APP, "Renewal operation not supported by SCEP server");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
DBG2(DBG_APP, "SCEP Renewal operation supported");
|
|
||||||
|
|
||||||
/* set message type for SCEP renewal request */
|
|
||||||
scep_msg_type = renewal_via_pkcs_req ? SCEP_PKCSReq_MSG :
|
|
||||||
SCEP_RenewalReq_MSG;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -419,8 +421,8 @@ static int scep()
|
|||||||
BUILD_END);
|
BUILD_END);
|
||||||
if (!x509_signer)
|
if (!x509_signer)
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "generating self-sigend certificate failed");
|
DBG1(DBG_APP, "generating self-signed certificate failed");
|
||||||
goto end;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the signing key is identical to the client key */
|
/* the signing key is identical to the client key */
|
||||||
@@ -429,8 +431,13 @@ static int scep()
|
|||||||
/* set message type for SCEP request */
|
/* set message type for SCEP request */
|
||||||
scep_msg_type = SCEP_PKCSReq_MSG;
|
scep_msg_type = SCEP_PKCSReq_MSG;
|
||||||
}
|
}
|
||||||
creds->add_cert(creds, FALSE, x509_signer->get_ref(x509_signer));
|
|
||||||
creds->add_key(creds, priv_signer->get_ref(priv_signer));
|
/* create a separate set for the self-signed or old client credentials */
|
||||||
|
client_creds = mem_cred_create();
|
||||||
|
lib->credmgr->add_set(lib->credmgr, &client_creds->set);
|
||||||
|
|
||||||
|
client_creds->add_cert(client_creds, FALSE, x509_signer);
|
||||||
|
client_creds->add_key(client_creds, priv_signer);
|
||||||
|
|
||||||
/* load CA or RA certificate used for encryption */
|
/* load CA or RA certificate used for encryption */
|
||||||
x509_ca_enc = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
x509_ca_enc = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||||
@@ -566,11 +573,21 @@ static int scep()
|
|||||||
}
|
}
|
||||||
container->destroy(container);
|
container->destroy(container);
|
||||||
container = NULL;
|
container = NULL;
|
||||||
|
status = 0;
|
||||||
status = pki_cert_extract_cert(data, form, creds) ? 0 : 1;
|
|
||||||
chunk_free(&data);
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
/* remove the old client certificate before extracting the new one */
|
||||||
|
lib->credmgr->remove_set(lib->credmgr, &client_creds->set);
|
||||||
|
client_creds->destroy(client_creds);
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
{
|
||||||
|
status = pki_cert_extract_cert(data, form) ? 0 : 1;
|
||||||
|
chunk_free(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* cleanup */
|
||||||
lib->credmgr->remove_set(lib->credmgr, &creds->set);
|
lib->credmgr->remove_set(lib->credmgr, &creds->set);
|
||||||
creds->destroy(creds);
|
creds->destroy(creds);
|
||||||
san->destroy_offset(san, offsetof(identification_t, destroy));
|
san->destroy_offset(san, offsetof(identification_t, destroy));
|
||||||
@@ -578,9 +595,6 @@ end:
|
|||||||
DESTROY_IF(subject);
|
DESTROY_IF(subject);
|
||||||
DESTROY_IF(private);
|
DESTROY_IF(private);
|
||||||
DESTROY_IF(public);
|
DESTROY_IF(public);
|
||||||
DESTROY_IF(priv_signer);
|
|
||||||
DESTROY_IF(x509_signer);
|
|
||||||
DESTROY_IF(pkcs10);
|
|
||||||
DESTROY_IF(x509_ca_enc);
|
DESTROY_IF(x509_ca_enc);
|
||||||
DESTROY_IF(x509_ca_sig);
|
DESTROY_IF(x509_ca_sig);
|
||||||
DESTROY_IF(container);
|
DESTROY_IF(container);
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ METHOD(est_tls_t, request, bool,
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
DBG1(DBG_APP, "http: %B", &http);
|
DBG2(DBG_APP, "http request: %B", &http);
|
||||||
|
|
||||||
/* send https request */
|
/* send https request */
|
||||||
if (this->tls->write(this->tls, http.ptr, http.len) != http.len)
|
if (this->tls->write(this->tls, http.ptr, http.len) != http.len)
|
||||||
@@ -237,7 +237,7 @@ METHOD(est_tls_t, request, bool,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
response = chunk_create(buf, len);
|
response = chunk_create(buf, len);
|
||||||
DBG1(DBG_APP, "response: %B", &response);
|
DBG2(DBG_APP, "http response: %B", &response);
|
||||||
|
|
||||||
if (!parse_http_header(&response, http_code, &content_len, &base64,
|
if (!parse_http_header(&response, http_code, &content_len, &base64,
|
||||||
retry_after))
|
retry_after))
|
||||||
|
|||||||
+24
-12
@@ -348,6 +348,7 @@ bool pki_cert_extract_cacerts(chunk_t data, char *caout, char *raout,
|
|||||||
cert_type = get_pki_cert_type(cert);
|
cert_type = get_pki_cert_type(cert);
|
||||||
if (cert_type != CERT_TYPE_ROOT_CA)
|
if (cert_type != CERT_TYPE_ROOT_CA)
|
||||||
{
|
{
|
||||||
|
certificate_t *cert_found = NULL;
|
||||||
enumerator_t *certs;
|
enumerator_t *certs;
|
||||||
bool trusted;
|
bool trusted;
|
||||||
|
|
||||||
@@ -359,7 +360,8 @@ bool pki_cert_extract_cacerts(chunk_t data, char *caout, char *raout,
|
|||||||
/* establish trust relativ to root CA */
|
/* establish trust relativ to root CA */
|
||||||
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
||||||
KEY_ANY, cert->get_subject(cert), FALSE);
|
KEY_ANY, cert->get_subject(cert), FALSE);
|
||||||
trusted = certs->enumerate(certs, &cert, NULL);
|
trusted = certs->enumerate(certs, &cert_found, NULL) &&
|
||||||
|
(cert_found == cert);
|
||||||
certs->destroy(certs);
|
certs->destroy(certs);
|
||||||
|
|
||||||
cert_type_count[cert_type]++;
|
cert_type_count[cert_type]++;
|
||||||
@@ -394,12 +396,12 @@ end:
|
|||||||
* Extract an X.509 client certificates from PKCS#7 container
|
* Extract an X.509 client certificates from PKCS#7 container
|
||||||
* check trust as well as validity and write to stdout
|
* check trust as well as validity and write to stdout
|
||||||
*/
|
*/
|
||||||
bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form,
|
bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form)
|
||||||
mem_cred_t *creds)
|
|
||||||
{
|
{
|
||||||
pkcs7_t *pkcs7;
|
pkcs7_t *pkcs7;
|
||||||
container_t *container;
|
container_t *container;
|
||||||
certificate_t *cert;
|
certificate_t *cert;
|
||||||
|
mem_cred_t *client_creds;
|
||||||
chunk_t cert_encoding = chunk_empty;
|
chunk_t cert_encoding = chunk_empty;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
bool stored = FALSE;
|
bool stored = FALSE;
|
||||||
@@ -413,6 +415,10 @@ bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
|
||||||
|
client_creds = mem_cred_create();
|
||||||
|
lib->credmgr->add_set(lib->credmgr, &client_creds->set);
|
||||||
|
|
||||||
/* store the end entity certificate */
|
/* store the end entity certificate */
|
||||||
pkcs7 = (pkcs7_t*)container;
|
pkcs7 = (pkcs7_t*)container;
|
||||||
enumerator = pkcs7->create_cert_enumerator(pkcs7);
|
enumerator = pkcs7->create_cert_enumerator(pkcs7);
|
||||||
@@ -420,13 +426,17 @@ bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form,
|
|||||||
while (enumerator->enumerate(enumerator, &cert))
|
while (enumerator->enumerate(enumerator, &cert))
|
||||||
{
|
{
|
||||||
x509_t *x509 = (x509_t*)cert;
|
x509_t *x509 = (x509_t*)cert;
|
||||||
|
certificate_t *cert_found = NULL;
|
||||||
enumerator_t *certs;
|
enumerator_t *certs;
|
||||||
|
chunk_t serial;
|
||||||
time_t from, until;
|
time_t from, until;
|
||||||
bool trusted, valid;
|
bool trusted, valid;
|
||||||
|
|
||||||
if (!(x509->get_flags(x509) & X509_CA))
|
if (!(x509->get_flags(x509) & X509_CA))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "certificate \"%Y\"", cert->get_subject(cert));
|
DBG1(DBG_APP, "issued certificate \"%Y\"", cert->get_subject(cert));
|
||||||
|
serial = x509->get_serial(x509);
|
||||||
|
DBG1(DBG_APP, " serial: %#B", &serial);
|
||||||
|
|
||||||
if (stored)
|
if (stored)
|
||||||
{
|
{
|
||||||
@@ -434,20 +444,20 @@ bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* establish trust relativ to root CA */
|
/* establish trust relative to root CA */
|
||||||
creds->add_cert(creds, FALSE, cert->get_ref(cert));
|
client_creds->add_cert(client_creds, FALSE, cert->get_ref(cert));
|
||||||
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
||||||
KEY_ANY, cert->get_subject(cert), FALSE);
|
KEY_ANY, cert->get_subject(cert), FALSE);
|
||||||
trusted = certs->enumerate(certs, &cert, NULL);
|
trusted = certs->enumerate(certs, &cert_found, NULL) &&
|
||||||
valid = cert->get_validity(cert, NULL, &from, &until);
|
(cert_found == cert);
|
||||||
|
certs->destroy(certs);
|
||||||
|
|
||||||
DBG1(DBG_APP, "certificate is %strusted, valid from %T until %T "
|
valid = cert->get_validity(cert, NULL, &from, &until);
|
||||||
"(currently %svalid)",
|
DBG1(DBG_APP, "issued certificate is %strusted, "
|
||||||
|
"valid from %T until %T (currently %svalid)",
|
||||||
trusted ? "" : "not ", &from, FALSE, &until, FALSE,
|
trusted ? "" : "not ", &from, FALSE, &until, FALSE,
|
||||||
valid ? "" : "not ");
|
valid ? "" : "not ");
|
||||||
|
|
||||||
certs->destroy(certs);
|
|
||||||
|
|
||||||
if (!cert->get_encoding(cert, form, &cert_encoding))
|
if (!cert->get_encoding(cert, form, &cert_encoding))
|
||||||
{
|
{
|
||||||
DBG1(DBG_APP, "encoding certificate failed");
|
DBG1(DBG_APP, "encoding certificate failed");
|
||||||
@@ -467,6 +477,8 @@ bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form,
|
|||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
container->destroy(container);
|
container->destroy(container);
|
||||||
|
lib->credmgr->remove_set(lib->credmgr, &client_creds->set);
|
||||||
|
client_creds->destroy(client_creds);
|
||||||
|
|
||||||
return stored;
|
return stored;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -37,7 +37,6 @@ bool pki_cert_extract_cacerts(chunk_t data, char *caout, char *raout,
|
|||||||
* Extract an X.509 client certificates from PKCS#7 container
|
* Extract an X.509 client certificates from PKCS#7 container
|
||||||
* check trust as well as validity and write to stdout
|
* check trust as well as validity and write to stdout
|
||||||
*/
|
*/
|
||||||
bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form,
|
bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form);
|
||||||
mem_cred_t *creds);
|
|
||||||
|
|
||||||
#endif /** PKI_CERT_H_ @}*/
|
#endif /** PKI_CERT_H_ @}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user