Annotation of suX/src/sux.c, revision 1.1

1.1     ! misho       1: /*************************************************************************
        !             2:  * (C) 2011 AITNET - Sofia/Bulgaria - <office@aitbg.com>
        !             3:  *  by Michael Pounov <misho@aitbg.com>
        !             4:  *
        !             5:  * $Author: misho $
        !             6:  * $Id: global.h,v 1.1.1.1 2009/04/22 22:38:22 misho Exp $
        !             7:  *
        !             8:  *************************************************************************/
        !             9: #include "global.h"
        !            10: 
        !            11: 
        !            12: sl_config cfg;
        !            13: int Verbose;
        !            14: struct tagProc proc;
        !            15: 
        !            16: 
        !            17: static inline void
        !            18: Log(int lvl, const char *fmt, ...)
        !            19: {
        !            20:        va_list lst;
        !            21: 
        !            22:        if (lvl <= Verbose) {
        !            23:                va_start(lst, fmt);
        !            24:                vsyslog(LOG_WARNING, fmt, lst);
        !            25:                va_end(lst);
        !            26:        }
        !            27: }
        !            28: 
        !            29: static inline void
        !            30: Err(const char *fmt, ...)
        !            31: {
        !            32:        va_list lst;
        !            33: 
        !            34:        va_start(lst, fmt);
        !            35:        vsyslog(LOG_ERR, fmt, lst);
        !            36:        va_end(lst);
        !            37: }
        !            38: 
        !            39: static void
        !            40: initProg()
        !            41: {
        !            42:        proc.proc_uid = getuid();
        !            43:        proc.proc_gid = getgid();
        !            44:        proc.proc_prio = getpriority(PRIO_PROCESS, 0);
        !            45:        getcwd(proc.proc_dir, sizeof proc.proc_dir);
        !            46: 
        !            47:        openlog(PACKAGE_NAME, LOG_CONS | LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER);
        !            48: }
        !            49: 
        !            50: static void
        !            51: Usage()
        !            52: {
        !            53:        printf( " -= suX =- suExecutor designed for web based applicaions\n"
        !            54:                "(C)`11 AITNET ltd - Sofia/Bulgaria - <office@aitnet.org>\n\n"
        !            55:                " Syntax: %s [options] <program> [arguments]\n"
        !            56:                "\t-u <user>\t\t\tUser for suID\n"
        !            57:                "\t-g <group>\t\t\tGroup for suID\n"
        !            58:                "\t-p <priority (-20..20)>\t\tExecute with priority\n"
        !            59:                "\t-d <directory>\t\t\tDirectory for suID\n"
        !            60:                "\t-v\t\t\t\tVerbose, (more -v, more verbosity)\n"
        !            61:                "\t-h\t\t\t\tThis help screen!\n\n", PACKAGE_NAME);
        !            62: }
        !            63: 
        !            64: static inline int
        !            65: setUIDGID(char flg, const char *name)
        !            66: {
        !            67:        struct stat sb;
        !            68: 
        !            69:        if (stat(name, &sb) == -1) {
        !            70:                Err("Error:: %s stat #%d - %s", name, errno, strerror(errno));
        !            71:                return -1;
        !            72:        }
        !            73: 
        !            74:        if (!(flg & 1))
        !            75:                proc.proc_uid = sb.st_uid;
        !            76:        if (!(flg & 2))
        !            77:                proc.proc_gid = sb.st_gid;
        !            78: 
        !            79:        return 0;
        !            80: }
        !            81: 
        !            82: static inline int
        !            83: SetClass()
        !            84: {
        !            85:        login_cap_t *cap;
        !            86:        struct passwd *pass;
        !            87: 
        !            88:        pass = getpwuid(proc.proc_uid);
        !            89:        if (!pass) {
        !            90:                Err("Error:: User with this UID %d not found", proc.proc_uid);
        !            91:                endpwent();
        !            92:                return -1;
        !            93:        } else 
        !            94:                strlcpy(proc.proc_class, pass->pw_class, sizeof proc.proc_class);
        !            95: 
        !            96:        cap = login_getclass(proc.proc_class);
        !            97:        if (!cap) {
        !            98:                Err("Error:: Cant get login class %s", proc.proc_class);
        !            99:                endpwent();
        !           100:                return -1;
        !           101:        }
        !           102: 
        !           103:        if (setusercontext(cap, pass, proc.proc_uid, LOGIN_SETALL)) {
        !           104:                Err("Error:: Cant set login class %s", proc.proc_class);
        !           105:                login_close(cap);
        !           106:                endpwent();
        !           107:                return -1;
        !           108:        }
        !           109: 
        !           110:        login_close(cap);
        !           111:        endpwent();
        !           112:        return 0;
        !           113: }
        !           114: 
        !           115: static int
        !           116: LoadCfgData(char flg)
        !           117: {
        !           118:        char *str, mode = 0;
        !           119: 
        !           120:        str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("mode"));
        !           121:        if (!str) {
        !           122:                Err("Error:: Unknown mode ...");
        !           123:                return -1;
        !           124:        }
        !           125:        if (!strcasecmp(str, "SCRIPT")) {
        !           126:                mode = 1;
        !           127:                if (setUIDGID(flg, proc.proc_name) == -1)
        !           128:                        return -1;
        !           129:        } else if (!strcasecmp(str, "FILE")) {
        !           130:                mode = 2;
        !           131:                if (setUIDGID(flg, proc.proc_name) == -1)
        !           132:                        return -1;
        !           133:        } else if (!strcasecmp(str, "DIR") && 
        !           134:                        (str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("directory")))) {
        !           135:                mode = 3;
        !           136:                if (!(flg & 8))
        !           137:                        strlcpy(proc.proc_dir, str, sizeof proc.proc_dir);
        !           138: 
        !           139:                if (setUIDGID(flg, proc.proc_dir) == -1)
        !           140:                        return -1;
        !           141:        } else {
        !           142:                Err("Error:: Unknown mode %s", str);
        !           143:                return -1;
        !           144:        }
        !           145:        if (!(flg & 4)) {
        !           146:                str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("priority"));
        !           147:                if (str)
        !           148:                        proc.proc_prio = strtol(str, NULL, 10);
        !           149:        }
        !           150: 
        !           151:        /* find associate extension */
        !           152:        str = strrchr(proc.proc_name, '.');
        !           153:        if (str) {
        !           154:                str++;
        !           155:                str = (*str) ? str : "default";
        !           156:                switch (cfg_LoadAttribute(&cfg, CFG("associate"), CFG(str), 
        !           157:                                        CFG(proc.proc_cmd), sizeof proc.proc_cmd, NULL)) {
        !           158:                        case -1:
        !           159:                                Err("Error:: can`t load attribute #%d - %s\n", cfg_GetErrno(), cfg_GetError());
        !           160:                                return -1;
        !           161:                        case 0:
        !           162:                                cfg_LoadAttribute(&cfg, CFG("associate"), CFG("default"), 
        !           163:                                                CFG(proc.proc_cmd), sizeof proc.proc_cmd, DEFAULT_CMD);
        !           164:                }
        !           165:        } else
        !           166:                strlcpy(proc.proc_cmd, DEFAULT_CMD, sizeof proc.proc_cmd);
        !           167: 
        !           168:        return 0;
        !           169: }
        !           170: 
        !           171: static int
        !           172: Run(char **argv)
        !           173: {
        !           174:        char **args, *cmd;
        !           175:        array_t *acmd, *aarg;
        !           176:        int n;
        !           177: 
        !           178:        if (!argv)
        !           179:                return -1;
        !           180: 
        !           181:        n = io_arrayMake(proc.proc_cmd, 0, " \t", &acmd);
        !           182:        if (n < 1)
        !           183:                return -1;
        !           184:        if (!(aarg = io_arrayFrom((const char**) argv, 0))) {
        !           185:                io_arrayDestroy(&acmd);
        !           186:                return -1;
        !           187:        } else if (*io_arrayGet(acmd, 0, char*) == '!') {
        !           188:                if (io_arrayGrow(acmd, 0)) {
        !           189:                        io_arrayDestroy(&aarg);
        !           190:                        io_arrayDestroy(&acmd);
        !           191:                        return -1;
        !           192:                }
        !           193:                cmd = io_arrayGet(aarg, 0, char*);
        !           194:        } else
        !           195:                cmd = io_arrayGet(acmd, 0, char*);
        !           196: 
        !           197:        if (io_arrayConcat(acmd, aarg) == -1) {
        !           198:                io_arrayDestroy(&aarg);
        !           199:                io_arrayDestroy(&acmd);
        !           200:                return -1;
        !           201:        }
        !           202:        io_arrayDestroy(&aarg);
        !           203:        if (!(args = io_arrayTo(acmd))) {
        !           204:                io_arrayDestroy(&acmd);
        !           205:                return -1;
        !           206:        }
        !           207:        io_arrayDestroy(&acmd);
        !           208: 
        !           209:        if (SetClass()) {
        !           210:                if (args)
        !           211:                        free(args);
        !           212:                return -1;
        !           213:        }
        !           214: 
        !           215:        if (setgid(proc.proc_gid) == -1) {
        !           216:                Err("Error:: setgid #%d - %s\n", errno, strerror(errno));
        !           217:                if (args)
        !           218:                        free(args);
        !           219:                return -1;
        !           220:        }
        !           221:        if (setuid(proc.proc_uid) == -1) {
        !           222:                Err("Error:: setuid #%d - %s\n", errno, strerror(errno));
        !           223:                if (args)
        !           224:                        free(args);
        !           225:                return -1;
        !           226:        }
        !           227:        if (setpriority(PRIO_PROCESS, 0, proc.proc_prio) == -1) {
        !           228:                Err("Error:: setpriority #%d - %s\n", errno, strerror(errno));
        !           229:                if (args)
        !           230:                        free(args);
        !           231:                return -1;
        !           232:        }
        !           233: 
        !           234:        if (3 <= Verbose) {
        !           235:                char **el = args - 1;
        !           236:                while (*++el)
        !           237:                        Log(3, "args: %s", *el);
        !           238:        }
        !           239: 
        !           240:        execve(cmd, args, environ);
        !           241:        if (args)
        !           242:                free(args);
        !           243:        Err("Error:: in exec() #%d - %s", errno, strerror(errno));
        !           244:        return -1;
        !           245: }
        !           246: 
        !           247: 
        !           248: int
        !           249: main(int argc, char **argv)
        !           250: {
        !           251:        char ch, *str, szCfg[MAXPATHLEN], flg = 0;
        !           252:        struct passwd *pass;
        !           253:        struct group *grp;
        !           254: 
        !           255:        initProg(*argv);
        !           256:        strlcpy(szCfg, DEFAULT_CONFIG, sizeof szCfg);
        !           257: 
        !           258:        while ((ch = getopt(argc, argv, "hvc:u:g:p:d:")) != -1)
        !           259:                switch (ch) {
        !           260:                        case 'd':
        !           261:                                strlcpy(proc.proc_dir, optarg, sizeof proc.proc_dir);
        !           262:                                flg |= 8;
        !           263:                                break;
        !           264:                        case 'p':
        !           265:                                proc.proc_prio = strtol(optarg, NULL, 0);
        !           266:                                flg |= 4;
        !           267:                                break;
        !           268:                        case 'g':
        !           269:                                setgrent();
        !           270:                                grp = getgrnam(optarg);
        !           271:                                if (grp) {
        !           272:                                        proc.proc_gid = grp->gr_gid;
        !           273:                                        flg |= 2;
        !           274:                                } else
        !           275:                                        Err("Error:: Group not found!");
        !           276:                                endgrent();
        !           277:                                break;
        !           278:                        case 'u':
        !           279:                                setpwent();
        !           280:                                pass = getpwnam(optarg);
        !           281:                                if (pass) {
        !           282:                                        proc.proc_uid = pass->pw_uid;
        !           283:                                        flg |= 1;
        !           284:                                } else
        !           285:                                        Err("Error:: User not found!");
        !           286:                                endpwent();
        !           287:                                break;
        !           288:                        case 'c':
        !           289:                                strlcpy(szCfg, optarg, sizeof szCfg);
        !           290:                                flg++;
        !           291:                                break;
        !           292:                        case 'v':
        !           293:                                Verbose++;
        !           294:                                break;
        !           295:                        case 'h':
        !           296:                        default:
        !           297:                                Usage();
        !           298:                                return 1;
        !           299:                }
        !           300:        argc -= optind;
        !           301:        argv += optind;
        !           302:        if (!argc) {
        !           303:                if (!(str = getenv("PATH_TRANSLATED"))) {
        !           304:                        Usage();
        !           305:                        return 1;
        !           306:                } else
        !           307:                        strlcpy(proc.proc_name, str, sizeof proc.proc_name);
        !           308:        } else
        !           309:                strlcpy(proc.proc_name, *argv, sizeof proc.proc_name);
        !           310:        Log(2, "Try to load config %s", szCfg);
        !           311:        if (LoadConfig(szCfg, &cfg)) {
        !           312:                Err("Error:: can`t load config #%d - %s\n", cfg_GetErrno(), cfg_GetError());
        !           313:                return 2;
        !           314:        } else
        !           315:                if (LoadCfgData(flg) == -1) {
        !           316:                        UnloadConfig(&cfg);
        !           317:                        closelog();
        !           318:                        return 3;
        !           319:                }
        !           320:        UnloadConfig(&cfg);
        !           321: 
        !           322:        Log(1, "UID:GID=%d:%d Prio=%d Class=%s Name=%s Dir=%s Cmd=%s\n", proc.proc_uid, proc.proc_gid, 
        !           323:                        proc.proc_prio, proc.proc_class, proc.proc_name, proc.proc_dir, proc.proc_cmd);
        !           324: 
        !           325:        if (Run(argv) == -1) {
        !           326:                closelog();
        !           327:                return 4;
        !           328:        }
        !           329: 
        !           330:        closelog();
        !           331:        return 0;
        !           332: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>