• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <netinet/in.h>
2 #include <stdlib.h>
3 #include <inttypes.h>
4 
5 #include "debug.h"
6 #include "context.h"
7 #include "handle.h"
8 
9 #include <sepol/ibpkey_record.h>
10 #include <sepol/policydb/policydb.h>
11 #include "ibpkey_internal.h"
12 
13 /* Create a low level ibpkey structure from
14  * a high level representation
15  */
ibpkey_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** ibpkey,const sepol_ibpkey_t * data)16 static int ibpkey_from_record(sepol_handle_t *handle,
17 			      const policydb_t *policydb,
18 			      ocontext_t **ibpkey, const sepol_ibpkey_t *data)
19 {
20 	ocontext_t *tmp_ibpkey = NULL;
21 	context_struct_t *tmp_con = NULL;
22 	char *subnet_prefix_buf = NULL;
23 	int low = sepol_ibpkey_get_low(data);
24 	int high = sepol_ibpkey_get_high(data);
25 
26 	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
27 	if (!tmp_ibpkey)
28 		goto omem;
29 
30 	tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data);
31 
32 	/* Pkey range */
33 	tmp_ibpkey->u.ibpkey.low_pkey = low;
34 	tmp_ibpkey->u.ibpkey.high_pkey = high;
35 	if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) {
36 		ERR(handle, "low ibpkey %d exceeds high ibpkey %d",
37 		    tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey);
38 		goto err;
39 	}
40 
41 	/* Context */
42 	if (context_from_record(handle, policydb, &tmp_con,
43 				sepol_ibpkey_get_con(data)) < 0)
44 		goto err;
45 	context_cpy(&tmp_ibpkey->context[0], tmp_con);
46 	context_destroy(tmp_con);
47 	free(tmp_con);
48 	tmp_con = NULL;
49 
50 	*ibpkey = tmp_ibpkey;
51 	return STATUS_SUCCESS;
52 
53 omem:
54 	ERR(handle, "out of memory");
55 
56 err:
57 	if (tmp_ibpkey) {
58 		context_destroy(&tmp_ibpkey->context[0]);
59 		free(tmp_ibpkey);
60 	}
61 	context_destroy(tmp_con);
62 	free(tmp_con);
63 	free(subnet_prefix_buf);
64 	ERR(handle, "could not create ibpkey structure");
65 	return STATUS_ERR;
66 }
67 
ibpkey_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * ibpkey,sepol_ibpkey_t ** record)68 static int ibpkey_to_record(sepol_handle_t *handle,
69 			    const policydb_t *policydb,
70 			    ocontext_t *ibpkey, sepol_ibpkey_t **record)
71 {
72 	context_struct_t *con = &ibpkey->context[0];
73 	sepol_context_t *tmp_con = NULL;
74 	sepol_ibpkey_t *tmp_record = NULL;
75 
76 	if (sepol_ibpkey_create(handle, &tmp_record) < 0)
77 		goto err;
78 
79 	sepol_ibpkey_set_subnet_prefix_bytes(tmp_record,
80 					     ibpkey->u.ibpkey.subnet_prefix);
81 
82 	sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey,
83 			       ibpkey->u.ibpkey.high_pkey);
84 
85 	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
86 		goto err;
87 
88 	if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0)
89 		goto err;
90 
91 	sepol_context_free(tmp_con);
92 	*record = tmp_record;
93 	return STATUS_SUCCESS;
94 
95 err:
96 	ERR(handle, "could not convert ibpkey to record");
97 	sepol_context_free(tmp_con);
98 	sepol_ibpkey_free(tmp_record);
99 	return STATUS_ERR;
100 }
101 
102 /* Return the number of ibpkeys */
sepol_ibpkey_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)103 extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)),
104 			      const sepol_policydb_t *p, unsigned int *response)
105 {
106 	unsigned int count = 0;
107 	ocontext_t *c, *head;
108 	const policydb_t *policydb = &p->p;
109 
110 	head = policydb->ocontexts[OCON_IBPKEY];
111 	for (c = head; c; c = c->next)
112 		count++;
113 
114 	*response = count;
115 
116 	return STATUS_SUCCESS;
117 }
118 
119 /* Check if a ibpkey exists */
sepol_ibpkey_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_ibpkey_key_t * key,int * response)120 int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)),
121 			const sepol_policydb_t *p,
122 			const sepol_ibpkey_key_t *key, int *response)
123 {
124 	const policydb_t *policydb = &p->p;
125 	ocontext_t *c, *head;
126 	int low, high;
127 	uint64_t subnet_prefix;
128 
129 	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
130 
131 	head = policydb->ocontexts[OCON_IBPKEY];
132 	for (c = head; c; c = c->next) {
133 		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
134 		uint16_t low2 = c->u.ibpkey.low_pkey;
135 		uint16_t high2 = c->u.ibpkey.high_pkey;
136 
137 		if (low2 == low &&
138 		    high2 == high &&
139 		    subnet_prefix == subnet_prefix2) {
140 			*response = 1;
141 			return STATUS_SUCCESS;
142 		}
143 	}
144 
145 	*response = 0;
146 	return STATUS_SUCCESS;
147 }
148 
149 /* Query a ibpkey */
sepol_ibpkey_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_ibpkey_key_t * key,sepol_ibpkey_t ** response)150 int sepol_ibpkey_query(sepol_handle_t *handle,
151 		       const sepol_policydb_t *p,
152 		       const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response)
153 {
154 	const policydb_t *policydb = &p->p;
155 	ocontext_t *c, *head;
156 	int low, high;
157 	uint64_t subnet_prefix;
158 
159 	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
160 
161 	head = policydb->ocontexts[OCON_IBPKEY];
162 	for (c = head; c; c = c->next) {
163 		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
164 		int low2 = c->u.ibpkey.low_pkey;
165 		int high2 = c->u.ibpkey.high_pkey;
166 
167 		if (low2 == low &&
168 		    high2 == high &&
169 		    subnet_prefix == subnet_prefix2) {
170 			if (ibpkey_to_record(handle, policydb, c, response) < 0)
171 				goto err;
172 			return STATUS_SUCCESS;
173 		}
174 	}
175 
176 	*response = NULL;
177 	return STATUS_SUCCESS;
178 
179 err:
180 	ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists",
181 	    subnet_prefix, low, high);
182 	return STATUS_ERR;
183 }
184 
185 /* Load a ibpkey into policy */
sepol_ibpkey_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_ibpkey_key_t * key,const sepol_ibpkey_t * data)186 int sepol_ibpkey_modify(sepol_handle_t *handle,
187 			sepol_policydb_t *p,
188 			const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data)
189 {
190 	policydb_t *policydb = &p->p;
191 	ocontext_t *ibpkey = NULL;
192 	int low, high;
193 	uint64_t subnet_prefix;
194 
195 	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
196 
197 	if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0)
198 		goto err;
199 
200 	/* Attach to context list */
201 	ibpkey->next = policydb->ocontexts[OCON_IBPKEY];
202 	policydb->ocontexts[OCON_IBPKEY] = ibpkey;
203 
204 	return STATUS_SUCCESS;
205 
206 err:
207 	ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists",
208 	    subnet_prefix, low, high);
209 	if (ibpkey) {
210 		context_destroy(&ibpkey->context[0]);
211 		free(ibpkey);
212 	}
213 	return STATUS_ERR;
214 }
215 
sepol_ibpkey_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_ibpkey_t * ibpkey,void * fn_arg),void * arg)216 int sepol_ibpkey_iterate(sepol_handle_t *handle,
217 			 const sepol_policydb_t *p,
218 			 int (*fn)(const sepol_ibpkey_t *ibpkey,
219 				   void *fn_arg), void *arg)
220 {
221 	const policydb_t *policydb = &p->p;
222 	ocontext_t *c, *head;
223 	sepol_ibpkey_t *ibpkey = NULL;
224 
225 	head = policydb->ocontexts[OCON_IBPKEY];
226 	for (c = head; c; c = c->next) {
227 		int status;
228 
229 		if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0)
230 			goto err;
231 
232 		/* Invoke handler */
233 		status = fn(ibpkey, arg);
234 		if (status < 0)
235 			goto err;
236 
237 		sepol_ibpkey_free(ibpkey);
238 		ibpkey = NULL;
239 
240 		/* Handler requested exit */
241 		if (status > 0)
242 			break;
243 	}
244 
245 	return STATUS_SUCCESS;
246 
247 err:
248 	ERR(handle, "could not iterate over ibpkeys");
249 	sepol_ibpkey_free(ibpkey);
250 	return STATUS_ERR;
251 }
252