diff --git a/configure.ac b/configure.ac index ec6ec9bb3..87aa40dd9 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/src/pki/commands/verify.c b/src/pki/commands/verify.c index 6cfaaf263..8cc633a95 100644 --- a/src/pki/commands/verify.c +++ b/src/pki/commands/verify.c @@ -19,32 +19,53 @@ #include #include +#include /** * 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; + goto end; } - 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; - } - } - 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 - { - printf("signature invalid\n"); - } - if (cafile) - { - ca->destroy(ca); - } - cert->destroy(cert); + enumerator->destroy(enumerator); - return good ? 0 : 2; + if (!trusted) + { + printf("certificate untrusted\n"); + } + +end: + lib->credmgr->remove_set(lib->credmgr, &creds->set); + creds->destroy(creds); + + if (!trusted) + { + return 1; + } + 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"}, } }); }