Beispiel #1
0
 /**
  * Returns true if the username and password work and false if they are
  * wrong or don't exist.
  *
  * @param string $username The username
  * @param string $password The password
  * @return bool Authentication success or failure.
  */
 function user_login($username, $password)
 {
     require_once 'Auth/RADIUS.php';
     require_once 'Crypt/CHAP.php';
     // Added by Clive on 7th May for test purposes
     // printf("Username: $username <br/>");
     // printf("Password: $password <br/>");
     // printf("host: $this->config->host <br/>");
     // printf("nasport: $this->config->nasport <br/>");
     // printf("secret: $this->config->secret <br/>");
     // Added by Stanislav Tsymbalov on 12th March 2008 only for test purposes
     //$type = 'PAP';
     //$type = 'CHAP_MD5';
     //$type = 'MSCHAPv1';
     //$type = 'MSCHAPv2';
     $type = $this->config->radiustype;
     if (empty($type)) {
         $type = 'PAP';
     }
     $classname = 'Auth_RADIUS_' . $type;
     $rauth = new $classname($username, $password);
     $rauth->addServer($this->config->host, $this->config->nasport, $this->config->secret);
     $rauth->username = $username;
     switch ($type) {
         case 'CHAP_MD5':
         case 'MSCHAPv1':
             $classname = $type == 'MSCHAPv1' ? 'Crypt_CHAP_MSv1' : 'Crypt_CHAP_MD5';
             $crpt = new $classname();
             $crpt->password = $password;
             $rauth->challenge = $crpt->challenge;
             $rauth->chapid = $crpt->chapid;
             $rauth->response = $crpt->challengeResponse();
             $rauth->flags = 1;
             // If you must use deprecated and weak LAN-Manager-Responses use this:
             // $rauth->lmResponse = $crpt->lmChallengeResponse();
             // $rauth->flags = 0;
             break;
         case 'MSCHAPv2':
             $crpt = new Crypt_CHAP_MSv2();
             $crpt->username = $username;
             $crpt->password = $password;
             $rauth->challenge = $crpt->authChallenge;
             $rauth->peerChallenge = $crpt->peerChallenge;
             $rauth->chapid = $crpt->chapid;
             $rauth->response = $crpt->challengeResponse();
             break;
         default:
             $rauth->password = $password;
             break;
     }
     if (!$rauth->start()) {
         printf("Radius start: %s<br/>\n", $rauth->getError());
         exit;
     }
     $result = $rauth->send();
     if ($rauth->isError($result)) {
         printf("Radius send failed: %s<br/>\n", $result->getMessage());
         exit;
     } else {
         if ($result === true) {
             // printf("Radius Auth succeeded<br/>\n");
             return true;
         } else {
             // printf("Radius Auth rejected<br/>\n");
             return false;
         }
     }
     // get attributes, even if auth failed
     if (!$rauth->getAttributes()) {
         printf("Radius getAttributes: %s<br/>\n", $rauth->getError());
     } else {
         $rauth->dumpAttributes();
     }
     $rauth->close();
 }
