Odyssey
lnappmiruser.i
1 <?php
2 /*
3  * Ability to log in using MIR credentials (user is not home banking user but
4  * is credit union member)
5  *
6  * The user will initially authenticate using credit union information obtained
7  * with a MIR packet. Subsequent logins will be using the password stored in
8  * the loan app system. A userlogintype of "N" is used to signify this type of
9  * user.
10  *
11  * A new unique key will be added (email, cu, userlogintype, user_name)
12  * It is unique to ensure data integrity.
13  *
14  * RULES FOR AUTHENTICATING USER
15  *
16  * There will be a challenge question cookie (machine cookie)
17  * There will be an authentciated user cookie (user cookie)
18  *
19  * Too many failed attempts need to be added to the code, with admin able to
20  * unlock
21  *
22  * 0. If in this function the user is of type "N" so don't bother checking the
23  * cuusers table.
24  *
25  * 1. Get cu code for current session, this must be known
26  *
27  * 2. Get user login id.
28  *
29  * 3. Check the existence for cu/user_name/userlogintype='N' in lnappuser
30  * a. If FOUND --
31  * 1. Verify the user password
32  * A. If found, insert lnappuser record, with cu, session_account, email
33  * userlogintype='H'
34  * B. if NOT found -- return to main screen --- user NOT found
35  * b. if NOT found
36  * 1. Gather information for MIR packet test
37  *
38  * 4. Machine Cookie Validation
39  * a. If machine cookie is found.. Validate that it is correct
40  * b. If machine cookie is NOT found OR is NOT correct
41  * 1. Set a random value from the users challenge questsions in the
42  * challenge_quest_id. This will can be done similar to how it is done
43  * already for loans
44  * 2. Show the user the question and force them to answer.
45  * A. On a correct answer, save the Machine Cookie
46  * B. On an incorrect answer, set the failedloginattempts and keep
47  * showing the same challenge question.
48  *
49  * 5. Password Validation -- after a machine cookie is set the password cookie
50  * will now need to be set
51  * a. Show a screen displaying their 'confidence' word and field to enter
52  * password
53  * 1. Upon submit validate the password.
54  * A. If SUCCESSFUL
55  * I. Create the user cookie and redirect to the Loan Application Main
56  * Screen
57  * B. If NOT Successful
58  * I. Increment the failedloginattempts by 1 for this user record in
59  * lnappuser
60  * II. Send the user back to the main entry screen with the message:
61  * 'Unable to login, password incorrect.'
62  *
63  *
64  * Validation
65  *
66  * Pieces of the User Cookie
67  *
68  * FORM VARIABLES
69  * $FORM_SHOW -- What option will this form show
70  * challenge -- show the challenge question
71  * passwd -- show the confidence/password screen
72  * validate -- show info to validate using MIR packet
73  *
74 */
75 
76  $FORM_SHOW = "";
77  $FORM_VALIDATION_ERROR = "";
78  $mem_email = "";
79 
80  // ** IMPORT FORM VALUES
81  $inputVars = array();
82  $varOk = array(
83 
84  );
85 
86  HCU_ImportVars( $inputVars, "", $varOk );
87 
88  $userEmail = FILTER_INPUT(INPUT_POST, 'val_email', FILTER_SANITIZE_EMAIL);
89  $cuserEmail = FILTER_INPUT(INPUT_POST, 'val_cemail', FILTER_SANITIZE_EMAIL);
90  $userSSN = FILTER_INPUT(INPUT_POST, 'val_ssn',FILTER_SANITIZE_STRING);
91  $userDOB = FILTER_INPUT(INPUT_POST, 'val_dob',FILTER_SANITIZE_STRING);
92  $userPhone = FILTER_INPUT(INPUT_POST, 'val_phone',FILTER_SANITIZE_STRING);
93  $form_hbuser = FILTER_INPUT(INPUT_POST, 'hbusername',FILTER_SANITIZE_STRING);
94 
95  /*
96  * 12/09/2015 - Added logic to be able to log in and not be a home banking
97  * user.
98  * Need to check if home banking user, and then a CU member (what we call
99  * Type "N")
100  */
101 
102  if(isset($_POST['applogin']) || ($miruser_cookie_user && $DMSAPP_CURRENTUSERID > 0)) {
103 
104  // * we are posting from the intro screen
105  // * validate the account(user_name) is entered
106  if (isset($form_hbuser) || $DMSAPP_CURRENTUSERID > 0 ) {
107 
108  if (isset($form_hbuser) && trim($form_hbuser) !== '') {
109  // determine if they are already a lnapp user
110  $sql = "SELECT *
111  FROM {$DB_TABLE_PREFIX}user
112  WHERE cu = '$DMSAPP_CURRENTCUCODE'
113  AND userlogintype = 'N'
114  AND session_account = '" . save_text($form_hbuser, 12) . "' ";
115  $user_rs = db_query($sql, $dbh);
116  $user_row = db_fetch_assoc($user_rs);
117 
118 
119  if ( !$user_row ) {
120  // Didn't find them in the table, so need to validate to see if they are a MIR user
121  if ( $DMSAPP_FETCHMIR ) {
122  // add an entry to the table first
123  $sql = "INSERT INTO {$DB_TABLE_PREFIX}user
124  (email, cu, failedloginattempts, challenge_quest_id, userlogintype, session_account, confidenceword)
125  VALUES
126  ('', '$DMSAPP_CURRENTCUCODE', 0, -1, 'N', '" . save_text($form_hbuser, 12) . "', '');";
127  $sth = db_query($sql,$dbh);
128 
129  // read back the entry
130  $sql = "SELECT *
131  FROM {$DB_TABLE_PREFIX}user
132  WHERE cu = '$DMSAPP_CURRENTCUCODE'
133  AND userlogintype = 'N'
134  AND session_account = '" . save_text($form_hbuser, 12) . "' ";
135  $user_rs = db_query($sql, $dbh);
136  $user_row = db_fetch_assoc($user_rs);
137 
138  } else {
139  // shouldn't be here
140  header("Location: {$self}f=intro&status=10");
141  exit;
142  }
143  }
144  } else {
145  if ( $DMSAPP_LOGINTYPE == DMSAPP_CONST_MIR_LOGIN ) {
146  // no home banking entry to check but get the user_row for later checking
147  $sql = "SELECT *
148  FROM {$DB_TABLE_PREFIX}user
149  WHERE cu = '$DMSAPP_CURRENTCUCODE'
150  AND userid = '" . intval($DMSAPP_CURRENTUSERID) . "' ";
151  $user_rs = db_query($sql, $dbh);
152  $user_row = db_fetch_assoc($user_rs);
153  } else {
154  // shouldn't be here if not a MIR login
155  header("Location: {$self}f=intro&status=999");
156  exit;
157  }
158  }
159 
160  // if we don't have a user row we have a problem
161  if ( !$user_row ) {
162  header("Location: {$self}f=intro&status=999");
163  exit;
164  }
165 
166  // now need to figure out what is next based on:
167  // 1. need to validate
168  // 2. has challenge questions selected (this should be handled through lnappusermaint)
169  // 3. has challenge answer cookie
170  if ( !$user_row["pwd"] || !$user_row["email"] ) {
171  $FORM_SHOW = "validate";
172  } else {
173  // make sure login attempts are not exceeded
174  if (intval($user_row['failedloginattempts']) >= $DMSAPP_FAILEDLOGINATTEMPTS) {
175  header("Location: {$self}f=intro&status=8");
176  exit;
177  }
178 
179  // MIR login type
180  $l_device_cookie_name = ReturnDeviceCookieName($DMSAPP_CURRENTCUCODE, DMSAPP_CONST_MIR_LOGIN, trim($user_row['email']), $user_row['userid']);
181 
182  $l_CookieVal = sha1($DMSAPP_SECRET_KEY . trim($user_row['pwd']) . trim($user_row['email']) . trim($user_row['confidenceword']) . trim($user_row['session_account']));
183 
184  if (isset($_COOKIE[$l_device_cookie_name]) && ($l_CookieVal == $_COOKIE[$l_device_cookie_name])) {
185  // ** Send to Password form, the Challenge was successful
186  $FORM_SHOW = "passwd";
187  } else {
188  //** They must first pass the Challenge question
189  $FORM_SHOW = "challenge";
190 
191  // set up some variables used below
192  $member = $user_row["session_account"];
193  $mem_email = $user_row["email"];
194 
195  // Determine if we have already selected a challenge question
196 
197  if ($user_row['challenge_quest_id'] > 0) {
198  $select_questid = $user_row['challenge_quest_id'];
199  } else {
200 
201  // ** NO PREVIOUS CHALLENGE PICK A RANDOM
202  // * First pick ONE of the multiple security questions this user
203  // * may have
204  $sql = "SELECT u_qs.*
205  FROM lnappuser_questselect as u_qs
206  JOIN {$DB_TABLE_PREFIX}user as u on u.userid = u_qs.userid
207  WHERE u.userid = " . intval($user_row['userid']) . "
208  ORDER BY RANDOM() LIMIT 1";
209  $qst_rs = db_query($sql, $dbh);
210  $qst_row = db_fetch_array($qst_rs);
211 
212  $select_questid = $qst_row['questid'];
213 
214  if (intval($select_questid) == 0) {
215  // no questions set up, so authenticate first and then get questions set up
216  $FORM_SHOW = "passwd";
217  } else {
218  // ** INSERT THE QuestID as the question that must be answered
219  $sql = "UPDATE {$DB_TABLE_PREFIX}user
220  SET challenge_quest_id = " . intval($select_questid) . "
221  WHERE userid = " . intval($user_row['userid']);
222 
223  if (!$upd_rs = db_query($sql, $dbh)) {
224  // ** UNKNOWN ERROR BACK TO INTRO
225  header("Location: {$self}f=intro&status=999");
226  exit;
227  }
228  }
229  }
230  }
231  }
232  } else {
233  // * PROBLEM -- Force back to login screen
234  header("Location: {$self}status=4&o=2");
235  exit;
236  }
237  } elseif (isset($_POST['mirconfchallenge'])) {
238  /*
239  * We should never get a user alias with a MIR user.
240  */
241  $postUsername = $form_hbuser;
242 
243  // ** They are on the challenge question and they just pressed
244  // * submit.. need to confirm if the answer is correct.
245  // * First get the challenge question
246  $sql = "SELECT *
247  FROM {$DB_TABLE_PREFIX}user
248  WHERE cu = '{$DMSAPP_CURRENTCUCODE}'
249  AND userlogintype = 'N'
250  AND session_account = '" . save_text($postUsername, 12) . "' ";
251  $user_rs = db_query($sql, $dbh);
252 
253  if ($user_row = db_fetch_assoc($user_rs)) {
254 
255  // * The challenge question
256  $sql = "SELECT *
257  FROM lnappuser_questselect
258  WHERE userid = {$user_row["userid"]}
259  AND questid = " . intval($user_row['challenge_quest_id']) . " ";
260 
261  $qst_rs = db_query($sql, $dbh);
262  $qst_row = db_fetch_assoc($qst_rs);
263  // ** NOW VALIDATE if the two options are the same
264  if (strtolower(trim($_POST['chg_resp'])) == strtolower(trim($qst_row['user_answer'])) && strtolower(trim($qst_row['user_answer'])) != '') {
265  // ** RESET THE challenge_quest_id
266  $sql = "UPDATE {$DB_TABLE_PREFIX}user
267  SET challenge_quest_id = -1
268  WHERE userid = " . intval($user_row['userid']) . " ";
269  $exec_rs = db_query($sql, $dbh);
270 
271  // ** SET COOKIE
272  $user_device_cookiename = ReturnDeviceCookieName($DMSAPP_CURRENTCUCODE, DMSAPP_CONST_MIR_LOGIN, trim($user_row['email']), $user_row['userid']);
273 
274  $setCookieVal = sha1($DMSAPP_SECRET_KEY . trim($user_row['pwd']) . trim($user_row['email']) . trim($user_row['confidenceword']) . trim($user_row['session_account']));
275 
276  $pSessionCookie = $_POST["chksecure"] != "Y";
277 
278  SetLnappDeviceCookie($HB_ENV, $user_device_cookiename, $setCookieVal, $pSessionCookie);
279  // ** Show password screen
280  $FORM_SHOW = "passwd";
281  } else {
282  // * PROBLEM -- Force WRONG ANSWER TO CHALLENGE questions -- back to login screen
283  $sql = "UPDATE {$DB_TABLE_PREFIX}user
284  SET failedloginattempts = failedloginattempts + 1
285  WHERE userid = {$user_row["userid"]}";
286 
287  if (!$exec_rs = db_query($sql, $dbh)) {
288  // * PROBLEM -- Force back to login screen -- UNKNOWN why can't insert
289  header("Location: {$self}status=999");
290  exit;
291  }
292 
293  header("Location: {$self}status=5");
294  exit;
295  }
296  } else {
297  // * PROBLEM -- Force back to login screen
298  header("Location: {$self}status=999");
299  exit;
300  }
301  } elseif (isset($_POST['hbvalidate'])) {
302  // need to validate against a MIR packet
303 
304  // make sure MIR validation is enabled
305  if ( $DMSAPP_FETCHMIR ) {
306  // validate the password
307  $mpmsg = "";
308 
309  if ($_POST['val_pwd'] <> $_POST['val_conf']) {
310  // ** PWD ERROR -- DO NOT MATCH
311  $mpmsg .= "&nbsp; The new passwords do not match<br>";
312  }
313 
314  $passwordNew = $_POST['val_pwd'];
315  $passwordConf = $_POST['val_conf'];
316 
317  if (key_exists("configPassword", $configOptions)) {
318  $pwdRules = json_decode($configOptions['configPassword'], true);
319  } else {
320  $pwdRules["len"] = 8;
321  $pwdRules["upper"] = 1;
322  $pwdRules["lower"] = 1;
323  $pwdRules["spec"] = 0;
324  $pwdRules["digit"] = 1;
325  }
326 
327  if ( strlen($passwordNew) < $pwdRules["len"] ) {
328  $mpmsg .= "&nbsp; Password is too short<br>";
329  }
330  if ( strlen($passwordNew) > 20 ) {
331  $mpmsg .= "&nbsp; Password is too long<br>";
332  }
333  $numDigitCount = 0;
334  $numUpperCharCount = 0;
335  $numLowerCharCount = 0;
336  $numSpecialCharCount = 0;
337  $passSpecial = Get_PwdSpecialCharacters();
338  $notAllowedCount = 0;
339  for ( $i = 0; $i < strlen( $passwordNew ); $i++ )
340  {
341  $ch = substr( $passwordNew, $i, 1 );
342  if ($ch >= '0' && $ch <= '9') { $numDigitCount++; }
343  else if ($ch >= 'A' && $ch <= 'Z') { $numUpperCharCount++; }
344  else if ($ch >= 'a' && $ch <= 'z') { $numLowerCharCount++; }
345  else if ( $ch != ',' && strpos( $passSpecial, $ch ) >= 0 ) { $numSpecialCharCount++; }
346  else { $notAllowedCount++; }
347  }
348  if ( $pwdRules["upper"] > 0 && $numUpperCharCount < $pwdRules["upper"] )
349  {
350  $plural = $pwdRules["upper"] > 1 ? 's' : '';
351  $mpmsg .= "&nbsp; Need at least {$pwdRules["upper"]} UPPER CASE letter$plural<br>";
352  }
353  if ( $pwdRules["lower"] > 0 && $numLowerCharCount < $pwdRules["lower"] )
354  {
355  $plural = $pwdRules["lower"] > 1 ? 's' : '';
356  $mpmsg .= "&nbsp; Need at least {$pwdRules["lower"]} lower case letter$plural<br>";
357  }
358  if ( $pwdRules["spec"] > 0 && $numSpecialCharCount < $pwdRules["spec"] )
359  {
360  $plural = $pwdRules["spec"] > 1 ? 's' : '';
361  $mbmsg .= "&nbsp; Need at least {$pwdRules["spec"]} special character$plural<br>";
362  }
363  if ( $pwdRules["digit"] > 0 && $numDigitCount < $pwdRules["digit"] )
364  {
365  $plural = $pwdRules["digit"] > 1 ? 's' : '';
366  $mpmsg .= "&nbsp; Need at least {$pwdRules["digit"]} digit$plural<br>";
367  }
368 
369  if ( $mpmsg === "" ) {
370  // validate the inputs
371  $msg = "";
372 
373  //validate if emails match
374  if (trim($userEmail) <> trim($cuserEmail)) {
375  // ** EMAIL ERROR -- DO NOT MATCH
376  $mpmsg .= "&nbsp; The emails do not match<br>";
377  }
378 
379  if (trim($form_hbuser) == "") {
380  $msg .= "&nbsp; Member number missing<br>";
381  } else if (!is_numeric($form_hbuser)) {
382  $msg .= "&nbsp; Invalid member number <br>";
383  } else {
384  $member = $form_hbuser;
385  }
386 
387  if (trim($userEmail) == "") {
388  $msg .= "&nbsp; Email missing <br>";
389  } else if (!validateEmail($userEmail)) {
390  $msg .= "&nbsp; Email appears invalid <br>";
391  }
392 
393  if (trim($userSSN) == "") {
394  $msg .= "&nbsp; Member last four SSN missing<br>";
395  } else if (!is_numeric($userSSN)) {
396  $msg .= "&nbsp; Invalid member SSN number <br>";
397  }
398 
399  if (trim($userDOB) == "") {
400  $msg .= "&nbsp; Member date of birth missing<br>";
401  } else {
402  $parts = explode( "/", $userDOB);
403  if (count($parts) != 3 || !is_numeric($parts[0]) || !is_numeric($parts[1]) || !is_numeric($parts[2]) ) {
404  $msg .= "&nbsp; Invalid member date of birth <br>";
405  }
406  }
407 
408  if (trim($userPhone) == "") {
409  $msg .= "&nbsp; Member phone missing<br>";
410  } else {
411  $parts = explode( "-", $userPhone);
412  if (count($parts) != 3 || !is_numeric($parts[0]) || !is_numeric($parts[1]) || !is_numeric($parts[2]) ) {
413  $msg .= "&nbsp; Invalid member phone number <br>";
414  }
415  }
416 
417  if ( $msg == "" ) {
418 
419  $memberData = [
420  'member' => $member,
421  'type' => 'PACKET_REQUEST_MIR'
422  ];
423  // see if the core can provide a MIR packet
424  $MIR = GetMemberInfo($HB_ENV, $memberData);
425  $statcode = $MIR["code"];
426 
427  if ($statcode == '000') {
428  # if response is 000, enter a partial entry into the lnappuser table
429  $sql1 = "select * from {$DB_TABLE_PREFIX}user
430  where cu='{$DMSAPP_CURRENTCUCODE}' and session_account ='$member'";
431  $sth = db_query($sql1,$dbh);
432 
433  if ( db_num_rows($sth) == 0 ) {
434  $sql = "INSERT INTO {$DB_TABLE_PREFIX}user
435  (email, cu, failedloginattempts, challenge_quest_id, userlogintype, session_account, confidenceword)
436  VALUES
437  ('" . save_text($userEmail, 50) . "', '$DMSAPP_CURRENTCUCODE', 0, -1,
438  'N', '" . save_text($member, 12) . "', '');";
439  $sth = db_query($sql,$dbh);
440  if ($sth) {
441  db_free_result($sth);
442  } else {
443  # something went wrong trying to update the database
444  $msg .= "&nbsp; Error Occurred updating settings.<br>";
445  # should fall through to initial screen w/ message showing
446  }
447  }
448 
449  // now validate the parameters
450  $validTests = true;
451  $validMsg = '';
452 
453  // last 4 of SSN
454  $testSSN = substr( $MIR["data"]["ssn"], -4 );
455  if ( $validTests && $testSSN != $userSSN ) {
456  $validTests = false;
457  $validMsg = 'SSN does not match.';
458  }
459 
460  // birth date - will always come back as mm/dd/yyyy; always get into yyyymmdd format)
461  // NOTE: this allows /,-,., and <space> for delimiters
462  $validDate = false;
463  if ( preg_match( "/^\\d{2}[-\/]\\d{2}[-\/]\\d{4}$/", $MIR["data"]["dob"] ) ) {
464  // mm/dd/yyyy
465  $testDateParts = explode( "/", $MIR["data"]["dob"]);
466  $testDate = $testDateParts[0] . $testDateParts[1] . $testDateParts[2];
467  $validDate = true;
468  }
469 
470  if ($validDate) {
471  // member entered date will always be mm/dd/yyyy
472  $testDOBParts = explode( "/", $userDOB );
473  $testDOB = $testDOBParts[0] . $testDOBParts[1] . $testDOBParts[2];
474  if ( $validTests && $testDOB != $testDate ) {
475  $validTests = false;
476  $validMsg = 'DOB does not match.';
477  }
478  } else {
479  $validTests = false;
480  $validMsg = 'DOB is not valid.';
481  }
482 
483  // email
484  $testEmail = trim( $MIR["data"]["email"] );
485  if ( $validTests && strcasecmp( $userEmail, $testEmail ) != 0 ) {
486  // NOTE: Not requiring email as part of validation because it is often wrong or missing on core system
487  // but we still require it because it is used for Home Banking
488  // $validTests = false;
489  }
490 
491  // custom1 = numeric portion of address - only test if exists
492  /*
493  if ( strlen( $custom1 ) > 0 ) {
494  $test4 = preg_replace("/[^0-9]/", '', $MIR["info"]["Address1"]);
495  if ( $validTests && $test4 != $custom1 ) {
496  $validTests = false;
497  }
498  }
499  */
500 
501  // home phone number (but still check cell if home phone fails) - only test if exists
502  if ( strlen( $userPhone ) > 0 ) {
503  $testPhone_1 = preg_replace("/[^0-9]/", '', $MIR["data"]["homephone"]);
504  $testPhone = preg_replace("/[^0-9]/", '', $userPhone);
505  if ( $validTests ) {
506  if ( $testPhone_1 != $testPhone ) {
507  // test the cell phone, too, just in case
508  $testPhone_2 = preg_replace("/[^0-9]/", '', $MIR["data"]["cellphone"]);
509  if ( $testPhone_2 != $testPhone ) {
510  $validTests = false;
511  $validMsg = 'Phone number does not match.';
512  }
513  }
514  }
515  }
516 
517  if ( $validTests ) {
518  // if response is 000, enter a partial entry into the lnappuser table
519  $sql1 = "select * from {$DB_TABLE_PREFIX}user
520  where cu='{$DMSAPP_CURRENTCUCODE}' and session_account ='$member'";
521  $sth = db_query($sql1,$dbh);
522 
523  // add the password
524  // $pwdCrypt = crypt( $passwordNew );
525  $pwdCrypt = password_hash($passwordNew, PASSWORD_DEFAULT);
526 
527  if ( db_num_rows($sth) == 0 ) {
528  $sql = "INSERT INTO {$DB_TABLE_PREFIX}user
529  (email, pwd, cu, failedloginattempts, challenge_quest_id, userlogintype, session_account, confidenceword)
530  VALUES
531  ('" . save_text($userEmail, 50) . "', '$pwdCrypt', '$DMSAPP_CURRENTCUCODE', 0, -1,
532  'N', '" . save_text($member, 12) . "', '');";
533  } else {
534  $sql = "UPDATE {$DB_TABLE_PREFIX}user
535  SET failedloginattempts = 0,
536  email = '" . save_text($userEmail, 50) . "',
537  pwd = '$pwdCrypt'
538  WHERE session_account = '$member' ";
539  }
540 
541  $sth = db_query($sql,$dbh);
542  if ($sth) {
543  db_free_result($sth);
544  // at this point we have authenticated and set up a password; now do the challenge questions
545  // Do this by setting up a form and submitting it so it looks like we came in from existing logic
546  $FORM_SHOW = "set_challenge";
547  } else {
548  # something went wrong trying to update the database
549  $msg .= "Error Occurred updating settings.<br>";
550  # should fall through to initial screen w/ message showing
551 
552  $FORM_SHOW = "validate";
553  }
554  } else {
555  $msg .= "&nbsp; Authentication Failed: " . $validMsg ."<br>";
556 
557  $sql = "UPDATE {$DB_TABLE_PREFIX}user
558  SET failedloginattempts = failedloginattempts + 1
559  WHERE userid = " . intval($member) . " ";
560  $sth = db_query($sql,$dbh);
561 
562  $FORM_VALIDATION_ERROR = $msg;
563  $FORM_SHOW = "validate";
564  }
565  } else {
566  // status response was something other than 101
567  $msg .= "&nbsp; Unable to activate account.<br>";
568 
569  // don't give any detailed info as to what failed
570  if ($statcode == '001') {
571  $msg .= "&nbsp; Authentication Failed.<br>";
572  }
573 
574  // fall through to print screen with error
575  // print "$sql\n";
576  $FORM_VALIDATION_ERROR = $msg;
577  $FORM_SHOW = "validate";
578  }
579  } else {
580  $FORM_VALIDATION_ERROR = $msg;
581  $FORM_SHOW = "validate";
582  }
583  } else {
584  $FORM_VALIDATION_ERROR = $mpmsg;
585  $FORM_SHOW = "validate";
586  }
587  } else {
588  // * PROBLEM -- Force back to login screen
589  header("Location: {$self}status=999");
590  exit;
591  }
592 
593  } elseif (isset($_POST['mirconfpassword'])) {
594  // first check what type of user this may be
595  $sql = "SELECT *
596  FROM {$DB_TABLE_PREFIX}user
597  WHERE cu = '{$DMSAPP_CURRENTCUCODE}'
598  AND session_account = '" . save_text($form_hbuser, 12) . "' ";
599  $user_rs = db_query($sql, $dbh);
600 
601  if ($user_row = db_fetch_assoc($user_rs)) {
602  if ( $user_row["userlogintype"] == "N" ) {
603  // ** AUTHENTICATE THE PASSWORD
604  $password = trim($_POST['hbloginpassword']);
605  $savepass = $user_row['pwd'];
606 
607  if ($savepass == crypt($password, $savepass)) {
608  // ** successful login
609 
610  // ** Update the user table
611  $sql = "UPDATE {$DB_TABLE_PREFIX}user
612  SET failedloginattempts = 0
613  WHERE userid = " . intval($user_row['userid']) . " ";
614  $exec_rs = db_query($sql, $dbh);
615 
616  // ** Create the user cookie
617  DMSAppSetCookie($HB_ENV, $user_row['userid'], DMSAPP_CONST_MIR_LOGIN);
618 
619  // see if have challenge questions or confidence word set up yet
620  if ( $user_row["confidenceword"] == "" ) {
621  // Do this by setting up a form and submitting it so it looks like we came in from existing logic
622  $FORM_SHOW = "set_challenge";
623  $member = $user_row["session_account"];
624  } else {
625  // See if the challenge questions have been set up or not
626  $sql = "SELECT count(*) as count
627  FROM lnappuser_questselect
628  WHERE userid = " . intval($user_row['userid']);
629  $qst_rs = db_query($sql, $dbh);
630  $qst_row = db_fetch_assoc($qst_rs);
631 
632  if ( !$qst_row["count"]) {
633  $FORM_SHOW = "set_challenge";
634  $member = $user_row["session_account"];
635  } else {
636  header("Location: {$self}f=portal");
637  exit;
638  }
639  }
640  } else {
641  // ** ERROR WRONG PASSWORD
642  // ** Increment failed login attempts
643 
644  $sql = "UPDATE {$DB_TABLE_PREFIX}user
645  SET failedloginattempts = failedloginattempts + 1
646  WHERE userid = " . intval($user_row['userid']) . " ";
647 
648  if (!$exec_rs = db_query($sql, $dbh)) {
649  // * PROBLEM -- Force back to login screen -- UNKNOWN why can't insert
650  header("Location: {$self}status=999");
651  exit;
652  }
653 
654  header("Location: {$self}status=6");
655  exit;
656  }
657 
658  } else {
659  // shouldn't be here if a MIR user
660  header("Location: {$self}status=999");
661  exit;
662  }
663  } else {
664  // ** Unable to find the user
665  header("Location: {$self}status=4&o=3");
666  exit;
667  }
668  }
669 
670  if (isset($form_hbuser)) {
671  $form_hbuser = disp_text($form_hbuser);
672  } elseif (isset($hb_row)) {
673  // ** if using the values from hb_row,
674  // ** use user_alias IF set, otherwise default to user_name
675  // ** this is because we need to keep the check consistent
676 
677  $form_hbuser = disp_text(($hb_row['user_alias'] != '' ? $hb_row['user_alias'] : $hb_row['session_account']));
678 
679  }
680 
681 
682  switch ($FORM_SHOW):
683  case "challenge":
684 
685  // ** First Check to see if device is NOT SET
686  $form_pwd_script = "
687  <script>
688  " . ($FORM_VALIDATION_ERROR != "" ? "$('#summary-container').css('display', 'inline-block');" : "") . "
689  </script> ";
690 
691  $sql = "SELECT *
692  FROM cuquestmaster
693  WHERE quest_lang = 'en_US'
694  AND quest_id = " . intval($select_questid) . "; ";
695  $quest_rs = db_query($sql, $dbh);
696  $quest_row = db_fetch_assoc($quest_rs);
697 
698  $challenge_quest_text = trim($quest_row['quest_text']);
699 
700 print <<< challenge_form
701  <div class="container-fluid">
702  <div class="row">
703  <div class="lnapp-form-section lnapp-summary-wrap col-xs-12 col-md-offset-3 col-md-6">
704  <div id="summary-container" class="validity-summary-container errors" >
705  <div class="alert alert-danger">
706  <p><em>You may not continue. the following errors were encountered:</em></p>
707  <ul>
708  $FORM_VALIDATION_ERROR
709  </ul>
710  </div>
711  </div>
712  </div>
713  </div>
714 
715  <form id="app_settings" name="app_settings" action="{$self}f=miruser" method="post">
716  <input type="hidden" name="form_set" value="$form_code">
717  <input type="hidden" name="loginemail" value="$mem_email">
718  <input type="hidden" name="hbusername" value="$form_hbuser">
719 
720  <div class="row">
721  <div class="col-xs-12 col-md-offset-3 col-md-6">
722 
723  <div class="alert alert-warning" role="alert">
724  <strong>We do not recognize the device you are using.</strong><br>
725  Please answer the question below to confirm your identity.
726  </div>
727 
728  <div class="panel panel-default">
729  <div class="panel-heading">
730  <h2 class="panel-title">Challenge Question</h2>
731  </div>
732  <div class="panel-body">
733  <div class="form-horizontal">
734  <div class="form-group">
735  <label class='col-xs-12' for="chg_resp">$challenge_quest_text</label>
736  <div class="col-xs-12">
737  <input id="chg_resp" class="form-control" name="chg_resp" type="text" size="30" maxlength="100" class="text-input" />
738  </div>
739  </div>
740 
741  <div class="form-group">
742  <div class="col-xs-12">
743  <div class="radio">
744  <label>
745  <input type='radio' id='chksecureY' name='chksecure' value='Y' checked/>
746  Yes, remember it
747  </label>
748  <br/>
749  <small>
750  <em>
751  For your convenience, we will not require additional authentication when you log in from this device.
752  We may occasionally require additional authentication to make sure you still want the system to recognize this device.
753  </em>
754  </small>
755  </div>
756  </div>
757  <div class="col-xs-12">
758  <div class="radio">
759  <label>
760  <input type='radio' id='chksecureN' name='chksecure' value='N' />
761  No, do not remember it
762  </label>
763  <br/>
764  <small>
765  <em>
766  We will continue to require additional authentication whenever you log in from this device.
767  </em>
768  </small>
769  </div>
770  </div>
771  </div>
772  </div>
773  </div>
774  </div>
775  </div>
776  </div>
777  <div class="row">
778  <div class="col-xs-12 col-md-offset-3 col-md-6">
779 
780  <input type="hidden" name="mirconfchallenge" value="Confirm Answer">
781  <a class="k-button k-primary" href="#" id='linkFormPost' label='Submit'><span>Confirm Answer</span></a>
782 
783 
784  </div>
785  </div>
786 
787 
788  $form_pwd_script
789  <script type="text/javascript">
790  $(document).ready(function() {
791 
792  \$('#app_settings').bind("keydown", function(event) {
793  // track enter key
794  var keycode = (event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode));
795  if (keycode == 13) { // keycode for enter key
796  // force the 'Enter Key' to implicitly click the Update button
797  \$('#app_settings').submit();
798  return false;
799  } else {
800  return true;
801  }
802  }); // end of function
803 
804  \$('#linkFormPost').click(function() {
805  \$("#app_settings").submit();
806  });
807  $('#chg_resp').focus();
808  }); // end of document ready
809  </script>
810 
811  </form>
812  </div>
813 
814 challenge_form;
815 
816  break;
817  case "validate":
818  // this path is to gather info that can be validated against a MIR packet
819 
820  // build up the password requirements message
821  if (key_exists("configPassword", $configOptions)) {
822  $pwdRules = json_decode($configOptions['configPassword'], true);
823  } else {
824  $pwdRules["len"] = 8;
825  $pwdRules["upper"] = 1;
826  $pwdRules["lower"] = 1;
827  $pwdRules["spec"] = 0;
828  $pwdRules["digit"] = 1;
829  }
830 
831  $passwordRequirements = "";
832  $passwordRequirements .= "&bull; At least {$pwdRules["len"]} characters<br>";
833  if ( $pwdRules["upper"] > 0 ) {
834  $plural = $pwdRules["upper"] > 1 ? "s" : "";
835  $passwordRequirements .= "&bull; At least {$pwdRules["upper"]} UPPER CASE character$plural<br>";
836  }
837  if ( $pwdRules["lower"] > 0 ) {
838  $plural = $pwdRules["lower"] > 1 ? "s" : "";
839  $passwordRequirements .= "&bull; At least {$pwdRules["lower"]} lower case character$plural<br>";
840  }
841  if ( $pwdRules["spec"] > 0 ) {
842  $specialCharList = Get_PwdSpecialCharacters();
843  $plural = $pwdRules["spec"] > 1 ? "s" : "";
844  $passwordRequirements .= "&bull; At least {$pwdRules["spec"]} special character$plural ($specialCharList)<br>";
845  }
846  if ( $pwdRules["digit"] > 0 ) {
847  $plural = $pwdRules["digit"] > 1 ? "s" : "";
848  $passwordRequirements .= "&bull; At least {$pwdRules["digit"]} digit$plural<br>";
849  }
850 
851  print <<< validate_form
852  <style>
853  .alert {display: inline-block; float:none}
854  .btn {display: inline-block !important; min-width: 200px !important}
855  @media only screen and (max-width: 479px) {
856  .btn {
857  width: -webkit-fill-available;
858  margin-bottom: 5px;
859  }
860  }
861  </style>
862  <div class="container-fluid">
863  <div class="row">
864  <div class="lnapp-form-section lnapp-summary-wrap col-xs-12 col-md-offset-3 col-md-6">
865  <div id="summary-container" class="validity-summary-container errors" >
866  <div class="alert alert-danger">
867  <p><em>You may not continue. the following errors were encountered:</em></p>
868  <ul>
869  $FORM_VALIDATION_ERROR
870  </ul>
871  </div>
872  </div>
873  </div>
874  </div>
875 
876  <form id="app_settings" name="app_settings" action="{$self}f=miruser" method="post">
877  <input type="hidden" name="form_set" value="$form_code">
878  <input type="hidden" name="hbusername" value="$form_hbuser">
879 
880  <div class="row">
881  <div class="col-xs-12 col-md-offset-3 col-md-6">
882  <div class="alert alert-warning" role="alert">
883  <strong>We have not found a record of you using the loan application before.</strong><br>
884  Please confirm your identity by entering the information below.
885  </div>
886 
887  <div class="panel panel-default">
888  <div class="panel-heading">
889  <h2 class="panel-title">Member Information</h2>
890  </div>
891  <div class="panel-body">
892  <div class="form-horizontal">
893  <div class="form-group">
894  <label class='col-xs-12' for="val_member">Member Account Number</label>
895  <div class="col-xs-12">
896  <input id="val_member" name="val_member" type="text" size="30" maxlength="100" class="form-control" value="$form_hbuser" disabled />
897  </div>
898  </div>
899  <div class="form-group">
900  <label class='col-xs-12' for="val_email">Email Address</label>
901  <div class="col-xs-12">
902  <input id="val_email" name="val_email" type="email" size="30" maxlength="100" class="form-control emails email k-textbox hcu-all-100"
903  value="{$userEmail}" />
904  </div>
905  </div>
906  <div class="form-group">
907  <label class='col-xs-12' for="val_cemail">Confirm Email Address</label>
908  <div class="col-xs-12">
909  <input id="val_cemail" name="val_cemail" type="email" size="30" maxlength="100" class="form-control emailconf emails k-textbox hcu-all-100" value="$cuserEmail" />
910  </div>
911  </div>
912  <div class="form-group">
913  <label class='col-xs-12' for="val_ssn">Last 4 of SSN</label>
914  <div class="col-xs-12">
915  <input id="val_ssn" name="val_ssn" type="text" size="30" maxlength="4" class="form-control k-textbox hcu-all-100"
916  value="{$userSSN}" />
917  </div>
918  </div>
919  <div class="form-group">
920  <label class='col-xs-12' for="val_dob">Birth Date</label>
921  <div class="col-xs-12">
922  <input id="val_dob" name="val_dob" type="text" size="30" maxlength="10" class="form-control k-textbox hcu-all-100"
923  value="{$userDOB}" placeholder="mm/dd/yyyy" />
924  </div>
925  </div>
926  <div class="form-group">
927  <label class='col-xs-12' for="val_phone">Home Phone</label>
928  <div class="col-xs-12">
929  <input id="val_phone" name="val_phone" type="tel" size="30" maxlength="12" class="form-control k-textbox hcu-all-100"
930  value="{$userPhone}" placeholder="555-555-5555" />
931  </div>
932  </div>
933  <div class="row">
934  <div class="col-xs-12 col-sm-6">
935  <div class="form-group">
936  <label class='col-xs-12' for="val_pwd">Password</label>
937  <div class="col-xs-12">
938  <input id="val_pwd" name="val_pwd" type="password" size="30" maxlength="20" class="form-control password passwords k-textbox hcu-all-100" value="" placeholder="Enter Password" />
939  </div>
940  </div>
941  <div class="form-group">
942  <label class='col-xs-12' for="val_conf">Confirm Password</label>
943  <div class="col-xs-12">
944  <input id="val_conf" name="val_conf" type="password" size="30" maxlength="20" class="form-control passwords passwordconf k-textbox hcu-all-100" value="" placeholder="Confirm Password" />
945  </div>
946  </div>
947  </div>
948  <div class="col-xs-12 col-sm-6">
949  <div class="alert alert-info">
950  <label class='col-xs-12' for="pwdreq"
951  style="color:red;">Password Requirements</label>
952  <div class="col-xs-12">
953  <span id="pwdreq">$passwordRequirements</span>
954  </div>
955  </div>
956  </div>
957  </div>
958  <div class="row">
959  <div class="col-xs-12 col-sm-12">
960  <input type="hidden" name="hbvalidate" value="Submit">
961  <button class="btn btn-primary" id="linkFormPost" type="submit">Confirm Membership</button>
962  <a class="btn btn-primary" href="{$self}" role="button">Back</a>
963  </div>
964  </div>
965  </div>
966  </div>
967  </div>
968  <script type="text/javascript">
969  $(document).ready(function() {
970 
971  \$('#app_settings').bind("keydown", function(event) {
972  // track enter key
973  var keycode = (event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode));
974  if (keycode == 13) { // keycode for enter key
975  // force the 'Enter Key' to implicitly click the Update button
976  \$('#app_settings').submit();
977  return false;
978  } else {
979  return true;
980  }
981  }); // end of function
982 
983 
984  $('#chg_resp').focus();
985 
986  }); // end of document ready
987  </script>
988 
989  </form>
990 
991 validate_form;
992  if ($FORM_VALIDATION_ERROR != '') {
993  print "<script language='javascript'>$('#summary-container').css('display', 'inline-block');</script>";
994  }
995 
996  break;
997  case "set_challenge":
998  ?>
999  <form id="newlogin" name="newlogin" method="post" action="<?php echo $self; ?>f=newmiruser">
1000  <input type="hidden" name="f" value="newmiruser">
1001  <input type="hidden" name="member" value="<?php echo $member ?>">
1002  </form>
1003  <script type="text/javascript">
1004  $(document).ready(function() {
1005  $('#newlogin').submit();
1006  });
1007  </script>
1008 
1009  <?php
1010  break;
1011  case "passwd":
1012 
1013  // ** First Check to see if device is NOT SET
1014  $form_pwd_script = "
1015  <script>
1016  " . ($FORM_VALIDATION_ERROR != "" ? "$('#summary-container').css('display', 'inline-block');" : "") . "
1017  </script> ";
1018 
1019  if (isset($user_row["confidenceword"])) {
1020  $confWord = "" . disp_text($user_row['confidenceword']);
1021  } else {
1022  $confWord = "&lt;Not Set&gt;";
1023  }
1024 
1025  $print_confword = "<label class='col-xs-12' for='chg_resp'>Confidence Word:</label><div class='col-xs-12'><input id='chg_resp' class='form-control' name='chg_resp' type='text' size='30' maxlength='100' class='text-input' value='$confWord' disabled/></div>";
1026 
1027  print <<< password_form
1028 
1029  <div class="container-fluid">
1030  <div class="row">
1031  <div class="lnapp-form-section lnapp-summary-wrap col-xs-12 col-md-offset-3 col-md-6">
1032  <div id="summary-container" class="validity-summary-container errors" >
1033  <div class="alert alert-danger">
1034  <p><em>You may not continue. the following errors were encountered:</em></p>
1035  <ul>
1036  $FORM_VALIDATION_ERROR
1037  </ul>
1038  </div>
1039  </div>
1040  </div>
1041  </div>
1042 
1043  <form id="app_settings" name="app_settings" action="{$self}f=miruser" method="post">
1044  <input type="hidden" name="form_set" value="miruser">
1045 
1046  <div class="row">
1047  <div class="col-xs-12 col-md-offset-3 col-md-6">
1048 
1049  <div class="panel panel-default">
1050  <div class="panel-heading">
1051  <h2 class="panel-title">Enter Password</h2>
1052  </div>
1053 
1054  <div class="panel-body">
1055  <div class="form-horizontal">
1056  <div class="form-group">
1057  $print_confword
1058  </div>
1059  <div class="form-group">
1060  <label class='col-xs-12' for="hbloginpassword">Password:</label>
1061  <div class="col-xs-12">
1062  <input id="hbloginpassword" name="hbloginpassword" type="password" size="30" maxlength="100" class="form-control"/>
1063  </div>
1064  </div>
1065 
1066  <div class="row">
1067  <div class="col-xs-12 col-sm-6">
1068  <input type="hidden" name="mirconfpassword" value="Login">
1069  <input type="hidden" name="hbusername" value="$form_hbuser">
1070  <a class="k-button k-primary" href="#" id='linkFormPost' label='Submit'><span>Login</span></a>
1071  </div>
1072  </div>
1073 
1074  $form_pwd_script
1075  <script type="text/javascript">
1076  $(document).ready(function() {
1077 
1078  \$('#app_settings').bind("keydown", function(event) {
1079  // track enter key
1080  var keycode = (event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode));
1081  if (keycode == 13) { // keycode for enter key
1082  // force the 'Enter Key' to implicitly click the Update button
1083  \$('#app_settings').submit();
1084  return false;
1085  } else {
1086  return true;
1087  }
1088  }); // end of function
1089 
1090  \$('#linkFormPost').click(function() {
1091  \$("#app_settings").submit();
1092  });
1093 
1094  $('#hbloginpassword').focus();
1095  }); // end of document ready
1096  </script>
1097 
1098  </div>
1099  </div>
1100  </div>
1101  </div>
1102  </div>
1103  </form>
1104 
1105 password_form;
1106  if ($FORM_VALIDATION_ERROR != '') {
1107  print "<script language='javascript'>$('#summary-container').css('display', 'inline-block');</script>";
1108  }
1109 
1110 
1111  break;
1112  endswitch;
1113 ?>
1114 
1115 <script type="text/javascript">
1116 
1117  $.validity.setup({ outputMode:"summary" });
1118  $.validity.setup({ defaultFieldName:"This Field" });
1119 
1120  $(function() {
1121 
1122  $("#app_settings").validity(function() {
1123 
1124  $('input.email')
1125  .require('Email is required')
1126  .match('email', '#{field} must be formatted as an email.')
1127 
1128  $('input.emailconf')
1129  .require('Email confirmation is required')
1130  .match('email', '#{field} must be formatted as an email.')
1131 
1132  $('input.emails')
1133  .equal("Email fields do not match.");
1134 
1135  $('input.password')
1136  .require('Password is required');
1137 
1138  $('input.passwordconf')
1139  .require('Password confirmation is required');
1140 
1141  $('input.passwords')
1142  .equal("Password fields do not match.");
1143 
1144  // check the password requirements
1145  var newPassword = $("#val_pwd").val();
1146  $("#val_pwd").minLength(<?php echo $pwdRules["len"] ?>, "Password too short.");
1147  if ( <?php echo $pwdRules["digit"] ?> > 0 ) {
1148  var test = newPassword;
1149  if ( test.replace(/[^0-9]/g,"").length < <?php echo $pwdRules["digit"] ?> ) {
1150  $("#val_pwd").assert(false, "Not enough digits in password.");
1151  }
1152  }
1153 
1154  if ( <?php echo $pwdRules["upper"] ?> > 0 ) {
1155  var test = newPassword;
1156  if ( test.replace(/[^A-Z]/g,"").length < <?php echo $pwdRules["upper"] ?> ) {
1157  $("#val_pwd").assert(false, "Not enough upper-case characters in password.");
1158  }
1159  }
1160 
1161  if ( <?php echo $pwdRules["lower"] ?> > 0 ) {
1162  var test = newPassword;
1163  if ( test.replace(/[^a-z]/g,"").length < <?php echo $pwdRules["lower"] ?> ) {
1164  $("#val_pwd").assert(false, "Not enough lower-case characters in password.");
1165  }
1166  }
1167 
1168  $('input#val_ssn')
1169  .require('Last 4 of SSN is required')
1170  .match('number', 'Last 4 of SSN must be a number.');
1171 
1172  $('input#val_dob')
1173  .require('DOB is required')
1174  .match('date', 'DOB must be formatted as an mm/dd/yyyy.');
1175 
1176  $('input#val_phone')
1177  .require('Phone number is required')
1178  .match(/^[1-9]\d{2}-\d{3}-\d{4}$/, 'Phone number must be formatted as 555-555-5555.');
1179 
1180  });
1181 
1182  <?php print ($FORM_VALIDATION_ERROR != "" ? "$('#summary-container').css('display', 'inline-block');" : ""); ?>
1183 
1184  });
1185 </script>