2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 #include <asn1/asn1.h>
23 #include <credentials/certificates/certificate.h>
24 #include <credentials/certificates/x509.h>
25 #include <credentials/certificates/crl.h>
26 #include <credentials/certificates/ac.h>
27 #include <selectors/traffic_selector.h>
37 * Print PEM encoding of a certificate
39 static void print_pem(certificate_t
*cert
)
43 if (cert
->get_encoding(cert
, CERT_PEM
, &encoding
))
45 printf("%.*s", (int)encoding
.len
, encoding
.ptr
);
50 fprintf(stderr
, "PEM encoding certificate failed\n");
55 * Print public key information
57 static void print_pubkey(public_key_t
*key
, bool has_privkey
)
61 printf("pubkey: %N %d bits", key_type_names
, key
->get_type(key
),
62 key
->get_keysize(key
));
65 printf(", has private key");
68 if (key
->get_fingerprint(key
, KEYID_PUBKEY_INFO_SHA1
, &chunk
))
70 printf("keyid: %#B\n", &chunk
);
72 if (key
->get_fingerprint(key
, KEYID_PUBKEY_SHA1
, &chunk
))
74 printf("subjkey: %#B\n", &chunk
);
79 * Print X509 specific certificate information
81 static void print_x509(x509_t
*x509
)
83 enumerator_t
*enumerator
;
85 traffic_selector_t
*block
;
89 int len
, explicit, inhibit
;
92 x509_cert_policy_t
*policy
;
93 x509_policy_mapping_t
*mapping
;
95 chunk
= chunk_skip_zero(x509
->get_serial(x509
));
96 printf("serial: %#B\n", &chunk
);
99 enumerator
= x509
->create_subjectAltName_enumerator(x509
);
100 while (enumerator
->enumerate(enumerator
, &id
))
104 printf("altNames: ");
117 enumerator
->destroy(enumerator
);
119 flags
= x509
->get_flags(x509
);
125 if (flags
& X509_CRL_SIGN
)
133 if (flags
& X509_OCSP_SIGNER
)
141 if (flags
& X509_SERVER_AUTH
)
143 printf("serverAuth ");
145 if (flags
& X509_CLIENT_AUTH
)
147 printf("clientAuth ");
149 if (flags
& X509_IKE_INTERMEDIATE
)
151 printf("iKEIntermediate ");
153 if (flags
& X509_SELF_SIGNED
)
155 printf("self-signed ");
160 enumerator
= x509
->create_crl_uri_enumerator(x509
);
161 while (enumerator
->enumerate(enumerator
, &cdp
))
165 printf("CRL URIs: %s", cdp
->uri
);
170 printf(" %s", cdp
->uri
);
174 printf(" (CRL issuer: %Y)", cdp
->issuer
);
178 enumerator
->destroy(enumerator
);
181 enumerator
= x509
->create_ocsp_uri_enumerator(x509
);
182 while (enumerator
->enumerate(enumerator
, &uri
))
186 printf("OCSP URIs: %s\n", uri
);
191 printf(" %s\n", uri
);
194 enumerator
->destroy(enumerator
);
196 len
= x509
->get_constraint(x509
, X509_PATH_LEN
);
197 if (len
!= X509_NO_CONSTRAINT
)
199 printf("pathlen: %d\n", len
);
203 enumerator
= x509
->create_name_constraint_enumerator(x509
, TRUE
);
204 while (enumerator
->enumerate(enumerator
, &id
))
208 printf("Permitted NameConstraints:\n");
213 enumerator
->destroy(enumerator
);
215 enumerator
= x509
->create_name_constraint_enumerator(x509
, FALSE
);
216 while (enumerator
->enumerate(enumerator
, &id
))
220 printf("Excluded NameConstraints:\n");
225 enumerator
->destroy(enumerator
);
228 enumerator
= x509
->create_cert_policy_enumerator(x509
);
229 while (enumerator
->enumerate(enumerator
, &policy
))
235 printf("CertificatePolicies:\n");
238 oid
= asn1_oid_to_string(policy
->oid
);
241 printf(" %s\n", oid
);
246 printf(" %#B\n", &policy
->oid
);
250 printf(" CPS: %s\n", policy
->cps_uri
);
252 if (policy
->unotice_text
)
254 printf(" Notice: %s\n", policy
->unotice_text
);
258 enumerator
->destroy(enumerator
);
261 enumerator
= x509
->create_policy_mapping_enumerator(x509
);
262 while (enumerator
->enumerate(enumerator
, &mapping
))
264 char *issuer_oid
, *subject_oid
;
268 printf("PolicyMappings:\n");
271 issuer_oid
= asn1_oid_to_string(mapping
->issuer
);
272 subject_oid
= asn1_oid_to_string(mapping
->subject
);
273 printf(" %s => %s\n", issuer_oid
, subject_oid
);
277 enumerator
->destroy(enumerator
);
279 explicit = x509
->get_constraint(x509
, X509_REQUIRE_EXPLICIT_POLICY
);
280 inhibit
= x509
->get_constraint(x509
, X509_INHIBIT_POLICY_MAPPING
);
281 len
= x509
->get_constraint(x509
, X509_INHIBIT_ANY_POLICY
);
283 if (explicit != X509_NO_CONSTRAINT
|| inhibit
!= X509_NO_CONSTRAINT
||
284 len
!= X509_NO_CONSTRAINT
)
286 printf("PolicyConstraints:\n");
287 if (explicit != X509_NO_CONSTRAINT
)
289 printf(" requireExplicitPolicy: %d\n", explicit);
291 if (inhibit
!= X509_NO_CONSTRAINT
)
293 printf(" inhibitPolicyMapping: %d\n", inhibit
);
295 if (len
!= X509_NO_CONSTRAINT
)
297 printf(" inhibitAnyPolicy: %d\n", len
);
301 chunk
= x509
->get_authKeyIdentifier(x509
);
304 printf("authkeyId: %#B\n", &chunk
);
307 chunk
= x509
->get_subjectKeyIdentifier(x509
);
310 printf("subjkeyId: %#B\n", &chunk
);
312 if (x509
->get_flags(x509
) & X509_IP_ADDR_BLOCKS
)
315 printf("addresses: ");
316 enumerator
= x509
->create_ipAddrBlock_enumerator(x509
);
317 while (enumerator
->enumerate(enumerator
, &block
))
329 enumerator
->destroy(enumerator
);
335 * Print CRL specific information
337 static void print_crl(crl_t
*crl
)
339 enumerator_t
*enumerator
;
349 chunk
= chunk_skip_zero(crl
->get_serial(crl
));
350 printf("serial: %#B\n", &chunk
);
352 if (crl
->is_delta_crl(crl
, &chunk
))
354 chunk
= chunk_skip_zero(chunk
);
355 printf("delta CRL: for serial %#B\n", &chunk
);
357 chunk
= crl
->get_authKeyIdentifier(crl
);
358 printf("authKeyId: %#B\n", &chunk
);
361 enumerator
= crl
->create_delta_crl_uri_enumerator(crl
);
362 while (enumerator
->enumerate(enumerator
, &cdp
))
366 printf("freshest: %s", cdp
->uri
);
371 printf(" %s", cdp
->uri
);
375 printf(" (CRL issuer: %Y)", cdp
->issuer
);
379 enumerator
->destroy(enumerator
);
381 enumerator
= crl
->create_enumerator(crl
);
382 while (enumerator
->enumerate(enumerator
, &chunk
, &ts
, &reason
))
386 enumerator
->destroy(enumerator
);
388 printf("%d revoked certificate%s%s\n", count
,
389 count
== 1 ?
"" : "s", count ?
":" : "");
390 enumerator
= crl
->create_enumerator(crl
);
391 while (enumerator
->enumerate(enumerator
, &chunk
, &ts
, &reason
))
393 chunk
= chunk_skip_zero(chunk
);
394 localtime_r(&ts
, &tm
);
395 strftime(buf
, sizeof(buf
), "%F %T", &tm
);
396 printf(" %#B %N %s\n", &chunk
, crl_reason_names
, reason
, buf
);
399 enumerator
->destroy(enumerator
);
403 * Print AC specific information
405 static void print_ac(ac_t
*ac
)
407 ac_group_type_t type
;
408 identification_t
*id
;
409 enumerator_t
*groups
;
413 chunk
= chunk_skip_zero(ac
->get_serial(ac
));
414 printf("serial: %#B\n", &chunk
);
416 id
= ac
->get_holderIssuer(ac
);
419 printf("hissuer: \"%Y\"\n", id
);
421 chunk
= chunk_skip_zero(ac
->get_holderSerial(ac
));
424 printf("hserial: %#B\n", &chunk
);
426 groups
= ac
->create_group_enumerator(ac
);
427 while (groups
->enumerate(groups
, &type
, &chunk
))
443 case AC_GROUP_TYPE_STRING
:
444 printf("%.*s", (int)chunk
.len
, chunk
.ptr
);
446 case AC_GROUP_TYPE_OID
:
447 oid
= asn1_known_oid(chunk
);
448 if (oid
== OID_UNKNOWN
)
450 str
= asn1_oid_to_string(chunk
);
458 printf("OID:%#B", &chunk
);
463 printf("%s", oid_names
[oid
].name
);
466 case AC_GROUP_TYPE_OCTETS
:
467 printf("%#B", &chunk
);
472 groups
->destroy(groups
);
474 chunk
= ac
->get_authKeyIdentifier(ac
);
477 printf("authkey: %#B\n", &chunk
);
482 * Print certificate information
484 static void print_cert(certificate_t
*cert
, bool has_privkey
)
486 time_t now
, notAfter
, notBefore
;
491 printf("cert: %N\n", certificate_type_names
, cert
->get_type(cert
));
492 if (cert
->get_type(cert
) != CERT_X509_CRL
)
494 printf("subject: \"%Y\"\n", cert
->get_subject(cert
));
496 printf("issuer: \"%Y\"\n", cert
->get_issuer(cert
));
498 cert
->get_validity(cert
, &now
, ¬Before
, ¬After
);
499 printf("validity: not before %T, ", ¬Before
, FALSE
);
502 printf("not valid yet (valid in %V)\n", &now
, ¬Before
);
508 printf(" not after %T, ", ¬After
, FALSE
);
511 printf("expired (%V ago)\n", &now
, ¬After
);
515 printf("ok (expires in %V)\n", &now
, ¬After
);
518 switch (cert
->get_type(cert
))
521 print_x509((x509_t
*)cert
);
524 print_crl((crl_t
*)cert
);
527 print_ac((ac_t
*)cert
);
530 fprintf(stderr
, "parsing certificate subtype %N not implemented\n",
531 certificate_type_names
, cert
->get_type(cert
));
534 key
= cert
->get_public_key(cert
);
537 print_pubkey(key
, has_privkey
);
543 CALLBACK(list_cb
, void,
544 format_options_t
*format
, char *name
, vici_res_t
*res
)
546 if (*format
& FORMAT_RAW
)
548 vici_dump(res
, "list-cert event", stdout
);
552 certificate_type_t type
;
558 buf
= vici_find(res
, &len
, "data");
559 has_privkey
= streq(vici_find_str(res
, "no", "has_privkey"), "yes");
560 if (enum_from_name(certificate_type_names
,
561 vici_find_str(res
, "ANY", "type"), &type
) &&
562 type
!= CERT_ANY
&& buf
)
564 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, type
,
565 BUILD_BLOB_ASN1_DER
, chunk_create(buf
, len
),
569 if (*format
& FORMAT_PEM
)
575 print_cert(cert
, has_privkey
);
581 fprintf(stderr
, "parsing certificate failed\n");
586 fprintf(stderr
, "received incomplete certificate data\n");
591 static int list_certs(vici_conn_t
*conn
)
595 format_options_t format
= 0;
596 char *arg
, *subject
= NULL
, *type
= NULL
;
600 switch (command_getopt(&arg
))
603 return command_usage(NULL
);
611 format
|= FORMAT_PEM
;
614 format
|= FORMAT_RAW
;
619 return command_usage("invalid --list-certs option");
623 if (vici_register(conn
, "list-cert", list_cb
, &format
) != 0)
625 fprintf(stderr
, "registering for certificates failed: %s\n",
629 req
= vici_begin("list-certs");
632 vici_add_key_valuef(req
, "type", "%s", type
);
636 vici_add_key_valuef(req
, "subject", "%s", subject
);
638 res
= vici_submit(req
, conn
);
641 fprintf(stderr
, "list-certs request failed: %s\n", strerror(errno
));
644 if (format
& FORMAT_RAW
)
646 vici_dump(res
, "list-certs reply", stdout
);
653 * Register the command.
655 static void __attribute__ ((constructor
))reg()
657 command_register((command_t
) {
658 list_certs
, 'x', "list-certs", "list stored certificates",
659 {"[--subject <dn/san>] [--type X509|X509_AC|X509_CRL] [--pem] [--raw]"},
661 {"help", 'h', 0, "show usage information"},
662 {"subject", 's', 1, "filter by certificate subject"},
663 {"type", 't', 1, "filter by certificate type"},
664 {"pem", 'p', 0, "print PEM encoding of certificate"},
665 {"raw", 'r', 0, "dump raw response message"},