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