#include <sys/stat.h>
#include <atf-c.h>
#include <fcntl.h>
#include <pkg.h>
#include <private/pkg.h>
#include <stdlib.h>
#include <xmalloc.h>
ATF_TC_WITHOUT_HEAD(badcommand);
ATF_TC_WITHOUT_HEAD(badrestrict);
ATF_TC_WITHOUT_HEAD(getfile);
ATF_TC_WITHOUT_HEAD(notrestricted);
ATF_TC_WITHOUT_HEAD(restricted);
ATF_TC_BODY(badcommand, tc)
{
char strout[] =
"ok: pkg " PKGVERSION "\n"
"ko: unknown command 'plop'\n";
char *cwd = getcwd(NULL, 0);
int rootfd = open(cwd, O_DIRECTORY);
free(cwd);
int stdin_pipe[2];
ATF_REQUIRE(pipe(stdin_pipe) >= 0);
pid_t p = atf_utils_fork();
if (p == 0) {
close(STDIN_FILENO);
dup2(stdin_pipe[0], STDIN_FILENO);
close(stdin_pipe[1]);
exit(pkg_sshserve(rootfd));
}
close(stdin_pipe[0]);
dprintf(stdin_pipe[1], "plop\n");
dprintf(stdin_pipe[1], "quit\n");
atf_utils_wait(p, 0, strout, "");
}
ATF_TC_BODY(getfile, tc)
{
extern ucl_object_t *config;
struct stat st;
char strout[] =
"ok: pkg " PKGVERSION "\n"
"ko: bad command get, expecting 'get file age'\n"
"ko: bad command get, expecting 'get file age'\n"
"ok: 12\n"
"testcontent\n"
"ok: 0\n"
"ko: bad number plop: invalid\n"
"ko: file not found\n"
"ko: not a file\n"
"ko: file not found\n";
char * cwd = getcwd(NULL, 0);
int rootfd = open(cwd, O_DIRECTORY);
free(cwd);
int stdin_pipe[2];
ATF_REQUIRE(pipe(stdin_pipe) >= 0);
FILE *f = fopen("testfile", "w+");
ATF_CHECK(f != NULL);
fputs("testcontent\n", f);
fclose(f);
ATF_CHECK(stat("testfile", &st) >= 0);
pid_t p = atf_utils_fork();
if (p == 0) {
close(STDIN_FILENO);
dup2(stdin_pipe[0], STDIN_FILENO);
close(stdin_pipe[1]);
config = ucl_object_typed_new(UCL_OBJECT);
char *cwd = getcwd(NULL, 0);
ucl_object_insert_key(config, ucl_object_fromstring_common(cwd, 0, UCL_STRING_TRIM),
"SSH_RESTRICT_DIR", 16, false);
free(cwd);
exit(pkg_sshserve(rootfd));
}
close(stdin_pipe[0]);
dprintf(stdin_pipe[1], "get \n");
dprintf(stdin_pipe[1], "get /testfile\n");
dprintf(stdin_pipe[1], "get /testfile 0\n");
dprintf(stdin_pipe[1], "get /testfile %ld\n", st.st_mtime);
dprintf(stdin_pipe[1], "get /testfile plop\n");
dprintf(stdin_pipe[1], "get /nonexistent 0\n");
mkdir("test", 0755);
dprintf(stdin_pipe[1], "get test 0\n");
dprintf(stdin_pipe[1], "get %s/Makefile.autosetup 0\n", atf_tc_get_config_var(tc, "srcdir"));
dprintf(stdin_pipe[1], "quit\n");
atf_utils_wait(p, 0, strout, "");
}
ATF_TC_BODY(badrestrict, tc)
{
extern ucl_object_t *config;
char strout[] =
"ok: pkg " PKGVERSION "\n"
"ko: chdir failed (/nonexistent)\n";
char *cwd = getcwd(NULL, 0);
int rootfd = open(cwd, O_DIRECTORY);
free(cwd);
int stdin_pipe[2];
ATF_REQUIRE(pipe(stdin_pipe) >= 0);
pid_t p = atf_utils_fork();
if (p == 0) {
close(STDIN_FILENO);
dup2(stdin_pipe[0], STDIN_FILENO);
close(stdin_pipe[1]);
config = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key(config, ucl_object_fromstring_common("/nonexistent", 0, UCL_STRING_TRIM),
"SSH_RESTRICT_DIR", 16, false);
exit(pkg_sshserve(rootfd));
}
close(stdin_pipe[0]);
dprintf(stdin_pipe[1], "get /testfile 0\n");
dprintf(stdin_pipe[1], "quit\n");
atf_utils_wait(p, 0, strout, "");
}
ATF_TC_BODY(notrestricted, tc)
{
struct stat st;
char strout[] =
"ok: pkg " PKGVERSION "\n"
"ok: 12\n"
"testcontent\n";
mkdir("test", 0755);
int rootfd = open("test", O_DIRECTORY);
int stdin_pipe[2];
ATF_REQUIRE(pipe(stdin_pipe) >= 0);
FILE *f = fopen("testfile", "w+");
ATF_CHECK(f != NULL);
fputs("testcontent\n", f);
fclose(f);
ATF_CHECK(stat("testfile", &st) >= 0);
pid_t p = atf_utils_fork();
if (p == 0) {
close(STDIN_FILENO);
dup2(stdin_pipe[0], STDIN_FILENO);
close(stdin_pipe[1]);
exit(pkg_sshserve(rootfd));
}
close(stdin_pipe[0]);
dprintf(stdin_pipe[1], "get ../testfile 0\n");
dprintf(stdin_pipe[1], "quit\n");
atf_utils_wait(p, 0, strout, "");
}
ATF_TC_BODY(restricted, tc)
{
extern ucl_object_t *config;
struct stat st;
char strout[] =
"ok: pkg " PKGVERSION "\n"
"ko: file not found\n";
mkdir("test", 0755);
int rootfd = open("test", O_DIRECTORY);
int stdin_pipe[2];
ATF_REQUIRE(pipe(stdin_pipe) >= 0);
FILE *f = fopen("testfile", "w+");
ATF_CHECK(f != NULL);
fputs("testcontent\n", f);
fclose(f);
ATF_CHECK(stat("testfile", &st) >= 0);
pid_t p = atf_utils_fork();
if (p == 0) {
close(STDIN_FILENO);
dup2(stdin_pipe[0], STDIN_FILENO);
close(stdin_pipe[1]);
config = ucl_object_typed_new(UCL_OBJECT);
char *restriteddir = 0;
char *cwd = getcwd(NULL, 0);
xasprintf(&restriteddir, "%s/test", cwd);
free(cwd);
ucl_object_insert_key(config, ucl_object_fromstring_common(restriteddir, 0, UCL_STRING_TRIM),
"SSH_RESTRICT_DIR", 16, false);
int ret = pkg_sshserve(rootfd);
free(restriteddir);
exit(ret);
}
close(stdin_pipe[0]);
dprintf(stdin_pipe[1], "get ../testfile 0\n");
dprintf(stdin_pipe[1], "quit\n");
atf_utils_wait(p, 0, strout, "");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, badcommand);
ATF_TP_ADD_TC(tp, getfile);
ATF_TP_ADD_TC(tp, badrestrict);
ATF_TP_ADD_TC(tp, notrestricted);
ATF_TP_ADD_TC(tp, restricted);
return (atf_no_error());
}