📄 security.c
字号:
pinlen = read_pin_code(sba, dba, pin); if (pairing == HCID_PAIRING_ONCE) { struct link_key *key = get_link_key(sba, dba); if (key) { ba2str(dba, da); syslog(LOG_WARNING, "PIN code request for already paired device %s", da); goto reject; } } else if (pairing == HCID_PAIRING_NONE) goto reject; if (hcid.security == HCID_SEC_AUTO) { if (!ci->out) { /* Incomming connection */ memcpy(pr.pin_code, hcid.pin_code, hcid.pin_len); pr.pin_len = hcid.pin_len; hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); } else { /* Outgoing connection */ if (pinlen > 0) { memcpy(pr.pin_code, pin, pinlen); pr.pin_len = pinlen; hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); } else { /* Let PIN helper handle that */ request_pin(dev, sba, ci); } } } else { /* Let PIN helper handle that */ request_pin(dev, sba, ci); } free(cr); return;reject: hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); free(cr); return;}static inline void cmd_status(int dev, bdaddr_t *sba, void *ptr){ evt_cmd_status *evt = ptr; if (evt->status) return; if (evt->opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY)) hcid_dbus_inquiry_start(sba);}static inline void cmd_complete(int dev, bdaddr_t *sba, void *ptr){ evt_cmd_complete *evt = ptr; switch (evt->opcode) { case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL): hcid_dbus_inquiry_complete(sba); break; case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME): hcid_dbus_setname_complete(sba); break; case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): hcid_dbus_setscan_enable_complete(sba); };}static inline void remote_name_information(int dev, bdaddr_t *sba, void *ptr){ evt_remote_name_req_complete *evt = ptr; bdaddr_t dba; bacpy(&dba, &evt->bdaddr); if (!evt->status) { char name[249]; memset(name, 0, sizeof(name)); memcpy(name, evt->name, 248); write_device_name(sba, &dba, name); hcid_dbus_remote_name(sba, &dba, name); } else hcid_dbus_remote_name_failed(sba, &dba, evt->status);}static inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr){ evt_read_remote_version_complete *evt = ptr; bdaddr_t dba; if (evt->status) return; if (get_bdaddr(dev, sba, btohs(evt->handle), &dba) < 0) return; write_version_info(sba, &dba, btohs(evt->manufacturer), evt->lmp_ver, btohs(evt->lmp_subver));}static inline void inquiry_complete(int dev, bdaddr_t *sba, void *ptr){ hcid_dbus_inquiry_complete(sba);}static inline void inquiry_result(int dev, bdaddr_t *sba, int plen, void *ptr){ uint8_t num = *(uint8_t *) ptr++; int i; for (i = 0; i < num; i++) { inquiry_info *info = ptr; uint32_t class = info->dev_class[0] | (info->dev_class[1] << 8) | (info->dev_class[2] << 16); hcid_dbus_inquiry_result(sba, &info->bdaddr, class, 0); ptr += INQUIRY_INFO_SIZE; }}static inline void inquiry_result_with_rssi(int dev, bdaddr_t *sba, int plen, void *ptr){ uint8_t num = *(uint8_t *) ptr++; int i; if (!num) return; if ((plen - 1) / num == INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE) { for (i = 0; i < num; i++) { inquiry_info_with_rssi_and_pscan_mode *info = ptr; uint32_t class = info->dev_class[0] | (info->dev_class[1] << 8) | (info->dev_class[2] << 16); hcid_dbus_inquiry_result(sba, &info->bdaddr, class, info->rssi); ptr += INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE; } } else { for (i = 0; i < num; i++) { inquiry_info_with_rssi *info = ptr; uint32_t class = info->dev_class[0] | (info->dev_class[1] << 8) | (info->dev_class[2] << 16); hcid_dbus_inquiry_result(sba, &info->bdaddr, class, info->rssi); ptr += INQUIRY_INFO_WITH_RSSI_SIZE; } }}static inline void extended_inquiry_result(int dev, bdaddr_t *sba, int plen, void *ptr){ uint8_t num = *(uint8_t *) ptr++; int i; for (i = 0; i < num; i++) { extended_inquiry_info *info = ptr; uint32_t class = info->dev_class[0] | (info->dev_class[1] << 8) | (info->dev_class[2] << 16); hcid_dbus_inquiry_result(sba, &info->bdaddr, class, info->rssi); ptr += EXTENDED_INQUIRY_INFO_SIZE; }}static inline void remote_features_information(int dev, bdaddr_t *sba, void *ptr){ evt_read_remote_features_complete *evt = ptr; bdaddr_t dba; if (evt->status) return; if (get_bdaddr(dev, sba, btohs(evt->handle), &dba) < 0) return; write_features_info(sba, &dba, evt->features);}static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr){ evt_conn_complete *evt = ptr; if (evt->status) return; hcid_dbus_conn_complete(sba, &evt->bdaddr);}static inline void disconn_complete(int dev, bdaddr_t *sba, void *ptr){ evt_disconn_complete *evt = ptr; bdaddr_t dba; if (evt->status) return; bacpy(&dba, BDADDR_ANY); hcid_dbus_disconn_complete(sba, &dba, evt->reason);}static inline void auth_complete(int dev, bdaddr_t *sba, void *ptr){ evt_auth_complete *evt = ptr; bdaddr_t dba; if (get_bdaddr(dev, sba, evt->handle, &dba) < 0) return; hcid_dbus_auth_complete(sba, &dba, evt->status);}static gboolean io_security_event(GIOChannel *chan, GIOCondition cond, gpointer data){ unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf; struct hci_dev_info *di = (void *) data; int type, dev; size_t len; hci_event_hdr *eh; GIOError err; if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { g_io_channel_close(chan); free(data); return FALSE; } if ((err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len))) { if (err == G_IO_ERROR_AGAIN) return TRUE; g_io_channel_close(chan); free(data); return FALSE; } type = *ptr++; if (type != HCI_EVENT_PKT) return TRUE; eh = (hci_event_hdr *) ptr; ptr += HCI_EVENT_HDR_SIZE; dev = g_io_channel_unix_get_fd(chan); ioctl(dev, HCIGETDEVINFO, (void *) di); if (hci_test_bit(HCI_RAW, &di->flags)) return TRUE; switch (eh->evt) { case EVT_CMD_STATUS: cmd_status(dev, &di->bdaddr, ptr); break; case EVT_CMD_COMPLETE: cmd_complete(dev, &di->bdaddr, ptr); break; case EVT_REMOTE_NAME_REQ_COMPLETE: remote_name_information(dev, &di->bdaddr, ptr); break; case EVT_READ_REMOTE_VERSION_COMPLETE: remote_version_information(dev, &di->bdaddr, ptr); break; case EVT_READ_REMOTE_FEATURES_COMPLETE: remote_features_information(dev, &di->bdaddr, ptr); break; case EVT_INQUIRY_COMPLETE: inquiry_complete(dev, &di->bdaddr, ptr); break; case EVT_INQUIRY_RESULT: inquiry_result(dev, &di->bdaddr, eh->plen, ptr); break; case EVT_INQUIRY_RESULT_WITH_RSSI: inquiry_result_with_rssi(dev, &di->bdaddr, eh->plen, ptr); break; case EVT_EXTENDED_INQUIRY_RESULT: extended_inquiry_result(dev, &di->bdaddr, eh->plen, ptr); break; case EVT_CONN_COMPLETE: conn_complete(dev, &di->bdaddr, ptr); break; case EVT_DISCONN_COMPLETE: disconn_complete(dev, &di->bdaddr, ptr); break; case EVT_AUTH_COMPLETE: auth_complete(dev, &di->bdaddr, ptr); break; } if (hci_test_bit(HCI_SECMGR, &di->flags)) return TRUE; switch (eh->evt) { case EVT_PIN_CODE_REQ: pin_code_request(dev, &di->bdaddr, (bdaddr_t *) ptr); break; case EVT_LINK_KEY_REQ: link_key_request(dev, &di->bdaddr, (bdaddr_t *) ptr); break; case EVT_LINK_KEY_NOTIFY: link_key_notify(dev, &di->bdaddr, ptr); break; case EVT_RETURN_LINK_KEYS: return_link_keys(dev, &di->bdaddr, ptr); break; } return TRUE;}void start_security_manager(int hdev){ GIOChannel *chan = io_chan[hdev]; struct hci_dev_info *di; struct hci_filter flt; read_stored_link_key_cp cp; int dev; if (chan) return; syslog(LOG_INFO, "Starting security manager %d", hdev); if ((dev = hci_open_dev(hdev)) < 0) { syslog(LOG_ERR, "Can't open device hci%d: %s (%d)", hdev, strerror(errno), errno); return; } /* Set filter */ hci_filter_clear(&flt); hci_filter_set_ptype(HCI_EVENT_PKT, &flt); hci_filter_set_event(EVT_CMD_STATUS, &flt); hci_filter_set_event(EVT_CMD_COMPLETE, &flt); hci_filter_set_event(EVT_PIN_CODE_REQ, &flt); hci_filter_set_event(EVT_LINK_KEY_REQ, &flt); hci_filter_set_event(EVT_LINK_KEY_NOTIFY, &flt); hci_filter_set_event(EVT_RETURN_LINK_KEYS, &flt); hci_filter_set_event(EVT_REMOTE_NAME_REQ_COMPLETE, &flt); hci_filter_set_event(EVT_READ_REMOTE_VERSION_COMPLETE, &flt); hci_filter_set_event(EVT_READ_REMOTE_FEATURES_COMPLETE, &flt); hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT, &flt); hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt); hci_filter_set_event(EVT_EXTENDED_INQUIRY_RESULT, &flt); hci_filter_set_event(EVT_CONN_COMPLETE, &flt); hci_filter_set_event(EVT_DISCONN_COMPLETE, &flt); hci_filter_set_event(EVT_AUTH_COMPLETE, &flt); if (setsockopt(dev, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { syslog(LOG_ERR, "Can't set filter on hci%d: %s (%d)", hdev, strerror(errno), errno); close(dev); return; } di = malloc(sizeof(*di)); if (!di) { syslog(LOG_ERR, "Can't allocate device info buffer: %s (%d)", strerror(errno), errno); close(dev); return; } di->dev_id = hdev; if (ioctl(dev, HCIGETDEVINFO, (void *)di)) { syslog(LOG_ERR, "Can't get device info: %s (%d)", strerror(errno), errno); close(dev); return; } chan = g_io_channel_unix_new(dev); g_io_add_watch(chan, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, io_security_event, (void *) di); io_chan[hdev] = chan; if (hci_test_bit(HCI_RAW, &di->flags)) return; bacpy(&cp.bdaddr, BDADDR_ANY); cp.read_all = 1; hci_send_cmd(dev, OGF_HOST_CTL, OCF_READ_STORED_LINK_KEY, READ_STORED_LINK_KEY_CP_SIZE, (void *) &cp);}void stop_security_manager(int hdev){ GIOChannel *chan = io_chan[hdev]; if (!chan) return; syslog(LOG_INFO, "Stoping security manager %d", hdev); /* this is a bit sneaky. closing the fd will cause the event loop to call us right back with G_IO_NVAL set, at which point we will see it and clean things up */ close(g_io_channel_unix_get_fd(chan)); io_chan[hdev] = NULL;}void init_security_data(void){ /* Set local PIN code */ if (read_default_pin_code() < 0) { strcpy((char *) hcid.pin_code, "BlueZ"); hcid.pin_len = 5; } pairing = hcid.pairing;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -