xref: /aosp_15_r20/external/selinux/libsemanage/src/users_base_file.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Copyright (C) 2005 Red Hat, Inc. */
2*2d543d20SAndroid Build Coastguard Worker 
3*2d543d20SAndroid Build Coastguard Worker struct semanage_user_base;
4*2d543d20SAndroid Build Coastguard Worker struct semanage_user_key;
5*2d543d20SAndroid Build Coastguard Worker typedef struct semanage_user_base record_t;
6*2d543d20SAndroid Build Coastguard Worker typedef struct semanage_user_key record_key_t;
7*2d543d20SAndroid Build Coastguard Worker #define DBASE_RECORD_DEFINED
8*2d543d20SAndroid Build Coastguard Worker 
9*2d543d20SAndroid Build Coastguard Worker struct dbase_file;
10*2d543d20SAndroid Build Coastguard Worker typedef struct dbase_file dbase_t;
11*2d543d20SAndroid Build Coastguard Worker #define DBASE_DEFINED
12*2d543d20SAndroid Build Coastguard Worker 
13*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
14*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
15*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
16*2d543d20SAndroid Build Coastguard Worker #include <string.h>
17*2d543d20SAndroid Build Coastguard Worker #include <semanage/handle.h>
18*2d543d20SAndroid Build Coastguard Worker #include "user_internal.h"
19*2d543d20SAndroid Build Coastguard Worker #include "database_file.h"
20*2d543d20SAndroid Build Coastguard Worker #include "parse_utils.h"
21*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
22*2d543d20SAndroid Build Coastguard Worker 
user_base_print(semanage_handle_t * handle,semanage_user_base_t * user,FILE * str)23*2d543d20SAndroid Build Coastguard Worker static int user_base_print(semanage_handle_t * handle,
24*2d543d20SAndroid Build Coastguard Worker 			   semanage_user_base_t * user, FILE * str)
25*2d543d20SAndroid Build Coastguard Worker {
26*2d543d20SAndroid Build Coastguard Worker 
27*2d543d20SAndroid Build Coastguard Worker 	const char **roles = NULL;
28*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, nroles;
29*2d543d20SAndroid Build Coastguard Worker 
30*2d543d20SAndroid Build Coastguard Worker 	const char *name = semanage_user_base_get_name(user);
31*2d543d20SAndroid Build Coastguard Worker 	const char *mls_level = semanage_user_base_get_mlslevel(user);
32*2d543d20SAndroid Build Coastguard Worker 	const char *mls_range = semanage_user_base_get_mlsrange(user);
33*2d543d20SAndroid Build Coastguard Worker 
34*2d543d20SAndroid Build Coastguard Worker 	if (fprintf(str, "user %s roles { ", name) < 0)
35*2d543d20SAndroid Build Coastguard Worker 		goto err;
36*2d543d20SAndroid Build Coastguard Worker 
37*2d543d20SAndroid Build Coastguard Worker 	if (semanage_user_base_get_roles(handle, user, &roles, &nroles) < 0)
38*2d543d20SAndroid Build Coastguard Worker 		goto err;
39*2d543d20SAndroid Build Coastguard Worker 
40*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < nroles; i++) {
41*2d543d20SAndroid Build Coastguard Worker 		if (fprintf(str, "%s ", roles[i]) < 0)
42*2d543d20SAndroid Build Coastguard Worker 			goto err;
43*2d543d20SAndroid Build Coastguard Worker 	}
44*2d543d20SAndroid Build Coastguard Worker 
45*2d543d20SAndroid Build Coastguard Worker 	if (fprintf(str, "} ") < 0)
46*2d543d20SAndroid Build Coastguard Worker 		goto err;
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker 	/* MLS */
49*2d543d20SAndroid Build Coastguard Worker 	if (mls_level != NULL && mls_range != NULL)
50*2d543d20SAndroid Build Coastguard Worker 		if (fprintf(str, "level %s range %s", mls_level, mls_range) < 0)
51*2d543d20SAndroid Build Coastguard Worker 			goto err;
52*2d543d20SAndroid Build Coastguard Worker 
53*2d543d20SAndroid Build Coastguard Worker 	if (fprintf(str, ";\n") < 0)
54*2d543d20SAndroid Build Coastguard Worker 		goto err;
55*2d543d20SAndroid Build Coastguard Worker 
56*2d543d20SAndroid Build Coastguard Worker 	free(roles);
57*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
58*2d543d20SAndroid Build Coastguard Worker 
59*2d543d20SAndroid Build Coastguard Worker       err:
60*2d543d20SAndroid Build Coastguard Worker 	free(roles);
61*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not print user %s to stream", name);
62*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
63*2d543d20SAndroid Build Coastguard Worker }
64*2d543d20SAndroid Build Coastguard Worker 
user_base_parse(semanage_handle_t * handle,parse_info_t * info,semanage_user_base_t * user)65*2d543d20SAndroid Build Coastguard Worker static int user_base_parse(semanage_handle_t * handle,
66*2d543d20SAndroid Build Coastguard Worker 			   parse_info_t * info, semanage_user_base_t * user)
67*2d543d20SAndroid Build Coastguard Worker {
68*2d543d20SAndroid Build Coastguard Worker 
69*2d543d20SAndroid Build Coastguard Worker 	int islist = 0;
70*2d543d20SAndroid Build Coastguard Worker 	char *str = NULL;
71*2d543d20SAndroid Build Coastguard Worker 	char *start;
72*2d543d20SAndroid Build Coastguard Worker 	char *name_str = NULL;
73*2d543d20SAndroid Build Coastguard Worker 
74*2d543d20SAndroid Build Coastguard Worker 	if (parse_skip_space(handle, info) < 0)
75*2d543d20SAndroid Build Coastguard Worker 		goto err;
76*2d543d20SAndroid Build Coastguard Worker 	if (!info->ptr)
77*2d543d20SAndroid Build Coastguard Worker 		goto last;
78*2d543d20SAndroid Build Coastguard Worker 
79*2d543d20SAndroid Build Coastguard Worker 	/* Parse user header */
80*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_str(handle, info, "user") < 0)
81*2d543d20SAndroid Build Coastguard Worker 		goto err;
82*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_space(handle, info) < 0)
83*2d543d20SAndroid Build Coastguard Worker 		goto err;
84*2d543d20SAndroid Build Coastguard Worker 
85*2d543d20SAndroid Build Coastguard Worker 	/* Parse user name */
86*2d543d20SAndroid Build Coastguard Worker 	if (parse_fetch_string(handle, info, &name_str, ' ', 0) < 0)
87*2d543d20SAndroid Build Coastguard Worker 		goto err;
88*2d543d20SAndroid Build Coastguard Worker 
89*2d543d20SAndroid Build Coastguard Worker 	if (semanage_user_base_set_name(handle, user, name_str) < 0) {
90*2d543d20SAndroid Build Coastguard Worker 		free(name_str);
91*2d543d20SAndroid Build Coastguard Worker 		goto err;
92*2d543d20SAndroid Build Coastguard Worker 	}
93*2d543d20SAndroid Build Coastguard Worker 	free(name_str);
94*2d543d20SAndroid Build Coastguard Worker 
95*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_space(handle, info) < 0)
96*2d543d20SAndroid Build Coastguard Worker 		goto err;
97*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_str(handle, info, "roles") < 0)
98*2d543d20SAndroid Build Coastguard Worker 		goto err;
99*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_space(handle, info) < 0)
100*2d543d20SAndroid Build Coastguard Worker 		goto err;
101*2d543d20SAndroid Build Coastguard Worker 
102*2d543d20SAndroid Build Coastguard Worker 	islist = (parse_optional_ch(info, '{') != STATUS_NODATA);
103*2d543d20SAndroid Build Coastguard Worker 
104*2d543d20SAndroid Build Coastguard Worker 	/* For each role, loop */
105*2d543d20SAndroid Build Coastguard Worker 	do {
106*2d543d20SAndroid Build Coastguard Worker 		char delim;
107*2d543d20SAndroid Build Coastguard Worker 
108*2d543d20SAndroid Build Coastguard Worker 		if (parse_skip_space(handle, info) < 0)
109*2d543d20SAndroid Build Coastguard Worker 			goto err;
110*2d543d20SAndroid Build Coastguard Worker 		if (parse_assert_noeof(handle, info) < 0)
111*2d543d20SAndroid Build Coastguard Worker 			goto err;
112*2d543d20SAndroid Build Coastguard Worker 
113*2d543d20SAndroid Build Coastguard Worker 		start = info->ptr;
114*2d543d20SAndroid Build Coastguard Worker 		while (*(info->ptr) &&
115*2d543d20SAndroid Build Coastguard Worker 		       *(info->ptr) != ';' &&
116*2d543d20SAndroid Build Coastguard Worker 		       *(info->ptr) != '}' && !isspace(*(info->ptr)))
117*2d543d20SAndroid Build Coastguard Worker 			info->ptr++;
118*2d543d20SAndroid Build Coastguard Worker 
119*2d543d20SAndroid Build Coastguard Worker 		delim = *(info->ptr);
120*2d543d20SAndroid Build Coastguard Worker 		*(info->ptr)++ = '\0';
121*2d543d20SAndroid Build Coastguard Worker 
122*2d543d20SAndroid Build Coastguard Worker 		if (semanage_user_base_add_role(handle, user, start) < 0)
123*2d543d20SAndroid Build Coastguard Worker 			goto err;
124*2d543d20SAndroid Build Coastguard Worker 
125*2d543d20SAndroid Build Coastguard Worker 		if (delim && !isspace(delim)) {
126*2d543d20SAndroid Build Coastguard Worker 			if (islist && delim == '}')
127*2d543d20SAndroid Build Coastguard Worker 				break;
128*2d543d20SAndroid Build Coastguard Worker 			else if (!islist && delim == ';')
129*2d543d20SAndroid Build Coastguard Worker 				goto skip_semicolon;
130*2d543d20SAndroid Build Coastguard Worker 			else
131*2d543d20SAndroid Build Coastguard Worker 				goto err;
132*2d543d20SAndroid Build Coastguard Worker 		}
133*2d543d20SAndroid Build Coastguard Worker 
134*2d543d20SAndroid Build Coastguard Worker 		if (parse_skip_space(handle, info) < 0)
135*2d543d20SAndroid Build Coastguard Worker 			goto err;
136*2d543d20SAndroid Build Coastguard Worker 		if (parse_optional_ch(info, ';') != STATUS_NODATA)
137*2d543d20SAndroid Build Coastguard Worker 			goto skip_semicolon;
138*2d543d20SAndroid Build Coastguard Worker 		if (parse_optional_ch(info, '}') != STATUS_NODATA)
139*2d543d20SAndroid Build Coastguard Worker 			islist = 0;
140*2d543d20SAndroid Build Coastguard Worker 
141*2d543d20SAndroid Build Coastguard Worker 	} while (islist);
142*2d543d20SAndroid Build Coastguard Worker 
143*2d543d20SAndroid Build Coastguard Worker 	/* Handle mls */
144*2d543d20SAndroid Build Coastguard Worker 	/* Parse level header */
145*2d543d20SAndroid Build Coastguard Worker 	if (parse_skip_space(handle, info) < 0)
146*2d543d20SAndroid Build Coastguard Worker 		goto err;
147*2d543d20SAndroid Build Coastguard Worker 	if (parse_optional_str(info, "level") == STATUS_NODATA)
148*2d543d20SAndroid Build Coastguard Worker 		goto semicolon;
149*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_space(handle, info) < 0)
150*2d543d20SAndroid Build Coastguard Worker 		goto err;
151*2d543d20SAndroid Build Coastguard Worker 
152*2d543d20SAndroid Build Coastguard Worker 	/* NOTE: does not allow spaces/multiline */
153*2d543d20SAndroid Build Coastguard Worker 	if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
154*2d543d20SAndroid Build Coastguard Worker 		goto err;
155*2d543d20SAndroid Build Coastguard Worker 	if (semanage_user_base_set_mlslevel(handle, user, str) < 0)
156*2d543d20SAndroid Build Coastguard Worker 		goto err;
157*2d543d20SAndroid Build Coastguard Worker 	free(str);
158*2d543d20SAndroid Build Coastguard Worker 	str = NULL;
159*2d543d20SAndroid Build Coastguard Worker 
160*2d543d20SAndroid Build Coastguard Worker 	/* Parse range header */
161*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_space(handle, info) < 0)
162*2d543d20SAndroid Build Coastguard Worker 		goto err;
163*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_str(handle, info, "range") < 0)
164*2d543d20SAndroid Build Coastguard Worker 		goto err;
165*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_space(handle, info) < 0)
166*2d543d20SAndroid Build Coastguard Worker 		goto err;
167*2d543d20SAndroid Build Coastguard Worker 
168*2d543d20SAndroid Build Coastguard Worker 	if (parse_fetch_string(handle, info, &str, ';', 1) < 0)
169*2d543d20SAndroid Build Coastguard Worker 		goto err;
170*2d543d20SAndroid Build Coastguard Worker 	if (semanage_user_base_set_mlsrange(handle, user, str) < 0)
171*2d543d20SAndroid Build Coastguard Worker 		goto err;
172*2d543d20SAndroid Build Coastguard Worker 
173*2d543d20SAndroid Build Coastguard Worker 	free(str);
174*2d543d20SAndroid Build Coastguard Worker 	str = NULL;
175*2d543d20SAndroid Build Coastguard Worker 
176*2d543d20SAndroid Build Coastguard Worker 	/* Check for semicolon */
177*2d543d20SAndroid Build Coastguard Worker       semicolon:
178*2d543d20SAndroid Build Coastguard Worker 	if (parse_skip_space(handle, info) < 0)
179*2d543d20SAndroid Build Coastguard Worker 		goto err;
180*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_ch(handle, info, ';') < 0)
181*2d543d20SAndroid Build Coastguard Worker 		goto err;
182*2d543d20SAndroid Build Coastguard Worker 
183*2d543d20SAndroid Build Coastguard Worker       skip_semicolon:
184*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
185*2d543d20SAndroid Build Coastguard Worker 
186*2d543d20SAndroid Build Coastguard Worker       last:
187*2d543d20SAndroid Build Coastguard Worker 	parse_dispose_line(info);
188*2d543d20SAndroid Build Coastguard Worker 	return STATUS_NODATA;
189*2d543d20SAndroid Build Coastguard Worker 
190*2d543d20SAndroid Build Coastguard Worker       err:
191*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not parse user record");
192*2d543d20SAndroid Build Coastguard Worker 	free(str);
193*2d543d20SAndroid Build Coastguard Worker 	parse_dispose_line(info);
194*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
195*2d543d20SAndroid Build Coastguard Worker }
196*2d543d20SAndroid Build Coastguard Worker 
197*2d543d20SAndroid Build Coastguard Worker /* USER BASE record: FILE extension: method table */
198*2d543d20SAndroid Build Coastguard Worker record_file_table_t SEMANAGE_USER_BASE_FILE_RTABLE = {
199*2d543d20SAndroid Build Coastguard Worker 	.parse = user_base_parse,
200*2d543d20SAndroid Build Coastguard Worker 	.print = user_base_print,
201*2d543d20SAndroid Build Coastguard Worker };
202*2d543d20SAndroid Build Coastguard Worker 
user_base_file_dbase_init(semanage_handle_t * handle,const char * path_ro,const char * path_rw,dbase_config_t * dconfig)203*2d543d20SAndroid Build Coastguard Worker int user_base_file_dbase_init(semanage_handle_t * handle,
204*2d543d20SAndroid Build Coastguard Worker 			      const char *path_ro,
205*2d543d20SAndroid Build Coastguard Worker 			      const char *path_rw,
206*2d543d20SAndroid Build Coastguard Worker 			      dbase_config_t * dconfig)
207*2d543d20SAndroid Build Coastguard Worker {
208*2d543d20SAndroid Build Coastguard Worker 
209*2d543d20SAndroid Build Coastguard Worker 	if (dbase_file_init(handle,
210*2d543d20SAndroid Build Coastguard Worker 			    path_ro,
211*2d543d20SAndroid Build Coastguard Worker 			    path_rw,
212*2d543d20SAndroid Build Coastguard Worker 			    &SEMANAGE_USER_BASE_RTABLE,
213*2d543d20SAndroid Build Coastguard Worker 			    &SEMANAGE_USER_BASE_FILE_RTABLE,
214*2d543d20SAndroid Build Coastguard Worker 			    &dconfig->dbase) < 0)
215*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
216*2d543d20SAndroid Build Coastguard Worker 
217*2d543d20SAndroid Build Coastguard Worker 	dconfig->dtable = &SEMANAGE_FILE_DTABLE;
218*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
219*2d543d20SAndroid Build Coastguard Worker }
220*2d543d20SAndroid Build Coastguard Worker 
user_base_file_dbase_release(dbase_config_t * dconfig)221*2d543d20SAndroid Build Coastguard Worker void user_base_file_dbase_release(dbase_config_t * dconfig)
222*2d543d20SAndroid Build Coastguard Worker {
223*2d543d20SAndroid Build Coastguard Worker 
224*2d543d20SAndroid Build Coastguard Worker 	dbase_file_release(dconfig->dbase);
225*2d543d20SAndroid Build Coastguard Worker }
226