1 /*
2  * Copyright (C) 2022-2023 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 "identical_account_group.h"
17 #include "alg_defs.h"
18 #include "callback_manager.h"
19 #include "common_defs.h"
20 #include "cred_manager.h"
21 #include "data_manager.h"
22 #include "device_auth_defines.h"
23 #include "group_operation_common.h"
24 #include "hc_dev_info.h"
25 #include "hc_log.h"
26 #include "string_util.h"
27 #include "dev_auth_module_manager.h"
28 #include "account_module.h"
29 
GenerateDevParams(const CJson * jsonParams,const char * groupId,TrustedDeviceEntry * devParams)30 static int32_t GenerateDevParams(const CJson *jsonParams, const char *groupId, TrustedDeviceEntry *devParams)
31 {
32     int32_t result;
33     if (((result = AddSelfUdidToParams(devParams)) != HC_SUCCESS) ||
34         ((result = AddCredTypeToParams(jsonParams, devParams)) != HC_SUCCESS) ||
35         ((result = AddUserIdToDevParams(jsonParams, devParams)) != HC_SUCCESS) ||
36         ((result = AddAuthIdToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) ||
37         ((result = AddSourceToParams(SELF_CREATED, devParams)) != HC_SUCCESS) ||
38         ((result = AddUserTypeToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) ||
39         ((result = AddGroupIdToDevParams(groupId, devParams)) != HC_SUCCESS) ||
40         ((result = AddServiceTypeToParams(groupId, devParams)) != HC_SUCCESS)) {
41         return result;
42     }
43     return HC_SUCCESS;
44 }
45 
GenerateGroupParams(const CJson * jsonParams,const char * groupId,TrustedGroupEntry * groupParams)46 static int32_t GenerateGroupParams(const CJson *jsonParams, const char *groupId, TrustedGroupEntry *groupParams)
47 {
48     const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
49     if (appId == NULL) {
50         LOGE("Failed to get appId from jsonParams!");
51         return HC_ERR_JSON_GET;
52     }
53     int32_t result;
54     if (((result = AddGroupTypeToParams(IDENTICAL_ACCOUNT_GROUP, groupParams)) != HC_SUCCESS) ||
55         ((result = AddGroupNameToParams(groupId, groupParams)) != HC_SUCCESS) ||
56         ((result = AddGroupIdToParams(groupId, groupParams)) != HC_SUCCESS) ||
57         ((result = AddUserIdToGroupParams(jsonParams, groupParams)) != HC_SUCCESS) ||
58         ((result = AddGroupOwnerToParams(appId, groupParams)) != HC_SUCCESS) ||
59         ((result = AddGroupVisibilityOrDefault(jsonParams, groupParams)) != HC_SUCCESS) ||
60         ((result = AddExpireTimeOrDefault(jsonParams, groupParams)) != HC_SUCCESS)) {
61         return result;
62     }
63     return HC_SUCCESS;
64 }
65 
GenerateGroupId(const char * userId,char ** returnGroupId)66 static int32_t GenerateGroupId(const char *userId, char **returnGroupId)
67 {
68     if ((userId == NULL) || (returnGroupId == NULL)) {
69         LOGE("The input parameters contains NULL value!");
70         return HC_ERR_INVALID_PARAMS;
71     }
72     /* identical account group: groupId = sha256(userId) */
73     int hashStrLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1;
74     *returnGroupId = (char *)HcMalloc(hashStrLen, 0);
75     if (*returnGroupId == NULL) {
76         LOGE("Failed to allocate returnGroupId memory!");
77         return HC_ERR_ALLOC_MEMORY;
78     }
79     if (memcpy_s(*returnGroupId, hashStrLen, userId, HcStrlen(userId)) != EOK) {
80         LOGE("Failed to copy userId for groupId!");
81         HcFree(*returnGroupId);
82         *returnGroupId = NULL;
83         return HC_ERR_MEMORY_COPY;
84     }
85     return HC_SUCCESS;
86 }
87 
GenerateIdenticalGroupId(const CJson * jsonParams,char ** returnGroupId)88 static int32_t GenerateIdenticalGroupId(const CJson *jsonParams, char **returnGroupId)
89 {
90     char *userId = NULL;
91     int32_t result = GetUserIdFromJson(jsonParams, &userId);
92     if (result != HC_SUCCESS) {
93         return result;
94     }
95     result = GenerateGroupId(userId, returnGroupId);
96     HcFree(userId);
97     if (result != HC_SUCCESS) {
98         LOGE("Failed to generate groupId!");
99         return result;
100     }
101     return HC_SUCCESS;
102 }
103 
AssertCredentialExist(const CJson * jsonParams)104 static int32_t AssertCredentialExist(const CJson *jsonParams)
105 {
106     CJson *credJson = GetObjFromJson(jsonParams, FIELD_CREDENTIAL);
107     if (credJson == NULL) {
108         LOGE("Failed to get credential from json!");
109         return HC_ERR_JSON_GET;
110     }
111     return HC_SUCCESS;
112 }
113 
CheckCreateParams(int32_t osAccountId,const CJson * jsonParams)114 static int32_t CheckCreateParams(int32_t osAccountId, const CJson *jsonParams)
115 {
116     const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
117     if (appId == NULL) {
118         LOGE("Failed to get appId from jsonParams!");
119         return HC_ERR_JSON_GET;
120     }
121     int32_t result;
122     if (((result = AssertUserIdExist(jsonParams)) != HC_SUCCESS) ||
123         ((result = AssertCredentialExist(jsonParams)) != HC_SUCCESS) ||
124         ((result = CheckUserTypeIfExist(jsonParams)) != HC_SUCCESS) ||
125         ((result = CheckGroupVisibilityIfExist(jsonParams)) != HC_SUCCESS) ||
126         ((result = CheckExpireTimeIfExist(jsonParams)) != HC_SUCCESS) ||
127         ((result = CheckGroupNumLimit(osAccountId, IDENTICAL_ACCOUNT_GROUP, appId)) != HC_SUCCESS)) {
128         return result;
129     }
130     return HC_SUCCESS;
131 }
132 
DelDeviceById(int32_t osAccountId,const char * groupId,const char * deviceId,bool isUdid)133 static int32_t DelDeviceById(int32_t osAccountId, const char *groupId, const char *deviceId, bool isUdid)
134 {
135     QueryDeviceParams queryDeviceParams = InitQueryDeviceParams();
136     queryDeviceParams.groupId = groupId;
137     if (isUdid) {
138         queryDeviceParams.udid = deviceId;
139     } else {
140         queryDeviceParams.authId = deviceId;
141     }
142     return DelTrustedDevice(osAccountId, &queryDeviceParams);
143 }
144 
ImportSelfToken(int32_t osAccountId,CJson * jsonParams)145 static int32_t ImportSelfToken(int32_t osAccountId, CJson *jsonParams)
146 {
147     const char *userId = GetStringFromJson(jsonParams, FIELD_USER_ID);
148     if (userId == NULL) {
149         LOGE("Failed to get userId from json!");
150         return HC_ERR_JSON_GET;
151     }
152     const char *deviceId = GetStringFromJson(jsonParams, FIELD_DEVICE_ID);
153     char udid[INPUT_UDID_LEN] = { 0 };
154     if (deviceId == NULL) {
155         LOGD("No deviceId is found. The default value is udid!");
156         int32_t res = HcGetUdid((uint8_t *)udid, INPUT_UDID_LEN);
157         if (res != HC_SUCCESS) {
158             LOGE("Failed to get local udid! res: %d", res);
159             return HC_ERR_DB;
160         }
161         deviceId = udid;
162     }
163     CJson *credJson = GetObjFromJson(jsonParams, FIELD_CREDENTIAL);
164     if (credJson == NULL) {
165         LOGE("Failed to get credential from json!");
166         return HC_ERR_JSON_GET;
167     }
168     if (AddStringToJson(credJson, FIELD_USER_ID, userId) != HC_SUCCESS) {
169         LOGE("Failed to add userId to json!");
170         return HC_ERR_JSON_ADD;
171     }
172     if (AddStringToJson(credJson, FIELD_DEVICE_ID, deviceId) != HC_SUCCESS) {
173         LOGE("Failed to add deviceId to json!");
174         return HC_ERR_JSON_ADD;
175     }
176     return ProcCred(ACCOUNT_RELATED_PLUGIN, osAccountId, IMPORT_SELF_CREDENTIAL, credJson, NULL);
177 }
178 
DelSelfToken(int32_t osAccountId,CJson * jsonParams)179 static int32_t DelSelfToken(int32_t osAccountId, CJson *jsonParams)
180 {
181     CJson *credJson = GetObjFromJson(jsonParams, FIELD_CREDENTIAL);
182     if (credJson == NULL) {
183         LOGE("Failed to get credential from json!");
184         return HC_ERR_JSON_GET;
185     }
186     return ProcCred(ACCOUNT_RELATED_PLUGIN, osAccountId, DELETE_SELF_CREDENTIAL, credJson, NULL);
187 }
188 
GenerateAddTokenParams(const CJson * jsonParams,CJson * addParams)189 static int32_t GenerateAddTokenParams(const CJson *jsonParams, CJson *addParams)
190 {
191     const char *userId = GetStringFromJson(jsonParams, FIELD_USER_ID);
192     if (userId == NULL) {
193         LOGE("Failed to get userId from json!");
194         return HC_ERR_JSON_GET;
195     }
196     const char *deviceId = GetStringFromJson(jsonParams, FIELD_DEVICE_ID);
197     if (deviceId == NULL) {
198         LOGE("Failed to get deviceId from json!");
199         return HC_ERR_JSON_GET;
200     }
201     if (AddStringToJson(addParams, FIELD_DEVICE_ID, deviceId) != HC_SUCCESS) {
202         LOGE("Failed to add deviceId to json!");
203         return HC_ERR_JSON_ADD;
204     }
205     if (AddStringToJson(addParams, FIELD_USER_ID, userId) != HC_SUCCESS) {
206         LOGE("Failed to add userId to json!");
207         return HC_ERR_JSON_ADD;
208     }
209     return HC_SUCCESS;
210 }
211 
GenerateDelTokenParams(const TrustedDeviceEntry * entry,CJson * delParams)212 static int32_t GenerateDelTokenParams(const TrustedDeviceEntry *entry, CJson *delParams)
213 {
214     if (AddIntToJson(delParams, FIELD_CREDENTIAL_TYPE, (int32_t)entry->credential) != HC_SUCCESS) {
215         LOGE("Failed to add credentialType to json!");
216         return HC_ERR_JSON_ADD;
217     }
218     if (AddStringToJson(delParams, FIELD_USER_ID, StringGet(&entry->userId)) != HC_SUCCESS) {
219         LOGE("Failed to add userId to json!");
220         return HC_ERR_JSON_ADD;
221     }
222     if (AddStringToJson(delParams, FIELD_DEVICE_ID, StringGet(&entry->authId)) != HC_SUCCESS) {
223         LOGE("Failed to add deviceId to json!");
224         return HC_ERR_JSON_ADD;
225     }
226     return HC_SUCCESS;
227 }
228 
DelDeviceToken(int32_t osAccountId,const TrustedDeviceEntry * entry,bool isLocalDev)229 static int32_t DelDeviceToken(int32_t osAccountId, const TrustedDeviceEntry *entry, bool isLocalDev)
230 {
231     CJson *delParams = CreateJson();
232     if (delParams == NULL) {
233         LOGE("Failed to allocate delParams memory!");
234         return HC_ERR_ALLOC_MEMORY;
235     }
236     int32_t res = GenerateDelTokenParams(entry, delParams);
237     if (res != HC_SUCCESS) {
238         FreeJson(delParams);
239         return res;
240     }
241     res = ProcCred(ACCOUNT_RELATED_PLUGIN, osAccountId,
242         (isLocalDev ? DELETE_SELF_CREDENTIAL : DELETE_TRUSTED_CREDENTIALS), delParams, NULL);
243     FreeJson(delParams);
244     return res;
245 }
246 
DelAllTokens(int32_t osAccountId,const DeviceEntryVec * vec)247 static void DelAllTokens(int32_t osAccountId, const DeviceEntryVec *vec)
248 {
249     int32_t res;
250     uint32_t index;
251     TrustedDeviceEntry **entry = NULL;
252     FOR_EACH_HC_VECTOR(*vec, index, entry) {
253         if (IsLocalDevice(StringGet(&(*entry)->udid))) {
254             res = DelDeviceToken(osAccountId, *entry, true);
255         } else {
256             res = DelDeviceToken(osAccountId, *entry, false);
257         }
258         if (res != HC_SUCCESS) {
259             LOGE("Failed to delete token! res: %d", res);
260         }
261     }
262 }
263 
DelAllPeerTokens(int32_t osAccountId,const DeviceEntryVec * vec)264 static void DelAllPeerTokens(int32_t osAccountId, const DeviceEntryVec *vec)
265 {
266     int32_t res;
267     uint32_t index;
268     TrustedDeviceEntry **entry = NULL;
269     FOR_EACH_HC_VECTOR(*vec, index, entry) {
270         if (IsLocalDevice(StringGet(&(*entry)->udid))) {
271             continue;
272         }
273         res = DelDeviceToken(osAccountId, *entry, false);
274         if (res != HC_SUCCESS) {
275             LOGE("Failed to delete peer device token! res: %d", res);
276         }
277     }
278 }
279 
DelAcrossAccountGroupAndTokens(int32_t osAccountId,const char * groupId)280 static int32_t DelAcrossAccountGroupAndTokens(int32_t osAccountId, const char *groupId)
281 {
282     DeviceEntryVec deviceList = CreateDeviceEntryVec();
283     (void)GetTrustedDevices(osAccountId, groupId, &deviceList);
284     int32_t res = DelGroupFromDb(osAccountId, groupId);
285     DelAllPeerTokens(osAccountId, &deviceList);
286     ClearDeviceEntryVec(&deviceList);
287     return res;
288 }
289 
GetRelatedAcrossAccountGroups(int32_t osAccountId,const char * groupId,GroupEntryVec * vec)290 static int32_t GetRelatedAcrossAccountGroups(int32_t osAccountId, const char *groupId, GroupEntryVec *vec)
291 {
292     TrustedGroupEntry *groupEntry = GetGroupEntryById(osAccountId, groupId);
293     if (groupEntry == NULL) {
294         LOGE("Failed to get groupEntry from db!");
295         return HC_ERR_DB;
296     }
297     QueryGroupParams groupParams = InitQueryGroupParams();
298     groupParams.userId = StringGet(&groupEntry->userId);
299     groupParams.groupType = ACROSS_ACCOUNT_AUTHORIZE_GROUP;
300     int32_t res = QueryGroups(osAccountId, &groupParams, vec);
301     DestroyGroupEntry(groupEntry);
302     return res;
303 }
304 
DelRelatedAcrossAccountGroups(int32_t osAccountId,const char * groupId)305 static int32_t DelRelatedAcrossAccountGroups(int32_t osAccountId, const char *groupId)
306 {
307     GroupEntryVec groupEntryVec = CreateGroupEntryVec();
308     (void)GetRelatedAcrossAccountGroups(osAccountId, groupId, &groupEntryVec);
309     int32_t res = HC_SUCCESS;
310     uint32_t index;
311     TrustedGroupEntry **entry = NULL;
312     FOR_EACH_HC_VECTOR(groupEntryVec, index, entry) {
313         if (DelAcrossAccountGroupAndTokens(osAccountId, StringGet(&(*entry)->id)) != HC_SUCCESS) {
314             res = HC_ERR_DEL_GROUP;
315         }
316     }
317     ClearGroupEntryVec(&groupEntryVec);
318     return res;
319 }
320 
DelGroupAndTokens(int32_t osAccountId,const char * groupId)321 static int32_t DelGroupAndTokens(int32_t osAccountId, const char *groupId)
322 {
323     int32_t res = HC_SUCCESS;
324     if (DelRelatedAcrossAccountGroups(osAccountId, groupId) != HC_SUCCESS) {
325         res = HC_ERR_DEL_GROUP;
326     }
327     DeviceEntryVec deviceList = CreateDeviceEntryVec();
328     (void)GetTrustedDevices(osAccountId, groupId, &deviceList);
329     if (DelGroupFromDb(osAccountId, groupId) != HC_SUCCESS) {
330         res = HC_ERR_DEL_GROUP;
331     }
332     DelAllTokens(osAccountId, &deviceList);
333     ClearDeviceEntryVec(&deviceList);
334     return res;
335 }
336 
GenerateTrustedDevParams(const CJson * jsonParams,const char * groupId,TrustedDeviceEntry * devParams)337 static int32_t GenerateTrustedDevParams(const CJson *jsonParams, const char *groupId, TrustedDeviceEntry *devParams)
338 {
339     int32_t result;
340     if (((result = AddUdidToParams(jsonParams, devParams)) != HC_SUCCESS) ||
341         ((result = AddAuthIdToParams(jsonParams, devParams)) != HC_SUCCESS) ||
342         ((result = AddCredTypeToParams(jsonParams, devParams)) != HC_SUCCESS) ||
343         ((result = AddUserIdToDevParams(jsonParams, devParams)) != HC_SUCCESS) ||
344         ((result = AddSourceToParams(IMPORTED_FROM_CLOUD, devParams)) != HC_SUCCESS) ||
345         ((result = AddUserTypeToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) ||
346         ((result = AddGroupIdToDevParams(groupId, devParams)) != HC_SUCCESS) ||
347         ((result = AddServiceTypeToParams(groupId, devParams)) != HC_SUCCESS)) {
348         return result;
349     }
350     return HC_SUCCESS;
351 }
352 
CheckPeerDeviceNotSelf(const CJson * deviceInfo)353 static int32_t CheckPeerDeviceNotSelf(const CJson *deviceInfo)
354 {
355     const char *udid = GetStringFromJson(deviceInfo, FIELD_UDID);
356     if (udid == NULL) {
357         LOGE("Failed to get udid from json!");
358         return HC_ERR_JSON_GET;
359     }
360     return AssertPeerDeviceNotSelf(udid);
361 }
362 
AddDeviceAndToken(int32_t osAccountId,const CJson * jsonParams,CJson * deviceInfo)363 static int32_t AddDeviceAndToken(int32_t osAccountId, const CJson *jsonParams, CJson *deviceInfo)
364 {
365     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
366     if (groupId == NULL) {
367         LOGE("Failed to get groupId from json!");
368         return HC_ERR_JSON_GET;
369     }
370     CJson *credential = GetObjFromJson(deviceInfo, FIELD_CREDENTIAL);
371     if (credential == NULL) {
372         LOGE("Failed to get credential from json!");
373         return HC_ERR_JSON_GET;
374     }
375     int32_t res = GenerateAddTokenParams(deviceInfo, credential);
376     if (res != HC_SUCCESS) {
377         return res;
378     }
379     res = ProcCred(ACCOUNT_RELATED_PLUGIN, osAccountId, IMPORT_TRUSTED_CREDENTIALS, credential, NULL);
380     if (res != HC_SUCCESS) {
381         LOGE("Failed to import device token! res: %d", res);
382         return res;
383     }
384     res = AddDeviceToDatabaseByJson(osAccountId, GenerateTrustedDevParams, deviceInfo, groupId);
385     if (res != HC_SUCCESS) {
386         LOGE("Failed to add device to database! res: %d", res);
387     }
388     return res;
389 }
390 
DelPeerDevice(int32_t osAccountId,CJson * jsonParams,CJson * deviceInfo,bool needDeleteToken)391 static int32_t DelPeerDevice(int32_t osAccountId, CJson *jsonParams, CJson *deviceInfo, bool needDeleteToken)
392 {
393     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
394     if (groupId == NULL) {
395         LOGE("Failed to get groupId from json!");
396         return HC_ERR_JSON_GET;
397     }
398     const char *deviceId = GetStringFromJson(deviceInfo, FIELD_DEVICE_ID);
399     if (deviceId == NULL) {
400         LOGE("Failed to get deviceId from json!");
401         return HC_ERR_JSON_GET;
402     }
403     TrustedDeviceEntry *entry = GetTrustedDeviceEntryById(osAccountId, deviceId, false, groupId);
404     if (entry == NULL) {
405         LOGE("Failed to get device from db!");
406         return HC_ERR_DEVICE_NOT_EXIST;
407     }
408     if (IsLocalDevice(StringGet(&entry->udid))) {
409         LOGE("Do not delete the local device!");
410         DestroyDeviceEntry(entry);
411         return HC_ERR_INVALID_PARAMS;
412     }
413     int32_t res = DelDeviceById(osAccountId, groupId, deviceId, false);
414     if (res != HC_SUCCESS) {
415         LOGE("Failed to delete device from database! res: %d", res);
416         DestroyDeviceEntry(entry);
417         return res;
418     }
419     if (needDeleteToken) {
420         res = DelDeviceToken(osAccountId, entry, false);
421     }
422     DestroyDeviceEntry(entry);
423     if (res != HC_SUCCESS) {
424         LOGE("Failed to delete token! res: %d", res);
425     }
426     return res;
427 }
428 
DelPeerDeviceAndToken(int32_t osAccountId,CJson * jsonParams,CJson * deviceInfo)429 static int32_t DelPeerDeviceAndToken(int32_t osAccountId, CJson *jsonParams, CJson *deviceInfo)
430 {
431     return DelPeerDevice(osAccountId, jsonParams, deviceInfo, true);
432 }
433 
CheckChangeParams(int32_t osAccountId,const char * appId,CJson * jsonParams)434 static int32_t CheckChangeParams(int32_t osAccountId, const char *appId, CJson *jsonParams)
435 {
436     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
437     if (groupId == NULL) {
438         LOGE("Failed to get groupId from json!");
439         return HC_ERR_JSON_GET;
440     }
441     uint32_t groupType;
442     int32_t result;
443     if (((result = CheckGroupExist(osAccountId, groupId)) != HC_SUCCESS) ||
444         ((result = GetGroupTypeFromDb(osAccountId, groupId, &groupType)) != HC_SUCCESS) ||
445         ((result = AssertGroupTypeMatch(groupType, IDENTICAL_ACCOUNT_GROUP)) != HC_SUCCESS) ||
446         ((result = CheckGroupEditAllowed(osAccountId, groupId, appId)) != HC_SUCCESS)) {
447         return result;
448     }
449     return HC_SUCCESS;
450 }
451 
AddGroupAndToken(int32_t osAccountId,CJson * jsonParams,const char * groupId)452 static int32_t AddGroupAndToken(int32_t osAccountId, CJson *jsonParams, const char *groupId)
453 {
454     int32_t res = AddGroupToDatabaseByJson(osAccountId, GenerateGroupParams, jsonParams, groupId);
455     if (res != HC_SUCCESS) {
456         LOGE("Failed to add group to database!");
457         return res;
458     }
459     res = ImportSelfToken(osAccountId, jsonParams);
460     if (res != HC_SUCCESS) {
461         LOGE("Failed to import self token!");
462         (void)DelGroupFromDb(osAccountId, groupId);
463         return res;
464     }
465     res = AddDeviceToDatabaseByJson(osAccountId, GenerateDevParams, jsonParams, groupId);
466     if (res != HC_SUCCESS) {
467         LOGE("Failed to add device to database!");
468         (void)DelGroupFromDb(osAccountId, groupId);
469         (void)DelSelfToken(osAccountId, jsonParams);
470         return res;
471     }
472     res = SaveOsAccountDb(osAccountId);
473     if (res != HC_SUCCESS) {
474         LOGE("Failed to save database!");
475         (void)DelGroupFromDb(osAccountId, groupId);
476         (void)DelSelfToken(osAccountId, jsonParams);
477     }
478     return res;
479 }
480 
CheckUserIdValid(int32_t osAccountId,const CJson * jsonParams,const CJson * deviceInfo)481 static int32_t CheckUserIdValid(int32_t osAccountId, const CJson *jsonParams, const CJson *deviceInfo)
482 {
483     const char *userId = GetStringFromJson(deviceInfo, FIELD_USER_ID);
484     if (userId == NULL) {
485         LOGE("Failed to get userId from json!");
486         return HC_ERR_JSON_GET;
487     }
488     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
489     if (groupId == NULL) {
490         LOGE("Failed to get groupId from json!");
491         return HC_ERR_JSON_GET;
492     }
493     uint32_t index;
494     TrustedGroupEntry **entry = NULL;
495     GroupEntryVec groupEntryVec = CreateGroupEntryVec();
496     QueryGroupParams params = InitQueryGroupParams();
497     params.groupId = groupId;
498     params.groupType = IDENTICAL_ACCOUNT_GROUP;
499     if (QueryGroups(osAccountId, &params, &groupEntryVec) != HC_SUCCESS) {
500         LOGE("Failed to query groups!");
501         ClearGroupEntryVec(&groupEntryVec);
502         return HC_ERR_DB;
503     }
504     FOR_EACH_HC_VECTOR(groupEntryVec, index, entry) {
505         if (strcmp(userId, StringGet(&(*entry)->userId)) == 0) {
506             ClearGroupEntryVec(&groupEntryVec);
507             return HC_SUCCESS;
508         }
509     }
510     LOGE("The input userId is inconsistent with the local userId!");
511     ClearGroupEntryVec(&groupEntryVec);
512     return HC_ERR_INVALID_PARAMS;
513 }
514 
CheckDeviceInfoValid(int32_t osAccountId,const CJson * jsonParams,const CJson * deviceInfo)515 static int32_t CheckDeviceInfoValid(int32_t osAccountId, const CJson *jsonParams, const CJson *deviceInfo)
516 {
517     int32_t res = CheckPeerDeviceNotSelf(deviceInfo);
518     if (res != HC_SUCCESS) {
519         LOGE("The peer device udid is equals to the local udid!");
520         return res;
521     }
522     /* Identical account group: input userId must be consistent with the local userId. */
523     return CheckUserIdValid(osAccountId, jsonParams, deviceInfo);
524 }
525 
CreateGroup(int32_t osAccountId,CJson * jsonParams,char ** returnJsonStr)526 static int32_t CreateGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr)
527 {
528     LOGI("[Start]: Start to create a identical account group!");
529     if ((jsonParams == NULL) || (returnJsonStr == NULL)) {
530         LOGE("The input parameters contains NULL value!");
531         return HC_ERR_INVALID_PARAMS;
532     }
533     char *groupId = NULL;
534     int32_t result;
535     if (((result = CheckCreateParams(osAccountId, jsonParams)) != HC_SUCCESS) ||
536         ((result = GenerateIdenticalGroupId(jsonParams, &groupId)) != HC_SUCCESS) ||
537         ((result = AssertSameGroupNotExist(osAccountId, groupId)) != HC_SUCCESS) ||
538         ((result = AddGroupAndToken(osAccountId, jsonParams, groupId)) != HC_SUCCESS) ||
539         ((result = ConvertGroupIdToJsonStr(groupId, returnJsonStr)) != HC_SUCCESS)) {
540         HcFree(groupId);
541         return result;
542     }
543     HcFree(groupId);
544     LOGI("[End]: Create a identical account group successfully!");
545     return HC_SUCCESS;
546 }
547 
DeleteGroup(int32_t osAccountId,CJson * jsonParams,char ** returnJsonStr)548 static int32_t DeleteGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr)
549 {
550     LOGI("[Start]: Start to delete a identical account group!");
551     if ((jsonParams == NULL) || (returnJsonStr == NULL)) {
552         LOGE("The input parameters contains NULL value!");
553         return HC_ERR_INVALID_PARAMS;
554     }
555     int32_t result;
556     const char *groupId = NULL;
557     if (((result = GetGroupIdFromJson(jsonParams, &groupId)) != HC_SUCCESS) ||
558         ((result = DelGroupAndTokens(osAccountId, groupId)) != HC_SUCCESS) ||
559         ((result = ConvertGroupIdToJsonStr(groupId, returnJsonStr)) != HC_SUCCESS)) {
560         return result;
561     }
562     LOGI("[End]: Delete a identical account group successfully!");
563     return HC_SUCCESS;
564 }
565 
UpdateTrustedDeviceForMetaNode(int32_t osAccountId,CJson * jsonParams,CJson * deviceList)566 static void UpdateTrustedDeviceForMetaNode(int32_t osAccountId, CJson *jsonParams, CJson *deviceList)
567 {
568     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
569     if (groupId == NULL) {
570         LOGE("Failed to get groupId from json!");
571         return;
572     }
573 
574     int32_t deviceNum = GetItemNum(deviceList);
575     int32_t addedCount = 0;
576     int32_t deletedCount = 0;
577     for (int32_t i = 0; i < deviceNum; i++) {
578         CJson *deviceInfo = GetItemFromArray(deviceList, i);
579         if (deviceInfo == NULL) {
580             LOGE("The deviceInfo is NULL!");
581             continue;
582         }
583         int32_t opCode = 0;
584         if (GetIntFromJson(deviceInfo, FIELD_GROUP_OP, &opCode) != HC_SUCCESS) {
585             LOGE("There is no group op code.");
586             continue;
587         }
588         if (CheckDeviceInfoValid(osAccountId, jsonParams, deviceInfo) != HC_SUCCESS) {
589             continue;
590         }
591         switch (opCode) {
592             case MEMBER_INVITE:
593             case MEMBER_JOIN:
594                 if (AddDeviceToDatabaseByJson(osAccountId, GenerateTrustedDevParams, deviceInfo, groupId) ==
595                     HC_SUCCESS) {
596                     addedCount++;
597                 }
598                 break;
599             case MEMBER_DELETE:
600                 if (DelPeerDevice(osAccountId, jsonParams, deviceInfo, false) == HC_SUCCESS) {
601                     deletedCount++;
602                 }
603                 break;
604             default:
605                 LOGE("Unknown group operate code: %d!", opCode);
606                 break;
607         }
608     }
609     if (addedCount > 0) {
610         LOGI("Add multiple members to a identical account group successfully! [ListNum]: %d, [AddedNum]: %d",
611             deviceNum, addedCount);
612     }
613     if (deletedCount > 0) {
614         LOGI("Delete multiple members from a identical account group successfully! [ListNum]: %d, [DeletedNum]: %d",
615             deviceNum, deletedCount);
616     }
617 }
618 
AddMetaNodeDeviceToGroup(int32_t osAccountId,CJson * jsonParams)619 static int32_t AddMetaNodeDeviceToGroup(int32_t osAccountId, CJson *jsonParams)
620 {
621     LOGI("[Start]: Start to add meta node device to a identical account group!");
622     CJson *processResult = CreateJson();
623     if (processResult == NULL) {
624         LOGE("Failed to allocate processResult memory!");
625         return HC_ERR_JSON_CREATE;
626     }
627     int32_t res = ProcCred(ACCOUNT_RELATED_PLUGIN, osAccountId, IMPORT_TRUSTED_CREDENTIALS, jsonParams, processResult);
628     if (res != HC_SUCCESS) {
629         LOGE("Failed to import device token! res: %d", res);
630         FreeJson(processResult);
631         return res;
632     }
633 
634     CJson *deviceList = GetObjFromJson(processResult, FIELD_DEVICE_LIST);
635     if (deviceList == NULL) {
636         LOGE("Failed to get deviceList from json!");
637         FreeJson(processResult);
638         return HC_ERR_JSON_GET;
639     }
640     UpdateTrustedDeviceForMetaNode(osAccountId, jsonParams, deviceList);
641     FreeJson(processResult);
642 
643     res = SaveOsAccountDb(osAccountId);
644     if (res != HC_SUCCESS) {
645         LOGE("Failed to save database!");
646         return res;
647     }
648     LOGI("[End]: Add meta node device successfully!");
649     return HC_SUCCESS;
650 }
651 
AddMultiMembersToGroup(int32_t osAccountId,const char * appId,CJson * jsonParams)652 static int32_t AddMultiMembersToGroup(int32_t osAccountId, const char *appId, CJson *jsonParams)
653 {
654     LOGI("[Start]: Start to add multiple members to a identical account group!");
655     if ((appId == NULL) || (jsonParams == NULL)) {
656         LOGE("Invalid params!");
657         return HC_ERR_INVALID_PARAMS;
658     }
659     int32_t res = CheckChangeParams(osAccountId, appId, jsonParams);
660     if (res != HC_SUCCESS) {
661         return res;
662     }
663 
664     const char *metaNodeType = GetStringFromJson(jsonParams, FIELD_META_NODE_TYPE);
665     if (metaNodeType != NULL) {
666         LOGI("Find MetaNodeType: %s", metaNodeType);
667         return AddMetaNodeDeviceToGroup(osAccountId, jsonParams);
668     }
669 
670     CJson *deviceList = GetObjFromJson(jsonParams, FIELD_DEVICE_LIST);
671     if (deviceList == NULL) {
672         LOGE("Failed to get deviceList from json!");
673         return HC_ERR_JSON_GET;
674     }
675     int32_t deviceNum = GetItemNum(deviceList);
676     int32_t addedCount = 0;
677     for (int32_t i = 0; i < deviceNum; i++) {
678         CJson *deviceInfo = GetItemFromArray(deviceList, i);
679         if (deviceInfo == NULL) {
680             LOGE("The deviceInfo is NULL!");
681             continue;
682         }
683         if (CheckDeviceInfoValid(osAccountId, jsonParams, deviceInfo) != HC_SUCCESS) {
684             continue;
685         }
686         if (AddDeviceAndToken(osAccountId, jsonParams, deviceInfo) == HC_SUCCESS) {
687             addedCount++;
688         }
689     }
690     res = SaveOsAccountDb(osAccountId);
691     if (res != HC_SUCCESS) {
692         LOGE("Failed to save database!");
693         return res;
694     }
695     LOGI("[End]: Add multiple members to a identical account group successfully! [ListNum]: %d, [AddedNum]: %d",
696         deviceNum, addedCount);
697     return HC_SUCCESS;
698 }
699 
DelMultiMembersFromGroup(int32_t osAccountId,const char * appId,CJson * jsonParams)700 static int32_t DelMultiMembersFromGroup(int32_t osAccountId, const char *appId, CJson *jsonParams)
701 {
702     LOGI("[Start]: Start to delete multiple members from a identical account group!");
703     if ((appId == NULL) || (jsonParams == NULL)) {
704         LOGE("Invalid params!");
705         return HC_ERR_INVALID_PARAMS;
706     }
707     int32_t res = CheckChangeParams(osAccountId, appId, jsonParams);
708     if (res != HC_SUCCESS) {
709         return res;
710     }
711     CJson *deviceList = GetObjFromJson(jsonParams, FIELD_DEVICE_LIST);
712     if (deviceList == NULL) {
713         LOGE("Failed to get deviceList from json!");
714         return HC_ERR_JSON_GET;
715     }
716     int32_t deviceNum = GetItemNum(deviceList);
717     int32_t deletedCount = 0;
718     for (int32_t i = 0; i < deviceNum; i++) {
719         CJson *deviceInfo = GetItemFromArray(deviceList, i);
720         if (deviceInfo == NULL) {
721             LOGE("The deviceInfo is NULL!");
722             continue;
723         }
724         if (DelPeerDeviceAndToken(osAccountId, jsonParams, deviceInfo) == HC_SUCCESS) {
725             deletedCount++;
726         }
727     }
728     res = SaveOsAccountDb(osAccountId);
729     if (res != HC_SUCCESS) {
730         LOGE("Failed to save database!");
731         return res;
732     }
733     LOGI("[End]: Delete multiple members from a identical account group successfully! [ListNum]: %d, [DeletedNum]: %d",
734         deviceNum, deletedCount);
735     return HC_SUCCESS;
736 }
737 
738 static IdenticalAccountGroup g_identicalAccountGroup = {
739     .base.type = IDENTICAL_ACCOUNT_GROUP,
740     .base.createGroup = CreateGroup,
741     .base.deleteGroup = DeleteGroup,
742     .addMultiMembersToGroup = AddMultiMembersToGroup,
743     .delMultiMembersFromGroup = DelMultiMembersFromGroup,
744 };
745 
GetIdenticalAccountGroupInstance(void)746 BaseGroup *GetIdenticalAccountGroupInstance(void)
747 {
748     return (BaseGroup *)&g_identicalAccountGroup;
749 }
750 
IsIdenticalAccountGroupSupported(void)751 bool IsIdenticalAccountGroupSupported(void)
752 {
753     return true;
754 }