diff options
author | Jean-Francois Brousseau <jfb@cvs.openbsd.org> | 2005-02-22 22:33:02 +0000 |
---|---|---|
committer | Jean-Francois Brousseau <jfb@cvs.openbsd.org> | 2005-02-22 22:33:02 +0000 |
commit | d73db9971ff4e818de32c0eea820a93be086461f (patch) | |
tree | 8a0ceb38ddef4172ac62bb7c631f2ba9ffc98a49 /usr.bin/cvs | |
parent | 29882321ce185cc5c5b4e0ff7d5b28261e6d9214 (diff) |
Split the cvs daemon into two different processes: cvsd and cvsd-child.
The cvsd process only takes care of managing children and repository
locks, while the child handles all requests made to access or modify
the contents of the repository.
This will allow us to take advantage of randomized library remapping
and new propolice cookies, and minimizes the amount of code that can
run with elevated privileges. Still work in progress.
suggested by deraadt@
Diffstat (limited to 'usr.bin/cvs')
-rw-r--r-- | usr.bin/cvs/child.c | 271 | ||||
-rw-r--r-- | usr.bin/cvs/cvsd-child/Makefile | 19 | ||||
-rw-r--r-- | usr.bin/cvs/cvsd.c | 373 | ||||
-rw-r--r-- | usr.bin/cvs/cvsd.h | 53 | ||||
-rw-r--r-- | usr.bin/cvs/cvsd/Makefile | 4 |
5 files changed, 407 insertions, 313 deletions
diff --git a/usr.bin/cvs/child.c b/usr.bin/cvs/child.c new file mode 100644 index 00000000000..a9ad357906b --- /dev/null +++ b/usr.bin/cvs/child.c @@ -0,0 +1,271 @@ +/* $OpenBSD: child.c,v 1.1 2005/02/22 22:33:01 jfb Exp $ */ +/* + * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 + * THE AUTHOR 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. + */ +/* + * cvsd-child + * ---------- + * + * This is the process taking care of cvs(1) repository requests + * This program is not meant to be run standalone and should only be started + * by the cvsd(8) process. + * + */ + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/uio.h> + +#include <err.h> +#include <pwd.h> +#include <grp.h> +#include <poll.h> +#include <fcntl.h> +#include <dirent.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <sysexits.h> + +#include "log.h" +#include "cvs.h" +#include "cvsd.h" +#include "cvspr.h" + + + +extern char *__progname; + + +int cvsd_fg = 0; + +volatile sig_atomic_t cvsd_running = 1; + +static int cvsd_privfd = -1; +static char cvsd_root[MAXPATHLEN]; +static char *cvsd_motd; +static uid_t cvsd_uid = -1; +static gid_t cvsd_gid = -1; + + +/* session info */ +static uid_t cvsd_sess_ruid = 0; /* UID of the cvs issuing requests */ +static gid_t cvsd_sess_rgid = 0; /* UID of the cvs issuing requests */ +static int cvsd_sess_fd = -1; + + +void usage (void); +void cvsd_sighdlr (int); +int cvsd_child_getreq (struct cvsd_req *); + + +/* + * cvsd_sighdlr() + * + * Generic signal handler. + */ +void +cvsd_sighdlr(int signo) +{ + switch (signo) { + case SIGINT: + case SIGTERM: + case SIGQUIT: + cvsd_running = 0; + break; + } +} + + +/* + * usage() + * + * Display program usage. + */ +void +usage(void) +{ + fprintf(stderr, + "Usage: %s [-dfhv] [-g group] " + "[-u user]\n" + "\t-d\t\tStart the server in debugging mode (very verbose)\n" + "\t-u user\t\tUse user <user> for privilege revocation\n" + "\t-v\t\tBe verbose\n", + __progname); +} + + +int +main(int argc, char **argv) +{ + int ret; + struct cvsd_req req; + + if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0) + err(1, "failed to initialize logging mechanism"); + + cvsd_sess_fd = CVSD_CHILD_SOCKFD; + if (getpeereid(cvsd_sess_fd, &cvsd_sess_ruid, &cvsd_sess_rgid) == -1) { + cvs_log(LP_ERRNO, "failed to get remote credentials"); + exit(EX_OSERR); + } + + while ((ret = getopt(argc, argv, "dfg:hr:u:v")) != -1) { + switch (ret) { + case 'd': + cvs_log_filter(LP_FILTER_UNSET, LP_DEBUG); + cvs_log_filter(LP_FILTER_UNSET, LP_INFO); + break; + case 'f': + cvsd_fg = 1; + break; + case 'g': + cvsd_gid = atoi(optarg); + break; + case 'h': + usage(); + exit(0); + /* NOTREACHED */ + break; + case 'r': + strlcpy(cvsd_root, optarg, sizeof(cvsd_root)); + break; + case 'u': + cvsd_uid = atoi(optarg); + break; + case 'v': + cvs_log_filter(LP_FILTER_UNSET, LP_INFO); + break; + default: + usage(); + exit(EX_USAGE); + } + } + + argc -= optind; + argv += optind; + if (argc > 0) + errx(EX_USAGE, "unrecognized trailing arguments"); + + /* Before getting any further, chroot to the CVS repository's root + * directory and drop all privileges to the appropriate user and + * group so we can't cause damage outside of the CVS data. + */ + if (chroot(cvsd_root) == -1) { + cvs_log(LP_ERRNO, "failed to chroot to %s", cvsd_root); + exit(EX_OSERR); + } + (void)chdir("/"); + cvs_log(LP_INFO, "dropping privileges to %d:%d", cvsd_uid, cvsd_gid); + if (setgid(cvsd_gid) == -1) { + cvs_log(LP_ERRNO, "failed to drop group privileges to %s", + CVSD_GROUP); + return (-1); + } + + if (setuid(cvsd_uid) == -1) { + cvs_log(LP_ERRNO, "failed to drop user privileges to %s", + CVSD_USER); + return (-1); + } + + signal(SIGINT, cvsd_sighdlr); + signal(SIGQUIT, cvsd_sighdlr); + signal(SIGTERM, cvsd_sighdlr); + signal(SIGPIPE, SIG_IGN); + + setproctitle("%s [child %d]", __progname, getpid()); + + for (;;) { + ret = cvsd_child_getreq(&req); + if (ret <= 0) + break; + + switch (req.cr_op) { + case CVS_OP_DIFF: + case CVS_OP_UPDATE: + default: + } + printf("request ID: %d, nfiles = %d\n", req.cr_op, + req.cr_nfiles); + } + + close(cvsd_sess_fd); + + cvs_log_cleanup(); + + return (0); +} + + +/* + * cvsd_child_getreq() + * + * Read the next request available on the session socket. + * Returns 1 if a request was received, 0 if there are no more requests to + * serve, and -1 in case of failure. + */ +int +cvsd_child_getreq(struct cvsd_req *reqp) +{ + ssize_t ret; + if ((ret = read(cvsd_sess_fd, reqp, sizeof(*reqp))) == -1) { + cvs_log(LP_ERRNO, "failed to read request"); + } else if (ret > 0) { + printf("reqlen = %d\n", ret); + ret = 1; + } + + return ((int)ret); +} + + +/* + * cvsd_child_reqhdlr() + * + */ +int +cvsd_child_reqhdlr(struct cvsp_req *req) +{ + int ret; + + switch (req->req_code) { + case CVSP_REQ_MOTD: + ret = cvs_proto_sendresp(cvsd_sess_fd, CVSP_RESP_DONE, + cvsd_motd, strlen(cvsd_motd) + 1); + break; + case CVSP_REQ_VERSION: + case CVSP_REQ_GETMSG: + case CVSP_REQ_SETMSG: + default: + ret = cvs_proto_sendresp(cvsd_sess_fd, CVSP_RESP_INVREQ, + req->req_seq, NULL, 0); + } + + return (ret); +} diff --git a/usr.bin/cvs/cvsd-child/Makefile b/usr.bin/cvs/cvsd-child/Makefile new file mode 100644 index 00000000000..dbe956d324a --- /dev/null +++ b/usr.bin/cvs/cvsd-child/Makefile @@ -0,0 +1,19 @@ +# $Id: Makefile,v 1.1 2005/02/22 22:33:01 jfb Exp $ + +.PATH: ${.CURDIR}/.. + +PROG=cvsd-child +SRCS= child.c buf.c log.c msg.c rcs.c rcsnum.c + +BINDIR=/usr/sbin +MAN= + +CFLAGS+= -Wall -I${.CURDIR}/.. +CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes +CFLAGS+= -Wmissing-declarations +CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual +CFLAGS+= -Wsign-compare +CFLAGS+= -DCVSD +YFLAGS= + +.include <bsd.prog.mk> diff --git a/usr.bin/cvs/cvsd.c b/usr.bin/cvs/cvsd.c index dea0e39cc02..487c47400c7 100644 --- a/usr.bin/cvs/cvsd.c +++ b/usr.bin/cvs/cvsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cvsd.c,v 1.17 2005/02/15 15:17:34 jfb Exp $ */ +/* $OpenBSD: cvsd.c,v 1.18 2005/02/22 22:33:01 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -46,12 +46,11 @@ #include "log.h" #include "sock.h" #include "cvs.h" +#include "repo.h" #include "cvsd.h" static void cvsd_parent_loop (void); -static void cvsd_child_main (void); -static int cvsd_privdrop (void); static void cvsd_report (void); @@ -59,8 +58,8 @@ extern char *__progname; int cvsd_fg = 0; -uid_t cvsd_uid = -1; -gid_t cvsd_gid = -1; +uid_t cvsd_uid = 0; +gid_t cvsd_gid = 0; volatile sig_atomic_t cvsd_running = 1; volatile sig_atomic_t cvsd_restart = 0; @@ -68,20 +67,21 @@ volatile sig_atomic_t cvsd_restart = 0; static char *cvsd_user = NULL; static char *cvsd_group = NULL; static char *cvsd_root = NULL; -static char *cvsd_conffile = CVSD_CONF; +static char *cvsd_conffile = CVSD_PATH_CONF; static char *cvsd_moddir = NULL; static int cvsd_privfd = -1; +static CVSREPO *cvsd_repo; + static TAILQ_HEAD(,cvsd_child) cvsd_children; static volatile sig_atomic_t cvsd_chnum = 0; -static volatile sig_atomic_t cvsd_chmin = CVSD_CHILD_DEFMIN; static volatile sig_atomic_t cvsd_chmax = CVSD_CHILD_DEFMAX; static volatile sig_atomic_t cvsd_sigchld = 0; static volatile sig_atomic_t cvsd_siginfo = 0; -void usage (void); +void usage (void); void cvsd_sighdlr (int); int cvsd_msghdlr (struct cvsd_child *, int); @@ -141,12 +141,11 @@ usage(void) int main(int argc, char **argv) { - u_int i; - int ret, checkrepo; + int ret, repo_flags; struct passwd *pwd; struct group *grp; - checkrepo = 0; + repo_flags = 0; cvsd_set(CVSD_SET_SOCK, CVSD_SOCK_PATH); cvsd_set(CVSD_SET_USER, CVSD_USER); cvsd_set(CVSD_SET_GROUP, CVSD_GROUP); @@ -154,7 +153,7 @@ main(int argc, char **argv) if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0) err(1, "failed to initialize logging mechanism"); - while ((ret = getopt(argc, argv, "a:c:dfhpr:s:v")) != -1) { + while ((ret = getopt(argc, argv, "c:dfg:hpr:s:u:v")) != -1) { switch (ret) { case 'c': cvsd_conffile = optarg; @@ -175,7 +174,7 @@ main(int argc, char **argv) /* NOTREACHED */ break; case 'p': - checkrepo = 1; + repo_flags |= CVS_REPO_CHKPERM; break; case 'r': cvsd_set(CVSD_SET_ROOT, optarg); @@ -217,6 +216,9 @@ main(int argc, char **argv) if (grp == NULL) err(EX_NOUSER, "failed to get group `%s'", cvsd_group); + endpwent(); + endgrent(); + cvsd_uid = pwd->pw_uid; cvsd_gid = grp->gr_gid; @@ -232,6 +234,11 @@ main(int argc, char **argv) exit(EX_OSERR); } + if ((cvsd_repo = cvs_repo_load(cvsd_root, repo_flags)) == NULL) { + cvs_log(LP_ERR, "failed to load repository"); + exit(EX_OSERR); + }; + if (cvsd_sock_open() < 0) { exit(1); } @@ -245,182 +252,44 @@ main(int argc, char **argv) exit(EX_OSERR); } - if (checkrepo && cvsd_checkperms("/") != 0) { - cvs_log(LP_ERR, - "exiting due to permission errors on repository"); - exit(1); - } - - /* spawn the initial pool of children */ - for (i = 0; i < (u_int)cvsd_chmin; i++) - if (cvsd_child_fork(NULL) < 0) - exit(EX_OSERR); - signal(SIGINFO, cvsd_sighdlr); cvsd_parent_loop(); - cvs_log(LP_NOTICE, "shutting down"); - cvs_log_cleanup(); - cvsd_sock_close(); - return (0); -} - - -/* - * cvsd_privdrop() - * - * Drop privileges. - */ -int -cvsd_privdrop(void) -{ - cvs_log(LP_INFO, "dropping privileges to %s[%d]:%s[%d]", - cvsd_user, cvsd_uid, cvsd_group, cvsd_gid); - if (setgid(cvsd_gid) == -1) { - cvs_log(LP_ERRNO, "failed to drop group privileges to %s", - CVSD_GROUP); - return (-1); - } - - if (setuid(cvsd_uid) == -1) { - cvs_log(LP_ERRNO, "failed to drop user privileges to %s", - CVSD_USER); - return (-1); - } + cvs_repo_free(cvsd_repo); + cvs_log(LP_NOTICE, "shutting down"); + cvs_log_cleanup(); return (0); } /* - * cvsd_checkperms() - * - * Check permissions on the CVS repository and log warnings for any - * weird of loose permissions. - * Returns the number of warnings on success, or -1 on failure. - */ -int -cvsd_checkperms(const char *path) -{ - int fd, nbwarn, ret; - mode_t fmode; - long base; - u_char *dp, *endp; - char buf[1024], spath[MAXPATHLEN]; - struct stat st; - struct dirent *dep; - - nbwarn = 0; - - cvs_log(LP_DEBUG, "checking permissions on `%s'", path); - - if (stat(path, &st) == -1) { - cvs_log(LP_ERRNO, "failed to stat `%s'", path); - return (-1); - } - - if (S_ISDIR(st.st_mode)) - fmode = CVSD_DPERM; - else - fmode = CVSD_FPERM; - - if (st.st_uid != cvsd_uid) { - cvs_log(LP_WARN, "owner of `%s' is not %s", path, CVSD_USER); - nbwarn++; - } - - if (st.st_gid != cvsd_gid) { - cvs_log(LP_WARN, "group of `%s' is not %s", path, CVSD_GROUP); - nbwarn++; - } - - if (st.st_mode & S_IWGRP) { - cvs_log(LP_WARN, "file `%s' is group-writable", path, - fmode); - nbwarn++; - } - - if (st.st_mode & S_IWOTH) { - cvs_log(LP_WARN, "file `%s' is world-writable", path, - fmode); - nbwarn++; - } - - if (S_ISDIR(st.st_mode)) { - fd = open(path, O_RDONLY, 0); - if (fd == -1) { - cvs_log(LP_ERRNO, "failed to open directory `%s'", - path); - return (nbwarn); - } - /* recurse */ - ret = getdirentries(fd, buf, sizeof(buf), &base); - if (ret == -1) { - cvs_log(LP_ERRNO, - "failed to get directory entries for `%s'", path); - (void)close(fd); - return (nbwarn); - } - - dp = buf; - endp = buf + ret; - - while (dp < endp) { - dep = (struct dirent *)dp; - dp += dep->d_reclen; - - if ((dep->d_namlen == 1) && (dep->d_name[0] == '.')) - continue; - if ((dep->d_namlen == 2) && (dep->d_name[0] == '.') && - (dep->d_name[1] == '.')) - continue; - - /* skip the CVSROOT directory */ - if (strcmp(dep->d_name, CVS_PATH_ROOT) == 0) - continue; - - snprintf(spath, sizeof(spath), "%s/%s", path, - dep->d_name); - ret = cvsd_checkperms(spath); - if (ret == -1) - nbwarn++; - else - nbwarn += ret; - } - (void)close(fd); - } - - - return (nbwarn); -} - - -/* * cvsd_child_fork() * - * Fork a child process which chroots to the CVS repository's root directory. - * If the <chpp> argument is not NULL, a reference to the newly created child - * structure will be returned. - * On success, returns 0 in the child process context, 1 in the parent's - * context, or -1 on failure. + * Fork a child process which chroots to the CVS repository's root directory, + * drops all privileges, and then executes the cvsd-child process, which will + * handle the incoming CVS requests. + * On success, returns a pointer to the new child structure, + * or NULL on failure. */ -int -cvsd_child_fork(struct cvsd_child **chpp) +struct cvsd_child* +cvsd_child_fork(int sock) { - int svec[2]; + int argc, svec[2]; pid_t pid; + char *argv[16], ubuf[8], gbuf[8]; struct cvsd_child *chp; if (cvsd_chnum == cvsd_chmax) { cvs_log(LP_WARN, "child pool reached limit of processes"); - return (-1); + return (NULL); } if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, svec) == -1) { cvs_log(LP_ERRNO, "failed to create socket pair"); - return (-1); + return (NULL); } /* @@ -429,7 +298,7 @@ cvsd_child_fork(struct cvsd_child **chpp) */ if (seteuid(0) == -1) { cvs_log(LP_ERRNO, "failed to regain privileges"); - return (-1); + return (NULL); } pid = fork(); @@ -437,43 +306,70 @@ cvsd_child_fork(struct cvsd_child **chpp) cvs_log(LP_ERRNO, "failed to fork child"); (void)close(svec[0]); (void)close(svec[1]); - return (-1); + return (NULL); } if (pid == 0) { cvsd_privfd = svec[1]; (void)close(svec[0]); - cvsd_child_main(); - /* NOTREACHED */ + /* + * Move the accepted socket to descriptor 3, where the child + * expects it to be. This could become troublesome if the + * descriptor is already taken, but then again, the child + * shouldn't have access to other descriptors except the + * connection and its side of the socket pair it shares with + * the parent. + */ + if (dup2(sock, CVSD_CHILD_SOCKFD) == -1) { + cvs_log(LP_ERRNO, "failed to dup child socket"); + exit(EX_OSERR); + } + (void)close(sock); + + argc = 0; + argv[argc++] = CVSD_PATH_CHILD; + argv[argc++] = "-r"; + argv[argc++] = cvsd_root; + if (cvsd_uid != 0) { + snprintf(ubuf, sizeof(ubuf), "%d", cvsd_uid); + argv[argc++] = "-u"; + argv[argc++] = ubuf; + } + if (cvsd_gid != 0) { + snprintf(gbuf, sizeof(gbuf), "%d", cvsd_gid); + argv[argc++] = "-g"; + argv[argc++] = gbuf; + } + argv[argc] = NULL; + + execv(CVSD_PATH_CHILD, argv); + err(1, "FUCK"); + exit(EX_OSERR); } cvs_log(LP_INFO, "spawning child %d", pid); - if (seteuid(cvsd_uid) == -1) { + (void)close(svec[1]); + + if (seteuid(cvsd_uid) == -1) cvs_log(LP_ERRNO, "failed to redrop privs"); - return (-1); - } chp = (struct cvsd_child *)malloc(sizeof(*chp)); if (chp == NULL) { + /* XXX kill child */ cvs_log(LP_ERRNO, "failed to allocate child data"); - return (-1); + return (NULL); } chp->ch_pid = pid; chp->ch_sock = svec[0]; chp->ch_state = CVSD_ST_IDLE; - signal(SIGCHLD, SIG_IGN); TAILQ_INSERT_TAIL(&cvsd_children, chp, ch_list); cvsd_chnum++; - signal(SIGCHLD, cvsd_sighdlr); - if (chpp != NULL) - *chpp = chp; - (void)close(svec[1]); - return (1); + return (chp); } @@ -482,8 +378,7 @@ cvsd_child_fork(struct cvsd_child **chpp) * * Wait for a child's status and perform the proper actions depending on it. * If the child has exited or has been terminated by a signal, it will be - * removed from the list and new children will be created until the pool has - * at least <cvsd_chmin> children in it. + * removed from the list. * Returns 0 on success, or -1 on failure. */ int @@ -522,41 +417,11 @@ cvsd_child_reap(void) } } - while (cvsd_chnum < cvsd_chmin) - cvsd_child_fork(NULL); - return (0); } /* - * cvsd_child_get() - * - * Find a child process in idle state and return a pointer to the child's - * structure. If there are no available child processes, a new one will be - * created unless the number of children has attained the maximum, in which - * case NULL is returned. - */ -struct cvsd_child* -cvsd_child_get(void) -{ - struct cvsd_child *chp; - - TAILQ_FOREACH(chp, &cvsd_children, ch_list) - if (chp->ch_state == CVSD_ST_IDLE) - return (chp); - - /* no available child, attempt to fork a new one */ - chp = NULL; - if ((cvsd_chnum < cvsd_chmax) && (cvsd_child_fork(&chp) < 0)) - return (NULL); - - return (chp); -} - - - -/* * cvsd_parent_loop() * * Main loop of the parent cvsd process, which listens on its end of the @@ -628,10 +493,10 @@ cvsd_parent_loop(void) uid_t uid; gid_t gid; - cfd = cvsd_sock_accept(pfd[0].fd); - if (cfd == -1) - chp = cvsd_child_get(); - if (chp == NULL) { + if ((cfd = cvsd_sock_accept(pfd[0].fd)) == -1) + continue; + + if ((chp = cvsd_child_fork(cfd)) == NULL) { cvs_log(LP_ALERT, "request queue not implemented"); break; @@ -669,78 +534,6 @@ cvsd_parent_loop(void) /* - * cvsd_child_main() - * - */ -static void -cvsd_child_main(void) -{ - int ret, timeout; - u_int mtype; - size_t mlen; - char mbuf[CVSD_MSG_MAXLEN]; - struct pollfd pfd[1]; - struct cvsd_sess *sessp; - - cvs_log(LP_INFO, "changing root to %s", cvsd_root); - if (chroot(cvsd_root) == -1) { - cvs_log(LP_ERRNO, "failed to chroot to `%s'", cvsd_root); - exit(EX_OSERR); - } - (void)chdir("/"); - - if (cvsd_privdrop() < 0) - exit(EX_OSERR); - - setproctitle("%s [child %d]", __progname, getpid()); - - pfd[0].fd = cvsd_privfd; - pfd[0].events = POLLIN; - timeout = INFTIM; - sessp = NULL; - - while (cvsd_running) { - ret = poll(pfd, 1, timeout); - if (ret == -1) { - if (errno == EINTR) - continue; - cvs_log(LP_ERRNO, "poll error"); - break; - } else if (ret == 0) - continue; - - if (pfd[0].revents & (POLLERR|POLLNVAL)) { - cvs_log(LP_ERR, "poll error"); - break; - } - - mlen = sizeof(mbuf); - ret = cvsd_recvmsg(pfd[0].fd, &mtype, mbuf, &mlen); - if (ret == -1) { - continue; - } else if (ret == 0) - break; - - switch (mtype) { - case CVSD_MSG_PASSFD: - sessp = cvsd_sess_alloc(*(int *)mbuf); - break; - case CVSD_MSG_SHUTDOWN: - cvsd_running = 0; - break; - default: - cvs_log(LP_ERR, - "unexpected message type %u from parent", mtype); - break; - } - - } - - exit(0); -} - - -/* * cvsd_msghdlr() * * Handler for messages received from child processes. @@ -887,10 +680,6 @@ cvsd_set(int what, ...) free(cvsd_moddir); cvsd_moddir = str; break; - case CVSD_SET_CHMIN: - cvsd_chmin = va_arg(vap, int); - /* we should increase the number of children accordingly */ - break; case CVSD_SET_CHMAX: cvsd_chmax = va_arg(vap, int); /* we should decrease the number of children accordingly */ @@ -912,6 +701,8 @@ cvsd_set(int what, ...) /* * cvsd_report() + * + * Report about the current state of child processes on the repository. */ static void cvsd_report(void) diff --git a/usr.bin/cvs/cvsd.h b/usr.bin/cvs/cvsd.h index 4a271478c26..bd4ff0549c4 100644 --- a/usr.bin/cvs/cvsd.h +++ b/usr.bin/cvs/cvsd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cvsd.h,v 1.7 2004/12/07 17:10:56 tedu Exp $ */ +/* $OpenBSD: cvsd.h,v 1.8 2005/02/22 22:33:01 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -42,10 +42,12 @@ #define CVSD_USER "_cvsd" #define CVSD_GROUP "_cvsd" -#define CVSD_CONF "/etc/cvsd.conf" -#define CVSD_CHILD_DEFMIN 3 +#define CVSD_PATH_CONF "/etc/cvsd.conf" +#define CVSD_PATH_CHILD "/usr/sbin/cvsd-child" + #define CVSD_CHILD_DEFMAX 5 +#define CVSD_CHILD_SOCKFD 3 #define CVSD_FPERM (S_IRUSR | S_IWUSR) @@ -105,37 +107,48 @@ struct cvsd_addr { } ca_addr; }; -#define CVSD_SESS_LOCAL 0 -#define CVSD_SESS_REMOTE 1 - -struct cvsd_sess { - int cs_fd; - int cs_type; - uid_t cs_uid; /* user ID of the session */ - struct cvsd_addr cs_raddr; /* remote address */ -}; - struct cvsd_child { pid_t ch_pid; int ch_sock; u_int ch_state; - struct cvsd_sess *ch_sess; - TAILQ_ENTRY(cvsd_child) ch_list; }; +/* + * The following structures are used to vehicle information to and from the + * cvsd-child process handling the cvs session. + */ + +struct cvsd_req { + int cr_op; /* operation (see CVS_OP_* in cvs.h) */ + int cr_nfiles; +}; + +struct cvsd_resp { + int cr_code; +}; + + +/* cvsd-child response codes */ +#define CVSD_RESP_OK 0 +#define CVSD_RESP_INVREQ 1 /* invalid request */ +#define CVSD_RESP_DENIED 2 /* access denied */ +#define CVSD_RESP_SYSERR 3 /* system error */ +#define CVSD_RESP_RDONLY 4 /* repository is read-only */ +#define CVSD_RESP_INVFILE 5 /* one or more files are unknown */ +#define CVSD_RESP_INVMOD 6 + + extern uid_t cvsd_uid; extern gid_t cvsd_gid; -int cvsd_set (int, ...); -int cvsd_checkperms (const char *); -int cvsd_child_fork (struct cvsd_child **); -struct cvsd_child* cvsd_child_get (void); -int cvsd_child_reap (void); +int cvsd_set (int, ...); +struct cvsd_child* cvsd_child_fork (int); +int cvsd_child_reap (void); /* from conf.y */ diff --git a/usr.bin/cvs/cvsd/Makefile b/usr.bin/cvs/cvsd/Makefile index 15c09b5b650..f2ba2e2e436 100644 --- a/usr.bin/cvs/cvsd/Makefile +++ b/usr.bin/cvs/cvsd/Makefile @@ -1,9 +1,9 @@ -# $Id: Makefile,v 1.8 2004/12/08 18:52:53 xsa Exp $ +# $Id: Makefile,v 1.9 2005/02/22 22:33:01 jfb Exp $ .PATH: ${.CURDIR}/.. PROG=cvsd -SRCS= cvsd.c buf.c conf.y log.c msg.c rcs.c rcsnum.c session.c sock.c +SRCS= cvsd.c buf.c conf.y log.c msg.c repo.c sock.c BINDIR=/usr/sbin MAN=cvsd.8 cvsd.conf.5 |