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