Task #2309 mot de passe fort
This commit is contained in:
parent
86852bc425
commit
a0d1c26eaf
10 changed files with 296 additions and 35 deletions
|
|
@ -113,7 +113,22 @@ if ($op == "progressBar") {
|
|||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
// check password
|
||||
//-------------------------------------------------------------------------------------------
|
||||
if ($op=='password_chk') {
|
||||
$cnt = $http->request("pass");
|
||||
$result=check_password_strength($cnt)['msg'];
|
||||
if (count($result) == 0) {
|
||||
echo json_response(["password" => "ok", "msg" => 0]);
|
||||
} else {
|
||||
$str="";
|
||||
foreach ($result as $item) {$str.=sprintf("<li>%s</li>",$item);}
|
||||
echo json_response(["password" => "nok", "msg" => '<ol>'.$str.'</ol>']);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
$html = var_export($_REQUEST, true);
|
||||
set_language();
|
||||
if ( LOGINPUT)
|
||||
|
|
|
|||
|
|
@ -233,7 +233,19 @@ if (isset($_POST['save_config'])) {
|
|||
$err++;
|
||||
|
||||
}
|
||||
|
||||
// check strenght password admin
|
||||
$passw_error=check_password_strength($cpassword_admin);
|
||||
if ( count($passw_error['msg'])>0) {
|
||||
echo '<h2 class="warning">';
|
||||
echo _("Mot de passe trop faible");
|
||||
echo '</h2>';
|
||||
echo '<ol>';
|
||||
foreach ($passw_error['msg'] as $error) {
|
||||
echo "<li>",$error,"</li>";
|
||||
}
|
||||
echo '</ol>';
|
||||
$err++;
|
||||
}
|
||||
// check password and admin not containing quote or double quote
|
||||
//
|
||||
if ( strpos($cpassword_admin,'"') !== false
|
||||
|
|
|
|||
|
|
@ -3786,9 +3786,13 @@ function updatePreference()
|
|||
method: "post",
|
||||
parameters: param,
|
||||
onSuccess: function (req) {
|
||||
var style = req.responseText.evalJSON();
|
||||
var answer = req.responseText.evalJSON();
|
||||
// $('pagestyle').setAttribute('href', style.style);
|
||||
removeDiv('preference_div');
|
||||
if ( answer['psw']=='NOK') {
|
||||
smoke.alert(answer['msg']);
|
||||
} else {
|
||||
removeDiv('preference_div');
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e)
|
||||
|
|
@ -4224,4 +4228,50 @@ function event_display_main(p_dossier) {
|
|||
{
|
||||
alert_box(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check if password is strong or not, update a DIV element
|
||||
* @param p_pass_domid DOM ID of the INPUT element with the password
|
||||
* @param p_result_domid DOM ID of the element to update
|
||||
*/
|
||||
function check_password_strength(p_pass_domid,p_result_domid,details)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( $(p_pass_domid).value=="") { $(p_result_domid).update("");return;}
|
||||
var queryString= {
|
||||
'op':"password_chk"
|
||||
,pass:$(p_pass_domid).value
|
||||
};
|
||||
var action = new Ajax.Request(
|
||||
"ajax_misc.php" ,
|
||||
{
|
||||
method:'GET',
|
||||
parameters:queryString,
|
||||
onFailure:ajax_misc_failure,
|
||||
onSuccess:function(req){
|
||||
remove_waiting_box();
|
||||
if (req.responseText == 'NOCONX') {
|
||||
return;
|
||||
}
|
||||
var answer=req.responseJSON;
|
||||
console.debug(answer);
|
||||
if (answer['password']=='nok') {
|
||||
|
||||
$(p_pass_domid).setStyle("background-color:red");
|
||||
if ( details) {
|
||||
$(p_result_domid).update(answer['msg'])
|
||||
}
|
||||
return;
|
||||
}
|
||||
$(p_pass_domid).setStyle("background-color: lightgreen");
|
||||
$(p_result_domid).update("")
|
||||
}
|
||||
}
|
||||
);
|
||||
}catch( e)
|
||||
{
|
||||
alert_box(e.message);
|
||||
}
|
||||
}
|
||||
|
|
@ -84,8 +84,9 @@ if ( $action == 'display_form' )
|
|||
<tr><td>
|
||||
Mot de passe :
|
||||
</td>
|
||||
<td><input type="password" value="" class="input_text" name="pass_1" nohistory>
|
||||
<td><input type="password" value="" class="input_text" name="pass_1" id="pass_1" nohistory onkeyup=check_password_strength('pass_1','info_passid',1)>
|
||||
<input type="password" value="" class="input_text" name="pass_2" nohistory>
|
||||
<span id="info_passid"></span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
|
@ -321,20 +322,32 @@ if ($action == 'save')
|
|||
$csv_decimal=$http->post("csv_decimal","number");
|
||||
$csv_encoding=$http->post("csv_encoding");
|
||||
$firstday=$http->post("selFirstDay","number");
|
||||
|
||||
$password="OK";
|
||||
$msg ="";
|
||||
if (noalyss_strlentrim($pass_1) != 0 && noalyss_strlentrim($pass_2) != 0)
|
||||
{
|
||||
if ( $g_user->save_password($_POST['pass_1'],$pass_2) )
|
||||
{ $g_user->password_to_session() ;
|
||||
{
|
||||
$g_user->password_to_session() ;
|
||||
|
||||
} else {
|
||||
/**
|
||||
* password not changed
|
||||
*/
|
||||
|
||||
*/
|
||||
$password="NOK";
|
||||
$msg="";
|
||||
if ( $_POST['pass_1'] !== $pass_2) {
|
||||
$msg = _("Mot de passe ne correspondent pas");
|
||||
$msg .="<br/>";
|
||||
}
|
||||
$a_pass_error=check_password_strength($_POST['pass_1']);
|
||||
if ( count($a_pass_error['msg']) != 0 ) {
|
||||
foreach($a_pass_error['msg'] as $pass_error) {
|
||||
$msg.=$pass_error."<br/>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if ( $inside_dossier)
|
||||
{
|
||||
|
|
@ -366,6 +379,6 @@ if ($action == 'save')
|
|||
{
|
||||
$style = "style-classic7.css";
|
||||
}
|
||||
json_response(["style"=>$style]);
|
||||
json_response(["style"=>$style,'psw'=>$password,'msg'=>$msg]);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1635,11 +1635,12 @@ class Noalyss_User
|
|||
* @brief Save the password of the current user
|
||||
* @param string $p_pass1 password (clear)
|
||||
* @param string $p_pass2 for confirming password (clear)
|
||||
* @see check_password_strength()
|
||||
* @return true : password successfully changed otherwise false
|
||||
*/
|
||||
function save_password($p_pass1, $p_pass2)
|
||||
{
|
||||
if ($p_pass1==$p_pass2)
|
||||
if ($p_pass1==$p_pass2 && count(check_password_strength($p_pass1)['msg'])==0)
|
||||
{
|
||||
$repo=new Database();
|
||||
$l_pass=md5($p_pass1);
|
||||
|
|
|
|||
|
|
@ -1416,10 +1416,13 @@ function remove_divide_zero($p_formula)
|
|||
* @brief Create randomly a string
|
||||
* @param int $p_length length of the generate string
|
||||
*/
|
||||
function generate_random_string($p_length)
|
||||
function generate_random_string($p_length,$special=1)
|
||||
{
|
||||
$string="";
|
||||
$chaine="abcdefghijklmnpqrstuvwxyABCDEFGHIJKLMNPQRSTUVWXY0123456789*/+-=";
|
||||
if ($special == 1)
|
||||
$chaine="abcdefghijklmnpqrstuvwxyABCDEFGHIJKLMNPQRSTUVWXY0123456789*/+-=";
|
||||
if ($special == 0)
|
||||
$chaine="abcdefghijklmnpqrstuvwxyABCDEFGHIJKLMNPQRSTUVWXY0123456789";
|
||||
$microtime=microtime(true)*microtime(true)*100;
|
||||
srand(0);
|
||||
srand((int)$microtime);
|
||||
|
|
@ -1663,3 +1666,111 @@ function MaintenanceMode($p_file)
|
|||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns an double array with the error found and code , if the count is 0 then the password is very string, 5 means it is
|
||||
* empty ,4 weak, ... the array contains the errors, [msg]=>array message [code] => array of code
|
||||
* Codes are
|
||||
* - 1 : too short
|
||||
* - 2 : missing digit
|
||||
* - 3 : missing lowercase letter
|
||||
* - 4 : missing uppercase letter
|
||||
* - 5 : too many time same letter or symbol..
|
||||
* - 6 : missing special char
|
||||
*
|
||||
* If the password is strong returns an empty array
|
||||
*
|
||||
* @param $password string
|
||||
* @code
|
||||
|
||||
$error = check_password_strength($password);
|
||||
if ( count($error['msg']) > 0 ) {
|
||||
echo "password to weak";
|
||||
foreach ($error['msg'] as $item_error) {
|
||||
echo "error $item_error";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "OK password strong";
|
||||
}
|
||||
|
||||
* @endcode
|
||||
*/
|
||||
function check_password_strength($password) {
|
||||
$errors=array();
|
||||
$error_code=array();
|
||||
|
||||
$len=strlen($password??"");
|
||||
if ( $len < 8) {
|
||||
$errors[] = _("mot de passe de 8 lettres minimum");
|
||||
$error_code[]=1;
|
||||
}
|
||||
|
||||
if (!preg_match("#[0-9]+#", $password)) {
|
||||
$errors[] = _("mot de passe doit inclure au moins un chiffre");
|
||||
$error_code[]=2;
|
||||
}
|
||||
|
||||
if (!preg_match("#[a-z]+#", $password)) {
|
||||
$errors[] = _("mot de passe doit inclure au moins une minuscule");
|
||||
$error_code[]=3;
|
||||
}
|
||||
if (!preg_match("#[A-Z]+#", $password)) {
|
||||
$errors[] = _("mot de passe doit inclure au moins une majuscule");
|
||||
$error_code[]=4;
|
||||
}
|
||||
|
||||
if ( $len > 0 ) {
|
||||
$cnt_diff=count(count_chars($password,1));
|
||||
$ratio_diff=$len/$cnt_diff;
|
||||
|
||||
if ($ratio_diff > 2) {
|
||||
$errors[] = _("Trop souvent le(s) même(s) symbole(s)");
|
||||
$error_code[]=5;
|
||||
}
|
||||
$special_char=preg_replace('/[[:alnum:]]/','',$password);
|
||||
if ( strlen($special_char??"")==0)
|
||||
{
|
||||
$errors[] = _("mot de passe doit inclure au moins un caractére spécial '+-/*[...'");
|
||||
$error_code[]=6;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return array( 'msg'=>$errors, 'code'=>$error_code);
|
||||
}
|
||||
/**
|
||||
* @brief generate a strong random password
|
||||
* @param $car int length of the password, minimum 8
|
||||
*
|
||||
*/
|
||||
function generate_random_password($car):string
|
||||
{
|
||||
$string="";
|
||||
$car=($car < 8 )?8:$car;
|
||||
$max_loop=20;$loop=0;
|
||||
do
|
||||
{
|
||||
$loop++;
|
||||
$string="";
|
||||
$chaine="abcdefghijklmnpqrstuvwxy";
|
||||
// srand( (int)microtime()*1020030);
|
||||
for ($i=0; $i<$car; $i++)
|
||||
{
|
||||
$string .= $chaine[rand()%strlen($chaine)];
|
||||
}
|
||||
$chaine="ABCDEFGHIJKLMNPQRSTUVWXY";
|
||||
for ($i=0;$i<2;$i++) {
|
||||
$string[rand()%$car]=$chaine[rand()%strlen($chaine)];;
|
||||
}
|
||||
$chaine="0123456789";
|
||||
for ($i=0;$i<2;$i++) {
|
||||
$string[rand()%$car]=$chaine[rand()%strlen($chaine)];;
|
||||
}
|
||||
$special_set="+-/*;,.=:&()[]";
|
||||
$special_car=$special_set[rand()%strlen($special_set)];
|
||||
$string[rand()%$car]=$special_car;
|
||||
// echo $string."\n";
|
||||
}while ( count(check_password_strength($string)['msg'])> 0 && $loop<$max_loop);
|
||||
return $string;
|
||||
}
|
||||
|
|
@ -17,27 +17,14 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
// Copyright (2014) Author Dany De Bontridder <dany@alchimerys.be>
|
||||
require_once NOALYSS_INCLUDE.'/lib/ac_common.php';
|
||||
|
||||
if (!defined('RECOVER'))
|
||||
die('Appel direct ne sont pas permis');
|
||||
define('SIZE_REQUEST', 70);
|
||||
|
||||
|
||||
/**
|
||||
* @brief generate a random string of char
|
||||
* @param $car int length of the string
|
||||
*/
|
||||
function generate_random($car)
|
||||
{
|
||||
$string="";
|
||||
$chaine="abcdefghijklmnpqrstuvwxyABCDEFGHIJKLMNPQRSTUVWXY0123456789";
|
||||
srand((double) microtime()*1020030);
|
||||
for ($i=0; $i<$car; $i++)
|
||||
{
|
||||
$string .= $chaine[rand()%strlen($chaine)];
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
$http=new HttpInput();
|
||||
/**
|
||||
* @file
|
||||
|
|
@ -89,8 +76,8 @@ elseif ($action=="send_email") :
|
|||
|
||||
|
||||
if ($valid==true):
|
||||
$request_id=generate_random(SIZE_REQUEST);
|
||||
$user_password=generate_random(10);
|
||||
$request_id=generate_random_string(SIZE_REQUEST,special: 0);
|
||||
$user_password=generate_random_password(10);
|
||||
// exist a valid request for this user ?
|
||||
$exist_request= $cn->get_array("select request , password from recover_pass
|
||||
where use_id=$1 and created_on > now() - interval '12 hours'",[$user_id]);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ echo '<div class="content" >';
|
|||
if ( isset ($_POST["ADD"]) )
|
||||
{
|
||||
$cn=new Database();
|
||||
$a_result =check_password_strength($_POST['PASS']);
|
||||
$pass5=md5($_POST['PASS']);
|
||||
$new_user=new Noalyss_user($cn,0);
|
||||
$new_user->first_name=$http->post('FNAME');
|
||||
|
|
@ -45,11 +46,18 @@ if ( isset ($_POST["ADD"]) )
|
|||
$login=str_replace(" ","",$login);
|
||||
$login=strtolower($login);
|
||||
$new_user->login=$login;
|
||||
$new_user->setPassword($pass5);
|
||||
|
||||
$new_user->email=$http->post('EMAIL',"string",'');
|
||||
if ( trim($login)=="")
|
||||
{
|
||||
alert(_("Le login ne peut pas être vide"));
|
||||
}elseif (count($a_result['msg']) > 0){
|
||||
// password too weak
|
||||
$msg='<span class="warning">'._("Mot de passe inchangé").'</span>';
|
||||
foreach ($a_result['msg'] as $result ) {
|
||||
$msg.="$result <br/>";
|
||||
}
|
||||
alert($msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -101,8 +109,18 @@ if ($sbaction == "save")
|
|||
}
|
||||
if ( trim($_POST['password'])<>'')
|
||||
{
|
||||
$UserChange->setPassword(md5($_POST['password']));
|
||||
$UserChange->save();
|
||||
$a_result =check_password_strength($_POST['password']);
|
||||
if (count($a_result['msg']) > 0){
|
||||
// password too weak
|
||||
$msg='<span class="warning">'._("Mot de passe inchangé").'</span>';
|
||||
foreach ($a_result['msg'] as $result ) {
|
||||
$msg.="$result <br/>";
|
||||
}
|
||||
alert($msg);
|
||||
} else {
|
||||
$UserChange->setPassword(md5($_POST['password']));
|
||||
$UserChange->save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -168,9 +186,19 @@ if ( isset($_REQUEST['det']) && $sbaction=="")
|
|||
<TR><TD style="text-align: right"> <?php echo _('login')?></TD><TD><INPUT id="input_login" class="input_text" TYPE="TEXT" NAME="LOGIN"></TD></tr>
|
||||
<TR><TD style="text-align: right"> <?php echo _('Prénom')?></TD><TD><INPUT class="input_text" TYPE="TEXT" NAME="FNAME"></TD></tr>
|
||||
<TR><TD style="text-align: right"> <?php echo _('Nom')?></TD><TD><INPUT class="input_text" TYPE="TEXT" NAME="LNAME"></TD></TR>
|
||||
<TR><TD style="text-align: right"> <?php echo _('Mot de passe')?></TD><TD> <INPUT id="input_password" class="input_text" TYPE="TEXT" NAME="PASS"></TD></TR>
|
||||
<TR>
|
||||
<TD style="text-align: right"> <?php echo _('Mot de passe')?>
|
||||
<?=\Icon_Action::tips("Mot de passe : longueur minimale = 8 dont au moins 1 majuscule, 1 minuscule,1 chiffre et 1 car.spécial")?>
|
||||
|
||||
</TD>
|
||||
<TD> <INPUT id="input_password" class="input_text" TYPE="TEXT" NAME="PASS"
|
||||
onkeyup=check_password_strength('input_password','info_passid')
|
||||
>
|
||||
<span id="info_passid"></span>
|
||||
</TD></TR>
|
||||
<TR><TD style="text-align: right"> <?php echo _('Email')?></TD><TD> <INPUT class="input_text" TYPE="TEXT" NAME="EMAIL"></TD></TR>
|
||||
</TABLE>
|
||||
|
||||
<?php
|
||||
echo HtmlInput::submit("ADD",_('Créer Utilisateur'),"",'button');
|
||||
echo HtmlInput::button_action(_("Fermer"), "$('create_user').style.display='none';");
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ if ($UserChange->id == false)
|
|||
|
||||
$UserChange->load();
|
||||
$it_pass=new IText('password');
|
||||
$it_pass->javascript='onkeyup="check_password_strength(\'password\',\'password_info\',1)"';
|
||||
$it_pass->value="";
|
||||
?>
|
||||
<FORM id="user_detail_frm" METHOD="POST">
|
||||
|
|
@ -81,6 +82,7 @@ $it_pass->value="";
|
|||
</td>
|
||||
<td>
|
||||
<?php echo $it_pass->input();?>
|
||||
<span id="password_info" style="background-color: yellow;color:red;position:absolute"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -424,4 +424,46 @@ EOF;
|
|||
$this->assertEquals(strtoupper($expect),strtoupper(preg_replace("/\s+/",'',faxTo('123'))),);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* supply data for user password
|
||||
* @return array[$password, $weakness] 0 means strong password
|
||||
*/
|
||||
public function dataCheck_password_strength()
|
||||
{
|
||||
return array(
|
||||
["AAAAAAA",5]
|
||||
,["123456789",3]
|
||||
,["Az123456789",1]
|
||||
,["",4]
|
||||
,["+",4]
|
||||
,["AAAA121212abx",2]
|
||||
,["Az&123456789",0]
|
||||
,["l5F8Cny=",0]
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @testDoc test the check_password_strength function
|
||||
* @dataProvider dataCheck_password_strength()
|
||||
*/
|
||||
public function testCheck_password_strength($p_password,$p_cnt)
|
||||
{
|
||||
|
||||
$count=count(check_password_strength($p_password)['msg']);
|
||||
$this->assertTrue($count ==$p_cnt,"error : $p_password weak password $count" );
|
||||
|
||||
}
|
||||
|
||||
public function testGenerate_strong_password()
|
||||
{
|
||||
|
||||
for ($i = 0; $i < 100; $i++)
|
||||
{
|
||||
$pass=generate_random_password(5);
|
||||
|
||||
$this->assertTrue( count(check_password_strength($pass)['msg'])==0
|
||||
,"error cannot generate strong password get $pass");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue