1 #include <stdlib.h> 2 #include <stddef.h> 3 #include <string.h> 4 5 #include "private.h" 6 #include "debug.h" 7 #include "handle.h" 8 9 #include <sepol/policydb/policydb.h> 10 #include <sepol/policydb/hashtab.h> 11 #include <sepol/policydb/expand.h> 12 #include "user_internal.h" 13 #include "mls.h" 14 user_to_record(sepol_handle_t * handle,const policydb_t * policydb,int user_idx,sepol_user_t ** record)15 static int user_to_record(sepol_handle_t * handle, 16 const policydb_t * policydb, 17 int user_idx, sepol_user_t ** record) 18 { 19 20 const char *name = policydb->p_user_val_to_name[user_idx]; 21 user_datum_t *usrdatum = policydb->user_val_to_struct[user_idx]; 22 ebitmap_t *roles; 23 ebitmap_node_t *rnode; 24 unsigned bit; 25 26 sepol_user_t *tmp_record = NULL; 27 28 if (!usrdatum) 29 goto err; 30 31 roles = &(usrdatum->roles.roles); 32 33 if (sepol_user_create(handle, &tmp_record) < 0) 34 goto err; 35 36 if (sepol_user_set_name(handle, tmp_record, name) < 0) 37 goto err; 38 39 /* Extract roles */ 40 ebitmap_for_each_bit(roles, rnode, bit) { 41 if (ebitmap_node_get_bit(rnode, bit)) { 42 char *role = policydb->p_role_val_to_name[bit]; 43 if (sepol_user_add_role(handle, tmp_record, role) < 0) 44 goto err; 45 } 46 } 47 48 /* Extract MLS info */ 49 if (policydb->mls) { 50 context_struct_t context; 51 char *str; 52 53 context_init(&context); 54 if (mls_level_cpy(&context.range.level[0], 55 &usrdatum->exp_dfltlevel) < 0) { 56 ERR(handle, "could not copy MLS level"); 57 context_destroy(&context); 58 goto err; 59 } 60 if (mls_level_cpy(&context.range.level[1], 61 &usrdatum->exp_dfltlevel) < 0) { 62 ERR(handle, "could not copy MLS level"); 63 context_destroy(&context); 64 goto err; 65 } 66 if (mls_to_string(handle, policydb, &context, &str) < 0) { 67 context_destroy(&context); 68 goto err; 69 } 70 context_destroy(&context); 71 72 if (sepol_user_set_mlslevel(handle, tmp_record, str) < 0) { 73 free(str); 74 goto err; 75 } 76 free(str); 77 78 context_init(&context); 79 if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) { 80 ERR(handle, "could not copy MLS range"); 81 context_destroy(&context); 82 goto err; 83 } 84 if (mls_to_string(handle, policydb, &context, &str) < 0) { 85 context_destroy(&context); 86 goto err; 87 } 88 context_destroy(&context); 89 90 if (sepol_user_set_mlsrange(handle, tmp_record, str) < 0) { 91 free(str); 92 goto err; 93 } 94 free(str); 95 } 96 97 *record = tmp_record; 98 return STATUS_SUCCESS; 99 100 err: 101 /* FIXME: handle error */ 102 sepol_user_free(tmp_record); 103 return STATUS_ERR; 104 } 105 sepol_user_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_user_key_t * key,const sepol_user_t * user)106 int sepol_user_modify(sepol_handle_t * handle, 107 sepol_policydb_t * p, 108 const sepol_user_key_t * key, const sepol_user_t * user) 109 { 110 111 policydb_t *policydb = &p->p; 112 113 /* For user data */ 114 const char *cname, *cmls_level, *cmls_range; 115 char *name = NULL; 116 117 const char **roles = NULL; 118 unsigned int num_roles = 0; 119 120 /* Low-level representation */ 121 user_datum_t *usrdatum = NULL; 122 role_datum_t *roldatum; 123 unsigned int i; 124 125 context_struct_t context; 126 unsigned bit; 127 int new = 0; 128 129 ebitmap_node_t *rnode; 130 131 /* First, extract all the data */ 132 sepol_user_key_unpack(key, &cname); 133 134 cmls_level = sepol_user_get_mlslevel(user); 135 cmls_range = sepol_user_get_mlsrange(user); 136 137 /* Make sure that worked properly */ 138 if (sepol_user_get_roles(handle, user, &roles, &num_roles) < 0) 139 goto err; 140 141 /* Now, see if a user exists */ 142 usrdatum = hashtab_search(policydb->p_users.table, cname); 143 144 /* If it does, we will modify it */ 145 if (usrdatum) { 146 147 int value_cp = usrdatum->s.value; 148 user_datum_destroy(usrdatum); 149 user_datum_init(usrdatum); 150 usrdatum->s.value = value_cp; 151 152 /* Otherwise, create a new one */ 153 } else { 154 usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t)); 155 if (!usrdatum) 156 goto omem; 157 user_datum_init(usrdatum); 158 new = 1; 159 } 160 161 /* For every role */ 162 for (i = 0; i < num_roles; i++) { 163 164 /* Search for the role */ 165 roldatum = hashtab_search(policydb->p_roles.table, roles[i]); 166 if (!roldatum) { 167 ERR(handle, "undefined role %s for user %s", 168 roles[i], cname); 169 goto err; 170 } 171 172 /* Set the role and every role it dominates */ 173 ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) { 174 if (ebitmap_node_get_bit(rnode, bit)) { 175 if (ebitmap_set_bit 176 (&(usrdatum->roles.roles), bit, 1)) 177 goto omem; 178 } 179 } 180 } 181 182 /* For MLS systems */ 183 if (policydb->mls) { 184 185 /* MLS level */ 186 if (cmls_level == NULL) { 187 ERR(handle, "MLS is enabled, but no MLS " 188 "default level was defined for user %s", cname); 189 goto err; 190 } 191 192 context_init(&context); 193 if (mls_from_string(handle, policydb, cmls_level, &context) < 0) { 194 context_destroy(&context); 195 goto err; 196 } 197 if (mls_level_cpy(&usrdatum->exp_dfltlevel, 198 &context.range.level[0]) < 0) { 199 ERR(handle, "could not copy MLS level %s", cmls_level); 200 context_destroy(&context); 201 goto err; 202 } 203 context_destroy(&context); 204 205 /* MLS range */ 206 if (cmls_range == NULL) { 207 ERR(handle, "MLS is enabled, but no MLS" 208 "range was defined for user %s", cname); 209 goto err; 210 } 211 212 context_init(&context); 213 if (mls_from_string(handle, policydb, cmls_range, &context) < 0) { 214 context_destroy(&context); 215 goto err; 216 } 217 if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) { 218 ERR(handle, "could not copy MLS range %s", cmls_range); 219 context_destroy(&context); 220 goto err; 221 } 222 context_destroy(&context); 223 } else if (cmls_level != NULL || cmls_range != NULL) { 224 ERR(handle, "MLS is disabled, but MLS level/range " 225 "was found for user %s", cname); 226 goto err; 227 } 228 229 /* If there are no errors, and this is a new user, add the user to policy */ 230 if (new) { 231 void *tmp_ptr; 232 233 /* Ensure reverse lookup array has enough space */ 234 tmp_ptr = realloc(policydb->user_val_to_struct, 235 (policydb->p_users.nprim + 236 1) * sizeof(user_datum_t *)); 237 if (!tmp_ptr) 238 goto omem; 239 policydb->user_val_to_struct = tmp_ptr; 240 policydb->user_val_to_struct[policydb->p_users.nprim] = NULL; 241 242 tmp_ptr = realloc(policydb->sym_val_to_name[SYM_USERS], 243 (policydb->p_users.nprim + 244 1) * sizeof(char *)); 245 if (!tmp_ptr) 246 goto omem; 247 policydb->sym_val_to_name[SYM_USERS] = tmp_ptr; 248 policydb->p_user_val_to_name[policydb->p_users.nprim] = NULL; 249 250 /* Need to copy the user name */ 251 name = strdup(cname); 252 if (!name) 253 goto omem; 254 255 /* Store user */ 256 usrdatum->s.value = ++policydb->p_users.nprim; 257 if (hashtab_insert(policydb->p_users.table, name, 258 (hashtab_datum_t) usrdatum) < 0) 259 goto omem; 260 261 /* Set up reverse entry */ 262 policydb->p_user_val_to_name[usrdatum->s.value - 1] = name; 263 policydb->user_val_to_struct[usrdatum->s.value - 1] = usrdatum; 264 name = NULL; 265 266 /* Expand roles */ 267 if (role_set_expand(&usrdatum->roles, &usrdatum->cache, 268 policydb, NULL, NULL)) { 269 ERR(handle, "unable to expand role set"); 270 goto err; 271 } 272 } 273 274 free(roles); 275 return STATUS_SUCCESS; 276 277 omem: 278 ERR(handle, "out of memory"); 279 280 err: 281 ERR(handle, "could not load %s into policy", name); 282 283 free(name); 284 free(roles); 285 if (new && usrdatum) { 286 role_set_destroy(&usrdatum->roles); 287 free(usrdatum); 288 } 289 return STATUS_ERR; 290 } 291 sepol_user_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_user_key_t * key,int * response)292 int sepol_user_exists(sepol_handle_t * handle __attribute__ ((unused)), 293 const sepol_policydb_t * p, 294 const sepol_user_key_t * key, int *response) 295 { 296 297 const policydb_t *policydb = &p->p; 298 299 const char *cname; 300 sepol_user_key_unpack(key, &cname); 301 302 *response = (hashtab_search(policydb->p_users.table, cname) != NULL); 303 304 return STATUS_SUCCESS; 305 } 306 sepol_user_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)307 int sepol_user_count(sepol_handle_t * handle __attribute__ ((unused)), 308 const sepol_policydb_t * p, unsigned int *response) 309 { 310 311 const policydb_t *policydb = &p->p; 312 *response = policydb->p_users.nprim; 313 314 return STATUS_SUCCESS; 315 } 316 sepol_user_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_user_key_t * key,sepol_user_t ** response)317 int sepol_user_query(sepol_handle_t * handle, 318 const sepol_policydb_t * p, 319 const sepol_user_key_t * key, sepol_user_t ** response) 320 { 321 322 const policydb_t *policydb = &p->p; 323 user_datum_t *usrdatum = NULL; 324 325 const char *cname; 326 sepol_user_key_unpack(key, &cname); 327 328 usrdatum = hashtab_search(policydb->p_users.table, cname); 329 330 if (!usrdatum) { 331 *response = NULL; 332 return STATUS_SUCCESS; 333 } 334 335 if (user_to_record(handle, policydb, usrdatum->s.value - 1, response) < 336 0) 337 goto err; 338 339 return STATUS_SUCCESS; 340 341 err: 342 ERR(handle, "could not query user %s", cname); 343 return STATUS_ERR; 344 } 345 sepol_user_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_user_t * user,void * fn_arg),void * arg)346 int sepol_user_iterate(sepol_handle_t * handle, 347 const sepol_policydb_t * p, 348 int (*fn) (const sepol_user_t * user, 349 void *fn_arg), void *arg) 350 { 351 352 const policydb_t *policydb = &p->p; 353 unsigned int nusers = policydb->p_users.nprim; 354 sepol_user_t *user = NULL; 355 unsigned int i; 356 357 /* For each user */ 358 for (i = 0; i < nusers; i++) { 359 360 int status; 361 362 if (user_to_record(handle, policydb, i, &user) < 0) 363 goto err; 364 365 /* Invoke handler */ 366 status = fn(user, arg); 367 if (status < 0) 368 goto err; 369 370 sepol_user_free(user); 371 user = NULL; 372 373 /* Handler requested exit */ 374 if (status > 0) 375 break; 376 } 377 378 return STATUS_SUCCESS; 379 380 err: 381 ERR(handle, "could not iterate over users"); 382 sepol_user_free(user); 383 return STATUS_ERR; 384 } 385