• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <netinet/in.h>
2 #ifndef IPPROTO_DCCP
3 #define IPPROTO_DCCP 33
4 #endif
5 #include <stdlib.h>
6 
7 #include "debug.h"
8 #include "context.h"
9 #include "handle.h"
10 
11 #include <sepol/policydb/policydb.h>
12 #include "port_internal.h"
13 
sepol2ipproto(sepol_handle_t * handle,int proto)14 static inline int sepol2ipproto(sepol_handle_t * handle, int proto)
15 {
16 
17 	switch (proto) {
18 	case SEPOL_PROTO_TCP:
19 		return IPPROTO_TCP;
20 	case SEPOL_PROTO_UDP:
21 		return IPPROTO_UDP;
22 	case SEPOL_PROTO_DCCP:
23 		return IPPROTO_DCCP;
24 	default:
25 		ERR(handle, "unsupported protocol %u", proto);
26 		return STATUS_ERR;
27 	}
28 }
29 
ipproto2sepol(sepol_handle_t * handle,int proto)30 static inline int ipproto2sepol(sepol_handle_t * handle, int proto)
31 {
32 
33 	switch (proto) {
34 	case IPPROTO_TCP:
35 		return SEPOL_PROTO_TCP;
36 	case IPPROTO_UDP:
37 		return SEPOL_PROTO_UDP;
38 	case IPPROTO_DCCP:
39 		return SEPOL_PROTO_DCCP;
40 	default:
41 		ERR(handle, "invalid protocol %u " "found in policy", proto);
42 		return STATUS_ERR;
43 	}
44 }
45 
46 /* Create a low level port structure from
47  * a high level representation */
port_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** port,const sepol_port_t * data)48 static int port_from_record(sepol_handle_t * handle,
49 			    const policydb_t * policydb,
50 			    ocontext_t ** port, const sepol_port_t * data)
51 {
52 
53 	ocontext_t *tmp_port = NULL;
54 	context_struct_t *tmp_con = NULL;
55 	int tmp_proto;
56 
57 	int low = sepol_port_get_low(data);
58 	int high = sepol_port_get_high(data);
59 	int proto = sepol_port_get_proto(data);
60 
61 	tmp_port = (ocontext_t *) calloc(1, sizeof(ocontext_t));
62 	if (!tmp_port)
63 		goto omem;
64 
65 	/* Process protocol */
66 	tmp_proto = sepol2ipproto(handle, proto);
67 	if (tmp_proto < 0)
68 		goto err;
69 	tmp_port->u.port.protocol = tmp_proto;
70 
71 	/* Port range */
72 	tmp_port->u.port.low_port = low;
73 	tmp_port->u.port.high_port = high;
74 	if (tmp_port->u.port.low_port > tmp_port->u.port.high_port) {
75 		ERR(handle, "low port %d exceeds high port %d",
76 		    tmp_port->u.port.low_port, tmp_port->u.port.high_port);
77 		goto err;
78 	}
79 
80 	/* Context */
81 	if (context_from_record(handle, policydb, &tmp_con,
82 				sepol_port_get_con(data)) < 0)
83 		goto err;
84 	context_cpy(&tmp_port->context[0], tmp_con);
85 	context_destroy(tmp_con);
86 	free(tmp_con);
87 	tmp_con = NULL;
88 
89 	*port = tmp_port;
90 	return STATUS_SUCCESS;
91 
92       omem:
93 	ERR(handle, "out of memory");
94 
95       err:
96 	if (tmp_port != NULL) {
97 		context_destroy(&tmp_port->context[0]);
98 		free(tmp_port);
99 	}
100 	context_destroy(tmp_con);
101 	free(tmp_con);
102 	ERR(handle, "could not create port structure for range %u:%u (%s)",
103 	    low, high, sepol_port_get_proto_str(proto));
104 	return STATUS_ERR;
105 }
106 
port_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * port,sepol_port_t ** record)107 static int port_to_record(sepol_handle_t * handle,
108 			  const policydb_t * policydb,
109 			  ocontext_t * port, sepol_port_t ** record)
110 {
111 
112 	int proto = port->u.port.protocol;
113 	int low = port->u.port.low_port;
114 	int high = port->u.port.high_port;
115 	context_struct_t *con = &port->context[0];
116 	int rec_proto = -1;
117 
118 	sepol_context_t *tmp_con = NULL;
119 	sepol_port_t *tmp_record = NULL;
120 
121 	if (sepol_port_create(handle, &tmp_record) < 0)
122 		goto err;
123 
124 	rec_proto = ipproto2sepol(handle, proto);
125 	if (rec_proto < 0)
126 		goto err;
127 
128 	sepol_port_set_proto(tmp_record, rec_proto);
129 	sepol_port_set_range(tmp_record, low, high);
130 
131 	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
132 		goto err;
133 
134 	if (sepol_port_set_con(handle, tmp_record, tmp_con) < 0)
135 		goto err;
136 
137 	sepol_context_free(tmp_con);
138 	*record = tmp_record;
139 	return STATUS_SUCCESS;
140 
141       err:
142 	ERR(handle, "could not convert port range %u - %u (%s) "
143 	    "to record", low, high, sepol_port_get_proto_str(rec_proto));
144 	sepol_context_free(tmp_con);
145 	sepol_port_free(tmp_record);
146 	return STATUS_ERR;
147 }
148 
149 /* Return the number of ports */
sepol_port_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)150 extern int sepol_port_count(sepol_handle_t * handle __attribute__ ((unused)),
151 			    const sepol_policydb_t * p, unsigned int *response)
152 {
153 
154 	unsigned int count = 0;
155 	ocontext_t *c, *head;
156 	const policydb_t *policydb = &p->p;
157 
158 	head = policydb->ocontexts[OCON_PORT];
159 	for (c = head; c != NULL; c = c->next)
160 		count++;
161 
162 	*response = count;
163 
164 	return STATUS_SUCCESS;
165 }
166 
167 /* Check if a port exists */
sepol_port_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_port_key_t * key,int * response)168 int sepol_port_exists(sepol_handle_t * handle,
169 		      const sepol_policydb_t * p,
170 		      const sepol_port_key_t * key, int *response)
171 {
172 
173 	const policydb_t *policydb = &p->p;
174 	ocontext_t *c, *head;
175 
176 	int low, high, proto;
177 	const char *proto_str;
178 	sepol_port_key_unpack(key, &low, &high, &proto);
179 	proto_str = sepol_port_get_proto_str(proto);
180 	proto = sepol2ipproto(handle, proto);
181 	if (proto < 0)
182 		goto err;
183 
184 	head = policydb->ocontexts[OCON_PORT];
185 	for (c = head; c; c = c->next) {
186 		int proto2 = c->u.port.protocol;
187 		int low2 = c->u.port.low_port;
188 		int high2 = c->u.port.high_port;
189 
190 		if (proto == proto2 && low2 == low && high2 == high) {
191 			*response = 1;
192 			return STATUS_SUCCESS;
193 		}
194 	}
195 
196 	*response = 0;
197 	return STATUS_SUCCESS;
198 
199       err:
200 	ERR(handle, "could not check if port range %u - %u (%s) exists",
201 	    low, high, proto_str);
202 	return STATUS_ERR;
203 }
204 
205 /* Query a port */
sepol_port_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_port_key_t * key,sepol_port_t ** response)206 int sepol_port_query(sepol_handle_t * handle,
207 		     const sepol_policydb_t * p,
208 		     const sepol_port_key_t * key, sepol_port_t ** response)
209 {
210 
211 	const policydb_t *policydb = &p->p;
212 	ocontext_t *c, *head;
213 
214 	int low, high, proto;
215 	const char *proto_str;
216 	sepol_port_key_unpack(key, &low, &high, &proto);
217 	proto_str = sepol_port_get_proto_str(proto);
218 	proto = sepol2ipproto(handle, proto);
219 	if (proto < 0)
220 		goto err;
221 
222 	head = policydb->ocontexts[OCON_PORT];
223 	for (c = head; c; c = c->next) {
224 		int proto2 = c->u.port.protocol;
225 		int low2 = c->u.port.low_port;
226 		int high2 = c->u.port.high_port;
227 
228 		if (proto == proto2 && low2 == low && high2 == high) {
229 			if (port_to_record(handle, policydb, c, response) < 0)
230 				goto err;
231 			return STATUS_SUCCESS;
232 		}
233 	}
234 
235 	*response = NULL;
236 	return STATUS_SUCCESS;
237 
238       err:
239 	ERR(handle, "could not query port range %u - %u (%s)",
240 	    low, high, proto_str);
241 	return STATUS_ERR;
242 
243 }
244 
245 /* Load a port into policy */
sepol_port_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_port_key_t * key,const sepol_port_t * data)246 int sepol_port_modify(sepol_handle_t * handle,
247 		      sepol_policydb_t * p,
248 		      const sepol_port_key_t * key, const sepol_port_t * data)
249 {
250 
251 	policydb_t *policydb = &p->p;
252 	ocontext_t *port = NULL;
253 
254 	int low, high, proto;
255 	const char *proto_str;
256 
257 	sepol_port_key_unpack(key, &low, &high, &proto);
258 	proto_str = sepol_port_get_proto_str(proto);
259 	proto = sepol2ipproto(handle, proto);
260 	if (proto < 0)
261 		goto err;
262 
263 	if (port_from_record(handle, policydb, &port, data) < 0)
264 		goto err;
265 
266 	/* Attach to context list */
267 	port->next = policydb->ocontexts[OCON_PORT];
268 	policydb->ocontexts[OCON_PORT] = port;
269 
270 	return STATUS_SUCCESS;
271 
272       err:
273 	ERR(handle, "could not load port range %u - %u (%s)",
274 	    low, high, proto_str);
275 	if (port != NULL) {
276 		context_destroy(&port->context[0]);
277 		free(port);
278 	}
279 	return STATUS_ERR;
280 }
281 
sepol_port_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_port_t * port,void * fn_arg),void * arg)282 int sepol_port_iterate(sepol_handle_t * handle,
283 		       const sepol_policydb_t * p,
284 		       int (*fn) (const sepol_port_t * port,
285 				  void *fn_arg), void *arg)
286 {
287 
288 	const policydb_t *policydb = &p->p;
289 	ocontext_t *c, *head;
290 	sepol_port_t *port = NULL;
291 
292 	head = policydb->ocontexts[OCON_PORT];
293 	for (c = head; c; c = c->next) {
294 		int status;
295 
296 		if (port_to_record(handle, policydb, c, &port) < 0)
297 			goto err;
298 
299 		/* Invoke handler */
300 		status = fn(port, arg);
301 		if (status < 0)
302 			goto err;
303 
304 		sepol_port_free(port);
305 		port = NULL;
306 
307 		/* Handler requested exit */
308 		if (status > 0)
309 			break;
310 	}
311 
312 	return STATUS_SUCCESS;
313 
314       err:
315 	ERR(handle, "could not iterate over ports");
316 	sepol_port_free(port);
317 	return STATUS_ERR;
318 }
319