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