Project

General

Profile

Download (9.81 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	radius_accounting.inc
4
	part of m0n0wall (http://m0n0.ch/wall)
5
	
6
	Copyright (C) 2004 Dinesh Nair <dinesh@alphaque.com>
7
	All rights reserved.
8
	
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11
	
12
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14
	
15
	2. Redistributions in binary form must reproduce the above copyright
16
	   notice, this list of conditions and the following disclaimer in the
17
	   documentation and/or other materials provided with the distribution.
18
	
19
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
	POSSIBILITY OF SUCH DAMAGE.
29

    
30
	// This version of radius_accounting.inc has been modified by
31
	// Rob Parker <rob.parker@keycom.co.uk>. Changes made include:
32
	// * now sends Framed-IP-Address (client IP)
33
	// * now sends Called-Station-ID (NAS IP)
34
	// * now sends Calling-Station-ID (client IP)
35
*/
36

    
37
function RADIUS_ACCOUNTING_START($username,$sessionid,$radiusip,$radiusport,$radiuskey,$clientip) {
38
	global $debug, $nasHostname, $errstr;
39
	$sharedsecret=$radiuskey ;
40
	# $debug = 1 ;
41

    
42
	exec("/bin/hostname", $nasHostname) ;
43
	if(!$nasHostname[0])
44
		$nasHostname[0] = "m0n0wall" ;
45

    
46
	$errno = "";	
47
	$fd = @fsockopen("udp://$radiusip",$radiusport,$errno,$errstr,3) ;
48
	if(!$fd) 
49
		return 1 ; /* error return */
50
	
51
	/* set 5 second timeout on socket i/o */
52
	stream_set_timeout($fd, 5) ;
53

    
54
	$nas_ip_address = get_nas_ip();
55

    
56
	if(!isset($clientip)) {
57
		//if there's no client ip, we'll need to use the NAS ip
58
		$clientip=$nas_ip_address;
59
	}
60
	$ip_exp=explode(".",$clientip);
61

    
62
	if ($debug)
63
	    echo "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\n";
64

    
65
	$thisidentifier=rand()%256;
66

    
67
	$length=4+				// header
68
		16+				// auth code
69
		6+				// service type
70
		2+strlen($username)+		// username
71
		2+strlen($nasHostname[0])+			// nasIdentifier
72
		6+				// nasPort
73
		6+				// nasPortType
74
		6+				// Acct Status Type
75
		6+				// Acct RADIUS Authenticated
76
		2+strlen($sessionid)+	// Acct SessionID
77
		6;				// Framed-IP-Address
78

    
79
	//          v   v   v     v   v   v     v     v     v     1   v
80
	// Line #   1   2   3     4   5   6     7     8     9     0   E
81
	$data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCCCCC",
82
	    4,$thisidentifier,$length/256,$length%256,		// header
83
	    0,0,0,0,						// authcode
84
	    6,6,0,0,0,1,					// service type
85
	    1,2+strlen($username),$username,			// username
86
	    32,2+strlen($nasHostname[0]),$nasHostname[0],	// nasIdentifier
87
	    5,6,0,0,0,0,						// nasPort
88
	    61,6,0,0,0,15,						// nasPortType = Ethernet
89
		40,6,0,0,0,1,						// Acct Status Type = Start
90
		45,6,0,0,0,1,						// Acct RADIUS Authenticated
91
		44,2+strlen($sessionid),$sessionid,	// Acct Session ID
92
		8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3]	//Framed-IP-Address
93
	    );
94

    
95
	/* Generate Accounting Request Authenticator */
96
	$RA = md5($data.$radiuskey) ;
97

    
98
	//          v   v v     v   v   v     v     v     v     1   v
99
	// Line #   1   2 3     4   5   6     7     8     9     0   E
100
	$data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCCCCC",
101
	    4,$thisidentifier,$length/256,$length%256,		// header
102
	    $RA,						// authcode
103
	    6,6,0,0,0,1,					// service type
104
	    1,2+strlen($username),$username,			// username
105
	    32,2+strlen($nasHostname[0]),$nasHostname[0],	// nasIdentifier
106
	    5,6,0,0,0,0,						// nasPort
107
	    61,6,0,0,0,15,						// nasPortType = Ethernet
108
		40,6,0,0,0,1,						// Acct Status Type = Start
109
		45,6,0,0,0,1,						// Acct RADIUS Authenticated
110
		44,2+strlen($sessionid),$sessionid,	// Acct Session ID
111
		8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3]	//Framed-IP-Address
