xref: /freebsd/contrib/libfido2/tools/config.c (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1 /*
2  * Copyright (c) 2020 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 <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <fido.h>
12 #include <fido/config.h>
13 
14 #include "../openbsd-compat/openbsd-compat.h"
15 #include "extern.h"
16 
17 int
18 config_entattest(char *path)
19 {
20 	fido_dev_t *dev;
21 	char *pin = NULL;
22 	int r, ok = 1;
23 
24 	dev = open_dev(path);
25 	if ((r = fido_dev_enable_entattest(dev, NULL)) != FIDO_OK &&
26 	    should_retry_with_pin(dev, r)) {
27 		if ((pin = get_pin(path)) == NULL)
28 			goto out;
29 		r = fido_dev_enable_entattest(dev, pin);
30 		freezero(pin, PINBUF_LEN);
31 		pin = NULL;
32 	}
33 	if (r != FIDO_OK) {
34 		warnx("fido_dev_enable_entattest: %s (0x%x)",
35 		    fido_strerr(r), r);
36 		goto out;
37 	}
38 
39 	ok = 0;
40 out:
41 	fido_dev_close(dev);
42 	fido_dev_free(&dev);
43 
44 	exit(ok);
45 }
46 
47 int
48 config_always_uv(char *path, int toggle)
49 {
50 	fido_dev_t *dev;
51 	char *pin = NULL;
52 	int v, r, ok = 1;
53 
54 	dev = open_dev(path);
55 	if (get_devopt(dev, "alwaysUv", &v) < 0) {
56 		warnx("%s: getdevopt", __func__);
57 		goto out;
58 	}
59 	if (v == -1) {
60 		warnx("%s: option not found", __func__);
61 		goto out;
62 	}
63 	if (v == toggle) {
64 		ok = 0;
65 		goto out;
66 	}
67 	if ((r = fido_dev_toggle_always_uv(dev, NULL)) != FIDO_OK &&
68 	    should_retry_with_pin(dev, r)) {
69 		if ((pin = get_pin(path)) == NULL)
70 			goto out;
71 		r = fido_dev_toggle_always_uv(dev, pin);
72 		freezero(pin, PINBUF_LEN);
73 		pin = NULL;
74 	}
75 	if (r != FIDO_OK) {
76 		warnx("fido_dev_toggle_always_uv: %s (0x%x)",
77 		    fido_strerr(r), r);
78 		goto out;
79 	}
80 
81 	ok = 0;
82 out:
83 	fido_dev_close(dev);
84 	fido_dev_free(&dev);
85 
86 	exit(ok);
87 }
88 
89 int
90 config_pin_minlen(char *path, const char *pinlen)
91 {
92 	fido_dev_t *dev;
93 	char *pin = NULL;
94 	int len, r, ok = 1;
95 
96 	dev = open_dev(path);
97 	if ((len = base10(pinlen)) < 0 || len > 63) {
98 		warnx("%s: len > 63", __func__);
99 		goto out;
100 	}
101 	if ((r = fido_dev_set_pin_minlen(dev, (size_t)len, NULL)) != FIDO_OK &&
102 	    should_retry_with_pin(dev, r)) {
103 		if ((pin = get_pin(path)) == NULL)
104 			goto out;
105 		r = fido_dev_set_pin_minlen(dev, (size_t)len, pin);
106 		freezero(pin, PINBUF_LEN);
107 		pin = NULL;
108 	}
109 	if (r != FIDO_OK) {
110 		warnx("fido_dev_set_pin_minlen: %s (0x%x)", fido_strerr(r), r);
111 		goto out;
112 	}
113 
114 	ok = 0;
115 out:
116 	fido_dev_close(dev);
117 	fido_dev_free(&dev);
118 
119 	exit(ok);
120 }
121 
122 int
123 config_force_pin_change(char *path)
124 {
125 	fido_dev_t *dev;
126 	char *pin = NULL;
127 	int r, ok = 1;
128 
129 	dev = open_dev(path);
130 	if ((r = fido_dev_force_pin_change(dev, NULL)) != FIDO_OK &&
131 	    should_retry_with_pin(dev, r)) {
132 		if ((pin = get_pin(path)) == NULL)
133 			goto out;
134 		r = fido_dev_force_pin_change(dev, pin);
135 		freezero(pin, PINBUF_LEN);
136 		pin = NULL;
137 	}
138 	if (r != FIDO_OK) {
139 		warnx("fido_dev_force_pin_change: %s (0x%x)", fido_strerr(r), r);
140 		goto out;
141 	}
142 
143 	ok = 0;
144 out:
145 	fido_dev_close(dev);
146 	fido_dev_free(&dev);
147 
148 	exit(ok);
149 }
150 
151 int
152 config_pin_minlen_rpid(char *path, const char *rpids)
153 {
154 	fido_dev_t *dev;
155 	char *otmp, *tmp, *cp;
156 	char *pin = NULL, **rpid = NULL;
157 	int r, ok = 1;
158 	size_t n;
159 
160 	if ((tmp = strdup(rpids)) == NULL)
161 		err(1, "strdup");
162 	otmp = tmp;
163 	for (n = 0; (cp = strsep(&tmp, ",")) != NULL; n++) {
164 		if (n == SIZE_MAX || (rpid = recallocarray(rpid, n, n + 1,
165 		    sizeof(*rpid))) == NULL)
166 			err(1, "recallocarray");
167 		if ((rpid[n] = strdup(cp)) == NULL)
168 			err(1, "strdup");
169 		if (*rpid[n] == '\0')
170 			errx(1, "empty rpid");
171 	}
172 	free(otmp);
173 	if (rpid == NULL || n == 0)
174 		errx(1, "could not parse rp_id");
175 	dev = open_dev(path);
176 	if ((r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
177 	    n, NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
178 		if ((pin = get_pin(path)) == NULL)
179 			goto out;
180 		r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
181 		    n, pin);
182 		freezero(pin, PINBUF_LEN);
183 		pin = NULL;
184 	}
185 	if (r != FIDO_OK) {
186 		warnx("fido_dev_set_pin_minlen_rpid: %s (0x%x)",
187 		    fido_strerr(r), r);
188 		goto out;
189 	}
190 
191 	ok = 0;
192 out:
193 	fido_dev_close(dev);
194 	fido_dev_free(&dev);
195 
196 	exit(ok);
197 }
198