Bluetooth fixes by Iain Hibbert:

Remove bluetooth.conf stuff from bthcid(8), and use XML with proplib(3)
for keyfile. Also, associate keys with local and remote address.
This commit is contained in:
tron 2006-07-26 11:00:07 +00:00
parent 1d78709e65
commit 7b1d74d73f
6 changed files with 176 additions and 109 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.1 2006/06/19 15:44:56 gdamore Exp $
# $NetBSD: Makefile,v 1.2 2006/07/26 11:00:07 tron Exp $
PROG= bthcid
MAN= bthcid.8
@ -6,7 +6,7 @@ SRCS= bthcid.c hci.c client.c config.c
CPPFLAGS+= -D_BTHCID_
DPADD+= ${LIBBLUETOOTH} ${LIBEVENT} ${LIBUTIL}
LDADD+= -lbluetooth -levent -lutil
DPADD+= ${LIBBLUETOOTH} ${LIBEVENT} ${LIBPROP} ${LIBUTIL}
LDADD+= -lbluetooth -levent -lprop -lutil
.include <bsd.prog.mk>

View File

@ -1,4 +1,4 @@
.\" $NetBSD: bthcid.8,v 1.1 2006/06/19 15:44:56 gdamore Exp $
.\" $NetBSD: bthcid.8,v 1.2 2006/07/26 11:00:07 tron Exp $
.\"
.\" Copyright (c) 2006 Itronix Inc.
.\" All rights reserved.
@ -52,7 +52,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: bthcid.8,v 1.1 2006/06/19 15:44:56 gdamore Exp $
.\" $Id: bthcid.8,v 1.2 2006/07/26 11:00:07 tron Exp $
.\" $FreeBSD: src/usr.sbin/bluetooth/hcsecd/hcsecd.8,v 1.6 2006/02/11 15:36:37 markus Exp $
.\"
.Dd November 16, 2002
@ -64,7 +64,6 @@
.Sh SYNOPSIS
.Nm
.Op Fl fn
.Op Fl c Ar config_file
.Op Fl d Ar device
.Op Fl m Ar mode
.Op Fl s Ar socket_name
@ -74,18 +73,15 @@
The
.Nm
daemon manages link keys and PIN codes for Bluetooth devices.
It opens a raw HCI socket and listens for the following HCI events at the
.Ar device
address given, if any.
It opens a raw HCI socket and listens for the following HCI events.
.Pp
.Bl -tag -width XXXX -compact
.It Dv Link_Key_Request
.Nm
scans first the
scans the
.Pa /var/db/bthcid.keys
file for a cached link key matching the remote device BD_ADDR and, if
none is found, further scans the configuration file. When a link key
has been found, the
found, the
.Dv Link_Key_Request_Reply
will be sent back to the device, otherwise the
.Dv Link_Key_Request_Negative_Reply
@ -100,9 +96,8 @@ link keys file, which will be created if it does not already exist.
.It Dv PIN_Code_Request
The
.Nm
daemon first checks its cached PINs, then the configuration file
for a matching remote device entry.
When no PIN is found, the
daemon checks its PIN cache for a matching remote device entry.
If no PIN is found, the
.Nm
daemon will send a message to any PIN clients that have
registered, with the device details and a timeout value.
@ -123,10 +118,6 @@ utility.
.Pp
The command line options are as follows:
.Bl -tag -width XXXX
.It Fl c Ar config_file
Specify the name of the configuration file.
The default is
.Pa /etc/bluetooth/bluetooth.conf .
.It Fl d Ar device
Specify the local Bluetooth device address. The default is BDADDR_ANY.
.It Fl f
@ -144,14 +135,12 @@ Specify the socket name to listen on for PIN clients. The default path is
.El
.Sh FILES
.Bl -tag -compact
.It Pa /etc/bluetooth/bluetooth.conf
.It Pa /var/db/bthcid.keys
.It Pa /var/run/bthcid
.It Pa /var/run/bthcid.pid
.El
.Sh SEE ALSO
.Xr bluetooth 4 ,
.Xr bluetooth.conf 5 ,
.Xr btconfig 8 ,
.Xr btpin 1
.Sh AUTHORS
@ -171,13 +160,13 @@ with its present name and extended to support PIN clients by
under the sponsorship of
.An Itronix, Inc.
.Sh BUGS
Currently there is no way to select the link key based on
which local device received the request.
.Pp
Everything is based on the remote device BD_ADDR.
.Pp
Currently the only way to make the
The only way to make the
.Nm
daemon forget a link key is to edit the
.Pa /var/db/bthcid.keys
file by hand.
.Pp
The only way to specify link keys (useful when multiple operating
systems are used on the same hardware), is to edit the
.Pa /var/db/bthcid.keys
file by hand.

View File

