diff options
Diffstat (limited to 'src/scepclient')
-rw-r--r-- | src/scepclient/Makefile.am | 2 | ||||
-rw-r--r-- | src/scepclient/pkcs10.c | 34 | ||||
-rw-r--r-- | src/scepclient/pkcs10.h | 7 | ||||
-rw-r--r-- | src/scepclient/scep.c | 6 | ||||
-rw-r--r-- | src/scepclient/scep.h | 8 | ||||
-rw-r--r-- | src/scepclient/scepclient.c | 220 |
6 files changed, 150 insertions, 127 deletions
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am index 88481fa15..36a38a628 100644 --- a/src/scepclient/Makefile.am +++ b/src/scepclient/Makefile.am @@ -1,5 +1,5 @@ ipsec_PROGRAMS = scepclient -scepclient_SOURCES = scepclient.c pkcs10.c pkcs10.h scep.c scep.h loglite.c +scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c PLUTODIR=$(top_srcdir)/src/pluto OPENACDIR=$(top_srcdir)/src/openac diff --git a/src/scepclient/pkcs10.c b/src/scepclient/pkcs10.c index 95fd768b7..04196777c 100644 --- a/src/scepclient/pkcs10.c +++ b/src/scepclient/pkcs10.c @@ -45,15 +45,14 @@ static const chunk_t ASN1_extensionRequest_oid = chunk_from_chars( ); /** - * @brief Adds a subjectAltName in DER-coded form to a linked list + * Adds a subjectAltName in DER-coded form to a linked list * - * @param[in,out] subjectAltNames head of the linked list of subjectAltNames - * @param[in] kind type of the subjectAltName (which is a generalName) - * @param[in] value value of the subjectAltName as an ASCII string + * @param[in] subjectAltNames linked list of subjectAltNames + * @param[in] kind type of the subjectAltName (which is a generalName) + * @param[in] value value of the subjectAltName as an ASCII string */ -void -pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind -, char *value) +void pkcs10_add_subjectAltName(linked_list_t *subjectAltNames, + generalNames_t kind, char *value) { generalName_t *gn; asn1_t asn1_type = ASN1_EOC; @@ -96,16 +95,15 @@ pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind } /** - * @brief Builds the requestInfoAttributes of the certificationRequestInfo-field + * Builds the requestInfoAttributes of the certificationRequestInfo-field * * challenge password ans subjectAltNames are only included, * when avaiable in given #pkcs10_t structure * * @param[in] pkcs10 Pointer to a #pkcs10_t structure - * @return 1 if succeeded, 0 otherwise + * @return 1 if succeeded, 0 otherwise */ -static chunk_t -build_req_info_attributes(pkcs10_t* pkcs10) +static chunk_t build_req_info_attributes(pkcs10_t* pkcs10) { chunk_t subjectAltNames = chunk_empty; @@ -143,13 +141,12 @@ build_req_info_attributes(pkcs10_t* pkcs10) } /** - * @brief Builds a DER-code pkcs#10 certificate request + * Builds a DER-code pkcs#10 certificate request * * @param[in] pkcs10 pointer to a pkcs10_t struct * @return DER-code pkcs10 request */ -static chunk_t -pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg) +static chunk_t pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg) { chunk_t key = chunk_empty; @@ -175,7 +172,7 @@ pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg) } /** - * @brief Creates a pkcs#10 certificate request object + * Creates a pkcs#10 certificate request object * * To create a certificate request, the RSA key and the * names to be included as subject in the certificate request @@ -190,7 +187,7 @@ pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg) */ pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public, chunk_t subject, chunk_t challengePassword, - generalName_t *subjectAltNames, int signature_alg) + linked_list_t *subjectAltNames, int signature_alg) { pkcs10_t *pkcs10 = malloc_thing(pkcs10_t); @@ -205,12 +202,11 @@ pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public, } /** - * @brief Frees the resources used by an #pkcs10_t object + * Frees the resources used by an #pkcs10_t object * * @param[in] pkcs10 #pkcs10_t to free */ -void -pkcs10_free(pkcs10_t *pkcs10) +void pkcs10_free(pkcs10_t *pkcs10) { if (pkcs10 != NULL) { diff --git a/src/scepclient/pkcs10.h b/src/scepclient/pkcs10.h index e10a3ef59..a4d892576 100644 --- a/src/scepclient/pkcs10.h +++ b/src/scepclient/pkcs10.h @@ -23,6 +23,7 @@ #ifndef _PKCS10_H #define _PKCS10_H +#include <utils/linked_list.h> #include <credentials/keys/private_key.h> #include <credentials/keys/public_key.h> @@ -45,16 +46,16 @@ struct pkcs10_struct { chunk_t request; chunk_t subject; chunk_t challengePassword; - generalName_t *subjectAltNames; + linked_list_t *subjectAltNames; }; extern const pkcs10_t empty_pkcs10; -extern void pkcs10_add_subjectAltName(generalName_t **subjectAltNames, +extern void pkcs10_add_subjectAltName(linked_list_t *subjectAltNames, generalNames_t kind, char *value); extern pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public, chunk_t subject, chunk_t challengePassword, - generalName_t *subjectAltNames, int signature_alg); + linked_list_t *subjectAltNames, int signature_alg); extern void pkcs10_free(pkcs10_t *pkcs10); #endif /* _PKCS10_H */ diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c index 86fd5656e..598705636 100644 --- a/src/scepclient/scep.c +++ b/src/scepclient/scep.c @@ -370,8 +370,8 @@ chunk_t scep_senderNonce_attribute(void) * Builds a pkcs7 enveloped and signed scep request */ chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, - const x509cert_t *enc_cert, int enc_alg, - const x509cert_t *signer_cert, int digest_alg, + certificate_t *enc_cert, int enc_alg, + certificate_t *signer_cert, int digest_alg, private_key_t *private_key) { chunk_t envelopedData, attributes, request; @@ -525,7 +525,7 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, } err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data, - scep_attributes_t *attrs, x509cert_t *signer_cert) + scep_attributes_t *attrs, certificate_t *signer_cert) { chunk_t attributes; diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h index e044f0b1c..f64c6b1cc 100644 --- a/src/scepclient/scep.h +++ b/src/scepclient/scep.h @@ -23,6 +23,8 @@ #ifndef _SCEP_H #define _SCEP_H +#include <credentials/certificates/certificate.h> + #include "../pluto/defs.h" #include "../pluto/pkcs7.h" @@ -81,13 +83,13 @@ extern chunk_t scep_transId_attribute(chunk_t transaction_id); extern chunk_t scep_messageType_attribute(scep_msg_t m); extern chunk_t scep_senderNonce_attribute(void); extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, - const x509cert_t *enc_cert, int enc_alg, - const x509cert_t *signer_cert, int digest_alg, + certificate_t *enc_cert, int enc_alg, + certificate_t *signer_cert, int digest_alg, private_key_t *private_key); extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, bool http_get_request, chunk_t *response); extern err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data, scep_attributes_t *attrs, - x509cert_t *signer_cert); + certificate_t *signer_cert); #endif /* _SCEP_H */ diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 34b98547e..91f89cc62 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -41,10 +41,15 @@ #include <asn1/oid.h> #include <utils/optionsfrom.h> #include <utils/enumerator.h> +#include <utils/linked_list.h> +#include <crypto/hashers/hasher.h> #include <crypto/crypters/crypter.h> #include <crypto/proposal/proposal_keywords.h> #include <credentials/keys/private_key.h> #include <credentials/keys/public_key.h> +#include <credentials/certificates/certificate.h> +#include <credentials/certificates/x509.h> +#include <credentials/certificates/pkcs10.h> #include "../pluto/constants.h" #include "../pluto/defs.h" @@ -52,7 +57,6 @@ #include "../pluto/pkcs7.h" #include "../pluto/certs.h" -#include "pkcs10.h" #include "scep.h" /* @@ -121,26 +125,27 @@ options_t *options; * Global variables */ -private_key_t *private_key = NULL; -public_key_t *public_key = NULL; - chunk_t pkcs1; chunk_t pkcs7; -chunk_t subject; chunk_t challengePassword; chunk_t serialNumber; chunk_t transID; chunk_t fingerprint; +chunk_t encoding; +chunk_t pkcs10_encoding; chunk_t issuerAndSubject; chunk_t getCertInitial; chunk_t scep_response; -cert_t cert; -x509cert_t *x509_signer = NULL; -x509cert_t *x509_ca_enc = NULL; -x509cert_t *x509_ca_sig = NULL; -generalName_t *subjectAltNames = NULL; -pkcs10_t *pkcs10 = NULL; +linked_list_t *subjectAltNames; + +identification_t *subject = NULL; +private_key_t *private_key = NULL; +public_key_t *public_key = NULL; +certificate_t *x509_signer = NULL; +certificate_t *x509_ca_enc = NULL; +certificate_t *x509_ca_sig = NULL; +certificate_t *pkcs10_req = NULL; /** * @brief exit scepclient @@ -152,27 +157,25 @@ exit_scepclient(err_t message, ...) { int status = 0; + DESTROY_IF(subject); DESTROY_IF(private_key); DESTROY_IF(public_key); + DESTROY_IF(x509_signer); + DESTROY_IF(x509_ca_enc); + DESTROY_IF(x509_ca_sig); + DESTROY_IF(pkcs10_req); + subjectAltNames->destroy_offset(subjectAltNames, + offsetof(identification_t, destroy)); free(pkcs1.ptr); free(pkcs7.ptr); - free(subject.ptr); free(serialNumber.ptr); free(transID.ptr); free(fingerprint.ptr); + free(encoding.ptr); + free(pkcs10_encoding.ptr); free(issuerAndSubject.ptr); free(getCertInitial.ptr); free(scep_response.ptr); - - free_generalNames(subjectAltNames, TRUE); - if (x509_signer != NULL) - { - x509_signer->subjectAltName = NULL; - } - free_x509cert(x509_signer); - free_x509cert(x509_ca_enc); - free_x509cert(x509_ca_sig); - pkcs10_free(pkcs10); options->destroy(options); /* print any error message to stderr */ @@ -357,8 +360,8 @@ int main(int argc, char **argv) /* digest algorithm used by pkcs7, default is SHA-1 */ int pkcs7_digest_alg = OID_SHA1; - /* signature algorithm used by pkcs10, default is SHA-1 with RSA encryption */ - int pkcs10_signature_alg = OID_SHA1; + /* signature algorithm used by pkcs10, default is SHA-1 */ + hash_algorithm_t pkcs10_signature_alg = HASH_SHA1; /* URL of the SCEP-Server */ char *scep_url = NULL; @@ -374,18 +377,6 @@ int main(int argc, char **argv) err_t ugh = NULL; - /* initialize global variables */ - pkcs1 = chunk_empty; - pkcs7 = chunk_empty; - serialNumber = chunk_empty; - transID = chunk_empty; - fingerprint = chunk_empty; - issuerAndSubject = chunk_empty; - challengePassword = chunk_empty; - getCertInitial = chunk_empty; - scep_response = chunk_empty; - log_to_stderr = TRUE; - /* initialize library */ if (!library_init(NULL)) { @@ -400,8 +391,21 @@ int main(int argc, char **argv) exit(SS_RC_DAEMON_INTEGRITY); } - /* initialize optionsfrom */ - options = options_create(); + /* initialize global variables */ + pkcs1 = chunk_empty; + pkcs7 = chunk_empty; + serialNumber = chunk_empty; + transID = chunk_empty; + fingerprint = chunk_empty; + encoding = chunk_empty; + pkcs10_encoding = chunk_empty; + issuerAndSubject = chunk_empty; + challengePassword = chunk_empty; + getCertInitial = chunk_empty; + scep_response = chunk_empty; + subjectAltNames = linked_list_create(); + options = options_create(); + log_to_stderr = TRUE; for (;;) { @@ -614,7 +618,6 @@ int main(int argc, char **argv) case 's': /* --subjectAltName */ { - generalNames_t kind; char *value = strstr(optarg, "="); if (value) @@ -625,25 +628,19 @@ int main(int argc, char **argv) value++; } - if (strcaseeq("email", optarg)) - { - kind = GN_RFC822_NAME; - } - else if (strcaseeq("dns", optarg)) - { - kind = GN_DNS_NAME; - } - else if (strcaseeq("ip", optarg)) + if (strcaseeq("email", optarg) || + strcaseeq("dns", optarg) || + strcaseeq("ip", optarg)) { - kind = GN_IP_ADDRESS; + subjectAltNames->insert_last(subjectAltNames, + identification_create_from_string(value)); + continue; } else { usage("invalid --subjectAltName type"); continue; } - pkcs10_add_subjectAltName(&subjectAltNames, kind, value); - continue; } case 'p': /* --password */ @@ -831,11 +828,6 @@ int main(int argc, char **argv) } else { - char buf[IDTOA_BUF]; - chunk_t dn = chunk_empty; - - dn.ptr = buf; - if (distinguishedName == NULL) { char buf[BUF_LEN]; @@ -853,21 +845,29 @@ int main(int argc, char **argv) DBG(DBG_CONTROL, DBG_log("dn: '%s'", distinguishedName); ) - ugh = atodn(distinguishedName, &dn); - if (ugh != NULL) + subject = identification_create_from_string(distinguishedName); + if (subject->get_type(subject) != ID_DER_ASN1_DN) { - exit_scepclient(ugh); + exit_scepclient("parsing of distinguished name failed"); } - subject = chunk_clone(dn); - DBG(DBG_CONTROL, DBG_log("building pkcs10 object:") ) - pkcs10 = pkcs10_build(private_key, public_key, subject, - challengePassword, subjectAltNames, - pkcs10_signature_alg); - fingerprint = scep_generate_pkcs10_fingerprint(pkcs10->request); + pkcs10_req = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_PKCS10_REQUEST, + BUILD_SIGNING_KEY, private_key, + BUILD_SUBJECT, subject, + BUILD_SUBJECT_ALTNAMES, subjectAltNames, + BUILD_PASSPHRASE, challengePassword, + BUILD_DIGEST_ALG, pkcs10_signature_alg, + BUILD_END); + if (!pkcs10_req) + { + exit_scepclient("generating pkcs10 request failed"); + } + pkcs10_encoding = pkcs10_req->get_encoding(pkcs10_req); + fingerprint = scep_generate_pkcs10_fingerprint(pkcs10_encoding); plog(" fingerprint: %s", fingerprint.ptr); } @@ -878,9 +878,10 @@ int main(int argc, char **argv) { char *path = concatenate_paths(REQ_PATH, file_out_pkcs10); - if (!chunk_write(pkcs10->request, path, "pkcs10", 0022, force)) + if (!chunk_write(pkcs10_encoding, path, "pkcs10", 0022, force)) + { exit_scepclient("could not write pkcs10 file '%s'", path); - + } filetype_out &= ~PKCS10; /* delete PKCS10 flag */ } @@ -901,8 +902,9 @@ int main(int argc, char **argv) ) if (!private_key->get_encoding(private_key, KEY_PRIV_ASN1_DER, &pkcs1) || !chunk_write(pkcs1, path, "pkcs1", 0066, force)) + { exit_scepclient("could not write pkcs1 file '%s'", path); - + } filetype_out &= ~PKCS1; /* delete PKCS1 flag */ } @@ -914,19 +916,23 @@ int main(int argc, char **argv) scep_generate_transaction_id(public_key, &transID, &serialNumber); plog(" transaction ID: %.*s", (int)transID.len, transID.ptr); + notBefore = notBefore ? notBefore : time(NULL); + notAfter = notAfter ? notAfter : (notBefore + validity); + /* generate a self-signed X.509 certificate */ - x509_signer = malloc_thing(x509cert_t); - *x509_signer = empty_x509cert; - x509_signer->serialNumber = serialNumber; - x509_signer->sigAlg = OID_SHA1_WITH_RSA; - x509_signer->issuer = subject; - x509_signer->notBefore = (notBefore)? notBefore - : time(NULL); - x509_signer->notAfter = (notAfter)? notAfter - : x509_signer->notBefore + validity; - x509_signer->subject = subject; - x509_signer->subjectAltName = subjectAltNames; - build_x509cert(x509_signer, public_key, private_key); + x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_SIGNING_KEY, private_key, + BUILD_PUBLIC_KEY, public_key, + BUILD_SUBJECT, subject, + BUILD_NOT_BEFORE_TIME, notBefore, + BUILD_NOT_AFTER_TIME, notAfter, + BUILD_SERIAL, serialNumber, + BUILD_SUBJECT_ALTNAMES, subjectAltNames, + BUILD_END); + if (!x509_signer) + { + exit_scepclient("generating certificate failed"); + } /* * output of self-signed X.509 certificate file @@ -935,9 +941,16 @@ int main(int argc, char **argv) { char *path = concatenate_paths(HOST_CERT_PATH, file_out_cert_self); - if (!chunk_write(x509_signer->certificate, path, "self-signed cert", 0022, force)) + encoding = x509_signer->get_encoding(x509_signer); + if (!encoding.ptr) + { + exit_scepclient("encoding certificate failed"); + } + if (!chunk_write(encoding, path, "self-signed cert", 0022, force)) + { exit_scepclient("could not write self-signed cert file '%s'", path); -; + } + chunk_free(&encoding); filetype_out &= ~CERT_SELF; /* delete CERT_SELF flag */ } @@ -951,13 +964,13 @@ int main(int argc, char **argv) */ { char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_enc); - cert_t cert; - - if (!load_cert(path, "encryption cacert", &cert)) + + x509_ca_enc = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, BUILD_END); + if (!x509_ca_enc) { exit_scepclient("could not load encryption cacert file '%s'", path); } - x509_ca_enc = cert.u.x509; } /* @@ -978,10 +991,10 @@ int main(int argc, char **argv) DBG(DBG_CONTROL, DBG_log("building pkcs7 request") ) - pkcs7 = scep_build_request(pkcs10->request - , transID, SCEP_PKCSReq_MSG - , x509_ca_enc, pkcs7_symmetric_cipher - , x509_signer, pkcs7_digest_alg, private_key); + pkcs7 = scep_build_request(pkcs10_encoding, + transID, SCEP_PKCSReq_MSG, + x509_ca_enc, pkcs7_symmetric_cipher, + x509_signer, pkcs7_digest_alg, private_key); } /* @@ -1008,7 +1021,6 @@ int main(int argc, char **argv) if (filetype_out & CERT) { char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig); - cert_t cert; time_t poll_start = 0; x509cert_t *certs = NULL; @@ -1017,9 +1029,12 @@ int main(int argc, char **argv) contentInfo_t data = empty_contentInfo; scep_attributes_t attrs = empty_scep_attributes; - if (!load_cert(path, "signature cacert", &cert)) + x509_ca_sig = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, BUILD_END); + if (!x509_ca_sig) + { exit_scepclient("could not load signature cacert file '%s'", path); - x509_ca_sig = cert.u.x509; + } if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION, http_get_request, &scep_response)) @@ -1036,12 +1051,14 @@ int main(int argc, char **argv) /* in case of manual mode, we are going into a polling loop */ if (attrs.pkiStatus == SCEP_PENDING) { + identification_t *issuer = x509_ca_sig->get_subject(x509_ca_sig); + plog(" scep request pending, polling every %d seconds" , poll_interval); poll_start = time_monotonic(NULL); - issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc" - , x509_ca_sig->subject - , subject); + issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc", + issuer->get_encoding(issuer), + subject); } while (attrs.pkiStatus == SCEP_PENDING) { @@ -1110,13 +1127,20 @@ int main(int argc, char **argv) { bool stored = FALSE; x509cert_t *cert = certs; + x509_t *x509 = (x509_t*)cert->cert; - if (!cert->isCA) + if (!(x509->get_flags(x509) & X509_CA)) { if (stored) + { exit_scepclient("multiple certs received, only first stored"); - if (!chunk_write(cert->certificate, path, "requested cert", 0022, force)) + } + encoding = cert->cert->get_encoding(cert->cert); + if (!chunk_write(encoding, path, "requested cert", 0022, force)) + { exit_scepclient("could not write cert file '%s'", path); + } + chunk_free(&encoding); stored = TRUE; } certs = certs->next; |