diff options
Diffstat (limited to 'src/scepclient/scepclient.c')
-rw-r--r-- | src/scepclient/scepclient.c | 116 |
1 files changed, 90 insertions, 26 deletions
diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 78b0d7e7a..83b5d6219 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -26,12 +26,12 @@ #include <syslog.h> #include <library.h> -#include <debug.h> +#include <utils/debug.h> #include <asn1/asn1.h> #include <asn1/oid.h> #include <utils/optionsfrom.h> -#include <utils/enumerator.h> -#include <utils/linked_list.h> +#include <collections/enumerator.h> +#include <collections/linked_list.h> #include <crypto/hashers/hasher.h> #include <crypto/crypters/crypter.h> #include <crypto/proposal/proposal_keywords.h> @@ -40,6 +40,7 @@ #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/pkcs10.h> +#include <credentials/sets/mem_cred.h> #include <plugins/plugin.h> #include "scep.h" @@ -140,6 +141,8 @@ certificate_t *x509_ca_enc = NULL; certificate_t *x509_ca_sig = NULL; certificate_t *pkcs10_req = NULL; +mem_cred_t *creds = NULL; + /* logging */ static bool log_to_stderr = TRUE; static bool log_to_syslog = TRUE; @@ -255,6 +258,12 @@ static void exit_scepclient(err_t message, ...) { int status = 0; + if (creds) + { + lib->credmgr->remove_set(lib->credmgr, &creds->set); + creds->destroy(creds); + } + DESTROY_IF(subject); DESTROY_IF(private_key); DESTROY_IF(public_key); @@ -361,6 +370,9 @@ static void usage(const char *message) " <algo> = md5 (default) | sha1 | sha256 |\n" " sha384 | sha512\n" "\n" + "Options for CA certificate acquisition:\n" + " --caname (-c) <name> name of CA to fetch CA certificate(s)\n" + " (default: CAIdentifier)\n" "Options for enrollment (cert):\n" " --url (-u) <url> url of the SCEP server\n" " --method (-m) post | get http request type\n" @@ -451,6 +463,9 @@ int main(int argc, char **argv) /* URL of the SCEP-Server */ char *scep_url = NULL; + /* Name of CA to fetch CA certs for */ + char *ca_name = "CAIdentifier"; + /* http request method, default is GET */ bool http_get_request = TRUE; @@ -512,6 +527,7 @@ int main(int argc, char **argv) { "password", required_argument, NULL, 'p' }, { "algorithm", required_argument, NULL, 'a' }, { "url", required_argument, NULL, 'u' }, + { "caname", required_argument, NULL, 'c'}, { "method", required_argument, NULL, 'm' }, { "interval", required_argument, NULL, 't' }, { "maxpolltime", required_argument, NULL, 'x' }, @@ -519,7 +535,7 @@ int main(int argc, char **argv) }; /* parse next option */ - int c = getopt_long(argc, argv, "hv+:qi:o:fk:d:s:p:a:u:m:t:x:APRCMS", long_opts, NULL); + int c = getopt_long(argc, argv, "hv+:qi:o:fk:d:s:p:a:u:c:m:t:x:APRCMS", long_opts, NULL); switch (c) { @@ -782,6 +798,10 @@ int main(int argc, char **argv) scep_url = optarg; continue; + case 'c': /* -- caname */ + ca_name = optarg; + continue; + case 'm': /* --method */ if (strcaseeq("get", optarg)) { @@ -915,20 +935,24 @@ int main(int argc, char **argv) if (request_ca_certificate) { char ca_path[PATH_MAX]; + container_t *container; pkcs7_t *pkcs7; - if (!scep_http_request(scep_url, chunk_empty, SCEP_GET_CA_CERT, - http_get_request, &scep_response)) + if (!scep_http_request(scep_url, chunk_create(ca_name, strlen(ca_name)), + SCEP_GET_CA_CERT, http_get_request, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } join_paths(ca_path, sizeof(ca_path), CA_CERT_PATH, file_out_ca_cert); - pkcs7 = pkcs7_create_from_chunk(scep_response, 0); - if (!pkcs7 || !pkcs7->parse_signedData(pkcs7, NULL)) + pkcs7 = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, scep_response, BUILD_END); + + if (!pkcs7) { /* no PKCS#7 encoded CA+RA certificates, assume simple CA cert */ - DESTROY_IF(pkcs7); + + DBG1(DBG_APP, "unable to parse PKCS#7, assuming plain CA cert"); if (!chunk_write(scep_response, ca_path, "ca cert", 0022, force)) { exit_scepclient("could not write ca cert file '%s'", ca_path); @@ -941,7 +965,7 @@ int main(int argc, char **argv) int ra_certs = 0, ca_certs = 0; int ra_index = 1, ca_index = 1; - enumerator = pkcs7->create_certificate_enumerator(pkcs7); + enumerator = pkcs7->create_cert_enumerator(pkcs7); while (enumerator->enumerate(enumerator, &cert)) { x509_t *x509 = (x509_t*)cert; @@ -956,7 +980,7 @@ int main(int argc, char **argv) } enumerator->destroy(enumerator); - enumerator = pkcs7->create_certificate_enumerator(pkcs7); + enumerator = pkcs7->create_cert_enumerator(pkcs7); while (enumerator->enumerate(enumerator, &cert)) { x509_t *x509 = (x509_t*)cert; @@ -993,11 +1017,15 @@ int main(int argc, char **argv) chunk_free(&encoding); } enumerator->destroy(enumerator); - pkcs7->destroy(pkcs7); + container = &pkcs7->container; + container->destroy(container); } exit_scepclient(NULL); /* no further output required */ } + creds = mem_cred_create(); + lib->credmgr->add_set(lib->credmgr, &creds->set); + /* * input of PKCS#1 file */ @@ -1020,6 +1048,7 @@ int main(int argc, char **argv) { exit_scepclient("no RSA private key available"); } + creds->add_key(creds, private_key->get_ref(private_key)); public_key = private_key->get_public_key(private_key); /* check for minimum key length */ @@ -1170,6 +1199,7 @@ int main(int argc, char **argv) exit_scepclient("generating certificate failed"); } } + creds->add_cert(creds, TRUE, x509_signer->get_ref(x509_signer)); /* * output of self-signed X.509 certificate file @@ -1270,7 +1300,9 @@ int main(int argc, char **argv) enumerator_t *enumerator; char path[PATH_MAX]; time_t poll_start = 0; - pkcs7_t *data = NULL; + pkcs7_t *p7; + container_t *container = NULL; + chunk_t chunk; scep_attributes_t attrs = empty_scep_attributes; join_paths(path, sizeof(path), CA_CERT_PATH, file_in_cacert_sig); @@ -1282,13 +1314,14 @@ int main(int argc, char **argv) exit_scepclient("could not load signature cacert file '%s'", path); } + creds->add_cert(creds, TRUE, x509_ca_sig->get_ref(x509_ca_sig)); + if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION, http_get_request, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } - ugh = scep_parse_response(scep_response, transID, &data, &attrs, - x509_ca_sig); + ugh = scep_parse_response(scep_response, transID, &container, &attrs); if (ugh != NULL) { exit_scepclient(ugh); @@ -1317,7 +1350,7 @@ int main(int argc, char **argv) DBG2(DBG_APP, "going to sleep for %d seconds", poll_interval); sleep(poll_interval); free(scep_response.ptr); - data->destroy(data); + container->destroy(container); DBG2(DBG_APP, "fingerprint: %.*s", (int)fingerprint.len, fingerprint.ptr); @@ -1338,8 +1371,7 @@ int main(int argc, char **argv) { exit_scepclient("did not receive a valid scep response"); } - ugh = scep_parse_response(scep_response, transID, &data, &attrs, - x509_ca_sig); + ugh = scep_parse_response(scep_response, transID, &container, &attrs); if (ugh != NULL) { exit_scepclient(ugh); @@ -1348,25 +1380,53 @@ int main(int argc, char **argv) if (attrs.pkiStatus != SCEP_SUCCESS) { - data->destroy(data); + container->destroy(container); exit_scepclient("reply status is not 'SUCCESS'"); } - if (!data->parse_envelopedData(data, serialNumber, private_key)) + if (!container->get_data(container, &chunk)) + { + container->destroy(container); + exit_scepclient("extracting signed-data failed"); + } + container->destroy(container); + + /* decrypt enveloped-data container */ + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, + BUILD_END); + free(chunk.ptr); + if (!container) { - data->destroy(data); exit_scepclient("could not decrypt envelopedData"); } - if (!data->parse_signedData(data, NULL)) + + if (!container->get_data(container, &chunk)) + { + container->destroy(container); + exit_scepclient("extracting encrypted-data failed"); + } + container->destroy(container); + + /* parse signed-data container */ + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, + BUILD_END); + free(chunk.ptr); + if (!container) { - data->destroy(data); - exit_scepclient("error parsing the scep response"); + exit_scepclient("could not parse singed-data"); } + /* no need to verify the signed-data container, the signature does NOT + * cover the contained certificates */ /* store the end entity certificate */ join_paths(path, sizeof(path), HOST_CERT_PATH, file_out_cert); - enumerator = data->create_certificate_enumerator(data); + p7 = (pkcs7_t*)container; + enumerator = p7->create_cert_enumerator(p7); while (enumerator->enumerate(enumerator, &cert)) { x509_t *x509 = (x509_t*)cert; @@ -1387,7 +1447,11 @@ int main(int argc, char **argv) } } enumerator->destroy(enumerator); - data->destroy(data); + container->destroy(container); + chunk_free(&attrs.transID); + chunk_free(&attrs.senderNonce); + chunk_free(&attrs.recipientNonce); + filetype_out &= ~CERT; /* delete CERT flag */ } |