pki: Allow to load CRLs from files in --verify
[strongswan.git] / src / pki / commands / verify.c
1 /*
2 * Copyright (C) 2016 Tobias Brunner
3 * Copyright (C) 2009 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <errno.h>
18
19 #include "pki.h"
20
21 #include <credentials/certificates/certificate.h>
22 #include <credentials/certificates/x509.h>
23 #include <credentials/sets/mem_cred.h>
24
25 /**
26 * Verify a certificate signature
27 */
28 static int verify()
29 {
30 bool trusted = FALSE, valid = FALSE, revoked = FALSE;
31 bool has_ca = FALSE, online = FALSE;
32 certificate_t *cert;
33 enumerator_t *enumerator;
34 auth_cfg_t *auth;
35 mem_cred_t *creds;
36 char *arg, *file = NULL;
37
38 creds = mem_cred_create();
39 lib->credmgr->add_set(lib->credmgr, &creds->set);
40
41 while (TRUE)
42 {
43 switch (command_getopt(&arg))
44 {
45 case 'h':
46 creds->destroy(creds);
47 return command_usage(NULL);
48 case 'i':
49 file = arg;
50 continue;
51 case 'c':
52 cert = lib->creds->create(lib->creds,
53 CRED_CERTIFICATE, CERT_X509,
54 BUILD_FROM_FILE, arg, BUILD_END);
55 if (!cert)
56 {
57 fprintf(stderr, "parsing CA certificate failed\n");
58 goto end;
59 }
60 has_ca = TRUE;
61 creds->add_cert(creds, TRUE, cert);
62 continue;
63 case 'l':
64 cert = lib->creds->create(lib->creds,
65 CRED_CERTIFICATE, CERT_X509_CRL,
66 BUILD_FROM_FILE, arg, BUILD_END);
67 if (!cert)
68 {
69 fprintf(stderr, "parsing CRL failed\n");
70 goto end;
71 }
72 online = TRUE;
73 creds->add_crl(creds, (crl_t*)cert);
74 continue;
75 case 'o':
76 online = TRUE;
77 continue;
78 case EOF:
79 break;
80 default:
81 creds->destroy(creds);
82 return command_usage("invalid --verify option");
83 }
84 break;
85 }
86
87 if (file)
88 {
89 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
90 BUILD_FROM_FILE, file, BUILD_END);
91 }
92 else
93 {
94 chunk_t chunk;
95
96 set_file_mode(stdin, CERT_ASN1_DER);
97 if (!chunk_from_fd(0, &chunk))
98 {
99 fprintf(stderr, "reading certificate failed: %s\n", strerror(errno));
100 goto end;
101 }
102 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
103 BUILD_BLOB, chunk, BUILD_END);
104 free(chunk.ptr);
105 }
106 if (!cert)
107 {
108 fprintf(stderr, "parsing certificate failed\n");
109 goto end;
110 }
111 creds->add_cert(creds, !has_ca, cert);
112
113 enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
114 KEY_ANY, cert->get_subject(cert), online);
115 if (enumerator->enumerate(enumerator, &cert, &auth))
116 {
117 trusted = TRUE;
118 if (cert->get_validity(cert, NULL, NULL, NULL))
119 {
120 printf("certificate trusted, lifetimes valid");
121 valid = TRUE;
122 }
123 else
124 {
125 printf("certificate trusted, but no valid lifetime");
126 }
127 if (online)
128 {
129 switch ((uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION))
130 {
131 case VALIDATION_GOOD:
132 printf(", certificate not revoked");
133 break;
134 case VALIDATION_SKIPPED:
135 printf(", no revocation information");
136 break;
137 case VALIDATION_STALE:
138 printf(", revocation information stale");
139 break;
140 case VALIDATION_FAILED:
141 printf(", revocation checking failed");
142 break;
143 case VALIDATION_ON_HOLD:
144 printf(", certificate revocation on hold");
145 revoked = TRUE;
146 break;
147 case VALIDATION_REVOKED:
148 printf(", certificate revoked");
149 revoked = TRUE;
150 break;
151 }
152 }
153 printf("\n");
154 }
155 enumerator->destroy(enumerator);
156
157 if (!trusted)
158 {
159 printf("certificate untrusted\n");
160 }
161
162 end:
163 lib->credmgr->remove_set(lib->credmgr, &creds->set);
164 creds->destroy(creds);
165
166 if (!trusted)
167 {
168 return 1;
169 }
170 if (!valid)
171 {
172 return 2;
173 }
174 if (revoked)
175 {
176 return 3;
177 }
178 return 0;
179 }
180
181 /**
182 * Register the command.
183 */
184 static void __attribute__ ((constructor))reg()
185 {
186 command_register((command_t) {
187 verify, 'v', "verify",
188 "verify a certificate using the CA certificate",
189 {"[--in file] [--cacert file] [--crl file]"},
190 {
191 {"help", 'h', 0, "show usage information"},
192 {"in", 'i', 1, "X.509 certificate to verify, default: stdin"},
193 {"cacert", 'c', 1, "CA certificate for trustchain verification"},
194 {"crl", 'l', 1, "CRL for trustchain verification"},
195 {"online", 'o', 0, "enable online CRL/OCSP revocation checking"},
196 }
197 });
198 }