version 1.1, 2011/05/20 16:02:05
|
version 1.3.2.2, 2013/04/09 08:29:20
|
Line 9
|
Line 9
|
#include "global.h" |
#include "global.h" |
|
|
|
|
sl_config cfg; | cfg_root_t cfg; |
int Verbose; |
int Verbose; |
struct tagProc proc; |
struct tagProc proc; |
|
FILE *lf; |
|
|
|
|
static inline void |
static inline void |
Log(int lvl, const char *fmt, ...) |
Log(int lvl, const char *fmt, ...) |
{ |
{ |
va_list lst; | va_list lst, cp; |
|
|
if (lvl <= Verbose) { |
if (lvl <= Verbose) { |
va_start(lst, fmt); |
va_start(lst, fmt); |
vsyslog(LOG_WARNING, fmt, lst); | va_copy(cp, lst); |
| vfprintf(lf, fmt, lst); |
va_end(lst); |
va_end(lst); |
|
fprintf(lf, "\n"); |
|
vsyslog(LOG_WARNING, fmt, cp); |
|
va_end(cp); |
} |
} |
} |
} |
|
|
static inline void |
static inline void |
Err(const char *fmt, ...) |
Err(const char *fmt, ...) |
{ |
{ |
va_list lst; | va_list lst, cp; |
|
|
va_start(lst, fmt); |
va_start(lst, fmt); |
vsyslog(LOG_ERR, fmt, lst); | va_copy(cp, lst); |
| vfprintf(lf, fmt, lst); |
va_end(lst); |
va_end(lst); |
|
fprintf(lf, "\n"); |
|
vsyslog(LOG_ERR, fmt, cp); |
|
va_end(cp); |
} |
} |
|
|
static void |
static void |
initProg() |
initProg() |
{ |
{ |
proc.proc_uid = getuid(); | char d[MAXPATHLEN]; |
proc.proc_gid = getgid(); | |
proc.proc_prio = getpriority(PRIO_PROCESS, 0); | |
getcwd(proc.proc_dir, sizeof proc.proc_dir); | |
|
|
openlog(PACKAGE_NAME, LOG_CONS | LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER); | AIT_SET_I16(&proc.proc_uid, getuid()); |
| AIT_SET_I16(&proc.proc_gid, getgid()); |
| AIT_SET_I32(&proc.proc_prio, getpriority(PRIO_PROCESS, 0)); |
| getcwd(d, sizeof d); |
| AIT_SET_STR(&proc.proc_dir, d); |
| |
| #if 0 |
| lf = fopen(DEFAULT_LOG, "a"); |
| if (!lf) |
| #endif |
| lf = stdout; |
| |
| openlog(PACKAGE_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER); |
} |
} |
|
|
static void |
static void |
Line 57 Usage()
|
Line 75 Usage()
|
"\t-g <group>\t\t\tGroup for suID\n" |
"\t-g <group>\t\t\tGroup for suID\n" |
"\t-p <priority (-20..20)>\t\tExecute with priority\n" |
"\t-p <priority (-20..20)>\t\tExecute with priority\n" |
"\t-d <directory>\t\t\tDirectory for suID\n" |
"\t-d <directory>\t\t\tDirectory for suID\n" |
|
"\t-C <directory>\t\t\tChroot to directory\n" |
|
"\t-c <cfgfile>\t\t\tConfig file\n" |
|
"\t-l <logfile>\t\t\tLog file path (default:/var/log/suX.log)\n" |
"\t-v\t\t\t\tVerbose, (more -v, more verbosity)\n" |
"\t-v\t\t\t\tVerbose, (more -v, more verbosity)\n" |
"\t-h\t\t\t\tThis help screen!\n\n", PACKAGE_NAME); |
"\t-h\t\t\t\tThis help screen!\n\n", PACKAGE_NAME); |
} |
} |
Line 72 setUIDGID(char flg, const char *name)
|
Line 93 setUIDGID(char flg, const char *name)
|
} |
} |
|
|
if (!(flg & 1)) |
if (!(flg & 1)) |
proc.proc_uid = sb.st_uid; | AIT_SET_I16(&proc.proc_uid, sb.st_uid); |
if (!(flg & 2)) |
if (!(flg & 2)) |
proc.proc_gid = sb.st_gid; | AIT_SET_I16(&proc.proc_gid, sb.st_gid); |
|
|
return 0; |
return 0; |
} |
} |
Line 85 SetClass()
|
Line 106 SetClass()
|
login_cap_t *cap; |
login_cap_t *cap; |
struct passwd *pass; |
struct passwd *pass; |
|
|
pass = getpwuid(proc.proc_uid); | pass = getpwuid(AIT_GET_I16(&proc.proc_uid)); |
if (!pass) { |
if (!pass) { |
Err("Error:: User with this UID %d not found", proc.proc_uid); |
Err("Error:: User with this UID %d not found", proc.proc_uid); |
endpwent(); |
endpwent(); |
return -1; |
return -1; |
} else |
} else |
strlcpy(proc.proc_class, pass->pw_class, sizeof proc.proc_class); | AIT_SET_STR(&proc.proc_class, pass->pw_class); |
|
|
cap = login_getclass(proc.proc_class); | cap = login_getclass(AIT_GET_STR(&proc.proc_class)); |
if (!cap) { |
if (!cap) { |
Err("Error:: Cant get login class %s", proc.proc_class); | Err("Error:: Cant get login class %s", AIT_GET_STR(&proc.proc_class)); |
endpwent(); |
endpwent(); |
return -1; |
return -1; |
} |
} |
|
|
if (setusercontext(cap, pass, proc.proc_uid, LOGIN_SETALL)) { | if (setusercontext(cap, pass, AIT_GET_I16(&proc.proc_uid), LOGIN_SETALL)) { |
Err("Error:: Cant set login class %s", proc.proc_class); | Err("Error:: Cant set login class %s", AIT_GET_STR(&proc.proc_class)); |
login_close(cap); |
login_close(cap); |
endpwent(); |
endpwent(); |
return -1; |
return -1; |
Line 115 SetClass()
|
Line 136 SetClass()
|
static int |
static int |
LoadCfgData(char flg) |
LoadCfgData(char flg) |
{ |
{ |
char *str, mode = 0; | const char *str; |
| char mode = 0; |
|
|
str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("mode")); | str = cfg_getAttribute(&cfg, "global", "mode"); |
if (!str) { |
if (!str) { |
Err("Error:: Unknown mode ..."); |
Err("Error:: Unknown mode ..."); |
return -1; |
return -1; |
} |
} |
if (!strcasecmp(str, "SCRIPT")) { |
if (!strcasecmp(str, "SCRIPT")) { |
mode = 1; |
mode = 1; |
if (setUIDGID(flg, proc.proc_name) == -1) | if (setUIDGID(flg, AIT_GET_STR(&proc.proc_name)) == -1) |
return -1; |
return -1; |
} else if (!strcasecmp(str, "FILE")) { |
} else if (!strcasecmp(str, "FILE")) { |
mode = 2; |
mode = 2; |
if (setUIDGID(flg, proc.proc_name) == -1) | if (setUIDGID(flg, AIT_GET_STR(&proc.proc_name)) == -1) |
return -1; |
return -1; |
} else if (!strcasecmp(str, "DIR") && |
} else if (!strcasecmp(str, "DIR") && |
(str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("directory")))) { | (str = cfg_getAttribute(&cfg, "global", "directory"))) { |
mode = 3; |
mode = 3; |
if (!(flg & 8)) |
if (!(flg & 8)) |
strlcpy(proc.proc_dir, str, sizeof proc.proc_dir); | AIT_SET_STR(&proc.proc_dir, str); |
|
|
if (setUIDGID(flg, proc.proc_dir) == -1) | if (setUIDGID(flg, AIT_GET_STR(&proc.proc_dir)) == -1) |
return -1; |
return -1; |
} else { |
} else { |
Err("Error:: Unknown mode %s", str); |
Err("Error:: Unknown mode %s", str); |
return -1; |
return -1; |
} |
} |
if (!(flg & 4)) { |
if (!(flg & 4)) { |
str = (char*) cfg_GetAttribute(&cfg, CFG("global"), CFG("priority")); | str = cfg_getAttribute(&cfg, "global", "priority"); |
if (str) |
if (str) |
proc.proc_prio = strtol(str, NULL, 10); | AIT_SET_I32(&proc.proc_prio, strtol(str, NULL, 10)); |
} |
} |
|
|
/* find associate extension */ |
/* find associate extension */ |
str = strrchr(proc.proc_name, '.'); | str = strrchr(AIT_GET_STR(&proc.proc_name), '.'); |
if (str) { |
if (str) { |
str++; |
str++; |
str = (*str) ? str : "default"; |
str = (*str) ? str : "default"; |
switch (cfg_LoadAttribute(&cfg, CFG("associate"), CFG(str), | switch (cfg_loadAttribute(&cfg, "associate", str, &proc.proc_cmd, NULL)) { |
CFG(proc.proc_cmd), sizeof proc.proc_cmd, NULL)) { | |
case -1: |
case -1: |
Err("Error:: can`t load attribute #%d - %s\n", cfg_GetErrno(), cfg_GetError()); | ELIBERR(cfg); |
return -1; |
return -1; |
case 0: |
case 0: |
cfg_LoadAttribute(&cfg, CFG("associate"), CFG("default"), | cfg_loadAttribute(&cfg, "associate", "default", &proc.proc_cmd, DEFAULT_CMD); |
CFG(proc.proc_cmd), sizeof proc.proc_cmd, DEFAULT_CMD); | |
} |
} |
} else |
} else |
strlcpy(proc.proc_cmd, DEFAULT_CMD, sizeof proc.proc_cmd); | AIT_SET_STR(&proc.proc_cmd, DEFAULT_CMD); |
|
|
return 0; |
return 0; |
} |
} |
Line 178 Run(char **argv)
|
Line 198 Run(char **argv)
|
if (!argv) |
if (!argv) |
return -1; |
return -1; |
|
|
n = io_arrayMake(proc.proc_cmd, 0, " \t", &acmd); | n = array_Args(AIT_GET_STR(&proc.proc_cmd), 0, " \t", &acmd); |
if (n < 1) |
if (n < 1) |
return -1; |
return -1; |
if (!(aarg = io_arrayFrom((const char**) argv, 0))) { | if (!(aarg = array_From((const char***) &argv, 0))) { |
io_arrayDestroy(&acmd); | array_Destroy(&acmd); |
return -1; |
return -1; |
} else if (*io_arrayGet(acmd, 0, char*) == '!') { | } else if (*array(acmd, 0, char*) == '!') { |
if (io_arrayGrow(acmd, 0)) { | if (array_Grow(acmd, 0, 0)) { |
io_arrayDestroy(&aarg); | array_Destroy(&aarg); |
io_arrayDestroy(&acmd); | array_Destroy(&acmd); |
return -1; |
return -1; |
} |
} |
cmd = io_arrayGet(aarg, 0, char*); | cmd = array(aarg, 0, char*); |
} else |
} else |
cmd = io_arrayGet(acmd, 0, char*); | cmd = array(acmd, 0, char*); |
|
|
if (io_arrayConcat(acmd, aarg) == -1) { | if (array_Concat(acmd, aarg) == -1) { |
io_arrayDestroy(&aarg); | array_Destroy(&aarg); |
io_arrayDestroy(&acmd); | array_Destroy(&acmd); |
return -1; |
return -1; |
} |
} |
io_arrayDestroy(&aarg); | array_Destroy(&aarg); |
if (!(args = io_arrayTo(acmd))) { | if (!(args = array_To(acmd))) { |
io_arrayDestroy(&acmd); | array_Destroy(&acmd); |
return -1; |
return -1; |
} |
} |
io_arrayDestroy(&acmd); | array_Destroy(&acmd); |
|
|
if (SetClass()) { |
if (SetClass()) { |
if (args) |
if (args) |
Line 212 Run(char **argv)
|
Line 232 Run(char **argv)
|
return -1; |
return -1; |
} |
} |
|
|
|
/* |
if (setgid(proc.proc_gid) == -1) { |
if (setgid(proc.proc_gid) == -1) { |
Err("Error:: setgid #%d - %s\n", errno, strerror(errno)); |
Err("Error:: setgid #%d - %s\n", errno, strerror(errno)); |
if (args) |
if (args) |
Line 230 Run(char **argv)
|
Line 251 Run(char **argv)
|
free(args); |
free(args); |
return -1; |
return -1; |
} |
} |
|
*/ |
|
|
|
Log(0, "UID:GID=%d:%d Prio=%d Class=%s Name=%s Dir=%s Cmd=%s Script=%s", |
|
proc.proc_uid, proc.proc_gid, proc.proc_prio, AIT_GET_STR(&proc.proc_class), |
|
AIT_GET_STR(&proc.proc_name), AIT_GET_STR(&proc.proc_dir), |
|
AIT_GET_STR(&proc.proc_cmd), getenv("PATH_TRANSLATED")); |
|
|
if (3 <= Verbose) { |
if (3 <= Verbose) { |
char **el = args - 1; |
char **el = args - 1; |
while (*++el) |
while (*++el) |
Log(3, "args: %s", *el); |
Log(3, "args: %s", *el); |
} |
} |
|
|
|
fflush(lf); |
|
|
execve(cmd, args, environ); |
execve(cmd, args, environ); |
if (args) |
if (args) |
free(args); |
free(args); |
Line 248 Run(char **argv)
|
Line 277 Run(char **argv)
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
char ch, *str, szCfg[MAXPATHLEN], flg = 0; | char ch, *str, *wrk, szCfg[MAXPATHLEN], **pp, flg = 0; |
struct passwd *pass; |
struct passwd *pass; |
struct group *grp; |
struct group *grp; |
|
FILE *f; |
|
|
initProg(*argv); | initProg(); |
strlcpy(szCfg, DEFAULT_CONFIG, sizeof szCfg); |
strlcpy(szCfg, DEFAULT_CONFIG, sizeof szCfg); |
|
|
while ((ch = getopt(argc, argv, "hvc:u:g:p:d:")) != -1) | while ((ch = getopt(argc, argv, "hvC:c:u:g:p:d:l:")) != -1) |
switch (ch) { |
switch (ch) { |
|
case 'l': |
|
f = fopen(optarg, "a"); |
|
if (!f) { |
|
Err("Error:: logfile #%d - %s", errno, strerror(errno)); |
|
return 1; |
|
} else |
|
if (fileno(lf) > 2) |
|
fclose(lf); |
|
lf = f; |
|
break; |
case 'd': |
case 'd': |
strlcpy(proc.proc_dir, optarg, sizeof proc.proc_dir); | AIT_SET_STR(&proc.proc_dir, optarg); |
flg |= 8; |
flg |= 8; |
break; |
break; |
case 'p': |
case 'p': |
proc.proc_prio = strtol(optarg, NULL, 0); | AIT_SET_I32(&proc.proc_prio, strtol(optarg, NULL, 0)); |
flg |= 4; |
flg |= 4; |
break; |
break; |
case 'g': |
case 'g': |
setgrent(); |
setgrent(); |
grp = getgrnam(optarg); |
grp = getgrnam(optarg); |
if (grp) { |
if (grp) { |
proc.proc_gid = grp->gr_gid; | AIT_SET_I16(&proc.proc_gid, grp->gr_gid); |
flg |= 2; |
flg |= 2; |
} else |
} else |
Err("Error:: Group not found!"); |
Err("Error:: Group not found!"); |
Line 279 main(int argc, char **argv)
|
Line 319 main(int argc, char **argv)
|
setpwent(); |
setpwent(); |
pass = getpwnam(optarg); |
pass = getpwnam(optarg); |
if (pass) { |
if (pass) { |
proc.proc_uid = pass->pw_uid; | AIT_SET_I16(&proc.proc_uid, pass->pw_uid); |
flg |= 1; |
flg |= 1; |
} else |
} else |
Err("Error:: User not found!"); |
Err("Error:: User not found!"); |
Line 287 main(int argc, char **argv)
|
Line 327 main(int argc, char **argv)
|
break; |
break; |
case 'c': |
case 'c': |
strlcpy(szCfg, optarg, sizeof szCfg); |
strlcpy(szCfg, optarg, sizeof szCfg); |
flg++; |
|
break; |
break; |
|
case 'C': |
|
if (chroot(optarg) == -1) |
|
Err("Error:: chroot to dir"); |
|
if ((str = getenv("PATH_TRANSLATED"))) |
|
if ((wrk = strstr(str, optarg))) |
|
setenv("PATH_TRANSLATED", str + strlen(optarg), 42); |
|
break; |
case 'v': |
case 'v': |
Verbose++; |
Verbose++; |
break; |
break; |
case 'h': |
case 'h': |
default: |
default: |
Usage(); |
Usage(); |
|
if (fileno(lf) > 2) |
|
fclose(lf); |
return 1; |
return 1; |
} |
} |
argc -= optind; |
argc -= optind; |
argv += optind; |
argv += optind; |
|
|
|
if (2 <= Verbose) { |
|
for (pp = argv; *pp; pp++) |
|
Log(2, "Args=%s\n", *pp); |
|
for (pp = environ; *pp; pp++) |
|
Log(2, "Envs=%s\n", *pp); |
|
} |
|
|
if (!argc) { |
if (!argc) { |
if (!(str = getenv("PATH_TRANSLATED"))) { |
if (!(str = getenv("PATH_TRANSLATED"))) { |
Usage(); |
Usage(); |
|
if (fileno(lf) > 2) |
|
fclose(lf); |
return 1; |
return 1; |
} else |
} else |
strlcpy(proc.proc_name, str, sizeof proc.proc_name); | AIT_SET_STR(&proc.proc_name, str); |
} else |
} else |
strlcpy(proc.proc_name, *argv, sizeof proc.proc_name); | AIT_SET_STR(&proc.proc_name, *argv); |
Log(2, "Try to load config %s", szCfg); |
Log(2, "Try to load config %s", szCfg); |
if (LoadConfig(szCfg, &cfg)) { | if (cfgLoadConfig(szCfg, &cfg)) { |
Err("Error:: can`t load config #%d - %s\n", cfg_GetErrno(), cfg_GetError()); |
Err("Error:: can`t load config #%d - %s\n", cfg_GetErrno(), cfg_GetError()); |
|
if (fileno(lf) > 2) |
|
fclose(lf); |
return 2; |
return 2; |
} else |
} else |
if (LoadCfgData(flg) == -1) { |
if (LoadCfgData(flg) == -1) { |
UnloadConfig(&cfg); | cfgUnloadConfig(&cfg); |
| if (fileno(lf) > 2) |
| fclose(lf); |
closelog(); |
closelog(); |
return 3; |
return 3; |
} |
} |
UnloadConfig(&cfg); | cfgUnloadConfig(&cfg); |
|
|
Log(1, "UID:GID=%d:%d Prio=%d Class=%s Name=%s Dir=%s Cmd=%s\n", proc.proc_uid, proc.proc_gid, |
|
proc.proc_prio, proc.proc_class, proc.proc_name, proc.proc_dir, proc.proc_cmd); |
|
|
|
if (Run(argv) == -1) { |
if (Run(argv) == -1) { |
|
if (fileno(lf) > 2) |
|
fclose(lf); |
closelog(); |
closelog(); |
return 4; |
return 4; |
} |
} |
|
|
|
if (fileno(lf) > 2) |
|
fclose(lf); |
closelog(); |
closelog(); |
return 0; |
return 0; |
} |
} |