4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
30 * $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $
34 #include <sys/queue.h>
35 #define L2CAP_SOCKET_CHECKED
36 #include <bluetooth.h>
50 static int process_pin_code_request_event
51 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
52 static int process_link_key_request_event
53 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
54 static int send_pin_code_reply
55 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
56 static int send_link_key_reply
57 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, uint8_t *key);
58 static int process_link_key_notification_event
59 (int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep);
69 main(int argc, char *argv[])
74 struct sockaddr_hci addr;
75 struct ng_btsocket_hci_raw_filter filter;
76 char buffer[HCSECD_BUFFER_SIZE];
77 ng_hci_event_pkt_t *event = NULL;
81 while ((n = getopt(argc, argv, "df:h")) != -1) {
98 if (config_file == NULL)
103 errx(1, "** ERROR: You should run %s as privileged user!",
106 /* Set signal handlers */
107 memset(&sa, 0, sizeof(sa));
108 sa.sa_handler = sigint;
109 sa.sa_flags = SA_NOCLDWAIT;
110 if (sigaction(SIGINT, &sa, NULL) < 0)
111 err(1, "Could not sigaction(SIGINT)");
112 if (sigaction(SIGTERM, &sa, NULL) < 0)
113 err(1, "Could not sigaction(SIGINT)");
115 memset(&sa, 0, sizeof(sa));
116 sa.sa_handler = sighup;
117 if (sigaction(SIGHUP, &sa, NULL) < 0)
118 err(1, "Could not sigaction(SIGHUP)");
120 /* Open socket and set filter */
121 sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
123 err(1, "Could not create HCI socket");
125 memset(&filter, 0, sizeof(filter));
126 bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
127 bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
128 bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
130 if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
131 (void * const) &filter, sizeof(filter)) < 0)
132 err(1, "Could not set HCI socket filter");
134 if (detach && daemon(0, 0) < 0)
135 err(1, "Could not daemon()ize");
137 openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
145 if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
146 syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
147 HCSECD_PIDFILE, strerror(errno), errno);
151 fprintf(pid, "%d", getpid());
155 event = (ng_hci_event_pkt_t *) buffer;
158 n = recvfrom(sock, buffer, sizeof(buffer), 0,
159 (struct sockaddr *) &addr, &size);
164 syslog(LOG_ERR, "Could not receive from HCI socket. " \
165 "%s (%d)", strerror(errno), errno);
169 if (event->type != NG_HCI_EVENT_PKT) {
170 syslog(LOG_ERR, "Received unexpected HCI packet, " \
171 "type=%#x", event->type);
175 switch (event->event) {
176 case NG_HCI_EVENT_PIN_CODE_REQ:
177 process_pin_code_request_event(sock, &addr,
178 (bdaddr_p)(event + 1));
181 case NG_HCI_EVENT_LINK_KEY_REQ:
182 process_link_key_request_event(sock, &addr,
183 (bdaddr_p)(event + 1));
186 case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
187 process_link_key_notification_event(sock, &addr,
188 (ng_hci_link_key_notification_ep *)(event + 1));
192 syslog(LOG_ERR, "Received unexpected HCI event, " \
193 "event=%#x", event->event);
199 if (remove(HCSECD_PIDFILE) < 0)
200 syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
201 HCSECD_PIDFILE, strerror(errno), errno);
211 /* Process PIN_Code_Request event */
213 process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
216 link_key_p key = NULL;
218 syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \
219 "remote bdaddr %s", addr->hci_node,
220 bt_ntoa(bdaddr, NULL));
222 if ((key = get_key(bdaddr, 0)) != NULL) {
223 syslog(LOG_DEBUG, "Found matching entry, " \
224 "remote bdaddr %s, name '%s', PIN code %s",
225 bt_ntoa(&key->bdaddr, NULL),
226 (key->name != NULL)? key->name : "No name",
227 (key->pin != NULL)? "exists" : "doesn't exist");
229 return (send_pin_code_reply(sock, addr, bdaddr, key->pin));
232 syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s",
233 bt_ntoa(bdaddr, NULL));
235 return (send_pin_code_reply(sock, addr, bdaddr, NULL));
238 /* Process Link_Key_Request event */
240 process_link_key_request_event(int sock, struct sockaddr_hci *addr,
243 link_key_p key = NULL;
245 syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \
246 "remote bdaddr %s", addr->hci_node,
247 bt_ntoa(bdaddr, NULL));
249 if ((key = get_key(bdaddr, 0)) != NULL) {
250 syslog(LOG_DEBUG, "Found matching entry, " \
251 "remote bdaddr %s, name '%s', link key %s",
252 bt_ntoa(&key->bdaddr, NULL),
253 (key->name != NULL)? key->name : "No name",
254 (key->key != NULL)? "exists" : "doesn't exist");
256 return (send_link_key_reply(sock, addr, bdaddr, key->key));
259 syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s",
260 bt_ntoa(bdaddr, NULL));
262 return (send_link_key_reply(sock, addr, bdaddr, NULL));
265 /* Send PIN_Code_[Negative]_Reply */
267 send_pin_code_reply(int sock, struct sockaddr_hci *addr,
268 bdaddr_p bdaddr, char const *pin)
270 uint8_t buffer[HCSECD_BUFFER_SIZE];
271 ng_hci_cmd_pkt_t *cmd = NULL;
273 memset(buffer, 0, sizeof(buffer));
275 cmd = (ng_hci_cmd_pkt_t *) buffer;
276 cmd->type = NG_HCI_CMD_PKT;
279 ng_hci_pin_code_rep_cp *cp = NULL;
281 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
282 NG_HCI_OCF_PIN_CODE_REP));
283 cmd->length = sizeof(*cp);
285 cp = (ng_hci_pin_code_rep_cp *)(cmd + 1);
286 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
287 strncpy((char *) cp->pin, pin, sizeof(cp->pin));
288 cp->pin_size = strlen((char const *) cp->pin);
290 syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \
291 "for remote bdaddr %s",
292 addr->hci_node, bt_ntoa(bdaddr, NULL));
294 ng_hci_pin_code_neg_rep_cp *cp = NULL;
296 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
297 NG_HCI_OCF_PIN_CODE_NEG_REP));
298 cmd->length = sizeof(*cp);
300 cp = (ng_hci_pin_code_neg_rep_cp *)(cmd + 1);
301 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
303 syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \
304 "for remote bdaddr %s",
305 addr->hci_node, bt_ntoa(bdaddr, NULL));
309 if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
310 (struct sockaddr *) addr, sizeof(*addr)) < 0) {
314 syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \
315 "for remote bdaddr %s. %s (%d)",
316 addr->hci_node, bt_ntoa(bdaddr, NULL),
317 strerror(errno), errno);
324 /* Send Link_Key_[Negative]_Reply */
326 send_link_key_reply(int sock, struct sockaddr_hci *addr,
327 bdaddr_p bdaddr, uint8_t *key)
329 uint8_t buffer[HCSECD_BUFFER_SIZE];
330 ng_hci_cmd_pkt_t *cmd = NULL;
332 memset(buffer, 0, sizeof(buffer));
334 cmd = (ng_hci_cmd_pkt_t *) buffer;
335 cmd->type = NG_HCI_CMD_PKT;
338 ng_hci_link_key_rep_cp *cp = NULL;
340 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
341 NG_HCI_OCF_LINK_KEY_REP));
342 cmd->length = sizeof(*cp);
344 cp = (ng_hci_link_key_rep_cp *)(cmd + 1);
345 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
346 memcpy(&cp->key, key, sizeof(cp->key));
348 syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \
349 "for remote bdaddr %s",
350 addr->hci_node, bt_ntoa(bdaddr, NULL));
352 ng_hci_link_key_neg_rep_cp *cp = NULL;
354 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
355 NG_HCI_OCF_LINK_KEY_NEG_REP));
356 cmd->length = sizeof(*cp);
358 cp = (ng_hci_link_key_neg_rep_cp *)(cmd + 1);
359 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
361 syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \
362 "for remote bdaddr %s",
363 addr->hci_node, bt_ntoa(bdaddr, NULL));
367 if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
368 (struct sockaddr *) addr, sizeof(*addr)) < 0) {
372 syslog(LOG_ERR, "Could not send link key reply to '%s' " \
373 "for remote bdaddr %s. %s (%d)",
374 addr->hci_node, bt_ntoa(bdaddr, NULL),
375 strerror(errno), errno);
382 /* Process Link_Key_Notification event */
384 process_link_key_notification_event(int sock, struct sockaddr_hci *addr,
385 ng_hci_link_key_notification_ep *ep)
387 link_key_p key = NULL;
389 syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \
390 "remote bdaddr %s", addr->hci_node,
391 bt_ntoa(&ep->bdaddr, NULL));
393 if ((key = get_key(&ep->bdaddr, 1)) == NULL) {
394 syslog(LOG_ERR, "Could not find entry for remote bdaddr %s",
395 bt_ntoa(&ep->bdaddr, NULL));
399 syslog(LOG_DEBUG, "Updating link key for the entry, " \
400 "remote bdaddr %s, name '%s', link key %s",
401 bt_ntoa(&key->bdaddr, NULL),
402 (key->name != NULL)? key->name : "No name",
403 (key->key != NULL)? "exists" : "doesn't exist");
405 if (key->key == NULL) {
406 key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE);
407 if (key->key == NULL) {
408 syslog(LOG_ERR, "Could not allocate link key");
413 memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE);
418 /* Signal handlers */
422 syslog(LOG_DEBUG, "Got SIGHUP (%d)", s);
432 syslog(LOG_DEBUG, "Got signal %d, total number of signals %d",
436 /* Display usage and exit */
441 "Usage: %s [-d] -f config_file [-h]\n" \
443 "\t-d do not detach from terminal\n" \
444 "\t-f config_file use <config_file>\n" \
445 "\t-h display this message\n", HCSECD_IDENT);