diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 2005-03-11 08:39:59 +0000 |
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 2005-03-11 08:39:59 +0000 |
| commit | 35713374b6f9eb7b48966f5e5a86d9d310ea734b (patch) | |
| tree | 04f19d557b249db4754422667acf01b70962bb9d /usr.sbin | |
| parent | 7daf778896e08eea5c0f31c514f883369c69fd84 (diff) | |
Notes
Diffstat (limited to 'usr.sbin')
| -rw-r--r-- | usr.sbin/mount_portalfs/cred.c | 75 | ||||
| -rw-r--r-- | usr.sbin/mount_portalfs/pt_pipe.c | 233 |
2 files changed, 308 insertions, 0 deletions
diff --git a/usr.sbin/mount_portalfs/cred.c b/usr.sbin/mount_portalfs/cred.c new file mode 100644 index 0000000000000..9e5d9f3f222b3 --- /dev/null +++ b/usr.sbin/mount_portalfs/cred.c @@ -0,0 +1,75 @@ +/*- + * Copyright (C) 2005 Diomidis Spinellis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/syslog.h> + +#include "portald.h" + +/* + * Set the process's credentials to those specified in user, + * saveing the existing ones in save. + * Return 0 on success, -1 (with errno set) on error. + */ +int +set_user_credentials(struct portal_cred *user, struct portal_cred *save) +{ + save->pcr_uid = geteuid(); + if ((save->pcr_ngroups = getgroups(NGROUPS_MAX, save->pcr_groups)) < 0) + return (-1); + if (setgroups(user->pcr_ngroups, user->pcr_groups) < 0) + return (-1); + if (seteuid(user->pcr_uid) < 0) + return (-1); + return (0); +} + +/* + * Restore the process's credentials to the ones specified in save. + * Log failures using LOG_ERR. + * Return 0 on success, -1 (with errno set) on error. + */ +int +restore_credentials(struct portal_cred *save) +{ + if (seteuid(save->pcr_uid) < 0) { + syslog(LOG_ERR, "seteuid: %m"); + return (-1); + } + if (setgroups(save->pcr_ngroups, save->pcr_groups) < 0) { + syslog(LOG_ERR, "setgroups: %m"); + return (-1); + } + return (0); +} diff --git a/usr.sbin/mount_portalfs/pt_pipe.c b/usr.sbin/mount_portalfs/pt_pipe.c new file mode 100644 index 0000000000000..285f193b4f179 --- /dev/null +++ b/usr.sbin/mount_portalfs/pt_pipe.c @@ -0,0 +1,233 @@ +/*- + * Copyright (C) 2005 Diomidis Spinellis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/syslog.h> + +#include "portald.h" + +/* Usage conventions for the pipe's endpoints. */ +#define READ_END 0 +#define WRITE_END 1 + +static int errlog(void); +static int parse_argv(char *args, char **argv); + +int portal_pipe(pcr, key, v, so, fdp) +struct portal_cred *pcr; +char *key; +char **v; +int so; +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); +} + +/* + * Redirect stderr to the system log. + * Return 0 if ok. + * Return -1 with errno set on error. + */ +static int +errlog(void) +{ + int fd[2]; + char buff[1024]; + FILE *f; + int ret = 0; + + if (pipe(fd) < 0) + return (-1); + switch (fork()) { + case -1: /* Error */ + return (-1); + case 0: /* Child */ + if ((f = fdopen(fd[READ_END], "r")) == NULL) { + syslog(LOG_ERR, "fdopen: %m"); + exit(EXIT_FAILURE); + } + (void)close(fd[WRITE_END]); + while (fgets(buff, sizeof(buff), f) != NULL) + syslog(LOG_ERR, "exec: %s", buff); + exit(EXIT_SUCCESS); + /* NOTREACHED */ + default: /* Parent */ + if (dup2(fd[WRITE_END], STDERR_FILENO) < 0) + ret = -1; + (void)close(fd[READ_END]); + (void)close(fd[WRITE_END]); + break; + } + return (ret); +} + +/* + * Parse the args string as a space-separated argument vector. + * If argv is not NULL, split the string into its constituent + * components, and set argv to point to the beginning of each + * string component; NULL-terminating argv. + * Return the number of string components. + */ +static int +parse_argv(char *args, char **argv) +{ + int count = 0; + char *p; + enum {WORD, SPACE} state = SPACE; + + for (p = args; *p; p++) + switch (state) { + case WORD: + if (isspace(*p)) { + if (argv) + *p = '\0'; + state = SPACE; + } + break; + case SPACE: + if (!isspace(*p)) { + if (argv) + argv[count] = p; + count++; + state = WORD; + } + } + if (argv) + argv[count] = NULL; + return (count); +} |
