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

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

Initial release 2.5.0

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