Index: hcsecd.8 =================================================================== RCS file: /usr/local/cvs/usr.sbin/bluetooth/hcsecd/hcsecd.8,v retrieving revision 1.5 diff -u -r1.5 hcsecd.8 --- hcsecd.8 26 May 2003 22:49:22 -0000 1.5 +++ hcsecd.8 6 Jun 2003 00:37:10 -0000 @@ -38,22 +38,28 @@ .Sh DESCRIPTION The .Nm -daemon controls link keys and PIN code for Bluetooth devices. +daemon controls link keys and PIN codes for Bluetooth devices. It opens raw HCI socket and listens for the -.Dv Link_Key_Request -and +.Dv Link_Key_Request , .Dv PIN_Code_Request +and +.Dv Link_Key_Notification HCI events. -Once appropriate HCI event has been received, the daemon will +.Pp +Once +.Dv Link_Key_Request +or +.Dv PIN_Code_Request +HCI event is received, the daemon will scan configuration file for matching entry. -The remove device BD_ADDR is used as a key. +The remote device BD_ADDR is used as a key. If no matching entry was found, the default entry will be used. -If no default entry was found then it is assumed that no link key and no PIN code -exist. +If no default entry was found then it is assumed that no link key and no +PIN code exists. For any given entry, link key takes precedence over PIN code. If link key was not specified, it means device must generate link key from PIN code. -If entry was found and has the link key (or PIN code) then the +If entry was found and the link key (or PIN code) exists then the .Dv Link_Key_Request_Reply (or .Dv PIN_Code_Request_Reply ) @@ -66,12 +72,28 @@ .Pp The .Nm -daemon currently does not handle HCI +daemon also handles HCI .Dv Link_Key_Notification -event and does not cache link keys created from the PIN codes. -It means that the link key only exists while connection is opened. -After the connection has been terminated, the user will have to enter PIN code -again. +event and caches link keys created from the PIN codes in the memory. +To preserve link keys between restarts the +.Nm +daemon dumps link keys for all entries in the +.Pa /var/run/hcsecd.keys +link keys file. +If exists, the link keys file gets processed by +.Nm +daemon after it processes its main configuration file. +The link keys file gets written every time +.Nm +daemon is gracefully shutdown. +It is possible to force +.Nm +daemon to re-read its main configuration file and dump link keys file by sending +.Dv HUP +signal to the +.Nm +process. +User is not expected to modify link keys file by hand. .Pp The command line options are as follows: .Bl -tag -width indent @@ -94,12 +116,12 @@ .Bl -tag -width ".Pa /etc/bluetooth/hcsecd.conf" -compact .It Pa /etc/bluetooth/hcsecd.conf .It Pa /var/run/hcsecd.pid +.It Pa /var/run/hcsecd.keys .El .Sh SEE ALSO -.Xr netgraph 3 , -.Xr netgraph 4 , .Xr ng_btsocket 4 , .Xr ng_hci 4 , +.Xr hcsecd.conf 5 , .Xr hccontrol 8 , .Xr hcseriald 8 .Sh AUTHORS Index: hcsecd.c =================================================================== RCS file: /usr/local/cvs/usr.sbin/bluetooth/hcsecd/hcsecd.c,v retrieving revision 1.4 diff -u -r1.4 hcsecd.c --- hcsecd.c 21 May 2003 22:40:31 -0000 1.4 +++ hcsecd.c 5 Jun 2003 20:56:47 -0000 @@ -43,10 +43,6 @@ #include #include "hcsecd.h" -#define HCSECD_BUFFER_SIZE 512 -#define HCSECD_IDENT "hcsecd" -#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid" - static int done = 0; static int process_pin_code_request_event @@ -57,6 +53,10 @@ (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin); static int send_link_key_reply (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, u_int8_t *key); +static int process_link_key_notification_event + (int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep); +static void sighup + (int s); static void sigint (int s); static void usage @@ -110,7 +110,7 @@ err(1, "Could not sigaction(SIGINT)"); memset(&sa, 0, sizeof(sa)); - sa.sa_handler = read_config_file; + sa.sa_handler = sighup; if (sigaction(SIGHUP, &sa, NULL) < 0) err(1, "Could not sigaction(SIGHUP)"); @@ -122,6 +122,7 @@ memset(&filter, 0, sizeof(filter)); bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1); bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1); + bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1); if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER, (void * const) &filter, sizeof(filter)) < 0) @@ -133,7 +134,8 @@ openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON); - read_config_file(0); + read_config_file(); + read_keys_file(); if (detach) { FILE *pid = NULL; @@ -179,6 +181,11 @@ (bdaddr_p)(event + 1)); break; + case NG_HCI_EVENT_LINK_KEY_NOTIFICATION: + process_link_key_notification_event(sock, &addr, + (ng_hci_link_key_notification_ep *)(event + 1)); + break; + default: syslog(LOG_ERR, "Received unexpected HCI event, " \ "event=%#x", event->event); @@ -191,6 +198,7 @@ syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)", HCSECD_PIDFILE, strerror(errno), errno); + dump_keys_file(); clean_config(); closelog(); close(sock); @@ -206,27 +214,21 @@ link_key_p key = NULL; syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \ - "remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "remote bdaddr %s", addr->hci_node, + bt_ntoa(bdaddr, NULL)); if ((key = get_key(bdaddr, 0)) != NULL) { syslog(LOG_DEBUG, "Found matching entry, " \ - "remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \ - "PIN code %s", - key->bdaddr.b[5], key->bdaddr.b[4], - key->bdaddr.b[3], key->bdaddr.b[2], - key->bdaddr.b[1], key->bdaddr.b[0], + "remote bdaddr %s, name '%s', PIN code %s", + bt_ntoa(&key->bdaddr, NULL), (key->name != NULL)? key->name : "No name", (key->pin != NULL)? "exists" : "doesn't exist"); return (send_pin_code_reply(sock, addr, bdaddr, key->pin)); } - syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr " \ - "%x:%x:%x:%x:%x:%x", - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s", + bt_ntoa(bdaddr, NULL)); return (send_pin_code_reply(sock, addr, bdaddr, NULL)); } @@ -239,27 +241,21 @@ link_key_p key = NULL; syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \ - "remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "remote bdaddr %s", addr->hci_node, + bt_ntoa(bdaddr, NULL)); if ((key = get_key(bdaddr, 0)) != NULL) { syslog(LOG_DEBUG, "Found matching entry, " \ - "remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \ - "link key %s", - key->bdaddr.b[5], key->bdaddr.b[4], - key->bdaddr.b[3], key->bdaddr.b[2], - key->bdaddr.b[1], key->bdaddr.b[0], + "remote bdaddr %s, name '%s', link key %s", + bt_ntoa(&key->bdaddr, NULL), (key->name != NULL)? key->name : "No name", (key->key != NULL)? "exists" : "doesn't exist"); return (send_link_key_reply(sock, addr, bdaddr, key->key)); } - syslog(LOG_DEBUG, "Could not find link key for remote bdaddr " \ - "%x:%x:%x:%x:%x:%x", - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s", + bt_ntoa(bdaddr, NULL)); return (send_link_key_reply(sock, addr, bdaddr, NULL)); } @@ -290,10 +286,8 @@ cp->pin_size = strlen(cp->pin); syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } else { ng_hci_pin_code_neg_rep_cp *cp = NULL; @@ -305,10 +299,8 @@ memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr)); syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } again: @@ -318,10 +310,8 @@ goto again; syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0], + "for remote bdaddr %s. %s (%d)", + addr->hci_node, bt_ntoa(bdaddr, NULL), strerror(errno), errno); return (-1); } @@ -354,10 +344,8 @@ memcpy(&cp->key, key, sizeof(cp->key)); syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } else { ng_hci_link_key_neg_rep_cp *cp = NULL; @@ -369,10 +357,8 @@ memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr)); syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } again: @@ -382,10 +368,8 @@ goto again; syslog(LOG_ERR, "Could not send link key reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0], + "for remote bdaddr %s. %s (%d)", + addr->hci_node, bt_ntoa(bdaddr, NULL), strerror(errno), errno); return (-1); } @@ -393,7 +377,53 @@ return (0); } -/* Signal handler */ +/* Process Link_Key_Notification event */ +static int +process_link_key_notification_event(int sock, struct sockaddr_hci *addr, + ng_hci_link_key_notification_ep *ep) +{ + link_key_p key = NULL; + + syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \ + "remote bdaddr %s", addr->hci_node, + bt_ntoa(&ep->bdaddr, NULL)); + + if ((key = get_key(&ep->bdaddr, 1)) == NULL) { + syslog(LOG_ERR, "Could not find entry for remote bdaddr %s", + bt_ntoa(&ep->bdaddr, NULL)); + return (-1); + } + + syslog(LOG_DEBUG, "Updating link key for the entry, " \ + "remote bdaddr %s, name '%s', link key %s", + bt_ntoa(&key->bdaddr, NULL), + (key->name != NULL)? key->name : "No name", + (key->key != NULL)? "exists" : "doesn't exist"); + + if (key->key == NULL) { + key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); + if (key->key == NULL) { + syslog(LOG_ERR, "Could not allocate link key"); + exit(1); + } + } + + memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE); + + return (0); +} + +/* Signal handlers */ +static void +sighup(int s) +{ + syslog(LOG_DEBUG, "Got SIGHUP (%d)", s); + + dump_keys_file(); + read_config_file(); + read_keys_file(); +} + static void sigint(int s) { Index: hcsecd.h =================================================================== RCS file: /usr/local/cvs/usr.sbin/bluetooth/hcsecd/hcsecd.h,v retrieving revision 1.1 diff -u -r1.1 hcsecd.h --- hcsecd.h 24 Nov 2002 20:22:39 -0000 1.1 +++ hcsecd.h 5 Jun 2003 20:52:50 -0000 @@ -32,6 +32,11 @@ #ifndef _HCSECD_H_ #define _HCSECD_H_ 1 +#define HCSECD_BUFFER_SIZE 512 +#define HCSECD_IDENT "hcsecd" +#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid" +#define HCSECD_KEYSFILE "/var/run/" HCSECD_IDENT ".keys" + struct link_key { bdaddr_t bdaddr; /* remote device BDADDR */ @@ -49,9 +54,12 @@ void dump_config (void); #endif -void read_config_file(int s); +void read_config_file(void); void clean_config (void); link_key_p get_key (bdaddr_p bdaddr, int exact_match); + +int read_keys_file (void); +int dump_keys_file (void); #endif /* ndef _HCSECD_H_ */ Index: parser.y =================================================================== RCS file: /usr/local/cvs/usr.sbin/bluetooth/hcsecd/parser.y,v retrieving revision 1.4 diff -u -r1.4 parser.y --- parser.y 26 May 2003 23:03:39 -0000 1.4 +++ parser.y 6 Jun 2003 00:28:16 -0000 @@ -30,9 +30,11 @@ * $FreeBSD$ */ +#include #include #include #include +#include #include #include #include @@ -81,13 +83,8 @@ { if (get_key(&key->bdaddr, 1) != NULL) { syslog(LOG_ERR, "Ignoring duplicated entry " \ - "for bdaddr %x:%x:%x:%x:%x:%x", - key->bdaddr.b[5], - key->bdaddr.b[4], - key->bdaddr.b[3], - key->bdaddr.b[2], - key->bdaddr.b[1], - key->bdaddr.b[0]); + "for bdaddr %s", + bt_ntoa(&key->bdaddr, NULL)); free_key(key); } else LIST_INSERT_HEAD(&link_keys, key, next); @@ -194,7 +191,7 @@ /* Re-read config file */ void -read_config_file(int s) +read_config_file(void) { extern FILE *yyin; @@ -285,6 +282,114 @@ } } #endif + +/* Read keys file */ +int +read_keys_file(void) +{ + FILE *f = NULL; + link_key_t *key = NULL; + char buf[HCSECD_BUFFER_SIZE], *p = NULL, *cp = NULL; + bdaddr_t bdaddr; + int i, len; + + if ((f = fopen(HCSECD_KEYSFILE, "r")) == NULL) { + if (errno == ENOENT) + return (0); + + syslog(LOG_ERR, "Could not open keys file %s. %s (%d)\n", + HCSECD_KEYSFILE, strerror(errno), errno); + + return (-1); + } + + while ((p = fgets(buf, sizeof(buf), f)) != NULL) { + if (*p == '#') + continue; + if ((cp = strpbrk(p, " ")) == NULL) + continue; + + *cp++ = '\0'; + + if (!bt_aton(p, &bdaddr)) + continue; + + if ((key = get_key(&bdaddr, 1)) == NULL) + continue; + + if (key->key == NULL) { + key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); + if (key->key == NULL) { + syslog(LOG_ERR, "Could not allocate link key"); + exit(1); + } + } + + memset(key->key, 0, NG_HCI_KEY_SIZE); + + len = strlen(cp) / 2; + if (len > NG_HCI_KEY_SIZE) + len = NG_HCI_KEY_SIZE; + + for (i = 0; i < len; i ++) + key->key[i] = hexa2int8(cp + 2*i); + + syslog(LOG_DEBUG, "Restored link key for the entry, " \ + "remote bdaddr %s, name '%s'", + bt_ntoa(&key->bdaddr, NULL), + (key->name != NULL)? key->name : "No name"); + } + + fclose(f); + + return (0); +} + +/* Dump keys file */ +int +dump_keys_file(void) +{ + link_key_p key = NULL; + char tmp[PATH_MAX], buf[HCSECD_BUFFER_SIZE]; + int f; + + snprintf(tmp, sizeof(tmp), "%s.tmp", HCSECD_KEYSFILE); + if ((f = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { + syslog(LOG_ERR, "Could not create temp keys file %s. %s (%d)\n", + tmp, strerror(errno), errno); + return (-1); + } + + LIST_FOREACH(key, &link_keys, next) { + if (key->key == NULL) + continue; + + snprintf(buf, sizeof(buf), +"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + bt_ntoa(&key->bdaddr, NULL), + key->key[0], key->key[1], key->key[2], key->key[3], + key->key[4], key->key[5], key->key[6], key->key[7], + key->key[8], key->key[9], key->key[10], key->key[11], + key->key[12], key->key[13], key->key[14], key->key[15]); + + if (write(f, buf, strlen(buf)) < 0) { + syslog(LOG_ERR, "Could not write temp keys file. " \ + "%s (%d)\n", strerror(errno), errno); + break; + } + } + + close(f); + + if (rename(tmp, HCSECD_KEYSFILE) < 0) { + syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n", + tmp, HCSECD_KEYSFILE, strerror(errno), errno); + unlink(tmp); + return (-1); + } + + return (0); +} /* Free key entry */ static void