Add a new utility 'btkey' for managment of Bluetooth Link Keys stored
in the NetBSD key cache (/var/db/bthcid.keys) and Bluetooth controller memory.
This commit is contained in:
parent
985d6fdf0b
commit
e5a7441d16
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.725 2007/11/08 20:14:07 drochner Exp $
|
||||
# $NetBSD: mi,v 1.726 2007/11/09 21:18:22 plunky Exp $
|
||||
. base-sys-root
|
||||
./altroot base-sys-root
|
||||
./bin base-sys-root
|
||||
@ -421,6 +421,7 @@
|
||||
./usr/bin/bdes base-crypto-bin crypto
|
||||
./usr/bin/biff base-mail-bin
|
||||
./usr/bin/bthset base-util-bin
|
||||
./usr/bin/btkey base-util-bin
|
||||
./usr/bin/btpin base-util-bin
|
||||
./usr/bin/bunzip2 base-util-bin
|
||||
./usr/bin/bzcat base-util-bin
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1077 2007/11/06 23:39:25 ad Exp $
|
||||
# $NetBSD: mi,v 1.1078 2007/11/09 21:18:23 plunky Exp $
|
||||
./etc/mtree/set.comp comp-sys-root
|
||||
./usr/bin/addr2line comp-debug-bin bfd
|
||||
./usr/bin/ar comp-util-bin bfd
|
||||
@ -2388,6 +2388,7 @@
|
||||
./usr/libdata/debug/usr/bin/bdes.debug comp-crypto-debug crypto,debug
|
||||
./usr/libdata/debug/usr/bin/biff.debug comp-mail-debug debug
|
||||
./usr/libdata/debug/usr/bin/bthset.debug comp-util-debug debug
|
||||
./usr/libdata/debug/usr/bin/btkey.debug comp-util-debug debug
|
||||
./usr/libdata/debug/usr/bin/btpin.debug comp-util-debug debug
|
||||
./usr/libdata/debug/usr/bin/bzip2.debug comp-util-debug debug
|
||||
./usr/libdata/debug/usr/bin/bzip2recover.debug comp-util-debug debug
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1032 2007/10/29 00:54:18 xtraeme Exp $
|
||||
# $NetBSD: mi,v 1.1033 2007/11/09 21:18:24 plunky Exp $
|
||||
./etc/mtree/set.man man-sys-root
|
||||
./usr/share/info/am-utils.info man-amd-info info
|
||||
./usr/share/info/as.info man-computil-info bfd,info
|
||||
@ -62,6 +62,7 @@
|
||||
./usr/share/man/cat1/biff.0 man-mail-catman .cat
|
||||
./usr/share/man/cat1/bpm.0 man-pkgutil-catman .cat
|
||||
./usr/share/man/cat1/bthset.0 man-util-catman .cat
|
||||
./usr/share/man/cat1/btkey.0 man-util-catman .cat
|
||||
./usr/share/man/cat1/btpin.0 man-util-catman .cat
|
||||
./usr/share/man/cat1/bunzip2.0 man-util-catman .cat
|
||||
./usr/share/man/cat1/bzcat.0 man-util-catman .cat
|
||||
@ -2559,6 +2560,7 @@
|
||||
./usr/share/man/man1/biff.1 man-mail-man .man
|
||||
./usr/share/man/man1/bpm.1 man-pkgutil-man .man
|
||||
./usr/share/man/man1/bthset.1 man-util-man .man
|
||||
./usr/share/man/man1/btkey.1 man-util-man .man
|
||||
./usr/share/man/man1/btpin.1 man-util-man .man
|
||||
./usr/share/man/man1/bunzip2.1 man-util-man .man
|
||||
./usr/share/man/man1/bzcat.1 man-util-man .man
|
||||
|
@ -1,9 +1,10 @@
|
||||
# $NetBSD: Makefile,v 1.158 2007/06/21 14:09:23 ginsbach Exp $
|
||||
# $NetBSD: Makefile,v 1.159 2007/11/09 21:18:24 plunky Exp $
|
||||
# from: @(#)Makefile 8.3 (Berkeley) 1/7/94
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= apply apropos asa at audio awk banner basename biff bthset btpin \
|
||||
SUBDIR= apply apropos asa at audio awk \
|
||||
banner basename biff bthset btkey btpin \
|
||||
bzip2 bzip2recover cal calendar cap_mkdb cdplay \
|
||||
checknr chflags chpass cksum cmp col colcrt colrm \
|
||||
column comm compress config crontab crunch csplit ctags cut \
|
||||
|
10
usr.bin/btkey/Makefile
Normal file
10
usr.bin/btkey/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# $NetBSD: Makefile,v 1.1 2007/11/09 21:18:24 plunky Exp $
|
||||
|
||||
PROG= btkey
|
||||
SRCS= btkey.c device.c file.c
|
||||
MAN= btkey.1
|
||||
|
||||
DPADD+= ${LIBBLUETOOTH} ${LIBPROP}
|
||||
LDADD+= -lbluetooth -lprop
|
||||
|
||||
.include <bsd.prog.mk>
|
130
usr.bin/btkey/btkey.1
Normal file
130
usr.bin/btkey/btkey.1
Normal file
@ -0,0 +1,130 @@
|
||||
.\" $NetBSD: btkey.1,v 1.1 2007/11/09 21:18:25 plunky Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Iain Hibbert
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd November 8, 2007
|
||||
.Dt BTKEY 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm btkey
|
||||
.Nd Bluetooth Link Key management utility
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl cCrRwW
|
||||
.Op Fl k Ar key
|
||||
.Fl a Ar address
|
||||
.Fl d Ar device
|
||||
.Nm
|
||||
.Fl lL
|
||||
.Op Fl d Ar device
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program is used to manage Bluetooth Link Key storage.
|
||||
Keys are normally handled by the
|
||||
.Xr bthcid 8
|
||||
daemon which caches them in the
|
||||
.Pa /var/db/bthcid.keys
|
||||
file and provides them as required when Bluetooth connections
|
||||
need to be authenticated.
|
||||
.Pp
|
||||
These keys are required for connections between remote
|
||||
devices and the specific controller
|
||||
.Pq not the Operating System
|
||||
and so for multi-boot systems where it may not always be possible to
|
||||
specify the same key across all OS's it can be better to have the
|
||||
Bluetooth controller provide the keys directly from its semi-permanent
|
||||
memory once devices are paired.
|
||||
.Nm
|
||||
will read, write or clear keys in device memory or the key cache
|
||||
as required.
|
||||
.Pp
|
||||
Note that without the
|
||||
.Xr bthcid 8
|
||||
daemon running users will be unable to supply PINs, and Link Keys
|
||||
resulting from new pairings will not be stored.
|
||||
If no new pairings are expected and the keys are stored in
|
||||
the controller then
|
||||
.Xr bthcid 8
|
||||
is not required.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width ".Fl a Ar address"
|
||||
.It Fl a Ar address
|
||||
Specify the remote device address.
|
||||
May be given as a BDADDR or a name.
|
||||
.It Fl c
|
||||
Clear key from file.
|
||||
.It Fl C
|
||||
Clear key from device.
|
||||
.It Fl d Ar device
|
||||
Specify the local device address.
|
||||
May be given as a BDADDR or a name.
|
||||
.It Fl k Ar key
|
||||
Supply a Link Key as a string of hexadecimal digits.
|
||||
Up to 32 digits will be processed and the resulting key
|
||||
will be zero padded to 16 octets.
|
||||
.It Fl l
|
||||
List keys stored in file.
|
||||
.It Fl L
|
||||
List keys stored in device.
|
||||
.It Fl r
|
||||
Read key from file.
|
||||
.It Fl R
|
||||
Read key from device.
|
||||
.It Fl w
|
||||
Write key to file.
|
||||
.It Fl W
|
||||
Write key to device.
|
||||
.El
|
||||
.Pp
|
||||
Super-user privileges are required to read or write link keys.
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
Read key for mouse at ubt0 from file and write to device
|
||||
.Pp
|
||||
.Dl btkey -d ubt0 -a mouse -rW
|
||||
.Pp
|
||||
Write new key for keyboard at ubt0 to file
|
||||
.Pp
|
||||
.Dl btkey -d ubt0 -a keyboard -k 92beda6cd8b8f66ebd2af270d55d70ec -w
|
||||
.Pp
|
||||
Clear key for phone at bt3c0 from file and device
|
||||
.Pp
|
||||
.Dl btkey -d bt3c0 -a phone -cC
|
||||
.Pp
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh FILES
|
||||
.Bl -tag -compact
|
||||
.Pa /var/db/bthcid.keys
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr btpin 1 ,
|
||||
.Xr btconfig 8 ,
|
||||
.Xr bthcid 8
|
||||
.Sh AUTHORS
|
||||
.An Iain Hibbert
|
300
usr.bin/btkey/btkey.c
Normal file
300
usr.bin/btkey/btkey.c
Normal file
@ -0,0 +1,300 @@
|
||||
/* $NetBSD: btkey.c,v 1.1 2007/11/09 21:18:25 plunky Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Iain Hibbert
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__COPYRIGHT("@(#) Copyright (c) 2007 Iain Hibbert\n"
|
||||
"All rights reserved.\n");
|
||||
__RCSID("$NetBSD: btkey.c,v 1.1 2007/11/09 21:18:25 plunky Exp $");
|
||||
|
||||
#include <bluetooth.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btkey.h"
|
||||
|
||||
static void usage(void);
|
||||
static bool scan_key(const char *);
|
||||
|
||||
bdaddr_t laddr;
|
||||
bdaddr_t raddr;
|
||||
uint8_t key[HCI_KEY_SIZE];
|
||||
|
||||
int
|
||||
main(int ac, char *av[])
|
||||
{
|
||||
struct hostent *he;
|
||||
int ch;
|
||||
bool cf, cd, lf, ld, rf, rd, wf, wd, nk;
|
||||
|
||||
memset(&laddr, 0, sizeof(laddr));
|
||||
memset(&raddr, 0, sizeof(raddr));
|
||||
memset(key, 0, sizeof(key));
|
||||
cf = cd = lf = ld = rf = rd = wf = wd = nk = false;
|
||||
|
||||
while ((ch = getopt(ac, av, "a:cCd:k:lLrRwW")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'a': /* remote device address */
|
||||
if (!bt_aton(optarg, &raddr)) {
|
||||
he = bt_gethostbyname(optarg);
|
||||
if (he == NULL)
|
||||
errx(EXIT_FAILURE, "%s: %s",
|
||||
optarg, hstrerror(h_errno));
|
||||
|
||||
bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c': /* clear from file */
|
||||
cf = true;
|
||||
break;
|
||||
|
||||
case 'C': /* clear from device */
|
||||
cd = true;
|
||||
break;
|
||||
|
||||
case 'd': /* local device address */
|
||||
if (!bt_devaddr(optarg, &laddr)
|
||||
&& !bt_aton(optarg, &laddr)) {
|
||||
he = bt_gethostbyname(optarg);
|
||||
if (he == NULL)
|
||||
errx(EXIT_FAILURE, "%s: %s",
|
||||
optarg, hstrerror(h_errno));
|
||||
|
||||
bdaddr_copy(&laddr, (bdaddr_t *)he->h_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'k': /* new link key */
|
||||
if (!scan_key(optarg))
|
||||
errx(EXIT_FAILURE, "invalid key '%s'", optarg);
|
||||
|
||||
nk = true;
|
||||
break;
|
||||
|
||||
case 'l': /* list from file */
|
||||
lf = true;
|
||||
break;
|
||||
|
||||
case 'L': /* list from device */
|
||||
ld = true;
|
||||
break;
|
||||
|
||||
case 'r': /* read from file */
|
||||
rf = true;
|
||||
break;
|
||||
|
||||
case 'R': /* read from device */
|
||||
rd = true;
|
||||
break;
|
||||
|
||||
case 'w': /* write to file */
|
||||
wf = true;
|
||||
break;
|
||||
|
||||
case 'W': /* write to device */
|
||||
wd = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
/*
|
||||
* validate options
|
||||
*/
|
||||
if ((lf || ld) && (rf || rd || wf || wd || cf || cd || nk))
|
||||
errx(EXIT_FAILURE, "list is exclusive of other options");
|
||||
|
||||
if (((rf && rd) || (rf && nk) || (rd && nk)) && (wf || wd))
|
||||
errx(EXIT_FAILURE, "too many key sources");
|
||||
|
||||
if (((bdaddr_any(&laddr) || bdaddr_any(&raddr)) && !(lf || ld))
|
||||
|| ((lf || ld) && (bdaddr_any(&laddr) || !bdaddr_any(&raddr)))
|
||||
|| ac > 0)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* do what we gotta do and be done
|
||||
*/
|
||||
if (!bdaddr_any(&laddr))
|
||||
print_addr("device", &laddr);
|
||||
|
||||
if (!bdaddr_any(&raddr))
|
||||
print_addr("bdaddr", &raddr);
|
||||
|
||||
if (lf && !list_file())
|
||||
err(EXIT_FAILURE, "list file");
|
||||
|
||||
if (ld && !list_device())
|
||||
err(EXIT_FAILURE, "list device");
|
||||
|
||||
if (nk)
|
||||
print_key("new key", key);
|
||||
|
||||
if (rf) {
|
||||
if (!read_file())
|
||||
err(EXIT_FAILURE, "file key");
|
||||
|
||||
print_key("file key", key);
|
||||
}
|
||||
|
||||
if (rd) {
|
||||
if (!read_device())
|
||||
err(EXIT_FAILURE, "device key");
|
||||
|
||||
print_key("device key", key);
|
||||
}
|
||||
|
||||
if (wf || wd || cf || cd)
|
||||
printf("\n");
|
||||
|
||||
if (wf) {
|
||||
if (!write_file())
|
||||
err(EXIT_FAILURE, "write to file");
|
||||
|
||||
printf("written to file\n");
|
||||
}
|
||||
|
||||
if (wd) {
|
||||
if (!write_device())
|
||||
err(EXIT_FAILURE, "write to device");
|
||||
|
||||
printf("written to device\n");
|
||||
}
|
||||
|
||||
if (cf) {
|
||||
if (!clear_file())
|
||||
err(EXIT_FAILURE, "clear from file");
|
||||
|
||||
printf("cleared from file\n");
|
||||
}
|
||||
|
||||
if (cd) {
|
||||
if (!clear_device())
|
||||
err(EXIT_FAILURE, "clear from device");
|
||||
|
||||
printf("cleared from device\n");
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-cCrRwW] [-k key] -a address -d device\n"
|
||||
" %s -lL -d device\n"
|
||||
"\n", getprogname(), getprogname());
|
||||
|
||||
fprintf(stderr,
|
||||
"Where:\n"
|
||||
"\t-a address remote device address\n"
|
||||
"\t-c clear from file\n"
|
||||
"\t-C clear from device\n"
|
||||
"\t-d device local device address\n"
|
||||
"\t-k key user specified link_key\n"
|
||||
"\t-l list file keys\n"
|
||||
"\t-L list device keys\n"
|
||||
"\t-r read from file\n"
|
||||
"\t-R read from device\n"
|
||||
"\t-w write to file\n"
|
||||
"\t-W write to device\n"
|
||||
"\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static bool
|
||||
scan_key(const char *arg)
|
||||
{
|
||||
static const char digits[] = "0123456789abcdef";
|
||||
const char *p;
|
||||
int i, j;
|
||||
|
||||
memset(key, 0, sizeof(key));
|
||||
|
||||
for (i = 0 ; i < HCI_KEY_SIZE ; i++) {
|
||||
for (j = 0 ; j < 2 ; j++) {
|
||||
if (*arg == '\0')
|
||||
return true;
|
||||
|
||||
for (p = digits ; *p != *arg ; p++)
|
||||
if (*p == '\0')
|
||||
return false;
|
||||
|
||||
arg++;
|
||||
key[i] = (key[i] << 4) + (p - digits);
|
||||
}
|
||||
}
|
||||
|
||||
if (*arg != '\0')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
print_key(const char *type, const uint8_t *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("%10s: ", type);
|
||||
for (i = 0 ; i < HCI_KEY_SIZE ; i++)
|
||||
printf("%2.2x", src[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_addr(const char *type, const bdaddr_t *addr)
|
||||
{
|
||||
char name[HCI_DEVNAME_SIZE];
|
||||
struct hostent *he;
|
||||
|
||||
printf("%10s: %s", type, bt_ntoa(addr, NULL));
|
||||
|
||||
if (bt_devname(name, addr))
|
||||
printf(" (%s)", name);
|
||||
else if ((he = bt_gethostbyaddr((const char *)addr,
|
||||
sizeof(bdaddr_t), AF_BLUETOOTH)) != NULL)
|
||||
printf(" (%s)", he->h_name);
|
||||
|
||||
printf("\n");
|
||||
}
|
48
usr.bin/btkey/btkey.h
Normal file
48
usr.bin/btkey/btkey.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* $NetBSD: btkey.h,v 1.1 2007/11/09 21:18:25 plunky Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Iain Hibbert
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* btkey.c */
|
||||
extern bdaddr_t laddr;
|
||||
extern bdaddr_t raddr;
|
||||
extern uint8_t key[];
|
||||
|
||||
void print_key(const char *, const uint8_t *);
|
||||
void print_addr(const char *, const bdaddr_t *);
|
||||
|
||||
/* device.c */
|
||||
bool list_device(void);
|
||||
bool read_device(void);
|
||||
bool write_device(void);
|
||||
bool clear_device(void);
|
||||
|
||||
/* file.c */
|
||||
bool list_file(void);
|
||||
bool read_file(void);
|
||||
bool write_file(void);
|
||||
bool clear_file(void);
|
265
usr.bin/btkey/device.c
Normal file
265
usr.bin/btkey/device.c
Normal file
@ -0,0 +1,265 @@
|
||||
/* $NetBSD: device.c,v 1.1 2007/11/09 21:18:25 plunky Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Iain Hibbert
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: device.c,v 1.1 2007/11/09 21:18:25 plunky Exp $");
|
||||
|
||||
#include <bluetooth.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btkey.h"
|
||||
|
||||
/*
|
||||
* read/write stored link keys packet, with space for one key
|
||||
*/
|
||||
struct stored_link_keys {
|
||||
uint8_t num_keys;
|
||||
struct {
|
||||
bdaddr_t addr;
|
||||
uint8_t key[HCI_KEY_SIZE];
|
||||
} key[1];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/*
|
||||
* generic request
|
||||
*
|
||||
* send command 'opcode' with command packet 'cptr' of size 'clen'
|
||||
* call 'func_cc' on command_complete event
|
||||
* call 'func_ev' on event 'event'
|
||||
* callbacks return -1 (failure), 0 (continue) or 1 (success)
|
||||
*/
|
||||
static bool
|
||||
hci_req(uint16_t opcode, void *cptr, size_t clen, int (*func_cc)(void *),
|
||||
uint8_t event, int (*func_ev)(void *))
|
||||
{
|
||||
uint8_t buf[sizeof(hci_cmd_hdr_t) + HCI_CMD_PKT_SIZE];
|
||||
struct sockaddr_bt sa;
|
||||
struct hci_filter f;
|
||||
hci_cmd_hdr_t *hdr;
|
||||
hci_event_hdr_t *ep;
|
||||
int fd, rv;
|
||||
|
||||
memset(&f, 0, sizeof(f));
|
||||
hci_filter_set(HCI_EVENT_COMMAND_COMPL, &f);
|
||||
if (event != 0) hci_filter_set(event, &f);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.bt_len = sizeof(sa);
|
||||
sa.bt_family = AF_BLUETOOTH;
|
||||
bdaddr_copy(&sa.bt_bdaddr, &laddr);
|
||||
|
||||
hdr = (hci_cmd_hdr_t *)buf;
|
||||
hdr->type = HCI_CMD_PKT;
|
||||
hdr->opcode = htole16(opcode);
|
||||
hdr->length = clen;
|
||||
|
||||
memcpy(buf + sizeof(hci_cmd_hdr_t), cptr, clen);
|
||||
|
||||
rv = -1;
|
||||
|
||||
if ((fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0
|
||||
|| setsockopt(fd, BTPROTO_HCI, SO_HCI_EVT_FILTER, &f, sizeof(f)) < 0
|
||||
|| bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0
|
||||
|| connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0
|
||||
|| send(fd, buf, sizeof(hci_cmd_hdr_t) + clen, 0) < 0)
|
||||
goto done;
|
||||
|
||||
ep = (hci_event_hdr_t *)buf;
|
||||
for (;;) {
|
||||
if (recv(fd, buf, sizeof(buf), 0) < 0)
|
||||
goto done;
|
||||
|
||||
if (ep->event == HCI_EVENT_COMMAND_COMPL) {
|
||||
hci_command_compl_ep *cc;
|
||||
|
||||
cc = (hci_command_compl_ep *)(ep + 1);
|
||||
if (opcode != le16toh(cc->opcode))
|
||||
continue;
|
||||
|
||||
rv = func_cc(cc + 1);
|
||||
if (rv == 0)
|
||||
continue;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (event != 0 && event == ep->event) {
|
||||
rv = func_ev(ep + 1);
|
||||
if (rv == 0)
|
||||
continue;
|
||||
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (fd >= 0) close(fd);
|
||||
return rv > 0 ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* List keys on device
|
||||
*/
|
||||
|
||||
static int
|
||||
list_device_cc(void *arg)
|
||||
{
|
||||
hci_read_stored_link_key_rp *rp = arg;
|
||||
|
||||
if (rp->status)
|
||||
return -1;
|
||||
|
||||
printf("\n");
|
||||
printf("read %d keys (max %d)\n", rp->num_keys_read, rp->max_num_keys);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
list_device_ev(void *arg)
|
||||
{
|
||||
struct stored_link_keys *ep = arg;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < ep->num_keys ; i++) {
|
||||
printf("\n");
|
||||
print_addr("bdaddr", &ep->key[i].addr);
|
||||
print_key("device key", ep->key[i].key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
list_device(void)
|
||||
{
|
||||
hci_read_stored_link_key_cp cp;
|
||||
|
||||
bdaddr_copy(&cp.bdaddr, BDADDR_ANY);
|
||||
cp.read_all = 0x01;
|
||||
|
||||
return hci_req(HCI_CMD_READ_STORED_LINK_KEY,
|
||||
&cp, sizeof(cp), list_device_cc,
|
||||
HCI_EVENT_RETURN_LINK_KEYS, list_device_ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read key from device
|
||||
*/
|
||||
|
||||
static int
|
||||
read_device_cc(void *arg)
|
||||
{
|
||||
|
||||
/* if we got here, no key was found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
read_device_ev(void *arg)
|
||||
{
|
||||
struct stored_link_keys *ep = arg;
|
||||
|
||||
if (ep->num_keys != 1
|
||||
|| !bdaddr_same(&ep->key[0].addr, &raddr))
|
||||
return 0;
|
||||
|
||||
memcpy(key, ep->key[0].key, HCI_KEY_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool
|
||||
read_device(void)
|
||||
{
|
||||
hci_read_stored_link_key_cp cp;
|
||||
|
||||
bdaddr_copy(&cp.bdaddr, &raddr);
|
||||
cp.read_all = 0x00;
|
||||
|
||||
return hci_req(HCI_CMD_READ_STORED_LINK_KEY,
|
||||
&cp, sizeof(cp), read_device_cc,
|
||||
HCI_EVENT_RETURN_LINK_KEYS, read_device_ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write key to device
|
||||
*/
|
||||
static int
|
||||
write_device_cc(void *arg)
|
||||
{
|
||||
hci_write_stored_link_key_rp *rp = arg;
|
||||
|
||||
if (rp->status || rp->num_keys_written != 1)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool
|
||||
write_device(void)
|
||||
{
|
||||
struct stored_link_keys cp;
|
||||
|
||||
cp.num_keys = 1;
|
||||
bdaddr_copy(&cp.key[0].addr, &raddr);
|
||||
memcpy(cp.key[0].key, key, HCI_KEY_SIZE);
|
||||
|
||||
return hci_req(HCI_CMD_WRITE_STORED_LINK_KEY,
|
||||
&cp, sizeof(cp), write_device_cc,
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear key from device
|
||||
*/
|
||||
static int
|
||||
clear_device_cc(void *arg)
|
||||
{
|
||||
hci_delete_stored_link_key_rp *rp = arg;
|
||||
|
||||
if (rp->status || rp->num_keys_deleted != 1)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool
|
||||
clear_device(void)
|
||||
{
|
||||
hci_delete_stored_link_key_cp cp;
|
||||
|
||||
cp.delete_all = 0x00;
|
||||
bdaddr_copy(&cp.bdaddr, &raddr);
|
||||
|
||||
return hci_req(HCI_CMD_DELETE_STORED_LINK_KEY,
|
||||
&cp, sizeof(cp), clear_device_cc,
|
||||
0, NULL);
|
||||
}
|
202
usr.bin/btkey/file.c
Normal file
202
usr.bin/btkey/file.c
Normal file
@ -0,0 +1,202 @@
|
||||
/* $NetBSD: file.c,v 1.1 2007/11/09 21:18:25 plunky Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Iain Hibbert
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: file.c,v 1.1 2007/11/09 21:18:25 plunky Exp $");
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <prop/proplib.h>
|
||||
|
||||
#include <bluetooth.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "btkey.h"
|
||||
|
||||
static const char *key_file = "/var/db/bthcid.keys";
|
||||
|
||||
/*
|
||||
* List keys file.
|
||||
*/
|
||||
bool
|
||||
list_file(void)
|
||||
{
|
||||
prop_dictionary_t db, dev;
|
||||
prop_object_iterator_t iter;
|
||||
prop_dictionary_keysym_t sym;
|
||||
prop_object_t dat;
|
||||
bdaddr_t bdaddr;
|
||||
bool rv = false;
|
||||
|
||||
db = prop_dictionary_internalize_from_file(key_file);
|
||||
if (db == NULL)
|
||||
return false;
|
||||
|
||||
dev = prop_dictionary_get(db, bt_ntoa(&laddr, NULL));
|
||||
if (prop_object_type(dev) != PROP_TYPE_DICTIONARY)
|
||||
goto done;
|
||||
|
||||
iter = prop_dictionary_iterator(dev);
|
||||
if (iter == NULL)
|
||||
goto done;
|
||||
|
||||
while ((sym = prop_object_iterator_next(iter)) != NULL) {
|
||||
memset(&bdaddr, 0, sizeof(bdaddr));
|
||||
bt_aton(prop_dictionary_keysym_cstring_nocopy(sym), &bdaddr);
|
||||
if (bdaddr_any(&bdaddr))
|
||||
continue;
|
||||
|
||||
dat = prop_dictionary_get_keysym(dev, sym);
|
||||
if (prop_data_size(dat) != HCI_KEY_SIZE)
|
||||
continue;
|
||||
|
||||
printf("\n");
|
||||
print_addr("bdaddr", &bdaddr);
|
||||
print_key("file key", prop_data_data_nocopy(dat));
|
||||
}
|
||||
|
||||
prop_object_iterator_release(iter);
|
||||
rv = true;
|
||||
|
||||
done:
|
||||
prop_object_release(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from keys file.
|
||||
*/
|
||||
bool
|
||||
read_file(void)
|
||||
{
|
||||
prop_dictionary_t db, dev;
|
||||
prop_object_t dat;
|
||||
bool rv = false;
|
||||
|
||||
db = prop_dictionary_internalize_from_file(key_file);
|
||||
if (db == NULL)
|
||||
return false;
|
||||
|
||||
dev = prop_dictionary_get(db, bt_ntoa(&laddr, NULL));
|
||||
if (prop_object_type(dev) != PROP_TYPE_DICTIONARY)
|
||||
goto done;
|
||||
|
||||
dat = prop_dictionary_get(dev, bt_ntoa(&raddr, NULL));
|
||||
if (prop_data_size(dat) != HCI_KEY_SIZE)
|
||||
goto done;
|
||||
|
||||
memcpy(key, prop_data_data_nocopy(dat), HCI_KEY_SIZE);
|
||||
rv = true;
|
||||
|
||||
done:
|
||||
prop_object_release(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to keys file.
|
||||
*/
|
||||
bool
|
||||
write_file(void)
|
||||
{
|
||||
prop_dictionary_t db, dev;
|
||||
prop_data_t dat;
|
||||
mode_t mode;
|
||||
bool rv = false;
|
||||
|
||||
db = prop_dictionary_internalize_from_file(key_file);
|
||||
if (db == NULL) {
|
||||
db = prop_dictionary_create();
|
||||
if (db == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
dev = prop_dictionary_get(db, bt_ntoa(&laddr, NULL));
|
||||
if (dev == NULL) {
|
||||
dev = prop_dictionary_create();
|
||||
if (dev == NULL)
|
||||
goto done;
|
||||
|
||||
rv = prop_dictionary_set(db, bt_ntoa(&laddr, NULL), dev);
|
||||
prop_object_release(dev);
|
||||
if (rv == false)
|
||||
goto done;
|
||||
}
|
||||
|
||||
dat = prop_data_create_data_nocopy(key, HCI_KEY_SIZE);
|
||||
if (dat == NULL)
|
||||
goto done;
|
||||
|
||||
rv = prop_dictionary_set(dev, bt_ntoa(&raddr, NULL), dat);
|
||||
prop_object_release(dat);
|
||||
if (rv == false)
|
||||
goto done;
|
||||
|
||||
mode = umask(S_IRWXG | S_IRWXO);
|
||||
rv = prop_dictionary_externalize_to_file(db, key_file);
|
||||
umask(mode);
|
||||
|
||||
done:
|
||||
prop_object_release(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear from keys file.
|
||||
*/
|
||||
bool
|
||||
clear_file(void)
|
||||
{
|
||||
prop_dictionary_t db, dev;
|
||||
prop_data_t dat;
|
||||
mode_t mode;
|
||||
bool rv = false;
|
||||
|
||||
db = prop_dictionary_internalize_from_file(key_file);
|
||||
if (db == NULL)
|
||||
return false;
|
||||
|
||||
dev = prop_dictionary_get(db, bt_ntoa(&laddr, NULL));
|
||||
if (dev == NULL)
|
||||
goto done;
|
||||
|
||||
dat = prop_dictionary_get(dev, bt_ntoa(&raddr, NULL));
|
||||
if (prop_data_size(dat) != HCI_KEY_SIZE)
|
||||
goto done;
|
||||
|
||||
prop_dictionary_remove(dev, bt_ntoa(&raddr, NULL));
|
||||
|
||||
mode = umask(S_IRWXG | S_IRWXO);
|
||||
rv = prop_dictionary_externalize_to_file(db, key_file);
|
||||
umask(mode);
|
||||
|
||||
done:
|
||||
prop_object_release(db);
|
||||
return rv;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: btpin.1,v 1.6 2007/09/24 19:29:01 plunky Exp $
|
||||
.\" $NetBSD: btpin.1,v 1.7 2007/11/09 21:18:24 plunky Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2006 Itronix Inc.
|
||||
.\" All rights reserved.
|
||||
@ -84,6 +84,7 @@ The default path is
|
||||
.Pa /var/run/bthcid
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr btkey 1 ,
|
||||
.Xr btconfig 8 ,
|
||||
.Xr bthcid 8
|
||||
.Sh AUTHORS
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: bthcid.8,v 1.5 2006/10/03 02:04:42 wiz Exp $
|
||||
.\" $NetBSD: bthcid.8,v 1.6 2007/11/09 21:18:24 plunky 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.5 2006/10/03 02:04:42 wiz Exp $
|
||||
.\" $Id: bthcid.8,v 1.6 2007/11/09 21:18:24 plunky Exp $
|
||||
.\" $FreeBSD: src/usr.sbin/bluetooth/hcsecd/hcsecd.8,v 1.6 2006/02/11 15:36:37 markus Exp $
|
||||
.\"
|
||||
.Dd September 29, 2006
|
||||
@ -72,7 +72,7 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
daemon manages link keys and PIN codes for Bluetooth devices.
|
||||
daemon handles Link Key and PIN code requests for Bluetooth devices.
|
||||
It opens a raw HCI socket and listens for the following HCI events.
|
||||
.Pp
|
||||
.Bl -tag -width XXXX -compact
|
||||
@ -116,6 +116,13 @@ to the cache prior to pairing with the
|
||||
utility.
|
||||
.El
|
||||
.Pp
|
||||
Some of the functionality of
|
||||
.Nm
|
||||
can be handled by the Bluetooth controller directly, and cached Link
|
||||
Keys may be examined, deleted or moved to device storage using the
|
||||
.Xr btkey 1
|
||||
program.
|
||||
.Pp
|
||||
The command line options are as follows:
|
||||
.Bl -tag -width XXXX
|
||||
.It Fl d Ar device
|
||||
@ -143,6 +150,7 @@ The default path is
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr btpin 1 ,
|
||||
.Xr btkey 1 ,
|
||||
.Xr bluetooth 4 ,
|
||||
.Xr btconfig 8
|
||||
.Sh HISTORY
|
||||
@ -160,14 +168,3 @@ under the sponsorship of Itronix, Inc.
|
||||
.Sh AUTHORS
|
||||
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
|
||||
.An Iain Hibbert
|
||||
.Sh BUGS
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user