pki: use libtls for pki --est|--estca
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@ pki_SOURCES = pki.c pki.h pki_cert.c pki_cert.h command.c command.h \
|
||||
commands/self.c \
|
||||
commands/signcrl.c \
|
||||
commands/verify.c \
|
||||
est/est.h est/est.c est/est_tls.h est/est_tls.c \
|
||||
est/est_tls.h est/est_tls.c \
|
||||
scep/scep.h scep/scep.c
|
||||
|
||||
pki_LDADD = \
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "pki.h"
|
||||
#include "pki_cert.h"
|
||||
#include "est/est.h"
|
||||
#include "est/est_tls.h"
|
||||
|
||||
#include <credentials/certificates/certificate.h>
|
||||
@@ -64,7 +63,7 @@ static int est()
|
||||
case 'i': /* --in */
|
||||
file = arg;
|
||||
continue;
|
||||
case 'c': /* --cacert */
|
||||
case 'C': /* --cacert */
|
||||
cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||
CERT_X509, BUILD_FROM_FILE, arg, BUILD_END);
|
||||
if (!cacert)
|
||||
@@ -74,7 +73,7 @@ static int est()
|
||||
}
|
||||
creds->add_cert(creds, TRUE, cacert);
|
||||
continue;
|
||||
case 'o': /* --cert */
|
||||
case 'c': /* --cert */
|
||||
client_cert_file = arg;
|
||||
continue;
|
||||
case 'X': /* --certid */
|
||||
@@ -193,7 +192,7 @@ static int est()
|
||||
{
|
||||
chunk_t handle;
|
||||
|
||||
if (client_cert_file) /* loadold certificate file */
|
||||
if (client_cert_file) /* load old certificate file */
|
||||
{
|
||||
client_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||
CERT_X509,
|
||||
@@ -362,9 +361,9 @@ static void __attribute__ ((constructor))reg()
|
||||
{"help", 'h', 0, "show usage information"},
|
||||
{"url", 'u', 1, "URL of the EST server"},
|
||||
{"in", 'i', 1, "PKCS#10 input file, default: stdin"},
|
||||
{"cacert", 'c', 1, "CA certificate"},
|
||||
{"cert", 'o', 1, "old certificate about to be renewed"},
|
||||
{"certid", 'X', 1, "smartcard or TPM certificate object handle" },
|
||||
{"cacert", 'C', 1, "CA certificate"},
|
||||
{"cert", 'c', 1, "old certificate about to be renewed"},
|
||||
{"certid", 'X', 1, "smartcard or TPM certificate object handle" },
|
||||
{"key", 'k', 1, "old private key about to be replaced"},
|
||||
{"keyid", 'x', 1, "smartcard or TPM private key object handle"},
|
||||
{"userpass", 'p', 1, "username:password for http basic auth"},
|
||||
|
||||
+60
-18
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "pki.h"
|
||||
#include "pki_cert.h"
|
||||
#include "est/est.h"
|
||||
#include "est/est_tls.h"
|
||||
|
||||
#include <credentials/containers/pkcs7.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
@@ -29,35 +29,55 @@ static int estca()
|
||||
{
|
||||
cred_encoding_type_t form = CERT_ASN1_DER;
|
||||
chunk_t est_response = chunk_empty;
|
||||
char *arg, *url = NULL, *caout = NULL;
|
||||
certificate_t *cacert;
|
||||
mem_cred_t *creds = NULL;
|
||||
est_tls_t *est_tls;
|
||||
char *arg, *error = NULL, *url = NULL, *caout = NULL;
|
||||
bool force = FALSE, success;
|
||||
u_int http_code = 0;
|
||||
status_t status = 1;
|
||||
|
||||
/* initialize CA certificate storage */
|
||||
creds = mem_cred_create();
|
||||
lib->credmgr->add_set(lib->credmgr, &creds->set);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (command_getopt(&arg))
|
||||
{
|
||||
case 'h':
|
||||
return command_usage(NULL);
|
||||
case 'u':
|
||||
case 'h': /* --help */
|
||||
goto usage;
|
||||
case 'u': /* --url */
|
||||
url = arg;
|
||||
continue;
|
||||
case 'c':
|
||||
case 'C': /* --cacert */
|
||||
cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||
CERT_X509, BUILD_FROM_FILE, arg, BUILD_END);
|
||||
if (!cacert)
|
||||
{
|
||||
DBG1(DBG_APP, "could not load cacert file '%s'", arg);
|
||||
goto err;
|
||||
}
|
||||
creds->add_cert(creds, TRUE, cacert);
|
||||
continue;
|
||||
case 'c': /* --caout */
|
||||
caout = arg;
|
||||
continue;
|
||||
case 'f':
|
||||
case 'f': /* --outform */
|
||||
if (!get_form(arg, &form, CRED_CERTIFICATE))
|
||||
{
|
||||
return command_usage("invalid certificate output format");
|
||||
error ="invalid certificate output format";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'F':
|
||||
case 'F': /* --force */
|
||||
force = TRUE;
|
||||
continue;
|
||||
case EOF:
|
||||
break;
|
||||
default:
|
||||
return command_usage("invalid --estca option");
|
||||
error ="invalid --estca option";
|
||||
goto usage;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -67,17 +87,38 @@ static int estca()
|
||||
return command_usage("--url is required");
|
||||
}
|
||||
|
||||
if (!est_https_request(url, EST_CACERTS, FALSE, chunk_empty, &est_response,
|
||||
&http_code))
|
||||
est_tls = est_tls_create(url, NULL, NULL);
|
||||
if (!est_tls)
|
||||
{
|
||||
DBG1(DBG_APP, "did not receive a valid EST response: HTTP %u", http_code);
|
||||
return 1;
|
||||
DBG1(DBG_APP, "TLS connection to EST server was not established");
|
||||
goto err;
|
||||
}
|
||||
success = pki_cert_extract_cacerts(est_response, caout, NULL, TRUE, form,
|
||||
force);
|
||||
success = est_tls->request(est_tls, EST_CACERTS, chunk_empty, &est_response,
|
||||
&http_code, NULL);
|
||||
est_tls->destroy(est_tls);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
DBG1(DBG_APP, "EST request failed: HTTP %u", http_code);
|
||||
goto err;
|
||||
}
|
||||
if (pki_cert_extract_cacerts(est_response, caout, NULL, TRUE, form, force))
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
|
||||
err:
|
||||
lib->credmgr->remove_set(lib->credmgr, &creds->set);
|
||||
creds->destroy(creds);
|
||||
chunk_free(&est_response);
|
||||
|
||||
return success ? 0 : 1;
|
||||
return status;
|
||||
|
||||
usage:
|
||||
lib->credmgr->remove_set(lib->credmgr, &creds->set);
|
||||
creds->destroy(creds);
|
||||
|
||||
return command_usage(error);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,10 +129,11 @@ static void __attribute__ ((constructor))reg()
|
||||
command_register((command_t) {
|
||||
estca, 'e', "estca",
|
||||
"get CA certificate[s] from a EST server",
|
||||
{"--url url [--caout file] [--outform der|pem] [--force]"},
|
||||
{"--url url [--cacert file]+ [--caout file] [--outform der|pem] [--force]"},
|
||||
{
|
||||
{"help", 'h', 0, "show usage information"},
|
||||
{"url", 'u', 1, "URL of the SCEP server"},
|
||||
{"cacert", 'C', 1, "TLS CA certificate"},
|
||||
{"caout", 'c', 1, "CA certificate [template]"},
|
||||
{"outform", 'f', 1, "encoding of stored certificates, default: der"},
|
||||
{"force", 'F', 0, "force overwrite of existing files"},
|
||||
|
||||
+32
-30
@@ -39,7 +39,7 @@ static int scep()
|
||||
{
|
||||
char *arg, *url = NULL, *file = NULL, *dn = NULL, *error = NULL;
|
||||
char *ca_enc_file = NULL, *ca_sig_file = NULL;
|
||||
char *old_cert_file = NULL, *old_key_file = NULL;
|
||||
char *client_cert_file = NULL, *client_key_file = NULL;
|
||||
cred_encoding_type_t form = CERT_ASN1_DER;
|
||||
chunk_t scep_response = chunk_empty;
|
||||
chunk_t challenge_password = chunk_empty;
|
||||
@@ -95,33 +95,33 @@ static int scep()
|
||||
{
|
||||
switch (command_getopt(&arg))
|
||||
{
|
||||
case 'h':
|
||||
case 'h': /* --help */
|
||||
goto usage;
|
||||
case 'u':
|
||||
case 'u': /* --url */
|
||||
url = arg;
|
||||
continue;
|
||||
case 'i':
|
||||
case 'i': /* --in */
|
||||
file = arg;
|
||||
continue;
|
||||
case 'd':
|
||||
case 'd': /* --dn */
|
||||
dn = arg;
|
||||
continue;
|
||||
case 'a':
|
||||
case 'a': /* --san */
|
||||
san->insert_last(san, identification_create_from_string(arg));
|
||||
continue;
|
||||
case 'P':
|
||||
case 'P': /* --profile */
|
||||
cert_type = chunk_create(arg, strlen(arg));
|
||||
continue;
|
||||
case 'p':
|
||||
case 'p': /* --password */
|
||||
challenge_password = chunk_create(arg, strlen(arg));
|
||||
continue;
|
||||
case 'e':
|
||||
case 'e': /* --cacert-enc */
|
||||
ca_enc_file = arg;
|
||||
continue;
|
||||
case 's':
|
||||
case 's': /* --cacert-sig */
|
||||
ca_sig_file = arg;
|
||||
continue;
|
||||
case 'c':
|
||||
case 'C': /* --cacert */
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, arg, BUILD_END);
|
||||
if (!cert)
|
||||
@@ -131,13 +131,13 @@ static int scep()
|
||||
}
|
||||
creds->add_cert(creds, TRUE, cert);
|
||||
continue;
|
||||
case 'o':
|
||||
old_cert_file = arg;
|
||||
case 'c': /* --cert */
|
||||
client_cert_file = arg;
|
||||
continue;
|
||||
case 'k':
|
||||
old_key_file = arg;
|
||||
case 'k': /* --key */
|
||||
client_key_file = arg;
|
||||
continue;
|
||||
case 'C':
|
||||
case 'E': /* --cipher */
|
||||
if (strcaseeq(arg, "des3"))
|
||||
{
|
||||
cipher = ENCR_3DES;
|
||||
@@ -154,14 +154,14 @@ static int scep()
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'g':
|
||||
case 'g': /* --digest */
|
||||
if (!enum_from_name(hash_algorithm_short_names, arg, &digest_alg))
|
||||
{
|
||||
error = "invalid --digest type";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'R':
|
||||
case 'R': /* --rsa-padding */
|
||||
if (streq(arg, "pss"))
|
||||
{
|
||||
pss = TRUE;
|
||||
@@ -186,7 +186,7 @@ static int scep()
|
||||
case 'm': /* --maxpolltime */
|
||||
max_poll_time = atoi(optarg);
|
||||
continue;
|
||||
case 'f':
|
||||
case 'f': /* --form */
|
||||
if (!get_form(arg, &form, CRED_CERTIFICATE))
|
||||
{
|
||||
error = "invalid certificate output format";
|
||||
@@ -220,7 +220,7 @@ static int scep()
|
||||
goto usage;
|
||||
}
|
||||
|
||||
if (old_cert_file && !old_key_file)
|
||||
if (client_cert_file && !client_key_file)
|
||||
{
|
||||
error = "--oldkey is required if --oldcert is set";
|
||||
goto usage;
|
||||
@@ -374,7 +374,7 @@ static int scep()
|
||||
}
|
||||
DBG1(DBG_APP, "transaction ID: %.*s", (int)transID.len, transID.ptr);
|
||||
|
||||
if (old_cert_file)
|
||||
if (client_cert_file)
|
||||
{
|
||||
/* check support of Renewal Operation */
|
||||
if (!(caps_flags & SCEP_CAPS_RENEWAL))
|
||||
@@ -390,19 +390,21 @@ static int scep()
|
||||
|
||||
/* load old client certificate */
|
||||
x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, old_cert_file, BUILD_END);
|
||||
BUILD_FROM_FILE, client_cert_file, BUILD_END);
|
||||
if (!x509_signer)
|
||||
{
|
||||
DBG1(DBG_APP, "could not load old cert file '%s'", old_cert_file);
|
||||
DBG1(DBG_APP, "loading client cert file '%s' failed",
|
||||
client_cert_file);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* load old RSA private key */
|
||||
priv_signer = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
||||
BUILD_FROM_FILE, old_key_file, BUILD_END);
|
||||
BUILD_FROM_FILE, client_key_file, BUILD_END);
|
||||
if (!priv_signer)
|
||||
{
|
||||
DBG1(DBG_APP, "parsing old private key failed");
|
||||
DBG1(DBG_APP, "loading client private key file '%s' failed",
|
||||
client_key_file);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -456,7 +458,7 @@ static int scep()
|
||||
DBG1(DBG_APP, "could not load signature cacert file '%s'", ca_sig_file);
|
||||
goto end;
|
||||
}
|
||||
creds->add_cert(creds, TRUE, x509_ca_sig->get_ref(x509_ca_sig));
|
||||
x509_ca_sig = creds->add_cert_ref(creds, TRUE, x509_ca_sig);
|
||||
|
||||
/* build pkcs7 request */
|
||||
pkcs7_req = scep_build_request(pkcs10_encoding, transID, scep_msg_type,
|
||||
@@ -642,10 +644,10 @@ static void __attribute__ ((constructor))reg()
|
||||
{"password", 'p', 1, "challengePassword to include in cert request"},
|
||||
{"cacert-enc", 'e', 1, "CA certificate for encryption"},
|
||||
{"cacert-sig", 's', 1, "CA certificate for signature verification"},
|
||||
{"cacert", 'c', 1, "Additional CA certificates"},
|
||||
{"oldcert", 'o', 1, "Old certificate about to be renewed"},
|
||||
{"oldkey", 'k', 1, "Old RSA private key about to be replaced"},
|
||||
{"cipher", 'C', 1, "encryption cipher, default: aes"},
|
||||
{"cacert", 'C', 1, "Additional CA certificates"},
|
||||
{"cert", 'c', 1, "Old certificate about to be renewed"},
|
||||
{"key", 'k', 1, "Old RSA private key about to be replaced"},
|
||||
{"cipher", 'E', 1, "encryption cipher, default: aes"},
|
||||
{"digest", 'g', 1, "digest for signature creation, default: sha256"},
|
||||
{"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"},
|
||||
{"interval", 't', 1, "poll interval, default: 60s"},
|
||||
|
||||
@@ -37,24 +37,24 @@ static int scepca()
|
||||
{
|
||||
switch (command_getopt(&arg))
|
||||
{
|
||||
case 'h':
|
||||
case 'h': /* --help */
|
||||
return command_usage(NULL);
|
||||
case 'u':
|
||||
case 'u': /* --url */
|
||||
url = arg;
|
||||
continue;
|
||||
case 'c':
|
||||
case 'c': /* --caout */
|
||||
caout = arg;
|
||||
continue;
|
||||
case 'r':
|
||||
case 'r': /* --raout */
|
||||
raout = arg;
|
||||
continue;
|
||||
case 'f':
|
||||
case 'f': /* --form */
|
||||
if (!get_form(arg, &form, CRED_CERTIFICATE))
|
||||
{
|
||||
return command_usage("invalid certificate output format");
|
||||
}
|
||||
continue;
|
||||
case 'F':
|
||||
case 'F': /* --force */
|
||||
force = TRUE;
|
||||
continue;
|
||||
case EOF:
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Andreas Steffen, strongSec GmbH
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
|
||||
#include "est.h"
|
||||
|
||||
#define HTTP_CODE_OK 200
|
||||
|
||||
static const char *operations[] = {
|
||||
"cacerts",
|
||||
"simpleenroll",
|
||||
"simplereenroll",
|
||||
"fullcmc",
|
||||
"serverkeygen",
|
||||
"csrattrs"
|
||||
};
|
||||
|
||||
static const char *request_types[] = {
|
||||
"",
|
||||
"application/pkcs10",
|
||||
"application/pkcs10",
|
||||
"application/pkcs7-mime",
|
||||
"application/pkcs10",
|
||||
""
|
||||
};
|
||||
|
||||
/**
|
||||
* Send an EST request via HTTPS and wait for a response
|
||||
*/
|
||||
bool est_https_request(const char *url, est_op_t op, bool http_post,
|
||||
chunk_t data, chunk_t *response, u_int *http_code)
|
||||
{
|
||||
host_t *srcip = NULL;
|
||||
char *complete_url = NULL;
|
||||
status_t status;
|
||||
|
||||
uint32_t http_timeout = lib->settings->get_time(lib->settings,
|
||||
"%s.est.http_timeout", 30, lib->ns);
|
||||
|
||||
char *http_bind = lib->settings->get_str(lib->settings,
|
||||
"%s.est.http_bind", NULL, lib->ns);
|
||||
|
||||
/* initialize response */
|
||||
*response = chunk_empty;
|
||||
*http_code = 0;
|
||||
|
||||
/* construct complete EST URL */
|
||||
if (asprintf(&complete_url, "%s/.well-known/est/%s", url, operations[op]) == -1)
|
||||
{
|
||||
DBG1(DBG_APP, "could not allocate complete_url string");
|
||||
return FALSE;
|
||||
}
|
||||
DBG2(DBG_APP, "sending EST request to '%s'", url);
|
||||
|
||||
if (http_bind)
|
||||
{
|
||||
srcip = host_create_from_string(http_bind, 0);
|
||||
}
|
||||
|
||||
if (http_post)
|
||||
{
|
||||
status = lib->fetcher->fetch(lib->fetcher, complete_url, response,
|
||||
FETCH_TIMEOUT, http_timeout,
|
||||
FETCH_REQUEST_DATA, data,
|
||||
FETCH_REQUEST_TYPE, request_types[op],
|
||||
FETCH_REQUEST_HEADER, "Expect:",
|
||||
FETCH_SOURCEIP, srcip,
|
||||
FETCH_RESPONSE_CODE, http_code,
|
||||
FETCH_END);
|
||||
}
|
||||
else /* HTTP_GET */
|
||||
{
|
||||
status = lib->fetcher->fetch(lib->fetcher, complete_url, response,
|
||||
FETCH_TIMEOUT, http_timeout,
|
||||
FETCH_SOURCEIP, srcip,
|
||||
FETCH_RESPONSE_CODE, http_code,
|
||||
FETCH_END);
|
||||
}
|
||||
DESTROY_IF(srcip);
|
||||
free(complete_url);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*http_code == HTTP_CODE_OK)
|
||||
{
|
||||
chunk_t base64_response = *response;
|
||||
|
||||
*response = chunk_from_base64(base64_response, NULL);
|
||||
chunk_free(&base64_response);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Andreas Steffen, strongSec GmbH
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef _EST_H
|
||||
#define _EST_H
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* EST (RFC 7030) Operations
|
||||
*/
|
||||
typedef enum {
|
||||
EST_CACERTS,
|
||||
EST_SIMPLE_ENROLL,
|
||||
EST_SIMPLE_REENROLL,
|
||||
EST_FULL_CMC,
|
||||
EST_SERVER_KEYGEN,
|
||||
EST_CSR_ATTRS
|
||||
} est_op_t;
|
||||
|
||||
/**
|
||||
* Send an EST request via HTTPS and wait for a response
|
||||
*/
|
||||
bool est_https_request(const char *url, est_op_t op, bool http_post,
|
||||
chunk_t data, chunk_t *response, u_int *http_code);
|
||||
|
||||
#endif /* _EST_H */
|
||||
+12
-4
@@ -16,8 +16,6 @@
|
||||
|
||||
#define _GNU_SOURCE /* for asprintf() */
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -133,7 +131,8 @@ static chunk_t build_http_request(private_est_tls_t *this, est_op_t op, chunk_t
|
||||
len = asprintf(&http_header,
|
||||
"GET %s/.well-known/est/%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"%s",
|
||||
"%s"
|
||||
"\r\n",
|
||||
this->http_path, operations[op], this->http_host, http_auth);
|
||||
if (len > 0)
|
||||
{
|
||||
@@ -154,6 +153,11 @@ static bool parse_http_header(chunk_t *in, u_int *http_code, u_int *content_len
|
||||
*content_len = 0;
|
||||
*base64 = FALSE;
|
||||
|
||||
if (retry_after)
|
||||
{
|
||||
*retry_after = 0;
|
||||
}
|
||||
|
||||
/* Process HTTP protocol version and HTTP status code */
|
||||
if (!fetchline(in, &line) || !extract_token(&version, ' ', &line) ||
|
||||
!match("HTTP/1.1", &version) || sscanf(line.ptr, "%d", http_code) != 1)
|
||||
@@ -210,7 +214,11 @@ METHOD(est_tls_t, request, bool,
|
||||
/* initialize output variables */
|
||||
*out = chunk_empty;
|
||||
*http_code = 0;
|
||||
*retry_after = 0;
|
||||
|
||||
if (retry_after)
|
||||
{
|
||||
*retry_after = 0;
|
||||
}
|
||||
|
||||
http = build_http_request(this, op, in);
|
||||
|
||||
|
||||
+12
-2
@@ -22,8 +22,6 @@
|
||||
#ifndef EST_TLS_H_
|
||||
#define EST_TLS_H_
|
||||
|
||||
#include "est.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
|
||||
@@ -32,6 +30,18 @@
|
||||
|
||||
typedef struct est_tls_t est_tls_t;
|
||||
|
||||
/**
|
||||
* EST (RFC 7030) Operations
|
||||
*/
|
||||
typedef enum {
|
||||
EST_CACERTS,
|
||||
EST_SIMPLE_ENROLL,
|
||||
EST_SIMPLE_REENROLL,
|
||||
EST_FULL_CMC,
|
||||
EST_SERVER_KEYGEN,
|
||||
EST_CSR_ATTRS
|
||||
} est_op_t;
|
||||
|
||||
/**
|
||||
* TLS Interface for sending and receiving HTTPS messages
|
||||
*/
|
||||
|
||||
+54
-16
@@ -73,11 +73,15 @@ static bool print_cert_info(certificate_t *cert, pki_cert_type_t cert_type)
|
||||
char digest_buf[HASH_SIZE_SHA256];
|
||||
char base64_buf[HASH_SIZE_SHA256];
|
||||
chunk_t cert_digest = {digest_buf, HASH_SIZE_SHA256};
|
||||
chunk_t cert_id, encoding = chunk_empty;
|
||||
chunk_t cert_id, serial, encoding = chunk_empty;
|
||||
x509_t *x509;
|
||||
bool success = FALSE;
|
||||
|
||||
DBG1(DBG_APP, "%s cert \"%Y\"", cert_type_label[cert_type],
|
||||
cert->get_subject(cert));
|
||||
x509 = (x509_t*)cert;
|
||||
serial = x509->get_serial(x509);
|
||||
DBG1(DBG_APP, " serial: %#B", &serial);
|
||||
|
||||
if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
|
||||
{
|
||||
@@ -299,26 +303,53 @@ bool pki_cert_extract_cacerts(chunk_t data, char *caout, char *raout,
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
pkcs7_t *pkcs7 = (pkcs7_t*)container;
|
||||
certificate_t *cert_found;
|
||||
enumerator_t *certs;
|
||||
bool trusted;
|
||||
|
||||
enumerator = pkcs7->create_cert_enumerator(pkcs7);
|
||||
while (enumerator->enumerate(enumerator, &cert))
|
||||
{
|
||||
trusted = FALSE;
|
||||
|
||||
cert_type = get_pki_cert_type(cert);
|
||||
if (cert_type == CERT_TYPE_ROOT_CA)
|
||||
{
|
||||
/* trust in root CA has to be established manuallly */
|
||||
creds->add_cert(creds, TRUE, cert->get_ref(cert));
|
||||
|
||||
cert_type_count[cert_type]++;
|
||||
|
||||
if (!print_cert_info(cert, cert_type))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* same root CA as trusted TLS root CA already in cred set? */
|
||||
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
||||
KEY_ANY, cert->get_subject(cert), FALSE);
|
||||
while (certs->enumerate(certs, &cert_found, NULL))
|
||||
{
|
||||
if (cert->equals(cert, cert_found))
|
||||
{
|
||||
DBG1(DBG_APP, "Root CA equals trusted TLS Root CA");
|
||||
trusted = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_APP, "non-matching TLS Root CA of same name");
|
||||
}
|
||||
}
|
||||
certs->destroy(certs);
|
||||
|
||||
/* otherwise trust in root CA has to be established manuallly */
|
||||
if (!trusted)
|
||||
{
|
||||
creds->add_cert(creds, TRUE, cert->get_ref(cert));
|
||||
trusted = FALSE;
|
||||
}
|
||||
cert_type_count[cert_type]++;
|
||||
|
||||
if (build_pathname(&path, cert_type, cert_type_count, caout,
|
||||
raout, form))
|
||||
{
|
||||
written = write_cert(cert, cert_type, FALSE, path, form,
|
||||
written = write_cert(cert, cert_type, trusted, path, form,
|
||||
force);
|
||||
free(path);
|
||||
}
|
||||
@@ -344,24 +375,31 @@ bool pki_cert_extract_cacerts(chunk_t data, char *caout, char *raout,
|
||||
while (enumerator->enumerate(enumerator, &cert))
|
||||
{
|
||||
written = FALSE;
|
||||
trusted = FALSE;
|
||||
|
||||
cert_type = get_pki_cert_type(cert);
|
||||
if (cert_type != CERT_TYPE_ROOT_CA)
|
||||
{
|
||||
certificate_t *cert_found = NULL;
|
||||
enumerator_t *certs;
|
||||
bool trusted;
|
||||
|
||||
if (!print_cert_info(cert, cert_type))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* establish trust relativ to root CA */
|
||||
/* establish trust relative to root CA */
|
||||
certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
|
||||
KEY_ANY, cert->get_subject(cert), FALSE);
|
||||
trusted = certs->enumerate(certs, &cert_found, NULL) &&
|
||||
(cert_found == cert);
|
||||
while (certs->enumerate(certs, &cert_found, NULL))
|
||||
{
|
||||
if (cert->equals(cert, cert_found))
|
||||
{
|
||||
trusted = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_APP, "non-matching TLS Sub CA of same name");
|
||||
}
|
||||
}
|
||||
certs->destroy(certs);
|
||||
|
||||
cert_type_count[cert_type]++;
|
||||
@@ -434,7 +472,7 @@ bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form)
|
||||
|
||||
if (!(x509->get_flags(x509) & X509_CA))
|
||||
{
|
||||
DBG1(DBG_APP, "issued 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);
|
||||
|
||||
@@ -453,7 +491,7 @@ bool pki_cert_extract_cert(chunk_t data, cred_encoding_type_t form)
|
||||
certs->destroy(certs);
|
||||
|
||||
valid = cert->get_validity(cert, NULL, &from, &until);
|
||||
DBG1(DBG_APP, "issued certificate is %strusted, "
|
||||
DBG1(DBG_APP, "Issued certificate is %strusted, "
|
||||
"valid from %T until %T (currently %svalid)",
|
||||
trusted ? "" : "not ", &from, FALSE, &until, FALSE,
|
||||
valid ? "" : "not ");
|
||||
|
||||
Reference in New Issue
Block a user