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