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