summaryrefslogtreecommitdiff
path: root/tools/token.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/token.c')
-rw-r--r--tools/token.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/tools/token.c b/tools/token.c
new file mode 100644
index 0000000..b149208
--- /dev/null
+++ b/tools/token.c
@@ -0,0 +1,364 @@
1/*
2 * Copyright (c) 2018 Yubico AB. All rights reserved.
3 * Use of this source code is governed by a BSD-style
4 * license that can be found in the LICENSE file.
5 */
6
7#include <fido.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#ifdef HAVE_UNISTD_H
13#include <unistd.h>
14#endif
15
16#include "../openbsd-compat/openbsd-compat.h"
17#include "extern.h"
18
19static void
20format_flags(char *ret, size_t retlen, uint8_t flags)
21{
22 memset(ret, 0, retlen);
23
24 if (flags & FIDO_CAP_WINK) {
25 if (strlcat(ret, "wink,", retlen) >= retlen)
26 goto toolong;
27 } else {
28 if (strlcat(ret, "nowink,", retlen) >= retlen)
29 goto toolong;
30 }
31
32 if (flags & FIDO_CAP_CBOR) {
33 if (strlcat(ret, " cbor,", retlen) >= retlen)
34 goto toolong;
35 } else {
36 if (strlcat(ret, " nocbor,", retlen) >= retlen)
37 goto toolong;
38 }
39
40 if (flags & FIDO_CAP_NMSG) {
41 if (strlcat(ret, " nomsg", retlen) >= retlen)
42 goto toolong;
43 } else {
44 if (strlcat(ret, " msg", retlen) >= retlen)
45 goto toolong;
46 }
47
48 return;
49toolong:
50 strlcpy(ret, "toolong", retlen);
51}
52
53static void
54print_attr(const fido_dev_t *dev)
55{
56 char flags_txt[128];
57
58 printf("proto: 0x%02x\n", fido_dev_protocol(dev));
59 printf("major: 0x%02x\n", fido_dev_major(dev));
60 printf("minor: 0x%02x\n", fido_dev_minor(dev));
61 printf("build: 0x%02x\n", fido_dev_build(dev));
62
63 format_flags(flags_txt, sizeof(flags_txt), fido_dev_flags(dev));
64 printf("caps: 0x%02x (%s)\n", fido_dev_flags(dev), flags_txt);
65}
66
67static void
68print_str_array(const char *label, char * const *sa, size_t len)
69{
70 if (len == 0)
71 return;
72
73 printf("%s strings: ", label);
74
75 for (size_t i = 0; i < len; i++)
76 printf("%s%s", i > 0 ? ", " : "", sa[i]);
77
78 printf("\n");
79}
80
81static void
82print_opt_array(const char *label, char * const *name, const bool *value,
83 size_t len)
84{
85 if (len == 0)
86 return;
87
88 printf("%s: ", label);
89
90 for (size_t i = 0; i < len; i++)
91 printf("%s%s%s", i > 0 ? ", " : "",
92 value[i] ? "" : "no", name[i]);
93
94 printf("\n");
95}
96
97static void
98print_aaguid(const unsigned char *buf, size_t buflen)
99{
100 printf("aaguid: ");
101
102 while (buflen--)
103 printf("%02x", *buf++);
104
105 printf("\n");
106}
107
108static void
109print_maxmsgsiz(uint64_t maxmsgsiz)
110{
111 printf("maxmsgsiz: %d\n", (int)maxmsgsiz);
112}
113
114static void
115print_byte_array(const char *label, const uint8_t *ba, size_t len)
116{
117 if (len == 0)
118 return;
119
120 printf("%s: ", label);
121
122 for (size_t i = 0; i < len; i++)
123 printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]);
124
125 printf("\n");
126}
127
128int
129token_info(int argc, char **argv, char *path)
130{
131 char *cred_id = NULL;
132 char *rp_id = NULL;
133 fido_cbor_info_t *ci = NULL;
134 fido_dev_t *dev = NULL;
135 int ch;
136 int credman = 0;
137 int r;
138 int retrycnt;
139
140 optind = 1;
141
142 while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
143 switch (ch) {
144 case 'c':
145 credman = 1;
146 break;
147 case 'i':
148 cred_id = optarg;
149 break;
150 case 'k':
151 rp_id = optarg;
152 break;
153 default:
154 break; /* ignore */
155 }
156 }
157
158 if (path == NULL || (credman && (cred_id != NULL || rp_id != NULL)))
159 usage();
160
161 dev = open_dev(path);
162
163 if (credman)
164 return (credman_get_metadata(dev, path));
165 if (cred_id && rp_id)
166 return (credman_print_rk(dev, path, rp_id, cred_id));
167 if (cred_id || rp_id)
168 usage();
169
170 print_attr(dev);
171
172 if (fido_dev_is_fido2(dev) == false)
173 goto end;
174 if ((ci = fido_cbor_info_new()) == NULL)
175 errx(1, "fido_cbor_info_new");
176 if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK)
177 errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r);
178
179 /* print supported protocol versions */
180 print_str_array("version", fido_cbor_info_versions_ptr(ci),
181 fido_cbor_info_versions_len(ci));
182
183 /* print supported extensions */
184 print_str_array("extension", fido_cbor_info_extensions_ptr(ci),
185 fido_cbor_info_extensions_len(ci));
186
187 /* print aaguid */
188 print_aaguid(fido_cbor_info_aaguid_ptr(ci),
189 fido_cbor_info_aaguid_len(ci));
190
191 /* print supported options */
192 print_opt_array("options", fido_cbor_info_options_name_ptr(ci),
193 fido_cbor_info_options_value_ptr(ci),
194 fido_cbor_info_options_len(ci));
195
196 /* print maximum message size */
197 print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci));
198
199 /* print supported pin protocols */
200 print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci),
201 fido_cbor_info_protocols_len(ci));
202
203 if ((r = fido_dev_get_retry_count(dev, &retrycnt)) != FIDO_OK)
204 printf("pin retries: undefined\n");
205 else
206 printf("pin retries: %d\n", retrycnt);
207
208 bio_info(dev);
209
210 fido_cbor_info_free(&ci);
211end:
212 fido_dev_close(dev);
213 fido_dev_free(&dev);
214
215 exit(0);
216}
217
218int
219token_reset(char *path)
220{
221 fido_dev_t *dev = NULL;
222 int r;
223
224 if (path == NULL)
225 usage();
226
227 dev = open_dev(path);
228 if ((r = fido_dev_reset(dev)) != FIDO_OK)
229 errx(1, "fido_dev_reset: %s", fido_strerr(r));
230
231 fido_dev_close(dev);
232 fido_dev_free(&dev);
233
234 exit(0);
235}
236
237int
238token_set(int argc, char **argv, char *path)
239{
240 char *id = NULL;
241 char *name = NULL;
242 int ch;
243 int enroll = 0;
244
245 optind = 1;
246
247 while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
248 switch (ch) {
249 case 'e':
250 enroll = 1;
251 break;
252 case 'i':
253 id = optarg;
254 break;
255 case 'n':
256 name = optarg;
257 break;
258 default:
259 break; /* ignore */
260 }
261 }
262
263 if (enroll) {
264 if (id && name)
265 return (bio_set_name(path, id, name));
266 if (!id && !name)
267 return (bio_enroll(path));
268 usage();
269 }
270
271 return (pin_set(path));
272}
273
274int
275token_list(int argc, char **argv, char *path)
276{
277 fido_dev_info_t *devlist;
278 size_t ndevs;
279 const char *rp_id = NULL;
280 int enrolls = 0;
281 int keys = 0;
282 int rplist = 0;
283 int ch;
284 int r;
285
286 optind = 1;
287
288 while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
289 switch (ch) {
290 case 'e':
291 enrolls = 1;
292 break;
293 case 'k':
294 keys = 1;
295 rp_id = optarg;
296 break;
297 case 'r':
298 rplist = 1;
299 break;
300 default:
301 break; /* ignore */
302 }
303 }
304
305 if (enrolls)
306 return (bio_list(path));
307 if (keys)
308 return (credman_list_rk(path, rp_id));
309 if (rplist)
310 return (credman_list_rp(path));
311
312 if ((devlist = fido_dev_info_new(64)) == NULL)
313 errx(1, "fido_dev_info_new");
314 if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK)
315 errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r);
316
317 for (size_t i = 0; i < ndevs; i++) {
318 const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
319 printf("%s: vendor=0x%04x, product=0x%04x (%s %s)\n",
320 fido_dev_info_path(di),
321 (uint16_t)fido_dev_info_vendor(di),
322 (uint16_t)fido_dev_info_product(di),
323 fido_dev_info_manufacturer_string(di),
324 fido_dev_info_product_string(di));
325 }
326
327 fido_dev_info_free(&devlist, ndevs);
328
329 exit(0);
330}
331
332int
333token_delete(int argc, char **argv, char *path)
334{
335 char *id = NULL;
336 fido_dev_t *dev = NULL;
337 int ch;
338 int enroll = 0;
339
340 optind = 1;
341
342 while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
343 switch (ch) {
344 case 'e':
345 enroll = 1;
346 break;
347 case 'i':
348 id = optarg;
349 break;
350 default:
351 break; /* ignore */
352 }
353 }
354
355 if (path == NULL || id == NULL)
356 usage();
357
358 dev = open_dev(path);
359
360 if (id && !enroll)
361 return (credman_delete_rk(dev, path, id));
362
363 return (bio_delete(dev, path, id));
364}