• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "cm_event_process.h"
17 
18 #include <dirent.h>
19 #include <sys/stat.h>
20 
21 #include "securec.h"
22 
23 #include "cert_manager.h"
24 #include "cert_manager_auth_mgr.h"
25 #include "cert_manager_file_operator.h"
26 #include "cert_manager_key_operation.h"
27 #include "cert_manager_session_mgr.h"
28 #include "cert_manager_status.h"
29 #include "cert_manager_storage.h"
30 #include "cert_manager_query.h"
31 #include "cm_cert_property_rdb.h"
32 #include "cm_log.h"
33 #include "cm_type.h"
34 #include "cm_util.h"
35 
36 // LCOV_EXCL_START
DeleteAuth(const struct CmContext * context,const char * fileName,bool isDeleteByUid)37 static void DeleteAuth(const struct CmContext *context, const char *fileName, bool isDeleteByUid)
38 {
39     CM_LOG_D("isDeleteByUid:%d", isDeleteByUid);
40     struct CmBlob keyUri = { strlen(fileName) + 1, (uint8_t *)fileName };
41 
42     int32_t ret;
43     if (isDeleteByUid) {
44         ret = CmAuthDeleteAuthInfoByUid(context->userId, context->uid, &keyUri);
45     } else {
46         ret = CmAuthDeleteAuthInfoByUserId(context->userId, &keyUri);
47     }
48     if (ret != CM_SUCCESS) {
49         CM_LOG_E("delete auth info failed ret: %d", ret); /* only record logs */
50     }
51     return;
52 }
53 
CmTraversalDirActionCredential(const char * filePath,const char * fileName)54 static int32_t CmTraversalDirActionCredential(const char *filePath, const char *fileName)
55 {
56     int32_t ret = remove(filePath);
57     if (ret != CM_SUCCESS) {
58         CM_LOG_E("App cert delete faild, ret: %d", ret);
59         return ret;
60     }
61 
62     struct CmBlob keyUri = { strlen(fileName) + 1, (uint8_t *)fileName };
63     enum CmAuthStorageLevel level;
64     ret = GetRdbAuthStorageLevel(&keyUri, &level);
65     if (ret != CM_SUCCESS) {
66         CM_LOG_E("get storage level failed, ret: %d", ret);
67         return ret;
68     }
69     if (level == ERROR_LEVEL) {
70         level = CM_AUTH_STORAGE_LEVEL_EL1;
71         CM_LOG_I("Traversal dir level is ERROR_LEVEL, change to default level el1");
72     }
73 
74     ret = CmKeyOpDeleteKey(&keyUri, level);
75     if (ret != CM_SUCCESS) { /* ignore the return of delete key */
76         CM_LOG_E("App key delete failed ret: %d", ret);
77     }
78     return CM_SUCCESS;
79 }
80 
CmTraversalDirActionUserCa(const struct CmContext * context,const char * filePath,const char * fileName,const uint32_t store)81 static int32_t CmTraversalDirActionUserCa(const struct CmContext *context, const char *filePath, const char *fileName,
82     const uint32_t store)
83 {
84     int32_t ret = remove(filePath);
85     if (ret != CM_SUCCESS) {
86         CM_LOG_E("User cert delete faild, ret: %d", ret);
87         return ret;
88     }
89 
90     ret = DeleteCertProperty(fileName);
91     if (ret != CM_SUCCESS) {
92         CM_LOG_E("delete user ca cert property failed, ret: %d", ret);
93         return ret;
94     }
95 
96     return CM_SUCCESS;
97 }
98 
CmTraversalDirAction(const struct CmContext * context,const char * filePath,const char * fileName,const uint32_t store)99 static int32_t CmTraversalDirAction(const struct CmContext *context, const char *filePath,
100     const char *fileName, const uint32_t store)
101 {
102     int32_t ret = CM_SUCCESS;
103 
104     switch (store) {
105         case CM_CREDENTIAL_STORE:
106             DeleteAuth(context, fileName, false);
107             __attribute__((fallthrough));
108         case CM_PRI_CREDENTIAL_STORE:
109         case CM_SYS_CREDENTIAL_STORE:
110             ret = CmTraversalDirActionCredential(filePath, fileName);
111             break;
112         case CM_USER_TRUSTED_STORE:
113             ret = CmTraversalDirActionUserCa(context, filePath, fileName, store);
114             break;
115         default:
116             break;
117     }
118     if (ret != CM_SUCCESS) {
119         CM_LOG_E("CmTraversalDirAction failed store:%u", store);
120     }
121 
122     return CM_SUCCESS;
123 }
124 
GetNextLayerPath(const char * path,const char * name,char * outPath,uint32_t outPathLen)125 static int32_t GetNextLayerPath(const char *path, const char *name, char *outPath, uint32_t outPathLen)
126 {
127     if (strncpy_s(outPath, outPathLen, path, strlen(path)) != EOK) {
128         return CMR_ERROR_MEM_OPERATION_PRINT;
129     }
130     if (outPath[strlen(outPath) - 1] != '/') {
131         if (strncat_s(outPath, outPathLen, "/", strlen("/")) != EOK) {
132             return CMR_ERROR_MEM_OPERATION_PRINT;
133         }
134     }
135     if (strncat_s(outPath, outPathLen, name, strlen(name)) != EOK) {
136         return CMR_ERROR_MEM_OPERATION_PRINT;
137     }
138     return CM_SUCCESS;
139 }
140 
RemoveDir(const char * dirPath)141 static int32_t RemoveDir(const char *dirPath)
142 {
143     struct stat fileStat;
144     int32_t ret = stat(dirPath, &fileStat);
145     if (ret != 0) {
146         return CMR_ERROR_FILE_STAT;
147     }
148 
149     if (!S_ISDIR(fileStat.st_mode)) {
150         return CMR_ERROR_INVALID_ARGUMENT;
151     }
152 
153     DIR *dir = opendir(dirPath);
154     if (dir  == NULL) {
155         return CMR_ERROR_FILE_OPEN_DIR;
156     }
157 
158     struct dirent *dire = readdir(dir);
159     while (dire != NULL) {
160         if (dire->d_type == DT_REG) { /* only care about files. */
161             ret = CmFileRemove(dirPath, dire->d_name);
162             if (ret != CM_SUCCESS) { /* Continue to delete remaining files */
163                 CM_LOG_E("remove file failed when remove authlist files, ret = %d.", ret);
164             }
165         }
166         dire = readdir(dir);
167     }
168     (void)closedir(dir);
169     (void)remove(dirPath);
170     return CM_SUCCESS;
171 }
172 
RemoveAuthListDir(const char * path,const uint32_t store,bool isSameUid)173 static void RemoveAuthListDir(const char *path, const uint32_t store, bool isSameUid)
174 {
175     if (!isSameUid || (store != CM_CREDENTIAL_STORE)) {
176         return;
177     }
178 
179     char authListPath[CM_MAX_FILE_NAME_LEN] = {0};
180     char name[] = "authlist";
181     int32_t ret = GetNextLayerPath(path, name, authListPath, sizeof(authListPath));
182     if (ret != CM_SUCCESS) {
183         return;
184     }
185 
186     RemoveDir(authListPath);
187 }
188 
TraversalUidLayerDir(const struct CmContext * context,const char * uidPath,const char * direName,const uint32_t store,bool isSameUid)189 static void TraversalUidLayerDir(const struct CmContext *context, const char *uidPath, const char *direName,
190     const uint32_t store, bool isSameUid)
191 {
192     if (!isSameUid) {
193         if (store == CM_CREDENTIAL_STORE) { /* remove deleted uid from authlist */
194             DeleteAuth(context, direName, true);
195         }
196     } else {
197         (void)CmTraversalDirAction(context, uidPath, direName, store);
198     }
199 }
200 
CmTraversalUidLayerDir(const struct CmContext * context,const char * path,const uint32_t store,bool isSameUid)201 static int32_t CmTraversalUidLayerDir(const struct CmContext *context, const char *path,
202     const uint32_t store, bool isSameUid)
203 {
204     int32_t ret = CM_SUCCESS;
205     /* do nothing when dir is not exist */
206     if (CmIsDirExist(path) != CMR_OK) {
207         CM_LOG_D("Dir is not exist");
208         return CM_SUCCESS;
209     }
210 
211     DIR *dir = opendir(path);
212     if (dir  == NULL) {
213         CM_LOG_E("open dir failed");
214         return CMR_ERROR_OPEN_FILE_FAIL;
215     }
216 
217     struct dirent *dire = readdir(dir);
218     while (dire != NULL) {
219         char uidPath[CM_MAX_FILE_NAME_LEN] = {0};
220         if (GetNextLayerPath(path, dire->d_name, uidPath, sizeof(uidPath)) != CM_SUCCESS) {
221             closedir(dir);
222             return CMR_ERROR_MEM_OPERATION_PRINT;
223         }
224 
225         if ((strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0) && (dire->d_type == DT_REG)) {
226             TraversalUidLayerDir(context, uidPath, dire->d_name, store, isSameUid);
227         }
228         dire = readdir(dir);
229     }
230     closedir(dir);
231 
232     /* remove authList Path */
233     RemoveAuthListDir(path, store, isSameUid);
234 
235     if (isSameUid) {
236         ret = remove(path);
237     }
238     return ret;
239 }
240 
TraversalUserIdLayerDir(const struct CmContext * context,const char * userIdPath,const char * direName,const uint32_t store,bool isUserDeleteEvent)241 static int32_t TraversalUserIdLayerDir(const struct CmContext *context, const char *userIdPath, const char *direName,
242     const uint32_t store, bool isUserDeleteEvent)
243 {
244     uint32_t uid = 0;
245     if (CmIsNumeric(direName, strlen(direName) + 1, &uid) != CM_SUCCESS) {
246         CM_LOG_E("parse string to uint32 failed.");
247         return CMR_ERROR_INVALID_ARGUMENT;
248     }
249 
250     CM_LOG_D("CmTraversalUserIdLayerDir userId:%u, uid:%u", context->userId, uid);
251 
252     int32_t ret = CM_SUCCESS;
253     if (isUserDeleteEvent) { /* user delete event */
254         struct CmContext userContext = { context->userId, uid, {0} };
255         ret = CmTraversalUidLayerDir(&userContext, userIdPath, store, true);
256     } else { /* package delete event */
257         if (uid == context->uid) {
258             ret = CmTraversalUidLayerDir(context, userIdPath, store, true);
259         } else if (store == CM_CREDENTIAL_STORE) {
260             ret = CmTraversalUidLayerDir(context, userIdPath, store, false);
261         } else {
262             /* do nothing */
263         }
264     }
265     return ret;
266 }
267 
CmTraversalUserIdLayerDir(const struct CmContext * context,const char * path,const uint32_t store)268 static int32_t CmTraversalUserIdLayerDir(const struct CmContext *context, const char *path, const uint32_t store)
269 {
270     bool isUserDeleteEvent = (context->uid == INVALID_VALUE);
271     int32_t ret = CM_SUCCESS;
272 
273     /* do nothing when dir is not exist */
274     if (CmIsDirExist(path) != CMR_OK) {
275         CM_LOG_D("UserId dir is not exist");
276         return CM_SUCCESS;
277     }
278 
279     DIR *dir = opendir(path);
280     if (dir  == NULL) {
281         CM_LOG_E("Open userId dir failed");
282         return CMR_ERROR_OPEN_FILE_FAIL;
283     }
284 
285     struct dirent *dire = readdir(dir);
286     while (dire != NULL) {
287         char userIdPath[CM_MAX_FILE_NAME_LEN] = {0};
288         if (GetNextLayerPath(path, dire->d_name, userIdPath, sizeof(userIdPath)) != CM_SUCCESS) {
289             closedir(dir);
290             return CMR_ERROR_MEM_OPERATION_PRINT;
291         }
292 
293         if (dire->d_type == DT_DIR && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
294             (void)TraversalUserIdLayerDir(context, userIdPath, dire->d_name, store, isUserDeleteEvent);
295         } else if (dire->d_type != DT_DIR) {
296             (void)remove(userIdPath);
297         }
298         dire = readdir(dir);
299     }
300     closedir(dir);
301 
302     /* delete userId directory only in user remove event */
303     if (isUserDeleteEvent) {
304         ret = remove(path);
305     }
306 
307     return ret;
308 }
309 
CmTraversalDir(const struct CmContext * context,const char * path,const uint32_t store)310 static int32_t CmTraversalDir(const struct CmContext *context, const char *path, const uint32_t store)
311 {
312     int32_t ret = CM_SUCCESS;
313     /* do nothing when dir is not exist */
314     if (CmIsDirExist(path) != CMR_OK) {
315         CM_LOG_D("Root dir is not exist");
316         return CM_SUCCESS;
317     }
318 
319     DIR *dir = opendir(path);
320     if (dir  == NULL) {
321         CM_LOG_E("open dir failed");
322         return CMR_ERROR_OPEN_FILE_FAIL;
323     }
324 
325     uint32_t uid = 0;
326     struct dirent *dire = readdir(dir);
327     while (dire != NULL) {
328         char deletePath[CM_MAX_FILE_NAME_LEN] = { 0 };
329         if (GetNextLayerPath(path, dire->d_name, deletePath, sizeof(deletePath)) != CM_SUCCESS) {
330             closedir(dir);
331             return CMR_ERROR_MEM_OPERATION_PRINT;
332         }
333 
334         if (CmIsNumeric(dire->d_name, strlen(dire->d_name) + 1, &uid) != CM_SUCCESS) {
335             CM_LOG_E("parse string to uint32 failed.");
336             dire = readdir(dir);
337             continue;
338         }
339 
340         if (dire->d_type == DT_DIR && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0) &&
341             (uid == context->userId)) {
342             ret = CmTraversalUserIdLayerDir(context, deletePath, store);
343         } else if (dire->d_type != DT_DIR) {
344             (void)remove(deletePath);
345         }
346         dire = readdir(dir);
347     }
348     closedir(dir);
349 
350     return ret;
351 }
352 
CmTraversalBackupUidDir(const char * certConfigUidDirPath)353 static int32_t CmTraversalBackupUidDir(const char *certConfigUidDirPath)
354 {
355     if (certConfigUidDirPath == NULL) {
356         CM_LOG_E("input params is invalid");
357         return CMR_ERROR_INVALID_ARGUMENT;
358     }
359 
360     uint32_t fileCounts = 0;
361     struct CmBlob fileNames[MAX_COUNT_CERTIFICATE] = { 0 };
362     /* Gets all files under the certConfigUidDirPath */
363     int32_t ret = CmUidLayerGetFileCountAndNames(certConfigUidDirPath, fileNames, MAX_COUNT_CERTIFICATE, &fileCounts);
364     if (ret != CM_SUCCESS) {
365         CM_LOG_E("Get file count and names for the certConfigUidDirPath, ret = %d", ret);
366         return ret;
367     }
368 
369     for (uint32_t i = 0; i < fileCounts; i++) {
370         struct CmBlob *certConfigFilePath = &fileNames[i];
371 
372         /* Delete user cert backup and config file */
373         ret = CmRemoveBackupUserCert(NULL, NULL, (const char *)certConfigFilePath->data);
374         if (ret != CM_SUCCESS) {
375             CM_LOG_E("CmRemoveBackupUserCert failed");
376             continue;
377         }
378     }
379 
380     CmFreeFileNames(fileNames, fileCounts);
381 
382     return CM_SUCCESS;
383 }
384 
CmTraversalBackupUserIdDir(const char * certConfigUserIdDirPath)385 static int32_t CmTraversalBackupUserIdDir(const char *certConfigUserIdDirPath)
386 {
387     if (certConfigUserIdDirPath == NULL) {
388         CM_LOG_E("input params is invalid");
389         return CMR_ERROR_INVALID_ARGUMENT;
390     }
391 
392     DIR *dir = opendir(certConfigUserIdDirPath);
393     if (dir == NULL) {
394         CM_LOG_E("opendir certConfigUserIdDirPath failed");
395         return CM_FAILURE;
396     }
397 
398     int32_t ret = CM_SUCCESS;
399     struct dirent *dire = NULL;
400     /* Traverse the {configRootDir}/{userid} directory */
401     while ((dire = readdir(dir)) != NULL) {
402         if ((strcmp(dire->d_name, ".") == 0) || (strcmp(dire->d_name, "..") == 0)) {
403             continue;
404         }
405         char certConfigUidDirPath[CERT_MAX_PATH_LEN] = { 0 };
406         if (snprintf_s(certConfigUidDirPath, CERT_MAX_PATH_LEN, CERT_MAX_PATH_LEN - 1, "%s/%s", certConfigUserIdDirPath,
407                        dire->d_name) < 0) {
408             CM_LOG_E("Construct certConfigUidDirPath failed");
409             continue;
410         }
411 
412         ret = CmTraversalBackupUidDir(certConfigUidDirPath);
413         if (ret != CM_SUCCESS) {
414             CM_LOG_E("CmTraversalBackupUidDir failed, ret = %d", ret);
415             continue;
416         }
417 
418         /* Delete user cert config {configRootDir}/{userid}/{uid} directory */
419         ret = CmDirRemove(certConfigUidDirPath);
420         if (ret != CM_SUCCESS) {
421             CM_LOG_E("Remove user certConfigUidDirPath fail, ret = %d", ret);
422             continue;
423         }
424     };
425 
426     closedir(dir);
427     return CM_SUCCESS;
428 }
429 
CmTraversalBackupUserCert(uint32_t userId)430 static int32_t CmTraversalBackupUserCert(uint32_t userId)
431 {
432     int32_t ret = CM_SUCCESS;
433     char certConfigUserIdDirPath[CERT_MAX_PATH_LEN] = { 0 };
434     ret = CmGetCertConfUserIdDir(userId, certConfigUserIdDirPath, CERT_MAX_PATH_LEN);
435     if (ret != CM_SUCCESS) {
436         CM_LOG_E("Construct certConfigUserIdDirPath(userId: %u) failed", userId);
437         return CM_FAILURE;
438     }
439 
440     ret = CmTraversalBackupUserIdDir(certConfigUserIdDirPath);
441     if (ret != CM_SUCCESS) {
442         CM_LOG_E("CmTraversalBackupUserIdDir failed, ret = %d", ret);
443         return CM_FAILURE;
444     }
445 
446     /* Delete {configRootDir}/{userid} directory */
447     ret = CmDirRemove(certConfigUserIdDirPath);
448     if (ret != CM_SUCCESS) {
449         CM_LOG_E("Remove user certConfigUserIdDirPath fail, ret = %d", ret);
450         return CMR_ERROR_REMOVE_FILE_FAIL;
451     }
452 
453     /* Delete {backupRootDir}/{userid} directory */
454     char certBackupUserIdDirPath[CERT_MAX_PATH_LEN] = { 0 };
455     ret = CmGetCertBackupDir(userId, certBackupUserIdDirPath, CERT_MAX_PATH_LEN);
456     if (ret != CM_SUCCESS) {
457         CM_LOG_E("Construct certBackupUserIdDirPath failed");
458         return CM_FAILURE;
459     }
460     ret = CmDirRemove(certBackupUserIdDirPath);
461     if (ret != CM_SUCCESS) {
462         CM_LOG_E("Remove user certBackupUserIdDirPath fail, ret = %d", ret);
463         return CMR_ERROR_REMOVE_FILE_FAIL;
464     }
465 
466     return CM_SUCCESS;
467 }
468 
RemoveSessionInfo(const struct CmContext * context)469 static void RemoveSessionInfo(const struct CmContext *context)
470 {
471     bool isUserDeleteEvent = (context->uid == INVALID_VALUE);
472 
473     if (isUserDeleteEvent) {
474         /* remove session node by user id */
475         struct CmSessionNodeInfo info = { context->userId, 0, { 0, NULL } };
476         CmDeleteSessionByNodeInfo(DELETE_SESSION_BY_USERID, &info);
477     } else {
478         /* remove session node by uid */
479         struct CmSessionNodeInfo info = { context->userId, context->uid, { 0, NULL } };
480         CmDeleteSessionByNodeInfo(DELETE_SESSION_BY_UID, &info);
481     }
482 }
483 
CmDeleteProcessInfo(const struct CmContext * context)484 int32_t CmDeleteProcessInfo(const struct CmContext *context)
485 {
486     RemoveSessionInfo(context);
487 
488     int32_t ret = CM_SUCCESS;
489     if (context->uid == INVALID_VALUE) { // user delete event
490         /* Delete user ca */
491         ret = CmTraversalDir(context, USER_CA_STORE, CM_USER_TRUSTED_STORE);
492         if (ret != CM_SUCCESS) {
493             CM_LOG_E("CmDeleteUserCa failed");
494         }
495 
496         /* Delete user ca backup and config */
497         ret = CmTraversalBackupUserCert(context->userId);
498         if (ret != CM_SUCCESS) {
499             CM_LOG_E("Delete user ca backup and config file failed");
500         }
501     }
502 
503     /* Delete private credentail */
504     ret = CmTraversalDir(context, PRI_CREDNTIAL_STORE, CM_PRI_CREDENTIAL_STORE);
505     if (ret != CM_SUCCESS) {
506         CM_LOG_E("CmDeletePrivateCredential failed");
507     }
508 
509     /* Delete public credentail */
510     ret = CmTraversalDir(context, CREDNTIAL_STORE, CM_CREDENTIAL_STORE);
511     if (ret != CM_SUCCESS) {
512         CM_LOG_E("CmDeletePublicCredential failed");
513     }
514 
515     /* Delete system credentail*/
516     ret = CmTraversalDir(context, SYS_CREDNTIAL_STORE, CM_SYS_CREDENTIAL_STORE);
517     if (ret != CM_SUCCESS) {
518         CM_LOG_E("CmDeleteSystemCredential failed");
519     }
520 
521     return ret;
522 }
523 // LCOV_EXCL_STOP