android/socket: Fix sockets security

Socket security shall be based on flags passed from HAL.

Android public API uses both encrypt and auth flags for "secure"
sockets which should be mapped to high security on our side, but since
this would also trigger requirement for 16-digits pin code (which is
not used in Android) we'll ignore auth flag and use either low or
medium security based on encrypt flag value only.
This commit is contained in:
Andrzej Kaczmarek 2014-02-11 17:58:21 +01:00 committed by Szymon Janc
parent 4e3ad171df
commit 968be4037c
2 changed files with 22 additions and 10 deletions

View File

@ -235,6 +235,9 @@ struct hal_cmd_le_test_mode {
#define HAL_SOCK_SCO 0x02
#define HAL_SOCK_L2CAP 0x03
#define HAL_SOCK_FLAG_ENCRYPT 0x01
#define HAL_SOCK_FLAG_AUTH 0x02
#define HAL_OP_SOCK_LISTEN 0x01
struct hal_cmd_sock_listen {
uint8_t type;

View File

@ -70,6 +70,7 @@ GList *connections = NULL;
struct rfcomm_sock {
int channel; /* RFCOMM channel */
BtIOSecLevel sec_level;
/* for socket to BT */
int bt_sock;
@ -84,8 +85,6 @@ struct rfcomm_sock {
uint8_t *buf;
int buf_size;
const struct profile_info *profile;
};
struct rfcomm_channel {
@ -721,6 +720,19 @@ static int find_free_channel(void)
return 0;
}
static BtIOSecLevel get_sec_level(uint8_t flags)
{
/* HAL_SOCK_FLAG_AUTH should require MITM but in our case setting
* security to BT_IO_SEC_HIGH would also require 16-digits PIN code
* for pre-2.1 devices which is not what Android expects. For this
* reason we ignore this flag to not break apps which use "secure"
* sockets (have both auth and encrypt flags set, there is no public
* API in Android which should provide proper high security socket).
*/
return flags & HAL_SOCK_FLAG_ENCRYPT ? BT_IO_SEC_MEDIUM :
BT_IO_SEC_LOW;
}
static uint8_t rfcomm_listen(int chan, const uint8_t *name, const uint8_t *uuid,
uint8_t flags, int *hal_sock)
{
@ -748,7 +760,7 @@ static uint8_t rfcomm_listen(int chan, const uint8_t *name, const uint8_t *uuid,
profile = get_profile_by_uuid(uuid);
if (!profile) {
sec_level = BT_IO_SEC_MEDIUM;
sec_level = get_sec_level(flags);
} else {
if (!profile->create_record)
return HAL_STATUS_INVALID;
@ -931,20 +943,16 @@ fail:
static bool do_rfcomm_connect(struct rfcomm_sock *rfsock, int chan)
{
BtIOSecLevel sec_level = BT_IO_SEC_MEDIUM;
GIOChannel *io;
GError *gerr = NULL;
if (rfsock->profile)
sec_level = rfsock->profile->sec_level;
DBG("rfsock %p sec_level %d chan %d", rfsock, sec_level, chan);
DBG("rfsock %p sec_level %d chan %d", rfsock, rfsock->sec_level, chan);
io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
BT_IO_OPT_CHANNEL, chan,
BT_IO_OPT_SEC_LEVEL, sec_level,
BT_IO_OPT_SEC_LEVEL, rfsock->sec_level,
BT_IO_OPT_INVALID);
if (!io) {
error("Failed connect: %s", gerr->message);
@ -1047,13 +1055,14 @@ static uint8_t connect_rfcomm(const bdaddr_t *addr, int chan,
DBG("rfsock %p jv_sock %d hal_sock %d", rfsock, rfsock->jv_sock,
*hal_sock);
rfsock->sec_level = get_sec_level(flags);
bacpy(&rfsock->dst, addr);
if (!memcmp(uuid, zero_uuid, sizeof(zero_uuid))) {
if (!do_rfcomm_connect(rfsock, chan))
goto failed;
} else {
rfsock->profile = get_profile_by_uuid(uuid);
if (bt_search_service(&adapter_addr, &rfsock->dst, &uu,
sdp_search_cb, rfsock, NULL, 0) < 0) {