applied Szabolcs patch, added him to LICENSE
This commit is contained in:
parent
0c7cc24c83
commit
a61a51b91d
3 changed files with 48 additions and 28 deletions
3
LICENSE
3
LICENSE
|
@ -1,6 +1,7 @@
|
||||||
MIT/X Consortium License
|
MIT/X Consortium License
|
||||||
|
|
||||||
© 2009 Anselm R Garbe <anselm@garbe.us>
|
© 2009-2011 Anselm R Garbe <anselm@garbe.us>
|
||||||
|
© 2011 Szabolcs Nagy <nszabolcs@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
|
|
@ -5,7 +5,7 @@ static const char serverport[] = "80";
|
||||||
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";
|
||||||
static const char group[] = "nobody";
|
static const char group[] = "nogroup";
|
||||||
static const char cgi_dir[] = "/var/www/werc-dev/bin";
|
static const char cgi_dir[] = "/var/www/werc-dev/bin";
|
||||||
static const char cgi_script[] = "./werc.rc";
|
static const char cgi_script[] = "./werc.rc";
|
||||||
static const int cgi_mode = 0;
|
static const int cgi_mode = 0;
|
||||||
|
|
71
quark.c
71
quark.c
|
@ -5,6 +5,7 @@
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -38,9 +39,10 @@ static const char texthtml[] = "text/html";
|
||||||
|
|
||||||
static ssize_t writetext(const char *buf);
|
static ssize_t writetext(const char *buf);
|
||||||
static ssize_t writedata(const char *buf, size_t buflen);
|
static ssize_t writedata(const char *buf, size_t buflen);
|
||||||
|
static void atomiclog(int fd, const char *errstr, va_list ap);
|
||||||
static void die(const char *errstr, ...);
|
static void die(const char *errstr, ...);
|
||||||
void logmsg(const char *errstr, ...);
|
static void logmsg(const char *errstr, ...);
|
||||||
void logerrmsg(const char *errstr, ...);
|
static void logerrmsg(const char *errstr, ...);
|
||||||
static void response(void);
|
static void response(void);
|
||||||
static void responsecgi(void);
|
static void responsecgi(void);
|
||||||
static void responsedir(void);
|
static void responsedir(void);
|
||||||
|
@ -68,7 +70,7 @@ writedata(const char *buf, size_t buf_len) {
|
||||||
|
|
||||||
while(offset < buf_len) {
|
while(offset < buf_len) {
|
||||||
if((r = write(cfd, buf + offset, buf_len - offset)) == -1) {
|
if((r = write(cfd, buf + offset, buf_len - offset)) == -1) {
|
||||||
logerrmsg("%s: client %s closed connection\n", tstamp(), host);
|
logerrmsg("client %s closed connection\n", host);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
offset += r;
|
offset += r;
|
||||||
|
@ -81,13 +83,28 @@ writetext(const char *buf) {
|
||||||
return writedata(buf, strlen(buf));
|
return writedata(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atomiclog(int fd, const char *errstr, va_list ap) {
|
||||||
|
static char buf[512];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/*
|
||||||
|
assemble the message in buf and write it in one pass
|
||||||
|
to avoid interleaved concurrent writes on a shared fd.
|
||||||
|
*/
|
||||||
|
n = snprintf(buf, sizeof buf, "%s: ", tstamp());
|
||||||
|
n += vsnprintf(buf + n, sizeof buf - n, errstr, ap);
|
||||||
|
if (n >= sizeof buf)
|
||||||
|
n = sizeof buf - 1;
|
||||||
|
write(fd, buf, n);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
logmsg(const char *errstr, ...) {
|
logmsg(const char *errstr, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
fprintf(stdout, "%s: ", tstamp());
|
|
||||||
va_start(ap, errstr);
|
va_start(ap, errstr);
|
||||||
vfprintf(stdout, errstr, ap);
|
atomiclog(STDOUT_FILENO, errstr, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,9 +112,8 @@ void
|
||||||
logerrmsg(const char *errstr, ...) {
|
logerrmsg(const char *errstr, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
fprintf(stderr, "%s: ", tstamp());
|
|
||||||
va_start(ap, errstr);
|
va_start(ap, errstr);
|
||||||
vfprintf(stderr, errstr, ap);
|
atomiclog(STDERR_FILENO, errstr, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +121,8 @@ void
|
||||||
die(const char *errstr, ...) {
|
die(const char *errstr, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
fprintf(stderr, "%s: ", tstamp());
|
|
||||||
va_start(ap, errstr);
|
va_start(ap, errstr);
|
||||||
vfprintf(stderr, errstr, ap);
|
atomiclog(STDERR_FILENO, errstr, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -181,8 +196,7 @@ responsefile(void) {
|
||||||
int i, ffd;
|
int i, ffd;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
stat(reqbuf, &st);
|
if(stat(reqbuf, &st) == -1 || (ffd = open(reqbuf, O_RDONLY)) == -1) {
|
||||||
if((ffd = open(reqbuf, O_RDONLY)) == -1) {
|
|
||||||
logerrmsg("%s requests unknown path %s\n", host, reqbuf);
|
logerrmsg("%s requests unknown path %s\n", host, reqbuf);
|
||||||
if(responsehdr(HttpNotFound) != -1
|
if(responsehdr(HttpNotFound) != -1
|
||||||
&& responsecontenttype(texthtml) != -1)
|
&& responsecontenttype(texthtml) != -1)
|
||||||
|
@ -269,6 +283,8 @@ responsedir(void) {
|
||||||
responsedirdata(d);
|
responsedirdata(d);
|
||||||
closedir(d);
|
closedir(d);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
logerrmsg("client %s requests %s but opendir failed: %s\n", host, reqbuf, strerror(errno));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
responsefile(); /* docindex */
|
responsefile(); /* docindex */
|
||||||
|
@ -290,7 +306,8 @@ responsecgi(void) {
|
||||||
setenv("SCRIPT_NAME", cgi_script, 1);
|
setenv("SCRIPT_NAME", cgi_script, 1);
|
||||||
setenv("REQUEST_URI", reqbuf, 1);
|
setenv("REQUEST_URI", reqbuf, 1);
|
||||||
logmsg("CGI SERVER_NAME=%s SCRIPT_NAME=%s REQUEST_URI=%s\n", reqhost, cgi_script, reqbuf);
|
logmsg("CGI SERVER_NAME=%s SCRIPT_NAME=%s REQUEST_URI=%s\n", reqhost, cgi_script, reqbuf);
|
||||||
chdir(cgi_dir);
|
if(chdir(cgi_dir) == -1)
|
||||||
|
logerrmsg("chdir to cgi directory %s failed: %s\n", cgi_dir, strerror(errno));
|
||||||
if((cgi = popen(cgi_script, "r"))) {
|
if((cgi = popen(cgi_script, "r"))) {
|
||||||
if(responsehdr(HttpOk) == -1)
|
if(responsehdr(HttpOk) == -1)
|
||||||
return;
|
return;
|
||||||
|
@ -335,8 +352,7 @@ response(void) {
|
||||||
if(cgi_mode)
|
if(cgi_mode)
|
||||||
responsecgi();
|
responsecgi();
|
||||||
else {
|
else {
|
||||||
stat(reqbuf, &st);
|
if(stat(reqbuf, &st) != -1 && S_ISDIR(st.st_mode))
|
||||||
if(S_ISDIR(st.st_mode))
|
|
||||||
responsedir();
|
responsedir();
|
||||||
else
|
else
|
||||||
responsefile();
|
responsefile();
|
||||||
|
@ -350,7 +366,7 @@ request(void) {
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
do { /* MAXBUFLEN byte of reqbuf is emergency 0 terminator */
|
do { /* MAXBUFLEN byte of reqbuf is emergency 0 terminator */
|
||||||
if((r = read(cfd, reqbuf + offset, MAXBUFLEN - offset)) < 0) {
|
if((r = read(cfd, reqbuf + offset, MAXBUFLEN - offset)) == -1) {
|
||||||
logerrmsg("read: %s\n", strerror(errno));
|
logerrmsg("read: %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -362,7 +378,7 @@ request(void) {
|
||||||
for(res = res + 5; *res && (*res == ' ' || *res == '\t'); res++);
|
for(res = res + 5; *res && (*res == ' ' || *res == '\t'); res++);
|
||||||
if(!*res)
|
if(!*res)
|
||||||
goto invalid_request;
|
goto invalid_request;
|
||||||
for(p = res; *p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\t'; p++);
|
for(p = res; *p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n'; p++);
|
||||||
if(!*p)
|
if(!*p)
|
||||||
goto invalid_request;
|
goto invalid_request;
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
@ -372,8 +388,6 @@ request(void) {
|
||||||
reqhost[p - res] = 0;
|
reqhost[p - res] = 0;
|
||||||
}
|
}
|
||||||
for(p = reqbuf; *p && *p != '\r' && *p != '\n'; p++);
|
for(p = reqbuf; *p && *p != '\r' && *p != '\n'; p++);
|
||||||
if(!*p)
|
|
||||||
goto invalid_request;
|
|
||||||
if(*p == '\r' || *p == '\n') {
|
if(*p == '\r' || *p == '\n') {
|
||||||
*p = 0;
|
*p = 0;
|
||||||
/* check command */
|
/* check command */
|
||||||
|
@ -407,15 +421,16 @@ serve(int fd) {
|
||||||
socklen_t salen;
|
socklen_t salen;
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
|
|
||||||
salen = sizeof sa;
|
|
||||||
while(running) {
|
while(running) {
|
||||||
|
salen = sizeof sa;
|
||||||
if((cfd = accept(fd, &sa, &salen)) == -1) {
|
if((cfd = accept(fd, &sa, &salen)) == -1) {
|
||||||
/* el cheapo socket release */
|
/* el cheapo socket release */
|
||||||
logerrmsg("cannot accept: %s, sleep a second...\n", strerror(errno));
|
logerrmsg("cannot accept: %s, sleep a second...\n", strerror(errno));
|
||||||
sleep(1);
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(fork() == 0) {
|
result = fork();
|
||||||
|
if(result == 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
host[0] = 0;
|
host[0] = 0;
|
||||||
getnameinfo(&sa, salen, host, sizeof host, NULL, 0, NI_NOFQDN);
|
getnameinfo(&sa, salen, host, sizeof host, NULL, 0, NI_NOFQDN);
|
||||||
|
@ -426,7 +441,8 @@ serve(int fd) {
|
||||||
shutdown(cfd, SHUT_WR);
|
shutdown(cfd, SHUT_WR);
|
||||||
close(cfd);
|
close(cfd);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
} else if (result == -1)
|
||||||
|
logerrmsg("fork failed: %s\n", strerror(errno));
|
||||||
close(cfd);
|
close(cfd);
|
||||||
}
|
}
|
||||||
logmsg("shutting down\n");
|
logmsg("shutting down\n");
|
||||||
|
@ -472,7 +488,8 @@ tstamp(void) {
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[]) {
|
main(int argc, char *argv[]) {
|
||||||
struct addrinfo hints, *ai;
|
struct addrinfo hints, *ai;
|
||||||
struct passwd *upwd, *gpwd;
|
struct passwd *upwd;
|
||||||
|
struct group *gpwd;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* arguments */
|
/* arguments */
|
||||||
|
@ -485,7 +502,7 @@ main(int argc, char *argv[]) {
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if(!(upwd = getpwnam(user)))
|
if(!(upwd = getpwnam(user)))
|
||||||
die("error: invalid user %s\n", user);
|
die("error: invalid user %s\n", user);
|
||||||
if(!(gpwd = getpwnam(group)))
|
if(!(gpwd = getgrnam(group)))
|
||||||
die("error: invalid group %s\n", group);
|
die("error: invalid group %s\n", group);
|
||||||
|
|
||||||
signal(SIGCHLD, sighandler);
|
signal(SIGCHLD, sighandler);
|
||||||
|
@ -529,10 +546,12 @@ main(int argc, char *argv[]) {
|
||||||
die("error: location too long\n");
|
die("error: location too long\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chroot(docroot) == -1)
|
if(chdir(docroot) == -1)
|
||||||
die("error: chroot %s: %s\n", docroot, strerror(errno));
|
die("error: chdir %s: %s\n", docroot, strerror(errno));
|
||||||
|
if(chroot(".") == -1)
|
||||||
|
die("error: chroot .: %s\n", strerror(errno));
|
||||||
|
|
||||||
if(setgid(gpwd->pw_gid) == -1)
|
if(setgid(gpwd->gr_gid) == -1)
|
||||||
die("error: cannot set group id\n");
|
die("error: cannot set group id\n");
|
||||||
if(setuid(upwd->pw_uid) == -1)
|
if(setuid(upwd->pw_uid) == -1)
|
||||||
die("error: cannot set user id\n");
|
die("error: cannot set user id\n");
|
||||||
|
|
Loading…
Reference in a new issue