112
	    );
113

    
114
	if($debug) {
115
		echo "username is $username with len " . strlen($username) ."\n" ;
116
		echo "nasHostname is {$nasHostname[0]} with len " . strlen($nasHostname[0]) ."\n" ;
117
	}	
118

    
119
	$ret = fwrite($fd,$data) ;
120
	if( !$ret || ($ret != $length) ) 
121
		return 1; /* error return */
122

    
123
	if ($debug)
124
	    echo "<br>writing $length bytes<hr>\n";
125

    
126
	$readdata = fgets($fd,2) ; /* read 1 byte */
127
	$status = socket_get_status($fd) ;
128
	fclose($fd) ;
129

    
130
	if($status['timed_out'])
131
		$retvalue = 1 ;
132
	else
133
		$retvalue = ord($readdata) ;
134

    
135
	return $retvalue ;
136
	// 5 -> Accounting-Response
137
	// See RFC2866 for this.
138
}
139

    
140
function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$radiusip,$radiusport,$radiuskey,$clientip,$interimupdate=false) {
141
	$sharedsecret=$radiuskey ;
142
	global $debug, $errno, $ipfw, $errstr,$nasHostname;
143
	$matches = "";
144
	# $debug = 1 ;
145
	exec("/bin/hostname", $nasHostname) ;
146
	if(!$nasHostname[0])
147
		$nasHostname[0] = "quewall" ;
148

    
149
	$input_pkts = $input_bytes = $output_pkts = $output_bytes = 0 ;
150

    
151
	exec("/sbin/ipfw show {$ruleno}", $ipfw) ;	
152
	preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+skipto/", $ipfw[0], $matches) ;
153
	$input_pkts = $matches[2] ;
154
	$input_bytes = $matches[3] ;
155

    
156
	unset($matches) ;
157
	preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+skipto/", $ipfw[1], $matches) ;
158
	$output_pkts = $matches[2] ;
159
	$output_bytes = $matches[3] ;
160

    
161
	$fd = @fsockopen("udp://$radiusip",$radiusport,$errno,$errstr,3) ;
162
	if(!$fd) 
163
		return 1 ; /* error return */
164
	
165
	/* set 5 second timeout on socket i/o */
166
	stream_set_timeout($fd, 5) ;
167

    
168
	$nas_ip_address = get_nas_ip();
169

    
170
	if(!isset($clientip)) {
171
		//if there's no client ip, we'll need to use the NAS ip
172
		$clientip=$nas_ip_address;
173
	}
174
	$ip_exp=explode(".",$clientip);
175

    
176
	if ($debug)
177
	    echo "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\n";
178

    
179
	$thisidentifier=rand()%256;
180

    
181
	$length=4+				// header
182
		16+				// auth code
183
		6+				// service type
184
		2+strlen($username)+		// username
185
		2+strlen($nasHostname[0])+			// nasIdentifier
186
		6+				// nasPort
187
		6+				// nasPortType
188
		6+				// Acct Status Type
189
		6+				// Acct RADIUS Authenticated
190
		2+strlen($sessionid)+	// Acct SessionID
191
		6+				// Acct terminate
192
		6+				// Session time
193
		6+				// input bytes
194
		6+				// input packets
195
		6+				// output bytes
196
		6+				// output packets
197
		2+strlen($nas_ip_address)+		//Called-Station-ID
198
		2+strlen($clientip)+	//Calling-Station-ID
199

    
200
		6;			//Framed-IP-Address
201

    
202
	if ($interimupdate)
203
		$acctstatustype = 3;
204
	else
205
		$acctstatustype = 2;
206

    
207
	//          v   v   v     v   v   v     v     v     v     1   1  1  1  1  1  1  v
208
	// Line #   1   2   3     4   5   6     7     8     9     0   1  2  3  4  5  6  E
209
	$data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCNCCa*CCa*CCCCCC",
210
	    4,$thisidentifier,$length/256,$length%256,		// header
211
	    0,0,0,0,						// authcode
212
	    6,6,0,0,0,1,					// service type
213
	    1,2+strlen($username),$username,			// username
214
	    32,2+strlen($nasHostname[0]),$nasHostname[0],	// nasIdentifier
215
	    5,6,0,0,0,0,						// nasPort
216
	    61,6,0,0,0,15,						// nasPortType = Ethernet
217
		40,6,0,0,0,$acctstatustype,			// Acct Status Type
218
		45,6,0,0,0,1,						// Acct RADIUS Authenticated
219
		44,2+strlen($sessionid),$sessionid,	// Acct Session ID
220
		49,6,1,		// Acct Terminate = User Request
221
		46,6,time() - $start_time,			// Session Time
222
		42,6,$input_bytes,	// Input Octets
223
		47,6,$input_pkts,	// Input Packets
224
		43,6,$output_bytes, // Output Octets
225
		48,6,$output_pkts,	// Output Packets
226
		30,2+strlen($nas_ip_address),$nas_ip_address,	//Called-Station-ID
227
		31,2+strlen($clientip),$clientip,				//Calling-Station-ID
228

    
229
		8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3]	//Framed-IP-Address
