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