source: extensions/Password_Policy/include/functions.inc.php @ 25973

Last change on this file since 25973 was 25104, checked in by Eric, 11 years ago

Next version is 2.5.1 :

  • Improve workflow when account is locked and a password renewal is set
  • Add missing translation keys
  • Update it_IT, thanks to : Ericnet
File size: 16.9 KB
Line 
1<?php
2
3load_language('plugin.lang', PP_PATH);
4
5/**
6 * Triggered on get_admin_plugin_menu_links
7 *
8 * Plugin's administration menu
9 */
10function PP_admin_menu($menu)
11{
12// +-----------------------------------------------------------------------+
13// |                      Getting plugin name                              |
14// +-----------------------------------------------------------------------+
15  $plugin =  PPInfos(PP_PATH);
16  $name = $plugin['name'];
17 
18  array_push($menu,
19    array(
20                'NAME' => $name,
21                'URL' => get_root_url().'admin.php?page=plugin-'.basename(PP_PATH)
22    )
23  );
24
25  return $menu;
26}
27
28
29/**
30 * Triggered on loc_begin_index
31 *
32 * Perform user logout after registration if account locked and redirection to profile page is password renewal is set
33 */
34function PP_Init()
35{
36  global $conf, $user;
37
38  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
39
40  $conf_PP = unserialize($conf['PasswordPolicy']);
41
42  // Perfoming redirection for locked accounts
43  // -----------------------------------------
44  if (!is_a_guest() and $user['username'] != "16" and $user['username'] != "18")
45  {
46    // Perform user logout if user account is locked
47    if (
48          (isset($conf_PP['LOGFAILBLOCK']) and $conf_PP['LOGFAILBLOCK'] == 'true')
49          and PP_UsrBlock_Verif($user['username'])
50          //and (isset($userlocked) and $userlocked == 'true')
51          and !is_admin()
52          and !is_webmaster())
53    {
54      invalidate_user_cache();
55      logout_user();
56      if ($conf['guest_access'])
57      {
58        redirect(make_index_url().'?PP_msg=locked', 0);
59      }
60      else
61      {
62        redirect(get_root_url().'identification.php?PP_msg=locked' , 0);
63      }
64    }
65  }
66
67  // Performing redirection to profile page for password reset
68  // ---------------------------------------------------------
69  if ((isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true'))
70  {
71    $query ='
72SELECT user_id, status
73FROM '.USER_INFOS_TABLE.'
74WHERE user_id = '.$user['id'].'
75;';
76    $data = pwg_db_fetch_assoc(pwg_query($query));
77
78    if ($data['status'] <> "webmaster" and $data['status'] <> "generic") // Exclusion of specific accounts
79    {
80      if (PP_check_pwdreset($user['id']))
81      {
82        redirect(PHPWG_ROOT_PATH.'profile.php');
83      }
84    }
85  }
86
87
88}
89
90
91/**
92 * Triggered on init
93 *
94 * Displays messages on index page
95 */
96function PP_InitPage()
97{
98  global $conf, $template, $page, $lang, $errors;
99
100  load_language('plugin.lang', PP_PATH);
101
102  if( isset($_GET['PP_msg']))
103  {
104    PP_DisplayMsg();
105  }
106}
107
108
109/**
110 * Triggered on init
111 *
112 * Display a message according to $_GET['PP_msg']
113 */
114function PP_DisplayMsg()
115{
116  if (isset($_GET['PP_msg']))
117  {
118    global $user, $lang, $conf, $page;
119    $conf_PP = unserialize($conf['PasswordPolicy']);
120
121    // User account locked after x failed attempts
122    if (isset($conf_PP['USRLOCKEDTXT']) and !empty($conf_PP['USRLOCKEDTXT']) and $_GET['PP_msg']=="locked")
123    {
124      if (function_exists('get_user_language_desc'))// Extended Description [lang] feature
125      {
126        $custom_text = get_user_language_desc($conf_PP['USRLOCKEDTXT']);
127      }
128      else $custom_text = l10n($conf_PP['USRLOCKEDTXT']);
129
130      $page["errors"][]=$custom_text;
131    }
132  }
133}
134
135
136/**
137 * Triggered on login_failure in main.inc.php
138 * Count of login failures and lock account after x attempt
139 *
140 */
141function PP_log_fail($username)
142{
143  global $conf, $user;
144
145  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
146
147  $conf_PP = unserialize($conf['PasswordPolicy']);
148
149  if (
150        (isset($conf_PP['NBLOGFAIL']) and $conf_PP['NBLOGFAIL'] <> 0)
151    and (isset($conf_PP['LOGFAILBLOCK']) and $conf_PP['LOGFAILBLOCK'] == 'true')
152    and !is_admin()
153    and !is_webmaster()
154    )
155  {
156    // If login failure then increments loginfailcount value in database
157    $query = '
158UPDATE '.USERS_TABLE.'
159SET PP_loginfailcount = PP_loginfailcount+1
160WHERE username = "'.stripslashes($username).'"
161LIMIT 1
162;';
163    pwg_query($query);
164
165    $query = '
166SELECT PP_loginfailcount
167FROM '.USERS_TABLE.'
168WHERE username = "'.stripslashes($username).'"
169;';
170
171    $datas = pwg_db_fetch_assoc(pwg_query($query));
172
173    // If number of failed logon exeeds $conf_PP['NBLOGFAIL'], set the account as locked
174    if (isset($datas['PP_loginfailcount']) and $datas['PP_loginfailcount'] >= $conf_PP['NBLOGFAIL'])
175    {
176      $query = '
177UPDATE '.USERS_TABLE.'
178SET PP_lock = "true"
179WHERE username = "'.stripslashes($username).'"
180LIMIT 1
181;';
182      pwg_query($query);
183
184    }
185  }
186}
187
188
189/**
190 * PP_user_list_pwdreset
191 * Adds a new feature in user_list to allow password reset for selected users by admin
192 *
193 */
194function PP_user_list_pwdreset($visible_user_list)
195{
196  global $template;
197 
198  load_language('plugin.lang', PP_PATH);
199
200  $template->append('plugin_user_list_column_titles', l10n('PP_PwdReset'));
201
202  $user_ids = array();
203
204  foreach ($visible_user_list as $i => $user)
205  {
206    $user_ids[$i] = $user['id'];
207  }
208
209  $user_nums = array_flip($user_ids);
210
211  // Query to get information in database
212  // ------------------------------------
213  if (!empty($user_ids))
214  {
215    $query = '
216SELECT DISTINCT id, PP_pwdreset
217  FROM '.USERS_TABLE.'
218  WHERE id IN ('.implode(',', $user_ids).')
219;';
220    $result = pwg_query($query);
221
222    while ($row = pwg_db_fetch_assoc($result))
223    {
224      if ($row['PP_pwdreset'] == 'false')
225      {
226        $pwdreset = l10n('PP_PwdReset_Done');
227      }
228      else if ($row['PP_pwdreset'] == 'true')
229      {
230        $pwdreset = l10n('PP_PwdReset_Todo');
231      }
232      else $pwdreset = l10n('PP_PwdReset_NA');
233
234                  $visible_user_list[$user_nums[$row['id']]]['plugin_columns'][] = $pwdreset; // Shows users password state in user_list
235    }
236  }
237  return $visible_user_list;
238}
239
240
241/**
242 * PP_user_list_locked
243 * Adds a new feature in user_list to allow user unlocking by admin
244 *
245 */
246function PP_user_list_locked($visible_user_list)
247{
248  global $template;
249 
250  load_language('plugin.lang', PP_PATH);
251
252  $template->append('plugin_user_list_column_titles', l10n('PP_LockedUsers'));
253
254  $user_ids = array();
255
256  foreach ($visible_user_list as $i => $user)
257  {
258    $user_ids[$i] = $user['id'];
259  }
260
261  $user_nums = array_flip($user_ids);
262
263  // Query to get information in database
264  // ------------------------------------
265  if (!empty($user_ids))
266  {
267    $query = '
268SELECT DISTINCT id, PP_lock
269  FROM '.USERS_TABLE.'
270  WHERE id IN ('.implode(',', $user_ids).')
271;';
272    $result = pwg_query($query);
273
274    while ($row = pwg_db_fetch_assoc($result))
275    {
276      if ($row['PP_lock'] == 'false')
277      {
278        $LockedUser = '<img src="'.PP_PATH.'admin/template/icons/nolock.png" title="'.l10n('PP_User Not Locked').'" alt="'.l10n('PP_User Not Locked').'"/>';
279      }
280      else if ($row['PP_lock'] == 'true')
281      {
282        $LockedUser = '<img src="'.PP_PATH.'admin/template/icons/lock.png" title="'.l10n('PP_User Locked').'" alt="'.l10n('PP_User Locked').'"/>';
283      }
284      else $LockedUser = '<img src="'.PP_PATH.'admin/template/icons/nolock.png" title="'.l10n('PP_User Not Locked').'" alt="'.l10n('PP_User Not Locked').'"/>';
285
286                  $visible_user_list[$user_nums[$row['id']]]['plugin_columns'][] = $LockedUser; // Shows users account state in user_list
287    }
288  }
289  return $visible_user_list;
290}
291
292
293/**
294 * Triggered on register_user_check
295 *
296 * Additional controls on user registration check
297 */
298function PP_RegistrationCheck($errors, $user)
299{
300  global $conf;
301
302  // Exclusion of Adult_Content users
303  // --------------------------------
304  if ($user['username'] != "16" and $user['username'] != "18")
305  {
306    load_language('plugin.lang', PP_PATH);
307
308    $PasswordCheck = 0;
309
310    $conf_PP = unserialize($conf['PasswordPolicy']);
311
312    // Password enforcement control
313    // ----------------------------
314    if (isset($conf_PP['PASSWORDENF']) and $conf_PP['PASSWORDENF'] == 'true' and !empty($conf_PP['PASSWORD_SCORE']))
315    {
316      if (!empty($user['password']) and !is_admin())
317      {
318        $PasswordCheck = PP_testpassword($user['password']);
319
320        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
321        {
322          $message = get_l10n_args('PP_Error_Password_Need_Enforcement_%s', $PasswordCheck);
323          $lang['reg_err_pass'] = l10n_args($message).$conf_PP['PASSWORD_SCORE'];
324          array_push($errors, $lang['reg_err_pass']);
325        }
326      }
327      else if (!empty($user['password']) and is_admin() and isset($conf_PP['ADMINPASSWENF']) and $conf_PP['ADMINPASSWENF'] == 'true')
328      {
329        $PasswordCheck = PP_testpassword($user['password']);
330
331        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
332        {
333          $message = get_l10n_args('PP_Error_Password_Need_Enforcement_%s', $PasswordCheck);
334          $lang['reg_err_pass'] = l10n_args($message).$conf_PP['PASSWORD_SCORE'];
335          array_push($errors, $lang['reg_err_pass']);
336        }
337      }
338    }
339    return $errors;
340  }
341}
342
343
344/**
345 * Triggered on loc_begin_profile
346 */
347function PP_Profile_Init()
348{
349  global $conf, $user, $template;
350 
351  load_language('plugin.lang', PP_PATH);
352
353  $conf_PP = unserialize($conf['PasswordPolicy']);
354
355  // Special message display for password reset
356  // ------------------------------------------
357  if ((isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true'))
358  {
359    if (PP_check_pwdreset($user['id']))
360    {
361      $template->append('errors', l10n('PP_Password_Reset_Msg'));
362    }
363  }
364
365  // Controls on profile page submission
366  // -----------------------------------
367  if (isset($_POST['validate']) and !is_admin())
368  {
369    // Password reset control
370    // ----------------------
371    if (isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true' and PP_check_pwdreset($user['id']))
372    {
373      // if password not changed then pwdreset field = true else pwdreset field = false
374      // ------------------------------------------------------------------------------
375      if (!empty($_POST['use_new_pwd']))
376      {
377        $query = '
378UPDATE '.USERS_TABLE.'
379SET PP_pwdreset = "false"
380WHERE id = '.$user['id'].'
381LIMIT 1
382;';
383        pwg_query($query);
384      }
385    }
386
387    if (!empty($_POST['use_new_pwd']))
388    {
389      // Password enforcement control
390      // ----------------------------
391      if (isset($conf_PP['PASSWORDENF']) and $conf_PP['PASSWORDENF'] == 'true' and !empty($conf_PP['PASSWORD_SCORE']))
392      {
393        $PasswordCheck = PP_testpassword($_POST['use_new_pwd']);
394
395        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
396        {
397          $message = get_l10n_args('PP_Error_Password_Need_Enforcement_%s', $PasswordCheck);
398          $template->append('errors', l10n_args($message).$conf_PP['PASSWORD_SCORE']);
399          unset($_POST['use_new_pwd']);
400          unset($_POST['validate']);
401        }
402      }
403    }
404  }
405}
406
407
408/**
409 * PP_Set_PwdReset
410 * Action in user_list to set a password reset for a user
411 */
412function PP_Set_PwdReset($uid)
413{
414  $query ='
415UPDATE '.USERS_TABLE.'
416SET PP_pwdreset = "true"
417WHERE id = '.$uid.'
418LIMIT 1
419;';
420
421  pwg_query($query);
422}
423
424
425/**
426 * PP_check_pwdreset
427 * checks if a user id is registered as having already
428 * changed his password.
429 *
430 * @uid        : the user id
431 *
432 * @returns    : true or false whether the users has already changed his password
433 *
434 */
435function PP_check_pwdreset($uid)
436{
437  $query = '
438SELECT PP_pwdreset
439FROM '.USERS_TABLE.'
440WHERE id='.$uid.'
441;';
442
443  $result = pwg_db_fetch_assoc(pwg_query($query));
444
445  if($result['PP_pwdreset'] == 'true')
446  {
447    return true;
448  }
449  else return false; 
450}
451
452
453/**
454 * Returns a password's score for password complexity check
455 *
456 * @param : password filled by user
457 *
458 * @return : Score calculation
459 *
460 * Thanx to MathieuGut from http://m-gut.developpez.com
461 */
462function PP_testpassword($password) // $password given by user
463{
464
465  // Variables initiation
466  // --------------------
467  $points = 0;
468  $point_lowercase = 0;
469  $point_uppercase = 0;
470  $point_numbers = 0;
471  $point_characters = 0;
472
473  // Getting password lengh
474  // ----------------------
475  $length = strlen($password);
476
477  // Loop to read password characters
478  for($i = 0; $i < $length; $i++)
479  {
480    // Select each letters
481    // $i is 0 at first turn
482    // ---------------------
483    $letters = $password[$i];
484
485    if ($letters>='a' && $letters<='z')
486    {
487      // Adding 1 point to score for a lowercase
488      // ---------------------------------------
489                                $points = $points + 1;
490
491      // Adding bonus points for lowercase
492      // ---------------------------------
493                  $point_lowercase = 1;
494    }
495    else if ($letters>='A' && $letters <='Z')
496    {
497      // Adding 2 points to score for uppercase
498      // --------------------------------------
499      $points = $points + 2;
500
501      // Adding bonus points for uppercase
502      // ---------------------------------
503      $point_uppercase = 2;
504    }
505    else if ($letters>='0' && $letters<='9')
506    {
507      // Adding 3 points to score for numbers
508      // ------------------------------------
509      $points = $points + 3;
510
511      // Adding bonus points for numbers
512      // -------------------------------
513      $point_numbers = 3;
514    }
515    else
516    {
517      // Adding 5 points to score for special characters
518      // -----------------------------------------------
519      $points = $points + 5;
520               
521      // Adding bonus points for special characters
522      // ------------------------------------------
523      $point_characters = 5;
524    }
525  }
526
527  // Calculating the coefficient points/length
528  // -----------------------------------------
529  $step1 = $points / $length;
530
531  // Calculation of the diversity of character types...
532  // --------------------------------------------------
533  $step2 = $point_lowercase + $point_uppercase + $point_numbers + $point_characters;
534
535  // Multiplying the coefficient of diversity with that of the length
536  // ----------------------------------------------------------------
537  $score = $step1 * $step2;
538
539  // Multiplying the result by the length of the string
540  // --------------------------------------------------
541  $finalscore = $score * $length;
542
543  return $finalscore;
544}
545
546
547/**
548 * PP_UsrBlock_Verif
549 * Check if the user's account is locked
550 *
551 * @returns : True if account is locked else False
552 */
553function PP_UsrBlock_Verif($username)
554{
555  global $conf;
556
557  $query = '
558SELECT PP_Lock
559FROM '.USERS_TABLE.'
560WHERE username = "'.stripslashes($username).'"
561;';
562
563  $result = pwg_db_fetch_assoc(pwg_query($query));
564
565  if($result['PP_Lock'] == 'true')
566  {
567    return true;
568  }
569  else return false;
570}
571
572
573/**
574 * PP_unlock_user
575 * Action in user_list to unlock a user
576 */
577function PP_unlock_user($uid)
578{
579  // Reset PP_loginfailcount value to 0
580  $query ='
581UPDATE '.USERS_TABLE.'
582SET PP_loginfailcount = 0
583WHERE id = '.$uid.'
584LIMIT 1
585;';
586
587  pwg_query($query);
588 
589  // Set account as unlocked
590  $query ='
591UPDATE '.USERS_TABLE.'
592SET PP_lock = "false"
593WHERE id = '.$uid.'
594LIMIT 1
595;';
596
597  pwg_query($query);
598}
599
600
601/**
602 * Function called from PP_admin.php to get the plugin version and name
603 *
604 * @param : plugin directory
605 *
606 * @return : plugin's version and name
607 *
608 */
609function PPInfos($dir)
610{
611  $path = $dir;
612
613  $plg_data = implode( '', file($path.'main.inc.php') );
614  if ( preg_match("|Plugin Name: (.*)|", $plg_data, $val) )
615  {
616    $plugin['name'] = trim( $val[1] );
617  }
618  if (preg_match("|Version: (.*)|", $plg_data, $val))
619  {
620    $plugin['version'] = trim($val[1]);
621  }
622  if ( preg_match("|Plugin URI: (.*)|", $plg_data, $val) )
623  {
624    $plugin['uri'] = trim($val[1]);
625  }
626  if ($desc = load_language('description.txt', $path.'/', array('return' => true)))
627  {
628    $plugin['description'] = trim($desc);
629  }
630  elseif ( preg_match("|Description: (.*)|", $plg_data, $val) )
631  {
632    $plugin['description'] = trim($val[1]);
633  }
634  if ( preg_match("|Author: (.*)|", $plg_data, $val) )
635  {
636    $plugin['author'] = trim($val[1]);
637  }
638  if ( preg_match("|Author URI: (.*)|", $plg_data, $val) )
639  {
640    $plugin['author uri'] = trim($val[1]);
641  }
642  if (!empty($plugin['uri']) and strpos($plugin['uri'] , 'extension_view.php?eid='))
643  {
644    list( , $extension) = explode('extension_view.php?eid=', $plugin['uri']);
645    if (is_numeric($extension)) $plugin['extension'] = $extension;
646  }
647// IMPORTANT SECURITY !
648// --------------------
649  $plugin = array_map('htmlspecialchars', $plugin);
650
651  return $plugin ;
652}
653
654
655/**
656 * Useful for debugging - 4 vars can be set
657 * Output result to log.txt file
658 *
659 */
660function PPLog($var1, $var2, $var3, $var4)
661{
662   $fo=fopen (PP_PATH.'log.txt','a') ;
663   fwrite($fo,"======================\n") ;
664   fwrite($fo,'le ' . date('D, d M Y H:i:s') . "\r\n");
665   fwrite($fo,$var1 ."\r\n") ;
666   fwrite($fo,$var2 ."\r\n") ;
667   fwrite($fo,$var3 ."\r\n") ;
668   fwrite($fo,$var4 ."\r\n") ;
669   fclose($fo) ;
670}
671?>
Note: See TracBrowser for help on using the repository browser.