• Home
  • History
  • Annotate
  • 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