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