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