1*2d543d20SAndroid Build Coastguard Worker /* Copyright (C) 2005 Red Hat, Inc. */
2*2d543d20SAndroid Build Coastguard Worker
3*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
4*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
5*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
6*2d543d20SAndroid Build Coastguard Worker #include <string.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
8*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
9*2d543d20SAndroid Build Coastguard Worker #include <semanage/handle.h>
10*2d543d20SAndroid Build Coastguard Worker #include "parse_utils.h"
11*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
12*2d543d20SAndroid Build Coastguard Worker
parse_init(semanage_handle_t * handle,const char * filename,void * parse_arg,parse_info_t ** info)13*2d543d20SAndroid Build Coastguard Worker int parse_init(semanage_handle_t * handle,
14*2d543d20SAndroid Build Coastguard Worker const char *filename, void *parse_arg, parse_info_t ** info)
15*2d543d20SAndroid Build Coastguard Worker {
16*2d543d20SAndroid Build Coastguard Worker
17*2d543d20SAndroid Build Coastguard Worker parse_info_t *tmp_info = (parse_info_t *) malloc(sizeof(parse_info_t));
18*2d543d20SAndroid Build Coastguard Worker
19*2d543d20SAndroid Build Coastguard Worker if (!tmp_info) {
20*2d543d20SAndroid Build Coastguard Worker ERR(handle,
21*2d543d20SAndroid Build Coastguard Worker "out of memory, could not allocate parse structure");
22*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
23*2d543d20SAndroid Build Coastguard Worker }
24*2d543d20SAndroid Build Coastguard Worker
25*2d543d20SAndroid Build Coastguard Worker tmp_info->filename = filename;
26*2d543d20SAndroid Build Coastguard Worker tmp_info->file_stream = NULL;
27*2d543d20SAndroid Build Coastguard Worker tmp_info->working_copy = NULL;
28*2d543d20SAndroid Build Coastguard Worker tmp_info->orig_line = NULL;
29*2d543d20SAndroid Build Coastguard Worker tmp_info->ptr = NULL;
30*2d543d20SAndroid Build Coastguard Worker tmp_info->lineno = 0;
31*2d543d20SAndroid Build Coastguard Worker tmp_info->parse_arg = parse_arg;
32*2d543d20SAndroid Build Coastguard Worker
33*2d543d20SAndroid Build Coastguard Worker *info = tmp_info;
34*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
35*2d543d20SAndroid Build Coastguard Worker }
36*2d543d20SAndroid Build Coastguard Worker
parse_release(parse_info_t * info)37*2d543d20SAndroid Build Coastguard Worker void parse_release(parse_info_t * info)
38*2d543d20SAndroid Build Coastguard Worker {
39*2d543d20SAndroid Build Coastguard Worker
40*2d543d20SAndroid Build Coastguard Worker parse_close(info);
41*2d543d20SAndroid Build Coastguard Worker parse_dispose_line(info);
42*2d543d20SAndroid Build Coastguard Worker free(info);
43*2d543d20SAndroid Build Coastguard Worker }
44*2d543d20SAndroid Build Coastguard Worker
parse_open(semanage_handle_t * handle,parse_info_t * info)45*2d543d20SAndroid Build Coastguard Worker int parse_open(semanage_handle_t * handle, parse_info_t * info)
46*2d543d20SAndroid Build Coastguard Worker {
47*2d543d20SAndroid Build Coastguard Worker
48*2d543d20SAndroid Build Coastguard Worker info->file_stream = fopen(info->filename, "r");
49*2d543d20SAndroid Build Coastguard Worker if (!info->file_stream && (errno != ENOENT)) {
50*2d543d20SAndroid Build Coastguard Worker ERR(handle, "could not open file %s: %s",
51*2d543d20SAndroid Build Coastguard Worker info->filename, strerror(errno));
52*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
53*2d543d20SAndroid Build Coastguard Worker }
54*2d543d20SAndroid Build Coastguard Worker if (info->file_stream)
55*2d543d20SAndroid Build Coastguard Worker __fsetlocking(info->file_stream, FSETLOCKING_BYCALLER);
56*2d543d20SAndroid Build Coastguard Worker
57*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
58*2d543d20SAndroid Build Coastguard Worker }
59*2d543d20SAndroid Build Coastguard Worker
parse_close(parse_info_t * info)60*2d543d20SAndroid Build Coastguard Worker void parse_close(parse_info_t * info)
61*2d543d20SAndroid Build Coastguard Worker {
62*2d543d20SAndroid Build Coastguard Worker
63*2d543d20SAndroid Build Coastguard Worker if (info->file_stream)
64*2d543d20SAndroid Build Coastguard Worker fclose(info->file_stream);
65*2d543d20SAndroid Build Coastguard Worker info->file_stream = NULL;
66*2d543d20SAndroid Build Coastguard Worker }
67*2d543d20SAndroid Build Coastguard Worker
parse_dispose_line(parse_info_t * info)68*2d543d20SAndroid Build Coastguard Worker void parse_dispose_line(parse_info_t * info)
69*2d543d20SAndroid Build Coastguard Worker {
70*2d543d20SAndroid Build Coastguard Worker if (info->orig_line) {
71*2d543d20SAndroid Build Coastguard Worker free(info->orig_line);
72*2d543d20SAndroid Build Coastguard Worker info->orig_line = NULL;
73*2d543d20SAndroid Build Coastguard Worker }
74*2d543d20SAndroid Build Coastguard Worker
75*2d543d20SAndroid Build Coastguard Worker if (info->working_copy) {
76*2d543d20SAndroid Build Coastguard Worker free(info->working_copy);
77*2d543d20SAndroid Build Coastguard Worker info->working_copy = NULL;
78*2d543d20SAndroid Build Coastguard Worker }
79*2d543d20SAndroid Build Coastguard Worker
80*2d543d20SAndroid Build Coastguard Worker info->ptr = NULL;
81*2d543d20SAndroid Build Coastguard Worker }
82*2d543d20SAndroid Build Coastguard Worker
parse_skip_space(semanage_handle_t * handle,parse_info_t * info)83*2d543d20SAndroid Build Coastguard Worker int parse_skip_space(semanage_handle_t * handle, parse_info_t * info)
84*2d543d20SAndroid Build Coastguard Worker {
85*2d543d20SAndroid Build Coastguard Worker
86*2d543d20SAndroid Build Coastguard Worker size_t buf_len = 0;
87*2d543d20SAndroid Build Coastguard Worker ssize_t len;
88*2d543d20SAndroid Build Coastguard Worker int lineno = info->lineno;
89*2d543d20SAndroid Build Coastguard Worker char *buffer = NULL;
90*2d543d20SAndroid Build Coastguard Worker char *ptr;
91*2d543d20SAndroid Build Coastguard Worker
92*2d543d20SAndroid Build Coastguard Worker if (info->ptr) {
93*2d543d20SAndroid Build Coastguard Worker while (*(info->ptr) && isspace(*(info->ptr)))
94*2d543d20SAndroid Build Coastguard Worker info->ptr++;
95*2d543d20SAndroid Build Coastguard Worker
96*2d543d20SAndroid Build Coastguard Worker if (*(info->ptr))
97*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
98*2d543d20SAndroid Build Coastguard Worker }
99*2d543d20SAndroid Build Coastguard Worker
100*2d543d20SAndroid Build Coastguard Worker parse_dispose_line(info);
101*2d543d20SAndroid Build Coastguard Worker
102*2d543d20SAndroid Build Coastguard Worker while (info->file_stream &&
103*2d543d20SAndroid Build Coastguard Worker ((len = getline(&buffer, &buf_len, info->file_stream)) > 0)) {
104*2d543d20SAndroid Build Coastguard Worker
105*2d543d20SAndroid Build Coastguard Worker lineno++;
106*2d543d20SAndroid Build Coastguard Worker
107*2d543d20SAndroid Build Coastguard Worker /* Eat newline, preceding whitespace */
108*2d543d20SAndroid Build Coastguard Worker if (buffer[len - 1] == '\n')
109*2d543d20SAndroid Build Coastguard Worker buffer[len - 1] = '\0';
110*2d543d20SAndroid Build Coastguard Worker
111*2d543d20SAndroid Build Coastguard Worker ptr = buffer;
112*2d543d20SAndroid Build Coastguard Worker while (*ptr && isspace(*ptr))
113*2d543d20SAndroid Build Coastguard Worker ptr++;
114*2d543d20SAndroid Build Coastguard Worker
115*2d543d20SAndroid Build Coastguard Worker /* Skip comments and blank lines */
116*2d543d20SAndroid Build Coastguard Worker if ((*ptr) && *ptr != '#') {
117*2d543d20SAndroid Build Coastguard Worker char *tmp = strdup(buffer);
118*2d543d20SAndroid Build Coastguard Worker if (!tmp)
119*2d543d20SAndroid Build Coastguard Worker goto omem;
120*2d543d20SAndroid Build Coastguard Worker
121*2d543d20SAndroid Build Coastguard Worker info->lineno = lineno;
122*2d543d20SAndroid Build Coastguard Worker info->working_copy = buffer;
123*2d543d20SAndroid Build Coastguard Worker info->orig_line = tmp;
124*2d543d20SAndroid Build Coastguard Worker info->ptr = ptr;
125*2d543d20SAndroid Build Coastguard Worker
126*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
127*2d543d20SAndroid Build Coastguard Worker }
128*2d543d20SAndroid Build Coastguard Worker }
129*2d543d20SAndroid Build Coastguard Worker
130*2d543d20SAndroid Build Coastguard Worker free(buffer);
131*2d543d20SAndroid Build Coastguard Worker buffer = NULL;
132*2d543d20SAndroid Build Coastguard Worker
133*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
134*2d543d20SAndroid Build Coastguard Worker
135*2d543d20SAndroid Build Coastguard Worker omem:
136*2d543d20SAndroid Build Coastguard Worker ERR(handle, "out of memory, could not allocate buffer");
137*2d543d20SAndroid Build Coastguard Worker free(buffer);
138*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
139*2d543d20SAndroid Build Coastguard Worker }
140*2d543d20SAndroid Build Coastguard Worker
parse_assert_noeof(semanage_handle_t * handle,parse_info_t * info)141*2d543d20SAndroid Build Coastguard Worker int parse_assert_noeof(semanage_handle_t * handle, parse_info_t * info)
142*2d543d20SAndroid Build Coastguard Worker {
143*2d543d20SAndroid Build Coastguard Worker
144*2d543d20SAndroid Build Coastguard Worker if (!info->ptr) {
145*2d543d20SAndroid Build Coastguard Worker ERR(handle, "unexpected end of file (%s: %u)",
146*2d543d20SAndroid Build Coastguard Worker info->filename, info->lineno);
147*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
148*2d543d20SAndroid Build Coastguard Worker }
149*2d543d20SAndroid Build Coastguard Worker
150*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
151*2d543d20SAndroid Build Coastguard Worker }
152*2d543d20SAndroid Build Coastguard Worker
parse_assert_space(semanage_handle_t * handle,parse_info_t * info)153*2d543d20SAndroid Build Coastguard Worker int parse_assert_space(semanage_handle_t * handle, parse_info_t * info)
154*2d543d20SAndroid Build Coastguard Worker {
155*2d543d20SAndroid Build Coastguard Worker
156*2d543d20SAndroid Build Coastguard Worker if (parse_assert_noeof(handle, info) < 0)
157*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
158*2d543d20SAndroid Build Coastguard Worker
159*2d543d20SAndroid Build Coastguard Worker if (*(info->ptr) && !isspace(*(info->ptr))) {
160*2d543d20SAndroid Build Coastguard Worker ERR(handle, "missing whitespace (%s: %u):\n%s",
161*2d543d20SAndroid Build Coastguard Worker info->filename, info->lineno, info->orig_line);
162*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
163*2d543d20SAndroid Build Coastguard Worker }
164*2d543d20SAndroid Build Coastguard Worker
165*2d543d20SAndroid Build Coastguard Worker if (parse_skip_space(handle, info) < 0)
166*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
167*2d543d20SAndroid Build Coastguard Worker
168*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
169*2d543d20SAndroid Build Coastguard Worker }
170*2d543d20SAndroid Build Coastguard Worker
parse_assert_ch(semanage_handle_t * handle,parse_info_t * info,const char ch)171*2d543d20SAndroid Build Coastguard Worker int parse_assert_ch(semanage_handle_t * handle,
172*2d543d20SAndroid Build Coastguard Worker parse_info_t * info, const char ch)
173*2d543d20SAndroid Build Coastguard Worker {
174*2d543d20SAndroid Build Coastguard Worker
175*2d543d20SAndroid Build Coastguard Worker if (parse_assert_noeof(handle, info) < 0)
176*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
177*2d543d20SAndroid Build Coastguard Worker
178*2d543d20SAndroid Build Coastguard Worker if (*(info->ptr) != ch) {
179*2d543d20SAndroid Build Coastguard Worker ERR(handle, "expected character \'%c\', but found \'%c\' "
180*2d543d20SAndroid Build Coastguard Worker "(%s: %u):\n%s", ch, *(info->ptr), info->filename,
181*2d543d20SAndroid Build Coastguard Worker info->lineno, info->orig_line);
182*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
183*2d543d20SAndroid Build Coastguard Worker }
184*2d543d20SAndroid Build Coastguard Worker
185*2d543d20SAndroid Build Coastguard Worker info->ptr++;
186*2d543d20SAndroid Build Coastguard Worker
187*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker
parse_assert_str(semanage_handle_t * handle,parse_info_t * info,const char * assert_str)190*2d543d20SAndroid Build Coastguard Worker int parse_assert_str(semanage_handle_t * handle,
191*2d543d20SAndroid Build Coastguard Worker parse_info_t * info, const char *assert_str)
192*2d543d20SAndroid Build Coastguard Worker {
193*2d543d20SAndroid Build Coastguard Worker
194*2d543d20SAndroid Build Coastguard Worker size_t len = strlen(assert_str);
195*2d543d20SAndroid Build Coastguard Worker
196*2d543d20SAndroid Build Coastguard Worker if (parse_assert_noeof(handle, info) < 0)
197*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
198*2d543d20SAndroid Build Coastguard Worker
199*2d543d20SAndroid Build Coastguard Worker if (strncmp(info->ptr, assert_str, len)) {
200*2d543d20SAndroid Build Coastguard Worker ERR(handle, "experted string \"%s\", but found \"%s\" "
201*2d543d20SAndroid Build Coastguard Worker "(%s: %u):\n%s", assert_str, info->ptr,
202*2d543d20SAndroid Build Coastguard Worker info->filename, info->lineno, info->orig_line);
203*2d543d20SAndroid Build Coastguard Worker
204*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
205*2d543d20SAndroid Build Coastguard Worker }
206*2d543d20SAndroid Build Coastguard Worker
207*2d543d20SAndroid Build Coastguard Worker info->ptr += len;
208*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
209*2d543d20SAndroid Build Coastguard Worker }
210*2d543d20SAndroid Build Coastguard Worker
parse_optional_ch(parse_info_t * info,const char ch)211*2d543d20SAndroid Build Coastguard Worker int parse_optional_ch(parse_info_t * info, const char ch)
212*2d543d20SAndroid Build Coastguard Worker {
213*2d543d20SAndroid Build Coastguard Worker
214*2d543d20SAndroid Build Coastguard Worker if (!info->ptr)
215*2d543d20SAndroid Build Coastguard Worker return STATUS_NODATA;
216*2d543d20SAndroid Build Coastguard Worker if (*(info->ptr) != ch)
217*2d543d20SAndroid Build Coastguard Worker return STATUS_NODATA;
218*2d543d20SAndroid Build Coastguard Worker
219*2d543d20SAndroid Build Coastguard Worker info->ptr++;
220*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
221*2d543d20SAndroid Build Coastguard Worker }
222*2d543d20SAndroid Build Coastguard Worker
parse_optional_str(parse_info_t * info,const char * str)223*2d543d20SAndroid Build Coastguard Worker int parse_optional_str(parse_info_t * info, const char *str)
224*2d543d20SAndroid Build Coastguard Worker {
225*2d543d20SAndroid Build Coastguard Worker size_t len = strlen(str);
226*2d543d20SAndroid Build Coastguard Worker
227*2d543d20SAndroid Build Coastguard Worker if (strncmp(info->ptr, str, len))
228*2d543d20SAndroid Build Coastguard Worker return STATUS_NODATA;
229*2d543d20SAndroid Build Coastguard Worker
230*2d543d20SAndroid Build Coastguard Worker info->ptr += len;
231*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
232*2d543d20SAndroid Build Coastguard Worker }
233*2d543d20SAndroid Build Coastguard Worker
parse_fetch_int(semanage_handle_t * handle,parse_info_t * info,int * num,char delim)234*2d543d20SAndroid Build Coastguard Worker int parse_fetch_int(semanage_handle_t * handle,
235*2d543d20SAndroid Build Coastguard Worker parse_info_t * info, int *num, char delim)
236*2d543d20SAndroid Build Coastguard Worker {
237*2d543d20SAndroid Build Coastguard Worker
238*2d543d20SAndroid Build Coastguard Worker char *str = NULL;
239*2d543d20SAndroid Build Coastguard Worker char *test = NULL;
240*2d543d20SAndroid Build Coastguard Worker int value = 0;
241*2d543d20SAndroid Build Coastguard Worker
242*2d543d20SAndroid Build Coastguard Worker if (parse_fetch_string(handle, info, &str, delim, 0) < 0)
243*2d543d20SAndroid Build Coastguard Worker goto err;
244*2d543d20SAndroid Build Coastguard Worker
245*2d543d20SAndroid Build Coastguard Worker if (!isdigit((int)*str)) {
246*2d543d20SAndroid Build Coastguard Worker ERR(handle, "expected a numeric value: (%s: %u)\n%s",
247*2d543d20SAndroid Build Coastguard Worker info->filename, info->lineno, info->orig_line);
248*2d543d20SAndroid Build Coastguard Worker goto err;
249*2d543d20SAndroid Build Coastguard Worker }
250*2d543d20SAndroid Build Coastguard Worker
251*2d543d20SAndroid Build Coastguard Worker value = strtol(str, &test, 10);
252*2d543d20SAndroid Build Coastguard Worker if (*test != '\0') {
253*2d543d20SAndroid Build Coastguard Worker ERR(handle, "could not parse numeric value \"%s\": "
254*2d543d20SAndroid Build Coastguard Worker "(%s: %u)\n%s", str, info->filename,
255*2d543d20SAndroid Build Coastguard Worker info->lineno, info->orig_line);
256*2d543d20SAndroid Build Coastguard Worker goto err;
257*2d543d20SAndroid Build Coastguard Worker }
258*2d543d20SAndroid Build Coastguard Worker
259*2d543d20SAndroid Build Coastguard Worker *num = value;
260*2d543d20SAndroid Build Coastguard Worker free(str);
261*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
262*2d543d20SAndroid Build Coastguard Worker
263*2d543d20SAndroid Build Coastguard Worker err:
264*2d543d20SAndroid Build Coastguard Worker ERR(handle, "could not fetch numeric value");
265*2d543d20SAndroid Build Coastguard Worker free(str);
266*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
267*2d543d20SAndroid Build Coastguard Worker }
268*2d543d20SAndroid Build Coastguard Worker
parse_fetch_string(semanage_handle_t * handle,parse_info_t * info,char ** str,char delim,int allow_spaces)269*2d543d20SAndroid Build Coastguard Worker int parse_fetch_string(semanage_handle_t * handle,
270*2d543d20SAndroid Build Coastguard Worker parse_info_t * info, char **str, char delim, int allow_spaces)
271*2d543d20SAndroid Build Coastguard Worker {
272*2d543d20SAndroid Build Coastguard Worker
273*2d543d20SAndroid Build Coastguard Worker char *start = info->ptr;
274*2d543d20SAndroid Build Coastguard Worker int len = 0;
275*2d543d20SAndroid Build Coastguard Worker char *tmp_str = NULL;
276*2d543d20SAndroid Build Coastguard Worker
277*2d543d20SAndroid Build Coastguard Worker if (parse_assert_noeof(handle, info) < 0)
278*2d543d20SAndroid Build Coastguard Worker goto err;
279*2d543d20SAndroid Build Coastguard Worker
280*2d543d20SAndroid Build Coastguard Worker while (*(info->ptr) && (allow_spaces || !isspace(*(info->ptr))) &&
281*2d543d20SAndroid Build Coastguard Worker (*(info->ptr) != delim)) {
282*2d543d20SAndroid Build Coastguard Worker info->ptr++;
283*2d543d20SAndroid Build Coastguard Worker len++;
284*2d543d20SAndroid Build Coastguard Worker }
285*2d543d20SAndroid Build Coastguard Worker
286*2d543d20SAndroid Build Coastguard Worker if (len == 0) {
287*2d543d20SAndroid Build Coastguard Worker ERR(handle, "expected non-empty string, but did not "
288*2d543d20SAndroid Build Coastguard Worker "find one (%s: %u):\n%s", info->filename, info->lineno,
289*2d543d20SAndroid Build Coastguard Worker info->orig_line);
290*2d543d20SAndroid Build Coastguard Worker goto err;
291*2d543d20SAndroid Build Coastguard Worker }
292*2d543d20SAndroid Build Coastguard Worker
293*2d543d20SAndroid Build Coastguard Worker tmp_str = (char *)malloc(len + 1);
294*2d543d20SAndroid Build Coastguard Worker if (!tmp_str) {
295*2d543d20SAndroid Build Coastguard Worker ERR(handle, "out of memory");
296*2d543d20SAndroid Build Coastguard Worker goto err;
297*2d543d20SAndroid Build Coastguard Worker }
298*2d543d20SAndroid Build Coastguard Worker
299*2d543d20SAndroid Build Coastguard Worker strncpy(tmp_str, start, len);
300*2d543d20SAndroid Build Coastguard Worker *(tmp_str + len) = '\0';
301*2d543d20SAndroid Build Coastguard Worker *str = tmp_str;
302*2d543d20SAndroid Build Coastguard Worker return STATUS_SUCCESS;
303*2d543d20SAndroid Build Coastguard Worker
304*2d543d20SAndroid Build Coastguard Worker err:
305*2d543d20SAndroid Build Coastguard Worker ERR(handle, "could not fetch string value");
306*2d543d20SAndroid Build Coastguard Worker return STATUS_ERR;
307*2d543d20SAndroid Build Coastguard Worker }
308