<?php // // Will test the login by TOTP // error_reporting(E_ALL | E_STRICT); ini_set("track_errors", "On"); $rg_cache_debug = TRUE; $test_normal = TRUE; $INC = dirname(__FILE__) . "/../inc"; require_once(dirname(__FILE__) . "/config.php"); require_once($INC . "/init.inc.php"); require_once($INC . "/util.inc.php"); require_once("helpers.inc.php"); require_once("http.inc.php"); rg_log_set_file("http_totp.log"); require_once("common.php"); $_testns = 'http_totp'; $rg_user_max_len = 60; prepare_http(); rg_test_create_user($db, $rg_ui); // Add an totp token to this account $key = 'ACHCBCCVQ7AK4RGM'; $r = rg_totp_enroll($db, $rg_ui['uid'], 'test', $key, '127.0.0.1', 't'); if ($r !== TRUE) { rg_log('cannot enroll!'); exit(1); } // Now test the login without and with login_token $lt = rg_totp_compute($key, time() / 30, 6); // First we need to load the form so we can get the token // We provide an old cookie to test if we generate a new pre-login one rg_log(''); rg_log_enter('Loading login form...'); $r = do_req($test_url . "/op/login", $data, $headers); if ($r === FALSE) { rg_log("Cannot load login form."); exit(1); } $good_token = $r['tokens']['login']; rg_log_exit(); rg_log(''); rg_log_enter("Do the login without login token (must fail)..."); $data = array( "doit" => 1, "token" => $good_token, "user" => $rg_ui['username'], "pass" => $rg_ui['pass'], "login_token" => '', "lock_ip" => 0); $headers = array(); $r = do_req($test_url . "/op/login", $data, $headers); if ($r === FALSE) { rg_log_ml('r=' . print_r($r, TRUE)); rg_log("Cannot login!"); exit(1); } if (!strstr($r['body'], "invalid user")) { rg_log_ml('r=' . print_r($r, TRUE)); rg_log("Seems we can login without token!"); exit(1); } $good_token = $r['tokens']['login']; rg_log_exit(); rg_log(''); rg_log_enter("Do the login (token=$good_token login_token=$lt) (must work)..."); $data = array( "doit" => 1, "token" => $good_token, "user" => $rg_ui['username'], "pass" => $rg_ui['pass'], "login_token" => $lt, "lock_ip" => 0); $headers = array(); $r = do_req($test_url . "/op/login", $data, $headers); if ($r === FALSE) { rg_log_ml('r=' . print_r($r, TRUE)); rg_log("Cannot login!"); exit(1); } if (strstr($r['body'], "invalid user")) { rg_log_ml('r=' . print_r($r, TRUE)); rg_log("Login invalid!"); exit(1); } rg_log_exit(); $r = totp_enroll($db); if ($r['ok'] !== 1) exit(1); rg_log(''); rg_log_enter('Testing the deletion of scratch codes'); $sc1 = rg_test_sc_generate($db, $rg_ui); sleep(1); // to not have the same itime; TODO: we will add uids to scratch_codes table $sc2 = rg_test_sc_generate($db, $rg_ui); $sql = "SELECT DISTINCT itime FROM scratch_codes WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); $list = array(); while (($row = rg_sql_fetch_array($res))) { $list[] = $row['itime']; } rg_sql_free_result($res); rg_log_ml('list=' . print_r($list, TRUE)); $r = totp_scratch_delete($list); if ($r['ok'] !== 1) exit(1); $sql = "SELECT DISTINCT itime FROM scratch_codes WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); $rows = rg_sql_num_rows($res); rg_sql_free_result($res); if ($rows != 0) { rg_log("Cannot delete scratch codes - sql still returns data!"); exit(1); } $key = 'user::' . $rg_ui['uid'] . '::login_tokens::sc'; rg_cache_core_unset($key); // else we will get data from local mem! $r = rg_cache_get($key); if (count($r) != 0) { rg_log_ml('cache: ' . print_r($r, TRUE)); rg_log('Deleted scratch codes are still in cache!'); exit(1); } rg_log_exit(); rg_log(''); rg_log_enter('Testing the deletion of a device'); $key = 'ACHCBCCVQ7AK4RGM'; $r = rg_totp_enroll($db, $rg_ui['uid'], 'test1', $key, 'A', 't'); if ($r !== TRUE) { rg_log('cannot enroll!'); exit(1); } $key = 'ACHCBCCVQ7AK4RGX'; $r = rg_totp_enroll($db, $rg_ui['uid'], 'test2', $key, 'A', 't'); if ($r !== TRUE) { rg_log('cannot enroll!'); exit(1); } rg_log('Getting ids from database...'); $sql = "SELECT id FROM login_tokens WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); $list = array(); while (($row = rg_sql_fetch_array($res))) { $list[] = $row['id']; } rg_sql_free_result($res); if (count($list) < 2) { rg_log_ml('list: ' . print_r($list, TRUE)); rg_log('I cannot find the enrollments in database!'); exit(1); } rg_log('Loading list devices form...'); $data = array(); $r = do_req($test_url . "/op/settings/totp/list", $data, $headers); if ($r === FALSE) { rg_log("Cannot load list devices form."); exit(1); } $good_token = $r['tokens']['login_tokens_list']; $data = array( 'delete' => 1, 'token' => $good_token); foreach ($list as $id) $data['delete_list[' . $id . ']'] = 'on'; $headers = array(); $r = do_req($test_url . "/op/settings/totp/list", $data, $headers); if (!strstr($r['body'], 'success')) { rg_log("Cannot delete login tokens!"); exit(1); } $sql = "SELECT DISTINCT id FROM login_tokens WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); $rows = rg_sql_num_rows($res); rg_sql_free_result($res); if ($rows != 0) { rg_log("Cannot delete device codes - sql still returns data!"); exit(1); } $key = 'user::' . $rg_ui['uid'] . '::login_tokens::device'; rg_cache_core_unset($key); // else we will get data from local mem! $r = rg_cache_get($key); if (count($r) != 0) { rg_log_ml($key . ': ' . print_r($r, TRUE)); rg_log('Deleted device codes are still in cache!'); exit(1); } rg_log_exit(); rg_prof_log(); rg_log("OK!"); ?>