return ret;
}
-static void _remove_file(const char *path)
+typedef int(*entry_callback)(const char *path, const struct dirent *entry, void *user_data);
+static int traverse_directory(const char *path, entry_callback ecb, void *user_data)
{
- unlink(path);
-}
-
-void _remove_directory(const char *path)
-{
- char file_path_buff[MAX_PATH_LEN] = {0, };
DIR *dir = opendir(path);
if (dir == NULL) {
- if (errno == ENOENT)
- WAE_SLOGI("directory is not exist already(%s)", path);
- else
+ if (errno == ENOENT) {
+ // it's not error for current cases of using traverse_directory.
+ // To open dek store directory for load/remove can be occured in some
+ // exception(or attacked) cases but we can just ignore it if it isn't the
+ // first time call load_preloaded_app_deks.
+ WAE_SLOGI("directory isn't exist(%s).", path);
+ return WAE_ERROR_NONE;
+ } else {
WAE_SLOGE("Failed to open dir(%s)", path);
-
- return;
+ return WAE_ERROR_FILE;
+ }
}
+ int ret = WAE_ERROR_NONE;
struct dirent entry;
struct dirent *result = NULL;
while (true) {
if (readdir_r(dir, &entry, &result) != 0) {
+ WAE_SLOGE("readdir_r error on dir(%s) errno(%d)", path, errno);
break;
} else if (result == NULL) {
- break;
+ break; // end of directory
} else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) {
continue;
}
- if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry.d_name)
- < 0)
- continue;
+ int _ret = ecb(path, result, user_data);
+ if (_ret != WAE_ERROR_NONE)
+ ret = _ret;
+ }
- if (entry.d_type == DT_DIR) {
- _remove_directory(file_path_buff);
- } else {
- WAE_SLOGD("remove file(%s)", file_path_buff);
- _remove_file(file_path_buff);
- }
+ closedir(dir);
+ return ret;
+}
+
+static void _remove_file(const char *path)
+{
+ unlink(path);
+}
+
+static int _entry_callback_remove_all(
+ const char *path, const struct dirent *entry, void *user_data)
+{
+ (void) user_data; // TODO: use UNUSED macro
+
+ char file_path_buff[MAX_PATH_LEN] = {0, };
+ if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0)
+ return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
+
+ int ret = WAE_ERROR_NONE;
+ if (entry->d_type == DT_DIR) {
+ int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all, NULL);
+ if (_ret != WAE_ERROR_NONE)
+ ret = _ret;
+ rmdir(file_path_buff);
+ } else {
+ _remove_file(file_path_buff);
}
+ return ret;
+}
+
+void _remove_directory(const char *path)
+{
+ traverse_directory(path, _entry_callback_remove_all, NULL);
WAE_SLOGD("remove directory(%s)", path);
- closedir(dir);
rmdir(path);
}
int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path)
{
- int ret = snprintf(path, size, "%s/%s_%s.adek",
- _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id);
-
- if (ret < 0)
+ if (snprintf(path, size, "%s/%s_%s.adek",
+ _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id) < 0)
return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
-
- return WAE_ERROR_NONE;
+ else
+ return WAE_ERROR_NONE;
}
static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id)
#endif
}
-int load_preloaded_app_deks()
+static int _entry_callback_load_preloaded_adeks(
+ const char *path, const struct dirent *entry, void *prikey)
{
- WAE_SLOGI("load_preloaded_app_deks start");
+ const char *pub_key_path = _get_dek_kek_pub_key_path();
+ const char *pri_key_path = _get_dek_kek_pri_key_path();
+
+ char file_path_buff[MAX_PATH_LEN] = {0, };
+ if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0)
+ return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
+
+ if (strcmp(file_path_buff, pub_key_path) == 0 ||
+ strcmp(file_path_buff, pri_key_path) == 0)
+ return WAE_ERROR_NONE; /* skip KEK files */
- int global_ret = WAE_ERROR_NONE;
+ if (entry->d_type != DT_REG || strstr(entry->d_name, APP_DEK_FILE_PFX) == NULL) {
+ if (entry->d_type == DT_DIR)
+ WAE_SLOGW(
+ "Invalid file in dek store(%s). Directory shouldn't be here.", path);
+ else
+ WAE_SLOGW(
+ "Invalid file in dek store(%s). "
+ "Not regular file or prefix(%s) is invalid.", path, APP_DEK_FILE_PFX);
+
+ return WAE_ERROR_FILE;
+ }
char pkg_id[MAX_PKGID_LEN] = {0, };
- char file_path_buff[MAX_PATH_LEN] = {0, };
+ int ret = _extract_pkg_id_from_file_name(entry->d_name, pkg_id);
+ if (ret != WAE_ERROR_NONE) {
+ WAE_SLOGW("Failed to extract pkgid from file(%s). It will be ignored.", file_path_buff);
+ return ret;
+ }
+
+ ret = _load_preloaded_app_dek((raw_buffer_s *)prikey, file_path_buff, pkg_id);
+ if (ret == WAE_ERROR_NONE || ret == WAE_ERROR_KEY_EXISTS) {
+ WAE_SLOGI("Successfully load app dek(%s)", file_path_buff);
+ return WAE_ERROR_NONE;
+ } else {
+ WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret);
+ return ret;
+ }
+}
+
+int load_preloaded_app_deks()
+{
+ WAE_SLOGI("load_preloaded_app_deks start");
+
+ int ret = WAE_ERROR_NONE;
const char *dek_store_path = _get_dek_store_path();
- const char *dek_kek_pub_key_path = _get_dek_kek_pub_key_path();
- const char *dek_kek_pri_key_path = _get_dek_kek_pri_key_path();
raw_buffer_s *prikey = NULL;
DIR *dir = NULL;
return WAE_ERROR_NONE;
} else {
WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path);
- global_ret = WAE_ERROR_FILE;
+ ret = WAE_ERROR_FILE;
goto out;
}
}
- global_ret = _get_app_dek_kek(&prikey);
-
- if (global_ret != WAE_ERROR_NONE) {
- WAE_SLOGE("Fail to get APP_DEK_KEK Private Key");
+ ret = _get_app_dek_kek(&prikey);
+ if (ret != WAE_ERROR_NONE) {
+ WAE_SLOGE("Fail to get APP_DEK_KEK Private Key. ret(%d)", ret);
goto out;
}
- struct dirent entry;
- struct dirent *result = NULL;
-
- while (true) {
- int ret = WAE_ERROR_NONE;
- if (readdir_r(dir, &entry, &result) != 0) {
- global_ret = WAE_ERROR_FILE;
- break;
- }
-
- // readdir_r returns NULL in *result if the end
- // of the directory stream is reached
- if (result == NULL)
- break;
-
- if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0)
- continue;
-
- if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s",
- dek_store_path, entry.d_name) < 0) {
- WAE_SLOGE("Failed to make file path by snprintf.");
- global_ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
- break;
- }
-
- // skip for KEKs. They'll be deleted after all akek loaded to key-manager.
- if (strcmp(file_path_buff, dek_kek_pub_key_path) == 0 ||
- strcmp(file_path_buff, dek_kek_pri_key_path) == 0) {
- WAE_SLOGD("Skip KEK file...(%s)", file_path_buff);
- continue;
- }
-
- // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX
- // clear all invalid cases silently
- if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL) {
- if (entry.d_type == DT_DIR) {
- WAE_SLOGW(
- "Invalid file in dek store(%s). Directory shouldn't be here.",
- dek_store_path);
- global_ret = WAE_ERROR_FILE;
- } else {
- WAE_SLOGW(
- "Invalid file in dek store(%s). "
- "Not regular file or prefix(%s) is invalid.",
- dek_store_path, APP_DEK_FILE_PFX);
- global_ret = WAE_ERROR_FILE;
- }
-
- continue;
- }
-
- ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id);
-
- if (ret != WAE_ERROR_NONE) {
- WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s",
- file_path_buff);
- global_ret = ret;
- continue;
- }
+ // close dek store dir fd not to affect the traverse_directory call
+ closedir(dir);
+ dir = NULL;
- ret = _load_preloaded_app_dek(prikey, file_path_buff, pkg_id);
- if (ret != WAE_ERROR_NONE && ret != WAE_ERROR_KEY_EXISTS) {
- WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret);
- global_ret = ret;
- } else {
- WAE_SLOGI("Successfully load app dek(%s)", file_path_buff);
- }
- }
+ ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks, prikey);
+ if (ret != WAE_ERROR_NONE)
+ WAE_SLOGE("Fail when traverse dek store directory. ret(%d)", ret);
out:
if (prikey != NULL)
// initializer service failure.
_remove_directory(dek_store_path);
- return global_ret;
+ return ret;
}
int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type)