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