/* NB: defaults for the execution state are not set here, but in
* the RESET_CONFIGURATION #define in daemon.h. */
-char **argarray;
-char *((*defvararray)[2]);
+struct request_msg request_mbuf;
+struct keyvaluepair *defvararray;
struct fdstate *fdarray;
int fdarraysize, fdarrayused;
int restfdwantstate= tokv_word_rejectfd, restfdwantrw;
-struct request_msg request_mbuf;
+int service_ngids;
+char **argarray;
char *serviceuser, *service, *logname, *cwd;
char *overridedata, *userrcfile;
char *serviceuser_dir, *serviceuser_shell, *callinguser_shell;
-int service_ngids;
gid_t *calling_gids, *service_gids;
-const char **calling_groups, **service_groups;
uid_t serviceuser_uid=-1;
+const char **calling_groups, **service_groups;
char *execpath, **execargs;
int execute;
int setenvironment, suppressargs, disconnecthup;
+builtinserviceexec_fnt *execbuiltin;
int syslogopenfacility=-1;
static FILE *swfile, *srfile;
return 0;
}
+const char *defaultpath(void) {
+ return serviceuser_uid ? DEFAULTPATH_USER : DEFAULTPATH_ROOT;
+}
+
/* General-purpose functions; these do nothing special about signals */
static void blocksignals(void) {
}
static void receive_request(void) {
- int i,j, fd;
+ int i, fd;
unsigned long ul;
xfread(&request_mbuf,sizeof(request_mbuf));
fdarray[fd].iswrite= (i>=request_mbuf.nreadfds);
}
- assert(request_mbuf.nargs <= MAX_ARGSDEFVARS);
+ assert(request_mbuf.nargs <= MAX_ARGSDEFVAR);
argarray= xmalloc(sizeof(char*)*(request_mbuf.nargs));
for (i=0; i<request_mbuf.nargs; i++) argarray[i]= xfreadstring();
- assert(request_mbuf.nvars <= MAX_ARGSDEFVARS);
- defvararray= xmalloc(sizeof(char*)*request_mbuf.nvars*2);
- for (i=0; i<request_mbuf.nvars; i++)
- for (j=0; j<2; j++) defvararray[i][j]= xfreadstring();
+ assert(request_mbuf.nvars <= MAX_ARGSDEFVAR);
+ defvararray= xmalloc(sizeof(struct keyvaluepair)*request_mbuf.nvars);
+ for (i=0; i<request_mbuf.nvars; i++) {
+ defvararray[i].key= xfreadstring();
+ assert(defvararray[i].key[0]);
+ defvararray[i].value= xfreadstring();
+ }
xfread(&ul,sizeof(ul));
assert(ul == REQUEST_END_MAGIC);
}
static void establish_pipes(void) {
int fd, tempfd;
- char pipepathbuf[PIPEMAXLEN];
+ char pipepathbuf[PIPEMAXLEN+2];
for (fd=0; fd<fdarrayused; fd++) {
if (fdarray[fd].iswrite == -1) continue;
- snyprintf(pipepathbuf,sizeof(pipepathbuf), PIPEFORMAT,
+ pipepathbuf[sizeof(pipepathbuf)-2]= 0;
+ snyprintf(pipepathbuf,sizeof(pipepathbuf),PIPEFORMAT,
(unsigned long)request_mbuf.clientpid,(unsigned long)mypid,fd);
+ assert(!pipepathbuf[sizeof(pipepathbuf)-2]);
tempfd= open(pipepathbuf,O_RDWR);
- if (tempfd == -1) syscallerror("prelim open pipe");
- if (!fdarray[fd].iswrite) {
- fdarray[fd].holdfd= open(pipepathbuf, O_WRONLY);
- if (fdarray[fd].holdfd == -1) syscallerror("hold open pipe");
- fdarray[fd].realfd= open(pipepathbuf, O_RDONLY);
- } else {
+ if (tempfd<0) syscallerror("prelim open pipe");
+ if (fdarray[fd].iswrite) {
fdarray[fd].holdfd= -1;
fdarray[fd].realfd= open(pipepathbuf, O_WRONLY);
+ } else {
+ fdarray[fd].holdfd= open(pipepathbuf, O_WRONLY);
+ if (fdarray[fd].holdfd<0) syscallerror("hold open pipe");
+ fdarray[fd].realfd= open(pipepathbuf, O_RDONLY);
}
- if (fdarray[fd].realfd == -1) syscallerror("real open pipe");
+ if (fdarray[fd].realfd<0) syscallerror("real open pipe");
if (unlink(pipepathbuf)) syscallerror("unlink pipe");
if (close(tempfd)) syscallerror("close prelim fd onto pipe");
}
serviceuser_dir= xstrsave(nondebug_serviceuserdir(pw->pw_dir));
serviceuser_shell= xstrsave(pw->pw_shell);
serviceuser_uid= pw->pw_uid;
+
if (initgroups(pw->pw_name,pw->pw_gid)) syscallerror("initgroups");
if (setreuid(pw->pw_uid,pw->pw_uid)) syscallerror("setreuid 1");
if (setreuid(pw->pw_uid,pw->pw_uid)) syscallerror("setreuid 2");
r= stat(execpath,&stab);
if (r) syscallfailure("checking for executable in directory, `%s'",execpath);
break;
+ case tokv_word_executebuiltin:
+ break;
case tokv_word_executefrompath:
if (strchr(service,'/')) {
r= stat(service,&stab);
execpath= service;
} else {
string= getenv("PATH");
- if (!string) failure("execute-from-path, but daemon inherited no PATH !");
+ if (!string) string= defaultpath();
while (string) {
delim= strchr(string,':');
if (delim) {
- if (delim-string > INT_MAX)
+ if (delim-string > MAX_GENERAL_STRING)
failure("execute-from-path, but PATH component too long");
partsize= delim-string;
nextstring= delim+1;
fdarray[fd].realfd= open("/dev/null",
fdarray[fd].iswrite == -1 ? O_RDWR :
fdarray[fd].iswrite ? O_WRONLY : O_RDONLY);
- if (fdarray[fd].realfd == -1)
+ if (fdarray[fd].realfd<0)
syscallfailure("cannot open /dev/null for null fd");
break;
case tokv_word_requirefd:
if (fdarray[fd].realfd == -1) {
fdarray[fd].iswrite= (fdarray[fd].wantrw == tokv_word_write);
fdarray[fd].realfd= open("/dev/null",fdarray[fd].iswrite ? O_WRONLY : O_RDONLY);
- if (fdarray[fd].realfd == -1)
+ if (fdarray[fd].realfd<0)
syscallfailure("cannot open /dev/null for allowed but not provided fd");
} else {
if (fdarray[fd].iswrite) {
"<builtin toplevel configuration>",1);
ensurelogopen(USERVD_LOGFACILITY);
- if (r == tokv_error) failure("error encountered while parsing configuration files");
+ if (r == tokv_error) failure("error encountered while parsing configuration");
assert(r == tokv_quit);
debug_dumpexecsettings();