File:  [ELWIX - Embedded LightWeight unIX -] / suX / src / sux.c
Revision 1.1.1.1.2.4: download - view: text, annotated - select for diffs - revision graph
Fri May 20 16:41:31 2011 UTC (13 years, 2 months ago) by misho
Branches: sux2_0
Diff to: branchpoint 1.1.1.1: preferred, unified
misc fixes

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

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