pki: Add support for EST server label

As specified in EST RFC 7030, Section 3.1 [1].

[1] https://www.rfc-editor.org/rfc/rfc7030.html#section-3.1
This commit is contained in:
Harald Gutmann
2023-04-03 13:59:48 +02:00
committed by Tobias Brunner
parent 7a47adb4f0
commit f6dc47f591
6 changed files with 47 additions and 14 deletions
+7 -3
View File
@@ -32,7 +32,7 @@
*/ */
static int est() static int est()
{ {
char *arg, *url = NULL, *file = NULL, *error = NULL; char *arg, *url = NULL, *label = NULL, *file = NULL, *error = NULL;
char *client_cert_file = NULL, *client_key_file = NULL; char *client_cert_file = NULL, *client_key_file = NULL;
char *keyid = NULL, *certid = NULL, *user_pass = NULL; char *keyid = NULL, *certid = NULL, *user_pass = NULL;
cred_encoding_type_t form = CERT_ASN1_DER; cred_encoding_type_t form = CERT_ASN1_DER;
@@ -60,6 +60,9 @@ static int est()
case 'u': /* --url */ case 'u': /* --url */
url = arg; url = arg;
continue; continue;
case 'l': /* --label */
label = arg;
continue;
case 'i': /* --in */ case 'i': /* --in */
file = arg; file = arg;
continue; continue;
@@ -256,7 +259,7 @@ static int est()
est_op = EST_SIMPLE_REENROLL; est_op = EST_SIMPLE_REENROLL;
} }
est_tls = est_tls_create(url, client_cert, user_pass); est_tls = est_tls_create(url, label, 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");
@@ -304,7 +307,7 @@ 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);
est_tls = est_tls_create(url, client_cert, user_pass); est_tls = est_tls_create(url, label, 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");
@@ -360,6 +363,7 @@ static void __attribute__ ((constructor))reg()
{ {
{"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"},
{"label", 'l', 1, "label in the EST server path"},
{"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", 'c', 1, "old certificate about to be renewed"}, {"cert", 'c', 1, "old certificate about to be renewed"},
+7 -3
View File
@@ -32,7 +32,7 @@ static int estca()
certificate_t *cacert; certificate_t *cacert;
mem_cred_t *creds = NULL; mem_cred_t *creds = NULL;
est_tls_t *est_tls; est_tls_t *est_tls;
char *arg, *error = NULL, *url = NULL, *caout = NULL; char *arg, *error = NULL, *url = NULL, *label = NULL, *caout = NULL;
bool force = FALSE, success; bool force = FALSE, success;
u_int http_code = 0; u_int http_code = 0;
status_t status = 1; status_t status = 1;
@@ -50,6 +50,9 @@ static int estca()
case 'u': /* --url */ case 'u': /* --url */
url = arg; url = arg;
continue; continue;
case 'l': /* --label */
label = arg;
continue;
case 'C': /* --cacert */ 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);
@@ -87,7 +90,7 @@ static int estca()
return command_usage("--url is required"); return command_usage("--url is required");
} }
est_tls = est_tls_create(url, NULL, NULL); est_tls = est_tls_create(url, label, NULL, 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");
@@ -132,7 +135,8 @@ static void __attribute__ ((constructor))reg()
{"--url url [--cacert file]+ [--caout file] [--outform der|pem] [--force]"}, {"--url url [--cacert file]+ [--caout file] [--outform der|pem] [--force]"},
{ {
{"help", 'h', 0, "show usage information"}, {"help", 'h', 0, "show usage information"},
{"url", 'u', 1, "URL of the SCEP server"}, {"url", 'u', 1, "URL of the EST server"},
{"label", 'l', 1, "label in the EST server path"},
{"cacert", 'C', 1, "TLS CA certificate"}, {"cacert", 'C', 1, "TLS CA certificate"},
{"caout", 'c', 1, "CA certificate [template]"}, {"caout", 'c', 1, "CA certificate [template]"},
{"outform", 'f', 1, "encoding of stored certificates, default: der"}, {"outform", 'f', 1, "encoding of stored certificates, default: der"},
+23 -7
View File
@@ -80,6 +80,11 @@ struct private_est_tls_t {
*/ */
char *http_path; char *http_path;
/**
* Label string used for http requests
*/
char *http_label;
/** /**
* Optional base64-encoded <username:password> for http basic authentication * Optional base64-encoded <username:password> for http basic authentication
*/ */
@@ -108,13 +113,13 @@ static chunk_t build_http_request(private_est_tls_t *this, est_op_t op, chunk_t
data = chunk_to_base64(in, NULL); data = chunk_to_base64(in, NULL);
len = asprintf(&http_header, len = asprintf(&http_header,
"POST %s/.well-known/est/%s HTTP/1.1\r\n" "POST %s/.well-known/est%s%s HTTP/1.1\r\n"
"Host: %s\r\n" "Host: %s\r\n"
"%s" "%s"
"Content-Type: %s\r\n" "Content-Type: %s\r\n"
"Content-Length: %d\r\n" "Content-Length: %d\r\n"
"\r\n", "\r\n",
this->http_path, operations[op], this->http_host, http_auth, this->http_path, this->http_label, operations[op], this->http_host, http_auth,
request_types[op], (int)data.len); request_types[op], (int)data.len);
if (len > 0) if (len > 0)
{ {
@@ -128,11 +133,11 @@ static chunk_t build_http_request(private_est_tls_t *this, est_op_t op, chunk_t
else /* create HTTP GET request */ else /* create HTTP GET request */
{ {
len = asprintf(&http_header, len = asprintf(&http_header,
"GET %s/.well-known/est/%s HTTP/1.1\r\n" "GET %s/.well-known/est%s%s HTTP/1.1\r\n"
"Host: %s\r\n" "Host: %s\r\n"
"%s" "%s"
"\r\n", "\r\n",
this->http_path, operations[op], this->http_host, http_auth); this->http_path, this->http_label, operations[op], this->http_host, http_auth);
if (len > 0) if (len > 0)
{ {
request = chunk_create(http_header, len); request = chunk_create(http_header, len);
@@ -289,11 +294,12 @@ METHOD(est_tls_t, destroy, void,
} }
chunk_clear(&this->user_pass); chunk_clear(&this->user_pass);
free(this->http_host); free(this->http_host);
free(this->http_label);
free(this->http_path); free(this->http_path);
free(this); free(this);
} }
static bool est_tls_init(private_est_tls_t *this, char *uri, static bool est_tls_init(private_est_tls_t *this, char *uri, char *label,
certificate_t *client_cert) certificate_t *client_cert)
{ {
identification_t *client_id = NULL, *server_id = NULL; identification_t *client_id = NULL, *server_id = NULL;
@@ -321,6 +327,16 @@ static bool est_tls_init(private_est_tls_t *this, char *uri,
*path_str = '\0'; *path_str = '\0';
} }
/* ensure sure label starts and ends with '/' character */
if (!label || !label[0] ||
asprintf(&this->http_label, "%s%s%s",
label[0] == '/' ? "" : "/",
label,
label[strlen(label) - 1] == '/' ? "" : "/") < 0)
{
this->http_label = strdup("/");
}
/* duplicate <hostname:port> string since we are going to manipulate it */ /* duplicate <hostname:port> string since we are going to manipulate it */
host_str = strdup(uri); host_str = strdup(uri);
@@ -392,7 +408,7 @@ end:
/** /**
* See header * See header
*/ */
est_tls_t *est_tls_create(char *uri, certificate_t *client_cert, char *user_pass) est_tls_t *est_tls_create(char *uri, char *label, certificate_t *client_cert, char *user_pass)
{ {
private_est_tls_t *this; private_est_tls_t *this;
@@ -408,7 +424,7 @@ est_tls_t *est_tls_create(char *uri, certificate_t *client_cert, char *user_pass
this->user_pass = chunk_to_base64(chunk_from_str(user_pass), NULL); this->user_pass = chunk_to_base64(chunk_from_str(user_pass), NULL);
} }
if (!est_tls_init(this, uri, client_cert)) if (!est_tls_init(this, uri, label, client_cert))
{ {
destroy(this); destroy(this);
return NULL; return NULL;
+2 -1
View File
@@ -70,10 +70,11 @@ struct est_tls_t {
* Create a est_tls instance. * Create a est_tls instance.
* *
* @param uri URI (https://...) * @param uri URI (https://...)
* @param label Optional EST server label
* @param client_cert Optional client certificate * @param client_cert Optional client certificate
* @param user_pass Optional username:password for HTTP Basic Authentication * @param user_pass Optional username:password for HTTP Basic Authentication
*/ */
est_tls_t *est_tls_create(char *uri, certificate_t *client_cert, est_tls_t *est_tls_create(char *uri, char *label, certificate_t *client_cert,
char *user_pass); char *user_pass);
#endif /** EST_TLS_H_ @}*/ #endif /** EST_TLS_H_ @}*/
+4
View File
@@ -8,6 +8,7 @@ pki \-\-est \- Enroll an X.509 certificate with an EST server
. .
.SY pki\ \-\-est .SY pki\ \-\-est
.BI\-\-\-url\~ url .BI\-\-\-url\~ url
.OP \-\-label label
.OP \-\-in file .OP \-\-in file
.BI \-\-cacert\~ file .BI \-\-cacert\~ file
.RB [ \-\-cert .RB [ \-\-cert
@@ -61,6 +62,9 @@ Read command line options from \fIfile\fR.
.BI "\-u, \-\-url " url .BI "\-u, \-\-url " url
URL of the EST server. URL of the EST server.
.TP .TP
.BI "\-l, \-\-label " label
Label in the EST server path.
.TP
.BI "\-i, \-\-in " file .BI "\-i, \-\-in " file
PKCS#10 certificate request. If not given, the certificate request is read from PKCS#10 certificate request. If not given, the certificate request is read from
\fISTDIN\fR. \fISTDIN\fR.
+4
View File
@@ -8,6 +8,7 @@ pki \-\-estca \- Get CA certificate[s] from an EST server
. .
.SY pki\ \-\-estca .SY pki\ \-\-estca
.BI\-\-\-url\~ url .BI\-\-\-url\~ url
.OP \-\-label label
.BI\-\-\-cacert\~ file .BI\-\-\-cacert\~ file
.OP \-\-caout file .OP \-\-caout file
.OP \-\-outform encoding .OP \-\-outform encoding
@@ -47,6 +48,9 @@ Read command line options from \fIfile\fR.
.BI "\-u, \-\-url " url .BI "\-u, \-\-url " url
URL of the SCEP server. URL of the SCEP server.
.TP .TP
.BI "\-l, \-\-label " label
Label in the EST server path.
.TP
.BI "\-C, \-\-cacert " file .BI "\-C, \-\-cacert " file
CA certificate in the trust chain used for EST TLS server signature verification. CA certificate in the trust chain used for EST TLS server signature verification.
Can be used multiple times. Can be used multiple times.