16cd6a6acSopenharmony_ci#include <errno.h> 26cd6a6acSopenharmony_ci#include <stdlib.h> 36cd6a6acSopenharmony_ci#include <string.h> 46cd6a6acSopenharmony_ci 56cd6a6acSopenharmony_ci#include "user_internal.h" 66cd6a6acSopenharmony_ci#include "debug.h" 76cd6a6acSopenharmony_ci#include "private.h" 86cd6a6acSopenharmony_ci 96cd6a6acSopenharmony_cistruct sepol_user { 106cd6a6acSopenharmony_ci /* This user's name */ 116cd6a6acSopenharmony_ci char *name; 126cd6a6acSopenharmony_ci 136cd6a6acSopenharmony_ci /* This user's mls level (only required for mls) */ 146cd6a6acSopenharmony_ci char *mls_level; 156cd6a6acSopenharmony_ci 166cd6a6acSopenharmony_ci /* This user's mls range (only required for mls) */ 176cd6a6acSopenharmony_ci char *mls_range; 186cd6a6acSopenharmony_ci 196cd6a6acSopenharmony_ci /* The role array */ 206cd6a6acSopenharmony_ci char **roles; 216cd6a6acSopenharmony_ci 226cd6a6acSopenharmony_ci /* The number of roles */ 236cd6a6acSopenharmony_ci unsigned int num_roles; 246cd6a6acSopenharmony_ci}; 256cd6a6acSopenharmony_ci 266cd6a6acSopenharmony_cistruct sepol_user_key { 276cd6a6acSopenharmony_ci /* This user's name */ 286cd6a6acSopenharmony_ci char *name; 296cd6a6acSopenharmony_ci}; 306cd6a6acSopenharmony_ci 316cd6a6acSopenharmony_ciint sepol_user_key_create(sepol_handle_t * handle, 326cd6a6acSopenharmony_ci const char *name, sepol_user_key_t ** key_ptr) 336cd6a6acSopenharmony_ci{ 346cd6a6acSopenharmony_ci 356cd6a6acSopenharmony_ci sepol_user_key_t *tmp_key = 366cd6a6acSopenharmony_ci (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t)); 376cd6a6acSopenharmony_ci 386cd6a6acSopenharmony_ci if (!tmp_key) { 396cd6a6acSopenharmony_ci ERR(handle, "out of memory, " 406cd6a6acSopenharmony_ci "could not create selinux user key"); 416cd6a6acSopenharmony_ci return STATUS_ERR; 426cd6a6acSopenharmony_ci } 436cd6a6acSopenharmony_ci 446cd6a6acSopenharmony_ci tmp_key->name = strdup(name); 456cd6a6acSopenharmony_ci if (!tmp_key->name) { 466cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not create selinux user key"); 476cd6a6acSopenharmony_ci free(tmp_key); 486cd6a6acSopenharmony_ci return STATUS_ERR; 496cd6a6acSopenharmony_ci } 506cd6a6acSopenharmony_ci 516cd6a6acSopenharmony_ci *key_ptr = tmp_key; 526cd6a6acSopenharmony_ci return STATUS_SUCCESS; 536cd6a6acSopenharmony_ci} 546cd6a6acSopenharmony_ci 556cd6a6acSopenharmony_ci 566cd6a6acSopenharmony_civoid sepol_user_key_unpack(const sepol_user_key_t * key, const char **name) 576cd6a6acSopenharmony_ci{ 586cd6a6acSopenharmony_ci 596cd6a6acSopenharmony_ci *name = key->name; 606cd6a6acSopenharmony_ci} 616cd6a6acSopenharmony_ci 626cd6a6acSopenharmony_ci 636cd6a6acSopenharmony_ciint sepol_user_key_extract(sepol_handle_t * handle, 646cd6a6acSopenharmony_ci const sepol_user_t * user, 656cd6a6acSopenharmony_ci sepol_user_key_t ** key_ptr) 666cd6a6acSopenharmony_ci{ 676cd6a6acSopenharmony_ci 686cd6a6acSopenharmony_ci if (sepol_user_key_create(handle, user->name, key_ptr) < 0) { 696cd6a6acSopenharmony_ci ERR(handle, "could not extract key from user %s", user->name); 706cd6a6acSopenharmony_ci return STATUS_ERR; 716cd6a6acSopenharmony_ci } 726cd6a6acSopenharmony_ci 736cd6a6acSopenharmony_ci return STATUS_SUCCESS; 746cd6a6acSopenharmony_ci} 756cd6a6acSopenharmony_ci 766cd6a6acSopenharmony_civoid sepol_user_key_free(sepol_user_key_t * key) 776cd6a6acSopenharmony_ci{ 786cd6a6acSopenharmony_ci if (!key) 796cd6a6acSopenharmony_ci return; 806cd6a6acSopenharmony_ci free(key->name); 816cd6a6acSopenharmony_ci free(key); 826cd6a6acSopenharmony_ci} 836cd6a6acSopenharmony_ci 846cd6a6acSopenharmony_ciint sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key) 856cd6a6acSopenharmony_ci{ 866cd6a6acSopenharmony_ci 876cd6a6acSopenharmony_ci return strcmp(user->name, key->name); 886cd6a6acSopenharmony_ci} 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ciint sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2) 916cd6a6acSopenharmony_ci{ 926cd6a6acSopenharmony_ci 936cd6a6acSopenharmony_ci return strcmp(user->name, user2->name); 946cd6a6acSopenharmony_ci} 956cd6a6acSopenharmony_ci 966cd6a6acSopenharmony_ci/* Name */ 976cd6a6acSopenharmony_ciconst char *sepol_user_get_name(const sepol_user_t * user) 986cd6a6acSopenharmony_ci{ 996cd6a6acSopenharmony_ci 1006cd6a6acSopenharmony_ci return user->name; 1016cd6a6acSopenharmony_ci} 1026cd6a6acSopenharmony_ci 1036cd6a6acSopenharmony_ciint sepol_user_set_name(sepol_handle_t * handle, 1046cd6a6acSopenharmony_ci sepol_user_t * user, const char *name) 1056cd6a6acSopenharmony_ci{ 1066cd6a6acSopenharmony_ci 1076cd6a6acSopenharmony_ci char *tmp_name = strdup(name); 1086cd6a6acSopenharmony_ci if (!tmp_name) { 1096cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not set name"); 1106cd6a6acSopenharmony_ci return STATUS_ERR; 1116cd6a6acSopenharmony_ci } 1126cd6a6acSopenharmony_ci free(user->name); 1136cd6a6acSopenharmony_ci user->name = tmp_name; 1146cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1156cd6a6acSopenharmony_ci} 1166cd6a6acSopenharmony_ci 1176cd6a6acSopenharmony_ci 1186cd6a6acSopenharmony_ci/* MLS */ 1196cd6a6acSopenharmony_ciconst char *sepol_user_get_mlslevel(const sepol_user_t * user) 1206cd6a6acSopenharmony_ci{ 1216cd6a6acSopenharmony_ci 1226cd6a6acSopenharmony_ci return user->mls_level; 1236cd6a6acSopenharmony_ci} 1246cd6a6acSopenharmony_ci 1256cd6a6acSopenharmony_ci 1266cd6a6acSopenharmony_ciint sepol_user_set_mlslevel(sepol_handle_t * handle, 1276cd6a6acSopenharmony_ci sepol_user_t * user, const char *mls_level) 1286cd6a6acSopenharmony_ci{ 1296cd6a6acSopenharmony_ci 1306cd6a6acSopenharmony_ci char *tmp_mls_level = strdup(mls_level); 1316cd6a6acSopenharmony_ci if (!tmp_mls_level) { 1326cd6a6acSopenharmony_ci ERR(handle, "out of memory, " 1336cd6a6acSopenharmony_ci "could not set MLS default level"); 1346cd6a6acSopenharmony_ci return STATUS_ERR; 1356cd6a6acSopenharmony_ci } 1366cd6a6acSopenharmony_ci free(user->mls_level); 1376cd6a6acSopenharmony_ci user->mls_level = tmp_mls_level; 1386cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1396cd6a6acSopenharmony_ci} 1406cd6a6acSopenharmony_ci 1416cd6a6acSopenharmony_ci 1426cd6a6acSopenharmony_ciconst char *sepol_user_get_mlsrange(const sepol_user_t * user) 1436cd6a6acSopenharmony_ci{ 1446cd6a6acSopenharmony_ci 1456cd6a6acSopenharmony_ci return user->mls_range; 1466cd6a6acSopenharmony_ci} 1476cd6a6acSopenharmony_ci 1486cd6a6acSopenharmony_ci 1496cd6a6acSopenharmony_ciint sepol_user_set_mlsrange(sepol_handle_t * handle, 1506cd6a6acSopenharmony_ci sepol_user_t * user, const char *mls_range) 1516cd6a6acSopenharmony_ci{ 1526cd6a6acSopenharmony_ci 1536cd6a6acSopenharmony_ci char *tmp_mls_range = strdup(mls_range); 1546cd6a6acSopenharmony_ci if (!tmp_mls_range) { 1556cd6a6acSopenharmony_ci ERR(handle, "out of memory, " 1566cd6a6acSopenharmony_ci "could not set MLS allowed range"); 1576cd6a6acSopenharmony_ci return STATUS_ERR; 1586cd6a6acSopenharmony_ci } 1596cd6a6acSopenharmony_ci free(user->mls_range); 1606cd6a6acSopenharmony_ci user->mls_range = tmp_mls_range; 1616cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1626cd6a6acSopenharmony_ci} 1636cd6a6acSopenharmony_ci 1646cd6a6acSopenharmony_ci 1656cd6a6acSopenharmony_ci/* Roles */ 1666cd6a6acSopenharmony_ciint sepol_user_get_num_roles(const sepol_user_t * user) 1676cd6a6acSopenharmony_ci{ 1686cd6a6acSopenharmony_ci 1696cd6a6acSopenharmony_ci return user->num_roles; 1706cd6a6acSopenharmony_ci} 1716cd6a6acSopenharmony_ci 1726cd6a6acSopenharmony_ciint sepol_user_add_role(sepol_handle_t * handle, 1736cd6a6acSopenharmony_ci sepol_user_t * user, const char *role) 1746cd6a6acSopenharmony_ci{ 1756cd6a6acSopenharmony_ci 1766cd6a6acSopenharmony_ci char *role_cp; 1776cd6a6acSopenharmony_ci char **roles_realloc = NULL; 1786cd6a6acSopenharmony_ci 1796cd6a6acSopenharmony_ci if (sepol_user_has_role(user, role)) 1806cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1816cd6a6acSopenharmony_ci 1826cd6a6acSopenharmony_ci role_cp = strdup(role); 1836cd6a6acSopenharmony_ci if (!role_cp) 1846cd6a6acSopenharmony_ci goto omem; 1856cd6a6acSopenharmony_ci 1866cd6a6acSopenharmony_ci roles_realloc = reallocarray(user->roles, 1876cd6a6acSopenharmony_ci user->num_roles + 1, 1886cd6a6acSopenharmony_ci sizeof(char *)); 1896cd6a6acSopenharmony_ci if (!roles_realloc) 1906cd6a6acSopenharmony_ci goto omem; 1916cd6a6acSopenharmony_ci 1926cd6a6acSopenharmony_ci user->num_roles++; 1936cd6a6acSopenharmony_ci user->roles = roles_realloc; 1946cd6a6acSopenharmony_ci user->roles[user->num_roles - 1] = role_cp; 1956cd6a6acSopenharmony_ci 1966cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1976cd6a6acSopenharmony_ci 1986cd6a6acSopenharmony_ci omem: 1996cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not add role %s", role); 2006cd6a6acSopenharmony_ci free(role_cp); 2016cd6a6acSopenharmony_ci free(roles_realloc); 2026cd6a6acSopenharmony_ci return STATUS_ERR; 2036cd6a6acSopenharmony_ci} 2046cd6a6acSopenharmony_ci 2056cd6a6acSopenharmony_ci 2066cd6a6acSopenharmony_ciint sepol_user_has_role(const sepol_user_t * user, const char *role) 2076cd6a6acSopenharmony_ci{ 2086cd6a6acSopenharmony_ci 2096cd6a6acSopenharmony_ci unsigned int i; 2106cd6a6acSopenharmony_ci 2116cd6a6acSopenharmony_ci for (i = 0; i < user->num_roles; i++) 2126cd6a6acSopenharmony_ci if (!strcmp(user->roles[i], role)) 2136cd6a6acSopenharmony_ci return 1; 2146cd6a6acSopenharmony_ci return 0; 2156cd6a6acSopenharmony_ci} 2166cd6a6acSopenharmony_ci 2176cd6a6acSopenharmony_ci 2186cd6a6acSopenharmony_ciint sepol_user_set_roles(sepol_handle_t * handle, 2196cd6a6acSopenharmony_ci sepol_user_t * user, 2206cd6a6acSopenharmony_ci const char **roles_arr, unsigned int num_roles) 2216cd6a6acSopenharmony_ci{ 2226cd6a6acSopenharmony_ci 2236cd6a6acSopenharmony_ci unsigned int i; 2246cd6a6acSopenharmony_ci char **tmp_roles = NULL; 2256cd6a6acSopenharmony_ci 2266cd6a6acSopenharmony_ci if (num_roles > 0) { 2276cd6a6acSopenharmony_ci 2286cd6a6acSopenharmony_ci /* First, make a copy */ 2296cd6a6acSopenharmony_ci tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles); 2306cd6a6acSopenharmony_ci if (!tmp_roles) 2316cd6a6acSopenharmony_ci goto omem; 2326cd6a6acSopenharmony_ci 2336cd6a6acSopenharmony_ci for (i = 0; i < num_roles; i++) { 2346cd6a6acSopenharmony_ci tmp_roles[i] = strdup(roles_arr[i]); 2356cd6a6acSopenharmony_ci if (!tmp_roles[i]) 2366cd6a6acSopenharmony_ci goto omem; 2376cd6a6acSopenharmony_ci } 2386cd6a6acSopenharmony_ci } 2396cd6a6acSopenharmony_ci 2406cd6a6acSopenharmony_ci /* Apply other changes */ 2416cd6a6acSopenharmony_ci for (i = 0; i < user->num_roles; i++) 2426cd6a6acSopenharmony_ci free(user->roles[i]); 2436cd6a6acSopenharmony_ci free(user->roles); 2446cd6a6acSopenharmony_ci user->roles = tmp_roles; 2456cd6a6acSopenharmony_ci user->num_roles = num_roles; 2466cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2476cd6a6acSopenharmony_ci 2486cd6a6acSopenharmony_ci omem: 2496cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not allocate roles array for" 2506cd6a6acSopenharmony_ci "user %s", user->name); 2516cd6a6acSopenharmony_ci 2526cd6a6acSopenharmony_ci if (tmp_roles) { 2536cd6a6acSopenharmony_ci for (i = 0; i < num_roles; i++) { 2546cd6a6acSopenharmony_ci if (!tmp_roles[i]) 2556cd6a6acSopenharmony_ci break; 2566cd6a6acSopenharmony_ci free(tmp_roles[i]); 2576cd6a6acSopenharmony_ci } 2586cd6a6acSopenharmony_ci } 2596cd6a6acSopenharmony_ci free(tmp_roles); 2606cd6a6acSopenharmony_ci return STATUS_ERR; 2616cd6a6acSopenharmony_ci} 2626cd6a6acSopenharmony_ci 2636cd6a6acSopenharmony_ciint sepol_user_get_roles(sepol_handle_t * handle, 2646cd6a6acSopenharmony_ci const sepol_user_t * user, 2656cd6a6acSopenharmony_ci const char ***roles_arr, unsigned int *num_roles) 2666cd6a6acSopenharmony_ci{ 2676cd6a6acSopenharmony_ci 2686cd6a6acSopenharmony_ci unsigned int i; 2696cd6a6acSopenharmony_ci const char **tmp_roles = 2706cd6a6acSopenharmony_ci (const char **)calloc(user->num_roles, sizeof(char *)); 2716cd6a6acSopenharmony_ci if (!tmp_roles) 2726cd6a6acSopenharmony_ci goto omem; 2736cd6a6acSopenharmony_ci 2746cd6a6acSopenharmony_ci for (i = 0; i < user->num_roles; i++) 2756cd6a6acSopenharmony_ci tmp_roles[i] = user->roles[i]; 2766cd6a6acSopenharmony_ci 2776cd6a6acSopenharmony_ci *roles_arr = tmp_roles; 2786cd6a6acSopenharmony_ci *num_roles = user->num_roles; 2796cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2806cd6a6acSopenharmony_ci 2816cd6a6acSopenharmony_ci omem: 2826cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not " 2836cd6a6acSopenharmony_ci "allocate roles array for user %s", user->name); 2846cd6a6acSopenharmony_ci free(tmp_roles); 2856cd6a6acSopenharmony_ci return STATUS_ERR; 2866cd6a6acSopenharmony_ci} 2876cd6a6acSopenharmony_ci 2886cd6a6acSopenharmony_ci 2896cd6a6acSopenharmony_civoid sepol_user_del_role(sepol_user_t * user, const char *role) 2906cd6a6acSopenharmony_ci{ 2916cd6a6acSopenharmony_ci 2926cd6a6acSopenharmony_ci unsigned int i; 2936cd6a6acSopenharmony_ci for (i = 0; i < user->num_roles; i++) { 2946cd6a6acSopenharmony_ci if (!strcmp(user->roles[i], role)) { 2956cd6a6acSopenharmony_ci free(user->roles[i]); 2966cd6a6acSopenharmony_ci user->roles[i] = NULL; 2976cd6a6acSopenharmony_ci user->roles[i] = user->roles[user->num_roles - 1]; 2986cd6a6acSopenharmony_ci user->num_roles--; 2996cd6a6acSopenharmony_ci } 3006cd6a6acSopenharmony_ci } 3016cd6a6acSopenharmony_ci} 3026cd6a6acSopenharmony_ci 3036cd6a6acSopenharmony_ci/* Create */ 3046cd6a6acSopenharmony_ciint sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr) 3056cd6a6acSopenharmony_ci{ 3066cd6a6acSopenharmony_ci 3076cd6a6acSopenharmony_ci sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t)); 3086cd6a6acSopenharmony_ci 3096cd6a6acSopenharmony_ci if (!user) { 3106cd6a6acSopenharmony_ci ERR(handle, "out of memory, " 3116cd6a6acSopenharmony_ci "could not create selinux user record"); 3126cd6a6acSopenharmony_ci return STATUS_ERR; 3136cd6a6acSopenharmony_ci } 3146cd6a6acSopenharmony_ci 3156cd6a6acSopenharmony_ci user->roles = NULL; 3166cd6a6acSopenharmony_ci user->num_roles = 0; 3176cd6a6acSopenharmony_ci user->name = NULL; 3186cd6a6acSopenharmony_ci user->mls_level = NULL; 3196cd6a6acSopenharmony_ci user->mls_range = NULL; 3206cd6a6acSopenharmony_ci 3216cd6a6acSopenharmony_ci *user_ptr = user; 3226cd6a6acSopenharmony_ci return STATUS_SUCCESS; 3236cd6a6acSopenharmony_ci} 3246cd6a6acSopenharmony_ci 3256cd6a6acSopenharmony_ci 3266cd6a6acSopenharmony_ci/* Deep copy clone */ 3276cd6a6acSopenharmony_ciint sepol_user_clone(sepol_handle_t * handle, 3286cd6a6acSopenharmony_ci const sepol_user_t * user, sepol_user_t ** user_ptr) 3296cd6a6acSopenharmony_ci{ 3306cd6a6acSopenharmony_ci 3316cd6a6acSopenharmony_ci sepol_user_t *new_user = NULL; 3326cd6a6acSopenharmony_ci unsigned int i; 3336cd6a6acSopenharmony_ci 3346cd6a6acSopenharmony_ci if (sepol_user_create(handle, &new_user) < 0) 3356cd6a6acSopenharmony_ci goto err; 3366cd6a6acSopenharmony_ci 3376cd6a6acSopenharmony_ci if (sepol_user_set_name(handle, new_user, user->name) < 0) 3386cd6a6acSopenharmony_ci goto err; 3396cd6a6acSopenharmony_ci 3406cd6a6acSopenharmony_ci for (i = 0; i < user->num_roles; i++) { 3416cd6a6acSopenharmony_ci if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0) 3426cd6a6acSopenharmony_ci goto err; 3436cd6a6acSopenharmony_ci } 3446cd6a6acSopenharmony_ci 3456cd6a6acSopenharmony_ci if (user->mls_level && 3466cd6a6acSopenharmony_ci (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0)) 3476cd6a6acSopenharmony_ci goto err; 3486cd6a6acSopenharmony_ci 3496cd6a6acSopenharmony_ci if (user->mls_range && 3506cd6a6acSopenharmony_ci (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0)) 3516cd6a6acSopenharmony_ci goto err; 3526cd6a6acSopenharmony_ci 3536cd6a6acSopenharmony_ci *user_ptr = new_user; 3546cd6a6acSopenharmony_ci return STATUS_SUCCESS; 3556cd6a6acSopenharmony_ci 3566cd6a6acSopenharmony_ci err: 3576cd6a6acSopenharmony_ci ERR(handle, "could not clone selinux user record"); 3586cd6a6acSopenharmony_ci sepol_user_free(new_user); 3596cd6a6acSopenharmony_ci return STATUS_ERR; 3606cd6a6acSopenharmony_ci} 3616cd6a6acSopenharmony_ci 3626cd6a6acSopenharmony_ci/* Destroy */ 3636cd6a6acSopenharmony_civoid sepol_user_free(sepol_user_t * user) 3646cd6a6acSopenharmony_ci{ 3656cd6a6acSopenharmony_ci 3666cd6a6acSopenharmony_ci unsigned int i; 3676cd6a6acSopenharmony_ci 3686cd6a6acSopenharmony_ci if (!user) 3696cd6a6acSopenharmony_ci return; 3706cd6a6acSopenharmony_ci 3716cd6a6acSopenharmony_ci free(user->name); 3726cd6a6acSopenharmony_ci for (i = 0; i < user->num_roles; i++) 3736cd6a6acSopenharmony_ci free(user->roles[i]); 3746cd6a6acSopenharmony_ci free(user->roles); 3756cd6a6acSopenharmony_ci free(user->mls_level); 3766cd6a6acSopenharmony_ci free(user->mls_range); 3776cd6a6acSopenharmony_ci free(user); 3786cd6a6acSopenharmony_ci} 3796cd6a6acSopenharmony_ci 380