summaryrefslogtreecommitdiffstats
path: root/usr/local/captiveportal/radius_authentication.inc
blob: 10a200983b6b3a5d9721de1104a5f340af8766b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php
    //
    // $Id$
    //
    // radius authentication v1.0 by Edwin Groothuis (edwin@mavetju.org)
    //
    // If you didn't get this file via http://www.mavetju.org, please
    // check for the availability of newer versions.
    //
    // See LICENSE for distribution issues. If this file isn't in
    // the distribution, please inform me about it.
    //
    // If you want to use this script, fill in the configuration in
    // radius_authentication.conf and call the function
    // RADIUS_AUTHENTICATION() with the username and password
    // provided by the user. If it returns a 2, the authentication
    // was successfull!

    // If you want to use this, make sure that you have raw sockets
    // enabled during compile-time: "./configure --enable-sockets".

	// This version has been modified by Dinesh Nair <dinesh@alphaque.com>
	// for use in the m0n0wall distribution http://m0n0.ch/wall/
	//
	// Changes include moving from raw sockets to fsockopen
	// and the removal of dependency on external conf file
	// An existing bug which resulted in a malformed RADIUS packet
	// was also fixed and patches submitted to Edwin. This bug would
	// have caused authentication to fail on every access.

function RADIUS_AUTHENTICATION($username,$password,$port_type,$radiusip,$radiusport,$radiuskey) {
	$sharedsecret=$radiuskey ;
	# $debug = 1 ;

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

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

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

	$RA=pack("CCCCCCCCCCCCCCCC",				// auth code
	    1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
	    1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
	    1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
	    1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255);

	$encryptedpassword=Encrypt($password,$sharedsecret,$RA);

	$length=4+				// header
		16+				// auth code
		6+				// service type
		2+strlen($username)+		// username
		2+strlen($encryptedpassword)+	// userpassword
		2+strlen($nasHostname[0])+			// nasIdentifier
		6+				// nasPort
		6;				// nasPortType

	$thisidentifier=rand()%256;
	//          v   v v     v   v   v   v     v     v
	// Line #   1   2 3     4   5   6   7     8     E
	$data=pack("CCCCa*CCCCCCCCa*CCa*CCa*CCCCCCCCCCCC",
	    1,$thisidentifier,$length/256,$length%256,		// header
	    $RA,						// authcode
	    6,6,0,0,0,1,					// service type
	    1,2+strlen($username),$username,			// username
	    2,2+strlen($encryptedpassword),$encryptedpassword,	// userpassword
	    32,2+strlen($nasHostname[0]),$nasHostname[0],	// nasIdentifier
	    5,6,0,0,0,0,						// nasPort
	    61,6,0,0,0,$port_type				// nasPortType
	    );

	if($debug) {
		echo "username is $username with len " . strlen($username) ."\n" ;
		echo "encryptedpassword is $encryptedpassword with len " . strlen($encryptedpassword) ."\n" ;
		echo "nasHostname is {$nasHostname[0]} with len " . strlen($nasHostname[0]) ."\n" ;
	}	

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

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

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

	if($status['timed_out'])
		$retvalue = 1 ;
	else
		$retvalue = ord($readdata) ;

	return $retvalue ;
	// 2 -> Access-Accept
	// 3 -> Access-Reject
	// See RFC2865 for this.
}

function Encrypt($password,$key,$RA) {
	global $debug;

	$keyRA=$key.$RA;

	if ($debug)
	    echo "<br>key: $key<br>password: $password<hr>\n";

	$md5checksum=md5($keyRA);
	$output="";

	for ($i=0;$i<=15;$i++) {
	    if (2*$i>strlen($md5checksum)) $m=0; else $m=hexdec(substr($md5checksum,2*$i,2));
	    if ($i>strlen($keyRA)) $k=0; else $k=ord(substr($keyRA,$i,1));
	    if ($i>strlen($password)) $p=0; else $p=ord(substr($password,$i,1));
	    $c=$m^$p;
	    $output.=chr($c);
	}
	return $output;
}
?>
OpenPOWER on IntegriCloud