1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #define LOG_TAG "bt_btif_sock_sdp"
20 
21 #include "btif_sock_sdp.h"
22 
23 #include <errno.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 
27 #include <hardware/bluetooth.h>
28 #include <hardware/bt_sock.h>
29 
30 #include "../bta/pb/bta_pbs_int.h"
31 #include "../include/bta_op_api.h"
32 #include "bt_target.h"
33 #include "bta_api.h"
34 #include "bta_jv_api.h"
35 #include "btif_common.h"
36 #include "btif_sock_util.h"
37 #include "btif_util.h"
38 #include "btm_api.h"
39 #include "btm_int.h"
40 #include "btu.h"
41 #include "bt_common.h"
42 #include "hcimsgs.h"
43 #include "sdp_api.h"
44 #include "utl.h"
45 
46 // This module provides an abstraction on top of the lower-level SDP database
47 // code for registration and discovery of various bluetooth sockets.
48 //
49 // This code also provides for on-demand registration of "pre-registered"
50 // services as a backwards compatibility function to third-party applications
51 // expecting a bluez stack.
52 
53 // Realm Character Set -- 0 is ASCII
54 #define BTA_PBS_REALM_CHARSET 0
55 
56 // Specifies whether or not client's user id is required during obex
57 // authentication
58 #define BTA_PBS_USERID_REQ FALSE
59 
60 static const tBTA_PBS_CFG bta_pbs_cfg = {
61   BTA_PBS_REALM_CHARSET,                          // realm_charset: Server only
62   BTA_PBS_USERID_REQ,                             // userid_req: Server only
63   (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),  // supported_features
64   BTA_PBS_REPOSIT_LOCAL,                          // supported_repositories
65 };
66 
67 // object format lookup table
68 #define OBEX_PUSH_NUM_FORMATS 7
69 
70 static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = {
71   BTA_OP_VCARD21_FMT,
72   BTA_OP_VCARD30_FMT,
73   BTA_OP_VCAL_FMT,
74   BTA_OP_ICAL_FMT,
75   BTA_OP_VNOTE_FMT,
76   BTA_OP_VMSG_FMT,
77   BTA_OP_OTHER_FMT
78 };
79 
80 // TODO(jtgans): Figure out if we actually need this define. This is ifndef
81 // defined in bt_target.h, but nowhere else, so right now, unless something
82 // overrides this before bt_target.h sets it, it will always be bt_target.h's
83 // version.
84 #ifndef BTUI_OPS_FORMATS
85 #define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK   \
86                           | BTA_OP_VCARD30_MASK \
87                           | BTA_OP_VCAL_MASK    \
88                           | BTA_OP_ICAL_MASK    \
89                           | BTA_OP_VNOTE_MASK   \
90                           | BTA_OP_VMSG_MASK    \
91                           | BTA_OP_ANY_MASK)
92 #endif
93 
94 #define RESERVED_SCN_PBS 19
95 #define RESERVED_SCN_OPS 12
96 
97 #define UUID_MAX_LENGTH 16
98 #define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
99 
100 // Adds a protocol list and service name (if provided) to an SDP record given by
101 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
102 // set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If
103 // |with_obex| is |TRUE|, then an additional OBEX protocol UUID will be included
104 // at the end of the protocol list.
105 //
106 // Returns TRUE if successful, otherwise FALSE.
create_base_record(const uint32_t sdp_handle,const char * name,const uint16_t channel,const bool with_obex)107 static bool create_base_record(const uint32_t sdp_handle, const char *name,
108                                const uint16_t channel, const bool with_obex) {
109   APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
110                    channel, name, with_obex);
111 
112   // Setup the protocol list and add it.
113   tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
114   int num_proto_elements = with_obex ? 3 : 2;
115 
116   memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
117 
118   proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
119   proto_list[0].num_params = 0;
120   proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
121   proto_list[1].num_params = 1;
122   proto_list[1].params[0] = channel;
123 
124   if (with_obex == TRUE) {
125     proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
126     proto_list[2].num_params = 0;
127   }
128 
129   char *stage = "protocol_list";
130   if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list))
131     goto error;
132 
133   // Add the name to the SDP record.
134   if (name[0] != '\0') {
135     stage = "service_name";
136     if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
137                           TEXT_STR_DESC_TYPE, (uint32_t)(strlen(name) + 1),
138                           (uint8_t *)name))
139       goto error;
140   }
141 
142   // Mark the service as browseable.
143   uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
144   stage = "browseable";
145   if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list))
146     goto error;
147 
148   APPL_TRACE_DEBUG("create_base_record: successfully created base service "
149                    "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
150                    sdp_handle, channel, name, with_obex);
151   return TRUE;
152 
153 error:
154   APPL_TRACE_ERROR("create_base_record: failed to create base service "
155                    "record, stage: %s, scn: %d, name: %s, with_obex: %d",
156                    stage, channel, name, with_obex);
157   return FALSE;
158 }
159 
160 // Registers a service with the given |name|, |uuid|, and |channel| in the SDP
161 // database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
162 // class sequence.
add_sdp_by_uuid(const char * name,const uint8_t * uuid,const uint16_t channel)163 static int add_sdp_by_uuid(const char *name,  const uint8_t *uuid,
164                            const uint16_t channel) {
165   APPL_TRACE_DEBUG("add_sdp_by_uuid: scn: %d, service_name: %s", channel, name);
166 
167   uint32_t handle = SDP_CreateRecord();
168   if (handle == 0) {
169     APPL_TRACE_ERROR("add_sdp_by_uuid: failed to create sdp record, "
170                      "scn: %d, service_name: %s", channel, name);
171     return 0;
172   }
173 
174   // Create the base SDP record.
175   char *stage = "create_base_record";
176   if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
177     goto error;
178 
179   // Convert the |uuid| into a big-endian representation and add it as a
180   // sequence.
181   uint8_t type = UUID_DESC_TYPE;
182   uint8_t type_len = UUID_MAX_LENGTH;
183   uint8_t type_buf[48];
184   // Store the address of type buf in a pointer on the stack, so we can pass
185   // a double pointer to SDP_AddSequence
186   uint8_t *type_buf_ptr = type_buf;
187 
188   // Do the conversion to big-endian -- tmp is only used to iterate through the
189   // UUID array in the macro and serves no other purpose as the conversion
190   // macros are not hygenic.
191   {
192     uint8_t *tmp = type_buf;
193     ARRAY_TO_BE_STREAM(tmp, uuid, UUID_MAX_LENGTH);
194   }
195 
196   stage = "service_class_sequence";
197   if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST,
198                        1, &type, &type_len, &type_buf_ptr))
199     goto error;
200 
201   APPL_TRACE_DEBUG("add_sdp_by_uuid: service registered successfully, "
202                    "service_name: %s, handle: 0x%08x", name, handle);
203   return handle;
204 
205 error:
206   SDP_DeleteRecord(handle);
207   APPL_TRACE_ERROR("add_sdp_by_uuid: failed to register service "
208                    "stage: %s, service_name: %s", stage, name);
209   return 0;
210 }
211 
212 // Registers a service with the given |name| and |channel| in the SDP
213 // database as a PBAP protocol.
add_pbap_sdp(const char * name,const int channel)214 static int add_pbap_sdp(const char *name, const int channel) {
215   APPL_TRACE_DEBUG("add_pbap_sdp: scn %d, service_name %s", channel, name);
216 
217   uint32_t handle = SDP_CreateRecord();
218   if (handle == 0) {
219     APPL_TRACE_ERROR("add_pbap_sdp: failed to create sdp record, "
220                      "service_name: %s", name);
221     return 0;
222   }
223 
224   // Create the base SDP record.
225   char *stage = "create_base_record";
226   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
227     goto error;
228 
229   // Add service class
230   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
231   stage = "service_class";
232   if (!SDP_AddServiceClassIdList(handle, 1, &service))
233     goto error;
234 
235   // Add in the phone access descriptor
236   stage = "profile_descriptor_list";
237   if (!SDP_AddProfileDescriptorList(handle,
238                                     UUID_SERVCLASS_PHONE_ACCESS,
239                                     BTA_PBS_DEFAULT_VERSION))
240     goto error;
241 
242   // Set up our supported repositories
243   stage = "supported_repositories";
244   if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
245                         1, (uint8_t*)&bta_pbs_cfg.supported_repositories))
246     goto error;
247 
248   // Notify the system that we've got a new service class UUID.
249   bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE);
250   APPL_TRACE_DEBUG("add_pbap_sdp: service registered successfully, "
251                    "service_name: %s, handle: 0x%08x", name, handle);
252 
253   return handle;
254 
255 error:
256   SDP_DeleteRecord(handle);
257   APPL_TRACE_ERROR("add_pbap_sdp: failed to register PBAP service, stage: %s, "
258                    "service_name: %s", stage, name);
259   return 0;
260 }
261 // Registers a service with the given |name| and |channel| as an OBEX Push
262 // protocol.
add_ops_sdp(const char * name,const int channel)263 static int add_ops_sdp(const char *name, const int channel) {
264   APPL_TRACE_DEBUG("add_ops_sdp: scn %d, service_name %s", channel, name);
265 
266   uint32_t handle = SDP_CreateRecord();
267   if (handle == 0) {
268     APPL_TRACE_ERROR("add_ops_sdp: failed to create sdp record, "
269                      "service_name: %s", name);
270     return 0;
271   }
272 
273   // Create the base SDP record.
274   char *stage = "create_base_record";
275   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
276     goto error;
277 
278   // Add service class.
279   stage = "service_class";
280   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
281   if (!SDP_AddServiceClassIdList(handle, 1, &service))
282     goto error;
283 
284   // Add the OBEX push profile descriptor.
285   stage = "profile_descriptor_list";
286   if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH,
287                                     0x0100))
288     goto error;
289 
290   // Add sequence for supported types.
291   uint8_t desc_type[OBEX_PUSH_NUM_FORMATS];
292   uint8_t type_len[OBEX_PUSH_NUM_FORMATS];
293   uint8_t *type_value[OBEX_PUSH_NUM_FORMATS];
294   uint8_t j = 0;
295 
296   for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) {
297     if ((BTUI_OPS_FORMATS >> i) & 1) {
298       type_value[j] = (uint8_t*)(&bta_ops_obj_fmt[i]);
299       desc_type[j] = UINT_DESC_TYPE;
300       type_len[j++] = 1;
301     }
302   }
303 
304   stage = "supported_types";
305   if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
306                        j, desc_type, type_len, type_value))
307     goto error;
308 
309   // Set class of device.
310   tBTA_UTL_COD cod;
311   cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
312   stage = "class_of_device";
313   if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS))
314     goto error;
315 
316   // Notify the system that we've got a new service class UUID.
317   bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
318   APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, "
319                    "service_name: %s, handle 0x%08x)", name, handle);
320 
321   return handle;
322 
323 error:
324   SDP_DeleteRecord(handle);
325   APPL_TRACE_ERROR("add_ops_sdp: failed to register OPS service, "
326                    "stage: %s, service_name: %s", stage, name);
327   return 0;
328 }
329 
330 // Registers a service with the given |name| and |channel| as a serial port
331 // profile protocol.
add_spp_sdp(const char * name,const int channel)332 static int add_spp_sdp(const char *name, const int channel) {
333   APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
334 
335   int handle = SDP_CreateRecord();
336   if (handle == 0) {
337     APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, "
338                      "service_name: %s", name);
339     return 0;
340   }
341 
342   // Create the base SDP record.
343   char *stage = "create_base_record";
344   if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
345     goto error;
346 
347   uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
348   stage = "service_class";
349   if (!SDP_AddServiceClassIdList(handle, 1, &service))
350     goto error;
351 
352   APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
353                    "service_name: %s, handle 0x%08x)", name, handle);
354 
355   return handle;
356 
357 error:
358   SDP_DeleteRecord(handle);
359   APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
360                    "stage: %s, service_name: %s", stage, name);
361   return 0;
362 }
363 
364 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
365 // |channel|. This function attempts to identify the type of the service based
366 // upon its |uuid|, and will override the |channel| with a reserved channel
367 // number if the |uuid| matches one of the preregistered bluez SDP records.
add_rfc_sdp_by_uuid(const char * name,const uint8_t * uuid,const int channel)368 static int add_rfc_sdp_by_uuid(const char *name, const uint8_t *uuid,
369                                const int channel) {
370   APPL_TRACE_DEBUG("add_rfc_sdp_by_uuid: service_name: %s, channel: %d", name,
371                    channel);
372 
373   /*
374    * Bluetooth Socket API relies on having preregistered bluez sdp records for
375    * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today
376    * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for
377    * now we will need to support OPP and PBAP to enable 3rd party developer apps
378    * running on BRCM Android.
379    *
380    * To do this we will check the UUID for the requested service and mimic the
381    * SDP records of bluez upon reception.  See functions add_opush() and
382    * add_pbap() in sdptool.c for actual records.
383    */
384 
385   int final_channel = get_reserved_rfc_channel(uuid);
386 
387   if (final_channel == -1) {
388     final_channel = channel;
389   }
390 
391   int handle = 0;
392 
393   if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
394     handle = add_ops_sdp(name, final_channel);
395   } else if (UUID_MATCHES(UUID_PBAP_PSE,uuid)) {
396     // PBAP Server is always channel 19
397     handle = add_pbap_sdp(name, final_channel);
398   } else if (UUID_MATCHES(UUID_SPP, uuid)) {
399     handle = add_spp_sdp(name, final_channel);
400   } else if (UUID_MATCHES(UUID_MAP_MAS,uuid)) {
401     // Record created by new SDP create record interface
402     handle = 0xff;
403   } else {
404     handle = add_sdp_by_uuid(name, uuid, final_channel);
405   }
406 
407   return handle;
408 }
409 
is_reserved_rfc_channel(const int channel)410 bool is_reserved_rfc_channel(const int channel) {
411   switch(channel) {
412     case RESERVED_SCN_PBS:
413     case RESERVED_SCN_OPS:
414       return TRUE;
415   }
416 
417   return FALSE;
418 }
419 
get_reserved_rfc_channel(const uint8_t * uuid)420 int get_reserved_rfc_channel(const uint8_t *uuid) {
421   if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) {
422     return RESERVED_SCN_PBS;
423   } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
424     return RESERVED_SCN_OPS;
425   }
426 
427   return -1;
428 }
429 
430 // Adds an SDP record to the SDP database using the given |name|, |uuid|, and
431 // |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
432 // upon the |channel| passed in.
add_rfc_sdp_rec(const char * name,const uint8_t * uuid,const int channel)433 int add_rfc_sdp_rec(const char *name, const uint8_t *uuid, const int channel) {
434   if (is_uuid_empty(uuid)) {
435     switch(channel) {
436       case RESERVED_SCN_PBS: // PBAP Reserved port
437         uuid = UUID_PBAP_PSE;
438         break;
439 
440       case RESERVED_SCN_OPS:
441         uuid = UUID_OBEX_OBJECT_PUSH;
442         break;
443 
444       default:
445         uuid = UUID_SPP;
446         break;
447     }
448   }
449 
450   return add_rfc_sdp_by_uuid(name, uuid, channel);
451 }
452 
453 // Deletes an SDP record with the given |handle|.
del_rfc_sdp_rec(int handle)454 void del_rfc_sdp_rec(int handle) {
455   APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle);
456 
457   if ((handle != -1) && (handle != 0))
458     BTA_JvDeleteRecord(handle);
459 }
460