• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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