1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bind_session_server.h"
17 #include "bind_session_common_util.h"
18 #include "callback_manager.h"
19 #include "channel_manager.h"
20 #include "das_module_defines.h"
21 #include "group_operation_common.h"
22 #include "hc_log.h"
23 #include "os_account_adapter.h"
24 #include "session_manager.h"
25
AddRecvModuleDataToParams(CJson * jsonParams,CJson * moduleParams)26 static int32_t AddRecvModuleDataToParams(CJson *jsonParams, CJson *moduleParams)
27 {
28 int32_t message = ERR_MESSAGE;
29 if (GetIntFromJson(jsonParams, FIELD_MESSAGE, &message) != HC_SUCCESS) {
30 LOGE("Failed to get message from in!");
31 return HC_ERR_JSON_GET;
32 }
33 int32_t authForm = AUTH_FORM_INVALID_TYPE;
34 (void)GetIntFromJson(jsonParams, FIELD_AUTH_FORM, &authForm);
35 CJson *payload = GetObjFromJson(jsonParams, FIELD_PAYLOAD);
36 if (payload == NULL) {
37 LOGE("Failed to get payload from in!");
38 return HC_ERR_JSON_GET;
39 }
40 if (AddIntToJson(moduleParams, FIELD_MESSAGE, message) != HC_SUCCESS) {
41 LOGE("Failed to add message to moduleParams!");
42 return HC_ERR_JSON_FAIL;
43 }
44 if (AddIntToJson(moduleParams, FIELD_AUTH_FORM, authForm) != HC_SUCCESS) {
45 LOGE("Failed to add authForm to moduleParams!");
46 return HC_ERR_JSON_FAIL;
47 }
48 if (AddObjToJson(moduleParams, FIELD_PAYLOAD, payload) != HC_SUCCESS) {
49 LOGE("Failed to add payload to moduleParams!");
50 return HC_ERR_JSON_FAIL;
51 }
52 return HC_SUCCESS;
53 }
54
AddConfirmationToParams(CJson * moduleParams)55 static int32_t AddConfirmationToParams(CJson *moduleParams)
56 {
57 if (AddIntToJson(moduleParams, FIELD_CONFIRMATION, REQUEST_ACCEPTED) != HC_SUCCESS) {
58 LOGE("Failed to add confirmation to moduleParams!");
59 return HC_ERR_JSON_FAIL;
60 }
61 return HC_SUCCESS;
62 }
63
GenerateServerModuleParams(BindSession * session,CJson * jsonParams,CJson * moduleParams)64 static int32_t GenerateServerModuleParams(BindSession *session, CJson *jsonParams, CJson *moduleParams)
65 {
66 int32_t result;
67 if (((result = GenerateBasicModuleParams(false, session, moduleParams)) != HC_SUCCESS) ||
68 ((result = AddConfirmationToParams(moduleParams)) != HC_SUCCESS) ||
69 ((result = AddRecvModuleDataToParams(jsonParams, moduleParams)) != HC_SUCCESS)) {
70 return result;
71 }
72 return HC_SUCCESS;
73 }
74
GetServerModuleReturnData(BindSession * session,CJson * jsonParams,CJson * out,bool * isNeedInform)75 static int32_t GetServerModuleReturnData(BindSession *session, CJson *jsonParams, CJson *out, bool *isNeedInform)
76 {
77 CJson *moduleParams = CreateJson();
78 if (moduleParams == NULL) {
79 LOGE("Failed to allocate moduleParams memory!");
80 return HC_ERR_JSON_FAIL;
81 }
82
83 int32_t result = GenerateServerModuleParams(session, jsonParams, moduleParams);
84 if (result != HC_SUCCESS) {
85 LOGE("Failed to generate all params sent to the module!");
86 FreeJson(moduleParams);
87 return result;
88 }
89 /* Release the memory in advance to reduce the memory usage. */
90 DeleteAllItem(jsonParams);
91
92 result = CreateAndProcessModule(session, moduleParams, out);
93 FreeJson(moduleParams);
94 if (result != HC_SUCCESS) {
95 *isNeedInform = false;
96 InformPeerModuleError(out, session);
97 return result;
98 }
99 return HC_SUCCESS;
100 }
101
PrepareData(BindSession * session,CJson * jsonParams,CJson ** sendData,bool * isNeedInform)102 static int32_t PrepareData(BindSession *session, CJson *jsonParams, CJson **sendData, bool *isNeedInform)
103 {
104 CJson *out = CreateJson();
105 if (out == NULL) {
106 LOGE("Failed to allocate out memory!");
107 return HC_ERR_JSON_FAIL;
108 }
109
110 int32_t result = GetServerModuleReturnData(session, jsonParams, out, isNeedInform);
111 if (result != HC_SUCCESS) {
112 FreeJson(out);
113 return result;
114 }
115
116 *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER);
117 FreeJson(out);
118 if (*sendData == NULL) {
119 LOGE("Failed to get sendToPeer from out!");
120 return HC_ERR_JSON_GET;
121 }
122
123 result = AddInfoToSendData((session->opCode == MEMBER_JOIN), session, *sendData);
124 if (result != HC_SUCCESS) {
125 LOGE("Failed to add information to sendData!");
126 FreeJson(*sendData);
127 *sendData = NULL;
128 return result;
129 }
130 return HC_SUCCESS;
131 }
132
PrepareAndSendDataServer(BindSession * session,CJson * jsonParams,bool * isNeedInform)133 static int32_t PrepareAndSendDataServer(BindSession *session, CJson *jsonParams, bool *isNeedInform)
134 {
135 CJson *sendData = NULL;
136 int32_t result = PrepareData(session, jsonParams, &sendData, isNeedInform);
137 if (result != HC_SUCCESS) {
138 return result;
139 }
140
141 result = SendBindSessionData(session, sendData);
142 FreeJson(sendData);
143 return result;
144 }
145
GenerateRequestParams(const CJson * jsonParams,CJson * requestParams)146 static int32_t GenerateRequestParams(const CJson *jsonParams, CJson *requestParams)
147 {
148 const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
149 if (groupId == NULL) {
150 LOGE("Failed to get groupId from jsonParams!");
151 return HC_ERR_JSON_GET;
152 }
153 const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_PEER_DEVICE_ID);
154 if (peerAuthId == NULL) {
155 LOGE("Failed to get peerAuthId from jsonParams!");
156 return HC_ERR_JSON_GET;
157 }
158 const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
159 if (appId == NULL) {
160 LOGE("Failed to get appId from jsonParams!");
161 return HC_ERR_JSON_GET;
162 }
163 int32_t groupType = PEER_TO_PEER_GROUP;
164 if (GetIntFromJson(jsonParams, FIELD_GROUP_TYPE, &groupType) != HC_SUCCESS) {
165 LOGE("Failed to get groupType from jsonParams!");
166 return HC_ERR_JSON_GET;
167 }
168 if (AddStringToJson(requestParams, FIELD_GROUP_ID, groupId) != HC_SUCCESS) {
169 LOGE("Failed to add groupId to requestParams!");
170 return HC_ERR_JSON_FAIL;
171 }
172 if (AddIntToJson(requestParams, FIELD_GROUP_TYPE, groupType) != HC_SUCCESS) {
173 LOGE("Failed to add groupType to requestParams!");
174 return HC_ERR_JSON_FAIL;
175 }
176 if (AddStringToJson(requestParams, FIELD_PEER_DEVICE_ID, peerAuthId) != HC_SUCCESS) {
177 LOGE("Failed to add peerDeviceId to requestParams!");
178 return HC_ERR_JSON_FAIL;
179 }
180 if (AddStringToJson(requestParams, FIELD_APP_ID, appId) != HC_SUCCESS) {
181 LOGE("Failed to add appId to requestParams!");
182 return HC_ERR_JSON_FAIL;
183 }
184 return HC_SUCCESS;
185 }
186
RequestConfirmation(const CJson * jsonParams,const BindSession * session,char ** returnStr)187 static int32_t RequestConfirmation(const CJson *jsonParams, const BindSession *session, char **returnStr)
188 {
189 CJson *requestParams = CreateJson();
190 if (requestParams == NULL) {
191 LOGE("Failed to create json object!");
192 return HC_ERR_JSON_FAIL;
193 }
194 int32_t result = GenerateRequestParams(jsonParams, requestParams);
195 if (result != HC_SUCCESS) {
196 LOGE("An error occurs when the request parameters are generated!");
197 FreeJson(requestParams);
198 return result;
199 }
200 char *requestParamsStr = PackJsonToString(requestParams);
201 FreeJson(requestParams);
202 if (requestParamsStr == NULL) {
203 LOGE("An error occurred when converting JSON data to String data.!");
204 return HC_ERR_JSON_FAIL;
205 }
206 char *returnDataStr = ProcessRequestCallback(session->reqId, session->opCode,
207 requestParamsStr, session->base.callback);
208 FreeJsonString(requestParamsStr);
209 if (returnDataStr == NULL) {
210 LOGE("The OnRequest callback is fail!");
211 return HC_ERR_REQ_REJECTED;
212 }
213 *returnStr = returnDataStr;
214 return HC_SUCCESS;
215 }
216
AddAuthIdIfExist(const CJson * returnData,CJson * jsonParams)217 static int32_t AddAuthIdIfExist(const CJson *returnData, CJson *jsonParams)
218 {
219 const char *authId = GetStringFromJson(returnData, FIELD_DEVICE_ID);
220 if (authId != NULL) {
221 if (AddStringToJson(jsonParams, FIELD_DEVICE_ID, authId) != HC_SUCCESS) {
222 LOGE("Failed to add authId to jsonParams!");
223 return HC_ERR_JSON_FAIL;
224 }
225 }
226 return HC_SUCCESS;
227 }
228
AddUserTypeIfExistAndValid(const CJson * returnData,CJson * jsonParams)229 static int32_t AddUserTypeIfExistAndValid(const CJson *returnData, CJson *jsonParams)
230 {
231 int32_t userType = DEVICE_TYPE_ACCESSORY;
232 if (GetIntFromJson(returnData, FIELD_USER_TYPE, &userType) == HC_SUCCESS) {
233 if (!IsUserTypeValid(userType)) {
234 LOGE("The input userType is invalid!");
235 return HC_ERR_INVALID_PARAMS;
236 }
237 if (AddIntToJson(jsonParams, FIELD_USER_TYPE, userType) != HC_SUCCESS) {
238 LOGE("Failed to add userType to jsonParams!");
239 return HC_ERR_JSON_FAIL;
240 }
241 }
242 return HC_SUCCESS;
243 }
244
AddGroupVisibilityIfExistAndValid(const CJson * returnData,CJson * jsonParams)245 static int32_t AddGroupVisibilityIfExistAndValid(const CJson *returnData, CJson *jsonParams)
246 {
247 int32_t groupVisibility = GROUP_VISIBILITY_PUBLIC;
248 if (GetIntFromJson(returnData, FIELD_GROUP_VISIBILITY, &groupVisibility) == HC_SUCCESS) {
249 if (!IsGroupVisibilityValid(groupVisibility)) {
250 LOGE("The input groupVisibility invalid!");
251 return HC_ERR_INVALID_PARAMS;
252 }
253 if (AddIntToJson(jsonParams, FIELD_GROUP_VISIBILITY, groupVisibility) != HC_SUCCESS) {
254 LOGE("Failed to add groupVisibility to jsonParams!");
255 return HC_ERR_JSON_FAIL;
256 }
257 }
258 return HC_SUCCESS;
259 }
260
AddExpireTimeIfExistAndValid(const CJson * returnData,CJson * jsonParams)261 static int32_t AddExpireTimeIfExistAndValid(const CJson *returnData, CJson *jsonParams)
262 {
263 int32_t expireTime = DEFAULT_EXPIRE_TIME;
264 if (GetIntFromJson(returnData, FIELD_EXPIRE_TIME, &expireTime) == HC_SUCCESS) {
265 if (!IsExpireTimeValid(expireTime)) {
266 LOGE("The input expireTime invalid!");
267 return HC_ERR_INVALID_PARAMS;
268 }
269 if (AddIntToJson(jsonParams, FIELD_EXPIRE_TIME, expireTime) != HC_SUCCESS) {
270 LOGE("Failed to add expireTime to jsonParams!");
271 return HC_ERR_JSON_FAIL;
272 }
273 }
274 return HC_SUCCESS;
275 }
276
AddPinCode(const CJson * returnData,CJson * jsonParams)277 static int32_t AddPinCode(const CJson *returnData, CJson *jsonParams)
278 {
279 const char *pinCode = GetStringFromJson(returnData, FIELD_PIN_CODE);
280 if (pinCode == NULL) {
281 LOGE("Failed to get pinCode from returnData!");
282 return HC_ERR_JSON_GET;
283 }
284 if (AddStringToJson(jsonParams, FIELD_PIN_CODE, pinCode) != HC_SUCCESS) {
285 LOGE("Failed to add pinCode to jsonParams!");
286 return HC_ERR_JSON_FAIL;
287 }
288 return HC_SUCCESS;
289 }
290
CombineInfoWhenInvite(const CJson * returnData,CJson * jsonParams)291 static int32_t CombineInfoWhenInvite(const CJson *returnData, CJson *jsonParams)
292 {
293 int32_t result;
294 if (((result = AddPinCode(returnData, jsonParams)) != HC_SUCCESS) ||
295 ((result = AddAuthIdIfExist(returnData, jsonParams)) != HC_SUCCESS) ||
296 ((result = AddUserTypeIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS) ||
297 ((result = AddGroupVisibilityIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS) ||
298 ((result = AddExpireTimeIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS)) {
299 return result;
300 }
301 return HC_SUCCESS;
302 }
303
CombineInputData(int operationCode,const CJson * returnData,CJson * jsonParams)304 static int32_t CombineInputData(int operationCode, const CJson *returnData, CJson *jsonParams)
305 {
306 if (operationCode == MEMBER_DELETE) {
307 return HC_SUCCESS;
308 } else if (operationCode == MEMBER_JOIN) {
309 return AddPinCode(returnData, jsonParams);
310 } else {
311 return CombineInfoWhenInvite(returnData, jsonParams);
312 }
313 }
314
CheckServerStatusIfNotInvite(int32_t osAccountId,int operationCode,const CJson * jsonParams)315 static int32_t CheckServerStatusIfNotInvite(int32_t osAccountId, int operationCode, const CJson *jsonParams)
316 {
317 if (operationCode == MEMBER_INVITE) {
318 return HC_SUCCESS;
319 }
320 const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
321 if (groupId == NULL) {
322 LOGE("Failed to get groupId from jsonParams!");
323 return HC_ERR_JSON_GET;
324 }
325 const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
326 if (appId == NULL) {
327 LOGE("Failed to get appId from jsonParams!");
328 return HC_ERR_JSON_GET;
329 }
330 const char *peerUdid = GetStringFromJson(jsonParams, FIELD_CONN_DEVICE_ID);
331 if (peerUdid == NULL) {
332 LOGE("Failed to get peerUdid from jsonParams!");
333 return HC_ERR_JSON_GET;
334 }
335 int32_t result = CheckGroupExist(osAccountId, groupId);
336 if (result != HC_SUCCESS) {
337 return result;
338 }
339 if (operationCode == MEMBER_JOIN) {
340 /* The client sends a join request, which is equivalent to the server performing an invitation operation. */
341 result = CheckPermForGroup(osAccountId, MEMBER_INVITE, appId, groupId);
342 if (result != HC_SUCCESS) {
343 return result;
344 }
345 result = CheckDeviceNumLimit(osAccountId, groupId, peerUdid);
346 } else if (operationCode == MEMBER_DELETE) {
347 result = CheckPermForGroup(osAccountId, MEMBER_DELETE, appId, groupId);
348 if (result != HC_SUCCESS) {
349 return result;
350 }
351 if (!IsTrustedDeviceInGroup(osAccountId, groupId, peerUdid, true)) {
352 result = HC_ERR_DEVICE_NOT_EXIST;
353 }
354 }
355 return result;
356 }
357
PrepareServer(BindSession * session,CJson * returnData,bool * isNeedInform)358 static int32_t PrepareServer(BindSession *session, CJson *returnData, bool *isNeedInform)
359 {
360 CJson *jsonParams = DetachItemFromJson(session->params, FIELD_RECEIVED_DATA);
361 if (jsonParams == NULL) {
362 LOGE("Received data before request confirmation are lost!");
363 return HC_ERR_LOST_DATA;
364 }
365 int32_t osAccountId = ANY_OS_ACCOUNT;
366 (void)GetIntFromJson(returnData, FIELD_OS_ACCOUNT_ID, &osAccountId);
367 osAccountId = DevAuthGetRealOsAccountLocalId(osAccountId);
368 if (osAccountId == INVALID_OS_ACCOUNT) {
369 FreeJson(jsonParams);
370 return HC_ERR_INVALID_PARAMS;
371 }
372 int32_t result = CheckServerStatusIfNotInvite(osAccountId, session->opCode, jsonParams);
373 if (result != HC_SUCCESS) {
374 FreeJson(jsonParams);
375 return result;
376 }
377 session->osAccountId = osAccountId;
378 result = CombineInputData(session->opCode, returnData, jsonParams);
379 /* Release the memory in advance to reduce the memory usage. */
380 DeleteAllItem(returnData);
381 if (result != HC_SUCCESS) {
382 FreeJson(jsonParams);
383 return result;
384 }
385 result = GenerateBindParams(osAccountId, SERVER, jsonParams, session);
386 if (result != HC_SUCCESS) {
387 FreeJson(jsonParams);
388 return result;
389 }
390 /*
391 * If the service is invited to join the peer group,
392 * the identity key pair of the corresponding group needs to be generated here.
393 */
394 if (NeedCreateGroup(SERVER, session->opCode)) {
395 const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
396 if (groupId == NULL) {
397 LOGE("Failed to get groupId from jsonParams!");
398 FreeJson(jsonParams);
399 return HC_ERR_JSON_GET;
400 }
401 result = ProcessKeyPair(CREATE_KEY_PAIR, jsonParams, groupId);
402 if (result != HC_SUCCESS) {
403 FreeJson(jsonParams);
404 return result;
405 }
406 }
407 result = PrepareAndSendDataServer(session, jsonParams, isNeedInform);
408 FreeJson(jsonParams);
409 return result;
410 }
411
BindSaveReceivedData(BindSession * session,const CJson * jsonParams)412 static int32_t BindSaveReceivedData(BindSession *session, const CJson *jsonParams)
413 {
414 if (session->params == NULL) {
415 session->params = CreateJson();
416 if (session->params == NULL) {
417 LOGE("Failed to allocate session params memory!");
418 return HC_ERR_ALLOC_MEMORY;
419 }
420 }
421 if (AddObjToJson(session->params, FIELD_RECEIVED_DATA, jsonParams) != HC_SUCCESS) {
422 LOGE("Failed to add received data to session params!");
423 return HC_ERR_JSON_FAIL;
424 }
425 return HC_SUCCESS;
426 }
427
JudgeConfirmation(CJson * returnData,CJson * jsonParams,BindSession * session,bool * isNeedInform)428 static int32_t JudgeConfirmation(CJson *returnData, CJson *jsonParams, BindSession *session, bool *isNeedInform)
429 {
430 uint32_t confirmation = REQUEST_ACCEPTED;
431 if (GetUnsignedIntFromJson(returnData, FIELD_CONFIRMATION, &confirmation) != HC_SUCCESS) {
432 LOGE("Failed to get confirmation from returnData!");
433 return HC_ERR_JSON_FAIL;
434 }
435 int32_t result;
436 switch (confirmation) {
437 case REQUEST_ACCEPTED:
438 LOGI("The service accepts the request!");
439 result = BindSaveReceivedData(session, jsonParams);
440 if (result != HC_SUCCESS) {
441 return result;
442 }
443 /* Release the memory in advance to reduce the memory usage. */
444 DeleteAllItem(jsonParams);
445 return PrepareServer(session, returnData, isNeedInform);
446 case REQUEST_REJECTED:
447 LOGE("The service rejects the request!");
448 return HC_ERR_REQ_REJECTED;
449 default:
450 LOGE("Enter the exception case!");
451 return HC_ERR_CASE;
452 }
453 }
454
HandleRequest(CJson * jsonParams,BindSession * session,bool * isNeedInform)455 static int32_t HandleRequest(CJson *jsonParams, BindSession *session, bool *isNeedInform)
456 {
457 char *returnDataStr = NULL;
458 int32_t result = RequestConfirmation(jsonParams, session, &returnDataStr);
459 if (result != HC_SUCCESS) {
460 return result;
461 }
462
463 CJson *returnData = CreateJsonFromString(returnDataStr);
464 FreeJsonString(returnDataStr);
465 if (returnData == NULL) {
466 LOGE("Failed to create returnData from string!");
467 return HC_ERR_JSON_FAIL;
468 }
469 result = JudgeConfirmation(returnData, jsonParams, session, isNeedInform);
470 FreeJson(returnData);
471 return result;
472 }
473
CreateServerBindSession(CJson * jsonParams,const DeviceAuthCallback * callback)474 Session *CreateServerBindSession(CJson *jsonParams, const DeviceAuthCallback *callback)
475 {
476 int32_t opCode = MEMBER_INVITE;
477 if (GetIntFromJson(jsonParams, FIELD_GROUP_OP, &opCode) != HC_SUCCESS) {
478 LOGE("Failed to get opCode from jsonParams!");
479 return NULL;
480 }
481
482 BindSession *session = CreateBaseBindSession(TYPE_SERVER_BIND_SESSION, opCode,
483 jsonParams, callback, ProcessBindSession);
484 if (session == NULL) {
485 return NULL;
486 }
487 InitServerChannel(jsonParams, session);
488 /* The server may receive the confirm request message. */
489
490 bool isNeedInform = true;
491 int32_t result = HandleRequest(jsonParams, session, &isNeedInform);
492 if (result != HC_SUCCESS) {
493 InformPeerGroupErrorIfNeed(isNeedInform, result, session);
494 ProcessErrorCallback(session->reqId, session->opCode, result, NULL, session->base.callback);
495 CloseChannel(session->channelType, session->channelId);
496 DestroyBindSession((Session *)session);
497 return NULL;
498 }
499 return (Session *)session;
500 }
501