#include #include #include #include #include #include /* path to look for .pl scripts, .conf should be there too */ #define SCRIPT_PATH "/home/ant/scripts:/var/scripts/" char *find_script(char *); int main(int argc, char **argv) { struct stat caller; int fd; int euid,uid,loc; char script[1024]; char cmd[4096]; char key[256]; char conf[1024]; char path[10240]; char *tmp,*tmp2; char *scr_path; int i = 0; /* strip base name */ if(tmp = rindex(argv[0], '/')) { tmp++; } else { tmp = argv[0]; } /* remove extension */ if(tmp2 = index(tmp,'.')) { *tmp2 = '\0'; } /* save it */ strcpy(key, tmp); /* find where script with same base name is */ scr_path = find_script(key); /* has path info */ if(index(argv[0],'/')) { lstat(argv[0], &caller); } else { /* was called from PATH... seek it out and make sure it is legal */ strcpy(path,(char *)getenv("PATH")); tmp = path; while(tmp = strtok(tmp,":")) { strcpy(cmd,tmp); strcat(cmd,"/"); strcat(cmd,argv[0]); if(!lstat(cmd, &caller)) { break; } tmp = NULL; } } euid = geteuid(); uid = getuid(); /* is link owned by suid user or root? */ if(caller.st_uid != euid && uid != 0) { fprintf(stderr, "Invalid attempt to call loader from an unauthorized link, bad user, no biscuit!\n"); exit(1); } /* build paths to script and conf */ sprintf(conf, "%s/%s.conf", scr_path, key); sprintf(script, "%s/%s.pl", scr_path, key); /* open conf... RW if can, RO if not put on fd why 27 and 28? why not? doubt they will be used? */ fd = open(conf, O_RDWR); if(fd >= 0) dup2(fd, 27); else { fd = open(conf, O_RDONLY); dup2(fd, 28); } close(fd); /* we don't want to be special any more */ setuid(getuid()); seteuid(getuid()); setgid(getgid()); setegid(getgid()); /* become the perl script */ execvp(script,NULL); } char *find_script(char *key) { char *tmp; char path[4096]; char cmd[1024]; struct stat script; strcpy(path, SCRIPT_PATH); tmp = path; while(tmp = strtok(tmp,":")) { strcpy(cmd,tmp); strcat(cmd,"/"); strcat(cmd,key); strcat(cmd,".pl"); if(!lstat(cmd, &script)) { break; } tmp = NULL; } return tmp; }