1 /* Copyright (C) 2005 Red Hat, Inc. */
2
3 #include <stdlib.h>
4 #include "policy.h"
5 #include "handle.h"
6 #include "database.h"
7 #include "modules.h"
8 #include "debug.h"
9
10 /* Powers of two only */
11 #define MODE_SET 1
12 #define MODE_MODIFY 2
13 #define MODE_SORT 4
14
clear_obsolete(semanage_handle_t * handle,record_t ** records,unsigned int nrecords,dbase_config_t * src,dbase_config_t * dst)15 static int clear_obsolete(semanage_handle_t * handle,
16 record_t ** records,
17 unsigned int nrecords,
18 dbase_config_t * src, dbase_config_t * dst)
19 {
20
21 record_key_t *key = NULL;
22 unsigned int i;
23
24 dbase_table_t *src_dtable = src->dtable;
25 dbase_table_t *dst_dtable = dst->dtable;
26 record_table_t *rtable = src_dtable->get_rtable(src->dbase);
27
28 for (i = 0; i < nrecords; i++) {
29 int exists;
30
31 if (rtable->key_extract(handle, records[i], &key) < 0)
32 goto err;
33
34 if (dst_dtable->exists(handle, dst->dbase, key, &exists) < 0)
35 goto err;
36
37 if (!exists) {
38 if (src_dtable->del(handle, src->dbase, key) < 0)
39 goto err;
40
41 rtable->free(records[i]);
42 records[i] = NULL;
43
44 /* FIXME: notice to user */
45 /* INFO(handle, "boolean %s is obsolete, unsetting configured value..."); */
46 }
47
48 rtable->key_free(key);
49 }
50
51 return STATUS_SUCCESS;
52
53 err:
54 /* FIXME: handle error */
55 rtable->key_free(key);
56 return STATUS_ERR;
57 }
58
load_records(semanage_handle_t * handle,dbase_config_t * dst,record_t ** records,unsigned int nrecords,int mode)59 static int load_records(semanage_handle_t * handle,
60 dbase_config_t * dst,
61 record_t ** records, unsigned int nrecords, int mode)
62 {
63
64 unsigned int i;
65 record_key_t *rkey = NULL;
66
67 dbase_t *dbase = dst->dbase;
68 dbase_table_t *dtable = dst->dtable;
69 record_table_t *rtable = dtable->get_rtable(dbase);
70
71 for (i = 0; i < nrecords; i++) {
72
73 /* Possibly obsoleted */
74 if (!records[i])
75 continue;
76
77 if (rtable->key_extract(handle, records[i], &rkey) < 0)
78 goto err;
79
80 if (mode & MODE_SET &&
81 dtable->set(handle, dbase, rkey, records[i]) < 0)
82 goto err;
83
84 else if (mode & MODE_MODIFY &&
85 dtable->modify(handle, dbase, rkey, records[i]) < 0)
86 goto err;
87
88 rtable->key_free(rkey);
89 }
90
91 return STATUS_SUCCESS;
92
93 err:
94 /* FIXME: handle error */
95 rtable->key_free(rkey);
96 return STATUS_ERR;
97 }
98
99 typedef struct load_table {
100 dbase_config_t *src;
101 dbase_config_t *dst;
102 int mode;
103 } load_table_t;
104
105 /* This function must be called AFTER all modules are loaded.
106 * Modules could be represented as a database, in which case
107 * they should be loaded at the beginning of this function */
108
semanage_base_merge_components(semanage_handle_t * handle)109 int semanage_base_merge_components(semanage_handle_t * handle)
110 {
111
112 unsigned int i, j;
113 int rc = STATUS_SUCCESS;
114
115 /* Order is important here - change things carefully.
116 * System components first, local next. Verify runs with
117 * mutual dependencies are ran after everything is merged */
118 load_table_t components[] = {
119
120 {semanage_user_base_dbase_local(handle),
121 semanage_user_base_dbase_policy(handle), MODE_MODIFY},
122
123 {semanage_user_extra_dbase_local(handle),
124 semanage_user_extra_dbase_policy(handle), MODE_MODIFY},
125
126 {semanage_port_dbase_local(handle),
127 semanage_port_dbase_policy(handle), MODE_MODIFY},
128
129 {semanage_iface_dbase_local(handle),
130 semanage_iface_dbase_policy(handle), MODE_MODIFY},
131
132 {semanage_bool_dbase_local(handle),
133 semanage_bool_dbase_policy(handle), MODE_SET},
134
135 {semanage_seuser_dbase_local(handle),
136 semanage_seuser_dbase_policy(handle), MODE_MODIFY},
137
138 {semanage_node_dbase_local(handle),
139 semanage_node_dbase_policy(handle), MODE_MODIFY | MODE_SORT},
140
141 {semanage_ibpkey_dbase_local(handle),
142 semanage_ibpkey_dbase_policy(handle), MODE_MODIFY},
143
144 {semanage_ibendport_dbase_local(handle),
145 semanage_ibendport_dbase_policy(handle), MODE_MODIFY},
146 };
147 const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]);
148
149 /* Merge components into policy (and validate) */
150 for (i = 0; i < CCOUNT; i++) {
151 record_t **records = NULL;
152 unsigned int nrecords = 0;
153
154 dbase_config_t *src = components[i].src;
155 dbase_config_t *dst = components[i].dst;
156 int mode = components[i].mode;
157 record_table_t *rtable = src->dtable->get_rtable(src->dbase);
158
159 /* Must invoke cache function first */
160 if (src->dtable->cache(handle, src->dbase) < 0)
161 goto err;
162 if (dst->dtable->cache(handle, dst->dbase) < 0)
163 goto err;
164
165 /* List all records */
166 if (src->dtable->list(handle, src->dbase,
167 &records, &nrecords) < 0)
168 goto err;
169
170 /* Sort records on MODE_SORT */
171 if (mode & MODE_SORT) {
172 qsort(records, nrecords, sizeof(record_t *),
173 (int (*)(const void *, const void *))rtable->
174 compare2_qsort);
175 }
176
177 /* Clear obsolete ones for MODE_SET */
178 if (mode & MODE_SET &&
179 clear_obsolete(handle, records, nrecords, src, dst) < 0) {
180 rc = STATUS_ERR;
181 goto dbase_exit;
182 }
183
184 /* Load records */
185 if (load_records(handle, dst, records, nrecords, mode) < 0) {
186
187 rc = STATUS_ERR;
188 goto dbase_exit;
189 }
190
191 /* Cleanup */
192 dbase_exit:
193 for (j = 0; j < nrecords; j++)
194 rtable->free(records[j]);
195 free(records);
196
197 /* Abort on error */
198 if (rc < 0)
199 goto err;
200 }
201
202 return rc;
203
204 err:
205 ERR(handle, "could not merge local modifications into policy");
206 return STATUS_ERR;
207 }
208
semanage_commit_components(semanage_handle_t * handle)209 int semanage_commit_components(semanage_handle_t * handle)
210 {
211
212 int i;
213 dbase_config_t *components[] = {
214 semanage_iface_dbase_local(handle),
215 semanage_bool_dbase_local(handle),
216 semanage_user_base_dbase_local(handle),
217 semanage_user_extra_dbase_local(handle),
218 semanage_user_extra_dbase_policy(handle),
219 semanage_port_dbase_local(handle),
220 semanage_fcontext_dbase_local(handle),
221 semanage_fcontext_dbase_policy(handle),
222 semanage_seuser_dbase_local(handle),
223 semanage_seuser_dbase_policy(handle),
224 semanage_bool_dbase_active(handle),
225 semanage_node_dbase_local(handle),
226 semanage_ibpkey_dbase_local(handle),
227 semanage_ibendport_dbase_local(handle),
228 };
229 const int CCOUNT = sizeof(components) / sizeof(components[0]);
230
231 for (i = 0; i < CCOUNT; i++) {
232 /* Flush to disk */
233 if (components[i]->dtable->flush(handle, components[i]->dbase) <
234 0)
235 goto err;
236 }
237
238 return STATUS_SUCCESS;
239
240 err:
241 ERR(handle, "could not commit local/active modifications");
242
243 for (i = 0; i < CCOUNT; i++)
244 components[i]->dtable->drop_cache(components[i]->dbase);
245 return STATUS_ERR;
246 }
247