1 %{ 2 /* 3 * parser.y 4 * 5 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Id: parser.y,v 1.5 2003/06/07 21:22:30 max Exp $ 30 * $FreeBSD: src/usr.sbin/bluetooth/hcsecd/parser.y,v 1.4 2004/09/14 20:04:33 emax Exp $ 31 */ 32 33 #include <sys/fcntl.h> 34 #include <sys/queue.h> 35 #include <bluetooth.h> 36 #include <errno.h> 37 #include <limits.h> 38 #include <stdio.h> 39 #include <stdarg.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <syslog.h> 43 #include <unistd.h> 44 #include "bthcid.h" 45 46 #if YYPATCH < 20180510 47 int yylex (void); 48 #endif 49 50 static void free_key (link_key_p key); 51 static int hexa2int4(char *a); 52 static int hexa2int8(char *a); 53 54 extern void yyerror(const char *); 55 extern int yylineno; 56 extern FILE *yyin; 57 58 static LIST_HEAD(, link_key) link_keys; 59 60 const char *config_file = "/etc/bluetooth/bthcid.conf"; 61 static link_key_p key = NULL; 62 %} 63 64 %union { 65 char *string; 66 } 67 68 %token <string> T_BDADDRSTRING T_HEXSTRING T_STRING 69 %token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY T_NOPIN T_JUNK 70 71 %% 72 73 config: line 74 | config line 75 ; 76 77 line: T_DEVICE 78 { 79 key = (link_key_p) malloc(sizeof(*key)); 80 if (key == NULL) { 81 syslog(LOG_ERR, "Could not allocate new " \ 82 "config entry"); 83 exit(1); 84 } 85 86 memset(key, 0, sizeof(*key)); 87 } 88 '{' options '}' 89 { 90 if (get_key(&key->bdaddr, 1) != NULL) { 91 syslog(LOG_ERR, "Ignoring duplicated entry " \ 92 "for bdaddr %s", 93 bt_ntoa(&key->bdaddr, NULL)); 94 free_key(key); 95 } else 96 LIST_INSERT_HEAD(&link_keys, key, next); 97 98 key = NULL; 99 } 100 ; 101 102 options: option ';' 103 | options option ';' 104 ; 105 106 option: bdaddr 107 | name 108 | key 109 | pin 110 ; 111 112 bdaddr: T_BDADDR T_BDADDRSTRING 113 { 114 if (!bt_aton($2, &key->bdaddr)) { 115 syslog(LOG_ERR, "Could not parse BD_ADDR " \ 116 "'%s'", $2); 117 exit(1); 118 } 119 } 120 ; 121 122 name: T_NAME T_STRING 123 { 124 if (key->name != NULL) 125 free(key->name); 126 127 key->name = strdup($2); 128 if (key->name == NULL) { 129 syslog(LOG_ERR, "Could not allocate new " \ 130 "device name"); 131 exit(1); 132 } 133 } 134 ; 135 136 key: T_KEY T_HEXSTRING 137 { 138 int i, len; 139 140 if (key->key != NULL) 141 free(key->key); 142 143 key->key = (uint8_t *) malloc(HCI_KEY_SIZE); 144 if (key->key == NULL) { 145 syslog(LOG_ERR, "Could not allocate new " \ 146 "link key"); 147 exit(1); 148 } 149 150 memset(key->key, 0, HCI_KEY_SIZE); 151 152 len = strlen($2) / 2; 153 if (len > HCI_KEY_SIZE) 154 len = HCI_KEY_SIZE; 155 156 for (i = 0; i < len; i ++) 157 key->key[i] = hexa2int8((char *)($2) + 2*i); 158 } 159 | T_KEY T_NOKEY 160 { 161 if (key->key != NULL) 162 free(key->key); 163 164 key->key = NULL; 165 } 166 ; 167 168 pin: T_PIN T_STRING 169 { 170 if (key->pin != NULL) 171 free(key->pin); 172 173 key->pin = strdup($2); 174 if (key->pin == NULL) { 175 syslog(LOG_ERR, "Could not allocate new " \ 176 "PIN code"); 177 exit(1); 178 } 179 } 180 | T_PIN T_NOPIN 181 { 182 if (key->pin != NULL) 183 free(key->pin); 184 185 key->pin = NULL; 186 } 187 ; 188 189 %% 190 191 /* Display parser error message */ 192 void 193 yyerror(char const *message) 194 { 195 syslog(LOG_ERR, "%s in line %d", message, yylineno); 196 } 197 198 /* Re-read config file */ 199 void 200 read_config_file(void) 201 { 202 if (config_file == NULL) { 203 syslog(LOG_ERR, "Unknown config file name!"); 204 exit(1); 205 } 206 207 if ((yyin = fopen(config_file, "r")) == NULL) { 208 syslog(LOG_ERR, "Could not open config file '%s'. %s (%d)", 209 config_file, strerror(errno), errno); 210 exit(1); 211 } 212 213 clean_config(); 214 if (yyparse() < 0) { 215 syslog(LOG_ERR, "Could not parse config file '%s'",config_file); 216 exit(1); 217 } 218 219 fclose(yyin); 220 yyin = NULL; 221 222 #ifdef __config_debug__ 223 dump_config(); 224 #endif 225 } 226 227 /* Clean config */ 228 void 229 clean_config(void) 230 { 231 link_key_p lkey = NULL; 232 233 while ((lkey = LIST_FIRST(&link_keys)) != NULL) { 234 LIST_REMOVE(lkey, next); 235 free_key(lkey); 236 } 237 } 238 239 /* Find link key entry in the list. Return exact or default match */ 240 link_key_p 241 get_key(bdaddr_p bdaddr, int exact_match) 242 { 243 link_key_p lkey = NULL, defkey = NULL; 244 245 LIST_FOREACH(lkey, &link_keys, next) { 246 if (memcmp(bdaddr, &lkey->bdaddr, sizeof(lkey->bdaddr)) == 0) 247 break; 248 249 if (!exact_match) 250 if (memcmp(BDADDR_ANY, &lkey->bdaddr, 251 sizeof(lkey->bdaddr)) == 0) 252 defkey = lkey; 253 } 254 255 return ((lkey != NULL)? lkey : defkey); 256 } 257 258 #ifdef __config_debug__ 259 /* Dump config */ 260 void 261 dump_config(void) 262 { 263 link_key_p lkey = NULL; 264 char buffer[64]; 265 266 LIST_FOREACH(lkey, &link_keys, next) { 267 if (lkey->key != NULL) 268 snprintf(buffer, sizeof(buffer), 269 "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 270 lkey->key[0], lkey->key[1], lkey->key[2], 271 lkey->key[3], lkey->key[4], lkey->key[5], 272 lkey->key[6], lkey->key[7], lkey->key[8], 273 lkey->key[9], lkey->key[10], lkey->key[11], 274 lkey->key[12], lkey->key[13], lkey->key[14], 275 lkey->key[15]); 276 277 syslog(LOG_DEBUG, 278 "device %s " \ 279 "bdaddr %s " \ 280 "pin %s " \ 281 "key %s", 282 (lkey->name != NULL)? lkey->name : "noname", 283 bt_ntoa(&lkey->bdaddr, NULL), 284 (lkey->pin != NULL)? lkey->pin : "nopin", 285 (lkey->key != NULL)? buffer : "nokey"); 286 } 287 } 288 #endif 289 290 /* Read keys file */ 291 int 292 read_keys_file(void) 293 { 294 FILE *f = NULL; 295 link_key_t *lkey = NULL; 296 char buf[BTHCID_BUFFER_SIZE], *p = NULL, *cp = NULL; 297 bdaddr_t bdaddr; 298 int i, len; 299 300 if ((f = fopen(BTHCID_KEYSFILE, "r")) == NULL) { 301 if (errno == ENOENT) 302 return (0); 303 304 syslog(LOG_ERR, "Could not open keys file %s. %s (%d)\n", 305 BTHCID_KEYSFILE, strerror(errno), errno); 306 307 return (-1); 308 } 309 310 while ((p = fgets(buf, sizeof(buf), f)) != NULL) { 311 if (*p == '#') 312 continue; 313 if ((cp = strpbrk(p, " ")) == NULL) 314 continue; 315 316 *cp++ = '\0'; 317 318 if (!bt_aton(p, &bdaddr)) 319 continue; 320 321 if ((lkey = get_key(&bdaddr, 1)) == NULL) 322 continue; 323 324 if (lkey->key == NULL) { 325 lkey->key = (uint8_t *) malloc(HCI_KEY_SIZE); 326 if (lkey->key == NULL) { 327 syslog(LOG_ERR, "Could not allocate link key"); 328 exit(1); 329 } 330 } 331 332 memset(lkey->key, 0, HCI_KEY_SIZE); 333 334 len = strlen(cp) / 2; 335 if (len > HCI_KEY_SIZE) 336 len = HCI_KEY_SIZE; 337 338 for (i = 0; i < len; i ++) 339 lkey->key[i] = hexa2int8(cp + 2*i); 340 341 syslog(LOG_DEBUG, "Restored link key for the entry, " \ 342 "remote bdaddr %s, name '%s'", 343 bt_ntoa(&lkey->bdaddr, NULL), 344 (lkey->name != NULL)? lkey->name : "No name"); 345 } 346 347 fclose(f); 348 349 return (0); 350 } 351 352 /* Dump keys file */ 353 int 354 dump_keys_file(void) 355 { 356 link_key_p lkey = NULL; 357 char tmp[PATH_MAX], buf[BTHCID_BUFFER_SIZE]; 358 int f; 359 360 snprintf(tmp, sizeof(tmp), "%s.tmp", BTHCID_KEYSFILE); 361 if ((f = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { 362 syslog(LOG_ERR, "Could not create temp keys file %s. %s (%d)\n", 363 tmp, strerror(errno), errno); 364 return (-1); 365 } 366 367 LIST_FOREACH(lkey, &link_keys, next) { 368 if (lkey->key == NULL) 369 continue; 370 371 snprintf(buf, sizeof(buf), 372 "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", 373 bt_ntoa(&lkey->bdaddr, NULL), 374 lkey->key[0], lkey->key[1], lkey->key[2], lkey->key[3], 375 lkey->key[4], lkey->key[5], lkey->key[6], lkey->key[7], 376 lkey->key[8], lkey->key[9], lkey->key[10], lkey->key[11], 377 lkey->key[12], lkey->key[13], lkey->key[14], lkey->key[15]); 378 379 if (write(f, buf, strlen(buf)) < 0) { 380 syslog(LOG_ERR, "Could not write temp keys file. " \ 381 "%s (%d)\n", strerror(errno), errno); 382 break; 383 } 384 } 385 386 close(f); 387 388 if (rename(tmp, BTHCID_KEYSFILE) < 0) { 389 syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n", 390 tmp, BTHCID_KEYSFILE, strerror(errno), errno); 391 unlink(tmp); 392 return (-1); 393 } 394 395 return (0); 396 } 397 398 /* Free key entry */ 399 static void 400 free_key(link_key_p lkey) 401 { 402 if (lkey->name != NULL) 403 free(lkey->name); 404 if (lkey->key != NULL) 405 free(lkey->key); 406 if (lkey->pin != NULL) 407 free(lkey->pin); 408 409 memset(lkey, 0, sizeof(*lkey)); 410 free(lkey); 411 } 412 413 /* Convert hex ASCII to int4 */ 414 static int 415 hexa2int4(char *a) 416 { 417 if ('0' <= *a && *a <= '9') 418 return (*a - '0'); 419 420 if ('A' <= *a && *a <= 'F') 421 return (*a - 'A' + 0xa); 422 423 if ('a' <= *a && *a <= 'f') 424 return (*a - 'a' + 0xa); 425 426 syslog(LOG_ERR, "Invalid hex character: '%c' (%#x)", *a, *a); 427 exit(1); 428 } 429 430 /* Convert hex ASCII to int8 */ 431 static int 432 hexa2int8(char *a) 433 { 434 return ((hexa2int4(a) << 4) | hexa2int4(a + 1)); 435 } 436 437