UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 30 #ifdef __gnu_linux__ 31 #define _GNU_SOURCE 32 #endif 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <dlfcn.h> 37 #include <grp.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 41 #include <openssl/bio.h> 42 #include <openssl/ssl.h> 43 #include <openssl/err.h> 44 45 #include "../public/nsapi.h" 46 #include "../public/auth.h" 47 #include "../util/systhr.h" 48 #include "../util/io.h" 49 #include "../util/util.h" 50 51 #include "../../ucx/utils.h" 52 53 #include "../safs/common.h" 54 55 #include "func.h" 56 #include "config.h" 57 #include "configmanager.h" 58 #include "httplistener.h" 59 #include "webserver.h" 60 #include "log.h" 61 #include "auth.h" 62 #include "srvctrl.h" 63 64 extern struct FuncStruct webserver_funcs[]; 65 66 static RestartCallback *atrestart; 67 68 int webserver_init() { 69 // init NSPR 70 systhread_init("webserver"); 71 72 // init ssl 73 if(ws_init_ssl()) { 74 return -1; 75 } 76 77 // init NSAPI functions 78 func_init(); 79 add_functions(webserver_funcs); 80 81 // load init.conf 82 if(load_init_conf("config/init.conf")) { 83 return -1; 84 } 85 86 // load server.conf 87 init_configuration_manager(); 88 ServerConfiguration *cfg; 89 if(cfgmgr_load_config(&cfg) != 0) { 90 fprintf(stderr, "Cannot load configuration\n"); 91 return -1; 92 } 93 94 // init caches 95 auth_cache_init(); 96 97 // init SAFs 98 common_saf_init(); 99 100 // set global vars 101 conf_global_vars_s *vars = conf_getglobals(); 102 103 WSBool changeuid = FALSE; 104 uid_t ws_uid = geteuid(); 105 setpwent(); 106 char *pwbuf = malloc(DEF_PWBUF); 107 vars->Vuserpw = malloc(sizeof(struct passwd)); 108 if(cfg->user.ptr) { 109 if(!util_getpwnam(cfg->user.ptr, vars->Vuserpw, pwbuf, DEF_PWBUF)) { 110 log_ereport( 111 LOG_MISCONFIG, 112 "user %s does not exist!", 113 cfg->user.ptr); 114 free(vars->Vuserpw); 115 vars->Vuserpw = NULL; 116 } else { 117 changeuid = TRUE; 118 } 119 } else { 120 if(!util_getpwuid(ws_uid, vars->Vuserpw, pwbuf, DEF_PWBUF)) { 121 log_ereport(LOG_FAILURE, "webserver_init: cannot get passwd data"); 122 free(vars->Vuserpw); 123 vars->Vuserpw = NULL; 124 } 125 } 126 if(!vars->Vuserpw) { 127 log_ereport(LOG_WARN, "globalvars->Vuserpw is null"); 128 } 129 130 // change uid 131 if(changeuid && ws_uid == 0) { 132 // a webserver user is set and we are root 133 134 if(setgid(vars->Vuserpw->pw_gid) != 0) { 135 log_ereport( 136 LOG_FAILURE, 137 "setgid(%d) failed", 138 vars->Vuserpw->pw_gid); 139 } else { 140 // setgid was successful 141 // we need to call initgroups to have all group permissions 142 if(initgroups(vars->Vuserpw->pw_name, vars->Vuserpw->pw_gid)!=0) { 143 log_ereport(LOG_FAILURE, "initgroups failed"); 144 } 145 } 146 147 // change the uid 148 if(setuid(vars->Vuserpw->pw_uid)) { 149 log_ereport( 150 LOG_FAILURE, 151 "setuid(%d) failed", 152 vars->Vuserpw->pw_uid); 153 } 154 } else if(vars->Vuserpw) { 155 log_ereport( 156 LOG_WARN, 157 "server must be started as root to change uid"); 158 } 159 160 // create tmp dir and pid file 161 char *mkdir_cmd = NULL; 162 asprintf(&mkdir_cmd, "mkdir -p %s", cfg->tmp.ptr); 163 system(mkdir_cmd); 164 free(mkdir_cmd); 165 166 char *pid_file_path = NULL; 167 asprintf(&pid_file_path, "%s/pid", cfg->tmp.ptr); 168 FILE *pidfile = fopen(pid_file_path, "w"); // TODO: check error 169 pid_t pid = getpid(); 170 fprintf(pidfile, "%d", pid); 171 fclose(pidfile); 172 free(pid_file_path); 173 174 // create unix domain socket for server control 175 sstr_t tmp_priv = ucx_sprintf("%s/private", cfg->tmp.ptr); 176 // TODO: remove existing private dir 177 if(mkdir(tmp_priv.ptr, S_IRWXU)) { 178 if(errno == EEXIST) { 179 if(chmod(tmp_priv.ptr, S_IRWXU)) { 180 log_ereport( 181 LOG_CATASTROPHE, 182 "cannot change permissions of tmp dir %s:", 183 tmp_priv.ptr, 184 strerror(errno)); 185 return 0; 186 } 187 } else { 188 log_ereport( 189 LOG_CATASTROPHE, 190 "cannot create tmp dir %s:", 191 tmp_priv.ptr, 192 strerror(errno)); 193 return -1; 194 } 195 } 196 197 198 // create srvctrl unix domain socket 199 // this socket is used for stop, reconfigure and other operations 200 if(srvctrl_init(cfg)) { 201 return -1; 202 } 203 204 //endpwent(); // TODO: close or not? 205 //free(pwbuf); // TODO: ? 206 207 return 0; 208 } 209 210 int webserver_run() { 211 log_ereport(LOG_VERBOSE, "webserver_run"); 212 213 // start all http listener 214 if(start_all_listener() != 0) { 215 fprintf(stderr, "Error: Cannot start http listener\n"); 216 } 217 218 log_ereport(LOG_INFORM, "webserver started"); 219 220 return 0; 221 } 222 223 void webserver_shutdown() { 224 log_ereport(LOG_INFORM, "webserver shutdown"); 225 226 srvctrl_shutdown(); 227 228 // execute restart callbacks 229 RestartCallback *re = atrestart; 230 while(re) { 231 re->func(re->data); 232 re = re->next; 233 } 234 } 235 236 int webserver_reconfig() { 237 if(cfgmgr_load_config(NULL) != 0) { 238 return -1; 239 } 240 // start newly created listeners 241 start_all_listener(); 242 243 return 0; 244 } 245 246 void webserver_atrestart(void (*fn)(void *), void *data) { 247 RestartCallback *cb = malloc(sizeof(RestartCallback)); 248 cb->func = fn; 249 cb->data = data; 250 cb->next = NULL; 251 252 if(atrestart) { 253 RestartCallback *elm = atrestart; 254 while(elm) { 255 if(!elm->next) { 256 elm->next = cb; 257 break; 258 } 259 elm = elm->next; 260 } 261 } else { 262 atrestart = cb; 263 } 264 } 265 266 int nsapi_runtime_version() { 267 return 303; 268 } 269 270 271 int ws_init_ssl() { 272 // TODO: handle errors 273 SSL_load_error_strings(); 274 SSL_library_init(); 275 OpenSSL_add_all_algorithms(); 276 return 0; 277 } 278