Project

General

Profile

Download (6.79 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * openvpn.attributes.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2011-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2020 Rubicon Communications, LLC (Netgate)
9
 * All rights reserved.
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 * http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23

    
24
global $username, $dev, $untrusted_port;
25

    
26
if (empty($dev)) {
27
	$dev = "openvpn";
28
}
29

    
30
function cisco_to_cidr($addr) {
31
	if (!is_ipaddr($addr)) {
32
		throw new Exception('Invalid IP Addr');
33
	}
34

    
35
	$mask = decbin(~ip2long($addr));
36
	$mask = substr($mask, -32);
37
	$k = 0;
38
	for ($i = 0; $i <= 32; $i++) {
39
		$k += intval($mask[$i]);
40
	}
41
	return $k;
42
}
43

    
44
function cisco_extract_index($prule) {
45
	$index = explode("#", $prule);
46
	if (is_numeric($index[1])) {
47
		return intval($index[1]);
48
	} else {
49
		syslog(LOG_WARNING, "Error parsing rule {$prule}: Could not extract index");
50
	}
51
	return -1;;
52
}
53

    
54
function parse_cisco_acl_rule($rule, $devname, $dir) {
55
	$rule_orig = $rule;
56
	$rule = explode(" ", $rule);
57
	$tmprule = "";
58
	$index = 0;
59

    
60
	if ($rule[$index] == "permit") {
61
		$tmprule = "pass {$dir} quick on {$devname} ";
62
	} else if ($rule[$index] == "deny") {
63
		$tmprule = "block {$dir} quick on {$devname} ";
64
	} else {
65
		return;
66
	}
67

    
68
	$index++;
69

    
70
	switch ($rule[$index]) {
71
		case "ip":
72
			$tmprule .= "inet ";
73
			break;
74
		case "icmp":
75
		case "tcp":
76
		case "udp":
77
			$tmprule .= "proto {$rule[$index]} ";
78
			break;
79
		default:
80
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid protocol.");
81
			return;
82
	}
83
	$index++;
84

    
85
	/* Source */
86
	if (trim($rule[$index]) == "host") {
87
		$index++;
88
		$tmprule .= "from {$rule[$index]} ";
89
		$index++;
90
	} else if (trim($rule[$index]) == "any") {
91
		$tmprule .= "from any ";
92
		$index++;
93
	} else {
94
		$network = $rule[$index];
95
		$netmask = $rule[++$index];
96

    
97

    
98
		if(!is_ipaddr($network)) {
99
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid source network '$network'.");
100
			return;
101
		}
102

    
103
		try {
104
			$netmask = cisco_to_cidr($netmask);
105
		} catch(Exception $e) {
106
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid source netmask '$netmask'.");
107
			return;
108
		}
109
		$tmprule .= "from {network}/{$netmask}";
110

    
111
		$index++;
112
	}
113

    
114
	/* Source Operator */
115
	if (in_array(trim($rule[$index]), array("lt", "gt", "eq", "neq"))) {
116
		switch(trim($rule[$index])) {
117
			case "lt":
118
				$operator = "<";
119
				break;
120
			case "gt":
121
				$operator = ">";
122
				break;
123
			case "eq":
124
				$operator = "=";
125
				break;
126
			case "neq":
127
				$operator = "!=";
128
				break;
129
		}
130

    
131
		$port = $rule[++$index];
132
		if (is_port($port)) {
133
			$tmprule .= "port {$operator} {$port} ";
134
		} else {
135
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid source port: '$port' not a numeric value between 0 and 65535.");
136
			return;
137
		}
138
		$index++;
139
	} else if (trim($rule[$index]) == "range") {
140
		$port = array($rule[++$index], $rule[++$index]);
141
		if (is_port($port[0]) && is_port($port[1])) {
142
			$port[0]--;
143
			$port[1]++;
144
			$tmprule .= "port {$port[0]} >< {$port[1]} ";
145
		} else {
146
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid source ports: '$port[0]' & '$port[1]' one or both are not a numeric value between 0 and 65535.");
147
			return;
148
		}
149
		$index++;
150
	}
151

    
152
	/* Destination */
153
	if (trim($rule[$index]) == "host") {
154
		$index++;
155
		$tmprule .= "to {$rule[$index]} ";
156
		$index++;
157
	} else if (trim($rule[$index]) == "any") {
158
		$tmprule .= "to any ";
159
		$index++;
160
	} else {
161
		$network = $rule[$index];
162
		$netmask = $rule[++$index];
163

    
164

    
165
		if(!is_ipaddr($network)) {
166
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid destination network '$network'.");
167
			return;
168
		}
169

    
170
		try {
171
			$netmask = cisco_to_cidr($netmask);
172
		} catch(Exception $e) {
173
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid destination netmask '$netmask'.");
174
			return;
175
		}
176
		$tmprule .= "to {network}/{$netmask}";
177

    
178
		$index++;
179
	}
180

    
181
	/* Destination Operator */
182
	if (in_array(trim($rule[$index]), array("lt", "gt", "eq", "neq"))) {
183
		switch(trim($rule[$index])) {
184
			case "lt":
185
				$operator = "<";
186
				break;
187
			case "gt":
188
				$operator = ">";
189
				break;
190
			case "eq":
191
				$operator = "=";
192
				break;
193
			case "neq":
194
				$operator = "!=";
195
				break;
196
		}
197

    
198
		$port = $rule[++$index];
199
		if (is_port($port)) {
200
			$tmprule .= "port {$operator} {$port} ";
201
		} else {
202
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid destination port: '$port' not a numeric value between 0 and 65535.");
203
			return;
204
		}
205
		$index++;
206
	} else if (trim($rule[$index]) == "range") {
207
		$port = array($rule[++$index], $rule[++$index]);
208
		if (is_port($port[0]) && is_port($port[1])) {
209
			$port[0]--;
210
			$port[1]++;
211
			$tmprule .= "port {$port[0]} >< {$port[1]} ";
212
		} else {
213
			syslog(LOG_WARNING, "Error parsing rule {$rule_orig}: Invalid destination ports: '$port[0]' '$port[1]' one or both are not a numeric value between 0 and 65535.");
214
			return;
215
		}
216
		$index++;
217
	}
218

    
219
	return $tmprule;
220
}
221

    
222
function parse_cisco_acl($attribs) {
223
	global $dev, $attributes;
224
	if (!is_array($attribs)) {
225
		return "";
226
	}
227
	$finalrules = "";
228
	if (is_array($attribs['ciscoavpair'])) {
229
		$inrules = array();
230
		$outrules = array();
231
		foreach ($attribs['ciscoavpair'] as $avrules) {
232
			$rule = explode("=", $avrules);
233
			$dir = "";
234
			if (strstr($rule[0], "inacl")) {
235
				$dir = "in";
236
			} else if (strstr($rule[0], "outacl")) {
237
				$dir = "out";
238
			} else if (strstr($rule[0], "dns-servers")) {
239
				$attributes['dns-servers'] = explode(" ", $rule[1]);
240
				continue;
241
			} else if (strstr($rule[0], "route")) {
242
				if (!is_array($attributes['routes'])) {
243
					$attributes['routes'] = array();
244
				}
245
				$attributes['routes'][] = $rule[1];
246
				continue;
247
			}
248
			$rindex = cisco_extract_index($rule[0]);
249
			if ($rindex < 0) {
250
				continue;
251
			}
252

    
253
			$tmprule = parse_cisco_acl_rule($rule[1], $dev, $dir);
254

    
255
			if ($dir == "in") {
256
				$inrules[$rindex] = $tmprule;
257
			} else if ($dir == "out") {
258
				$outrules[$rindex] = $tmprule;
259
			}
260
		}
261

    
262

    
263
		$state = "";
264
		if (!empty($outrules)) {
265
			$state = "no state";
266
		}
267
		ksort($inrules, SORT_NUMERIC);
268
		foreach ($inrules as $inrule) {
269
			$finalrules .= "{$inrule} {$state}\n";
270
		}
271
		if (!empty($outrules)) {
272
			ksort($outrules, SORT_NUMERIC);
273
			foreach ($outrules as $outrule) {
274
				$finalrules .= "{$outrule} {$state}\n";
275
			}
276
		}
277
	}
278
	return $finalrules;
279
}
280

    
281
$rules = parse_cisco_acl($attributes);
282
if (!empty($rules)) {
283
	$filename = "{$g['tmp_path']}/ovpn_{$dev}_{$username}_{$untrusted_port}.rules";
284
	@file_put_contents($filename, $rules);
285
}
286

    
287
?>
(31-31/60)