--- suX/src/sux.c 2011/10/09 18:58:44 1.2.2.1 +++ suX/src/sux.c 2015/06/17 14:01:33 1.5.2.2 @@ -3,13 +3,13 @@ * by Michael Pounov * * $Author: misho $ - * $Id: sux.c,v 1.2.2.1 2011/10/09 18:58:44 misho Exp $ + * $Id: sux.c,v 1.5.2.2 2015/06/17 14:01:33 misho Exp $ * *************************************************************************/ #include "global.h" -sl_config cfg; +cfg_root_t cfg; int Verbose; struct tagProc proc; FILE *lf; @@ -20,13 +20,13 @@ Log(int lvl, const char *fmt, ...) { va_list lst, cp; - if (lvl <= Verbose) { + EVERBS(lvl) { va_start(lst, fmt); va_copy(cp, lst); vfprintf(lf, fmt, lst); va_end(lst); fprintf(lf, "\n"); - vsyslog(LOG_WARNING, fmt, cp); + vsyslog(LOG_INFO, fmt, cp); va_end(cp); } } @@ -45,13 +45,29 @@ Err(const char *fmt, ...) va_end(cp); } -static void +static inline void +DumpProc(const char *txt) +{ + Log(1, "%s:: uid:gid=%d:%d UID:GID=%d:%d Prio=%d Class=%s Name=%s Dir=%s Cmd=%s " + "Script=%s From=%s:%s Get=%s", txt ? txt : __func__, + geteuid(), getegid(), AIT_GET_I16(&proc.proc_uid), + AIT_GET_I16(&proc.proc_gid), AIT_GET_I32(&proc.proc_prio), + AIT_GET_STR(&proc.proc_class), AIT_GET_STR(&proc.proc_name), + AIT_GET_STR(&proc.proc_dir), AIT_GET_STR(&proc.proc_cmd), + getenv("PATH_TRANSLATED"), getenv("REMOTE_ADDR"), + getenv("REMOTE_PORT"), getenv("REQUEST_URI")); +} + +static int initProg() { - proc.proc_uid = getuid(); - proc.proc_gid = getgid(); - proc.proc_prio = getpriority(PRIO_PROCESS, 0); - getcwd(proc.proc_dir, sizeof proc.proc_dir); + AIT_SET_I16(&proc.proc_uid, getuid()); + AIT_SET_I16(&proc.proc_gid, getgid()); + AIT_SET_I32(&proc.proc_prio, getpriority(PRIO_PROCESS, 0)); + AIT_INIT_VAL2(&proc.proc_class, string); + AIT_INIT_VAL2(&proc.proc_dir, string); + AIT_INIT_VAL2(&proc.proc_name, string); + AIT_INIT_VAL2(&proc.proc_cmd, string); #if 0 lf = fopen(DEFAULT_LOG, "a"); @@ -60,14 +76,27 @@ initProg() lf = stdout; openlog(PACKAGE_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER); + return 0; } static void +endProg() +{ + AIT_FREE_VAL(&proc.proc_uid); + AIT_FREE_VAL(&proc.proc_gid); + AIT_FREE_VAL(&proc.proc_prio); + AIT_FREE_VAL(&proc.proc_class); + AIT_FREE_VAL(&proc.proc_dir); + AIT_FREE_VAL(&proc.proc_name); + AIT_FREE_VAL(&proc.proc_cmd); +} + +static void Usage() { printf( " -= suX =- suExecutor designed for web based applicaions\n" "(C)`11 AITNET ltd - Sofia/Bulgaria - \n\n" - " Syntax: %s [options] [arguments]\n" + " Syntax: %s [options] [arguments]\n" "\t-u \t\t\tUser for suID\n" "\t-g \t\t\tGroup for suID\n" "\t-p \t\tExecute with priority\n" @@ -75,6 +104,7 @@ Usage() "\t-C \t\t\tChroot to directory\n" "\t-c \t\t\tConfig file\n" "\t-l \t\t\tLog file path (default:/var/log/suX.log)\n" + "\t-o\t\t\t\tForce set UID,GID and Priority for program\n" "\t-v\t\t\t\tVerbose, (more -v, more verbosity)\n" "\t-h\t\t\t\tThis help screen!\n\n", PACKAGE_NAME); } @@ -83,111 +113,117 @@ static inline int setUIDGID(char flg, const char *name) { struct stat sb; + struct passwd *pass; + short uid, gid; - if (stat(name, &sb) == -1) { - Err("Error:: %s stat #%d - %s", name, errno, strerror(errno)); - return -1; + if (name) { + if (stat(name, &sb) == -1) { + ESYSERR(0); + return -1; + } + uid = sb.st_uid; + gid = sb.st_gid; + } else { + pass = getpwnam(getenv("SUX_USER") ? getenv("SUX_USER") : DEFAULT_SUX_USER); + if (!pass) { + Err("Error:: User %s not found", getenv("SUX_USER")); + endpwent(); + return -1; + } + uid = pass->pw_uid; + gid = pass->pw_gid; + endpwent(); } - if (!(flg & 1)) - proc.proc_uid = sb.st_uid; - if (!(flg & 2)) - proc.proc_gid = sb.st_gid; + if (!(flg & SUX_GET_UID)) + AIT_SET_I16(&proc.proc_uid, uid); + if (!(flg & SUX_GET_GID)) + AIT_SET_I16(&proc.proc_gid, gid); return 0; } static inline int -SetClass() +setClassDir() { - login_cap_t *cap; struct passwd *pass; + int ret = 0; - pass = getpwuid(proc.proc_uid); + pass = getpwuid(AIT_GET_I16(&proc.proc_uid)); if (!pass) { - Err("Error:: User with this UID %d not found", proc.proc_uid); - endpwent(); - return -1; - } else - strlcpy(proc.proc_class, pass->pw_class, sizeof proc.proc_class); + Err("Error:: User with this UID %d not found", AIT_GET_I16(&proc.proc_uid)); + ret = -1; + } else { + AIT_SET_STR(&proc.proc_class, pass->pw_class); + AIT_SET_STR(&proc.proc_dir, pass->pw_dir); - cap = login_getclass(proc.proc_class); - if (!cap) { - Err("Error:: Cant get login class %s", proc.proc_class); - endpwent(); - return -1; + if (setusercontext(NULL, pass, AIT_GET_I16(&proc.proc_uid), + LOGIN_SETLOGIN | LOGIN_SETGROUP | LOGIN_SETUSER | + LOGIN_SETPRIORITY | LOGIN_SETRESOURCES)) { + Err("Error:: Can't set login class %s", AIT_GET_STR(&proc.proc_class)); + ret = -1; + } } - if (setusercontext(cap, pass, proc.proc_uid, LOGIN_SETALL)) { - Err("Error:: Cant set login class %s", proc.proc_class); - login_close(cap); - endpwent(); - return -1; - } - - login_close(cap); endpwent(); - return 0; + return ret; } static int LoadCfgData(char flg) { - char *str, mode = 0; + const char *str; + char mode = 0; - str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("mode")); + str = cfg_getAttribute(&cfg, "global", "mode"); if (!str) { Err("Error:: Unknown mode ..."); return -1; } if (!strcasecmp(str, "SCRIPT")) { mode = 1; - if (setUIDGID(flg, proc.proc_name) == -1) + if (setUIDGID(flg, (getenv("SUX_USER") ? NULL : getenv("PATH_TRANSLATED"))) == -1) return -1; } else if (!strcasecmp(str, "FILE")) { mode = 2; - if (setUIDGID(flg, proc.proc_name) == -1) + if (setUIDGID(flg, AIT_GET_STR(&proc.proc_name)) == -1) return -1; - } else if (!strcasecmp(str, "DIR") && - (str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("directory")))) { + } else if (!strcasecmp(str, "DIR")) { mode = 3; - if (!(flg & 8)) - strlcpy(proc.proc_dir, str, sizeof proc.proc_dir); - - if (setUIDGID(flg, proc.proc_dir) == -1) + str = AIT_GET_STR(&proc.proc_dir) ? AIT_GET_STR(&proc.proc_dir) : "."; + if (setUIDGID(flg, str) == -1) return -1; } else { Err("Error:: Unknown mode %s", str); return -1; } - if (!(flg & 4)) { - str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("priority")); + if (!(flg & SUX_GET_PRIO)) { + str = cfg_getAttribute(&cfg, "global", "priority"); if (str) - proc.proc_prio = strtol(str, NULL, 10); + AIT_SET_I32(&proc.proc_prio, strtol(str, NULL, 10)); } /* find associate extension */ - str = strrchr(proc.proc_name, '.'); + str = strrchr(AIT_GET_STR(&proc.proc_name), '.'); if (str) { str++; str = (*str) ? str : "default"; - switch (cfg_LoadAttribute(&cfg, CFG("associate"), CFG(str), - CFG(proc.proc_cmd), sizeof proc.proc_cmd, NULL)) { + switch (cfg_loadAttribute(&cfg, "associate", str, &proc.proc_cmd, NULL)) { case -1: - Err("Error:: can`t load attribute #%d - %s\n", cfg_GetErrno(), cfg_GetError()); + ELIBERR(cfg); return -1; case 0: - cfg_LoadAttribute(&cfg, CFG("associate"), CFG("default"), - CFG(proc.proc_cmd), sizeof proc.proc_cmd, DEFAULT_CMD); + cfg_loadAttribute(&cfg, "associate", "default", + &proc.proc_cmd, DEFAULT_CMD); } } else - strlcpy(proc.proc_cmd, DEFAULT_CMD, sizeof proc.proc_cmd); + AIT_SET_STR(&proc.proc_cmd, DEFAULT_CMD); return 0; } static int -Run(char **argv) +Run(char **argv, char flg) { char **args, *cmd; array_t *acmd, *aarg; @@ -196,77 +232,66 @@ Run(char **argv) if (!argv) return -1; - n = io_arrayMake(proc.proc_cmd, 0, " \t", &acmd); + n = array_Args(AIT_GET_STR(&proc.proc_cmd), 0, " \t", &acmd); if (n < 1) return -1; - if (!(aarg = io_arrayFrom((const char**) argv, 0))) { - io_arrayDestroy(&acmd); + if (!(aarg = array_From((const char***) &argv, 0))) { + array_Destroy(&acmd); return -1; - } else if (*io_arrayGet(acmd, 0, char*) == '!') { - if (io_arrayGrow(acmd, 0)) { - io_arrayDestroy(&aarg); - io_arrayDestroy(&acmd); + } + /* '!' exclude associated wrapper aka direct args execution */ + if (*array(acmd, 0, char*) == '!') { + if (array_Grow(acmd, 0, 0)) { + array_Destroy(&aarg); + array_Destroy(&acmd); return -1; } - cmd = io_arrayGet(aarg, 0, char*); + cmd = array(aarg, 0, char*); } else - cmd = io_arrayGet(acmd, 0, char*); + cmd = array(acmd, 0, char*); - if (io_arrayConcat(acmd, aarg) == -1) { - io_arrayDestroy(&aarg); - io_arrayDestroy(&acmd); + if (!(flg & SUX_GET_STDIN) && array_Concat(acmd, aarg) == -1) { + array_Destroy(&aarg); + array_Destroy(&acmd); return -1; } - io_arrayDestroy(&aarg); - if (!(args = io_arrayTo(acmd))) { - io_arrayDestroy(&acmd); + array_Destroy(&aarg); + if (!(args = array_To(acmd))) { + array_Destroy(&acmd); return -1; } - io_arrayDestroy(&acmd); + array_Destroy(&acmd); - if (SetClass()) { + if (setClassDir()) { if (args) - free(args); + e_free(args); return -1; } - /* - if (setgid(proc.proc_gid) == -1) { - Err("Error:: setgid #%d - %s\n", errno, strerror(errno)); - if (args) - free(args); - return -1; + if (flg & SUX_GET_FORCE) { + if (setegid(AIT_GET_I16(&proc.proc_gid)) == -1) + goto err; + if (seteuid(AIT_GET_I16(&proc.proc_uid)) == -1) + goto err; + if (setpriority(PRIO_PROCESS, 0, AIT_GET_I32(&proc.proc_prio)) == -1) + goto err; } - if (setuid(proc.proc_uid) == -1) { - Err("Error:: setuid #%d - %s\n", errno, strerror(errno)); - if (args) - free(args); - return -1; - } - if (setpriority(PRIO_PROCESS, 0, proc.proc_prio) == -1) { - Err("Error:: setpriority #%d - %s\n", errno, strerror(errno)); - if (args) - free(args); - return -1; - } - */ - Log(0, "UID:GID=%d:%d Prio=%d Class=%s Name=%s Dir=%s Cmd=%s Script=%s", - proc.proc_uid, proc.proc_gid, proc.proc_prio, proc.proc_class, - proc.proc_name, proc.proc_dir, proc.proc_cmd, getenv("PATH_TRANSLATED")); - - if (3 <= Verbose) { + EVERBS(3) { char **el = args - 1; while (*++el) Log(3, "args: %s", *el); } + DumpProc(__func__); + fflush(lf); execve(cmd, args, environ); +err: + ESYSERR(0); if (args) - free(args); - Err("Error:: in exec() #%d - %s", errno, strerror(errno)); + e_free(args); return -1; } @@ -274,7 +299,7 @@ Run(char **argv) int main(int argc, char **argv) { - char ch, *str, szCfg[MAXPATHLEN], **pp, flg = 0; + char ch, *str, *wrk, szCfg[MAXPATHLEN], **pp, flg = 0; struct passwd *pass; struct group *grp; FILE *f; @@ -282,7 +307,7 @@ main(int argc, char **argv) initProg(); strlcpy(szCfg, DEFAULT_CONFIG, sizeof szCfg); - while ((ch = getopt(argc, argv, "hvC:c:u:g:p:d:l:")) != -1) + while ((ch = getopt(argc, argv, "hvoC:c:u:g:p:d:l:")) != -1) switch (ch) { case 'l': f = fopen(optarg, "a"); @@ -295,19 +320,19 @@ main(int argc, char **argv) lf = f; break; case 'd': - strlcpy(proc.proc_dir, optarg, sizeof proc.proc_dir); - flg |= 8; + AIT_SET_STR(&proc.proc_dir, optarg); + flg |= SUX_GET_DIR; break; case 'p': - proc.proc_prio = strtol(optarg, NULL, 0); - flg |= 4; + AIT_SET_I32(&proc.proc_prio, strtol(optarg, NULL, 0)); + flg |= SUX_GET_PRIO; break; case 'g': setgrent(); grp = getgrnam(optarg); if (grp) { - proc.proc_gid = grp->gr_gid; - flg |= 2; + AIT_SET_I16(&proc.proc_gid, grp->gr_gid); + flg |= SUX_GET_GID; } else Err("Error:: Group not found!"); endgrent(); @@ -316,8 +341,8 @@ main(int argc, char **argv) setpwent(); pass = getpwnam(optarg); if (pass) { - proc.proc_uid = pass->pw_uid; - flg |= 1; + AIT_SET_I16(&proc.proc_uid, pass->pw_uid); + flg |= SUX_GET_UID; } else Err("Error:: User not found!"); endpwent(); @@ -328,13 +353,20 @@ main(int argc, char **argv) case 'C': if (chroot(optarg) == -1) Err("Error:: chroot to dir"); + if ((str = getenv("PATH_TRANSLATED"))) + if ((wrk = strstr(str, optarg))) + setenv("PATH_TRANSLATED", str + strlen(optarg), 42); break; + case 'o': + flg |= SUX_GET_FORCE; + break; case 'v': - Verbose++; + e_incVerbose; break; case 'h': default: Usage(); + endProg(); if (fileno(lf) > 2) fclose(lf); return 1; @@ -342,7 +374,7 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (2 <= Verbose) { + EVERBS(2) { for (pp = argv; *pp; pp++) Log(2, "Args=%s\n", *pp); for (pp = environ; *pp; pp++) @@ -352,36 +384,45 @@ main(int argc, char **argv) if (!argc) { if (!(str = getenv("PATH_TRANSLATED"))) { Usage(); + endProg(); if (fileno(lf) > 2) fclose(lf); return 1; } else - strlcpy(proc.proc_name, str, sizeof proc.proc_name); - } else - strlcpy(proc.proc_name, *argv, sizeof proc.proc_name); + AIT_SET_STR(&proc.proc_name, str); + } else if (strcmp(*argv, "-")) + AIT_SET_STR(&proc.proc_name, *argv); + else { + flg |= SUX_GET_STDIN; + AIT_SET_STR(&proc.proc_name, "-.stdin"); /* hack for associate to stdin */ + } Log(2, "Try to load config %s", szCfg); - if (LoadConfig(szCfg, &cfg)) { - Err("Error:: can`t load config #%d - %s\n", cfg_GetErrno(), cfg_GetError()); + if (cfgLoadConfig(szCfg, &cfg)) { + ELIBERR(cfg); + endProg(); if (fileno(lf) > 2) fclose(lf); return 2; } else if (LoadCfgData(flg) == -1) { - UnloadConfig(&cfg); + cfgUnloadConfig(&cfg); + endProg(); if (fileno(lf) > 2) fclose(lf); closelog(); return 3; } - UnloadConfig(&cfg); + cfgUnloadConfig(&cfg); - if (Run(argv) == -1) { + if (Run(argv, flg) == -1) { + endProg(); if (fileno(lf) > 2) fclose(lf); closelog(); return 4; } + endProg(); if (fileno(lf) > 2) fclose(lf); closelog();