Commit 01c893c08b for strongswan.org
commit 01c893c08bb7dc3a62f1d1e7d676e2d6d5c83f30
Author: Tobias Brunner <tobias@strongswan.org>
Date: Thu Nov 5 15:17:58 2026 +0100
vici: Load first type-matching certificate from a bundle
Usually, bundles start with the root or an intermediate CA certificate,
so this allows using such a file in `certs` without having to reverse
the order. For `cacerts`, we also only load the first certificate but
in this case we explicitly filter for CA certificates.
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index 12f3303e72..61577590a0 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -47,6 +47,7 @@
#include <daemon.h>
#include <threading/rwlock.h>
#include <threading/rwlock_condvar.h>
+#include <credentials/containers/pem.h>
#include <collections/array.h>
#include <collections/hashtable.h>
#include <collections/linked_list.h>
@@ -1338,9 +1339,22 @@ static bool add_cert(auth_data_t *auth, auth_rule_t rule, certificate_t *cert)
static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
{
certificate_t *cert;
+ pem_selection_t sel;
+ pem_t *bundle;
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB, v, BUILD_END);
+ bundle = lib->creds->create(lib->creds, CRED_CONTAINER,
+ CONTAINER_PEM, BUILD_BLOB, v, BUILD_END);
+ if (bundle)
+ {
+ sel = (rule == AUTH_RULE_CA_CERT) ? PEM_SELECTION_CA : PEM_SELECTION_EE;
+ cert = bundle->get_first(bundle, sel);
+ bundle->container.destroy(&bundle->container);
+ }
+ else
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB, v, BUILD_END);
+ }
if (cert)
{
return add_cert(auth, rule, cert);
@@ -1753,6 +1767,8 @@ CALLBACK(auth_sn, bool,
auth_rule_t rule;
certificate_t *cert;
chunk_t handle;
+ pem_selection_t sel;
+ pem_t *bundle;
INIT(data,
.request = auth->request,
@@ -1781,8 +1797,22 @@ CALLBACK(auth_sn, bool,
if (data->file)
{
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, data->file, BUILD_END);
+ bundle = lib->creds->create(lib->creds, CRED_CONTAINER,
+ CONTAINER_PEM, BUILD_FROM_FILE, data->file,
+ BUILD_END);
+ if (bundle)
+ {
+ sel = strcasepfx(name, "cert") ? PEM_SELECTION_EE
+ : PEM_SELECTION_CA;
+ cert = bundle->get_first(bundle, sel);
+ bundle->container.destroy(&bundle->container);
+ }
+ else
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_X509, BUILD_FROM_FILE, data->file,
+ BUILD_END);
+ }
}
else
{
diff --git a/src/swanctl/swanctl.8.in b/src/swanctl/swanctl.8.in
index 98ef758f2e..e3249d6aaf 100644
--- a/src/swanctl/swanctl.8.in
+++ b/src/swanctl/swanctl.8.in
@@ -178,9 +178,11 @@ May contain config snippets (\fI*.conf\fR files) that are merged with the main
.SS PEM-encoded Certificate Bundles
In some directories, PEM-encoded certificate bundles are supported (i.e. files
that concatenate several PEM-encoded certificates). This may be used to
-load certificate chains from a single file. However, please be aware that for
-all other uses, such as referencing a file in \fBcerts\fR or \fBcacerts\fR in
-\fIswanctl.conf\fR, only the \fBfirst\fR certificate is loaded from such a file.
+load certificate chains from a single file. However, please be aware that in
+most other cases only the first certificate is loaded from such a file. As a
+special exception, when used in \fBcerts\fR or \fBcacerts\fR in
+\fIswanctl.conf\fR, the type of certificate is considered, i.e. the \fBfirst\fR
+end entity or CA certificate is loaded, respectively.
So if necessary, structure your files accordingly or split them up.
.SH SEE ALSO
.BR swanctl.conf (5)
diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt
index ea82706ac0..a397203d87 100644
--- a/src/swanctl/swanctl.opt
+++ b/src/swanctl/swanctl.opt
@@ -384,7 +384,8 @@ connections.<conn>.local<suffix>.certs =
Comma separated list of certificate candidates to use for authentication.
The certificates may use a relative path from the **swanctl** _x509_
- directory or an absolute path.
+ directory or an absolute path. Be aware that only the first end entity
+ certificate from a PEM-encoded certificate bundle is loaded.
The certificate used for authentication is selected based on the received
certificate request payloads. If no appropriate CA can be located, the
@@ -401,7 +402,8 @@ connections.<conn>.local<suffix>.cert<suffix>.file =
Absolute path to the certificate to load.
Absolute path to the certificate to load. Passed as-is to the daemon, so it
- must be readable by it.
+ must be readable by it. Be aware that only the first end entity certificate
+ from a PEM-encoded certificate bundle is loaded.
Configure either this or _handle_, but not both, in one section.
@@ -576,8 +578,8 @@ connections.<conn>.remote<suffix>.certs =
Comma separated list of certificates to accept for authentication.
The certificates may use a relative path from the **swanctl** _x509_
- directory or an absolute path. Be aware that only the first certificate
- from a PEM-encoded certificate bundle is loaded.
+ directory or an absolute path. Be aware that only the first end entity
+ certificate from a PEM-encoded certificate bundle is loaded.
connections.<conn>.remote<suffix>.cert<suffix> =
Section for a certificate to accept for authentication.
@@ -590,7 +592,8 @@ connections.<conn>.remote<suffix>.cert<suffix>.file =
Absolute path to the certificate to load.
Absolute path to the certificate to load. Passed as-is to the daemon, so it
- must be readable by it.
+ must be readable by it. Be aware that only the first end entity certificate
+ from a PEM-encoded certificate bundle is loaded.
Configure either this or _handle_, but not both, in one section.
@@ -612,7 +615,7 @@ connections.<conn>.remote<suffix>.cacerts =
Comma separated list of CA certificates to accept for authentication.
The certificates may use a relative path from the **swanctl** _x509ca_
- directory or an absolute path. Be aware that only the first certificate
+ directory or an absolute path. Be aware that only the first CA certificate
from a PEM-encoded certificate bundle is loaded.
connections.<conn>.remote<suffix>.cacert<suffix> =
@@ -626,7 +629,8 @@ connections.<conn>.remote<suffix>.cacert<suffix>.file =
Absolute path to the certificate to load.
Absolute path to the certificate to load. Passed as-is to the daemon, so it
- must be readable by it.
+ must be readable by it. Be aware that only the first CA certificate
+ from a PEM-encoded certificate bundle is loaded.
Configure either this or _handle_, but not both, in one section.