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