2 * Copyright (C) 2015 Andreas Steffen
3 * Copyright (C) 2014 Martin Willi
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include <asn1/asn1.h>
25 #include <credentials/certificates/certificate.h>
26 #include <credentials/certificates/certificate_printer.h>
27 #include <selectors/traffic_selector.h>
32 * Static certificate printer object
34 static certificate_printer_t
*cert_printer
= NULL
;
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");
54 CALLBACK(list_cb
, void,
55 command_format_options_t
*format
, char *name
, vici_res_t
*res
)
58 certificate_type_t type
;
59 x509_flag_t flag
= X509_NONE
;
60 identification_t
*subject
= NULL
;
61 time_t not_before
= UNDEFINED_TIME
;
62 time_t not_after
= UNDEFINED_TIME
;
69 if (*format
& COMMAND_FORMAT_RAW
)
71 vici_dump(res
, "list-cert event", *format
& COMMAND_FORMAT_PRETTY
,
76 buf
= vici_find(res
, &len
, "data");
79 fprintf(stderr
, "received incomplete certificate data\n");
82 has_privkey
= streq(vici_find_str(res
, "no", "has_privkey"), "yes");
84 str
= vici_find_str(res
, "ANY", "type");
85 if (!enum_from_name(certificate_type_names
, str
, &type
) || type
== CERT_ANY
)
87 fprintf(stderr
, "unsupported certificate type '%s'\n", str
);
90 if (type
== CERT_X509
)
92 str
= vici_find_str(res
, "ANY", "flag");
93 if (!enum_from_name(x509_flag_names
, str
, &flag
) || flag
== X509_ANY
)
95 fprintf(stderr
, "unsupported certificate flag '%s'\n", str
);
99 if (type
== CERT_TRUSTED_PUBKEY
)
101 str
= vici_find_str(res
, NULL
, "subject");
104 subject
= identification_create_from_string(str
);
106 str
= vici_find_str(res
, NULL
, "not-before");
109 t_ch
= chunk_from_str(str
);
110 not_before
= asn1_to_time(&t_ch
, ASN1_GENERALIZEDTIME
);
112 str
= vici_find_str(res
, NULL
, "not-after");
115 t_ch
= chunk_from_str(str
);
116 not_after
= asn1_to_time(&t_ch
, ASN1_GENERALIZEDTIME
);
118 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, type
,
119 BUILD_BLOB_ASN1_DER
, chunk_create(buf
, len
),
120 BUILD_NOT_BEFORE_TIME
, not_before
,
121 BUILD_NOT_AFTER_TIME
, not_after
,
122 BUILD_SUBJECT
, subject
, BUILD_END
);
127 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, type
,
128 BUILD_BLOB_ASN1_DER
, chunk_create(buf
, len
),
133 if (*format
& COMMAND_FORMAT_PEM
)
139 cert_printer
->print_caption(cert_printer
, type
, flag
);
140 cert_printer
->print(cert_printer
, cert
, has_privkey
);
146 fprintf(stderr
, "parsing certificate failed\n");
150 static int list_certs(vici_conn_t
*conn
)
154 command_format_options_t format
= COMMAND_FORMAT_NONE
;
155 char *arg
, *subject
= NULL
, *type
= NULL
, *flag
= NULL
;
156 bool detailed
= TRUE
, utc
= FALSE
;
161 switch (command_getopt(&arg
))
164 return command_usage(NULL
);
175 format
|= COMMAND_FORMAT_PEM
;
178 format
|= COMMAND_FORMAT_PRETTY
;
179 /* fall through to raw */
181 format
|= COMMAND_FORMAT_RAW
;
192 return command_usage("invalid --list-certs option");
196 if (vici_register(conn
, "list-cert", list_cb
, &format
) != 0)
199 fprintf(stderr
, "registering for certificates failed: %s\n",
203 req
= vici_begin("list-certs");
207 vici_add_key_valuef(req
, "type", "%s", type
);
211 vici_add_key_valuef(req
, "flag", "%s", flag
);
215 vici_add_key_valuef(req
, "subject", "%s", subject
);
217 cert_printer
= certificate_printer_create(stdout
, detailed
, utc
);
219 res
= vici_submit(req
, conn
);
223 fprintf(stderr
, "list-certs request failed: %s\n", strerror(errno
));
224 cert_printer
->destroy(cert_printer
);
228 if (format
& COMMAND_FORMAT_RAW
)
230 vici_dump(res
, "list-certs reply", format
& COMMAND_FORMAT_PRETTY
,
235 cert_printer
->destroy(cert_printer
);
241 * Register the command.
243 static void __attribute__ ((constructor
))reg()
245 command_register((command_t
) {
246 list_certs
, 'x', "list-certs", "list stored certificates",
247 {"[--subject <dn/san>] [--pem]",
248 "[--type x509|x509_ac|x509_crl|ocsp_response|pubkey]",
249 "[--flag none|ca|aa|ocsp|any] [--raw|--pretty|--short|--utc]"},
251 {"help", 'h', 0, "show usage information"},
252 {"subject", 's', 1, "filter by certificate subject"},
253 {"type", 't', 1, "filter by certificate type"},
254 {"flag", 'f', 1, "filter by X.509 certificate flag"},
255 {"pem", 'p', 0, "print PEM encoding of certificate"},
256 {"raw", 'r', 0, "dump raw response message"},
257 {"pretty", 'P', 0, "dump raw response message in pretty print"},
258 {"short", 'S', 0, "omit some certificate details"},
259 {"utc", 'U', 0, "use UTC for time fields"},