#include #include #include #include #include extern const char **environ; #define SETUID 554 /* "pserver" user UID */ #define SETGID 554 /* "pserver" group GID */ #define PERMITTED_ENV_LIST "PWD" #define EXEC_PATHNAME "/usr/bin/cvs" #ifndef G_GNUC_NORETURN #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) #define G_GNUC_NORETURN __attribute__((noreturn)) #else /* !__GNUC__ */ #define G_GNUC_NORETURN #endif /* !__GNUC__ */ #endif /* !G_GNUC_NORETURN */ #define EXITLOG(msg...) do {\ openlog("pserverchroot",LOG_PID,LOG_DAEMON); \ syslog(LOG_CRIT,msg); \ closelog(); \ exit(EXIT_FAILURE); \ } while (0) #define LENGTH(x) (sizeof((x))/sizeof(*(x))) #define FUNCCHK(funcname,args...) do { \ if (errno=0,funcname(args)) \ funcfail( #funcname ); \ } while (0) static void funcfail(const char *funcname) G_GNUC_NORETURN; static void funcfail(const char *funcname) { EXITLOG("Unable to %s(2): %s",funcname,strerror(errno)); } int main(int argc,char **argv) { int total=0; const char *allowed[]={ PERMITTED_ENV_LIST }; const char **allp,**envp; char *dup=NULL,*s; retry: for (envp=environ;*envp;envp++) { if (dup) free(dup); dup=strdup(*envp); if ((s=strchr(dup,'='))) *s='\0'; for (allp=allowed;allp1000) EXITLOG("Unable to clean environment for CVS pserver: %s",*envp); unsetenv(dup); goto retry; ok:; } FUNCCHK(setenv,"PATH","/usr/bin",1); FUNCCHK(chroot,"/home/short/pserver"); FUNCCHK(chdir,"/"); FUNCCHK(setgid,SETGID); FUNCCHK(setuid,SETUID); if (!getuid() || !geteuid() || !getgid() || !getegid()) EXITLOG("Privileges NOT dropped!: uid=%d,euid=%d,gid=%d,egid=%d", getuid(),geteuid(),getgid(),getegid()); errno=0,execv(EXEC_PATHNAME,argv); funcfail("execv"); }