]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/swanctl/commands/list_certs.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / swanctl / commands / list_certs.c
1 /*
2 * Copyright (C) 2015 Andreas Steffen
3 * Copyright (C) 2014 Martin Willi
4 *
5 * Copyright (C) secunet Security Networks AG
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18 #define _GNU_SOURCE
19 #include <stdio.h>
20 #include <errno.h>
21 #include <time.h>
22
23 #include <asn1/asn1.h>
24 #include <asn1/oid.h>
25 #include <credentials/certificates/certificate.h>
26 #include <credentials/certificates/certificate_printer.h>
27 #include <selectors/traffic_selector.h>
28
29 #include "command.h"
30
31 /**
32 * Static certificate printer object
33 */
34 static certificate_printer_t *cert_printer = NULL;
35
36 /**
37 * Print PEM encoding of a certificate
38 */
39 static void print_pem(certificate_t *cert)
40 {
41 chunk_t encoding;
42
43 if (cert->get_encoding(cert, CERT_PEM, &encoding))
44 {
45 printf("%.*s", (int)encoding.len, encoding.ptr);
46 free(encoding.ptr);
47 }
48 else
49 {
50 fprintf(stderr, "PEM encoding certificate failed\n");
51 }
52 }
53
54 CALLBACK(list_cb, void,
55 command_format_options_t *format, char *name, vici_res_t *res)
56 {
57 certificate_t *cert;
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;
63 chunk_t t_ch;
64 bool has_privkey;
65 char *str;
66 void *buf;
67 int len;
68
69 if (*format & COMMAND_FORMAT_RAW)
70 {
71 vici_dump(res, "list-cert event", *format & COMMAND_FORMAT_PRETTY,
72 stdout);
73 return;
74 }
75
76 buf = vici_find(res, &len, "data");
77 if (!buf)
78 {
79 fprintf(stderr, "received incomplete certificate data\n");
80 return;
81 }
82 has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes");
83
84 str = vici_find_str(res, "ANY", "type");
85 if (!enum_from_name(certificate_type_names, str, &type) || type == CERT_ANY)
86 {
87 fprintf(stderr, "unsupported certificate type '%s'\n", str);
88 return;
89 }
90 if (type == CERT_X509)
91 {
92 str = vici_find_str(res, "ANY", "flag");
93 if (!enum_from_name(x509_flag_names, str, &flag) || flag == X509_ANY)
94 {
95 fprintf(stderr, "unsupported certificate flag '%s'\n", str);
96 return;
97 }
98 }
99 if (type == CERT_TRUSTED_PUBKEY)
100 {
101 str = vici_find_str(res, NULL, "subject");
102 if (str)
103 {
104 subject = identification_create_from_string(str);
105 }
106 str = vici_find_str(res, NULL, "not-before");
107 if (str)
108 {
109 t_ch = chunk_from_str(str);
110 not_before = asn1_to_time(&t_ch, ASN1_GENERALIZEDTIME);
111 }
112 str = vici_find_str(res, NULL, "not-after");
113 if (str)
114 {
115 t_ch = chunk_from_str(str);
116 not_after = asn1_to_time(&t_ch, ASN1_GENERALIZEDTIME);
117 }
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);
123 DESTROY_IF(subject);
124 }
125 else
126 {
127 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
128 BUILD_BLOB_ASN1_DER, chunk_create(buf, len),
129 BUILD_END);
130 }
131 if (cert)
132 {
133 if (*format & COMMAND_FORMAT_PEM)
134 {
135 print_pem(cert);
136 }
137 else
138 {
139 cert_printer->print_caption(cert_printer, type, flag);
140 cert_printer->print(cert_printer, cert, has_privkey);
141 }
142 cert->destroy(cert);
143 }
144 else
145 {
146 fprintf(stderr, "parsing certificate failed\n");
147 }
148 }
149
150 static int list_certs(vici_conn_t *conn)
151 {
152 vici_req_t *req;
153 vici_res_t *res;
154 command_format_options_t format = COMMAND_FORMAT_NONE;
155 char *arg, *subject = NULL, *type = NULL, *flag = NULL;
156 bool detailed = TRUE, utc = FALSE;
157 int ret;
158
159 while (TRUE)
160 {
161 switch (command_getopt(&arg))
162 {
163 case 'h':
164 return command_usage(NULL);
165 case 's':
166 subject = arg;
167 continue;
168 case 't':
169 type = arg;
170 continue;
171 case 'f':
172 flag = arg;
173 continue;
174 case 'p':
175 format |= COMMAND_FORMAT_PEM;
176 continue;
177 case 'P':
178 format |= COMMAND_FORMAT_PRETTY;
179 /* fall through to raw */
180 case 'r':
181 format |= COMMAND_FORMAT_RAW;
182 continue;
183 case 'S':
184 detailed = FALSE;
185 continue;
186 case 'U':
187 utc = TRUE;
188 continue;
189 case EOF:
190 break;
191 default:
192 return command_usage("invalid --list-certs option");
193 }
194 break;
195 }
196 if (vici_register(conn, "list-cert", list_cb, &format) != 0)
197 {
198 ret = errno;
199 fprintf(stderr, "registering for certificates failed: %s\n",
200 strerror(errno));
201 return ret;
202 }
203 req = vici_begin("list-certs");
204
205 if (type)
206 {
207 vici_add_key_valuef(req, "type", "%s", type);
208 }
209 if (flag)
210 {
211 vici_add_key_valuef(req, "flag", "%s", flag);
212 }
213 if (subject)
214 {
215 vici_add_key_valuef(req, "subject", "%s", subject);
216 }
217 cert_printer = certificate_printer_create(stdout, detailed, utc);
218
219 res = vici_submit(req, conn);
220 if (!res)
221 {
222 ret = errno;
223 fprintf(stderr, "list-certs request failed: %s\n", strerror(errno));
224 cert_printer->destroy(cert_printer);
225 cert_printer = NULL;
226 return ret;
227 }
228 if (format & COMMAND_FORMAT_RAW)
229 {
230 vici_dump(res, "list-certs reply", format & COMMAND_FORMAT_PRETTY,
231 stdout);
232 }
233 vici_free_res(res);
234
235 cert_printer->destroy(cert_printer);
236 cert_printer = NULL;
237 return 0;
238 }
239
240 /**
241 * Register the command.
242 */
243 static void __attribute__ ((constructor))reg()
244 {
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]"},
250 {
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"},
260 }
261 });
262 }