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