Sun, 13 Jan 2013 14:16:45 +0100
server can change uid
--- a/src/server/daemon/configmanager.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/configmanager.c Sun Jan 13 14:16:45 2013 +0100 @@ -37,10 +37,12 @@ #include "log.h" #include "configmanager.h" -ServerConfiguration *current_config = NULL; -time_t sc_last_modified = 0; +static ServerConfiguration *current_config = NULL; +static time_t sc_last_modified = 0; -UcxMap *config_files; +static UcxMap *config_files; + +static conf_global_vars_s global_vars; void init_configuration_manager() { /* init parser */ @@ -49,6 +51,10 @@ config_files = ucx_map_new(16); } +NSAPI_PUBLIC conf_global_vars_s* conf_getglobals() { + return &global_vars; +} + void cfgmgr_attach_file(ConfigFile *cf) { ucx_map_sstr_put(config_files, cf->file, cf); }
--- a/src/server/daemon/error.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/error.c Sun Jan 13 14:16:45 2013 +0100 @@ -30,13 +30,16 @@ #include "../ucx/string.h" #include "../util/pblock.h" +#include "../util/strbuf.h" // macro for creating an error string (ucx sstr_t) #define ERRMSG(s) { s, sizeof(s)-1 } +static sstr_t error_400 = ERRMSG("<html><body>bad request</body></html>"); static sstr_t error_403 = ERRMSG("<html><body>forbidden</body></html>"); static sstr_t error_404 = ERRMSG("<html><body>not found</body></html>"); static sstr_t error_500 = ERRMSG("<html><body>server error</body></html>"); +static sstr_t error_503 = ERRMSG("<html><body>service unavailable</body></html>"); static sstr_t error_std = ERRMSG("<html><body>error</body></html>"); @@ -67,3 +70,42 @@ return REQ_PROCEED; } + +void fatal_error(HTTPRequest *req, int status) { + sstr_t msg = error_500; + char *statusmsg = "Internal Server Error"; + switch(status) { + case 400: { + msg = error_400; + statusmsg = "Bad request"; + break; + } + case 500: { + msg = error_500; + statusmsg = "Internal Server Error"; + break; + } + case 503: { + msg = error_503; + statusmsg = "Service Unavailable"; + break; + } + } + + char buf[512]; + int len = snprintf(buf, 512, "HTTP/1.1 %d %s\r\nServer: webserver\r\nContent-type: text/html\r\nContent-length: %d\r\n\r\n", status, statusmsg, msg.length); + + // set socket blocking + int flags; + if (-1 == (flags = fcntl(req->connection->fd, F_GETFL, 0))) { + flags = 0; + } + if (fcntl(req->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { + // error + } + + write(req->connection->fd, buf, len); + write(req->connection->fd, msg.ptr, msg.length); + + close(req->connection->fd); +}
--- a/src/server/daemon/error.h Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/error.h Sun Jan 13 14:16:45 2013 +0100 @@ -31,12 +31,16 @@ #include "../public/nsapi.h" +#include "sessionhandler.h" +#include "httprequest.h" + #ifdef __cplusplus extern "C" { #endif int nsapi_error_request(Session *sn, Request *rq); +void fatal_error(HTTPRequest *req, int status); #ifdef __cplusplus }
--- a/src/server/daemon/httprequest.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/httprequest.c Sun Jan 13 14:16:45 2013 +0100 @@ -99,7 +99,8 @@ // init NSAPI request structure if(request_initialize(pool, request, rq) != 0) { - printf("Cannot initialize request structure\n"); + log_ereport(LOG_LEVEL_ERROR, "Cannot initialize request structure"); + pool_destroy(pool); return 1; }
--- a/src/server/daemon/main.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/main.c Sun Jan 13 14:16:45 2013 +0100 @@ -40,7 +40,7 @@ #include "../util/date.h" #include "webserver.h" - +#include "log.h" #include "httprequest.h" #include "configmanager.h" @@ -58,10 +58,10 @@ * SIGUSR1: reload the configuration files */ void sig_usr1_reload(int sig) { - printf("reload\n"); + log_ereport(LOG_LEVEL_INFO, "sig reload"); if(cfgmgr_load_config() != 0) { - fprintf(stderr, "Error: cannot reload configuration"); + log_ereport(LOG_LEVEL_ERROR, "cannot reload config"); } signal(SIGUSR1, sig_usr1_reload); @@ -75,25 +75,25 @@ } void* log_pipe_thread(void *data) { - FILE *log_out = fopen("log.txt", "a"); + //FILE *log_out = fopen("log.txt", "a"); char buf[1024]; ssize_t r; while((r = read(std_pipe_fds[0], buf, 1024)) > 0) { - fwrite(buf, 1, r, log_out); - fflush(log_out); + //fwrite(buf, 1, r, log_out); + //fflush(log_out); } - fclose(log_out); + //fclose(log_out); return NULL; } int main(int argc, char **argv) { - test(); + //test(); /* if the -c parameter is specified, we don't create a daemon */ - int d = 0; + int d = 1; for(int i=0;i<argc;i++) { char *p = argv[i]; if(p[0] == '-' && p[1] == 'c') { @@ -111,9 +111,10 @@ } if(setsid() < 0) { - printf("setsid failed\n"); + fprintf(stderr, "setsid failed\n"); return EXIT_FAILURE; } + printf("start daemon\n"); for(int i=0;i<3;i++) { close(i);
--- a/src/server/daemon/sessionhandler.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/sessionhandler.c Sun Jan 13 14:16:45 2013 +0100 @@ -28,12 +28,15 @@ #include <stdio.h> #include <stdlib.h> +#include <errno.h> #include "../public/nsapi.h" #include "sessionhandler.h" #include "httprequest.h" #include "httpparser.h" +#include "log.h" +#include "error.h" typedef struct _event_http_io { HTTPRequest *request; @@ -169,7 +172,10 @@ event->cookie = io; if(ev_pollin(ev, conn->fd, event) != 0) { - perror("poll"); + // TODO: ev_pollin should log, intercept some errors here + log_ereport(LOG_LEVEL_ERROR, "ev_pollin failed: %s", strerror(errno)); + close(conn->fd); + // TODO: free stuff } } @@ -186,16 +192,16 @@ buf->inbuf + buf->pos, buf->maxsize - buf->pos); if(r == -1) { - // TODO: error handling - fprintf(stderr, "%s\n", "Error: Cannot read from socket"); + event->finish = evt_request_error; return 0; } buf->cursize += r; state = http_parser_process(parser); if(state == 2) { - // TODO: error handling - fprintf(stderr, "%s\n", "Error: Cannot parse http request"); + // parse error + fatal_error(request, 400); + event->finish = evt_request_error; return 0; } else if(state == 1) { /* @@ -213,8 +219,9 @@ flags = 0; } if (fcntl(request->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { - perror("Error: evt_request_input: fcntl"); - // TODO: critical error + // just close the connection if fcntl fails + event->finish = evt_request_error; + return 0; } /* @@ -232,7 +239,10 @@ HTTPRequest *request = io->request; int r = handle_request(request, NULL); - // TODO: if r != REQ_PROCEED ... + if(r != 0) { + // TODO: error message + close(request->connection->fd); + } /* * handle_request can return before the request is finished, but it copies @@ -250,3 +260,21 @@ return 0; } + +int evt_request_error(event_handler_t *h, event_t *event) { + EventHttpIO *io = event->cookie; + HttpParser *parser = io->parser; + HTTPRequest *request = io->request; + + close(request->connection->fd); + + header_array_free(request->headers); + free(request); + + http_parser_free(parser); + + free(io); + free(event); + + return 0; +}
--- a/src/server/daemon/sessionhandler.h Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/sessionhandler.h Sun Jan 13 14:16:45 2013 +0100 @@ -94,6 +94,7 @@ int evt_request_input(event_handler_t *h, event_t *event); int evt_request_finish(event_handler_t *h, event_t *event); +int evt_request_error(event_handler_t *h, event_t *event); #ifdef __cplusplus
--- a/src/server/daemon/webserver.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/daemon/webserver.c Sun Jan 13 14:16:45 2013 +0100 @@ -34,10 +34,12 @@ #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> +#include <grp.h> #include "../public/nsapi.h" #include "../util/systhr.h" #include "../util/io.h" +#include "../util/util.h" #include "func.h" #include "config.h" @@ -68,7 +70,7 @@ fprintf(stderr, "Cannot load configuration\n"); return -1; } - + // create tmp dir and pid file ServerConfiguration *cfg = cfgmgr_get_server_config(); char *mkdir_cmd = NULL; @@ -83,8 +85,56 @@ fprintf(pidfile, "%d", pid); fclose(pidfile); free(pid_file_path); + + // set global vars + conf_global_vars_s *vars = conf_getglobals(); + + if(cfg->user.ptr) { + char *pwbuf = malloc(DEF_PWBUF); + vars->Vuserpw = malloc(sizeof(struct passwd)); + // open user database + setpwent(); + if(!util_getpwnam(cfg->user.ptr, vars->Vuserpw, pwbuf, DEF_PWBUF)) { + log_ereport( + LOG_LEVEL_ERROR, + "user %s does not exist!", + cfg->user.ptr); + free(vars->Vuserpw); + vars->Vuserpw = NULL; + } + free(pwbuf); + endpwent(); + } - // init NSAPI functions + // change uid + if(vars->Vuserpw && geteuid() == 0) { + // a webserver user is set and we are root + + if(setgid(vars->Vuserpw->pw_gid) != 0) { + log_ereport( + LOG_LEVEL_ERROR, + "setgid(%d) failed", + vars->Vuserpw->pw_gid); + } else { + // setgid was successful + // we need to call initgroups to have all group permissions + if(initgroups(vars->Vuserpw->pw_name, vars->Vuserpw->pw_gid)!=0) { + log_ereport(LOG_LEVEL_ERROR, "initgroups failed"); + } + } + + // change the uid + if(setuid(vars->Vuserpw->pw_uid)) { + log_ereport( + LOG_LEVEL_ERROR, + "setuid(%d) failed", + vars->Vuserpw->pw_uid); + } + } else if(vars->Vuserpw) { + log_ereport( + LOG_LEVEL_INFO, + "server must be started as root to change uid"); + } return 0;
--- a/src/server/public/nsapi.h Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/public/nsapi.h Sun Jan 13 14:16:45 2013 +0100 @@ -883,7 +883,7 @@ long Vssl3_session_timeout; /* The server's hostname as should be reported in self-ref URLs */ -#define server_hostname "x4" +#define server_hostname "x4" // TODO: fix char *Vserver_hostname; /* The main object from which all are derived */ @@ -1164,6 +1164,8 @@ /* nsapi functions */ +NSAPI_PUBLIC conf_global_vars_s* conf_getglobals(); + ssize_t net_write(SYS_NETFD fd, void *buf, size_t nbytes); ssize_t net_printf(SYS_NETFD fd, char *format, ...);
--- a/src/server/safs/service.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/safs/service.c Sun Jan 13 14:16:45 2013 +0100 @@ -133,7 +133,7 @@ } int service_index(pblock *pb, Session *sn, Request *rq) { - printf("service_index\n"); + //printf("service_index\n"); char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
--- a/src/server/util/util.c Sat Jan 12 14:00:47 2013 +0100 +++ b/src/server/util/util.c Sun Jan 13 14:16:45 2013 +0100 @@ -132,3 +132,43 @@ return p + negative; } + + + +#ifndef XP_WIN32 +NSAPI_PUBLIC struct passwd * +util_getpwnam(const char *name, struct passwd *result, char *buffer, + int buflen) +{ + struct passwd *rv; + +#if defined(AIX) || defined(LINUX) || defined(HPUX) + errno = getpwnam_r(name, result, buffer, buflen, &rv); + if (errno != 0) + rv = NULL; +#else + rv = getpwnam_r(name, result, buffer, buflen); +#endif + + return rv; +} +#endif + + +#ifndef XP_WIN32 +NSAPI_PUBLIC struct passwd * +util_getpwuid(uid_t uid, struct passwd *result, char *buffer, int buflen) +{ + struct passwd *rv; + +#if defined(AIX) || defined(LINUX) || defined(HPUX) + errno = getpwuid_r(uid, result, buffer, buflen, &rv); + if (errno != 0) + rv = NULL; +#else + rv = getpwuid_r(uid, result, buffer, buflen); +#endif + + return rv; +} +#endif