<?php error_reporting(E_ALL | E_STRICT); ini_set("track_errors", "On"); $test_normal = TRUE; $INC = dirname(__FILE__) . "/../inc"; require_once(dirname(__FILE__) . "/config.php"); require_once($INC . "/init.inc.php"); require_once($INC . "/user.inc.php"); require_once("helpers.inc.php"); require_once("http.inc.php"); rg_log_set_file("ssh.log"); require_once("common.php"); $_testns = 'ssh'; prepare_http(); // This test makes sense only on my devel machine if (php_uname("n") != "r1.embedromix.ro") { // TODO: start a sshd daemon? rg_log("OK!"); exit(0); } rg_log(''); rg_log_enter("Creating a user..."); rg_test_create_user($db, $rg_ui); rg_test_create_repo($db, $rg_ui, $repo); $r = test_login($test_url, $rg_ui); if ($r === FALSE) { rg_log("Cannot login!"); exit(1); } rg_log_exit(); rg_test_upload_ssh_key($db, $rg_ui, 'ssh', $kn); rg_log(''); rg_log_enter('Testing ssh help...'); $list = array('', 'status', 'repos', 'repo', 'totp'); foreach ($list as $s) { rg_log('Connecting for [' . $s . ']'); $r = test_ssh($rg_ui['uid'], $s); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['stderr'], "Welcome to RocketGit")) { rg_log_ml('stderr: ' . $r['stderr']); rg_log("Trying to get the help detected missing welcome!"); exit(1); } } rg_log_exit(); rg_log(''); rg_log_enter('Testing ssh help for totp commands...'); $list = array('remove-device', 'unenroll'); foreach ($list as $s) { rg_log('Connecting for [totp ' . $s . ']'); $r = test_ssh($rg_ui['uid'], ' totp ' . $s); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } } rg_log_exit(); rg_log(''); rg_log_enter('Testing wrong command'); $r = test_ssh($rg_ui['uid'], ' wrongcmd'); if ($r['ok'] != 0) { rg_log_ml('error: ' . $r['stderr']); rg_log('We should receive error code 0 not ' . $r['ok'] . '!'); exit(1); } if (!strstr($r['stderr'], "nknown command")) { rg_log('stderr: ' . $r['stderr']); rg_log("Wrong answer for a wrong command!"); exit(1); } rg_log_exit(); rg_log(''); rg_log('Testing enroll procedure'); $r = test_ssh($rg_ui['uid'], ' totp enroll', '', FALSE, FALSE); $t = explode('enter the following code: ', $r['data']); $t = explode('.', $t[1]); $key = trim($t[0]); rg_log("key=$key"); $tc = intval(time() / 30) - 1; // we try one in the past $token = rg_totp_compute($key, $tc, 6); $r = test_ssh($rg_ui['uid'], ' totp enroll ' . $token); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], 'Success!')) { rg_log('data: ' . $r['data']); rg_log('Cannot enroll!'); exit(1); } rg_log(''); rg_log('Testing \'val\' command'); $tc = intval(time() / 30); $token = rg_totp_compute($key, $tc, 6); $r = test_ssh($rg_ui['uid'], ' totp val ' . $token . ' 2m'); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], 'Success!')) { rg_log('data: ' . $r['data']); rg_log('Cannot validate ip!'); exit(1); } $t = explode('valid till ', $r['data']); $t = explode(' (', $t[1]); $exp = trim($t[0]); rg_log('exp=' . $exp); rg_log(''); rg_log('Reuse of the token must be forbidden (device)'); $r = test_ssh($rg_ui['uid'], ' totp val ' . $token . ' 2m'); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['stderr'], 'cannot reuse')) { rg_log('stderr: ' . $r['data']); rg_log('we get no error on token reuse!'); exit(1); } rg_log(''); rg_log('Testing \'list-val\' command'); $r = test_ssh($rg_ui['uid'], ' totp list-val'); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], $exp)) { rg_log('data: ' . $r['data']); rg_log('Invalid output for list-val!'); exit(1); } rg_log(''); rg_log('Testing \'inval\' command - wrong ip'); $tc = intval(time() / 30) + 1; // we try one in the future $token = rg_totp_compute($key, $tc, 6); $r = test_ssh($rg_ui['uid'], ' totp inval 1.1.1.1'); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['stderr'], 'ip not found')) { rg_log('stderr: ' . $r['stderr']); rg_log('Cannot invalidate ip!'); exit(1); } rg_log(''); rg_log('Testing \'inval\' command - all'); $tc = intval(time() / 30) + 1; // we try one in the future $token = rg_totp_compute($key, $tc, 6); $r = test_ssh($rg_ui['uid'], ' totp inval all'); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], 'Success!')) { rg_log('data: ' . $r['data']); rg_log('Cannot invalidate all!'); exit(1); } rg_log(''); rg_log('Testing \'remove-device\''); $tc = intval(time() / 30) + 2; $token = rg_totp_compute($key, $tc, 6); $_cmd = ' totp remove-device ' . $token; $r = test_ssh($rg_ui['uid'], $_cmd); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], 'Success!')) { rg_log('data: ' . $r['data']); rg_log('Cannot remove device!'); exit(1); } $sc = rg_test_sc_generate($db, $rg_ui); $sql = "UPDATE scratch_codes SET sc = '0' || substring(sc from 1 for 7)" . " WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_log('Cannot do query!'); exit(1); } rg_sql_free_result($res); // we want to test with a short code, so insert one and flush cache $key = 'user::' . $rg_ui['uid'] . '::login_tokens::sc'; rg_cache_unset($key, 0); foreach ($sc as &$t) $t = substr($t, 0, 7); rg_log(''); rg_log_enter('Testing \'unenroll\' (must work)'); $token = array_pop($sc); $token = ltrim($token, '0'); $_cmd = ' totp unenroll ' . $token; $r = test_ssh($rg_ui['uid'], $_cmd); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], 'You are now unenrolled')) { rg_log('data: ' . $r['data']); rg_log('Cannot unenroll!'); exit(1); } rg_log_exit(); rg_log(''); rg_log_enter('After enroll we should not be able to use the scratch codes'); $token = array_pop($sc); $r = test_ssh($rg_ui['uid'], ' totp val ' . $token . ' 2m'); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (strstr($r['data'], 'Success!')) { rg_log('data: ' . $r['data']); rg_log('Seems we are able to use scratch codes after unenroll!'); exit(1); } rg_log_exit(); $sc = rg_test_sc_generate($db, $rg_ui); rg_log(''); rg_log_enter('sc: testing \'val\' cmd...'); $token = array_pop($sc); $_cmd = ' totp val ' . $token . ' 2m'; $r = test_ssh($rg_ui['uid'], $_cmd); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['data'], 'Success!')) { rg_log('data: ' . $r['data']); rg_log('Cannot validate ip!'); exit(1); } rg_log_exit(); rg_log(''); rg_log_enter('Reuse of the scratch code must be forbidden (sc)'); $_cmd = ' totp val ' . $token . ' 2m'; $r = test_ssh($rg_ui['uid'], $_cmd); if ($r['ok'] != 1) { rg_log_ml('error: ' . $r['stderr']); exit(1); } if (!strstr($r['stderr'], 'invalid token')) { rg_log('stderr: ' . $r['stderr']); rg_log('we get no error on token reuse!'); exit(1); } rg_log_exit(); rg_log("OK!"); ?>