mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-23 09:41:03 +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){
|
||||
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;
|
||||
uint8_t event = packet[0];
|
||||
@ -53,7 +53,7 @@ static void btstack_setup(){
|
||||
btstack_memory_init();
|
||||
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_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){
|
||||
log_info("hci_emit_security_level %u for handle %x", level, con_handle);
|
||||
uint8_t event[5];
|
||||
int pos = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
int hci_ssp_supported_on_both_sides(hci_con_handle_t handle){
|
||||
return hci_local_ssp_activated() && hci_remote_ssp_supported(handle);
|
||||
}
|
||||
|
||||
// GAP API
|
||||
/**
|
||||
* @bbrief enable/disable bonding. default is enabled
|
||||
|
@ -409,6 +409,10 @@ int hci_local_ssp_activated();
|
||||
// query if the remote side supports SSP
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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, ...){
|
||||
|
||||
@ -495,7 +499,7 @@ void l2cap_run(void){
|
||||
|
||||
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:
|
||||
if (channel->state_var & 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 (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
|
||||
// success, start l2cap handshake
|
||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
||||
channel->handle = handle;
|
||||
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;
|
||||
|
||||
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:
|
||||
handle = READ_BT_16(packet, 2);
|
||||
log_info("GAP_SECURITY_LEVEL");
|
||||
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
|
||||
channel = (l2cap_channel_t *) it;
|
||||
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;
|
||||
log_info("handle ok");
|
||||
if (channel->state != L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE) continue;
|
||||
log_info("state ok");
|
||||
if (actual_level >= channel->required_security_level){
|
||||
log_info("level ok");
|
||||
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
|
||||
l2cap_emit_connection_request(channel);
|
||||
} else {
|
||||
log_info("level nok");
|
||||
channel->reason = 0x03; // security block
|
||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE;
|
||||
switch (channel->state){
|
||||
case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE:
|
||||
log_info("gap incoming");
|
||||
if (actual_level >= channel->required_security_level){
|
||||
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
|
||||
l2cap_emit_connection_request(channel);
|
||||
} else {
|
||||
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;
|
||||
@ -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
|
||||
if (psm != PSM_SDP
|
||||
&& hci_local_ssp_activated()
|
||||
&& hci_remote_ssp_supported(handle)
|
||||
&& gap_security_level(handle) == LEVEL_3){
|
||||
if ( l2cap_security_level_0_allowed_for_PSM(psm)
|
||||
&& hci_ssp_supported_on_both_sides(handle)
|
||||
&& gap_security_level(handle) == LEVEL_0){
|
||||
|
||||
// 0x0003 Security Block
|
||||
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->packets_granted = 0;
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
// add to connections list
|
||||
@ -1258,8 +1293,8 @@ void l2cap_register_service_internal(void *connection, btstack_packet_handler_t
|
||||
service->mtu = mtu;
|
||||
service->connection = connection;
|
||||
service->packet_handler = packet_handler;
|
||||
service->security_level = security_level;
|
||||
|
||||
service->required_security_level = security_level;
|
||||
|
||||
// add to services list
|
||||
linked_list_add(&l2cap_services, (linked_item_t *) service);
|
||||
|
||||
|
@ -93,7 +93,9 @@ typedef enum {
|
||||
L2CAP_STATE_CLOSED = 1, // no baseband
|
||||
L2CAP_STATE_WILL_SEND_CREATE_CONNECTION,
|
||||
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_CONNECT_RSP, // from peer
|
||||
L2CAP_STATE_CONFIG,
|
||||
@ -180,7 +182,7 @@ typedef struct {
|
||||
btstack_packet_handler_t packet_handler;
|
||||
|
||||
// required security level
|
||||
gap_security_level_t security_level;
|
||||
gap_security_level_t required_security_level;
|
||||
} l2cap_service_t;
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user