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>