PageRenderTime 29ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/pear/Auth/RADIUS.php

https://bitbucket.org/ngmares/moodle
PHP | 1001 lines | 420 code | 118 blank | 463 comment | 52 complexity | 0c30ec4e7c3f36b1b9b6193b960fb54f MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. /*
  4. Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without
  7. modification, are permitted provided that the following conditions
  8. are met:
  9. 1. Redistributions of source code must retain the above copyright
  10. notice, this list of conditions and the following disclaimer.
  11. 2. Redistributions in binary form must reproduce the above copyright
  12. notice, this list of conditions and the following disclaimer in the
  13. documentation and/or other materials provided with the distribution.
  14. 3. The names of the authors may not be used to endorse or promote products
  15. derived from this software without specific prior written permission.
  16. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  20. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  21. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  23. OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  25. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. This code cannot simply be copied and put under the GNU Public License or
  27. any other GPL-like (LGPL, GPL2) License.
  28. $Id$
  29. */
  30. require_once 'PEAR.php';
  31. /**
  32. * Client implementation of RADIUS. This are wrapper classes for
  33. * the RADIUS PECL.
  34. * Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866).
  35. *
  36. * @package Auth_RADIUS
  37. * @author Michael Bretterklieber <michael@bretterklieber.com>
  38. * @access public
  39. * @version $Revision$
  40. */
  41. PEAR::loadExtension('radius');
  42. /**
  43. * class Auth_RADIUS
  44. *
  45. * Abstract base class for RADIUS
  46. *
  47. * @package Auth_RADIUS
  48. */
  49. class Auth_RADIUS extends PEAR {
  50. /**
  51. * List of RADIUS servers.
  52. * @var array
  53. * @see addServer(), putServer()
  54. */
  55. var $_servers = array();
  56. /**
  57. * Path to the configuration-file.
  58. * @var string
  59. * @see setConfigFile()
  60. */
  61. var $_configfile = null;
  62. /**
  63. * Resource.
  64. * @var resource
  65. * @see open(), close()
  66. */
  67. var $res = null;
  68. /**
  69. * Username for authentication and accounting requests.
  70. * @var string
  71. */
  72. var $username = null;
  73. /**
  74. * Password for plaintext-authentication (PAP).
  75. * @var string
  76. */
  77. var $password = null;
  78. /**
  79. * List of known attributes.
  80. * @var array
  81. * @see dumpAttributes(), getAttributes()
  82. */
  83. var $attributes = array();
  84. /**
  85. * List of raw attributes.
  86. * @var array
  87. * @see dumpAttributes(), getAttributes()
  88. */
  89. var $rawAttributes = array();
  90. /**
  91. * List of raw vendor specific attributes.
  92. * @var array
  93. * @see dumpAttributes(), getAttributes()
  94. */
  95. var $rawVendorAttributes = array();
  96. /**
  97. * Switch whether we should put standard attributes or not
  98. * @var bool
  99. * @see putStandardAttributes()
  100. */
  101. var $useStandardAttributes = true;
  102. /**
  103. * Constructor
  104. *
  105. * Loads the RADIUS PECL/extension
  106. *
  107. * @return void
  108. */
  109. function Auth_RADIUS()
  110. {
  111. $this->PEAR();
  112. }
  113. /**
  114. * Adds a RADIUS server to the list of servers for requests.
  115. *
  116. * At most 10 servers may be specified. When multiple servers
  117. * are given, they are tried in round-robin fashion until a
  118. * valid response is received
  119. *
  120. * @access public
  121. * @param string $servername Servername or IP-Address
  122. * @param integer $port Portnumber
  123. * @param string $sharedSecret Shared secret
  124. * @param integer $timeout Timeout for each request
  125. * @param integer $maxtries Max. retries for each request
  126. * @return void
  127. */
  128. function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3)
  129. {
  130. $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
  131. }
  132. /**
  133. * Returns an error message, if an error occurred.
  134. *
  135. * @access public
  136. * @return string
  137. */
  138. function getError()
  139. {
  140. return radius_strerror($this->res);
  141. }
  142. /**
  143. * Sets the configuration-file.
  144. *
  145. * @access public
  146. * @param string $file Path to the configuration file
  147. * @return void
  148. */
  149. function setConfigfile($file)
  150. {
  151. $this->_configfile = $file;
  152. }
  153. /**
  154. * Puts an attribute.
  155. *
  156. * @access public
  157. * @param integer $attrib Attribute-number
  158. * @param mixed $port Attribute-value
  159. * @param type $type Attribute-type
  160. * @return bool true on success, false on error
  161. */
  162. function putAttribute($attrib, $value, $type = null)
  163. {
  164. if ($type == null) {
  165. $type = gettype($value);
  166. }
  167. switch ($type) {
  168. case 'integer':
  169. case 'double':
  170. return radius_put_int($this->res, $attrib, $value);
  171. case 'addr':
  172. return radius_put_addr($this->res, $attrib, $value);
  173. case 'string':
  174. default:
  175. return radius_put_attr($this->res, $attrib, $value);
  176. }
  177. }
  178. /**
  179. * Puts a vendor-specific attribute.
  180. *
  181. * @access public
  182. * @param integer $vendor Vendor (MSoft, Cisco, ...)
  183. * @param integer $attrib Attribute-number
  184. * @param mixed $port Attribute-value
  185. * @param type $type Attribute-type
  186. * @return bool true on success, false on error
  187. */
  188. function putVendorAttribute($vendor, $attrib, $value, $type = null)
  189. {
  190. if ($type == null) {
  191. $type = gettype($value);
  192. }
  193. switch ($type) {
  194. case 'integer':
  195. case 'double':
  196. return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
  197. case 'addr':
  198. return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
  199. case 'string':
  200. default:
  201. return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
  202. }
  203. }
  204. /**
  205. * Prints known attributes received from the server.
  206. *
  207. * @access public
  208. */
  209. function dumpAttributes()
  210. {
  211. foreach ($this->attributes as $name => $data) {
  212. echo "$name:$data<br>\n";
  213. }
  214. }
  215. /**
  216. * Overwrite this.
  217. *
  218. * @access public
  219. */
  220. function open()
  221. {
  222. }
  223. /**
  224. * Overwrite this.
  225. *
  226. * @access public
  227. */
  228. function createRequest()
  229. {
  230. }
  231. /**
  232. * Puts standard attributes.
  233. *
  234. * @access public
  235. */
  236. function putStandardAttributes()
  237. {
  238. if (!$this->useStandardAttributes)
  239. return;
  240. if (isset($_SERVER)) {
  241. $var = &$_SERVER;
  242. } else {
  243. $var = &$GLOBALS['HTTP_SERVER_VARS'];
  244. }
  245. $this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost');
  246. $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
  247. $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
  248. $this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
  249. $this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1');
  250. }
  251. /**
  252. * Puts custom attributes.
  253. *
  254. * @access public
  255. */
  256. function putAuthAttributes()
  257. {
  258. if (isset($this->username)) {
  259. $this->putAttribute(RADIUS_USER_NAME, $this->username);
  260. }
  261. }
  262. /**
  263. * Configures the radius library.
  264. *
  265. * @access public
  266. * @param string $servername Servername or IP-Address
  267. * @param integer $port Portnumber
  268. * @param string $sharedSecret Shared secret
  269. * @param integer $timeout Timeout for each request
  270. * @param integer $maxtries Max. retries for each request
  271. * @return bool true on success, false on error
  272. * @see addServer()
  273. */
  274. function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
  275. {
  276. if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
  277. return false;
  278. }
  279. return true;
  280. }
  281. /**
  282. * Configures the radius library via external configurationfile
  283. *
  284. * @access public
  285. * @param string $servername Servername or IP-Address
  286. * @return bool true on success, false on error
  287. */
  288. function putConfigfile($file)
  289. {
  290. if (!radius_config($this->res, $file)) {
  291. return false;
  292. }
  293. return true;
  294. }
  295. /**
  296. * Initiates a RADIUS request.
  297. *
  298. * @access public
  299. * @return bool true on success, false on errors
  300. */
  301. function start()
  302. {
  303. if (!$this->open()) {
  304. return false;
  305. }
  306. foreach ($this->_servers as $s) {
  307. // Servername, port, sharedsecret, timeout, retries
  308. if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
  309. return false;
  310. }
  311. }
  312. if (!empty($this->_configfile)) {
  313. if (!$this->putConfigfile($this->_configfile)) {
  314. return false;
  315. }
  316. }
  317. $this->createRequest();
  318. $this->putStandardAttributes();
  319. $this->putAuthAttributes();
  320. return true;
  321. }
  322. /**
  323. * Sends a prepared RADIUS request and waits for a response
  324. *
  325. * @access public
  326. * @return mixed true on success, false on reject, PEAR_Error on error
  327. */
  328. function send()
  329. {
  330. $req = radius_send_request($this->res);
  331. if (!$req) {
  332. return $this->raiseError('Error sending request: ' . $this->getError());
  333. }
  334. switch($req) {
  335. case RADIUS_ACCESS_ACCEPT:
  336. if (is_subclass_of($this, 'auth_radius_acct')) {
  337. return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
  338. }
  339. return true;
  340. case RADIUS_ACCESS_REJECT:
  341. return false;
  342. case RADIUS_ACCOUNTING_RESPONSE:
  343. if (is_subclass_of($this, 'auth_radius_pap')) {
  344. return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
  345. }
  346. return true;
  347. default:
  348. return $this->raiseError("Unexpected return value: $req");
  349. }
  350. }
  351. /**
  352. * Reads all received attributes after sending the request.
  353. *
  354. * This methods stores known attributes in the property attributes,
  355. * all attributes (including known attibutes) are stored in rawAttributes
  356. * or rawVendorAttributes.
  357. * NOTE: call this function also even if the request was rejected, because the
  358. * Server returns usualy an errormessage
  359. *
  360. * @access public
  361. * @return bool true on success, false on error
  362. */
  363. function getAttributes()
  364. {
  365. while ($attrib = radius_get_attr($this->res)) {
  366. if (!is_array($attrib)) {
  367. return false;
  368. }
  369. $attr = $attrib['attr'];
  370. $data = $attrib['data'];
  371. $this->rawAttributes[$attr] = $data;
  372. switch ($attr) {
  373. case RADIUS_FRAMED_IP_ADDRESS:
  374. $this->attributes['framed_ip'] = radius_cvt_addr($data);
  375. break;
  376. case RADIUS_FRAMED_IP_NETMASK:
  377. $this->attributes['framed_mask'] = radius_cvt_addr($data);
  378. break;
  379. case RADIUS_FRAMED_MTU:
  380. $this->attributes['framed_mtu'] = radius_cvt_int($data);
  381. break;
  382. case RADIUS_FRAMED_COMPRESSION:
  383. $this->attributes['framed_compression'] = radius_cvt_int($data);
  384. break;
  385. case RADIUS_SESSION_TIMEOUT:
  386. $this->attributes['session_timeout'] = radius_cvt_int($data);
  387. break;
  388. case RADIUS_IDLE_TIMEOUT:
  389. $this->attributes['idle_timeout'] = radius_cvt_int($data);
  390. break;
  391. case RADIUS_SERVICE_TYPE:
  392. $this->attributes['service_type'] = radius_cvt_int($data);
  393. break;
  394. case RADIUS_CLASS:
  395. $this->attributes['class'] = radius_cvt_string($data);
  396. break;
  397. case RADIUS_FRAMED_PROTOCOL:
  398. $this->attributes['framed_protocol'] = radius_cvt_int($data);
  399. break;
  400. case RADIUS_FRAMED_ROUTING:
  401. $this->attributes['framed_routing'] = radius_cvt_int($data);
  402. break;
  403. case RADIUS_FILTER_ID:
  404. $this->attributes['filter_id'] = radius_cvt_string($data);
  405. break;
  406. case RADIUS_REPLY_MESSAGE:
  407. $this->attributes['reply_message'] = radius_cvt_string($data);
  408. break;
  409. case RADIUS_VENDOR_SPECIFIC:
  410. $attribv = radius_get_vendor_attr($data);
  411. if (!is_array($attribv)) {
  412. return false;
  413. }
  414. $vendor = $attribv['vendor'];
  415. $attrv = $attribv['attr'];
  416. $datav = $attribv['data'];
  417. $this->rawVendorAttributes[$vendor][$attrv] = $datav;
  418. if ($vendor == RADIUS_VENDOR_MICROSOFT) {
  419. switch ($attrv) {
  420. case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
  421. $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
  422. break;
  423. case RADIUS_MICROSOFT_MS_CHAP_ERROR:
  424. $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
  425. break;
  426. case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
  427. $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
  428. break;
  429. case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
  430. $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
  431. break;
  432. case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
  433. $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
  434. break;
  435. case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
  436. $demangled = radius_demangle($this->res, $datav);
  437. $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
  438. $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
  439. break;
  440. case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
  441. $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
  442. break;
  443. case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
  444. $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
  445. break;
  446. case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
  447. $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
  448. break;
  449. }
  450. }
  451. break;
  452. }
  453. }
  454. return true;
  455. }
  456. /**
  457. * Frees resources.
  458. *
  459. * Calling this method is always a good idea, because all security relevant
  460. * attributes are filled with Nullbytes to leave nothing in the mem.
  461. *
  462. * @access public
  463. */
  464. function close()
  465. {
  466. if ($this->res != null) {
  467. radius_close($this->res);
  468. $this->res = null;
  469. }
  470. $this->username = str_repeat("\0", strlen($this->username));
  471. $this->password = str_repeat("\0", strlen($this->password));
  472. }
  473. }
  474. /**
  475. * class Auth_RADIUS_PAP
  476. *
  477. * Class for authenticating using PAP (Plaintext)
  478. *
  479. * @package Auth_RADIUS
  480. */
  481. class Auth_RADIUS_PAP extends Auth_RADIUS
  482. {
  483. /**
  484. * Constructor
  485. *
  486. * @param string $username Username
  487. * @param string $password Password
  488. * @return void
  489. */
  490. function Auth_RADIUS_PAP($username = null, $password = null)
  491. {
  492. $this->Auth_RADIUS();
  493. $this->username = $username;
  494. $this->password = $password;
  495. }
  496. /**
  497. * Creates a RADIUS resource
  498. *
  499. * Creates a RADIUS resource for authentication. This should be the first
  500. * call before you make any other things with the library.
  501. *
  502. * @return bool true on success, false on error
  503. */
  504. function open()
  505. {
  506. $this->res = radius_auth_open();
  507. if (!$this->res) {
  508. return false;
  509. }
  510. return true;
  511. }
  512. /**
  513. * Creates an authentication request
  514. *
  515. * Creates an authentication request.
  516. * You MUST call this method before you can put any attribute
  517. *
  518. * @return bool true on success, false on error
  519. */
  520. function createRequest()
  521. {
  522. if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
  523. return false;
  524. }
  525. return true;
  526. }
  527. /**
  528. * Put authentication specific attributes
  529. *
  530. * @return void
  531. */
  532. function putAuthAttributes()
  533. {
  534. if (isset($this->username)) {
  535. $this->putAttribute(RADIUS_USER_NAME, $this->username);
  536. }
  537. if (isset($this->password)) {
  538. $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
  539. }
  540. }
  541. }
  542. /**
  543. * class Auth_RADIUS_CHAP_MD5
  544. *
  545. * Class for authenticating using CHAP-MD5 see RFC1994.
  546. * Instead og the plaintext password the challenge and
  547. * the response are needed.
  548. *
  549. * @package Auth_RADIUS
  550. */
  551. class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
  552. {
  553. /**
  554. * 8 Bytes binary challenge
  555. * @var string
  556. */
  557. var $challenge = null;
  558. /**
  559. * 16 Bytes MD5 response binary
  560. * @var string
  561. */
  562. var $response = null;
  563. /**
  564. * Id of the authentication request. Should incremented after every request.
  565. * @var integer
  566. */
  567. var $chapid = 1;
  568. /**
  569. * Constructor
  570. *
  571. * @param string $username Username
  572. * @param string $challenge 8 Bytes Challenge (binary)
  573. * @param integer $chapid Requestnumber
  574. * @return void
  575. */
  576. function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
  577. {
  578. $this->Auth_RADIUS_PAP();
  579. $this->username = $username;
  580. $this->challenge = $challenge;
  581. $this->chapid = $chapid;
  582. }
  583. /**
  584. * Put CHAP-MD5 specific attributes
  585. *
  586. * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge
  587. * and the response. The chapid is inserted in the first byte of the response.
  588. *
  589. * @return void
  590. */
  591. function putAuthAttributes()
  592. {
  593. if (isset($this->username)) {
  594. $this->putAttribute(RADIUS_USER_NAME, $this->username);
  595. }
  596. if (isset($this->response)) {
  597. $response = pack('C', $this->chapid) . $this->response;
  598. $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
  599. }
  600. if (isset($this->challenge)) {
  601. $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
  602. }
  603. }
  604. /**
  605. * Frees resources.
  606. *
  607. * Calling this method is always a good idea, because all security relevant
  608. * attributes are filled with Nullbytes to leave nothing in the mem.
  609. *
  610. * @access public
  611. */
  612. function close()
  613. {
  614. Auth_RADIUS_PAP::close();
  615. $this->challenge = str_repeat("\0", strlen($this->challenge));
  616. $this->response = str_repeat("\0", strlen($this->response));
  617. }
  618. }
  619. /**
  620. * class Auth_RADIUS_MSCHAPv1
  621. *
  622. * Class for authenticating using MS-CHAPv1 see RFC2433
  623. *
  624. * @package Auth_RADIUS
  625. */
  626. class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
  627. {
  628. /**
  629. * LAN-Manager-Response
  630. * @var string
  631. */
  632. var $lmResponse = null;
  633. /**
  634. * Wether using deprecated LM-Responses or not.
  635. * 0 = use LM-Response, 1 = use NT-Response
  636. * @var bool
  637. */
  638. var $flags = 1;
  639. /**
  640. * Put MS-CHAPv1 specific attributes
  641. *
  642. * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
  643. * and the response. The response has this structure:
  644. * struct rad_mschapvalue {
  645. * u_char ident;
  646. * u_char flags;
  647. * u_char lm_response[24];
  648. * u_char response[24];
  649. * };
  650. *
  651. * @return void
  652. */
  653. function putAuthAttributes()
  654. {
  655. if (isset($this->username)) {
  656. $this->putAttribute(RADIUS_USER_NAME, $this->username);
  657. }
  658. if (isset($this->response) || isset($this->lmResponse)) {
  659. $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
  660. $ntResp = isset($this->response) ? $this->response : str_repeat ("\0", 24);
  661. $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
  662. $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
  663. }
  664. if (isset($this->challenge)) {
  665. $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
  666. }
  667. }
  668. }
  669. /**
  670. * class Auth_RADIUS_MSCHAPv2
  671. *
  672. * Class for authenticating using MS-CHAPv2 see RFC2759
  673. *
  674. * @package Auth_RADIUS
  675. */
  676. class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
  677. {
  678. /**
  679. * 16 Bytes binary challenge
  680. * @var string
  681. */
  682. var $challenge = null;
  683. /**
  684. * 16 Bytes binary Peer Challenge
  685. * @var string
  686. */
  687. var $peerChallenge = null;
  688. /**
  689. * Put MS-CHAPv2 specific attributes
  690. *
  691. * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
  692. * and the response. The response has this structure:
  693. * struct rad_mschapv2value {
  694. * u_char ident;
  695. * u_char flags;
  696. * u_char pchallenge[16];
  697. * u_char reserved[8];
  698. * u_char response[24];
  699. * };
  700. * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
  701. * @return void
  702. */
  703. function putAuthAttributes()
  704. {
  705. if (isset($this->username)) {
  706. $this->putAttribute(RADIUS_USER_NAME, $this->username);
  707. }
  708. if (isset($this->response) && isset($this->peerChallenge)) {
  709. // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
  710. $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
  711. $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
  712. }
  713. if (isset($this->challenge)) {
  714. $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
  715. }
  716. }
  717. /**
  718. * Frees resources.
  719. *
  720. * Calling this method is always a good idea, because all security relevant
  721. * attributes are filled with Nullbytes to leave nothing in the mem.
  722. *
  723. * @access public
  724. */
  725. function close()
  726. {
  727. Auth_RADIUS_MSCHAPv1::close();
  728. $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
  729. }
  730. }
  731. /**
  732. * class Auth_RADIUS_Acct
  733. *
  734. * Class for RADIUS accounting
  735. *
  736. * @package Auth_RADIUS
  737. */
  738. class Auth_RADIUS_Acct extends Auth_RADIUS
  739. {
  740. /**
  741. * Defines where the Authentication was made, possible values are:
  742. * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
  743. * @var integer
  744. */
  745. var $authentic = null;
  746. /**
  747. * Defines the type of the accounting request, on of:
  748. * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
  749. * @var integer
  750. */
  751. var $status_type = null;
  752. /**
  753. * The time the user was logged in in seconds
  754. * @var integer
  755. */
  756. var $session_time = null;
  757. /**
  758. * A uniq identifier for the session of the user, maybe the PHP-Session-Id
  759. * @var string
  760. */
  761. var $session_id = null;
  762. /**
  763. * Constructor
  764. *
  765. * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
  766. * @return void
  767. */
  768. function Auth_RADIUS_Acct()
  769. {
  770. $this->Auth_RADIUS();
  771. if (isset($_SERVER)) {
  772. $var = &$_SERVER;
  773. } else {
  774. $var = &$GLOBALS['HTTP_SERVER_VARS'];
  775. }
  776. $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
  777. }
  778. /**
  779. * Creates a RADIUS resource
  780. *
  781. * Creates a RADIUS resource for accounting. This should be the first
  782. * call before you make any other things with the library.
  783. *
  784. * @return bool true on success, false on error
  785. */
  786. function open()
  787. {
  788. $this->res = radius_acct_open();
  789. if (!$this->res) {
  790. return false;
  791. }
  792. return true;
  793. }
  794. /**
  795. * Creates an accounting request
  796. *
  797. * Creates an accounting request.
  798. * You MUST call this method before you can put any attribute.
  799. *
  800. * @return bool true on success, false on error
  801. */
  802. function createRequest()
  803. {
  804. if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
  805. return false;
  806. }
  807. return true;
  808. }
  809. /**
  810. * Put attributes for accounting.
  811. *
  812. * Here we put some accounting values. There many more attributes for accounting,
  813. * but for web-applications only certain attributes make sense.
  814. * @return void
  815. */
  816. function putAuthAttributes()
  817. {
  818. $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id);
  819. $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
  820. if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
  821. $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
  822. }
  823. if (isset($this->authentic)) {
  824. $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
  825. }
  826. }
  827. }
  828. /**
  829. * class Auth_RADIUS_Acct_Start
  830. *
  831. * Class for RADIUS accounting. Its usualy used, after the user has logged in.
  832. *
  833. * @package Auth_RADIUS
  834. */
  835. class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
  836. {
  837. /**
  838. * Defines the type of the accounting request.
  839. * It is set to RADIUS_START by default in this class.
  840. * @var integer
  841. */
  842. var $status_type = RADIUS_START;
  843. }
  844. /**
  845. * class Auth_RADIUS_Acct_Start
  846. *
  847. * Class for RADIUS accounting. Its usualy used, after the user has logged out.
  848. *
  849. * @package Auth_RADIUS
  850. */
  851. class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
  852. {
  853. /**
  854. * Defines the type of the accounting request.
  855. * It is set to RADIUS_STOP by default in this class.
  856. * @var integer
  857. */
  858. var $status_type = RADIUS_STOP;
  859. }
  860. if (!defined('RADIUS_UPDATE'))
  861. define('RADIUS_UPDATE', 3);
  862. /**
  863. * class Auth_RADIUS_Acct_Update
  864. *
  865. * Class for interim RADIUS accounting updates.
  866. *
  867. * @package Auth_RADIUS
  868. */
  869. class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
  870. {
  871. /**
  872. * Defines the type of the accounting request.
  873. * It is set to RADIUS_UPDATE by default in this class.
  874. * @var integer
  875. */
  876. var $status_type = RADIUS_UPDATE;
  877. }
  878. ?>