Beispiel #2
0
printf("ChallResp : %s\nexpected  : d39bfaf5d6855a948c8c81a85947502c\n", bin2hex($crpt->challengeResponse()));
echo "\n";
echo "MS-CHAPv1 str2unicode\n";
$crpt = new Crypt_CHAP_MSv1();
printf("Passed 123 as Number:%s\n", bin2hex($crpt->str2unicode(123)));
printf("Passed 123 as String:%s\n", bin2hex($crpt->str2unicode('123')));
echo "MS-CHAPv1 TEST\n";
$crpt->password = '******';
$crpt->challenge = pack('H*', '102DB5DF085D3041');
$unipw = $crpt->str2unicode($pass);
printf("Unicode PW: %s\nexpected  : 4d00790050007700\n", bin2hex($unipw));
printf("NT HASH   : %s\nexpected  : fc156af7edcd6c0edde3337d427f4eac\n", bin2hex($crpt->ntPasswordHash()));
printf("NT Resp   : %s\nexpected  : 4e9d3c8f9cfd385d5bf4d3246791956ca4c351ab409a3d61\n", bin2hex($crpt->challengeResponse()));
printf("LM HASH   : %s\nexpected  : 75ba30198e6d1975aad3b435b51404ee\n", bin2hex($crpt->lmPasswordHash()));
printf("LM Resp   : %s\nexpected  : 91881d0152ab0c33c524135ec24a95ee64e23cdc2d33347d\n", bin2hex($crpt->lmChallengeResponse()));
//printf ("Response  : %s\nexpected  : unknown\n", bin2hex($crpt->response()));
echo "\n";
echo "MS-CHAPv2 TEST\n";
$crpt = new Crypt_CHAP_MSv2();
$crpt->username = '******';
$crpt->password = '******';
printf("Username  : %s\nexpected  : 55736572\n", bin2hex($crpt->username));
$crpt->authChallenge = pack('H*', '5b5d7c7d7b3f2f3e3c2c602132262628');
$crpt->peerChallenge = pack('H*', '21402324255E262A28295F2B3A337C7E');
$nthash = $crpt->ntPasswordHash();
printf("NT HASH      : %s\nexpected     : 44ebba8d5312b8d611474411f56989ae\n", bin2hex($nthash));
$nthashhash = $crpt->ntPasswordHashHash($nthash);
printf("NT HASH-HASH : %s\nexpected     : 41c00c584bd2d91c4017a2a12fa59f3f\n", bin2hex($nthashhash));
printf("ChallResp    : %s\nexpected     : 82309ecd8d708b5ea08faa3981cd83544233114a3d85d6df\n", bin2hex($crpt->challengeResponse()));
printf("Challenge    : %s\nexpected     : d02e4386bce91226\n", bin2hex($crpt->challenge));
echo "\n";
Beispiel #3
0
/**
 * Check username and password against RADIUS authentication backend.
 *
 * @param string $username User name to check
 * @param string $password User password to check
 * @return int Authentication success (0 = fail, 1 = success) FIXME bool
 */
