Adding OTP support
This commit is contained in:
parent
5fc1c99ccf
commit
5926f62bd1
@ -172,8 +172,25 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
'initial' => '',
|
'initial' => '',
|
||||||
'help_text' => __('You will get an email to confirm that you own the address you specify.'),
|
'help_text' => __('You will get an email to confirm that you own the address you specify.'),
|
||||||
));
|
));
|
||||||
|
$otp = "";
|
||||||
|
if ($user_data->otpkey != "")
|
||||||
|
$otp = Pluf_Utils::convBase($this->user->otpkey, '0123456789abcdef', 'abcdefghijklmnopqrstuvwxyz234567');
|
||||||
|
$this->fields['otpkey'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Add a OTP Key'),
|
||||||
|
//'initial' => (!empty($user_data->otpkey)) ? : "",
|
||||||
|
//'initial' => (string)(!empty($user_data->otpkey)),
|
||||||
|
'initial' => $otp,
|
||||||
|
'help_text' => __('Key must be in base32 for generated QRcode and import into Google Authenticator.'),
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 32,
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private function send_validation_mail($new_email, $secondary_mail=false)
|
private function send_validation_mail($new_email, $secondary_mail=false)
|
||||||
{
|
{
|
||||||
if ($secondary_mail) {
|
if ($secondary_mail) {
|
||||||
@ -243,6 +260,8 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($commit) {
|
if ($commit) {
|
||||||
|
if ($this->cleaned_data["otpkey"] != "")
|
||||||
|
$this->user->otpkey = Pluf_Utils::convBase($this->cleaned_data["otpkey"], 'abcdefghijklmnopqrstuvwxyz234567', '0123456789abcdef');
|
||||||
$this->user->update();
|
$this->user->update();
|
||||||
|
|
||||||
// FIXME: go the extra mile and check the input lengths for
|
// FIXME: go the extra mile and check the input lengths for
|
||||||
|
@ -231,6 +231,8 @@ class IDF_Plugin_SyncMercurial
|
|||||||
$fcontent .= '<Location '. sprintf(Pluf::f('idf_plugin_syncmercurial_private_url'), $project->shortname).'>'."\n";
|
$fcontent .= '<Location '. sprintf(Pluf::f('idf_plugin_syncmercurial_private_url'), $project->shortname).'>'."\n";
|
||||||
$fcontent .= 'AuthType Basic'."\n";
|
$fcontent .= 'AuthType Basic'."\n";
|
||||||
$fcontent .= 'AuthName "Restricted"'."\n";
|
$fcontent .= 'AuthName "Restricted"'."\n";
|
||||||
|
$fcontent .= 'AuthExternal otpauth\n';
|
||||||
|
$fcontent .= 'AuthBasicProvider external\n';
|
||||||
$fcontent .= sprintf('AuthUserFile %s', Pluf::f('idf_plugin_syncmercurial_passwd_file'))."\n";
|
$fcontent .= sprintf('AuthUserFile %s', Pluf::f('idf_plugin_syncmercurial_passwd_file'))."\n";
|
||||||
$fcontent .= sprintf('Require user %s', $user)."\n";
|
$fcontent .= sprintf('Require user %s', $user)."\n";
|
||||||
$fcontent .= '</Location>'."\n\n";
|
$fcontent .= '</Location>'."\n\n";
|
||||||
|
@ -100,6 +100,16 @@
|
|||||||
<span class="helptext">{$form.f.public_key.help_text}</span>
|
<span class="helptext">{$form.f.public_key.help_text}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.otpkey.labelTag}:</th>
|
||||||
|
<td>{if $form.f.otpkey.errors}{$form.f.otpkey.fieldErrors}{/if}
|
||||||
|
{$form.f.otpkey|unsafe} <a id="id_otpgen" href="#">Generate</a><br />
|
||||||
|
<span class="helptext">{$form.f.otpkey.help_text}</span>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<div id="QRcode"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr><td colspan="2" class="separator">{trans "Secondary Emails"}</td></tr>
|
<tr><td colspan="2" class="separator">{trans "Secondary Emails"}</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{$form.f.secondary_mail.labelTag}:</th>
|
<th>{$form.f.secondary_mail.labelTag}:</th>
|
||||||
@ -153,8 +163,10 @@
|
|||||||
<p>{trans 'The extra password is used to access some of the external systems and the API key is used to interact with this website using a program.'}</p>
|
<p>{trans 'The extra password is used to access some of the external systems and the API key is used to interact with this website using a program.'}</p>
|
||||||
</div>{/block}
|
</div>{/block}
|
||||||
|
|
||||||
{block javascript}<script type="text/javascript">
|
{block javascript}
|
||||||
|
<script type="text/javascript">
|
||||||
document.getElementById('id_first_name').focus();
|
document.getElementById('id_first_name').focus();
|
||||||
|
var user = "{$user.login}";
|
||||||
{literal}
|
{literal}
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Hide the key password by default.
|
// Hide the key password by default.
|
||||||
@ -165,6 +177,32 @@ $(document).ready(function() {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
$(".pass-info").hide();
|
$(".pass-info").hide();
|
||||||
|
$("#id_otpkey").bind('input', function ()
|
||||||
|
{
|
||||||
|
if ($("#id_otpkey").val() != "")
|
||||||
|
{
|
||||||
|
var url = "https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=otpauth%3A%2F%2Ftotp%2F" + user + "?secret=" + $("#id_otpkey").val() + "%26issuer=srchub&choe=UTF-8";
|
||||||
|
$("#QRcode").html('<img src="' + url + '" />');
|
||||||
|
} else {
|
||||||
|
$("#QRcode").html('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#id_otpgen").click(function ()
|
||||||
|
{
|
||||||
|
var chars = "abcdefghijklmnopqrstuvwxyz234567";
|
||||||
|
var key = "";
|
||||||
|
for(var i = 0; i < 32; i++)
|
||||||
|
key += chars[Math.floor(Math.random() * 32)];
|
||||||
|
$("#id_otpkey").val(key);
|
||||||
|
var url = "https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=otpauth%3A%2F%2Ftotp%2F" + user + "?secret=" + $("#id_otpkey").val().toUpperCase() + "%26issuer=srchub&choe=UTF-8";
|
||||||
|
$("#QRcode").html('<img src="' + url + '" />')
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if ($("#id_otpkey").val() != "")
|
||||||
|
{
|
||||||
|
var url = "https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=otpauth%3A%2F%2Ftotp%2F" + user + "?secret=" + $("#id_otpkey").val().toUpperCase() + "%26issuer=srchub&choe=UTF-8";
|
||||||
|
$("#QRcode").html('<img src="' + url + '" />')
|
||||||
|
}
|
||||||
});{/literal}
|
});{/literal}
|
||||||
</script>
|
</script>
|
||||||
{/block}
|
{/block}
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#
|
#
|
||||||
# ***** END LICENSE BLOCK ***** */
|
# ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
require_once dirname(__FILE__).'/thirdparty/otp/otphp.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User Model.
|
* User Model.
|
||||||
*/
|
*/
|
||||||
@ -155,6 +157,14 @@ class Pluf_User extends Pluf_Model
|
|||||||
'verbose' => __('last login'),
|
'verbose' => __('last login'),
|
||||||
'editable' => false,
|
'editable' => false,
|
||||||
),
|
),
|
||||||
|
'otpkey' =>
|
||||||
|
array(
|
||||||
|
'type' => 'Pluf_DB_Field_Varchar',
|
||||||
|
'blank' => true,
|
||||||
|
'size' => 50,
|
||||||
|
'verbose' => __('OTP Key for user'),
|
||||||
|
'help_text' => __('OTP Key used for authentication against repos.')
|
||||||
|
),
|
||||||
);
|
);
|
||||||
$this->_a['idx'] = array(
|
$this->_a['idx'] = array(
|
||||||
'login_idx' =>
|
'login_idx' =>
|
||||||
@ -237,8 +247,6 @@ class Pluf_User extends Pluf_Model
|
|||||||
{
|
{
|
||||||
//$salt = Pluf_Utils::getRandomString(5);
|
//$salt = Pluf_Utils::getRandomString(5);
|
||||||
//$this->password = 'sha1:'.$salt.':'.sha1($salt.$password);
|
//$this->password = 'sha1:'.$salt.':'.sha1($salt.$password);
|
||||||
//$this->password = sha1($password);
|
|
||||||
//file_put_contents("/tmp/test", $password);
|
|
||||||
$this->password = base64_encode(sha1($password, TRUE));
|
$this->password = base64_encode(sha1($password, TRUE));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -254,10 +262,24 @@ class Pluf_User extends Pluf_Model
|
|||||||
if ($this->password == '') {
|
if ($this->password == '') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ($this->otpkey == "")
|
||||||
|
{
|
||||||
if ($this->password == base64_encode(sha1($password, TRUE)))
|
if ($this->password == base64_encode(sha1($password, TRUE)))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
$otp = substr($password, 0, 6);
|
||||||
|
$pass = substr($password, 6);
|
||||||
|
$totp = new \OTPHP\TOTP(strtoupper($this->otpkey));
|
||||||
|
if ($totp->verify($otp) && $this->password == base64_encode(sha1($pass, TRUE)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/*list($algo, $salt, $hash) = explode(':', $this->password);
|
/*list($algo, $salt, $hash) = explode(':', $this->password);
|
||||||
if ($hash == $algo($salt.$password)) {
|
if ($hash == $algo($salt.$password)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -71,6 +71,37 @@ class Pluf_Utils
|
|||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function convBase($numberInput, $fromBaseInput, $toBaseInput)
|
||||||
|
{
|
||||||
|
if ($fromBaseInput==$toBaseInput) return $numberInput;
|
||||||
|
$fromBase = str_split($fromBaseInput,1);
|
||||||
|
$toBase = str_split($toBaseInput,1);
|
||||||
|
$number = str_split($numberInput,1);
|
||||||
|
$fromLen=strlen($fromBaseInput);
|
||||||
|
$toLen=strlen($toBaseInput);
|
||||||
|
$numberLen=strlen($numberInput);
|
||||||
|
$retval='';
|
||||||
|
if ($toBaseInput == '0123456789')
|
||||||
|
{
|
||||||
|
$retval=0;
|
||||||
|
for ($i = 1;$i <= $numberLen; $i++)
|
||||||
|
$retval = bcadd($retval, bcmul(array_search($number[$i-1], $fromBase),bcpow($fromLen,$numberLen-$i)));
|
||||||
|
return $retval;
|
||||||
|
}
|
||||||
|
if ($fromBaseInput != '0123456789')
|
||||||
|
$base10=Pluf_Utils::convBase($numberInput, $fromBaseInput, '0123456789');
|
||||||
|
else
|
||||||
|
$base10 = $numberInput;
|
||||||
|
if ($base10<strlen($toBaseInput))
|
||||||
|
return $toBase[$base10];
|
||||||
|
while($base10 != '0')
|
||||||
|
{
|
||||||
|
$retval = $toBase[bcmod($base10,$toLen)].$retval;
|
||||||
|
$base10 = bcdiv($base10,$toLen,0);
|
||||||
|
}
|
||||||
|
return $retval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean the name of a file to only have alphanumeric characters.
|
* Clean the name of a file to only have alphanumeric characters.
|
||||||
*
|
*
|
||||||
|
74
pluf/src/Pluf/thirdparty/otp/hotp.php
vendored
Normal file
74
pluf/src/Pluf/thirdparty/otp/hotp.php
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Le Lag
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OTPHP {
|
||||||
|
/**
|
||||||
|
* HOTP - One time password generator
|
||||||
|
*
|
||||||
|
* The HOTP class allow for the generation
|
||||||
|
* and verification of one-time password using
|
||||||
|
* the HOTP specified algorithm.
|
||||||
|
*
|
||||||
|
* This class is meant to be compatible with
|
||||||
|
* Google Authenticator
|
||||||
|
*
|
||||||
|
* This class was originally ported from the rotp
|
||||||
|
* ruby library available at https://github.com/mdp/rotp
|
||||||
|
*/
|
||||||
|
class HOTP extends OTP {
|
||||||
|
/**
|
||||||
|
* Get the password for a specific counter value
|
||||||
|
* @param integer $count the counter which is used to
|
||||||
|
* seed the hmac hash function.
|
||||||
|
* @return integer the One Time Password
|
||||||
|
*/
|
||||||
|
public function at($count) {
|
||||||
|
return $this->generateOTP($count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if a password is valid for a specific counter value
|
||||||
|
*
|
||||||
|
* @param integer $otp the one-time password
|
||||||
|
* @param integer $counter the counter value
|
||||||
|
* @return bool true if the counter is valid, false otherwise
|
||||||
|
*/
|
||||||
|
public function verify($otp, $counter) {
|
||||||
|
return ($otp == $this->at($counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the uri for a specific secret for hotp method.
|
||||||
|
* Can be encoded as a image for simple configuration in
|
||||||
|
* Google Authenticator.
|
||||||
|
*
|
||||||
|
* @param string $name the name of the account / profile
|
||||||
|
* @param integer $initial_count the initial counter
|
||||||
|
* @return string the uri for the hmac secret
|
||||||
|
*/
|
||||||
|
public function provisioning_uri($name, $initial_count) {
|
||||||
|
return "otpauth://hotp/".urlencode($name)."?secret={$this->secret}&counter=$initial_count";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
120
pluf/src/Pluf/thirdparty/otp/otp.php
vendored
Normal file
120
pluf/src/Pluf/thirdparty/otp/otp.php
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Le Lag
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OTPHP {
|
||||||
|
/**
|
||||||
|
* One Time Password Generator
|
||||||
|
*
|
||||||
|
* The OTP class allow the generation of one-time
|
||||||
|
* password that is described in rfc 4xxx.
|
||||||
|
*
|
||||||
|
* This is class is meant to be compatible with
|
||||||
|
* Google Authenticator.
|
||||||
|
*
|
||||||
|
* This class was originally ported from the rotp
|
||||||
|
* ruby library available at https://github.com/mdp/rotp
|
||||||
|
*/
|
||||||
|
class OTP {
|
||||||
|
/**
|
||||||
|
* The base32 encoded secret key
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $secret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm used for the hmac hash function
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $digest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of digits in the one-time password
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $digits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the OTP class
|
||||||
|
* @param string $secret the secret key
|
||||||
|
* @param array $opt options array can contain the
|
||||||
|
* following keys :
|
||||||
|
* @param integer digits : the number of digits in the one time password
|
||||||
|
* Currently Google Authenticator only support 6. Defaults to 6.
|
||||||
|
* @param string digest : the algorithm used for the hmac hash function
|
||||||
|
* Google Authenticator only support sha1. Defaults to sha1
|
||||||
|
*
|
||||||
|
* @return new OTP class.
|
||||||
|
*/
|
||||||
|
public function __construct($secret, $opt = Array()) {
|
||||||
|
$this->digits = isset($opt['digits']) ? $opt['digits'] : 6;
|
||||||
|
$this->digest = isset($opt['digest']) ? $opt['digest'] : 'sha1';
|
||||||
|
$this->secret = $secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a one-time password
|
||||||
|
*
|
||||||
|
* @param integer $input : number used to seed the hmac hash function.
|
||||||
|
* This number is usually a counter (HOTP) or calculated based on the current
|
||||||
|
* timestamp (see TOTP class).
|
||||||
|
* @return integer the one-time password
|
||||||
|
*/
|
||||||
|
public function generateOTP($input) {
|
||||||
|
$hash = hash_hmac($this->digest, $this->intToBytestring($input), $this->byteSecret());
|
||||||
|
foreach(str_split($hash, 2) as $hex) { // stupid PHP has bin2hex but no hex2bin WTF
|
||||||
|
$hmac[] = hexdec($hex);
|
||||||
|
}
|
||||||
|
$offset = $hmac[19] & 0xf;
|
||||||
|
$code = ($hmac[$offset+0] & 0x7F) << 24 |
|
||||||
|
($hmac[$offset + 1] & 0xFF) << 16 |
|
||||||
|
($hmac[$offset + 2] & 0xFF) << 8 |
|
||||||
|
($hmac[$offset + 3] & 0xFF);
|
||||||
|
return $code % pow(10, $this->digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the binary value of the base32 encoded secret
|
||||||
|
* @access private
|
||||||
|
* This method should be private but was left public for
|
||||||
|
* phpunit tests to work.
|
||||||
|
* @return binary secret key
|
||||||
|
*/
|
||||||
|
public function byteSecret() {
|
||||||
|
return \Base32::decode($this->secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns an integer in a OATH bytestring
|
||||||
|
* @param integer $int
|
||||||
|
* @access private
|
||||||
|
* @return string bytestring
|
||||||
|
*/
|
||||||
|
public function intToBytestring($int) {
|
||||||
|
$result = Array();
|
||||||
|
while($int != 0) {
|
||||||
|
$result[] = chr($int & 0xFF);
|
||||||
|
$int >>= 8;
|
||||||
|
}
|
||||||
|
return str_pad(join(array_reverse($result)), 8, "\000", STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
pluf/src/Pluf/thirdparty/otp/otphp.php
vendored
Normal file
26
pluf/src/Pluf/thirdparty/otp/otphp.php
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Le Lag
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__).'/vendor/libs.php';
|
||||||
|
require_once dirname(__FILE__).'/otp.php';
|
||||||
|
require_once dirname(__FILE__).'/hotp.php';
|
||||||
|
require_once dirname(__FILE__).'/totp.php';
|
106
pluf/src/Pluf/thirdparty/otp/totp.php
vendored
Normal file
106
pluf/src/Pluf/thirdparty/otp/totp.php
vendored
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Le Lag
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OTPHP {
|
||||||
|
/**
|
||||||
|
* TOTP - One time password generator
|
||||||
|
*
|
||||||
|
* The TOTP class allow for the generation
|
||||||
|
* and verification of one-time password using
|
||||||
|
* the TOTP specified algorithm.
|
||||||
|
*
|
||||||
|
* This class is meant to be compatible with
|
||||||
|
* Google Authenticator
|
||||||
|
*
|
||||||
|
* This class was originally ported from the rotp
|
||||||
|
* ruby library available at https://github.com/mdp/rotp
|
||||||
|
*/
|
||||||
|
class TOTP extends OTP {
|
||||||
|
/**
|
||||||
|
* The interval in seconds for a one-time password timeframe
|
||||||
|
* Defaults to 30
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $interval;
|
||||||
|
|
||||||
|
public function __construct($s, $opt = Array()) {
|
||||||
|
$this->interval = isset($opt['interval']) ? $opt['interval'] : 30;
|
||||||
|
parent::__construct($s, $opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password for a specific timestamp value
|
||||||
|
*
|
||||||
|
* @param integer $timestamp the timestamp which is timecoded and
|
||||||
|
* used to seed the hmac hash function.
|
||||||
|
* @return integer the One Time Password
|
||||||
|
*/
|
||||||
|
public function at($timestamp) {
|
||||||
|
return $this->generateOTP($this->timecode($timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password for the current timestamp value
|
||||||
|
*
|
||||||
|
* @return integer the current One Time Password
|
||||||
|
*/
|
||||||
|
public function now() {
|
||||||
|
return $this->generateOTP($this->timecode(time()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if a password is valid for a specific counter value
|
||||||
|
*
|
||||||
|
* @param integer $otp the one-time password
|
||||||
|
* @param integer $timestamp the timestamp for the a given time, defaults to current time.
|
||||||
|
* @return bool true if the counter is valid, false otherwise
|
||||||
|
*/
|
||||||
|
public function verify($otp, $timestamp = null) {
|
||||||
|
if($timestamp === null)
|
||||||
|
$timestamp = time();
|
||||||
|
return ($otp == $this->at($timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the uri for a specific secret for totp method.
|
||||||
|
* Can be encoded as a image for simple configuration in
|
||||||
|
* Google Authenticator.
|
||||||
|
*
|
||||||
|
* @param string $name the name of the account / profile
|
||||||
|
* @return string the uri for the hmac secret
|
||||||
|
*/
|
||||||
|
public function provisioning_uri($name) {
|
||||||
|
return "otpauth://totp/".urlencode($name)."?secret={$this->secret}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a timestamp in a counter based on specified internal
|
||||||
|
*
|
||||||
|
* @param integer $timestamp
|
||||||
|
* @return integer the timecode
|
||||||
|
*/
|
||||||
|
protected function timecode($timestamp) {
|
||||||
|
return (int)( (((int)$timestamp * 1000) / ($this->interval * 1000)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
82
pluf/src/Pluf/thirdparty/otp/vendor/base32.php
vendored
Normal file
82
pluf/src/Pluf/thirdparty/otp/vendor/base32.php
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode in Base32 based on RFC 4648.
|
||||||
|
* Requires 20% more space than base64
|
||||||
|
* Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls)
|
||||||
|
*
|
||||||
|
* @package default
|
||||||
|
* @author Bryan Ruiz
|
||||||
|
**/
|
||||||
|
class Base32 {
|
||||||
|
|
||||||
|
private static $map = array(
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
|
||||||
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
|
||||||
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
|
||||||
|
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
|
||||||
|
'=' // padding char
|
||||||
|
);
|
||||||
|
|
||||||
|
private static $flippedMap = array(
|
||||||
|
'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7',
|
||||||
|
'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15',
|
||||||
|
'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23',
|
||||||
|
'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use padding false when encoding for urls
|
||||||
|
*
|
||||||
|
* @return base32 encoded string
|
||||||
|
* @author Bryan Ruiz
|
||||||
|
**/
|
||||||
|
public static function encode($input, $padding = true) {
|
||||||
|
if(empty($input)) return "";
|
||||||
|
$input = str_split($input);
|
||||||
|
$binaryString = "";
|
||||||
|
for($i = 0; $i < count($input); $i++) {
|
||||||
|
$binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
$fiveBitBinaryArray = str_split($binaryString, 5);
|
||||||
|
$base32 = "";
|
||||||
|
$i=0;
|
||||||
|
while($i < count($fiveBitBinaryArray)) {
|
||||||
|
$base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
if($padding && ($x = strlen($binaryString) % 40) != 0) {
|
||||||
|
if($x == 8) $base32 .= str_repeat(self::$map[32], 6);
|
||||||
|
else if($x == 16) $base32 .= str_repeat(self::$map[32], 4);
|
||||||
|
else if($x == 24) $base32 .= str_repeat(self::$map[32], 3);
|
||||||
|
else if($x == 32) $base32 .= self::$map[32];
|
||||||
|
}
|
||||||
|
return $base32;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function decode($input) {
|
||||||
|
if(empty($input)) return;
|
||||||
|
$paddingCharCount = substr_count($input, self::$map[32]);
|
||||||
|
$allowedValues = array(6,4,3,1,0);
|
||||||
|
if(!in_array($paddingCharCount, $allowedValues)) return false;
|
||||||
|
for($i=0; $i<4; $i++){
|
||||||
|
if($paddingCharCount == $allowedValues[$i] &&
|
||||||
|
substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false;
|
||||||
|
}
|
||||||
|
$input = str_replace('=','', $input);
|
||||||
|
$input = str_split($input);
|
||||||
|
$binaryString = "";
|
||||||
|
for($i=0; $i < count($input); $i = $i+8) {
|
||||||
|
$x = "";
|
||||||
|
if(!in_array($input[$i], self::$map)) return false;
|
||||||
|
for($j=0; $j < 8; $j++) {
|
||||||
|
$x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
$eightBits = str_split($x, 8);
|
||||||
|
for($z = 0; $z < count($eightBits); $z++) {
|
||||||
|
$binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $binaryString;
|
||||||
|
}
|
||||||
|
}
|
26
pluf/src/Pluf/thirdparty/otp/vendor/libs.php
vendored
Normal file
26
pluf/src/Pluf/thirdparty/otp/vendor/libs.php
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Le Lag
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add any needed third party library to this directory
|
||||||
|
|
||||||
|
//require_once dirname(__FILE__).'/some_lib/lib.php';
|
||||||
|
require_once dirname(__FILE__).'/base32.php';
|
Loading…
Reference in New Issue
Block a user