Home | History | Annotate | Line # | Download | only in btkey
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