pki: --verify command optionally takes directories for CAs and CRLs
authorTobias Brunner <tobias@strongswan.org>
Mon, 12 Feb 2018 10:48:16 +0000 (11:48 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 18 May 2018 15:29:00 +0000 (17:29 +0200)
src/pki/commands/verify.c
src/pki/man/pki---verify.1.in

index dd667fb..88ef448 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2018 Tobias Brunner
  * Copyright (C) 2009 Martin Willi
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -14,6 +14,9 @@
  * for more details.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <errno.h>
 
 #include "pki.h"
 #include <credentials/sets/mem_cred.h>
 
 /**
+ * Load a CA or CRL and add it to the credential set
+ */
+static bool load_cert(mem_cred_t *creds, char *path, certificate_type_t subtype)
+{
+       certificate_t *cert;
+       char *credname;
+
+       switch (subtype)
+       {
+               case CERT_X509:
+                       credname = "CA certificate";
+                       break;
+               case CERT_X509_CRL:
+                       credname = "CRL";
+                       break;
+               default:
+                       return FALSE;
+       }
+       cert = lib->creds->create(lib->creds,
+                                                         CRED_CERTIFICATE, subtype,
+                                                         BUILD_FROM_FILE, path, BUILD_END);
+       if (!cert)
+       {
+               fprintf(stderr, "parsing %s from '%s' failed\n", credname, path);
+               return FALSE;
+       }
+       if (subtype == CERT_X509_CRL)
+       {
+               creds->add_crl(creds, (crl_t*)cert);
+       }
+       else
+       {
+               creds->add_cert(creds, TRUE, cert);
+       }
+       return TRUE;
+}
+
+/**
+ * Load CA cert or CRL either from a file or a path
+ */
+static bool load_certs(mem_cred_t *creds, char *path,
+                                          certificate_type_t subtype)
+{
+       enumerator_t *enumerator;
+       struct stat st;
+       bool loaded = FALSE;
+
+       if (stat(path, &st))
+       {
+               fprintf(stderr, "failed to access '%s': %s\n", path, strerror(errno));
+               return FALSE;
+       }
+       if (S_ISDIR(st.st_mode))
+       {
+               enumerator = enumerator_create_directory(path);
+               if (!enumerator)
+               {
+                       fprintf(stderr, "directory '%s' can not be opened: %s",
+                                       path, strerror(errno));
+                       return FALSE;
+               }
+               while (enumerator->enumerate(enumerator, NULL, &path, &st))
+               {
+                       if (S_ISREG(st.st_mode) && load_cert(creds, path, subtype))
+                       {
+                               loaded = TRUE;
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               loaded = load_cert(creds, path, subtype);
+       }
+       return loaded;
+}
+
+/**
  * Verify a certificate signature
  */
 static int verify()
@@ -49,28 +130,16 @@ static int verify()
                                file = arg;
                                continue;
                        case 'c':
-                               cert = lib->creds->create(lib->creds,
-                                                                                 CRED_CERTIFICATE, CERT_X509,
-                                                                                 BUILD_FROM_FILE, arg, BUILD_END);
-                               if (!cert)
+                               if (load_certs(creds, arg, CERT_X509))
                                {
-                                       fprintf(stderr, "parsing CA certificate failed\n");
-                                       goto end;
+                                       has_ca = TRUE;
                                }
-                               has_ca = TRUE;
-                               creds->add_cert(creds, TRUE, cert);
                                continue;
                        case 'l':
-                               cert = lib->creds->create(lib->creds,
-                                                                                 CRED_CERTIFICATE, CERT_X509_CRL,
-                                                                                 BUILD_FROM_FILE, arg, BUILD_END);
-                               if (!cert)
+                               if (load_certs(creds, arg, CERT_X509_CRL))
                                {
-                                       fprintf(stderr, "parsing CRL failed\n");
-                                       goto end;
+                                       online = TRUE;
                                }
-                               online = TRUE;
-                               creds->add_crl(creds, (crl_t*)cert);
                                continue;
                        case 'o':
                                online = TRUE;
@@ -108,7 +177,7 @@ static int verify()
                fprintf(stderr, "parsing certificate failed\n");
                goto end;
        }
-       creds->add_cert(creds, !has_ca, cert);
+       cert = creds->add_cert_ref(creds, !has_ca, cert);
 
        enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
                                                                        KEY_ANY, cert->get_subject(cert), online);
@@ -153,6 +222,7 @@ static int verify()
                printf("\n");
        }
        enumerator->destroy(enumerator);
+       cert->destroy(cert);
 
        if (!trusted)
        {
index 74adaf1..a655858 100644 (file)
@@ -47,10 +47,13 @@ X.509 certificate to verify. If not given it is read from \fISTDIN\fR.
 .TP
 .BI "\-c, \-\-cacert " file
 CA certificate to use for trustchain verification. If not given the certificate
-is assumed to be self\-signed.
+is assumed to be self\-signed. May optionally be a path to a directory from
+which CA certificates are loaded. Can be used multiple times.
 .TP
 .BI "\-l, \-\-crl " file
-Local CRL to use for trustchain verification. Implies \fB-o\fR.
+Local CRL to use for trustchain verification. May optionally be a path to a
+directory from which CRLs are loaded. Can be used multiple times.
+Implies \fB-o\fR.
 .TP
 .BI "\-o, \-\-online
 Enable online CRL/OCSP revocation checking.