server can change uid

Sun, 13 Jan 2013 14:16:45 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 13 Jan 2013 14:16:45 +0100
changeset 47
ce9790523346
parent 46
636e05eb48f6
child 48
37a512d7b8f6

server can change uid

src/server/daemon/configmanager.c file | annotate | diff | comparison | revisions
src/server/daemon/error.c file | annotate | diff | comparison | revisions
src/server/daemon/error.h file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.c file | annotate | diff | comparison | revisions
src/server/daemon/main.c file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.c file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.h file | annotate | diff | comparison | revisions
src/server/daemon/webserver.c file | annotate | diff | comparison | revisions
src/server/public/nsapi.h file | annotate | diff | comparison | revisions
src/server/safs/service.c file | annotate | diff | comparison | revisions
src/server/util/util.c file | annotate | diff | comparison | revisions
templates/bin/stopserv.template file | annotate | diff | comparison | revisions
--- 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
--- a/templates/bin/stopserv.template	Sat Jan 12 14:00:47 2013 +0100
+++ b/templates/bin/stopserv.template	Sun Jan 13 14:16:45 2013 +0100
@@ -2,5 +2,5 @@
 
 PID=`cat /tmp/webserver-rw6pgl8b/pid`
 
-kill -SIGTERM $PID
+kill -TERM $PID
 

mercurial