pki: Support complex trustchain and revocation checking in --verify
authorMartin Willi <martin@revosec.ch>
Fri, 4 Apr 2014 08:37:59 +0000 (10:37 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Jun 2014 14:34:16 +0000 (16:34 +0200)
configure.ac
src/pki/commands/verify.c

index ec6ec9b..87aa40d 100644 (file)
@@ -1160,9 +1160,9 @@ s_plugins=
 t_plugins=
 
 ADD_PLUGIN([test-vectors],         [s charon scepclient pki])
-ADD_PLUGIN([curl],                 [s charon scepclient scripts nm cmd])
-ADD_PLUGIN([winhttp],              [s charon scripts])
-ADD_PLUGIN([soup],                 [s charon scripts nm cmd])
+ADD_PLUGIN([curl],                 [s charon scepclient pki scripts nm cmd])
+ADD_PLUGIN([winhttp],              [s charon pki scripts])
+ADD_PLUGIN([soup],                 [s charon pki scripts nm cmd])
 ADD_PLUGIN([unbound],              [s charon scripts])
 ADD_PLUGIN([ldap],                 [s charon scepclient scripts nm cmd])
 ADD_PLUGIN([mysql],                [s charon pool manager medsrv attest])
@@ -1180,7 +1180,7 @@ ADD_PLUGIN([rdrand],               [s charon scepclient pki scripts medsrv attes
 ADD_PLUGIN([random],               [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
 ADD_PLUGIN([nonce],                [s charon nm cmd aikgen])
 ADD_PLUGIN([x509],                 [s charon scepclient pki scripts attest nm cmd aikgen])
-ADD_PLUGIN([revocation],           [s charon nm cmd])
+ADD_PLUGIN([revocation],           [s charon pki nm cmd])
 ADD_PLUGIN([constraints],          [s charon nm cmd])
 ADD_PLUGIN([acert],                [s charon])
 ADD_PLUGIN([pubkey],               [s charon cmd aikgen])
index 6cfaaf2..8cc633a 100644 (file)
 
 #include <credentials/certificates/certificate.h>
 #include <credentials/certificates/x509.h>
+#include <credentials/sets/mem_cred.h>
 
 /**
  * Verify a certificate signature
  */
 static int verify()
 {
-       certificate_t *cert, *ca;
-       char *file = NULL, *cafile = NULL;
-       bool good = FALSE;
-       char *arg;
+       bool trusted = FALSE, valid = FALSE, revoked = FALSE;
+       bool has_ca = FALSE, online = FALSE;
+       certificate_t *cert;
+       enumerator_t *enumerator;
+       auth_cfg_t *auth;
+       mem_cred_t *creds;
+       char *arg, *file = NULL;
+
+       creds = mem_cred_create();
+       lib->credmgr->add_set(lib->credmgr, &creds->set);
 
        while (TRUE)
        {
                switch (command_getopt(&arg))
                {
                        case 'h':
+                               creds->destroy(creds);
                                return command_usage(NULL);
                        case 'i':
                                file = arg;
                                continue;
                        case 'c':
-                               cafile = arg;
+                               cert = lib->creds->create(lib->creds,
+                                                                                 CRED_CERTIFICATE, CERT_X509,
+                                                                                 BUILD_FROM_FILE, arg, BUILD_END);
+                               if (!cert)
+                               {
+                                       fprintf(stderr, "parsing CA certificate failed\n");
+                                       goto end;
+                               }
+                               has_ca = TRUE;
+                               creds->add_cert(creds, TRUE, cert);
+                               continue;
+                       case 'o':
+                               online = TRUE;
                                continue;
                        case EOF:
                                break;
                        default:
+                               creds->destroy(creds);
                                return command_usage("invalid --verify option");
                }
                break;
@@ -63,7 +84,7 @@ static int verify()
                if (!chunk_from_fd(0, &chunk))
                {
                        fprintf(stderr, "reading certificate failed: %s\n", strerror(errno));
-                       return 1;
+                       goto end;
                }
                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                                                                  BUILD_BLOB, chunk, BUILD_END);
@@ -72,60 +93,76 @@ static int verify()
        if (!cert)
        {
                fprintf(stderr, "parsing certificate failed\n");
-               return 1;
-       }
-       if (cafile)
-       {
-               ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
-                                                               BUILD_FROM_FILE, cafile, BUILD_END);
-               if (!ca)
-               {
-                       fprintf(stderr, "parsing CA certificate failed\n");
-                       return 1;
-               }
+               goto end;
        }
-       else
-       {
-               ca = cert;
-       }
-       if (cert->issued_by(cert, ca, NULL))
+       creds->add_cert(creds, !has_ca, cert);
+
+       enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+                                                                       KEY_ANY, cert->get_subject(cert), online);
+       if (enumerator->enumerate(enumerator, &cert, &auth))
        {
+               trusted = TRUE;
                if (cert->get_validity(cert, NULL, NULL, NULL))
                {
-                       if (cafile)
-                       {
-                               if (ca->get_validity(ca, NULL, NULL, NULL))
-                               {
-                                       printf("signature good, certificates valid\n");
-                                       good = TRUE;
-                               }
-                               else
-                               {
-                                       printf("signature good, CA certificates not valid now\n");
-                               }
-                       }
-                       else
-                       {
-                               printf("signature good, certificate valid\n");
-                               good = TRUE;
-                       }
+                       printf("certificate trusted, lifetimes valid");
+                       valid = TRUE;
                }
                else
                {
-                       printf("certificate not valid now\n");
+                       printf("certificate trusted, but no valid lifetime");
                }
+               if (online)
+               {
+                       switch ((uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION))
+                       {
+                               case VALIDATION_GOOD:
+                                       printf(", certificate not revoked");
+                                       break;
+                               case VALIDATION_SKIPPED:
+                                       printf(", no revocation information");
+                                       break;
+                               case VALIDATION_STALE:
+                                       printf(", revocation information stale");
+                                       break;
+                               case VALIDATION_FAILED:
+                                       printf(", revocation checking failed");
+                                       break;
+                               case VALIDATION_ON_HOLD:
+                                       printf(", certificate revocation on hold");
+                                       revoked = TRUE;
+                                       break;
+                               case VALIDATION_REVOKED:
+                                       printf(", certificate revoked");
+                                       revoked = TRUE;
+                                       break;
+                       }
+               }
+               printf("\n");
        }
-       else
+       enumerator->destroy(enumerator);
+
+       if (!trusted)
        {
-               printf("signature invalid\n");
+               printf("certificate untrusted\n");
        }
-       if (cafile)
+
+end:
+       lib->credmgr->remove_set(lib->credmgr, &creds->set);
+       creds->destroy(creds);
+
+       if (!trusted)
        {
-               ca->destroy(ca);
+               return 1;
        }
-       cert->destroy(cert);
-
-       return good ? 0 : 2;
+       if (!valid)
+       {
+               return 2;
+       }
+       if (revoked)
+       {
+               return 3;
+       }
+       return 0;
 }
 
 /**
@@ -140,7 +177,8 @@ static void __attribute__ ((constructor))reg()
                {
                        {"help",        'h', 0, "show usage information"},
                        {"in",          'i', 1, "X.509 certificate to verify, default: stdin"},
-                       {"cacert",      'c', 1, "CA certificate, default: verify self signed"},
+                       {"cacert",      'c', 1, "CA certificate for trustchain verification"},
+                       {"online",      'o', 0, "enable online CRL/OCSP revocation checking"},
                }
        });
 }