• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "cert_manager_file_operator.h"
17 
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <limits.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include "securec.h"
26 
27 #include "cert_manager_mem.h"
28 #include "cm_log.h"
29 
GetFileName(const char * path,const char * fileName,char * fullFileName,uint32_t fullFileNameLen)30 static int32_t GetFileName(const char *path, const char *fileName, char *fullFileName, uint32_t fullFileNameLen)
31 {
32     if (path != NULL) {
33         if (strncpy_s(fullFileName, fullFileNameLen, path, strlen(path)) != EOK) {
34             return CMR_ERROR_INVALID_OPERATION;
35         }
36 
37         if (path[strlen(path) - 1] != '/') {
38             if (strncat_s(fullFileName, fullFileNameLen, "/", strlen("/")) != EOK) {
39                 return CMR_ERROR_INVALID_OPERATION;
40             }
41         }
42 
43         if (strncat_s(fullFileName, fullFileNameLen, fileName, strlen(fileName)) != EOK) {
44             return CMR_ERROR_INVALID_OPERATION;
45         }
46     } else {
47         if (strncpy_s(fullFileName, fullFileNameLen, fileName, strlen(fileName)) != EOK) {
48             return CMR_ERROR_INVALID_OPERATION;
49         }
50     }
51     return CMR_OK;
52 }
53 
GetFullFileName(const char * path,const char * fileName,char ** fullFileName)54 static int32_t GetFullFileName(const char *path, const char *fileName, char **fullFileName)
55 {
56     uint32_t nameLen = CM_MAX_FILE_NAME_LEN;
57     char *tmpFileName = (char *)CMMalloc(nameLen);
58     if (tmpFileName == NULL) {
59         return CMR_ERROR_MALLOC_FAIL;
60     }
61     (void)memset_s(tmpFileName, nameLen, 0, nameLen);
62 
63     int32_t ret = GetFileName(path, fileName, tmpFileName, nameLen);
64     if (ret != CMR_OK) {
65         CM_LOG_E("get full fileName failed");
66         CM_FREE_PTR(tmpFileName);
67         return ret;
68     }
69     *fullFileName = tmpFileName;
70 
71     return CMR_OK;
72 }
73 
IsFileExist(const char * fileName)74 static int32_t IsFileExist(const char *fileName)
75 {
76     if (access(fileName, F_OK) != 0) {
77         return CMR_ERROR_NOT_EXIST;
78     }
79 
80     return CMR_OK;
81 }
82 
CmIsDirExist(const char * path)83 int32_t CmIsDirExist(const char *path)
84 {
85     if (path == NULL) {
86         return CMR_ERROR_NULL_POINTER;
87     }
88     return IsFileExist(path);
89 }
90 
FileRead(const char * fileName,uint32_t offset,uint8_t * buf,uint32_t len)91 static uint32_t FileRead(const char *fileName, uint32_t offset, uint8_t *buf, uint32_t len)
92 {
93     (void)offset;
94     if (IsFileExist(fileName) != CMR_OK) {
95         return 0;
96     }
97     if (strstr(fileName, "../") != NULL) {
98         CM_LOG_E("invalid filePath");
99         return 0;
100     }
101 
102     char filePath[PATH_MAX + 1] = {0};
103     if (realpath(fileName, filePath) == NULL) {
104         CM_LOG_E("invalid filepath: %s", fileName);
105         return 0;
106     }
107 
108     FILE *fp = fopen(filePath, "rb");
109     if (fp == NULL) {
110         CM_LOG_E("failed to open file");
111         return 0;
112     }
113 
114     uint32_t size = fread(buf, 1, len, fp);
115     if (fclose(fp) < 0) {
116         CM_LOG_E("failed to close file");
117         return 0;
118     }
119 
120     return size;
121 }
122 
FileSize(const char * fileName)123 static uint32_t FileSize(const char *fileName)
124 {
125     if (IsFileExist(fileName) != CMR_OK) {
126         CM_LOG_E("file IsFileExist fail.");
127         return 0;
128     }
129 
130     struct stat fileStat;
131     (void)memset_s(&fileStat, sizeof(fileStat), 0, sizeof(fileStat));
132 
133     if (stat(fileName, &fileStat) != 0) {
134         CM_LOG_E("file stat fail.");
135         return 0;
136     }
137 
138     return (uint32_t)fileStat.st_size;
139 }
140 
FileWrite(const char * fileName,uint32_t offset,const uint8_t * buf,uint32_t len)141 static int32_t FileWrite(const char *fileName, uint32_t offset, const uint8_t *buf, uint32_t len)
142 {
143     (void)offset;
144     char filePath[PATH_MAX + 1] = {0};
145     if (memcpy_s(filePath, sizeof(filePath) - 1, fileName, strlen(fileName)) != EOK) {
146         return CMR_ERROR_INVALID_OPERATION;
147     }
148     if (strstr(filePath, "../") != NULL) {
149         CM_LOG_E("invalid filePath");
150         return CMR_ERROR_NOT_EXIST;
151     }
152     /* Ignore return value: realpath will return null in musl c when the file does not exist */
153     (void)realpath(fileName, filePath);
154 
155     int32_t fd = open(filePath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
156     if (fd < 0) {
157         CM_LOG_E("open file failed, errno = 0x%x", errno);
158         return CMR_ERROR_OPEN_FILE_FAIL;
159     }
160 
161     int32_t size = write(fd, buf, len);
162     if (size < 0) {
163         CM_LOG_E("write file failed, errno = 0x%x", errno);
164         close(fd);
165         return CMR_ERROR_WRITE_FILE_FAIL;
166     }
167     if (fsync(fd) < 0) {
168         CM_LOG_E("sync file failed");
169         close(fd);
170         return CMR_ERROR_WRITE_FILE_FAIL;
171     }
172     close(fd);
173     return CMR_OK;
174 }
175 
FileRemove(const char * fileName)176 static int32_t FileRemove(const char *fileName)
177 {
178     int32_t ret = IsFileExist(fileName);
179     if (ret != CMR_OK) {
180         return CMR_OK; /* if file not exist, return ok */
181     }
182 
183     struct stat tmp;
184     if (stat(fileName, &tmp) != 0) {
185         return CMR_ERROR_INVALID_OPERATION;
186     }
187 
188     if (S_ISDIR(tmp.st_mode)) {
189         return CMR_ERROR_INVALID_ARGUMENT;
190     }
191 
192     if ((unlink(fileName) != 0) && (errno != ENOENT)) {
193         CM_LOG_E("failed to remove file: errno = 0x%x", errno);
194         return CMR_ERROR_REMOVE_FILE_FAIL;
195     }
196 
197     return CMR_OK;
198 }
199 
CmFileRemove(const char * path,const char * fileName)200 int32_t CmFileRemove(const char *path, const char *fileName)
201 {
202     if (fileName == NULL) {
203         return CMR_ERROR_INVALID_ARGUMENT;
204     }
205 
206     char *fullFileName = NULL;
207     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
208     if (ret != CMR_OK) {
209         return ret;
210     }
211 
212     ret = FileRemove(fullFileName);
213     CM_FREE_PTR(fullFileName);
214     return ret;
215 }
216 
CmMakeDir(const char * path)217 int32_t CmMakeDir(const char *path)
218 {
219     if ((access(path, F_OK)) != -1) {
220         CM_LOG_I("path exist");
221         return CMR_OK;
222     }
223 
224     if (mkdir(path, S_IRWXU) == 0) {
225         return CMR_OK;
226     } else {
227         if (errno == EEXIST  || errno == EAGAIN) {
228             return CMR_ERROR_ALREADY_EXISTS;
229         } else {
230             return CMR_ERROR_MAKE_DIR_FAIL;
231         }
232     }
233 }
234 
CmOpenDir(const char * path)235 void *CmOpenDir(const char *path)
236 {
237     return (void *)opendir(path);
238 }
239 
CmCloseDir(void * dirp)240 int32_t CmCloseDir(void *dirp)
241 {
242     return closedir((DIR *)dirp);
243 }
244 
CmGetDirFile(void * dirp,struct CmFileDirentInfo * direntInfo)245 int32_t CmGetDirFile(void *dirp, struct CmFileDirentInfo *direntInfo)
246 {
247     DIR *dir = (DIR *)dirp;
248     struct dirent *dire = readdir(dir);
249 
250     while (dire != NULL) {
251         if (dire->d_type != DT_REG) { /* only care about files. */
252             dire = readdir(dir);
253             continue;
254         }
255 
256         uint32_t len = strlen(dire->d_name);
257         if (memcpy_s(direntInfo->fileName, sizeof(direntInfo->fileName) - 1, dire->d_name, len) != EOK) {
258             return CMR_ERROR_INVALID_OPERATION;
259         }
260         direntInfo->fileName[len] = '\0';
261         return CMR_OK;
262     }
263 
264     return CMR_ERROR_NOT_EXIST;
265 }
266 
CmFileRead(const char * path,const char * fileName,uint32_t offset,uint8_t * buf,uint32_t len)267 uint32_t CmFileRead(const char *path, const char *fileName, uint32_t offset, uint8_t *buf, uint32_t len)
268 {
269     if ((fileName == NULL) || (buf == NULL) || (len == 0)) {
270         return 0;
271     }
272 
273     char *fullFileName = NULL;
274     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
275     if (ret != CMR_OK) {
276         return 0;
277     }
278 
279     uint32_t size = FileRead(fullFileName, offset, buf, len);
280     CM_FREE_PTR(fullFileName);
281     return size;
282 }
283 
CmFileWrite(const char * path,const char * fileName,uint32_t offset,const uint8_t * buf,uint32_t len)284 int32_t CmFileWrite(const char *path, const char *fileName, uint32_t offset, const uint8_t *buf, uint32_t len)
285 {
286     if ((fileName == NULL) || (buf == NULL) || (len == 0)) {
287         return CMR_ERROR_INVALID_ARGUMENT;
288     }
289 
290     char *fullFileName = NULL;
291     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
292     if (ret != CMR_OK) {
293         return ret;
294     }
295 
296     ret = FileWrite(fullFileName, offset, buf, len);
297     CM_FREE_PTR(fullFileName);
298     return ret;
299 }
300 
CmFileSize(const char * path,const char * fileName)301 uint32_t CmFileSize(const char *path, const char *fileName)
302 {
303     if (fileName == NULL) {
304         CM_LOG_E("fileName is NULL");
305         return 0;
306     }
307 
308     char *fullFileName = NULL;
309     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
310     if (ret != CMR_OK) {
311         CM_LOG_E("GetFullFileName failed");
312         return 0;
313     }
314 
315     uint32_t size = FileSize(fullFileName);
316     CM_FREE_PTR(fullFileName);
317     return size;
318 }
319 
CmUidLayerGetFileNames(const char * filePath,struct CmBlob * fileNames,const uint32_t arraySize,uint32_t count)320 static int32_t CmUidLayerGetFileNames(const char *filePath, struct CmBlob *fileNames,
321     const uint32_t arraySize, uint32_t count)
322 {
323     if (count >= arraySize) {
324         return CMR_ERROR_BUFFER_TOO_SMALL;
325     }
326     uint32_t filePathLen = strlen(filePath);
327     if (filePathLen >= CM_MAX_FILE_NAME_LEN) {
328         CM_LOG_E("CmUidLayerGetFileNames filePathLen:%u", filePathLen);
329         return CMR_ERROR_BUFFER_TOO_SMALL;
330     }
331 
332     fileNames[count].data = (uint8_t *)CMMalloc(filePathLen + 1);
333     if (fileNames[count].data == NULL) {
334         return CMR_ERROR_MALLOC_FAIL;
335     }
336     (void)memset_s(fileNames[count].data, filePathLen + 1, 0, filePathLen + 1);
337     if (memcpy_s(fileNames[count].data, CM_MAX_FILE_NAME_LEN, filePath, filePathLen) != EOK) {
338         /* fileNames memory free in top layer function */
339         return CMR_ERROR_BUFFER_TOO_SMALL;
340     }
341     fileNames[count].size = filePathLen + 1; /* include '\0' at end */
342     return CM_SUCCESS;
343 }
344 
CmUidLayerGetFileCountAndNames(const char * path,struct CmBlob * fileNames,const uint32_t arraySize,uint32_t * fileCount)345 int32_t CmUidLayerGetFileCountAndNames(const char *path, struct CmBlob *fileNames,
346     const uint32_t arraySize, uint32_t *fileCount)
347 {
348     /* do nothing when dir is not exist */
349     if (CmIsDirExist(path) != CMR_OK) {
350         CM_LOG_I("Uid layer dir is not exist");
351         return CM_SUCCESS;
352     }
353     DIR *dir = opendir(path);
354     if (dir == NULL) {
355         CM_LOG_E("open uid layer dir failed");
356         return CMR_ERROR_OPEN_FILE_FAIL;
357     }
358 
359     int32_t ret = CM_SUCCESS;
360     uint32_t count = *fileCount;
361     struct dirent *dire = readdir(dir);
362     while (dire != NULL) {
363         char uidPath[CM_MAX_FILE_NAME_LEN] = {0};
364         if (strncpy_s(uidPath, sizeof(uidPath), path, strlen(path)) != EOK) {
365             ret = CMR_ERROR_INVALID_OPERATION;
366             break;
367         }
368 
369         if (uidPath[strlen(uidPath) - 1] != '/') {
370             if (strncat_s(uidPath, sizeof(uidPath), "/", strlen("/")) != EOK) {
371                 ret = CMR_ERROR_INVALID_OPERATION;
372                 break;
373             }
374         }
375 
376         if (strncat_s(uidPath, sizeof(uidPath), dire->d_name, strlen(dire->d_name)) != EOK) {
377             ret = CMR_ERROR_INVALID_OPERATION;
378             break;
379         }
380 
381         if ((dire->d_type == DT_REG) && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
382             ret = CmUidLayerGetFileNames(uidPath, fileNames, arraySize, count);
383             if (ret != CM_SUCCESS) {
384                 break;
385             }
386             count++;
387         }
388         dire = readdir(dir);
389     }
390     *fileCount = count;
391     closedir(dir);
392     return ret;
393 }
394 
CmUserIdLayerGetFileCountAndNames(const char * path,struct CmBlob * fileNames,const uint32_t arraySize,uint32_t * fileCount)395 int32_t CmUserIdLayerGetFileCountAndNames(const char *path, struct CmBlob *fileNames,
396     const uint32_t arraySize, uint32_t *fileCount)
397 {
398     char userIdPath[CM_MAX_FILE_NAME_LEN] = { 0 };
399     /* do nothing when dir is not exist */
400     if (CmIsDirExist(path) != CMR_OK) {
401         CM_LOG_I("UserId layer dir is not exist");
402         return CM_SUCCESS;
403     }
404     DIR *dir = opendir(path);
405     if (dir  == NULL) {
406         CM_LOG_E("open userId layer dir failed");
407         return CMR_ERROR_OPEN_FILE_FAIL;
408     }
409     struct dirent *dire = readdir(dir);
410     while (dire != NULL) {
411         (void)memset_s(userIdPath, CM_MAX_FILE_NAME_LEN, 0, CM_MAX_FILE_NAME_LEN);
412         if (strncpy_s(userIdPath, sizeof(userIdPath), path, strlen(path)) != EOK) {
413             closedir(dir);
414             return CMR_ERROR_INVALID_OPERATION;
415         }
416 
417         if (userIdPath[strlen(userIdPath) - 1] != '/') {
418             if (strncat_s(userIdPath, sizeof(userIdPath), "/", strlen("/")) != EOK) {
419                 closedir(dir);
420                 return CMR_ERROR_INVALID_OPERATION;
421             }
422         }
423 
424         if (strncat_s(userIdPath, sizeof(userIdPath), dire->d_name, strlen(dire->d_name)) != EOK) {
425             closedir(dir);
426             return CMR_ERROR_INVALID_OPERATION;
427         }
428 
429         if ((dire->d_type == DT_DIR) && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
430             if (CmUidLayerGetFileCountAndNames(userIdPath, fileNames, arraySize, fileCount) != CM_SUCCESS) {
431                 CM_LOG_E("CmUidLayerGetFileCountAndNames faild");
432                 closedir(dir);
433                 return CM_FAILURE;
434             }
435         } else if (dire->d_type != DT_DIR) {
436             (void)remove(userIdPath);
437         }
438         dire = readdir(dir);
439     }
440     closedir(dir);
441     return CM_SUCCESS;
442 }
443 
CmIsFileExist(const char * path,const char * fileName)444 int32_t CmIsFileExist(const char *path, const char *fileName)
445 {
446     if (fileName == NULL) {
447         CM_LOG_E("fileName is NULL");
448         return CMR_ERROR_INVALID_ARGUMENT;
449     }
450 
451     char *fullFileName = NULL;
452     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
453     if (ret != CM_SUCCESS) {
454         CM_LOG_E("GetFullFileName failed");
455         return ret;
456     }
457 
458     ret = IsFileExist(fullFileName);
459     CM_FREE_PTR(fullFileName);
460     return ret;
461 }
462 
CmGetSubDir(void * dirp,struct CmFileDirentInfo * direntInfo)463 int32_t CmGetSubDir(void *dirp, struct CmFileDirentInfo *direntInfo)
464 {
465     DIR *dir = (DIR *)dirp;
466     struct dirent *dire = readdir(dir);
467 
468     while (dire != NULL) {
469         if ((dire->d_type != DT_DIR) || (strcmp(dire->d_name, ".") == 0) ||
470             (strcmp(dire->d_name, "..") == 0)) {
471             dire = readdir(dir);
472             continue;
473         }
474 
475         uint32_t dirLen = strlen(dire->d_name);
476         if (memcpy_s(direntInfo->fileName, sizeof(direntInfo->fileName) - 1, dire->d_name, dirLen) != EOK) {
477             return CMR_ERROR_INVALID_OPERATION;
478         }
479         direntInfo->fileName[dirLen] = '\0';
480         return CMR_OK;
481     }
482 
483     return CMR_ERROR_NOT_EXIST;
484 }
485 
DirRemove(const char * path)486 static int32_t DirRemove(const char *path)
487 {
488     if (access(path, F_OK) != 0) {
489         return CMR_ERROR_NOT_EXIST;
490     }
491 
492     struct stat tmp;
493     if (stat(path, &tmp) != 0) {
494         return CMR_ERROR_INVALID_OPERATION;
495     }
496 
497     if (S_ISDIR(tmp.st_mode)) {
498         uint32_t i = 0;
499         struct dirent *dire = NULL;
500         DIR *dirp = opendir(path);
501         if (dirp == NULL) {
502             CM_LOG_E("open dir failed");
503             return CMR_ERROR_OPEN_FILE_FAIL;
504         }
505         while ((dire = readdir(dirp)) != NULL) {
506             if ((strcmp(dire->d_name, ".") == 0) || (strcmp(dire->d_name, "..") == 0)) {
507                 continue;
508             }
509             i++;
510         }
511         closedir(dirp);
512 
513         if (i != 0) {
514             CM_LOG_E("Dir is not empty");
515             return CMR_ERROR_INVALID_ARGUMENT;
516         }
517         rmdir(path);
518         return CMR_OK;
519     }
520     return CMR_ERROR_INVALID_ARGUMENT;
521 }
522 
CmDirRemove(const char * path)523 int32_t CmDirRemove(const char *path)
524 {
525     if (path == NULL) {
526         return CMR_ERROR_INVALID_ARGUMENT;
527     }
528 
529     return DirRemove(path);
530 }
531