change the behavior of docroot
Change the behavior of docroot, which is now used as a prefix path for
all file operations related to static files. And add chrootdir, which is
just the old docroot behavior and allows to control the path into which
quark will chroot.
Not having properly distinct configuration variables for chroot,
document root and CGI root was specially annoying since commit 2822488
which allowed users to retrieve the CGI script or binary by just
guessing its path, since quark was chrooting into docroot before
anything else, and thus the CGI script/binary was in the user accessible
path.
This is implemented by moving the reqbuf buffer in the middle of a
bigger buffer, reqpath. That buffer contains the value of docroot at its
beginning and reqbuf simply points to the first byte after this value.
This commit is contained in:
parent
4674ccde50
commit
e42bb27846
3 changed files with 36 additions and 15 deletions
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
static const char *servername = "127.0.0.1";
|
static const char *servername = "127.0.0.1";
|
||||||
static const char *serverport = "80";
|
static const char *serverport = "80";
|
||||||
|
static const char *chrootdir = ".";
|
||||||
static const char *docroot = ".";
|
static const char *docroot = ".";
|
||||||
static const char *docindex = "index.html";
|
static const char *docindex = "index.html";
|
||||||
static const char *user = "nobody";
|
static const char *user = "nobody";
|
||||||
|
|
7
quark.1
7
quark.1
|
@ -4,6 +4,8 @@ quark \- simple httpd
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B quark
|
.B quark
|
||||||
.RB [ \-c ]
|
.RB [ \-c ]
|
||||||
|
.RB [ \-C
|
||||||
|
.IR chrootdir ]
|
||||||
.RB [ \-d
|
.RB [ \-d
|
||||||
.IR cgidir ]
|
.IR cgidir ]
|
||||||
.RB [ \-e
|
.RB [ \-e
|
||||||
|
@ -29,6 +31,9 @@ Quark is a simple httpd.
|
||||||
.B \-c
|
.B \-c
|
||||||
enable CGI-mode, disabled by default.
|
enable CGI-mode, disabled by default.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-C " chrootdir"
|
||||||
|
chroot into chrootdir, by default ".".
|
||||||
|
.TP
|
||||||
.B \-d " cgidir"
|
.B \-d " cgidir"
|
||||||
change directory to cgidir for CGI-mode, by default ".".
|
change directory to cgidir for CGI-mode, by default ".".
|
||||||
.TP
|
.TP
|
||||||
|
@ -48,7 +53,7 @@ enable directory listing, disabled by default.
|
||||||
listen on port, by default "80".
|
listen on port, by default "80".
|
||||||
.TP
|
.TP
|
||||||
.B \-r " docroot"
|
.B \-r " docroot"
|
||||||
change directory to docroot, by default ".".
|
change directory to docroot for static files, by default ".".
|
||||||
.TP
|
.TP
|
||||||
.B \-s " server"
|
.B \-s " server"
|
||||||
listen on server, by default "127.0.0.1".
|
listen on server, by default "127.0.0.1".
|
||||||
|
|
43
quark.c
43
quark.c
|
@ -93,7 +93,8 @@ static char location[256];
|
||||||
static int running = 1;
|
static int running = 1;
|
||||||
static int status;
|
static int status;
|
||||||
static char host[NI_MAXHOST];
|
static char host[NI_MAXHOST];
|
||||||
static char reqbuf[MAXBUFLEN];
|
static char* reqbuf = NULL;
|
||||||
|
static char* reqpath = NULL;
|
||||||
static char resbuf[MAXBUFLEN];
|
static char resbuf[MAXBUFLEN];
|
||||||
static char reqhost[256];
|
static char reqhost[256];
|
||||||
static char reqmod[256];
|
static char reqmod[256];
|
||||||
|
@ -204,7 +205,7 @@ responsefile(void) {
|
||||||
int r, ffd;
|
int r, ffd;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if ((r = stat(reqbuf, &st)) == -1 || (ffd = open(reqbuf, O_RDONLY)) == -1) {
|
if ((r = stat(reqpath, &st)) == -1 || (ffd = open(reqpath, O_RDONLY)) == -1) {
|
||||||
/* file not found */
|
/* file not found */
|
||||||
if (putresentry(HEADER, HttpNotFound, tstamp(0))
|
if (putresentry(HEADER, HttpNotFound, tstamp(0))
|
||||||
|| putresentry(CONTENTTYPE, texthtml))
|
|| putresentry(CONTENTTYPE, texthtml))
|
||||||
|
@ -291,8 +292,8 @@ responsedir(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (len + strlen(docindex) + 1 < MAXBUFLEN)
|
if (len + strlen(docindex) + 1 < MAXBUFLEN)
|
||||||
memcpy(reqbuf + len, docindex, strlen(docindex) + 1);
|
memmove(reqbuf + len, docindex, strlen(docindex) + 1);
|
||||||
if (access(reqbuf, R_OK) == -1) { /* directory mode */
|
if (access(reqpath, R_OK) == -1) { /* directory mode */
|
||||||
reqbuf[len] = 0; /* cut off docindex again */
|
reqbuf[len] = 0; /* cut off docindex again */
|
||||||
if(!allowdirlist) {
|
if(!allowdirlist) {
|
||||||
if (putresentry(HEADER, HttpForbidden, tstamp(0))
|
if (putresentry(HEADER, HttpForbidden, tstamp(0))
|
||||||
|
@ -303,12 +304,12 @@ responsedir(void) {
|
||||||
writetext("\r\n<html><body>"HttpForbidden"</body></html>\r\n");
|
writetext("\r\n<html><body>"HttpForbidden"</body></html>\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((n = scandir(reqbuf, &namelist, NULL, alphasort)) >= 0) {
|
if ((n = scandir(reqpath, &namelist, NULL, alphasort)) >= 0) {
|
||||||
responsedirdata(namelist, n);
|
responsedirdata(namelist, n);
|
||||||
free(namelist);
|
free(namelist);
|
||||||
} else {
|
} else {
|
||||||
logerrmsg("client %s requests %s but scandir failed: %s\n",
|
logerrmsg("client %s requests %s but scandir failed: %s\n",
|
||||||
host, reqbuf, strerror(errno));
|
host, reqpath, strerror(errno));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
responsefile(); /* docindex */
|
responsefile(); /* docindex */
|
||||||
|
@ -406,7 +407,7 @@ response(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = stat(reqbuf, &st);
|
r = stat(reqpath, &st);
|
||||||
if (cgi_mode) {
|
if (cgi_mode) {
|
||||||
if(r != -1 && !S_ISDIR(st.st_mode))
|
if(r != -1 && !S_ISDIR(st.st_mode))
|
||||||
responsefile();
|
responsefile();
|
||||||
|
@ -562,9 +563,9 @@ sighandler(int sig) {
|
||||||
|
|
||||||
void
|
void
|
||||||
usage(void) {
|
usage(void) {
|
||||||
fprintf(stderr, "usage: quark [-c] [-d cgidir] [-e cgiscript] [-g group] "
|
fprintf(stderr, "usage: quark [-c] [-C chrootdir] [-d cgidir] "
|
||||||
"[-i index] [-l] [-p port] [-r docroot] [-s server] "
|
"[-e cgiscript] [-g group] [-i index] [-l] [-p port] "
|
||||||
"[-u user] [-v]\n");
|
"[-r docroot] [-s server] [-u user] [-v]\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,12 +575,15 @@ main(int argc, char *argv[]) {
|
||||||
struct passwd *upwd = NULL;
|
struct passwd *upwd = NULL;
|
||||||
struct group *gpwd = NULL;
|
struct group *gpwd = NULL;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
int i;
|
int i, docrootlen;
|
||||||
|
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'c':
|
case 'c':
|
||||||
cgi_mode = 1;
|
cgi_mode = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
chrootdir = EARGF(usage());
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
cgi_dir = EARGF(usage());
|
cgi_dir = EARGF(usage());
|
||||||
break;
|
break;
|
||||||
|
@ -619,6 +623,15 @@ main(int argc, char *argv[]) {
|
||||||
if (group && *group && !(gpwd = getgrnam(group)))
|
if (group && *group && !(gpwd = getgrnam(group)))
|
||||||
die("error\tinvalid group %s\n", group);
|
die("error\tinvalid group %s\n", group);
|
||||||
|
|
||||||
|
docrootlen = strlen(docroot);
|
||||||
|
reqpath = malloc(docrootlen + MAXBUFLEN);
|
||||||
|
if (reqpath == NULL) {
|
||||||
|
logerrmsg("error\tcannot allocate memory\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
memcpy(reqpath, docroot, docrootlen + 1);
|
||||||
|
reqbuf = reqpath + docrootlen;
|
||||||
|
|
||||||
signal(SIGCHLD, sighandler);
|
signal(SIGCHLD, sighandler);
|
||||||
signal(SIGHUP, sighandler);
|
signal(SIGHUP, sighandler);
|
||||||
signal(SIGINT, sighandler);
|
signal(SIGINT, sighandler);
|
||||||
|
@ -666,8 +679,8 @@ main(int argc, char *argv[]) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chdir(docroot) == -1) {
|
if (chdir(chrootdir) == -1) {
|
||||||
logerrmsg("error\tchdir %s: %s\n", docroot, strerror(errno));
|
logerrmsg("error\tchdir %s: %s\n", chrootdir, strerror(errno));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (chroot(".") == -1) {
|
if (chroot(".") == -1) {
|
||||||
|
@ -693,15 +706,17 @@ main(int argc, char *argv[]) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
logmsg("ready\t%s:%s\t%s\n", servername, serverport, docroot);
|
logmsg("ready\t%s:%s\t%s\n", servername, serverport, chrootdir);
|
||||||
|
|
||||||
serve(listenfd); /* main loop */
|
serve(listenfd); /* main loop */
|
||||||
close(listenfd);
|
close(listenfd);
|
||||||
|
free(reqpath);
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
err:
|
err:
|
||||||
if (listenfd != -1)
|
if (listenfd != -1)
|
||||||
close(listenfd);
|
close(listenfd);
|
||||||
|
free(reqpath);
|
||||||
if (ai)
|
if (ai)
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
Loading…
Reference in a new issue