parser.y revision 302408
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: stable/11/usr.sbin/bluetooth/hcsecd/parser.y 281210 2015-04-07 16:48:23Z takawata $ 31 */ 32 33#include <sys/fcntl.h> 34#include <sys/queue.h> 35#define L2CAP_SOCKET_CHECKED 36#include <bluetooth.h> 37#include <errno.h> 38#include <limits.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <stdarg.h> 42#include <string.h> 43#include <syslog.h> 44#include <unistd.h> 45#include "hcsecd.h" 46 47 int yyparse (void); 48 int yylex (void); 49 50static void free_key (link_key_p key); 51static int hexa2int4(char *a); 52static int hexa2int8(char *a); 53 54extern int yylineno; 55static LIST_HEAD(, link_key) link_keys; 56 char *config_file = "/etc/bluetooth/hcsecd.conf"; 57 58static link_key_p key = NULL; 59%} 60 61%union { 62 char *string; 63} 64 65%token <string> T_BDADDRSTRING T_HEXSTRING T_STRING 66%token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY T_NOPIN T_JUNK 67 68%% 69 70config: line 71 | config line 72 ; 73 74line: T_DEVICE 75 { 76 key = (link_key_p) malloc(sizeof(*key)); 77 if (key == NULL) { 78 syslog(LOG_ERR, "Could not allocate new " \ 79 "config entry"); 80 exit(1); 81 } 82 83 memset(key, 0, sizeof(*key)); 84 } 85 '{' options '}' 86 { 87 if (get_key(&key->bdaddr, 1) != NULL) { 88 syslog(LOG_ERR, "Ignoring duplicated entry " \ 89 "for bdaddr %s", 90 bt_ntoa(&key->bdaddr, NULL)); 91 free_key(key); 92 } else 93 LIST_INSERT_HEAD(&link_keys, key, next); 94 95 key = NULL; 96 } 97 ; 98 99options: option ';' 100 | options option ';' 101 ; 102 103option: bdaddr 104 | name 105 | key 106 | pin 107 ; 108 109bdaddr: T_BDADDR T_BDADDRSTRING 110 { 111 if (!bt_aton($2, &key->bdaddr)) { 112 syslog(LOG_ERR, "Cound not parse BD_ADDR " \ 113 "'%s'", $2); 114 exit(1); 115 } 116 } 117 ; 118 119name: T_NAME T_STRING 120 { 121 if (key->name != NULL) 122 free(key->name); 123 124 key->name = strdup($2); 125 if (key->name == NULL) { 126 syslog(LOG_ERR, "Could not allocate new " \ 127 "device name"); 128 exit(1); 129 } 130 } 131 ; 132 133key: T_KEY T_HEXSTRING 134 { 135 int i, len; 136 137 if (key->key != NULL) 138 free(key->key); 139 140 key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE); 141 if (key->key == NULL) { 142 syslog(LOG_ERR, "Could not allocate new " \ 143 "link key"); 144 exit(1); 145 } 146 147 memset(key->key, 0, NG_HCI_KEY_SIZE); 148 149 len = strlen($2) / 2; 150 if (len > NG_HCI_KEY_SIZE) 151 len = NG_HCI_KEY_SIZE; 152 153 for (i = 0; i < len; i ++) 154 key->key[i] = hexa2int8((char *)($2) + 2*i); 155 } 156 | T_KEY T_NOKEY 157 { 158 if (key->key != NULL) 159 free(key->key); 160 161 key->key = NULL; 162 } 163 ; 164 165pin: T_PIN T_STRING 166 { 167 if (key->pin != NULL) 168 free(key->pin); 169 170 key->pin = strdup($2); 171 if (key->pin == NULL) { 172 syslog(LOG_ERR, "Could not allocate new " \ 173 "PIN code"); 174 exit(1); 175 } 176 } 177 | T_PIN T_NOPIN 178 { 179 if (key->pin != NULL) 180 free(key->pin); 181 182 key->pin = NULL; 183 } 184 ; 185 186%% 187 188/* Display parser error message */ 189void 190yyerror(char const *message) 191{ 192 syslog(LOG_ERR, "%s in line %d", message, yylineno); 193} 194 195/* Re-read config file */ 196void 197read_config_file(void) 198{ 199 extern FILE *yyin; 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 */ 227void 228clean_config(void) 229{ 230 link_key_p key = NULL; 231 232 while ((key = LIST_FIRST(&link_keys)) != NULL) { 233 LIST_REMOVE(key, next); 234 free_key(key); 235 } 236} 237 238/* Find link key entry in the list. Return exact or default match */ 239link_key_p 240get_key(bdaddr_p bdaddr, int exact_match) 241{ 242 link_key_p key = NULL, defkey = NULL; 243 244 LIST_FOREACH(key, &link_keys, next) { 245 if (memcmp(bdaddr, &key->bdaddr, sizeof(key->bdaddr)) == 0) 246 break; 247 248 if (!exact_match) 249 if (memcmp(NG_HCI_BDADDR_ANY, &key->bdaddr, 250 sizeof(key->bdaddr)) == 0) 251 defkey = key; 252 } 253 254 return ((key != NULL)? key : defkey); 255} 256 257#if __config_debug__ 258/* Dump config */ 259void 260dump_config(void) 261{ 262 link_key_p key = NULL; 263 char buffer[64]; 264 265 LIST_FOREACH(key, &link_keys, next) { 266 if (key->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 key->key[0], key->key[1], key->key[2], 270 key->key[3], key->key[4], key->key[5], 271 key->key[6], key->key[7], key->key[8], 272 key->key[9], key->key[10], key->key[11], 273 key->key[12], key->key[13], key->key[14], 274 key->key[15]); 275 276 syslog(LOG_DEBUG, 277"device %s " \ 278"bdaddr %s " \ 279"pin %s " \ 280"key %s", 281 (key->name != NULL)? key->name : "noname", 282 bt_ntoa(&key->bdaddr, NULL), 283 (key->pin != NULL)? key->pin : "nopin", 284 (key->key != NULL)? buffer : "nokey"); 285 } 286} 287#endif 288 289/* Read keys file */ 290int 291read_keys_file(void) 292{ 293 FILE *f = NULL; 294 link_key_t *key = NULL; 295 char buf[HCSECD_BUFFER_SIZE], *p = NULL, *cp = NULL; 296 bdaddr_t bdaddr; 297 int i, len; 298 299 if ((f = fopen(HCSECD_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 HCSECD_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 ((key = get_key(&bdaddr, 1)) == NULL) 321 continue; 322 323 if (key->key == NULL) { 324 key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE); 325 if (key->key == NULL) { 326 syslog(LOG_ERR, "Could not allocate link key"); 327 exit(1); 328 } 329 } 330 331 memset(key->key, 0, NG_HCI_KEY_SIZE); 332 333 len = strlen(cp) / 2; 334 if (len > NG_HCI_KEY_SIZE) 335 len = NG_HCI_KEY_SIZE; 336 337 for (i = 0; i < len; i ++) 338 key->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(&key->bdaddr, NULL), 343 (key->name != NULL)? key->name : "No name"); 344 } 345 346 fclose(f); 347 348 return (0); 349} 350 351/* Dump keys file */ 352int 353dump_keys_file(void) 354{ 355 link_key_p key = NULL; 356 char tmp[PATH_MAX], buf[HCSECD_BUFFER_SIZE]; 357 int f; 358 359 snprintf(tmp, sizeof(tmp), "%s.tmp", HCSECD_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(key, &link_keys, next) { 367 if (key->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(&key->bdaddr, NULL), 373 key->key[0], key->key[1], key->key[2], key->key[3], 374 key->key[4], key->key[5], key->key[6], key->key[7], 375 key->key[8], key->key[9], key->key[10], key->key[11], 376 key->key[12], key->key[13], key->key[14], key->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, HCSECD_KEYSFILE) < 0) { 388 syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n", 389 tmp, HCSECD_KEYSFILE, strerror(errno), errno); 390 unlink(tmp); 391 return (-1); 392 } 393 394 return (0); 395} 396 397/* Free key entry */ 398static void 399free_key(link_key_p key) 400{ 401 if (key->name != NULL) 402 free(key->name); 403 if (key->key != NULL) 404 free(key->key); 405 if (key->pin != NULL) 406 free(key->pin); 407 408 memset(key, 0, sizeof(*key)); 409 free(key); 410} 411 412/* Convert hex ASCII to int4 */ 413static int 414hexa2int4(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 */ 430static int 431hexa2int8(char *a) 432{ 433 return ((hexa2int4(a) << 4) | hexa2int4(a + 1)); 434} 435 436