1 /*
2  * Copyright (C) 2015 Red Hat, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <config.h>
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <common-config.h>
24 #include <c-strcase.h>
25 #include <c-ctype.h>
26 #include <talloc.h>
27 
28 #include <vpn.h>
29 
append_port(void * pool,FwPortSt *** fw_ports,size_t * n_fw_ports,int port,fw_proto_t proto,unsigned negate)30 static int append_port(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, int port, fw_proto_t proto, unsigned negate)
31 {
32 	FwPortSt *current;
33 
34 	*fw_ports = talloc_realloc(pool, *fw_ports, FwPortSt*, (*n_fw_ports)+1);
35 	if (*fw_ports == NULL)
36 		return -1;
37 
38 	current = talloc(pool, FwPortSt);
39 	if (current == NULL) {
40 		talloc_free(*fw_ports);
41 		*fw_ports = NULL;
42 		return -1;
43 	}
44 	fw_port_st__init(current);
45 
46 	current->port = port;
47 	current->proto = proto;
48 	current->negate = negate;
49 
50 	(*fw_ports)[*n_fw_ports] = current;
51 	(*n_fw_ports)++;
52 
53 	return 0;
54 }
55 
56 /* Parse strings of the format tcp(443), udp(111), and fill in
57  * allowed_tcp_ports and allowed_udp_ports.
58  */
cfg_parse_ports(void * pool,FwPortSt *** fw_ports,size_t * n_fw_ports,const char * str)59 int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const char *str)
60 {
61 	const char *p, *p2;
62 	unsigned finish = 0;
63 	int port, ret;
64 	fw_proto_t proto;
65 	int negate = 0, bracket_start = 0;
66 
67 	if (str == NULL)
68 		return 0;
69 
70 	p = str;
71 
72 	while (c_isspace(*p))
73 		p++;
74 
75 	if (*p == '!') {
76 		negate = 1;
77 		p++;
78 		while (c_isspace(*p) || (*p == '(')) {
79 			if (*p == '(')
80 				bracket_start = 1;
81 			p++;
82 		}
83 
84 		if (bracket_start == 0) {
85 			syslog(LOG_ERR, "no bracket following negation at %d '%s'", (int)(ptrdiff_t)(p-str), str);
86 			return -1;
87 		}
88 	}
89 
90 	do {
91 
92 		while (c_isspace(*p))
93 			p++;
94 
95 		if (strncasecmp(p, "tcp", 3) == 0) {
96 			proto = PROTO_TCP;
97 			p += 3;
98 		} else if (strncasecmp(p, "udp", 3) == 0) {
99 			proto = PROTO_UDP;
100 			p += 3;
101 		} else if (strncasecmp(p, "sctp", 4) == 0) {
102 			proto = PROTO_SCTP;
103 			p += 4;
104 		} else if (strncasecmp(p, "icmpv6", 6) == 0) {
105 			proto = PROTO_ICMPv6;
106 			p += 6;
107 		} else if (strncasecmp(p, "icmp", 4) == 0) {
108 			proto = PROTO_ICMP;
109 			p += 4;
110 		} else if (strncasecmp(p, "esp", 3) == 0) {
111 			proto = PROTO_ESP;
112 			p += 3;
113 		} else {
114 			syslog(LOG_ERR, "unknown protocol on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p-str), str);
115 			return -1;
116 		}
117 
118 		while (c_isspace(*p))
119 			p++;
120 
121 		if (*p != '(') {
122 			syslog(LOG_ERR, "expected parenthesis on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p-str), str);
123 			return -1;
124 		}
125 
126 		p++;
127 		port = atoi(p);
128 
129 		ret = append_port(pool, fw_ports, n_fw_ports, port, proto, negate);
130 		if (ret < 0) {
131 			syslog(LOG_ERR, "memory error");
132 			return -1;
133 		}
134 
135 		p2 = strchr(p, ')');
136 		if (p2 == NULL) {
137 			syslog(LOG_ERR, "expected closing parenthesis on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p-str), str);
138 			return -1;
139 		}
140 
141 		p2++;
142 		while (c_isspace(*p2))
143 			p2++;
144 
145 		if (*p2 == 0 || (negate != 0 && *p2 == ')')) {
146 			finish = 1;
147 		} else if (*p2 != ',') {
148 			syslog(LOG_ERR, "expected comma or end of line on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p2-str), str);
149 			return -1;
150 		}
151 		p=p2;
152 		p++;
153 	} while(finish == 0);
154 
155 	return 0;
156 }
157