Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bluetooth/hcsecd/hcsecd.c
103381 views
1
/*-
2
* hcsecd.c
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 2001-2002 Maksim Yevmenkin <[email protected]>
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*
30
* $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $
31
*/
32
33
#include <sys/queue.h>
34
#define L2CAP_SOCKET_CHECKED
35
#include <bluetooth.h>
36
#include <err.h>
37
#include <errno.h>
38
#include <signal.h>
39
#include <stdarg.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <syslog.h>
44
#include <unistd.h>
45
#include "hcsecd.h"
46
47
static int done = 0;
48
49
static int process_pin_code_request_event
50
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
51
static int process_link_key_request_event
52
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
53
static int send_pin_code_reply
54
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
55
static int send_link_key_reply
56
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, uint8_t *key);
57
static int process_link_key_notification_event
58
(int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep);
59
static void sighup
60
(int s);
61
static void sigint
62
(int s);
63
static void usage
64
(void);
65
66
/* Main */
67
int
68
main(int argc, char *argv[])
69
{
70
int n, detach, sock;
71
socklen_t size;
72
struct sigaction sa;
73
struct sockaddr_hci addr;
74
struct ng_btsocket_hci_raw_filter filter;
75
char buffer[HCSECD_BUFFER_SIZE];
76
ng_hci_event_pkt_t *event = NULL;
77
78
detach = 1;
79
80
while ((n = getopt(argc, argv, "df:h")) != -1) {
81
switch (n) {
82
case 'd':
83
detach = 0;
84
break;
85
86
case 'f':
87
config_file = optarg;
88
break;
89
90
case 'h':
91
default:
92
usage();
93
/* NOT REACHED */
94
}
95
}
96
97
if (config_file == NULL)
98
usage();
99
/* NOT REACHED */
100
101
if (getuid() != 0)
102
errx(1, "** ERROR: You should run %s as privileged user!",
103
HCSECD_IDENT);
104
105
/* Set signal handlers */
106
memset(&sa, 0, sizeof(sa));
107
sa.sa_handler = sigint;
108
sa.sa_flags = SA_NOCLDWAIT;
109
if (sigaction(SIGINT, &sa, NULL) < 0)
110
err(1, "Could not sigaction(SIGINT)");
111
if (sigaction(SIGTERM, &sa, NULL) < 0)
112
err(1, "Could not sigaction(SIGINT)");
113
114
memset(&sa, 0, sizeof(sa));
115
sa.sa_handler = sighup;
116
if (sigaction(SIGHUP, &sa, NULL) < 0)
117
err(1, "Could not sigaction(SIGHUP)");
118
119
/* Open socket and set filter */
120
sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
121
if (sock < 0)
122
err(1, "Could not create HCI socket");
123
124
memset(&filter, 0, sizeof(filter));
125
bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
126
bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
127
bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
128
129
if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
130
(void * const) &filter, sizeof(filter)) < 0)
131
err(1, "Could not set HCI socket filter");
132
133
if (detach && daemon(0, 0) < 0)
134
err(1, "Could not daemon()ize");
135
136
openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
137
138
read_config_file();
139
read_keys_file();
140
141
if (detach) {
142
FILE *pid = NULL;
143
144
if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
145
syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
146
HCSECD_PIDFILE, strerror(errno), errno);
147
exit(1);
148
}
149
150
fprintf(pid, "%d", getpid());
151
fclose(pid);
152
}
153
154
event = (ng_hci_event_pkt_t *) buffer;
155
while (!done) {
156
size = sizeof(addr);
157
n = recvfrom(sock, buffer, sizeof(buffer), 0,
158
(struct sockaddr *) &addr, &size);
159
if (n < 0) {
160
if (errno == EINTR)
161
continue;
162
163
syslog(LOG_ERR, "Could not receive from HCI socket. " \
164
"%s (%d)", strerror(errno), errno);
165
exit(1);
166
}
167
168
if (event->type != NG_HCI_EVENT_PKT) {
169
syslog(LOG_ERR, "Received unexpected HCI packet, " \
170
"type=%#x", event->type);
171
continue;
172
}
173
174
switch (event->event) {
175
case NG_HCI_EVENT_PIN_CODE_REQ:
176
process_pin_code_request_event(sock, &addr,
177
(bdaddr_p)(event + 1));
178
break;
179
180
case NG_HCI_EVENT_LINK_KEY_REQ:
181
process_link_key_request_event(sock, &addr,
182
(bdaddr_p)(event + 1));
183
break;
184
185
case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
186
process_link_key_notification_event(sock, &addr,
187
(ng_hci_link_key_notification_ep *)(event + 1));
188
break;
189
190
default:
191
syslog(LOG_ERR, "Received unexpected HCI event, " \
192
"event=%#x", event->event);
193
break;
194
}
195
}
196
197
if (detach)
198
if (remove(HCSECD_PIDFILE) < 0)
199
syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
200
HCSECD_PIDFILE, strerror(errno), errno);
201
202
dump_keys_file();
203
clean_config();
204
closelog();
205
close(sock);
206
207
return (0);
208
}
209
210
/* Process PIN_Code_Request event */
211
static int
212
process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
213
bdaddr_p bdaddr)
214
{
215
link_key_p key = NULL;
216
217
syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \
218
"remote bdaddr %s", addr->hci_node,
219
bt_ntoa(bdaddr, NULL));
220
221
if ((key = get_key(bdaddr, 0)) != NULL) {
222
syslog(LOG_DEBUG, "Found matching entry, " \
223
"remote bdaddr %s, name '%s', PIN code %s",
224
bt_ntoa(&key->bdaddr, NULL),
225
(key->name != NULL)? key->name : "No name",
226
(key->pin != NULL)? "exists" : "doesn't exist");
227
228
return (send_pin_code_reply(sock, addr, bdaddr, key->pin));
229
}
230
231
syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s",
232
bt_ntoa(bdaddr, NULL));
233
234
return (send_pin_code_reply(sock, addr, bdaddr, NULL));
235
}
236
237
/* Process Link_Key_Request event */
238
static int
239
process_link_key_request_event(int sock, struct sockaddr_hci *addr,
240
bdaddr_p bdaddr)
241
{
242
link_key_p key = NULL;
243
244
syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \
245
"remote bdaddr %s", addr->hci_node,
246
bt_ntoa(bdaddr, NULL));
247
248
if ((key = get_key(bdaddr, 0)) != NULL) {
249
syslog(LOG_DEBUG, "Found matching entry, " \
250
"remote bdaddr %s, name '%s', link key %s",
251
bt_ntoa(&key->bdaddr, NULL),
252
(key->name != NULL)? key->name : "No name",
253
(key->key != NULL)? "exists" : "doesn't exist");
254
255
return (send_link_key_reply(sock, addr, bdaddr, key->key));
256
}
257
258
syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s",
259
bt_ntoa(bdaddr, NULL));
260
261
return (send_link_key_reply(sock, addr, bdaddr, NULL));
262
}
263
264
/* Send PIN_Code_[Negative]_Reply */
265
static int
266
send_pin_code_reply(int sock, struct sockaddr_hci *addr,
267
bdaddr_p bdaddr, char const *pin)
268
{
269
uint8_t buffer[HCSECD_BUFFER_SIZE];
270
ng_hci_cmd_pkt_t *cmd = NULL;
271
272
memset(buffer, 0, sizeof(buffer));
273
274
cmd = (ng_hci_cmd_pkt_t *) buffer;
275
cmd->type = NG_HCI_CMD_PKT;
276
277
if (pin != NULL) {
278
ng_hci_pin_code_rep_cp *cp = NULL;
279
280
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
281
NG_HCI_OCF_PIN_CODE_REP));
282
cmd->length = sizeof(*cp);
283
284
cp = (ng_hci_pin_code_rep_cp *)(cmd + 1);
285
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
286
strncpy((char *) cp->pin, pin, sizeof(cp->pin));
287
cp->pin_size = strlen((char const *) cp->pin);
288
289
syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \
290
"for remote bdaddr %s",
291
addr->hci_node, bt_ntoa(bdaddr, NULL));
292
} else {
293
ng_hci_pin_code_neg_rep_cp *cp = NULL;
294
295
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
296
NG_HCI_OCF_PIN_CODE_NEG_REP));
297
cmd->length = sizeof(*cp);
298
299
cp = (ng_hci_pin_code_neg_rep_cp *)(cmd + 1);
300
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
301
302
syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \
303
"for remote bdaddr %s",
304
addr->hci_node, bt_ntoa(bdaddr, NULL));
305
}
306
307
again:
308
if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
309
(struct sockaddr *) addr, sizeof(*addr)) < 0) {
310
if (errno == EINTR)
311
goto again;
312
313
syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \
314
"for remote bdaddr %s. %s (%d)",
315
addr->hci_node, bt_ntoa(bdaddr, NULL),
316
strerror(errno), errno);
317
return (-1);
318
}
319
320
return (0);
321
}
322
323
/* Send Link_Key_[Negative]_Reply */
324
static int
325
send_link_key_reply(int sock, struct sockaddr_hci *addr,
326
bdaddr_p bdaddr, uint8_t *key)
327
{
328
uint8_t buffer[HCSECD_BUFFER_SIZE];
329
ng_hci_cmd_pkt_t *cmd = NULL;
330
331
memset(buffer, 0, sizeof(buffer));
332
333
cmd = (ng_hci_cmd_pkt_t *) buffer;
334
cmd->type = NG_HCI_CMD_PKT;
335
336
if (key != NULL) {
337
ng_hci_link_key_rep_cp *cp = NULL;
338
339
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
340
NG_HCI_OCF_LINK_KEY_REP));
341
cmd->length = sizeof(*cp);
342
343
cp = (ng_hci_link_key_rep_cp *)(cmd + 1);
344
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
345
memcpy(&cp->key, key, sizeof(cp->key));
346
347
syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \
348
"for remote bdaddr %s",
349
addr->hci_node, bt_ntoa(bdaddr, NULL));
350
} else {
351
ng_hci_link_key_neg_rep_cp *cp = NULL;
352
353
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
354
NG_HCI_OCF_LINK_KEY_NEG_REP));
355
cmd->length = sizeof(*cp);
356
357
cp = (ng_hci_link_key_neg_rep_cp *)(cmd + 1);
358
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
359
360
syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \
361
"for remote bdaddr %s",
362
addr->hci_node, bt_ntoa(bdaddr, NULL));
363
}
364
365
again:
366
if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
367
(struct sockaddr *) addr, sizeof(*addr)) < 0) {
368
if (errno == EINTR)
369
goto again;
370
371
syslog(LOG_ERR, "Could not send link key reply to '%s' " \
372
"for remote bdaddr %s. %s (%d)",
373
addr->hci_node, bt_ntoa(bdaddr, NULL),
374
strerror(errno), errno);
375
return (-1);
376
}
377
378
return (0);
379
}
380
381
/* Process Link_Key_Notification event */
382
static int
383
process_link_key_notification_event(int sock, struct sockaddr_hci *addr,
384
ng_hci_link_key_notification_ep *ep)
385
{
386
link_key_p key = NULL;
387
388
syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \
389
"remote bdaddr %s", addr->hci_node,
390
bt_ntoa(&ep->bdaddr, NULL));
391
392
if ((key = get_key(&ep->bdaddr, 1)) == NULL) {
393
syslog(LOG_ERR, "Could not find entry for remote bdaddr %s",
394
bt_ntoa(&ep->bdaddr, NULL));
395
return (-1);
396
}
397
398
syslog(LOG_DEBUG, "Updating link key for the entry, " \
399
"remote bdaddr %s, name '%s', link key %s",
400
bt_ntoa(&key->bdaddr, NULL),
401
(key->name != NULL)? key->name : "No name",
402
(key->key != NULL)? "exists" : "doesn't exist");
403
404
if (key->key == NULL) {
405
key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE);
406
if (key->key == NULL) {
407
syslog(LOG_ERR, "Could not allocate link key");
408
exit(1);
409
}
410
}
411
412
memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE);
413
414
return (0);
415
}
416
417
/* Signal handlers */
418
static void
419
sighup(int s)
420
{
421
syslog(LOG_DEBUG, "Got SIGHUP (%d)", s);
422
423
dump_keys_file();
424
read_config_file();
425
read_keys_file();
426
}
427
428
static void
429
sigint(int s)
430
{
431
syslog(LOG_DEBUG, "Got signal %d, total number of signals %d",
432
s, ++ done);
433
}
434
435
/* Display usage and exit */
436
static void
437
usage(void)
438
{
439
fprintf(stderr,
440
"Usage: %s [-d] -f config_file [-h]\n" \
441
"Where:\n" \
442
"\t-d do not detach from terminal\n" \
443
"\t-f config_file use <config_file>\n" \
444
"\t-h display this message\n", HCSECD_IDENT);
445
446
exit(255);
447
}
448
449
450