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

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

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