summaryrefslogtreecommitdiff
path: root/src/scepclient/scepclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/scepclient/scepclient.c')
-rw-r--r--src/scepclient/scepclient.c116
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 */
}