Annotation of suX/src/sux.c, revision 1.1.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>