int portal_file(struct portal_cred *pcr, char *key, char **v, int so __unused, int *fdp) { int fd; char pbuf[MAXPATHLEN]; int error; struct portal_cred save_area; pbuf[0] = '/'; strcpy(pbuf+1, key + (v[1] ? strlen(v[1]) : 0)); #ifdef DEBUG printf("path = %s, uid = %d, gid = %d\n", pbuf, pcr->pcr_uid, pcr->pcr_groups[0]); printf ("fflag = %x, oflag = %x\n", pcr->pcr_flag, (pcr->pcr_flag)-1); #endif if (set_user_credentials(pcr, &save_area) < 0) return (errno); /* dmb convert kernel flags to oflags, see <fcntl.h> */ fd = open(pbuf, (pcr->pcr_flag)-1, 0777); if (fd < 0) error = errno; else error = 0; if (restore_credentials(&save_area) < 0) { error = errno; if (fd >= 0) { (void) close(fd); fd = -1; } } if (error == 0) *fdp = fd; #ifdef DEBUG fprintf(stderr, "pt_file returns *fdp = %d, error = %d\n", *fdp, error); #endif return (error); }
int portal_pipe(struct portal_cred *pcr, char *key, char **v, int kso __unused, int *fdp) { int fd[2]; /* Pipe endpoints. */ int caller_end; /* The pipe end we will use. */ int process_end; /* The pipe end the spawned process will use. */ int redirect_fd; /* The fd to redirect on the spawned process. */ char pbuf[MAXPATHLEN]; int error = 0; int i; char **argv; int argc; struct portal_cred save_area; /* Validate open mode, and assign roles. */ if ((pcr->pcr_flag & FWRITE) && (pcr->pcr_flag & FREAD)) /* Don't allow both on a single fd. */ return (EINVAL); else if (pcr->pcr_flag & FREAD) { /* * The caller reads from the pipe, * the spawned process writes to it. */ caller_end = READ_END; process_end = WRITE_END; redirect_fd = STDOUT_FILENO; } else if (pcr->pcr_flag & FWRITE) { /* * The caller writes to the pipe, * the spawned process reads from it. */ caller_end = WRITE_END; process_end = READ_END; redirect_fd = STDIN_FILENO; } else return (EINVAL); /* Get and check command line. */ pbuf[0] = '/'; strcpy(pbuf+1, key + (v[1] ? strlen(v[1]) : 0)); argc = parse_argv(pbuf, NULL); if (argc == 0) return (ENOENT); /* Swap priviledges. */ if (set_user_credentials(pcr, &save_area) < 0) return (errno); /* Redirect and spawn the specified process. */ fd[READ_END] = fd[WRITE_END] = -1; if (pipe(fd) < 0) { error = errno; goto done; } switch (fork()) { case -1: /* Error */ error = errno; break; default: /* Parent */ (void)close(fd[process_end]); break; case 0: /* Child */ argv = (char **)malloc((argc + 1) * sizeof(char *)); if (argv == 0) { syslog(LOG_ALERT, "malloc: failed to get space for %d pointers", argc + 1); exit(EXIT_FAILURE); } parse_argv(pbuf, argv); if (dup2(fd[process_end], redirect_fd) < 0) { syslog(LOG_ERR, "dup2: %m"); exit(EXIT_FAILURE); } (void)close(fd[caller_end]); (void)close(fd[process_end]); if (errlog() < 0) { syslog(LOG_ERR, "errlog: %m"); exit(EXIT_FAILURE); } if (execv(argv[0], argv) < 0) { syslog(LOG_ERR, "execv(%s): %m", argv[0]); exit(EXIT_FAILURE); } /* NOTREACHED */ } done: /* Re-establish our priviledges. */ if (restore_credentials(&save_area) < 0) error = errno; /* Set return fd value. */ if (error == 0) *fdp = fd[caller_end]; else { for (i = 0; i < 2; i++) if (fd[i] >= 0) (void)close(fd[i]); *fdp = -1; } return (error); }