/* Copyright (C) 2005 Red Hat, Inc. */ struct semanage_user_base; struct semanage_user_key; typedef struct semanage_user_base record_t; typedef struct semanage_user_key record_key_t; #define DBASE_RECORD_DEFINED struct dbase_file; typedef struct dbase_file dbase_t; #define DBASE_DEFINED #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <semanage/handle.h> #include "user_internal.h" #include "database_file.h" #include "parse_utils.h" #include "debug.h" static int user_base_print(semanage_handle_t * handle, semanage_user_base_t * user, FILE * str) { const char **roles = NULL; unsigned int i, nroles; const char *name = semanage_user_base_get_name(user); const char *mls_level = semanage_user_base_get_mlslevel(user); const char *mls_range = semanage_user_base_get_mlsrange(user); if (fprintf(str, "user %s roles { ", name) < 0) goto err; if (semanage_user_base_get_roles(handle, user, &roles, &nroles) < 0) goto err; for (i = 0; i < nroles; i++) { if (fprintf(str, "%s ", roles[i]) < 0) goto err; } if (fprintf(str, "} ") < 0) goto err; /* MLS */ if (mls_level != NULL && mls_range != NULL) if (fprintf(str, "level %s range %s", mls_level, mls_range) < 0) goto err; if (fprintf(str, ";\n") < 0) goto err; free(roles); return STATUS_SUCCESS; err: free(roles); ERR(handle, "could not print user %s to stream", name); return STATUS_ERR; } static int user_base_parse(semanage_handle_t * handle, parse_info_t * info, semanage_user_base_t * user) { int islist = 0; char *str = NULL; char *start; char *name_str = NULL; if (parse_skip_space(handle, info) < 0) goto err; if (!info->ptr) goto last; /* Parse user header */ if (parse_assert_str(handle, info, "user") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* Parse user name */ if (parse_fetch_string(handle, info, &name_str, ' ') < 0) goto err; if (semanage_user_base_set_name(handle, user, name_str) < 0) { free(name_str); goto err; } free(name_str); if (parse_assert_space(handle, info) < 0) goto err; if (parse_assert_str(handle, info, "roles") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; islist = (parse_optional_ch(info, '{') != STATUS_NODATA); /* For each role, loop */ do { char delim; if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_noeof(handle, info) < 0) goto err; start = info->ptr; while (*(info->ptr) && *(info->ptr) != ';' && *(info->ptr) != '}' && !isspace(*(info->ptr))) info->ptr++; delim = *(info->ptr); *(info->ptr)++ = '\0'; if (semanage_user_base_add_role(handle, user, start) < 0) goto err; if (delim && !isspace(delim)) { if (islist && delim == '}') break; else if (!islist && delim == ';') goto skip_semicolon; else goto err; } if (parse_skip_space(handle, info) < 0) goto err; if (parse_optional_ch(info, ';') != STATUS_NODATA) goto skip_semicolon; if (parse_optional_ch(info, '}') != STATUS_NODATA) islist = 0; } while (islist); /* Handle mls */ /* Parse level header */ if (parse_skip_space(handle, info) < 0) goto err; if (parse_optional_str(info, "level") == STATUS_NODATA) goto semicolon; if (parse_assert_space(handle, info) < 0) goto err; /* NOTE: does not allow spaces/multiline */ if (parse_fetch_string(handle, info, &str, ' ') < 0) goto err; if (semanage_user_base_set_mlslevel(handle, user, str) < 0) goto err; free(str); str = NULL; /* Parse range header */ if (parse_assert_space(handle, info) < 0) goto err; if (parse_assert_str(handle, info, "range") < 0) goto err; if (parse_assert_space(handle, info) < 0) goto err; /* NOTE: does not allow spaces/multiline */ if (parse_fetch_string(handle, info, &str, ';') < 0) goto err; if (semanage_user_base_set_mlsrange(handle, user, str) < 0) goto err; free(str); str = NULL; /* Check for semicolon */ semicolon: if (parse_skip_space(handle, info) < 0) goto err; if (parse_assert_ch(handle, info, ';') < 0) goto err; skip_semicolon: return STATUS_SUCCESS; last: parse_dispose_line(info); return STATUS_NODATA; err: ERR(handle, "could not parse user record"); free(str); parse_dispose_line(info); return STATUS_ERR; } /* USER BASE record: FILE extension: method table */ record_file_table_t SEMANAGE_USER_BASE_FILE_RTABLE = { .parse = user_base_parse, .print = user_base_print, }; int user_base_file_dbase_init(semanage_handle_t * handle, const char *path_ro, const char *path_rw, dbase_config_t * dconfig) { if (dbase_file_init(handle, path_ro, path_rw, &SEMANAGE_USER_BASE_RTABLE, &SEMANAGE_USER_BASE_FILE_RTABLE, &dconfig->dbase) < 0) return STATUS_ERR; dconfig->dtable = &SEMANAGE_FILE_DTABLE; return STATUS_SUCCESS; } void user_base_file_dbase_release(dbase_config_t * dconfig) { dbase_file_release(dconfig->dbase); }