Annotation of suX/src/sux.c, revision 1.1.1.1.2.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 $
1.1.1.1.2.1! misho       6:  * $Id: sux.c,v 1.1.1.1 2011/05/20 16:02:05 misho Exp $
1.1       misho       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: 
1.1.1.1.2.1! misho     234:        Log(1, "UID:GID=%d:%d Prio=%d Class=%s Name=%s Dir=%s Cmd=%s\n", proc.proc_uid, proc.proc_gid, 
        !           235:                        proc.proc_prio, proc.proc_class, proc.proc_name, proc.proc_dir, proc.proc_cmd);
        !           236: 
1.1       misho     237:        if (3 <= Verbose) {
                    238:                char **el = args - 1;
                    239:                while (*++el)
                    240:                        Log(3, "args: %s", *el);
                    241:        }
                    242: 
                    243:        execve(cmd, args, environ);
                    244:        if (args)
                    245:                free(args);
                    246:        Err("Error:: in exec() #%d - %s", errno, strerror(errno));
                    247:        return -1;
                    248: }
                    249: 
                    250: 
                    251: int
                    252: main(int argc, char **argv)
                    253: {
                    254:        char ch, *str, szCfg[MAXPATHLEN], flg = 0;
                    255:        struct passwd *pass;
                    256:        struct group *grp;
                    257: 
                    258:        initProg(*argv);
                    259:        strlcpy(szCfg, DEFAULT_CONFIG, sizeof szCfg);
                    260: 
                    261:        while ((ch = getopt(argc, argv, "hvc:u:g:p:d:")) != -1)
                    262:                switch (ch) {
                    263:                        case 'd':
                    264:                                strlcpy(proc.proc_dir, optarg, sizeof proc.proc_dir);
                    265:                                flg |= 8;
                    266:                                break;
                    267:                        case 'p':
                    268:                                proc.proc_prio = strtol(optarg, NULL, 0);
                    269:                                flg |= 4;
                    270:                                break;
                    271:                        case 'g':
                    272:                                setgrent();
                    273:                                grp = getgrnam(optarg);
                    274:                                if (grp) {
                    275:                                        proc.proc_gid = grp->gr_gid;
                    276:                                        flg |= 2;
                    277:                                } else
                    278:                                        Err("Error:: Group not found!");
                    279:                                endgrent();
                    280:                                break;
                    281:                        case 'u':
                    282:                                setpwent();
                    283:                                pass = getpwnam(optarg);
                    284:                                if (pass) {
                    285:                                        proc.proc_uid = pass->pw_uid;
                    286:                                        flg |= 1;
                    287:                                } else
                    288:                                        Err("Error:: User not found!");
                    289:                                endpwent();
                    290:                                break;
                    291:                        case 'c':
                    292:                                strlcpy(szCfg, optarg, sizeof szCfg);
                    293:                                flg++;
                    294:                                break;
                    295:                        case 'v':
                    296:                                Verbose++;
                    297:                                break;
                    298:                        case 'h':
                    299:                        default:
                    300:                                Usage();
                    301:                                return 1;
                    302:                }
                    303:        argc -= optind;
                    304:        argv += optind;
                    305:        if (!argc) {
                    306:                if (!(str = getenv("PATH_TRANSLATED"))) {
                    307:                        Usage();
                    308:                        return 1;
                    309:                } else
                    310:                        strlcpy(proc.proc_name, str, sizeof proc.proc_name);
                    311:        } else
                    312:                strlcpy(proc.proc_name, *argv, sizeof proc.proc_name);
                    313:        Log(2, "Try to load config %s", szCfg);
                    314:        if (LoadConfig(szCfg, &cfg)) {
                    315:                Err("Error:: can`t load config #%d - %s\n", cfg_GetErrno(), cfg_GetError());
                    316:                return 2;
                    317:        } else
                    318:                if (LoadCfgData(flg) == -1) {
                    319:                        UnloadConfig(&cfg);
                    320:                        closelog();
                    321:                        return 3;
                    322:                }
                    323:        UnloadConfig(&cfg);
                    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>