[BACK]Return to child.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/child.c, Revision 1.1

1.1     ! jfb         1: /*     $OpenBSD$       */
        !             2: /*
        !             3:  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  *
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. The name of the author may not be used to endorse or promote products
        !            13:  *    derived from this software without specific prior written permission.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
        !            16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
        !            17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
        !            18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
        !            21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
        !            23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            25:  */
        !            26: /*
        !            27:  * cvsd-child
        !            28:  * ----------
        !            29:  *
        !            30:  * This is the process taking care of cvs(1) repository requests
        !            31:  * This program is not meant to be run standalone and should only be started
        !            32:  * by the cvsd(8) process.
        !            33:  *
        !            34:  */
        !            35:
        !            36: #include <sys/param.h>
        !            37: #include <sys/stat.h>
        !            38: #include <sys/wait.h>
        !            39: #include <sys/uio.h>
        !            40:
        !            41: #include <err.h>
        !            42: #include <pwd.h>
        !            43: #include <grp.h>
        !            44: #include <poll.h>
        !            45: #include <fcntl.h>
        !            46: #include <dirent.h>
        !            47: #include <stdlib.h>
        !            48: #include <stdio.h>
        !            49: #include <unistd.h>
        !            50: #include <signal.h>
        !            51: #include <errno.h>
        !            52: #include <string.h>
        !            53: #include <sysexits.h>
        !            54:
        !            55: #include "log.h"
        !            56: #include "cvs.h"
        !            57: #include "cvsd.h"
        !            58: #include "cvspr.h"
        !            59:
        !            60:
        !            61:
        !            62: extern char *__progname;
        !            63:
        !            64:
        !            65: int    cvsd_fg = 0;
        !            66:
        !            67: volatile sig_atomic_t cvsd_running = 1;
        !            68:
        !            69: static int    cvsd_privfd = -1;
        !            70: static char   cvsd_root[MAXPATHLEN];
        !            71: static char  *cvsd_motd;
        !            72: static uid_t  cvsd_uid = -1;
        !            73: static gid_t  cvsd_gid = -1;
        !            74:
        !            75:
        !            76: /* session info */
        !            77: static uid_t  cvsd_sess_ruid = 0;      /* UID of the cvs issuing requests */
        !            78: static gid_t  cvsd_sess_rgid = 0;      /* UID of the cvs issuing requests */
        !            79: static int    cvsd_sess_fd = -1;
        !            80:
        !            81:
        !            82: void   usage         (void);
        !            83: void   cvsd_sighdlr  (int);
        !            84: int    cvsd_child_getreq (struct cvsd_req *);
        !            85:
        !            86:
        !            87: /*
        !            88:  * cvsd_sighdlr()
        !            89:  *
        !            90:  * Generic signal handler.
        !            91:  */
        !            92: void
        !            93: cvsd_sighdlr(int signo)
        !            94: {
        !            95:        switch (signo) {
        !            96:        case SIGINT:
        !            97:        case SIGTERM:
        !            98:        case SIGQUIT:
        !            99:                cvsd_running = 0;
        !           100:                break;
        !           101:        }
        !           102: }
        !           103:
        !           104:
        !           105: /*
        !           106:  * usage()
        !           107:  *
        !           108:  * Display program usage.
        !           109:  */
        !           110: void
        !           111: usage(void)
        !           112: {
        !           113:        fprintf(stderr,
        !           114:            "Usage: %s [-dfhv] [-g group] "
        !           115:            "[-u user]\n"
        !           116:            "\t-d\t\tStart the server in debugging mode (very verbose)\n"
        !           117:            "\t-u user\t\tUse user <user> for privilege revocation\n"
        !           118:            "\t-v\t\tBe verbose\n",
        !           119:            __progname);
        !           120: }
        !           121:
        !           122:
        !           123: int
        !           124: main(int argc, char **argv)
        !           125: {
        !           126:        int ret;
        !           127:        struct cvsd_req req;
        !           128:
        !           129:        if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0)
        !           130:                err(1, "failed to initialize logging mechanism");
        !           131:
        !           132:        cvsd_sess_fd = CVSD_CHILD_SOCKFD;
        !           133:        if (getpeereid(cvsd_sess_fd, &cvsd_sess_ruid, &cvsd_sess_rgid) == -1) {
        !           134:                cvs_log(LP_ERRNO, "failed to get remote credentials");
        !           135:                exit(EX_OSERR);
        !           136:        }
        !           137:
        !           138:        while ((ret = getopt(argc, argv, "dfg:hr:u:v")) != -1) {
        !           139:                switch (ret) {
        !           140:                case 'd':
        !           141:                        cvs_log_filter(LP_FILTER_UNSET, LP_DEBUG);
        !           142:                        cvs_log_filter(LP_FILTER_UNSET, LP_INFO);
        !           143:                        break;
        !           144:                case 'f':
        !           145:                        cvsd_fg = 1;
        !           146:                        break;
        !           147:                case 'g':
        !           148:                        cvsd_gid = atoi(optarg);
        !           149:                        break;
        !           150:                case 'h':
        !           151:                        usage();
        !           152:                        exit(0);
        !           153:                        /* NOTREACHED */
        !           154:                        break;
        !           155:                case 'r':
        !           156:                        strlcpy(cvsd_root, optarg, sizeof(cvsd_root));
        !           157:                        break;
        !           158:                case 'u':
        !           159:                        cvsd_uid = atoi(optarg);
        !           160:                        break;
        !           161:                case 'v':
        !           162:                        cvs_log_filter(LP_FILTER_UNSET, LP_INFO);
        !           163:                        break;
        !           164:                default:
        !           165:                        usage();
        !           166:                        exit(EX_USAGE);
        !           167:                }
        !           168:        }
        !           169:
        !           170:        argc -= optind;
        !           171:        argv += optind;
        !           172:        if (argc > 0)
        !           173:                errx(EX_USAGE, "unrecognized trailing arguments");
        !           174:
        !           175:        /* Before getting any further, chroot to the CVS repository's root
        !           176:         * directory and drop all privileges to the appropriate user and
        !           177:         * group so we can't cause damage outside of the CVS data.
        !           178:         */
        !           179:        if (chroot(cvsd_root) == -1) {
        !           180:                cvs_log(LP_ERRNO, "failed to chroot to %s", cvsd_root);
        !           181:                exit(EX_OSERR);
        !           182:        }
        !           183:        (void)chdir("/");
        !           184:        cvs_log(LP_INFO, "dropping privileges to %d:%d", cvsd_uid, cvsd_gid);
        !           185:        if (setgid(cvsd_gid) == -1) {
        !           186:                cvs_log(LP_ERRNO, "failed to drop group privileges to %s",
        !           187:                    CVSD_GROUP);
        !           188:                return (-1);
        !           189:        }
        !           190:
        !           191:        if (setuid(cvsd_uid) == -1) {
        !           192:                cvs_log(LP_ERRNO, "failed to drop user privileges to %s",
        !           193:                    CVSD_USER);
        !           194:                return (-1);
        !           195:        }
        !           196:
        !           197:        signal(SIGINT, cvsd_sighdlr);
        !           198:        signal(SIGQUIT, cvsd_sighdlr);
        !           199:        signal(SIGTERM, cvsd_sighdlr);
        !           200:        signal(SIGPIPE, SIG_IGN);
        !           201:
        !           202:        setproctitle("%s [child %d]", __progname, getpid());
        !           203:
        !           204:        for (;;) {
        !           205:                ret = cvsd_child_getreq(&req);
        !           206:                if (ret <= 0)
        !           207:                        break;
        !           208:
        !           209:                switch (req.cr_op) {
        !           210:                case CVS_OP_DIFF:
        !           211:                case CVS_OP_UPDATE:
        !           212:                default:
        !           213:                }
        !           214:                printf("request ID: %d, nfiles = %d\n", req.cr_op,
        !           215:                    req.cr_nfiles);
        !           216:        }
        !           217:
        !           218:        close(cvsd_sess_fd);
        !           219:
        !           220:        cvs_log_cleanup();
        !           221:
        !           222:        return (0);
        !           223: }
        !           224:
        !           225:
        !           226: /*
        !           227:  * cvsd_child_getreq()
        !           228:  *
        !           229:  * Read the next request available on the session socket.
        !           230:  * Returns 1 if a request was received, 0 if there are no more requests to
        !           231:  * serve, and -1 in case of failure.
        !           232:  */
        !           233: int
        !           234: cvsd_child_getreq(struct cvsd_req *reqp)
        !           235: {
        !           236:        ssize_t ret;
        !           237:        if ((ret = read(cvsd_sess_fd, reqp, sizeof(*reqp))) == -1) {
        !           238:                cvs_log(LP_ERRNO, "failed to read request");
        !           239:        } else if (ret > 0) {
        !           240:                printf("reqlen = %d\n", ret);
        !           241:                ret = 1;
        !           242:        }
        !           243:
        !           244:        return ((int)ret);
        !           245: }
        !           246:
        !           247:
        !           248: /*
        !           249:  * cvsd_child_reqhdlr()
        !           250:  *
        !           251:  */
        !           252: int
        !           253: cvsd_child_reqhdlr(struct cvsp_req *req)
        !           254: {
        !           255:        int ret;
        !           256:
        !           257:        switch (req->req_code) {
        !           258:        case CVSP_REQ_MOTD:
        !           259:                ret = cvs_proto_sendresp(cvsd_sess_fd, CVSP_RESP_DONE,
        !           260:                    cvsd_motd, strlen(cvsd_motd) + 1);
        !           261:                break;
        !           262:        case CVSP_REQ_VERSION:
        !           263:        case CVSP_REQ_GETMSG:
        !           264:        case CVSP_REQ_SETMSG:
        !           265:        default:
        !           266:                ret = cvs_proto_sendresp(cvsd_sess_fd, CVSP_RESP_INVREQ,
        !           267:                    req->req_seq, NULL, 0);
        !           268:        }
        !           269:
        !           270:        return (ret);
        !           271: }