mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-23 18:39:52 +00:00
if both devices support SSP, initiator shall setup unauthenticated link unless connecting to SDP
This commit is contained in:
parent
f01ad3fb0d
commit
df3354fc67
@ -31,7 +31,7 @@ static char* service_name[10];
|
|||||||
|
|
||||||
|
|
||||||
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
|
// printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
|
||||||
|
|
||||||
if (packet_type != HCI_EVENT_PACKET) return;
|
if (packet_type != HCI_EVENT_PACKET) return;
|
||||||
uint8_t event = packet[0];
|
uint8_t event = packet[0];
|
||||||
@ -53,7 +53,7 @@ static void btstack_setup(){
|
|||||||
btstack_memory_init();
|
btstack_memory_init();
|
||||||
run_loop_init(RUN_LOOP_POSIX);
|
run_loop_init(RUN_LOOP_POSIX);
|
||||||
|
|
||||||
hci_dump_open("/tmp/hci_dump_sdp_rfcomm_query.pklg", HCI_DUMP_PACKETLOGGER);
|
hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
|
||||||
|
|
||||||
hci_transport_t * transport = hci_transport_usb_instance();
|
hci_transport_t * transport = hci_transport_usb_instance();
|
||||||
hci_uart_config_t * config = NULL;
|
hci_uart_config_t * config = NULL;
|
||||||
|
@ -1746,6 +1746,7 @@ void hci_emit_discoverable_enabled(uint8_t enabled){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){
|
void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){
|
||||||
|
log_info("hci_emit_security_level %u for handle %x", level, con_handle);
|
||||||
uint8_t event[5];
|
uint8_t event[5];
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
event[pos++] = GAP_SECURITY_LEVEL;
|
event[pos++] = GAP_SECURITY_LEVEL;
|
||||||
@ -1764,6 +1765,10 @@ int hci_remote_ssp_supported(hci_con_handle_t con_handle){
|
|||||||
return (connection->bonding_flags & BONDING_REMOTE_SUPPORTS_SSP) ? 1 : 0;
|
return (connection->bonding_flags & BONDING_REMOTE_SUPPORTS_SSP) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hci_ssp_supported_on_both_sides(hci_con_handle_t handle){
|
||||||
|
return hci_local_ssp_activated() && hci_remote_ssp_supported(handle);
|
||||||
|
}
|
||||||
|
|
||||||
// GAP API
|
// GAP API
|
||||||
/**
|
/**
|
||||||
* @bbrief enable/disable bonding. default is enabled
|
* @bbrief enable/disable bonding. default is enabled
|
||||||
|
@ -409,6 +409,10 @@ int hci_local_ssp_activated();
|
|||||||
// query if the remote side supports SSP
|
// query if the remote side supports SSP
|
||||||
int hci_remote_ssp_supported(hci_con_handle_t con_handle);
|
int hci_remote_ssp_supported(hci_con_handle_t con_handle);
|
||||||
|
|
||||||
|
// query if both sides support SSP
|
||||||
|
int hci_ssp_supported_on_both_sides(hci_con_handle_t handle);
|
||||||
|
|
||||||
|
|
||||||
// disconnect because of security block
|
// disconnect because of security block
|
||||||
void hci_disconnect_security_block(hci_con_handle_t con_handle);
|
void hci_disconnect_security_block(hci_con_handle_t con_handle);
|
||||||
|
|
||||||
|
79
src/l2cap.c
79
src/l2cap.c
@ -286,6 +286,10 @@ static void l2cap_start_ertx(l2cap_channel_t * channel){
|
|||||||
run_loop_add_timer(&channel->rtx);
|
run_loop_add_timer(&channel->rtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l2cap_security_level_0_allowed_for_PSM(uint16_t psm){
|
||||||
|
// return 0; // TESTING!
|
||||||
|
return psm != PSM_SDP;
|
||||||
|
}
|
||||||
|
|
||||||
int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
|
int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
|
||||||
|
|
||||||
@ -495,7 +499,7 @@ void l2cap_run(void){
|
|||||||
|
|
||||||
switch (channel->state){
|
switch (channel->state){
|
||||||
|
|
||||||
case L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE:
|
case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE:
|
||||||
case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT:
|
case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT:
|
||||||
if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND) {
|
if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND) {
|
||||||
channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND);
|
channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND);
|
||||||
@ -670,9 +674,10 @@ static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_
|
|||||||
if ( ! BD_ADDR_CMP( channel->address, address) ){
|
if ( ! BD_ADDR_CMP( channel->address, address) ){
|
||||||
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
|
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
|
||||||
// success, start l2cap handshake
|
// success, start l2cap handshake
|
||||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
|
||||||
channel->handle = handle;
|
channel->handle = handle;
|
||||||
channel->local_cid = l2cap_next_local_cid();
|
channel->local_cid = l2cap_next_local_cid();
|
||||||
|
// check remote SSP feature first
|
||||||
|
channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,24 +776,55 @@ void l2cap_event_handler( uint8_t *packet, uint16_t size ){
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
|
||||||
|
handle = READ_BT_16(packet, 3);
|
||||||
|
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
|
||||||
|
channel = (l2cap_channel_t *) it;
|
||||||
|
if (channel->handle != handle) continue;
|
||||||
|
if (channel->state != L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) continue;
|
||||||
|
// we have been waiting for remote supported features, if both support SSP,
|
||||||
|
if (hci_ssp_supported_on_both_sides(channel->handle) && !l2cap_security_level_0_allowed_for_PSM(channel->psm)){
|
||||||
|
// request security level 2
|
||||||
|
gap_request_security_level(channel->handle, LEVEL_2);
|
||||||
|
channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// fine, go ahead
|
||||||
|
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case GAP_SECURITY_LEVEL:
|
case GAP_SECURITY_LEVEL:
|
||||||
handle = READ_BT_16(packet, 2);
|
handle = READ_BT_16(packet, 2);
|
||||||
|
log_info("GAP_SECURITY_LEVEL");
|
||||||
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
|
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
|
||||||
channel = (l2cap_channel_t *) it;
|
channel = (l2cap_channel_t *) it;
|
||||||
gap_security_level_t actual_level = packet[4];
|
gap_security_level_t actual_level = packet[4];
|
||||||
log_info("GAP_SECURITY_LEVEL handle %x/%x level %u, state %u", handle, channel->handle, actual_level, channel->state);
|
|
||||||
if (channel->handle != handle) continue;
|
if (channel->handle != handle) continue;
|
||||||
log_info("handle ok");
|
switch (channel->state){
|
||||||
if (channel->state != L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE) continue;
|
case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE:
|
||||||
log_info("state ok");
|
log_info("gap incoming");
|
||||||
if (actual_level >= channel->required_security_level){
|
if (actual_level >= channel->required_security_level){
|
||||||
log_info("level ok");
|
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
|
||||||
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
|
l2cap_emit_connection_request(channel);
|
||||||
l2cap_emit_connection_request(channel);
|
} else {
|
||||||
} else {
|
channel->reason = 0x03; // security block
|
||||||
log_info("level nok");
|
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE;
|
||||||
channel->reason = 0x03; // security block
|
}
|
||||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE;
|
break;
|
||||||
|
|
||||||
|
case L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE:
|
||||||
|
log_info("gap outgoing");
|
||||||
|
if (actual_level >= channel->required_security_level){
|
||||||
|
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
||||||
|
} else {
|
||||||
|
// disconnnect, authentication not good enough
|
||||||
|
hci_disconnect_security_block(handle);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -837,10 +873,9 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reject connection (0x03 security block) and disconnect if both have SSP, connection is not encrypted and PSM != SDP
|
// reject connection (0x03 security block) and disconnect if both have SSP, connection is not encrypted and PSM != SDP
|
||||||
if (psm != PSM_SDP
|
if ( l2cap_security_level_0_allowed_for_PSM(psm)
|
||||||
&& hci_local_ssp_activated()
|
&& hci_ssp_supported_on_both_sides(handle)
|
||||||
&& hci_remote_ssp_supported(handle)
|
&& gap_security_level(handle) == LEVEL_0){
|
||||||
&& gap_security_level(handle) == LEVEL_3){
|
|
||||||
|
|
||||||
// 0x0003 Security Block
|
// 0x0003 Security Block
|
||||||
l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0003);
|
l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0003);
|
||||||
@ -869,7 +904,7 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
|
|||||||
channel->remote_mtu = L2CAP_DEFAULT_MTU;
|
channel->remote_mtu = L2CAP_DEFAULT_MTU;
|
||||||
channel->packets_granted = 0;
|
channel->packets_granted = 0;
|
||||||
channel->remote_sig_id = sig_id;
|
channel->remote_sig_id = sig_id;
|
||||||
channel->required_security_level = LEVEL_0; // @TODO get from 'security database'
|
channel->required_security_level = service->required_security_level;
|
||||||
|
|
||||||
// limit local mtu to max acl packet length
|
// limit local mtu to max acl packet length
|
||||||
if (channel->local_mtu > l2cap_max_mtu()) {
|
if (channel->local_mtu > l2cap_max_mtu()) {
|
||||||
@ -877,7 +912,7 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set initial state
|
// set initial state
|
||||||
channel->state = L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE;
|
channel->state = L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE;
|
||||||
channel->state_var = L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND;
|
channel->state_var = L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND;
|
||||||
|
|
||||||
// add to connections list
|
// add to connections list
|
||||||
@ -1258,8 +1293,8 @@ void l2cap_register_service_internal(void *connection, btstack_packet_handler_t
|
|||||||
service->mtu = mtu;
|
service->mtu = mtu;
|
||||||
service->connection = connection;
|
service->connection = connection;
|
||||||
service->packet_handler = packet_handler;
|
service->packet_handler = packet_handler;
|
||||||
service->security_level = security_level;
|
service->required_security_level = security_level;
|
||||||
|
|
||||||
// add to services list
|
// add to services list
|
||||||
linked_list_add(&l2cap_services, (linked_item_t *) service);
|
linked_list_add(&l2cap_services, (linked_item_t *) service);
|
||||||
|
|
||||||
|
@ -93,7 +93,9 @@ typedef enum {
|
|||||||
L2CAP_STATE_CLOSED = 1, // no baseband
|
L2CAP_STATE_CLOSED = 1, // no baseband
|
||||||
L2CAP_STATE_WILL_SEND_CREATE_CONNECTION,
|
L2CAP_STATE_WILL_SEND_CREATE_CONNECTION,
|
||||||
L2CAP_STATE_WAIT_CONNECTION_COMPLETE,
|
L2CAP_STATE_WAIT_CONNECTION_COMPLETE,
|
||||||
L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE,
|
L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES,
|
||||||
|
L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE,
|
||||||
|
L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE,
|
||||||
L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT,
|
L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT,
|
||||||
L2CAP_STATE_WAIT_CONNECT_RSP, // from peer
|
L2CAP_STATE_WAIT_CONNECT_RSP, // from peer
|
||||||
L2CAP_STATE_CONFIG,
|
L2CAP_STATE_CONFIG,
|
||||||
@ -180,7 +182,7 @@ typedef struct {
|
|||||||
btstack_packet_handler_t packet_handler;
|
btstack_packet_handler_t packet_handler;
|
||||||
|
|
||||||
// required security level
|
// required security level
|
||||||
gap_security_level_t security_level;
|
gap_security_level_t required_security_level;
|
||||||
} l2cap_service_t;
|
} l2cap_service_t;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user