1 /******************************************************************************
2  *
3  *  Copyright 2014 The Android Open Source Project
4  *  Copyright 2003-2012 Broadcom Corporation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 
20 /******************************************************************************
21  *
22  *  This file contains the audio gateway functions performing SDP
23  *  operations.
24  *
25  ******************************************************************************/
26 
27 #include <bluetooth/log.h>
28 #include <com_android_bluetooth_flags.h>
29 
30 #include <cstddef>
31 #include <cstdint>
32 #include <cstring>
33 
34 #include "bta/hf_client/bta_hf_client_int.h"
35 #include "bta/include/bta_hf_client_api.h"
36 #include "bta/include/bta_rfcomm_scn.h"
37 #include "bta/sys/bta_sys.h"
38 #include "bta_hfp_api.h"
39 #include "common/bind.h"
40 #include "internal_include/bt_target.h"
41 #include "osi/include/allocator.h"
42 #include "sdp_status.h"
43 #include "stack/include/bt_types.h"
44 #include "stack/include/bt_uuid16.h"
45 #include "stack/include/sdp_api.h"
46 #include "stack/include/sdpdefs.h"
47 #include "stack/sdp/sdp_discovery_db.h"
48 #include "types/bluetooth/uuid.h"
49 #include "types/raw_address.h"
50 
51 using bluetooth::Uuid;
52 using namespace bluetooth::legacy::stack::sdp;
53 using namespace bluetooth;
54 
55 /* Number of protocol elements in protocol element list. */
56 #define BTA_HF_CLIENT_NUM_PROTO_ELEMS 2
57 
58 /* Number of elements in service class id list. */
59 #define BTA_HF_CLIENT_NUM_SVC_ELEMS 2
60 
61 /*******************************************************************************
62  *
63  * Function         bta_hf_client_sdp_cback
64  *
65  * Description      SDP callback function.
66  *
67  *
68  * Returns          void
69  *
70  ******************************************************************************/
bta_hf_client_sdp_cback(tBTA_HF_CLIENT_CB * client_cb,const RawAddress &,tSDP_STATUS status)71 static void bta_hf_client_sdp_cback(tBTA_HF_CLIENT_CB* client_cb, const RawAddress& /* bd_addr */,
72                                     tSDP_STATUS status) {
73   uint16_t event;
74   tBTA_HF_CLIENT_DISC_RESULT* p_buf =
75           (tBTA_HF_CLIENT_DISC_RESULT*)osi_malloc(sizeof(tBTA_HF_CLIENT_DISC_RESULT));
76 
77   log::verbose("bta_hf_client_sdp_cback status:0x{:x}", status);
78 
79   /* set event according to int/acp */
80   if (client_cb->role == BTA_HF_CLIENT_ACP) {
81     event = BTA_HF_CLIENT_DISC_ACP_RES_EVT;
82   } else {
83     event = BTA_HF_CLIENT_DISC_INT_RES_EVT;
84   }
85 
86   p_buf->hdr.event = event;
87   p_buf->hdr.layer_specific = client_cb->handle;
88   p_buf->status = status;
89 
90   bta_sys_sendmsg(p_buf);
91 }
92 
93 /******************************************************************************
94  *
95  * Function         bta_hf_client_add_record
96  *
97  * Description      This function is called by a server application to add
98  *                  HFP Client information to an SDP record.  Prior to
99  *                  calling this function the application must call
100  *                  get_legacy_stack_sdp_api()->handle.SDP_CreateRecord() to
101  *                  create an SDP record.
102  *
103  * Returns          true if function execution succeeded,
104  *                  false if function execution failed.
105  *
106  *****************************************************************************/
bta_hf_client_add_record(const char * p_service_name,uint8_t scn,tBTA_HF_CLIENT_FEAT features,uint32_t sdp_handle)107 bool bta_hf_client_add_record(const char* p_service_name, uint8_t scn, tBTA_HF_CLIENT_FEAT features,
108                               uint32_t sdp_handle) {
109   tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HF_CLIENT_NUM_PROTO_ELEMS];
110   uint16_t svc_class_id_list[BTA_HF_CLIENT_NUM_SVC_ELEMS];
111   uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
112   uint16_t version;
113   uint16_t profile_uuid;
114   bool result = true;
115   uint8_t buf[2];
116   uint16_t sdp_features = 0;
117 
118   log::verbose("bta_hf_client_add_record");
119   log::info("features: {}", features);
120 
121   memset(proto_elem_list, 0, BTA_HF_CLIENT_NUM_PROTO_ELEMS * sizeof(tSDP_PROTOCOL_ELEM));
122 
123   /* add the protocol element sequence */
124   proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
125   proto_elem_list[0].num_params = 0;
126   proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
127   proto_elem_list[1].num_params = 1;
128   proto_elem_list[1].params[0] = scn;
129   result &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
130           sdp_handle, BTA_HF_CLIENT_NUM_PROTO_ELEMS, proto_elem_list);
131 
132   /* add service class id list */
133   svc_class_id_list[0] = UUID_SERVCLASS_HF_HANDSFREE;
134   svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
135   result &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
136           sdp_handle, BTA_HF_CLIENT_NUM_SVC_ELEMS, svc_class_id_list);
137 
138   /* add profile descriptor list */
139   profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
140   version = get_default_hfp_version();
141 
142   result &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(sdp_handle,
143                                                                             profile_uuid, version);
144 
145   /* add service name */
146   if (p_service_name != NULL && p_service_name[0] != 0) {
147     result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
148             sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
149             (uint32_t)(strlen(p_service_name) + 1), (uint8_t*)p_service_name);
150   }
151 
152   /* add features */
153   if (features & BTA_HF_CLIENT_FEAT_ECNR) {
154     sdp_features |= BTA_HF_CLIENT_FEAT_ECNR;
155   }
156 
157   if (features & BTA_HF_CLIENT_FEAT_3WAY) {
158     sdp_features |= BTA_HF_CLIENT_FEAT_3WAY;
159   }
160 
161   if (features & BTA_HF_CLIENT_FEAT_CLI) {
162     sdp_features |= BTA_HF_CLIENT_FEAT_CLI;
163   }
164 
165   if (features & BTA_HF_CLIENT_FEAT_VREC) {
166     sdp_features |= BTA_HF_CLIENT_FEAT_VREC;
167   }
168 
169   if (features & BTA_HF_CLIENT_FEAT_VOL) {
170     sdp_features |= BTA_HF_CLIENT_FEAT_VOL;
171   }
172 
173   /* Codec bit position is different in SDP (bit 5) and in BRSF (bit 7) */
174   if (features & BTA_HF_CLIENT_FEAT_CODEC) {
175     sdp_features |= BTA_HF_CLIENT_WBS_SUPPORT;
176   }
177 
178   /* Support swb */
179   if (features & BTA_HF_CLIENT_FEAT_SWB) {
180     sdp_features |= BTA_HF_CLIENT_FEAT_SWB_SUPPORT;
181   }
182 
183   UINT16_TO_BE_FIELD(buf, sdp_features);
184   result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
185           sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf);
186 
187   /* add browse group list */
188   result &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
189           sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
190 
191   return result;
192 }
193 
194 /*******************************************************************************
195  *
196  * Function         bta_hf_client_create_record
197  *
198  * Description      Create SDP record for registered service.
199  *
200  *
201  * Returns          void
202  *
203  ******************************************************************************/
bta_hf_client_create_record(tBTA_HF_CLIENT_CB_ARR * client_cb_arr,const char * p_service_name)204 void bta_hf_client_create_record(tBTA_HF_CLIENT_CB_ARR* client_cb_arr, const char* p_service_name) {
205   /* add sdp record if not already registered */
206   if (client_cb_arr->sdp_handle == 0) {
207     client_cb_arr->sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
208     client_cb_arr->scn = BTA_AllocateSCN();
209     bta_hf_client_add_record(p_service_name, client_cb_arr->scn, client_cb_arr->features,
210                              client_cb_arr->sdp_handle);
211 
212     bta_sys_add_uuid(UUID_SERVCLASS_HF_HANDSFREE);
213   }
214 }
215 
216 /*******************************************************************************
217  *
218  * Function         bta_hf_client_del_record
219  *
220  * Description      Delete SDP record for registered service.
221  *
222  *
223  * Returns          void
224  *
225  ******************************************************************************/
bta_hf_client_del_record(tBTA_HF_CLIENT_CB_ARR * client_cb)226 void bta_hf_client_del_record(tBTA_HF_CLIENT_CB_ARR* client_cb) {
227   log::verbose("");
228 
229   if (client_cb->sdp_handle != 0) {
230     if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(client_cb->sdp_handle)) {
231       log::warn("Unable to delete SDP record handle:{}", client_cb->sdp_handle);
232     }
233     client_cb->sdp_handle = 0;
234     BTA_FreeSCN(client_cb->scn);
235     bta_sys_remove_uuid(UUID_SERVCLASS_HF_HANDSFREE);
236   }
237 }
238 
239 /*******************************************************************************
240  *
241  * Function         bta_hf_client_sdp_find_attr
242  *
243  * Description      Process SDP discovery results to find requested attribute
244  *
245  *
246  * Returns          true if results found, false otherwise.
247  *
248  ******************************************************************************/
bta_hf_client_sdp_find_attr(tBTA_HF_CLIENT_CB * client_cb)249 bool bta_hf_client_sdp_find_attr(tBTA_HF_CLIENT_CB* client_cb) {
250   tSDP_DISC_REC* p_rec = NULL;
251   tSDP_DISC_ATTR* p_attr;
252   tSDP_PROTOCOL_ELEM pe;
253   bool result = false;
254 
255   client_cb->peer_version = HFP_VERSION_1_1; /* Default version */
256 
257   /* loop through all records we found */
258   while (true) {
259     /* get next record; if none found, we're done */
260     p_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(client_cb->p_disc_db,
261                                                                UUID_SERVCLASS_AG_HANDSFREE, p_rec);
262     if (p_rec == NULL) {
263       break;
264     }
265 
266     /* get scn from proto desc list if initiator */
267     if (client_cb->role == BTA_HF_CLIENT_INT) {
268       if (get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
269                   p_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
270         client_cb->peer_scn = (uint8_t)pe.params[0];
271       } else {
272         continue;
273       }
274     }
275 
276     /* get profile version (if failure, version parameter is not updated) */
277     if (!get_legacy_stack_sdp_api()->record.SDP_FindProfileVersionInRec(
278                 p_rec, UUID_SERVCLASS_HF_HANDSFREE, &client_cb->peer_version)) {
279       log::warn("Uable to find HFP profile version in SDP record peer:{}", p_rec->remote_bd_addr);
280     }
281 
282     /* get features */
283     p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(p_rec,
284                                                                        ATTR_ID_SUPPORTED_FEATURES);
285     if (p_attr != NULL && SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UINT_DESC_TYPE &&
286         SDP_DISC_ATTR_LEN(p_attr->attr_len_type) >= 2) {
287       /* Found attribute. Get value. */
288       /* There might be race condition between SDP and BRSF.  */
289       /* Do not update if we already received BRSF.           */
290       if (client_cb->peer_features == 0) {
291         client_cb->peer_features = p_attr->attr_value.v.u16;
292 
293         /* SDP and BRSF WBS bit are different, correct it if set */
294         if (client_cb->peer_features & 0x0020) {
295           client_cb->peer_features &= ~0x0020;
296           client_cb->peer_features |= BTA_HF_CLIENT_PEER_CODEC;
297         }
298 
299         /* get network for ability to reject calls */
300         p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(p_rec, ATTR_ID_NETWORK);
301         if (p_attr != NULL && SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UINT_DESC_TYPE &&
302             SDP_DISC_ATTR_LEN(p_attr->attr_len_type) >= 2) {
303           if (p_attr->attr_value.v.u16 == 0x01) {
304             client_cb->peer_features |= BTA_HF_CLIENT_PEER_REJECT;
305           }
306         }
307       }
308     }
309 
310     /* found what we needed */
311     result = true;
312     break;
313   }
314 
315   log::verbose("peer_version=0x{:x} peer_features=0x{:x}", client_cb->peer_version,
316                client_cb->peer_features);
317 
318   return result;
319 }
320 
321 /*******************************************************************************
322  *
323  * Function         bta_hf_client_do_disc
324  *
325  * Description      Do service discovery.
326  *
327  *
328  * Returns          void
329  *
330  ******************************************************************************/
bta_hf_client_do_disc(tBTA_HF_CLIENT_CB * client_cb)331 void bta_hf_client_do_disc(tBTA_HF_CLIENT_CB* client_cb) {
332   Uuid uuid_list[1];
333   uint16_t num_uuid = 1;
334   uint16_t attr_list[4];
335   uint8_t num_attr;
336   bool db_inited = false;
337 
338   /* initiator; get proto list and features */
339   if (client_cb->role == BTA_HF_CLIENT_INT) {
340     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
341     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
342     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
343     attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
344     num_attr = 4;
345     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
346   } else {
347     /* acceptor; get features */
348     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
349     attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
350     attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
351     num_attr = 3;
352     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
353   }
354 
355   /* If we already have a non-null discovery database at this point, we can get
356    * into a race condition leading to UAF once this connection is closed.
357    * This should only happen with malicious modifications to a client. */
358   if (com::android::bluetooth::flags::btsec_check_valid_discovery_database() &&
359       client_cb->p_disc_db != NULL) {
360     log::error("Tried to set up a HF client with a preexisting discovery database.");
361     client_cb->p_disc_db = NULL;
362     // We manually set the state here because it's possible to call this from an
363     // OPEN state, in which case the discovery fail event will be ignored.
364     client_cb->state = 0;  // BTA_HF_CLIENT_INIT_ST
365     return;
366   }
367 
368   /* allocate buffer for sdp database */
369   client_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
370 
371   /* set up service discovery database; attr happens to be attr_list len */
372   db_inited = get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
373           client_cb->p_disc_db, BT_DEFAULT_BUFFER_SIZE, num_uuid, uuid_list, num_attr, attr_list);
374 
375   if (db_inited) {
376     /*Service discovery not initiated */
377     db_inited = get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest2(
378             client_cb->peer_addr, client_cb->p_disc_db,
379             base::BindRepeating(&bta_hf_client_sdp_cback, client_cb));
380   }
381 
382   if (!db_inited) {
383     log::warn("Unable to start SDP service search request peer:{}", client_cb->peer_addr);
384     /*free discover db */
385     osi_free_and_reset((void**)&client_cb->p_disc_db);
386     /* sent failed event */
387     tBTA_HF_CLIENT_DATA msg;
388     msg.hdr.layer_specific = client_cb->handle;
389     bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, &msg);
390   }
391 }
392 
393 /*******************************************************************************
394  *
395  * Function         bta_hf_client_free_db
396  *
397  * Description      Free discovery database.
398  *
399  *
400  * Returns          void
401  *
402  ******************************************************************************/
bta_hf_client_free_db(tBTA_HF_CLIENT_DATA * p_data)403 void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA* p_data) {
404   log::assert_that(p_data != NULL, "assert failed: p_data != NULL");
405   tBTA_HF_CLIENT_CB* client_cb = bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
406   if (client_cb == NULL) {
407     log::error("cb not found for handle {}", p_data->hdr.layer_specific);
408     return;
409   }
410 
411   osi_free_and_reset((void**)&client_cb->p_disc_db);
412 }
413