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