1#include <errno.h> 2#include <stdlib.h> 3#include <string.h> 4 5#include "user_internal.h" 6#include "debug.h" 7 8struct sepol_user { 9 /* This user's name */ 10 char *name; 11 12 /* This user's mls level (only required for mls) */ 13 char *mls_level; 14 15 /* This user's mls range (only required for mls) */ 16 char *mls_range; 17 18 /* The role array */ 19 char **roles; 20 21 /* The number of roles */ 22 unsigned int num_roles; 23}; 24 25struct sepol_user_key { 26 /* This user's name */ 27 const char *name; 28}; 29 30int sepol_user_key_create(sepol_handle_t * handle, 31 const char *name, sepol_user_key_t ** key_ptr) 32{ 33 34 sepol_user_key_t *tmp_key = 35 (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t)); 36 37 if (!tmp_key) { 38 ERR(handle, "out of memory, " 39 "could not create selinux user key"); 40 return STATUS_ERR; 41 } 42 43 tmp_key->name = name; 44 45 *key_ptr = tmp_key; 46 return STATUS_SUCCESS; 47} 48 49hidden_def(sepol_user_key_create) 50 51void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name) 52{ 53 54 *name = key->name; 55} 56 57hidden_def(sepol_user_key_unpack) 58 59int sepol_user_key_extract(sepol_handle_t * handle, 60 const sepol_user_t * user, 61 sepol_user_key_t ** key_ptr) 62{ 63 64 if (sepol_user_key_create(handle, user->name, key_ptr) < 0) { 65 ERR(handle, "could not extract key from user %s", user->name); 66 return STATUS_ERR; 67 } 68 69 return STATUS_SUCCESS; 70} 71 72void sepol_user_key_free(sepol_user_key_t * key) 73{ 74 free(key); 75} 76 77int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key) 78{ 79 80 return strcmp(user->name, key->name); 81} 82 83int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2) 84{ 85 86 return strcmp(user->name, user2->name); 87} 88 89/* Name */ 90const char *sepol_user_get_name(const sepol_user_t * user) 91{ 92 93 return user->name; 94} 95 96int sepol_user_set_name(sepol_handle_t * handle, 97 sepol_user_t * user, const char *name) 98{ 99 100 char *tmp_name = strdup(name); 101 if (!tmp_name) { 102 ERR(handle, "out of memory, could not set name"); 103 return STATUS_ERR; 104 } 105 free(user->name); 106 user->name = tmp_name; 107 return STATUS_SUCCESS; 108} 109 110hidden_def(sepol_user_set_name) 111 112/* MLS */ 113const char *sepol_user_get_mlslevel(const sepol_user_t * user) 114{ 115 116 return user->mls_level; 117} 118 119hidden_def(sepol_user_get_mlslevel) 120 121int sepol_user_set_mlslevel(sepol_handle_t * handle, 122 sepol_user_t * user, const char *mls_level) 123{ 124 125 char *tmp_mls_level = strdup(mls_level); 126 if (!tmp_mls_level) { 127 ERR(handle, "out of memory, " 128 "could not set MLS default level"); 129 return STATUS_ERR; 130 } 131 free(user->mls_level); 132 user->mls_level = tmp_mls_level; 133 return STATUS_SUCCESS; 134} 135 136hidden_def(sepol_user_set_mlslevel) 137 138const char *sepol_user_get_mlsrange(const sepol_user_t * user) 139{ 140 141 return user->mls_range; 142} 143 144hidden_def(sepol_user_get_mlsrange) 145 146int sepol_user_set_mlsrange(sepol_handle_t * handle, 147 sepol_user_t * user, const char *mls_range) 148{ 149 150 char *tmp_mls_range = strdup(mls_range); 151 if (!tmp_mls_range) { 152 ERR(handle, "out of memory, " 153 "could not set MLS allowed range"); 154 return STATUS_ERR; 155 } 156 free(user->mls_range); 157 user->mls_range = tmp_mls_range; 158 return STATUS_SUCCESS; 159} 160 161hidden_def(sepol_user_set_mlsrange) 162 163/* Roles */ 164int sepol_user_get_num_roles(const sepol_user_t * user) 165{ 166 167 return user->num_roles; 168} 169 170int sepol_user_add_role(sepol_handle_t * handle, 171 sepol_user_t * user, const char *role) 172{ 173 174 char *role_cp; 175 char **roles_realloc; 176 177 if (sepol_user_has_role(user, role)) 178 return STATUS_SUCCESS; 179 180 role_cp = strdup(role); 181 roles_realloc = realloc(user->roles, 182 sizeof(char *) * (user->num_roles + 1)); 183 184 if (!role_cp || !roles_realloc) 185 goto omem; 186 187 user->num_roles++; 188 user->roles = roles_realloc; 189 user->roles[user->num_roles - 1] = role_cp; 190 191 return STATUS_SUCCESS; 192 193 omem: 194 ERR(handle, "out of memory, could not add role %s", role); 195 free(role_cp); 196 free(roles_realloc); 197 return STATUS_ERR; 198} 199 200hidden_def(sepol_user_add_role) 201 202int sepol_user_has_role(const sepol_user_t * user, const char *role) 203{ 204 205 unsigned int i; 206 207 for (i = 0; i < user->num_roles; i++) 208 if (!strcmp(user->roles[i], role)) 209 return 1; 210 return 0; 211} 212 213hidden_def(sepol_user_has_role) 214 215int sepol_user_set_roles(sepol_handle_t * handle, 216 sepol_user_t * user, 217 const char **roles_arr, unsigned int num_roles) 218{ 219 220 unsigned int i; 221 char **tmp_roles = NULL; 222 223 if (num_roles > 0) { 224 225 /* First, make a copy */ 226 tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles); 227 if (!tmp_roles) 228 goto omem; 229 230 for (i = 0; i < num_roles; i++) { 231 tmp_roles[i] = strdup(roles_arr[i]); 232 if (!tmp_roles[i]) 233 goto omem; 234 } 235 } 236 237 /* Apply other changes */ 238 for (i = 0; i < user->num_roles; i++) 239 free(user->roles[i]); 240 free(user->roles); 241 user->roles = tmp_roles; 242 user->num_roles = num_roles; 243 return STATUS_SUCCESS; 244 245 omem: 246 ERR(handle, "out of memory, could not allocate roles array for" 247 "user %s", user->name); 248 249 if (tmp_roles) { 250 for (i = 0; i < num_roles; i++) { 251 if (!tmp_roles[i]) 252 break; 253 free(tmp_roles[i]); 254 } 255 } 256 free(tmp_roles); 257 return STATUS_ERR; 258} 259 260int sepol_user_get_roles(sepol_handle_t * handle, 261 const sepol_user_t * user, 262 const char ***roles_arr, unsigned int *num_roles) 263{ 264 265 unsigned int i; 266 const char **tmp_roles = 267 (const char **)malloc(sizeof(char *) * user->num_roles); 268 if (!tmp_roles) 269 goto omem; 270 271 for (i = 0; i < user->num_roles; i++) 272 tmp_roles[i] = user->roles[i]; 273 274 *roles_arr = tmp_roles; 275 *num_roles = user->num_roles; 276 return STATUS_SUCCESS; 277 278 omem: 279 ERR(handle, "out of memory, could not " 280 "allocate roles array for user %s", user->name); 281 free(tmp_roles); 282 return STATUS_ERR; 283} 284 285hidden_def(sepol_user_get_roles) 286 287void sepol_user_del_role(sepol_user_t * user, const char *role) 288{ 289 290 unsigned int i; 291 for (i = 0; i < user->num_roles; i++) { 292 if (!strcmp(user->roles[i], role)) { 293 free(user->roles[i]); 294 user->roles[i] = NULL; 295 user->roles[i] = user->roles[user->num_roles - 1]; 296 user->num_roles--; 297 } 298 } 299} 300 301/* Create */ 302int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr) 303{ 304 305 sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t)); 306 307 if (!user) { 308 ERR(handle, "out of memory, " 309 "could not create selinux user record"); 310 return STATUS_ERR; 311 } 312 313 user->roles = NULL; 314 user->num_roles = 0; 315 user->name = NULL; 316 user->mls_level = NULL; 317 user->mls_range = NULL; 318 319 *user_ptr = user; 320 return STATUS_SUCCESS; 321} 322 323hidden_def(sepol_user_create) 324 325/* Deep copy clone */ 326int sepol_user_clone(sepol_handle_t * handle, 327 const sepol_user_t * user, sepol_user_t ** user_ptr) 328{ 329 330 sepol_user_t *new_user = NULL; 331 unsigned int i; 332 333 if (sepol_user_create(handle, &new_user) < 0) 334 goto err; 335 336 if (sepol_user_set_name(handle, new_user, user->name) < 0) 337 goto err; 338 339 for (i = 0; i < user->num_roles; i++) { 340 if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0) 341 goto err; 342 } 343 344 if (user->mls_level && 345 (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0)) 346 goto err; 347 348 if (user->mls_range && 349 (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0)) 350 goto err; 351 352 *user_ptr = new_user; 353 return STATUS_SUCCESS; 354 355 err: 356 ERR(handle, "could not clone selinux user record"); 357 sepol_user_free(new_user); 358 return STATUS_ERR; 359} 360 361/* Destroy */ 362void sepol_user_free(sepol_user_t * user) 363{ 364 365 unsigned int i; 366 367 if (!user) 368 return; 369 370 free(user->name); 371 for (i = 0; i < user->num_roles; i++) 372 free(user->roles[i]); 373 free(user->roles); 374 free(user->mls_level); 375 free(user->mls_range); 376 free(user); 377} 378 379hidden_def(sepol_user_free) 380