Forbid Indexes
[nethome.git] / src / pserverchroot.c
1 #include <stdlib.h>
2 #include <syslog.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <errno.h>
6
7 extern const char **environ;
8
9
10 #define SETUID 613 /* "pserver" user  UID */
11 #define SETGID 613 /* "pserver" group GID */
12 #define PERMITTED_ENV_LIST "PWD"
13 #define EXEC_PATHNAME "/usr/bin/cvs"
14
15
16 #ifndef G_GNUC_NORETURN
17 #if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
18 #define G_GNUC_NORETURN __attribute__((noreturn))
19 #else   /* !__GNUC__ */
20 #define G_GNUC_NORETURN
21 #endif  /* !__GNUC__ */
22 #endif  /* !G_GNUC_NORETURN */
23
24 #define EXITLOG(msg...) do {\
25         openlog("pserverchroot",LOG_PID,LOG_DAEMON); \
26         syslog(LOG_CRIT,msg); \
27         closelog(); \
28         exit(EXIT_FAILURE); \
29         } while (0)
30
31 #define LENGTH(x) (sizeof((x))/sizeof(*(x)))
32
33 #define FUNCCHK(funcname,args...) do { \
34         if (errno=0,funcname(args)) \
35                 funcfail( #funcname ); \
36         } while (0)
37
38 static void funcfail(const char *funcname) G_GNUC_NORETURN;
39 static void funcfail(const char *funcname)
40 {
41         EXITLOG("Unable to %s(2): %s",funcname,strerror(errno));
42 }
43
44 int main(int argc,char **argv)
45 {
46 int total=0;
47 const char *allowed[]={ PERMITTED_ENV_LIST };
48 const char **allp,**envp;
49 char *dup=NULL,*s;
50
51 retry:
52         for (envp=environ;*envp;envp++) {
53                 if (dup) free(dup);
54                 dup=strdup(*envp);
55                 if ((s=strchr(dup,'='))) *s='\0';
56                 for (allp=allowed;allp<allowed+LENGTH(allowed);allp++)
57                         if (!strcmp(dup,*allp)) goto ok;
58                 if (total++>1000)
59                         EXITLOG("Unable to clean environment for CVS pserver: %s",*envp);
60                 unsetenv(dup);
61                 goto retry;
62 ok:;
63                 }
64         FUNCCHK(setenv,"PATH","/usr/bin",1);
65         FUNCCHK(chroot,"/home/short/pserver");
66         FUNCCHK(chdir,"/");
67         FUNCCHK(setgid,SETGID);
68         FUNCCHK(setuid,SETUID);
69         if (!getuid() || !geteuid() || !getgid() || !getegid())
70                 EXITLOG("Privileges NOT dropped!: uid=%d,euid=%d,gid=%d,egid=%d",
71                                 getuid(),geteuid(),getgid(),getegid());
72         errno=0,execv(EXEC_PATHNAME,argv);
73         funcfail("execv");
74 }