|
@@ -1,11 +1,14 @@
|
|
<?php
|
|
<?php
|
|
|
|
+umask(0077);
|
|
const ROOT_PATH = __DIR__;
|
|
const ROOT_PATH = __DIR__;
|
|
define('CONF', parse_ini_file(ROOT_PATH . '/config.ini', true, INI_SCANNER_TYPED));
|
|
define('CONF', parse_ini_file(ROOT_PATH . '/config.ini', true, INI_SCANNER_TYPED));
|
|
|
|
|
|
const SFTP = '/usr/bin/sftp';
|
|
const SFTP = '/usr/bin/sftp';
|
|
const SSHPASS = '/usr/bin/sshpass';
|
|
const SSHPASS = '/usr/bin/sshpass';
|
|
|
|
|
|
-const URL = 'https://servnest.test:42443';
|
|
|
|
|
|
+const HTTPS_PORT = '42443';
|
|
|
|
+const CORE_DOMAIN = 'servnest.test';
|
|
|
|
+const CORE_URL = 'https://' . CORE_DOMAIN . ':' . HTTPS_PORT;
|
|
const SUFFIX = 'test.servnest.test.';
|
|
const SUFFIX = 'test.servnest.test.';
|
|
|
|
|
|
const TOR_PROXY = 'socks5h://127.0.0.1:9050';
|
|
const TOR_PROXY = 'socks5h://127.0.0.1:9050';
|
|
@@ -20,38 +23,42 @@ if (CONF['common']['services']['ns'] === 'rest') {
|
|
echo 'a';
|
|
echo 'a';
|
|
}
|
|
}
|
|
|
|
|
|
-const COMMON_OPT = [
|
|
|
|
- CURLOPT_POST => true,
|
|
|
|
- CURLOPT_SSL_VERIFYPEER => false,
|
|
|
|
- CURLOPT_SSL_VERIFYHOST => 0,
|
|
|
|
- CURLOPT_RETURNTRANSFER => true,
|
|
|
|
- CURLOPT_HEADER => true,
|
|
|
|
- CURLOPT_HTTPHEADER => [
|
|
|
|
- 'Sec-Fetch-Site: none',
|
|
|
|
- ],
|
|
|
|
-];
|
|
|
|
|
|
+define('COOKIE_FILE', sys_get_temp_dir() . '/cookie-' . bin2hex(random_bytes(16)) . '.txt');
|
|
|
|
|
|
-define('COOKIE_FILE', sys_get_temp_dir() . '/cookie-' . random_bytes(16) . '.txt');
|
|
|
|
-
|
|
|
|
-function curlTest($path, $args) {
|
|
|
|
|
|
+function curlTest($address, $post = [], $tor = false) {
|
|
$req = curl_init();
|
|
$req = curl_init();
|
|
- curl_setopt_array($req, COMMON_OPT);
|
|
|
|
- curl_setopt_array($req, [
|
|
|
|
- CURLOPT_URL => URL . $path,
|
|
|
|
- CURLOPT_COOKIEFILE => COOKIE_FILE,
|
|
|
|
- CURLOPT_COOKIEJAR => COOKIE_FILE,
|
|
|
|
- CURLOPT_POSTFIELDS => $args,
|
|
|
|
- ]);
|
|
|
|
|
|
+ curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
+
|
|
|
|
+ if (str_starts_with($address, '/'))
|
|
|
|
+ curl_setopt_array($req, [
|
|
|
|
+ CURLOPT_POST => true,
|
|
|
|
+ CURLOPT_HEADER => true,
|
|
|
|
+ CURLOPT_HTTPHEADER => [
|
|
|
|
+ 'Sec-Fetch-Site: none',
|
|
|
|
+ ],
|
|
|
|
+ CURLOPT_URL => CORE_URL . $address,
|
|
|
|
+ CURLOPT_COOKIEFILE => COOKIE_FILE,
|
|
|
|
+ CURLOPT_COOKIEJAR => COOKIE_FILE,
|
|
|
|
+ CURLOPT_POSTFIELDS => $post,
|
|
|
|
+ ]);
|
|
|
|
+ else
|
|
|
|
+ curl_setopt($req, CURLOPT_URL, $address);
|
|
|
|
+
|
|
|
|
+ if ($tor)
|
|
|
|
+ curl_setopt($req, CURLOPT_PROXY, TOR_PROXY);
|
|
|
|
+ else
|
|
|
|
+ curl_setopt($req, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
|
+
|
|
|
|
+ $result = curl_exec($req);
|
|
$status_code = curl_getinfo($req, CURLINFO_RESPONSE_CODE);
|
|
$status_code = curl_getinfo($req, CURLINFO_RESPONSE_CODE);
|
|
- if ($status_code >= 400) {
|
|
|
|
|
|
+ if ($status_code >= 400 OR $result === false) {
|
|
var_dump(curl_exec($req));
|
|
var_dump(curl_exec($req));
|
|
- exit($path . ' test failed with status code ' . $status_code . LF);
|
|
|
|
|
|
+ var_dump(curl_error($req));
|
|
|
|
+ exit($address . ' test failed with status code ' . $status_code . LF);
|
|
}
|
|
}
|
|
- return curl_exec($req);
|
|
|
|
|
|
+ return $result;
|
|
}
|
|
}
|
|
|
|
|
|
-// AUTH TEST
|
|
|
|
-
|
|
|
|
$username = 'check-' . bin2hex(random_bytes(16));
|
|
$username = 'check-' . bin2hex(random_bytes(16));
|
|
$password = bin2hex(random_bytes(16));
|
|
$password = bin2hex(random_bytes(16));
|
|
|
|
|
|
@@ -78,7 +85,6 @@ curlTest('/auth/username', [
|
|
'current-password' => $password,
|
|
'current-password' => $password,
|
|
'new-username' => $username . '2',
|
|
'new-username' => $username . '2',
|
|
]);
|
|
]);
|
|
-
|
|
|
|
curlTest('/auth/username', [
|
|
curlTest('/auth/username', [
|
|
'current-password' => $password,
|
|
'current-password' => $password,
|
|
'new-username' => $username,
|
|
'new-username' => $username,
|
|
@@ -86,68 +92,149 @@ curlTest('/auth/username', [
|
|
|
|
|
|
echo 'Created account with username "' . $username . '" and password "' . $password . '".' . LF;
|
|
echo 'Created account with username "' . $username . '" and password "' . $password . '".' . LF;
|
|
|
|
|
|
-// REG TEST
|
|
|
|
|
|
+function testReg() {
|
|
|
|
+ $subdomain = bin2hex(random_bytes(16));
|
|
|
|
|
|
-$subdomain = bin2hex(random_bytes(16));
|
|
|
|
-var_dump($subdomain);
|
|
|
|
-curlTest('/reg/register', [
|
|
|
|
- 'subdomain' => $subdomain,
|
|
|
|
- 'suffix' => SUFFIX,
|
|
|
|
- 'action' => 'register',
|
|
|
|
-]);
|
|
|
|
|
|
+ curlTest('/reg/register', [
|
|
|
|
+ 'subdomain' => $subdomain,
|
|
|
|
+ 'suffix' => SUFFIX,
|
|
|
|
+ 'action' => 'register',
|
|
|
|
+ ]);
|
|
|
|
|
|
-curlTest('/reg/ns', [
|
|
|
|
- 'action' => 'add',
|
|
|
|
- 'domain' => $subdomain . '.' . SUFFIX,
|
|
|
|
- 'ns' => 'ns1.servnest.invalid.',
|
|
|
|
-]);
|
|
|
|
|
|
+ $domain = $subdomain . '.' . SUFFIX;
|
|
|
|
|
|
-exec(CONF['dns']['kdig_path'] . ' @' . CONF['reg']['address'] . ' ' . $subdomain . '.' . SUFFIX . ' NS', $output2, $return_code);
|
|
|
|
-if (preg_match('/[ \t]+ns1.servnest.invalid.$/Dm', implode(LF, $output2)) !== 1)
|
|
|
|
- exit('Error: /reg/ns: NS record not set');
|
|
|
|
|
|
+ curlTest('/reg/ns', [
|
|
|
|
+ 'action' => 'add',
|
|
|
|
+ 'domain' => $domain,
|
|
|
|
+ 'ns' => 'ns1.servnest.invalid.',
|
|
|
|
+ ]);
|
|
|
|
+ exec(CONF['dns']['kdig_path'] . ' @' . CONF['reg']['address'] . ' ' . $domain . ' NS', $output);
|
|
|
|
+ if (preg_match('/[ \t]+ns1\.servnest\.invalid\.$/Dm', implode(LF, $output)) !== 1)
|
|
|
|
+ exit('Error: /reg/ns: NS record not set' . LF);
|
|
|
|
+
|
|
|
|
+ curlTest('/reg/ns', [
|
|
|
|
+ 'action' => 'delete',
|
|
|
|
+ 'domain' => $domain,
|
|
|
|
+ 'ns' => 'ns1.servnest.invalid.',
|
|
|
|
+ ]);
|
|
|
|
|
|
-// HT TEST
|
|
|
|
|
|
+ return $domain;
|
|
|
|
+}
|
|
|
|
|
|
-curlTest('/ht/', []);
|
|
|
|
|
|
+function testNs($domain) {
|
|
|
|
+ foreach (CONF['ns']['servers'] as $ns)
|
|
|
|
+ curlTest('/reg/ns', [
|
|
|
|
+ 'action' => 'add',
|
|
|
|
+ 'domain' => $domain,
|
|
|
|
+ 'ns' => $ns,
|
|
|
|
+ ]);
|
|
|
|
+
|
|
|
|
+ preg_match('#\<code\>(?<token>[0-9a-z-]{16,128}\._domain-verification\.' . preg_quote(CORE_DOMAIN) . '\.)\</code\>#', curlTest('/ns/zone-add', []), $matches);
|
|
|
|
+ curlTest('/reg/ns', [
|
|
|
|
+ 'action' => 'add',
|
|
|
|
+ 'domain' => $domain,
|
|
|
|
+ 'ns' => $matches['token'],
|
|
|
|
+ ]);
|
|
|
|
|
|
-define('TEST_CONTENT', 'test-' . random_bytes(4));
|
|
|
|
|
|
+ curlTest('/ns/zone-add', [
|
|
|
|
+ 'domain' => $domain,
|
|
|
|
+ ]);
|
|
|
|
|
|
-file_put_contents(sys_get_temp_dir() . '/index.html', TEST_CONTENT);
|
|
|
|
|
|
+ curlTest('/reg/ns', [
|
|
|
|
+ 'action' => 'delete',
|
|
|
|
+ 'domain' => $domain,
|
|
|
|
+ 'ns' => $matches['token'],
|
|
|
|
+ ]);
|
|
|
|
|
|
-file_put_contents(sys_get_temp_dir() . '/exec.txt', 'mkdir /_site0-
|
|
|
|
|
|
+ curlTest('/ns/caa', [
|
|
|
|
+ 'action' => 'add',
|
|
|
|
+ 'subdomain' => '@',
|
|
|
|
+ 'zone' => $domain,
|
|
|
|
+ 'ttl-value' => '2',
|
|
|
|
+ 'ttl-multiplier' => '3600',
|
|
|
|
+ 'flag' => '0',
|
|
|
|
+ 'tag' => 'issue',
|
|
|
|
+ 'value' => 'letsencrypt.org',
|
|
|
|
+ ]);
|
|
|
|
+ exec(CONF['dns']['kdig_path'] . ' @' . CONF['reg']['address'] . ' ' . $domain . ' CAA', $output);
|
|
|
|
+ if (preg_match('/^' . preg_quote($domain) . '[ \t]+7200[ \t]+IN[ \t]+CAA[ \t]+0[ \t]+issue[ \t]+"letsencrypt\.org"$/Dm', implode(LF, $output)) !== 1)
|
|
|
|
+ exit('Error: /ns/caa: CAA record not set' . LF);
|
|
|
|
+
|
|
|
|
+ curlTest('/ns/edit', [
|
|
|
|
+ 'zone' => $domain,
|
|
|
|
+ 'zone-content' => 'aaaa.' . $domain . ' 3600 AAAA ' . CONF['ht']['ipv6_address'] . "\r\n"
|
|
|
|
+ . '@ 86400 NS ' . CONF['ns']['servers'][0] . "\r\n",
|
|
|
|
+ ]);
|
|
|
|
+ exec(CONF['dns']['kdig_path'] . ' @' . CONF['reg']['address'] . ' aaaa.' . $domain . ' AAAA', $output);
|
|
|
|
+ if (preg_match('/[ \t]+' . preg_quote(CONF['ht']['ipv6_address']) . '$/Dm', implode(LF, $output)) !== 1)
|
|
|
|
+ exit('Error: /ns/edit: AAAA record not set' . LF);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function testHt($username, $password) {
|
|
|
|
+ curlTest('/ht/', []);
|
|
|
|
+
|
|
|
|
+ define('TEST_CONTENT', 'test-' . random_bytes(4));
|
|
|
|
+
|
|
|
|
+ file_put_contents(sys_get_temp_dir() . '/index.html', TEST_CONTENT);
|
|
|
|
+
|
|
|
|
+ file_put_contents(sys_get_temp_dir() . '/exec.txt', 'mkdir /_site0-
|
|
put ' . sys_get_temp_dir() . '/index.html /_site0-/index.html
|
|
put ' . sys_get_temp_dir() . '/index.html /_site0-/index.html
|
|
exit
|
|
exit
|
|
');
|
|
');
|
|
|
|
|
|
-$process = proc_open(SSHPASS . ' ' . SFTP . ' -o BatchMode=no -b ' . sys_get_temp_dir() . '/exec.txt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P ' . CONF['ht']['public_sftp_port'] . ' ' . $username . '@' . CONF['ht']['sftp_domain'], [0 => ['pipe', 'r']], $pipes);
|
|
|
|
-if (is_resource($process) !== true)
|
|
|
|
- exit('Can\'t spawn sftp with sshpass.');
|
|
|
|
-fwrite($pipes[0], $password);
|
|
|
|
-fclose($pipes[0]);
|
|
|
|
-if (proc_close($process) !== 0)
|
|
|
|
- exit('File not sent successfully.');
|
|
|
|
|
|
+ $process = proc_open(SSHPASS . ' ' . SFTP . ' -o BatchMode=no -b ' . sys_get_temp_dir() . '/exec.txt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P ' . CONF['ht']['public_sftp_port'] . ' ' . $username . '@' . CONF['ht']['sftp_domain'], [0 => ['pipe', 'r']], $pipes);
|
|
|
|
+ if (is_resource($process) !== true)
|
|
|
|
+ exit('Can\'t spawn sftp with sshpass.' . LF);
|
|
|
|
+ fwrite($pipes[0], $password);
|
|
|
|
+ fclose($pipes[0]);
|
|
|
|
+ if (proc_close($process) !== 0)
|
|
|
|
+ exit('File not sent successfully.' . LF);
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ $ht_subpath = bin2hex(random_bytes(16));
|
|
|
|
+ curlTest('/ht/add-subpath', [
|
|
|
|
+ 'path' => $ht_subpath,
|
|
|
|
+ 'dir' => '_site0-',
|
|
|
|
+ ]);
|
|
|
|
+ if (curlTest('https://' . CONF['ht']['subpath_domain'] . ':' . HTTPS_PORT . '/' . $ht_subpath . '/') !== TEST_CONTENT)
|
|
|
|
+ exit('Unexpected subpath response' . LF);
|
|
|
|
+ curlTest('/ht/del', [
|
|
|
|
+ 'site' => 'subpath:' . $ht_subpath,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
|
|
-$html = curlTest('/ht/add-onion', [
|
|
|
|
- 'dir' => '_site0-'
|
|
|
|
-]);
|
|
|
|
-if (preg_match('#\<code\>http\://(?<onion>[0-9a-z]{56})\.onion/\</code\>#D', $html, $matches) !== 1)
|
|
|
|
- exit('Can\'t find onion address.');
|
|
|
|
|
|
+ {
|
|
|
|
+ $ht_subdomain = 'test3';
|
|
|
|
+ curlTest('/ht/add-subdomain', [
|
|
|
|
+ 'subdomain' => $ht_subdomain,
|
|
|
|
+ 'dir' => '_site0-',
|
|
|
|
+ ]);
|
|
|
|
+ if (curlTest('https://' . $ht_subdomain . '.' . CONF['ht']['subpath_domain'] . ':' . HTTPS_PORT . '/') !== TEST_CONTENT)
|
|
|
|
+ exit('Unexpected subpath response' . LF);
|
|
|
|
+ curlTest('/ht/del', [
|
|
|
|
+ 'site' => 'subdomain:' . $ht_subdomain,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
|
|
-sleep(10);
|
|
|
|
|
|
+ {
|
|
|
|
+ $html = curlTest('/ht/add-onion', [
|
|
|
|
+ 'dir' => '_site0-',
|
|
|
|
+ ]);
|
|
|
|
+ if (preg_match('#\<code\>http\://(?<onion>[0-9a-z]{56})\.onion/\</code\>#D', $html, $matches) !== 1)
|
|
|
|
+ exit('Can\'t find onion address.' . LF);
|
|
|
|
+ sleep(5);
|
|
|
|
+ if (curlTest('http://' . $matches['onion'] . '.onion/', tor: true) !== TEST_CONTENT)
|
|
|
|
+ exit('Unexpected onion service response (' . $matches['onion'] . '.onion)' . LF);
|
|
|
|
+ curlTest('/ht/del', [
|
|
|
|
+ 'site' => 'onion:' . $matches['onion'] . '.onion',
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
|
|
-$req = curl_init();
|
|
|
|
-curl_setopt_array($req, [
|
|
|
|
- CURLOPT_PROXY => TOR_PROXY,
|
|
|
|
- CURLOPT_URL => 'http://' . $matches['onion'] . '.onion/',
|
|
|
|
- CURLOPT_RETURNTRANSFER => true,
|
|
|
|
-]);
|
|
|
|
-var_dump(curl_error($req));
|
|
|
|
-if (curl_exec($req) !== TEST_CONTENT) {
|
|
|
|
- var_dump(curl_exec($req));
|
|
|
|
- exit('Unexpected onion service response (status:' . $status_code . ') (' . $matches['onion'] . '.onion)' . LF);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-// STOP
|
|
|
|
|
|
+$domain = testReg();
|
|
|
|
+testNs($domain);
|
|
|
|
+testHt($username, $password);
|
|
|
|
|
|
curlTest('/auth/unregister', [
|
|
curlTest('/auth/unregister', [
|
|
'current-password' => $password,
|
|
'current-password' => $password,
|