11592Srgrimes/*
21592Srgrimes * Copyright (c) 1983, 1993
31592Srgrimes *	The Regents of the University of California.  All rights reserved.
41592Srgrimes *
51592Srgrimes * Redistribution and use in source and binary forms, with or without
61592Srgrimes * modification, are permitted provided that the following conditions
71592Srgrimes * are met:
81592Srgrimes * 1. Redistributions of source code must retain the above copyright
91592Srgrimes *    notice, this list of conditions and the following disclaimer.
101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111592Srgrimes *    notice, this list of conditions and the following disclaimer in the
121592Srgrimes *    documentation and/or other materials provided with the distribution.
131592Srgrimes * 3. All advertising materials mentioning features or use of this software
141592Srgrimes *    must display the following acknowledgement:
151592Srgrimes *	This product includes software developed by the University of
161592Srgrimes *	California, Berkeley and its contributors.
171592Srgrimes * 4. Neither the name of the University nor the names of its contributors
181592Srgrimes *    may be used to endorse or promote products derived from this software
191592Srgrimes *    without specific prior written permission.
201592Srgrimes *
211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241592Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311592Srgrimes * SUCH DAMAGE.
321592Srgrimes */
331592Srgrimes
341592Srgrimes#ifndef lint
3531491Scharnier#if 0
361592Srgrimesstatic char sccsid[] = "@(#)process.c	8.2 (Berkeley) 11/16/93";
3731491Scharnier#endif
3831491Scharnierstatic const char rcsid[] =
3950476Speter  "$FreeBSD$";
401592Srgrimes#endif /* not lint */
411592Srgrimes
421592Srgrimes/*
431592Srgrimes * process.c handles the requests, which can be of three types:
441592Srgrimes *	ANNOUNCE - announce to a user that a talk is wanted
451592Srgrimes *	LEAVE_INVITE - insert the request into the table
461592Srgrimes *	LOOK_UP - look up to see if a request is waiting in
471592Srgrimes *		  in the table for the local user
481592Srgrimes *	DELETE - delete invitation
491592Srgrimes */
501592Srgrimes#include <sys/param.h>
511592Srgrimes#include <sys/stat.h>
521592Srgrimes#include <sys/socket.h>
531592Srgrimes#include <netinet/in.h>
541592Srgrimes#include <protocols/talkd.h>
5531491Scharnier#include <ctype.h>
5631491Scharnier#include <err.h>
571592Srgrimes#include <netdb.h>
5831491Scharnier#include <paths.h>
591592Srgrimes#include <stdio.h>
601592Srgrimes#include <string.h>
6131491Scharnier#include <syslog.h>
62202210Sed#include <utmpx.h>
631592Srgrimes
6490261Simp#include "extern.h"
651592Srgrimes
6631491Scharniervoid
6790261Simpprocess_request(CTL_MSG *mp, CTL_RESPONSE *rp)
681592Srgrimes{
6990261Simp	CTL_MSG *ptr;
703793Sache	char *s;
711592Srgrimes
721592Srgrimes	rp->vers = TALK_VERSION;
731592Srgrimes	rp->type = mp->type;
741592Srgrimes	rp->id_num = htonl(0);
751592Srgrimes	if (mp->vers != TALK_VERSION) {
7631491Scharnier		syslog(LOG_WARNING, "bad protocol version %d", mp->vers);
771592Srgrimes		rp->answer = BADVERSION;
781592Srgrimes		return;
791592Srgrimes	}
801592Srgrimes	mp->id_num = ntohl(mp->id_num);
811592Srgrimes	mp->addr.sa_family = ntohs(mp->addr.sa_family);
821592Srgrimes	if (mp->addr.sa_family != AF_INET) {
8331491Scharnier		syslog(LOG_WARNING, "bad address, family %d",
841592Srgrimes		    mp->addr.sa_family);
851592Srgrimes		rp->answer = BADADDR;
861592Srgrimes		return;
871592Srgrimes	}
881592Srgrimes	mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
891592Srgrimes	if (mp->ctl_addr.sa_family != AF_INET) {
9031491Scharnier		syslog(LOG_WARNING, "bad control address, family %d",
911592Srgrimes		    mp->ctl_addr.sa_family);
921592Srgrimes		rp->answer = BADCTLADDR;
931592Srgrimes		return;
941592Srgrimes	}
953793Sache	for (s = mp->l_name; *s; s++)
963793Sache		if (!isprint(*s)) {
9731491Scharnier			syslog(LOG_NOTICE, "illegal user name. Aborting");
983793Sache			rp->answer = FAILED;
993793Sache			return;
1003793Sache		}
1011592Srgrimes	mp->pid = ntohl(mp->pid);
1021592Srgrimes	if (debug)
1031592Srgrimes		print_request("process_request", mp);
1041592Srgrimes	switch (mp->type) {
1051592Srgrimes
1061592Srgrimes	case ANNOUNCE:
1071592Srgrimes		do_announce(mp, rp);
1081592Srgrimes		break;
1091592Srgrimes
1101592Srgrimes	case LEAVE_INVITE:
1111592Srgrimes		ptr = find_request(mp);
1121592Srgrimes		if (ptr != (CTL_MSG *)0) {
1131592Srgrimes			rp->id_num = htonl(ptr->id_num);
1141592Srgrimes			rp->answer = SUCCESS;
1151592Srgrimes		} else
1161592Srgrimes			insert_table(mp, rp);
1171592Srgrimes		break;
1181592Srgrimes
1191592Srgrimes	case LOOK_UP:
1201592Srgrimes		ptr = find_match(mp);
1211592Srgrimes		if (ptr != (CTL_MSG *)0) {
1221592Srgrimes			rp->id_num = htonl(ptr->id_num);
1231592Srgrimes			rp->addr = ptr->addr;
1241592Srgrimes			rp->addr.sa_family = htons(ptr->addr.sa_family);
1251592Srgrimes			rp->answer = SUCCESS;
1261592Srgrimes		} else
1271592Srgrimes			rp->answer = NOT_HERE;
1281592Srgrimes		break;
1291592Srgrimes
1301592Srgrimes	case DELETE:
1311592Srgrimes		rp->answer = delete_invite(mp->id_num);
1321592Srgrimes		break;
1331592Srgrimes
1341592Srgrimes	default:
1351592Srgrimes		rp->answer = UNKNOWN_REQUEST;
1361592Srgrimes		break;
1371592Srgrimes	}
1381592Srgrimes	if (debug)
1391592Srgrimes		print_response("process_request", rp);
1401592Srgrimes}
1411592Srgrimes
14231491Scharniervoid
14390261Simpdo_announce(CTL_MSG *mp, CTL_RESPONSE *rp)
1441592Srgrimes{
1451592Srgrimes	struct hostent *hp;
1461592Srgrimes	CTL_MSG *ptr;
1471592Srgrimes	int result;
1481592Srgrimes
1491592Srgrimes	/* see if the user is logged */
1501592Srgrimes	result = find_user(mp->r_name, mp->r_tty);
1511592Srgrimes	if (result != SUCCESS) {
1521592Srgrimes		rp->answer = result;
1531592Srgrimes		return;
1541592Srgrimes	}
155201022Sed#define	satosin(sa)	((struct sockaddr_in *)(void *)(sa))
156201022Sed	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
1571592Srgrimes		sizeof (struct in_addr), AF_INET);
1581592Srgrimes	if (hp == (struct hostent *)0) {
1591592Srgrimes		rp->answer = MACHINE_UNKNOWN;
1601592Srgrimes		return;
1611592Srgrimes	}
1621592Srgrimes	ptr = find_request(mp);
1631592Srgrimes	if (ptr == (CTL_MSG *) 0) {
1641592Srgrimes		insert_table(mp, rp);
1651592Srgrimes		rp->answer = announce(mp, hp->h_name);
1661592Srgrimes		return;
1671592Srgrimes	}
1681592Srgrimes	if (mp->id_num > ptr->id_num) {
1691592Srgrimes		/*
1701592Srgrimes		 * This is an explicit re-announce, so update the id_num
1711592Srgrimes		 * field to avoid duplicates and re-announce the talk.
1721592Srgrimes		 */
1731592Srgrimes		ptr->id_num = new_id();
1741592Srgrimes		rp->id_num = htonl(ptr->id_num);
1751592Srgrimes		rp->answer = announce(mp, hp->h_name);
1761592Srgrimes	} else {
1771592Srgrimes		/* a duplicated request, so ignore it */
1781592Srgrimes		rp->id_num = htonl(ptr->id_num);
1791592Srgrimes		rp->answer = SUCCESS;
1801592Srgrimes	}
1811592Srgrimes}
1821592Srgrimes
1831592Srgrimes/*
1841592Srgrimes * Search utmp for the local user
1851592Srgrimes */
18631491Scharnierint
18790261Simpfind_user(const char *name, char *tty)
1881592Srgrimes{
189200983Sed	struct utmpx *ut;
1901592Srgrimes	int status;
1911592Srgrimes	struct stat statb;
19214783Sjkh	time_t best = 0;
193200983Sed	char ftty[sizeof(_PATH_DEV) - 1 + sizeof(ut->ut_line)];
1941592Srgrimes
195200983Sed	setutxent();
1961592Srgrimes	status = NOT_HERE;
1971592Srgrimes	(void) strcpy(ftty, _PATH_DEV);
198200983Sed	while ((ut = getutxent()) != NULL)
199200983Sed		if (ut->ut_type == USER_PROCESS &&
200200983Sed		    strcmp(ut->ut_user, name) == 0) {
20114783Sjkh			if (*tty == '\0' || best != 0) {
20214783Sjkh				if (best == 0)
20314783Sjkh					status = PERMISSION_DENIED;
2041592Srgrimes				/* no particular tty was requested */
2051592Srgrimes				(void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
206200983Sed				    ut->ut_line);
2071592Srgrimes				if (stat(ftty, &statb) == 0) {
2081592Srgrimes					if (!(statb.st_mode & 020))
2091592Srgrimes						continue;
21014783Sjkh					if (statb.st_atime > best) {
21114783Sjkh						best = statb.st_atime;
212200983Sed						(void) strcpy(tty, ut->ut_line);
21314783Sjkh						status = SUCCESS;
21414783Sjkh						continue;
21514783Sjkh					}
2161592Srgrimes				}
2171592Srgrimes			}
218200983Sed			if (strcmp(ut->ut_line, tty) == 0) {
2191592Srgrimes				status = SUCCESS;
2201592Srgrimes				break;
2211592Srgrimes			}
2221592Srgrimes		}
223200983Sed	endutxent();
2241592Srgrimes	return (status);
2251592Srgrimes}
226