1*44f6d24cSlukem /* $NetBSD: term_chk.c,v 1.8 2009/04/14 07:59:17 lukem Exp $ */
273b3e2aeSchristos
373b3e2aeSchristos /*
473b3e2aeSchristos * Copyright (c) 1989, 1993
573b3e2aeSchristos * The Regents of the University of California. All rights reserved.
673b3e2aeSchristos *
773b3e2aeSchristos * This code is derived from software contributed to Berkeley by
873b3e2aeSchristos * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
973b3e2aeSchristos *
1073b3e2aeSchristos * Redistribution and use in source and binary forms, with or without
1173b3e2aeSchristos * modification, are permitted provided that the following conditions
1273b3e2aeSchristos * are met:
1373b3e2aeSchristos * 1. Redistributions of source code must retain the above copyright
1473b3e2aeSchristos * notice, this list of conditions and the following disclaimer.
1573b3e2aeSchristos * 2. Redistributions in binary form must reproduce the above copyright
1673b3e2aeSchristos * notice, this list of conditions and the following disclaimer in the
1773b3e2aeSchristos * documentation and/or other materials provided with the distribution.
1889aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1973b3e2aeSchristos * may be used to endorse or promote products derived from this software
2073b3e2aeSchristos * without specific prior written permission.
2173b3e2aeSchristos *
2273b3e2aeSchristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2373b3e2aeSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2473b3e2aeSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2573b3e2aeSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2673b3e2aeSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2773b3e2aeSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2873b3e2aeSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2973b3e2aeSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3073b3e2aeSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3173b3e2aeSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3273b3e2aeSchristos * SUCH DAMAGE.
3373b3e2aeSchristos */
3473b3e2aeSchristos
3573b3e2aeSchristos #include <sys/cdefs.h>
3673b3e2aeSchristos #ifndef lint
37*44f6d24cSlukem __RCSID("$NetBSD: term_chk.c,v 1.8 2009/04/14 07:59:17 lukem Exp $");
3873b3e2aeSchristos #endif
3973b3e2aeSchristos
4073b3e2aeSchristos #include <sys/types.h>
4173b3e2aeSchristos #include <sys/param.h>
4273b3e2aeSchristos #include <sys/stat.h>
4373b3e2aeSchristos #include <time.h>
4473b3e2aeSchristos #include <stdio.h>
4573b3e2aeSchristos #include <errno.h>
4673b3e2aeSchristos #include <unistd.h>
4773b3e2aeSchristos #include <paths.h>
4873b3e2aeSchristos #include <fcntl.h>
4973b3e2aeSchristos #include <string.h>
5073b3e2aeSchristos #include <err.h>
5173b3e2aeSchristos
5273b3e2aeSchristos #include "term_chk.h"
5373b3e2aeSchristos
5473b3e2aeSchristos /*
5573b3e2aeSchristos * term_chk - check that a terminal exists, and get the message bit
5673b3e2aeSchristos * and the access time
5773b3e2aeSchristos */
5873b3e2aeSchristos int
term_chk(uid_t uid,const char * tty,int * msgsokP,time_t * atimeP,int ismytty,gid_t saved_egid)5973b3e2aeSchristos term_chk(uid_t uid, const char *tty, int *msgsokP, time_t *atimeP, int ismytty,
6073b3e2aeSchristos gid_t saved_egid)
6173b3e2aeSchristos {
6273b3e2aeSchristos char path[MAXPATHLEN];
6373b3e2aeSchristos struct stat s;
6473b3e2aeSchristos int i, fd, serrno;
6573b3e2aeSchristos
6667a132acSchristos if (strstr(tty, "../") != NULL) {
67b0eade51Schristos errno = EINVAL;
68b0eade51Schristos return -1;
6973b3e2aeSchristos }
7073b3e2aeSchristos i = snprintf(path, sizeof path, _PATH_DEV "%s", tty);
71*44f6d24cSlukem if (i < 0 || i >= (int)sizeof(path)) {
72b0eade51Schristos errno = ENOMEM;
73b0eade51Schristos return -1;
7473b3e2aeSchristos }
7573b3e2aeSchristos
7673b3e2aeSchristos (void)setegid(saved_egid);
7773b3e2aeSchristos fd = open(path, O_WRONLY, 0);
7873b3e2aeSchristos serrno = errno;
7973b3e2aeSchristos (void)setegid(getgid());
8073b3e2aeSchristos errno = serrno;
8173b3e2aeSchristos
8273b3e2aeSchristos if (fd == -1)
8373b3e2aeSchristos return(-1);
8473b3e2aeSchristos if (fstat(fd, &s) == -1)
8573b3e2aeSchristos goto error;
86b0eade51Schristos if (!isatty(fd))
8773b3e2aeSchristos goto error;
882d67d54fSchristos if (s.st_uid != uid && uid != 0) {
89b0eade51Schristos errno = EPERM;
90b0eade51Schristos goto error;
91b0eade51Schristos }
9274c9d10cSchristos if (msgsokP)
9373b3e2aeSchristos *msgsokP = (s.st_mode & S_IWGRP) != 0; /* group write bit */
9474c9d10cSchristos if (atimeP)
9573b3e2aeSchristos *atimeP = s.st_atime;
9673b3e2aeSchristos if (ismytty)
9773b3e2aeSchristos (void)close(fd);
98b0eade51Schristos return ismytty ? 0 : fd;
9973b3e2aeSchristos error:
10073b3e2aeSchristos if (fd != -1) {
10173b3e2aeSchristos serrno = errno;
102b0eade51Schristos (void)close(fd);
10373b3e2aeSchristos errno = serrno;
10473b3e2aeSchristos }
105b0eade51Schristos return -1;
10673b3e2aeSchristos }
10773b3e2aeSchristos
10873b3e2aeSchristos char *
check_sender(time_t * atime,uid_t myuid,gid_t saved_egid)10973b3e2aeSchristos check_sender(time_t *atime, uid_t myuid, gid_t saved_egid)
11073b3e2aeSchristos {
11173b3e2aeSchristos int myttyfd;
11273b3e2aeSchristos int msgsok;
11373b3e2aeSchristos char *mytty;
11473b3e2aeSchristos
11573b3e2aeSchristos /* check that sender has write enabled */
11673b3e2aeSchristos if (isatty(fileno(stdin)))
11773b3e2aeSchristos myttyfd = fileno(stdin);
11873b3e2aeSchristos else if (isatty(fileno(stdout)))
11973b3e2aeSchristos myttyfd = fileno(stdout);
12073b3e2aeSchristos else if (isatty(fileno(stderr)))
12173b3e2aeSchristos myttyfd = fileno(stderr);
12274c9d10cSchristos else if (atime == NULL)
1234b03e4a9Schristos return NULL;
12473b3e2aeSchristos else
1254b03e4a9Schristos errx(1, "Cannot find your tty");
1264b03e4a9Schristos if ((mytty = ttyname(myttyfd)) == NULL)
1274b03e4a9Schristos err(1, "Cannot find the name of your tty");
12867a132acSchristos if (strncmp(mytty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
12967a132acSchristos mytty += sizeof(_PATH_DEV) - 1;
13073b3e2aeSchristos if (term_chk(myuid, mytty, &msgsok, atime, 1, saved_egid) == -1)
13173b3e2aeSchristos err(1, "%s%s", _PATH_DEV, mytty);
13273b3e2aeSchristos if (!msgsok) {
13373b3e2aeSchristos warnx(
13473b3e2aeSchristos "You have write permission turned off; no reply possible");
13573b3e2aeSchristos }
13673b3e2aeSchristos return mytty;
13773b3e2aeSchristos }
138