@ -1,4 +1,4 @@
/* $NetBSD: bthcid.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $ */
/* $NetBSD: bthcid.c,v 1.2 2006/07/26 11:00:07 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -33,7 +33,7 @@
__COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc.\n"
"@(#) Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>\n"
"All rights reserved.\n");
__RCSID("$NetBSD: bthcid.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $");
__RCSID("$NetBSD: bthcid.c,v 1.2 2006/07/26 11:00:07 tron Exp $");
#include <sys/param.h>
#include <sys/stat.h>
@ -49,8 +49,6 @@ __RCSID("$NetBSD: bthcid.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $");
#include "bthcid.h"
const char *key_file = "/var/db/bthcid.keys";
const char *config_file = NULL;
const char *socket_name = BTHCID_SOCKET_NAME;
int detach = 1;
@ -71,12 +69,8 @@ main(int argc, char *argv[])
bdaddr_copy(&bdaddr, BDADDR_ANY);
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
while ((ch = getopt(argc, argv, "c:d:fm:ns:h")) != -1) {
while ((ch = getopt(argc, argv, "d:fm:ns:h")) != -1) {
switch (ch) {
case 'c':
config_file = optarg;
break;
case 'd':
if (!bt_devaddr(optarg, &bdaddr))
err(EXIT_FAILURE, "%s", optarg);

View File

@ -1,4 +1,4 @@
/* $NetBSD: bthcid.h,v 1.1 2006/06/19 15:44:56 gdamore Exp $ */
/* $NetBSD: bthcid.h,v 1.2 2006/07/26 11:00:07 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -61,18 +61,14 @@ typedef struct {
#ifdef _BTHCID_
extern const char *key_file;
extern const char *config_file;
/* config.c */
uint8_t *lookup_pin (bdaddr_t *, bdaddr_t *);
uint8_t *lookup_key (bdaddr_t *, bdaddr_t *);
void save_key (bdaddr_t *, bdaddr_t *, uint8_t *);
/* client.c */
int init_control (const char *, mode_t);
int send_client_request (bdaddr_t *, bdaddr_t *, int);
uint8_t *lookup_item (bdaddr_t *, bdaddr_t *);
uint8_t *lookup_pin (bdaddr_t *, bdaddr_t *);
/* hci.c */
int init_hci (bdaddr_t *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: client.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $ */
/* $NetBSD: client.c,v 1.2 2006/07/26 11:00:07 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: client.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $");
__RCSID("$NetBSD: client.c,v 1.2 2006/07/26 11:00:07 tron Exp $");
#include <sys/ioctl.h>
#include <sys/queue.h>
@ -313,7 +313,7 @@ process_item(int fd, short ev, void *arg)
/* lookup PIN in item cache */
uint8_t *
lookup_item(bdaddr_t *laddr, bdaddr_t *raddr)
lookup_pin(bdaddr_t *laddr, bdaddr_t *raddr)
{
struct item *item;

View File

@ -1,4 +1,4 @@
/* $NetBSD: config.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $ */
/* $NetBSD: config.c,v 1.2 2006/07/26 11:00:07 tron Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -30,104 +30,192 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: config.c,v 1.1 2006/06/19 15:44:56 gdamore Exp $");
__RCSID("$NetBSD: config.c,v 1.2 2006/07/26 11:00:07 tron Exp $");
#include <sys/time.h>
#include <prop/proplib.h>
#include <bluetooth.h>
#include <errno.h>
#include <event.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "bthcid.h"
static bt_cfgentry_t *cfg = NULL;
static const char *key_file = "/var/db/bthcid.keys";
static const char *new_key_file = "/var/db/bthcid.keys.new";
static prop_dictionary_t
load_keys(void)
{
prop_dictionary_t dict;
char *xml;
off_t len;
int fd;
fd = open(key_file, O_RDONLY, 0);
if (fd < 0)
return NULL;
len = lseek(fd, 0, SEEK_END);
if (len == 0) {
close(fd);
return NULL;
}
xml = malloc(len);
if (xml == NULL) {
close(fd);
return NULL;
}
(void)lseek(fd, 0, SEEK_SET);
if (read(fd, xml, len) != len) {
free(xml);
close(fd);
return NULL;
}
dict = prop_dictionary_internalize(xml);
free(xml);
close(fd);
return dict;
}
/*
* Look up key in keys file. We store a dictionary for each
* remote address, and inside that we have a data object for
* each local address containing the key.
*/
uint8_t *
lookup_key(bdaddr_t *laddr, bdaddr_t *raddr)
{
bt_handle_t handle;
static uint8_t key[HCI_KEY_SIZE];
prop_dictionary_t cfg;
prop_object_t obj;
if (cfg != NULL) {
bt_freeconfig(cfg);
cfg = NULL;
}
handle = bt_openconfig(key_file);
if (handle == NULL)
cfg = load_keys();
if (cfg == NULL)
return NULL;
cfg = bt_getconfig(handle, raddr);
bt_closeconfig(handle);
if (cfg == NULL) {
handle = bt_openconfig(config_file);
if (handle == NULL)
return NULL;
cfg = bt_getconfig(handle, raddr);
bt_closeconfig(handle);
obj = prop_dictionary_get(cfg, bt_ntoa(laddr, NULL));
if (obj == NULL || prop_object_type(obj) != PROP_TYPE_DICTIONARY) {
prop_object_release(cfg);
return NULL;
}
if (cfg != NULL)
return cfg->key;
return NULL;
}
uint8_t *
lookup_pin(bdaddr_t *laddr, bdaddr_t *raddr)
{
bt_handle_t handle;
if (cfg != NULL) {
bt_freeconfig(cfg);
cfg = NULL;
obj = prop_dictionary_get(obj, bt_ntoa(raddr, NULL));
if (obj == NULL || prop_object_type(obj) != PROP_TYPE_DATA
|| prop_data_size(obj) != sizeof(key)) {
prop_object_release(cfg);
return NULL;
}
handle = bt_openconfig(config_file);
if (handle != NULL) {
cfg = bt_getconfig(handle, raddr);
bt_closeconfig(handle);
if (cfg != NULL && cfg->pin != NULL)
return cfg->pin;
}
return lookup_item(laddr, raddr);
memcpy(key, prop_data_data_nocopy(obj), sizeof(key));
prop_object_release(cfg);
return key;
}
void
save_key(bdaddr_t *laddr, bdaddr_t *raddr, uint8_t *key)
{
static const char hex[] = "0123456789abcdef";
char buffer[100], keybuf[HCI_KEY_SIZE * 2 + 1];
int fd, n, i;
prop_dictionary_t cfg, dev;
prop_data_t dat;
char *xml;
int fd;
size_t len;
fd = open(key_file, O_WRONLY|O_APPEND|O_CREAT|O_EXLOCK, 0600);
if (fd < 0) {
syslog(LOG_ERR, "Cannot open keyfile %s. %s (%d)",
key_file, strerror(errno), errno);
cfg = load_keys();
if (cfg == NULL) {
cfg = prop_dictionary_create();
if (cfg == NULL) {
syslog(LOG_ERR, "prop_dictionary_create() failed. %s (%d)",
strerror(errno), errno);
return;
}
}
dev = prop_dictionary_get(cfg, bt_ntoa(laddr, NULL));
if (dev == NULL) {
dev = prop_dictionary_create();
if (dev == NULL) {
syslog(LOG_ERR, "prop_dictionary_create() failed. %s (%d)",
strerror(errno), errno);
prop_object_release(cfg);
return;
}
if (!prop_dictionary_set(cfg, bt_ntoa(laddr, NULL), dev)) {
syslog(LOG_ERR, "prop_dictionary_set() failed. %s (%d)",
strerror(errno), errno);
prop_object_release(dev);
prop_object_release(cfg);
return;
}
}
dat = prop_data_create_data_nocopy(key, HCI_KEY_SIZE);
if (dat == NULL) {
syslog(LOG_ERR, "Cannot create data object. %s (%d)",
strerror(errno), errno);
prop_object_release(cfg);
return;
}
for (n = i = 0 ; i < HCI_KEY_SIZE ; i++) {
keybuf[n++] = hex[(key[i] >> 4) & 0xf];
keybuf[n++] = hex[key[i] & 0xf];
if (!prop_dictionary_set(dev, bt_ntoa(raddr, NULL), dat)) {
syslog(LOG_ERR, "prop_dictionary_set() failed. %s (%d)",
strerror(errno), errno);
prop_object_release(dat);
prop_object_release(cfg);
return;
}
keybuf[n] = '\0';
n = snprintf(buffer, sizeof(buffer),
"\ndevice {\n"
"\tbdaddr %s;\n"
"\tkey 0x%s;\n"
"}\n",
bt_ntoa(raddr, NULL),
keybuf);
xml = prop_dictionary_externalize(cfg);
if (xml == NULL) {
syslog(LOG_ERR, "prop_dictionary_externalize() failed. %s (%d)",
strerror(errno), errno);
write(fd, buffer, (size_t)n);
prop_object_release(cfg);
return;
}
prop_object_release(cfg);
fd = open(new_key_file, O_WRONLY|O_TRUNC|O_CREAT|O_EXLOCK, 0600);
if (fd < 0) {
syslog(LOG_ERR, "Cannot open new keyfile %s. %s (%d)",
key_file, strerror(errno), errno);
free(xml);
return;
}
len = strlen(xml);
if (write(fd, xml, len) != len) {
syslog(LOG_ERR, "Write of keyfile failed. %s (%d)",
strerror(errno), errno);
free(xml);
close(fd);
unlink(new_key_file);
return;
}
free(xml);
close(fd);
if (rename(new_key_file, key_file) < 0) {
syslog(LOG_ERR, "rename(%s, %s) failed. %s (%d)",
new_key_file, key_file, strerror(errno), errno);
unlink(new_key_file);
}
}