#include #include #include #include #include extern const char **environ; #define ZONES "jankratochvil.net","dyn.jankratochvil.net" #define SETUID 0 /* user UID */ #define SETGID 0 /* group GID */ #define PERMITTED_ENV_LIST "PWD" #define EXEC_PATHNAME "/usr/sbin/rndc" #define EXEC_ARGV(zone) "/usr/sbin/rndc","reload",(zone),NULL #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("ndc-reload-short",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: %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; const char *zones_allowed[]={ ZONES }; errno=0; if (argc!=2) funcfail("argc!=2"); for (allp=zones_allowed;allp=zones_allowed+LENGTH(zones_allowed)) funcfail("zone rejected"); 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 'ndc': %s",*envp); unsetenv(dup); goto retry; ok:; } FUNCCHK(setenv,"PATH","/usr/bin",1); FUNCCHK(chdir,"/"); FUNCCHK(setgid,SETGID); FUNCCHK(setuid,SETUID); errno=0,execl(EXEC_PATHNAME,EXEC_ARGV(argv[1])); funcfail("execl()"); }