btkey.c revision 1.2 1 /* $NetBSD: btkey.c,v 1.2 2008/07/21 14:19:21 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 2007 Iain Hibbert
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __COPYRIGHT("@(#) Copyright (c) 2007 Iain Hibbert. All rights reserved.");
32 __RCSID("$NetBSD: btkey.c,v 1.2 2008/07/21 14:19:21 lukem Exp $");
33
34 #include <bluetooth.h>
35 #include <err.h>
36 #include <errno.h>
37 #include <stdbool.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 #include "btkey.h"
43
44 static void usage(void);
45 static bool scan_key(const char *);
46
47 bdaddr_t laddr;
48 bdaddr_t raddr;
49 uint8_t key[HCI_KEY_SIZE];
50
51 int
52 main(int ac, char *av[])
53 {
54 struct hostent *he;
55 int ch;
56 bool cf, cd, lf, ld, rf, rd, wf, wd, nk;
57
58 memset(&laddr, 0, sizeof(laddr));
59 memset(&raddr, 0, sizeof(raddr));
60 memset(key, 0, sizeof(key));
61 cf = cd = lf = ld = rf = rd = wf = wd = nk = false;
62
63 while ((ch = getopt(ac, av, "a:cCd:k:lLrRwW")) != EOF) {
64 switch (ch) {
65 case 'a': /* remote device address */
66 if (!bt_aton(optarg, &raddr)) {
67 he = bt_gethostbyname(optarg);
68 if (he == NULL)
69 errx(EXIT_FAILURE, "%s: %s",
70 optarg, hstrerror(h_errno));
71
72 bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
73 }
74 break;
75
76 case 'c': /* clear from file */
77 cf = true;
78 break;
79
80 case 'C': /* clear from device */
81 cd = true;
82 break;
83
84 case 'd': /* local device address */
85 if (!bt_devaddr(optarg, &laddr)
86 && !bt_aton(optarg, &laddr)) {
87 he = bt_gethostbyname(optarg);
88 if (he == NULL)
89 errx(EXIT_FAILURE, "%s: %s",
90 optarg, hstrerror(h_errno));
91
92 bdaddr_copy(&laddr, (bdaddr_t *)he->h_addr);
93 }
94 break;
95
96 case 'k': /* new link key */
97 if (!scan_key(optarg))
98 errx(EXIT_FAILURE, "invalid key '%s'", optarg);
99
100 nk = true;
101 break;
102
103 case 'l': /* list from file */
104 lf = true;
105 break;
106
107 case 'L': /* list from device */
108 ld = true;
109 break;
110
111 case 'r': /* read from file */
112 rf = true;
113 break;
114
115 case 'R': /* read from device */
116 rd = true;
117 break;
118
119 case 'w': /* write to file */
120 wf = true;
121 break;
122
123 case 'W': /* write to device */
124 wd = true;
125 break;
126
127 default:
128 usage();
129 }
130 }
131
132 ac -= optind;
133 av += optind;
134
135 /*
136 * validate options
137 */
138 if ((lf || ld) && (rf || rd || wf || wd || cf || cd || nk))
139 errx(EXIT_FAILURE, "list is exclusive of other options");
140
141 if (((rf && rd) || (rf && nk) || (rd && nk)) && (wf || wd))
142 errx(EXIT_FAILURE, "too many key sources");
143
144 if (((bdaddr_any(&laddr) || bdaddr_any(&raddr)) && !(lf || ld))
145 || ((lf || ld) && (bdaddr_any(&laddr) || !bdaddr_any(&raddr)))
146 || ac > 0)
147 usage();
148
149 /*
150 * do what we gotta do and be done
151 */
152 if (!bdaddr_any(&laddr))
153 print_addr("device", &laddr);
154
155 if (!bdaddr_any(&raddr))
156 print_addr("bdaddr", &raddr);
157
158 if (lf && !list_file())
159 err(EXIT_FAILURE, "list file");
160
161 if (ld && !list_device())
162 err(EXIT_FAILURE, "list device");
163
164 if (nk)
165 print_key("new key", key);
166
167 if (rf) {
168 if (!read_file())
169 err(EXIT_FAILURE, "file key");
170
171 print_key("file key", key);
172 }
173
174 if (rd) {
175 if (!read_device())
176 err(EXIT_FAILURE, "device key");
177
178 print_key("device key", key);
179 }
180
181 if (wf || wd || cf || cd)
182 printf("\n");
183
184 if (wf) {
185 if (!write_file())
186 err(EXIT_FAILURE, "write to file");
187
188 printf("written to file\n");
189 }
190
191 if (wd) {
192 if (!write_device())
193 err(EXIT_FAILURE, "write to device");
194
195 printf("written to device\n");
196 }
197
198 if (cf) {
199 if (!clear_file())
200 err(EXIT_FAILURE, "clear from file");
201
202 printf("cleared from file\n");
203 }
204
205 if (cd) {
206 if (!clear_device())
207 err(EXIT_FAILURE, "clear from device");
208
209 printf("cleared from device\n");
210 }
211
212 exit(EXIT_SUCCESS);
213 }
214
215 static void
216 usage(void)
217 {
218
219 fprintf(stderr,
220 "Usage: %s [-cCrRwW] [-k key] -a address -d device\n"
221 " %s -lL -d device\n"
222 "\n", getprogname(), getprogname());
223
224 fprintf(stderr,
225 "Where:\n"
226 "\t-a address remote device address\n"
227 "\t-c clear from file\n"
228 "\t-C clear from device\n"
229 "\t-d device local device address\n"
230 "\t-k key user specified link_key\n"
231 "\t-l list file keys\n"
232 "\t-L list device keys\n"
233 "\t-r read from file\n"
234 "\t-R read from device\n"
235 "\t-w write to file\n"
236 "\t-W write to device\n"
237 "\n");
238
239 exit(EXIT_FAILURE);
240 }
241
242 static bool
243 scan_key(const char *arg)
244 {
245 static const char digits[] = "0123456789abcdef";
246 const char *p;
247 int i, j;
248
249 memset(key, 0, sizeof(key));
250
251 for (i = 0 ; i < HCI_KEY_SIZE ; i++) {
252 for (j = 0 ; j < 2 ; j++) {
253 if (*arg == '\0')
254 return true;
255
256 for (p = digits ; *p != *arg ; p++)
257 if (*p == '\0')
258 return false;
259
260 arg++;
261 key[i] = (key[i] << 4) + (p - digits);
262 }
263 }
264
265 if (*arg != '\0')
266 return false;
267
268 return true;
269 }
270
271 void
272 print_key(const char *type, const uint8_t *src)
273 {
274 int i;
275
276 printf("%10s: ", type);
277 for (i = 0 ; i < HCI_KEY_SIZE ; i++)
278 printf("%2.2x", src[i]);
279
280 printf("\n");
281 }
282
283
284 void
285 print_addr(const char *type, const bdaddr_t *addr)
286 {
287 char name[HCI_DEVNAME_SIZE];
288 struct hostent *he;
289
290 printf("%10s: %s", type, bt_ntoa(addr, NULL));
291
292 if (bt_devname(name, addr))
293 printf(" (%s)", name);
294 else if ((he = bt_gethostbyaddr((const char *)addr,
295 sizeof(bdaddr_t), AF_BLUETOOTH)) != NULL)
296 printf(" (%s)", he->h_name);
297
298 printf("\n");
299 }
300