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>