function radius_authenticate($username, $password)
{
    global $config, $rad;
    radius_init();
    if ($username && $rad) {
        //print_vars(radius_server_secret($rad));
        radius_create_request($rad, RADIUS_ACCESS_REQUEST);
        radius_put_attr($rad, RADIUS_USER_NAME, $username);
        switch (strtolower($config['auth_radius_method'])) {
            // CHAP-MD5 see RFC1994
            case 'chap':
            case 'chap_md5':
                $chapid = 1;
                // Specify a CHAP identifier
                //$challenge = mt_rand(); // Generate a challenge
                //$cresponse = md5(pack('Ca*', $chapid, $password.$challenge), TRUE);
                new Crypt_CHAP();
                // Pre load class
                $crpt = new Crypt_CHAP_MD5();
                $crpt->password = $password;
                $challenge = $crpt->challenge;
                $resp_md5 = $crpt->challengeResponse();
                $resp = pack('C', $chapid) . $resp_md5;
                radius_put_attr($rad, RADIUS_CHAP_PASSWORD, $resp);
                // Add the Chap-Password attribute
                radius_put_attr($rad, RADIUS_CHAP_CHALLENGE, $challenge);
                // Add the Chap-Challenge attribute.
                break;
                // MS-CHAPv1 see RFC2433
            // MS-CHAPv1 see RFC2433
            case 'mschapv1':
                $chapid = 1;
                // Specify a CHAP identifier
                $flags = 1;
                // 0 = use LM-Response, 1 = use NT-Response (we not use old LM)
                new Crypt_CHAP();
                // Pre load class
                $crpt = new Crypt_CHAP_MSv1();
                $crpt->password = $password;
                $challenge = $crpt->challenge;
                $resp_lm = str_repeat("", 24);
                $resp_nt = $crpt->challengeResponse();
                $resp = pack('CC', $chapid, $flags) . $resp_lm . $resp_nt;
                radius_put_vendor_attr($rad, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
                radius_put_vendor_attr($rad, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $challenge);
                break;
                // MS-CHAPv2 see RFC2759
            // MS-CHAPv2 see RFC2759
            case 'mschapv2':
                $chapid = 1;
                // Specify a CHAP identifier
                $flags = 1;
                // 0 = use LM-Response, 1 = use NT-Response (we not use old LM)
                new Crypt_CHAP();
                // Pre load class
                $crpt = new Crypt_CHAP_MSv2();
                $crpt->username = $username;
                $crpt->password = $password;
                $challenge = $crpt->authChallenge;
                $challenge_p = $crpt->peerChallenge;
                $resp_nt = $crpt->challengeResponse();
                // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
                $resp = pack('CCa16a8a24', $chapid, $flags, $challenge_p, str_repeat("", 8), $resp_nt);
                radius_put_vendor_attr($rad, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
                radius_put_vendor_attr($rad, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $challenge);
                break;
                // PAP (Plaintext)
            // PAP (Plaintext)
            default:
                radius_put_attr($rad, RADIUS_USER_PASSWORD, $password);
        }
        // Puts standard attributes
        $radius_ip = get_ip_version($config['auth_radius_nas_address']) ? $config['auth_radius_nas_address'] : $_SERVER['SERVER_ADDR'];
        if (get_ip_version($radius_ip) == 6) {
            // FIXME, not sure that this work correctly
            radius_put_attr($rad, RADIUS_NAS_IPV6_ADDRESS, $radius_ip);
        } else {
            radius_put_addr($rad, RADIUS_NAS_IP_ADDRESS, $radius_ip);
        }
        $radius_id = empty($config['auth_radius_id']) ? get_localhost() : $config['auth_radius_id'];
        radius_put_attr($rad, RADIUS_NAS_IDENTIFIER, $radius_id);
        //radius_put_attr($rad, RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
        //radius_put_attr($rad, RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
        //radius_put_attr($rad, RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
        radius_put_attr($rad, RADIUS_CALLING_STATION_ID, isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1');
        $response = radius_send_request($rad);
        //print_vars($response);
        switch ($response) {
            case RADIUS_ACCESS_ACCEPT:
                // An Access-Accept response to an Access-Request indicating that the RADIUS server authenticated the user successfully.
                //echo 'Authentication successful';
                return 1;
                break;
            case RADIUS_ACCESS_REJECT:
                // An Access-Reject response to an Access-Request indicating that the RADIUS server could not authenticate the user.
                //echo 'Authentication failed';
                break;
            case RADIUS_ACCESS_CHALLENGE:
                // An Access-Challenge response to an Access-Request indicating that the RADIUS server requires further information
                // in another Access-Request before authenticating the user.
                //echo 'Challenge required';
                break;
            default:
                print_error('A RADIUS error has occurred: ' . radius_strerror($rad));
        }
    }
    //session_logout();
    return 0;
}
 /**
  * Attempts to login a user against the authentication source.
  *
  * If successfull, returns a User object
  *
  * @param string $username A valid identifying token for the source.
  *                         Not necessarily unique.
  * @param string $password Clear text password.
  * @param string $errmsg   Reference of error message
  *
  * @return object The actual User object if login was successfull,
  *                false otherwise.
  */
 public function login($username, $password, &$errmsg = null)
 {
     $db = AbstractDb::getObject();
     User::setCurrentUser(null);
     //This should fix a security hole if using an empty username.  I didn't have time to audit the radius code to see if it really was vulnerable, and code a better fix.
     // Init values
     $retval = false;
     $username = $db->escapeString($username);
     $password = $db->escapeString($password);
     if (Dependency::check("Auth_RADIUS", $errmsg)) {
         /*
          * Supported encryption methods are :
          *
          * CHAP_MD5 :Challenge-Handshake Authentication Protocol with MD5
          * MSCHAPv1 and MSCHAPv2: Microsoft's CHAP implementation
          */
         switch ($this->mRadius_encryption_method) {
             case "PAP":
             case "CHAP_MD5":
             case "MSCHAPv1":
             case "MSCHAPv2":
                 // Instanciate PEAR class
                 $classname = 'Auth_RADIUS_' . $this->mRadius_encryption_method;
                 $radius_server = new $classname($username, $password);
                 $radius_server->addServer($this->mRadius_hostname, $this->mRadius_auth_port, $this->mRadius_secret_key);
                 break;
             default:
                 // Invalid encryption method
                 $errmsg = _("Invalid RADIUS encryption method.");
                 return false;
         }
         // Instructing PEAR RADIUS class auth parameters
         $radius_server->username = $username;
         // Depending on the auth method, generate challenge response
         switch ($this->mRadius_encryption_method) {
             case 'CHAP_MD5':
             case 'MSCHAPv1':
                 $classname = $this->mRadius_encryption_method == 'MSCHAPv1' ? 'Crypt_CHAP_MSv1' : 'Crypt_CHAP_MD5';
                 $crypt_class = new $classname();
                 $crypt_class->password = $password;
                 $radius_server->challenge = $crypt_class->challenge;
                 $radius_server->chapid = $crypt_class->chapid;
                 $radius_server->response = $crypt_class->challengeResponse();
                 $radius_server->flags = 1;
                 break;
             case 'MSCHAPv2':
                 $crypt_class = new Crypt_CHAP_MSv2();
                 $crypt_class->username = $username;
                 $crypt_class->password = $password;
                 $radius_server->challenge = $crypt_class->authChallenge;
                 $radius_server->peerChallenge = $crypt_class->peerChallenge;
                 $radius_server->chapid = $crypt_class->chapid;
                 $radius_server->response = $crypt_class->challengeResponse();
                 break;
             default:
                 $radius_server->password = $password;
                 break;
         }
         if (!$radius_server->start()) {
             $errmsg = _("Could not initiate PEAR RADIUS Auth class : " . $radius_server->getError());
             return false;
         }
         // Send the authentication request to the RADIUS server
         $result = $radius_server->send();
         if (PEAR::isError($result)) {
             $errmsg = _("Failed to send authentication request to the RADIUS server. : " . $result->getMessage());
             return false;
         } else {
             if ($result === true) {
                 // RADIUS authentication succeeded!
                 // Now checking for local copy of this user
                 $user_info = null;
                 $sql = "SELECT user_id, pass FROM users WHERE (username='******') AND account_origin='" . $this->getNetwork()->getId() . "'";
                 $db->execSqlUniqueRes($sql, $user_info, false);
                 if ($user_info != null) {
                     $user = User::getObject($user_info['user_id']);
                     if ($user->isUserValid($errmsg)) {
                         $retval =& $user;
                         User::setCurrentUser($user);
                         $errmsg = _("Login successfull");
                     } else {
                         $retval = false;
                         //Reason for refusal is already in $errmsg
                     }
                 } else {
                     /*
                      * This user has been succcessfully authenticated through
                      * remote RADIUS, but it's not yet in our local database.
                      * Creating the user with a Global Unique ID, empty email
                      * and password.
                      * Local database password hashing is based on an empty
                      * string (we do not store remote passwords).
                      */
                     $user = User::createUser(get_guid(), $username, $this->getNetwork(), "", "");
                     $retval =& $user;
                     // Validate the user right away !
                     $user->setAccountStatus(ACCOUNT_STATUS_ALLOWED);
                     User::setCurrentUser($user);
                     $errmsg = _("Login successfull");
                 }
                 return $retval;
             } else {
                 $errmsg = _("The RADIUS server rejected this username/password combination.");
                 return false;
             }
         }
         $radius_server->close();
     } else {
         return false;
     }
 }
Beispiel #5
0
 public function accessRequestEapMsChapV2($username, $password)
 {
     /*
      * RADIUS EAP MSCHAPv2 Process:
      * > RADIUS ACCESS_REQUEST w/ EAP identity packet
      * < ACCESS_CHALLENGE w/ MSCHAP challenge encapsulated in EAP request
      *   CHAP packet contains auth_challenge value
      *   Calculate encrypted password based on challenge for response
      * > ACCESS_REQUEST w/ MSCHAP challenge response, peer_challenge &
      *   encrypted password encapsulated in an EAP response packet
      * < ACCESS_CHALLENGE w/ MSCHAP success or failure in EAP packet.
      * > ACCESS_REQUEST w/ EAP success packet if challenge was accepted
      *
      */
     $attributes = $this->getAttributesToSend();
     $this->clearDataToSend()->clearError()->setPacketType(self::TYPE_ACCESS_REQUEST);
     $this->attributesToSend = $attributes;
     $eapPacket = EAPPacket::identity($username);
     $this->setUsername($username)->setAttribute(79, $eapPacket)->setIncludeMessageAuthenticator();
     $this->accessRequest();
     if ($this->errorCode) {
         return false;
     } elseif ($this->radiusPacketReceived != self::TYPE_ACCESS_CHALLENGE) {
         $this->errorCode = 102;
         $this->errorMessage = 'Access-Request did not get Access-Challenge response';
         return false;
     }
     $state = $this->getReceivedAttribute(24);
     $eap = $this->getReceivedAttribute(79);
     if ($eap == null) {
         $this->errorCode = 102;
         $this->errorMessage = 'EAP packet missing from MSCHAP v2 access response';
         return false;
     }
     $eap = EAPPacket::fromString($eap);
     if ($eap->type != EAPPacket::TYPE_EAP_MS_AUTH) {
         $this->errorCode = 102;
         $this->errorMessage = 'EAP type is not EAP_MS_AUTH in access response';
         return false;
     }
     $chapPacket = MsChapV2Packet::fromString($eap->data);
     if (!$chapPacket || $chapPacket->opcode != MsChapV2Packet::OPCODE_CHALLENGE) {
         $this->errorCode = 102;
         $this->errorMessage = 'MSCHAP v2 access response packet missing challenge';
         return false;
     }
     $challenge = $chapPacket->challenge;
     $chapId = $chapPacket->msChapId;
     $msChapV2 = new \Crypt_CHAP_MSv2();
     $msChapV2->username = $username;
     $msChapV2->password = $password;
     $msChapV2->chapid = $chapPacket->msChapId;
     $msChapV2->authChallenge = $challenge;
     $response = $msChapV2->challengeResponse();
     $chapPacket->opcode = MsChapV2Packet::OPCODE_RESPONSE;
     $chapPacket->response = $response;
     $chapPacket->name = $username;
     $chapPacket->challenge = $msChapV2->peerChallenge;
     $eapPacket = EAPPacket::mschapv2($chapPacket, $chapId);
     $this->clearDataToSend()->setPacketType(self::TYPE_ACCESS_REQUEST)->setUsername($username)->setAttribute(79, $eapPacket)->setIncludeMessageAuthenticator();
     $resp = $this->accessRequest(null, null, 0, $state);
     if ($this->errorCode) {
         return false;
     }
     $eap = $this->getReceivedAttribute(79);
     if ($eap == null) {
         $this->errorCode = 102;
         $this->errorMessage = 'EAP packet missing from MSCHAP v2 challenge response';
         return false;
     }
     $eap = EAPPacket::fromString($eap);
     if ($eap->type != EAPPacket::TYPE_EAP_MS_AUTH) {
         $this->errorCode = 102;
         $this->errorMessage = 'EAP type is not EAP_MS_AUTH in access response';
         return false;
     }
     $chapPacket = MsChapV2Packet::fromString($eap->data);
     if ($chapPacket->opcode != MsChapV2Packet::OPCODE_SUCCESS) {
         $this->errorCode = 3;
         $err = !empty($chapPacket->response) ? $chapPacket->response : 'General authentication failure';
         if (preg_match('/E=(\\d+)/', $chapPacket->response, $err)) {
             switch ($err[1]) {
                 case '691':
                     $err = 'Authentication failure, username or password incorrect.';
                     break;
                 case '646':
                     $err = 'Authentication failure, restricted logon hours.';
                     break;
                 case '647':
                     $err = 'Account disabled';
                     break;
                 case '648':
                     $err = 'Password expired';
                     break;
                 case '649':
                     $err = 'No dial in permission';
                     break;
             }
         }
         $this->errorMessage = $err;
         return false;
     }
     // got a success response - send success acknowledgement
     $state = $this->getReceivedAttribute(24);
     $chapPacket = new MsChapV2Packet();
     $chapPacket->opcode = MsChapV2Packet::OPCODE_SUCCESS;
     $eapPacket = EAPPacket::mschapv2($chapPacket, $chapId + 1);
     $this->clearDataToSend()->setPacketType(self::TYPE_ACCESS_REQUEST)->setUsername($username)->setAttribute(79, $eapPacket)->setIncludeMessageAuthenticator();
     $resp = $this->accessRequest(null, null, 0, $state);
     if ($resp !== true) {
         return false;
     } else {
         return true;
     }
 }