1 /* Copyright (C) 2005 Red Hat, Inc. */ 2 3 struct semanage_user_base; 4 struct semanage_user_key; 5 typedef struct semanage_user_base record_t; 6 typedef struct semanage_user_key record_key_t; 7 #define DBASE_RECORD_DEFINED 8 9 struct dbase_file; 10 typedef struct dbase_file dbase_t; 11 #define DBASE_DEFINED 12 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <ctype.h> 16 #include <string.h> 17 #include <semanage/handle.h> 18 #include "user_internal.h" 19 #include "database_file.h" 20 #include "parse_utils.h" 21 #include "debug.h" 22 23 static int user_base_print(semanage_handle_t * handle, 24 semanage_user_base_t * user, FILE * str) 25 { 26 27 const char **roles = NULL; 28 unsigned int i, nroles; 29 30 const char *name = semanage_user_base_get_name(user); 31 const char *mls_level = semanage_user_base_get_mlslevel(user); 32 const char *mls_range = semanage_user_base_get_mlsrange(user); 33 34 if (fprintf(str, "user %s roles { ", name) < 0) 35 goto err; 36 37 if (semanage_user_base_get_roles(handle, user, &roles, &nroles) < 0) 38 goto err; 39 40 for (i = 0; i < nroles; i++) { 41 if (fprintf(str, "%s ", roles[i]) < 0) 42 goto err; 43 } 44 45 if (fprintf(str, "} ") < 0) 46 goto err; 47 48 /* MLS */ 49 if (mls_level != NULL && mls_range != NULL) 50 if (fprintf(str, "level %s range %s", mls_level, mls_range) < 0) 51 goto err; 52 53 if (fprintf(str, ";\n") < 0) 54 goto err; 55 56 free(roles); 57 return STATUS_SUCCESS; 58 59 err: 60 free(roles); 61 ERR(handle, "could not print user %s to stream", name); 62 return STATUS_ERR; 63 } 64 65 static int user_base_parse(semanage_handle_t * handle, 66 parse_info_t * info, semanage_user_base_t * user) 67 { 68 69 int islist = 0; 70 char *str = NULL; 71 char *start; 72 char *name_str = NULL; 73 74 if (parse_skip_space(handle, info) < 0) 75 goto err; 76 if (!info->ptr) 77 goto last; 78 79 /* Parse user header */ 80 if (parse_assert_str(handle, info, "user") < 0) 81 goto err; 82 if (parse_assert_space(handle, info) < 0) 83 goto err; 84 85 /* Parse user name */ 86 if (parse_fetch_string(handle, info, &name_str, ' ') < 0) 87 goto err; 88 89 if (semanage_user_base_set_name(handle, user, name_str) < 0) { 90 free(name_str); 91 goto err; 92 } 93 free(name_str); 94 95 if (parse_assert_space(handle, info) < 0) 96 goto err; 97 if (parse_assert_str(handle, info, "roles") < 0) 98 goto err; 99 if (parse_assert_space(handle, info) < 0) 100 goto err; 101 102 islist = (parse_optional_ch(info, '{') != STATUS_NODATA); 103 104 /* For each role, loop */ 105 do { 106 char delim; 107 108 if (parse_skip_space(handle, info) < 0) 109 goto err; 110 if (parse_assert_noeof(handle, info) < 0) 111 goto err; 112 113 start = info->ptr; 114 while (*(info->ptr) && 115 *(info->ptr) != ';' && 116 *(info->ptr) != '}' && !isspace(*(info->ptr))) 117 info->ptr++; 118 119 delim = *(info->ptr); 120 *(info->ptr)++ = '\0'; 121 122 if (semanage_user_base_add_role(handle, user, start) < 0) 123 goto err; 124 125 if (delim && !isspace(delim)) { 126 if (islist && delim == '}') 127 break; 128 else if (!islist && delim == ';') 129 goto skip_semicolon; 130 else 131 goto err; 132 } 133 134 if (parse_skip_space(handle, info) < 0) 135 goto err; 136 if (parse_optional_ch(info, ';') != STATUS_NODATA) 137 goto skip_semicolon; 138 if (parse_optional_ch(info, '}') != STATUS_NODATA) 139 islist = 0; 140 141 } while (islist); 142 143 /* Handle mls */ 144 /* Parse level header */ 145 if (parse_skip_space(handle, info) < 0) 146 goto err; 147 if (parse_optional_str(info, "level") == STATUS_NODATA) 148 goto semicolon; 149 if (parse_assert_space(handle, info) < 0) 150 goto err; 151 152 /* NOTE: does not allow spaces/multiline */ 153 if (parse_fetch_string(handle, info, &str, ' ') < 0) 154 goto err; 155 if (semanage_user_base_set_mlslevel(handle, user, str) < 0) 156 goto err; 157 free(str); 158 str = NULL; 159 160 /* Parse range header */ 161 if (parse_assert_space(handle, info) < 0) 162 goto err; 163 if (parse_assert_str(handle, info, "range") < 0) 164 goto err; 165 if (parse_assert_space(handle, info) < 0) 166 goto err; 167 168 /* NOTE: does not allow spaces/multiline */ 169 if (parse_fetch_string(handle, info, &str, ';') < 0) 170 goto err; 171 if (semanage_user_base_set_mlsrange(handle, user, str) < 0) 172 goto err; 173 174 free(str); 175 str = NULL; 176 177 /* Check for semicolon */ 178 semicolon: 179 if (parse_skip_space(handle, info) < 0) 180 goto err; 181 if (parse_assert_ch(handle, info, ';') < 0) 182 goto err; 183 184 skip_semicolon: 185 return STATUS_SUCCESS; 186 187 last: 188 parse_dispose_line(info); 189 return STATUS_NODATA; 190 191 err: 192 ERR(handle, "could not parse user record"); 193 free(str); 194 parse_dispose_line(info); 195 return STATUS_ERR; 196 } 197 198 /* USER BASE record: FILE extension: method table */ 199 record_file_table_t SEMANAGE_USER_BASE_FILE_RTABLE = { 200 .parse = user_base_parse, 201 .print = user_base_print, 202 }; 203 204 int user_base_file_dbase_init(semanage_handle_t * handle, 205 const char *path_ro, 206 const char *path_rw, 207 dbase_config_t * dconfig) 208 { 209 210 if (dbase_file_init(handle, 211 path_ro, 212 path_rw, 213 &SEMANAGE_USER_BASE_RTABLE, 214 &SEMANAGE_USER_BASE_FILE_RTABLE, 215 &dconfig->dbase) < 0) 216 return STATUS_ERR; 217 218 dconfig->dtable = &SEMANAGE_FILE_DTABLE; 219 return STATUS_SUCCESS; 220 } 221 222 void user_base_file_dbase_release(dbase_config_t * dconfig) 223 { 224 225 dbase_file_release(dconfig->dbase); 226 } 227