230
	    );
231

    
232
	/* Generate Accounting Request Authenticator */
233
	$RA = md5($data.$radiuskey) ;
234

    
235
	//          v   v v     v   v   v     v     v     v     1   1  1  1  1  1  1  v
236
	// Line #   1   2 3     4   5   6     7     8     9     0   1  2  3  4  5  6  E
237
	$data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCNCCa*CCa*CCCCCC",
238
	    4,$thisidentifier,$length/256,$length%256,		// header
239
	    $RA,						// authcode
240
	    6,6,0,0,0,1,					// service type
241
	    1,2+strlen($username),$username,			// username
242
	    32,2+strlen($nasHostname[0]),$nasHostname[0],	// nasIdentifier
243
	    5,6,0,0,0,0,						// nasPort
244
	    61,6,0,0,0,15,						// nasPortType = Ethernet
245
		40,6,0,0,0,$acctstatustype,			// Acct Status Type
246
		45,6,0,0,0,1,						// Acct RADIUS Authenticated
247
		44,2+strlen($sessionid),$sessionid,	// Acct Session ID
248
		49,6,1,		// Acct Terminate = User Request
249
		46,6,time() - $start_time,			// Session Time
250
		42,6,$input_bytes,	// Input Octets
251
		47,6,$input_pkts,	// Input Packets
252
		43,6,$output_bytes, // Output Octets
253
		48,6,$output_pkts,	// Output Packets
254
		30,2+strlen($nas_ip_address),$nas_ip_address,	//Called-Station-ID
255
		31,2+strlen($clientip),$clientip,				//Calling-Station-ID
256

    
257
		8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3]	//Framed-IP-Address
258
	    );
259

    
260
	if($debug) {
261
		echo "username is $username with len " . strlen($username) ."\n" ;
262
		echo "nasHostname is {$nasHostname[0]} with len " . strlen($nasHostname[0]) ."\n" ;
263
	}	
264

    
265
	$ret = fwrite($fd,$data) ;
266
	if( !$ret || ($ret != $length) ) 
267
		return 1; /* error return */
268

    
269
	if ($debug)
270
	    echo "<br>writing $length bytes<hr>\n";
271

    
272
	$readdata = fgets($fd,2) ; /* read 1 byte */
273
	$status = socket_get_status($fd) ;
274
	fclose($fd) ;
275

    
276
	if($status['timed_out'])
277
		$retvalue = 1 ;
278
	else
279
		$retvalue = ord($readdata) ;
280

    
281
	return $retvalue ;
282
	// 5 -> Accounting-Response
283
	// See RFC2866 for this.
284
}
285

    
286
function get_nas_ip() {
287
	global $config;
288
	
289
	/* static WAN IP address */
290
	return $config['interfaces']['wan']['ipaddr'];
291
}
292

    
293
?>
(2-2/3)