1*c9899b11Skrw /* $OpenBSD: process.c,v 1.23 2016/03/16 15:41:10 krw Exp $ */
2ebad6d3cSmickey
3df930be7Sderaadt /*
4df930be7Sderaadt * Copyright (c) 1983 Regents of the University of California.
5df930be7Sderaadt * All rights reserved.
6df930be7Sderaadt *
7df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt * modification, are permitted provided that the following conditions
9df930be7Sderaadt * are met:
10df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt * documentation and/or other materials provided with the distribution.
15e33d3bd3Smillert * 3. Neither the name of the University nor the names of its contributors
16df930be7Sderaadt * may be used to endorse or promote products derived from this software
17df930be7Sderaadt * without specific prior written permission.
18df930be7Sderaadt *
19df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df930be7Sderaadt * SUCH DAMAGE.
30df930be7Sderaadt */
31df930be7Sderaadt
32df930be7Sderaadt /*
33df930be7Sderaadt * process.c handles the requests, which can be of three types:
34df930be7Sderaadt * ANNOUNCE - announce to a user that a talk is wanted
35df930be7Sderaadt * LEAVE_INVITE - insert the request into the table
36df930be7Sderaadt * LOOK_UP - look up to see if a request is waiting in
37df930be7Sderaadt * in the table for the local user
38df930be7Sderaadt * DELETE - delete invitation
39df930be7Sderaadt */
40df930be7Sderaadt #include <sys/socket.h>
41f652621fSmestre #include <sys/stat.h>
42ebad6d3cSmickey #include <arpa/inet.h>
43df930be7Sderaadt #include <protocols/talkd.h>
44f652621fSmestre
45f652621fSmestre #include <ctype.h>
46f652621fSmestre #include <limits.h>
47df930be7Sderaadt #include <netdb.h>
48f652621fSmestre #include <paths.h>
49df930be7Sderaadt #include <stdio.h>
50df930be7Sderaadt #include <string.h>
51f652621fSmestre #include <syslog.h>
52f652621fSmestre #include <utmp.h>
53f652621fSmestre
54ebad6d3cSmickey #include "talkd.h"
55df930be7Sderaadt
56e5df81a8Smickey #define satosin(sa) ((struct sockaddr_in *)(sa))
57e5df81a8Smickey
58ebad6d3cSmickey void
process_request(CTL_MSG * mp,CTL_RESPONSE * rp)596bcb9e83Sderaadt process_request(CTL_MSG *mp, CTL_RESPONSE *rp)
60df930be7Sderaadt {
6150d2b651Smpech CTL_MSG *ptr;
62fbfbd66cSmillert char *s;
63df930be7Sderaadt
64df930be7Sderaadt rp->vers = TALK_VERSION;
65df930be7Sderaadt rp->type = mp->type;
66df930be7Sderaadt rp->id_num = htonl(0);
67df930be7Sderaadt if (mp->vers != TALK_VERSION) {
68df930be7Sderaadt syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
69df930be7Sderaadt rp->answer = BADVERSION;
70df930be7Sderaadt return;
71df930be7Sderaadt }
72df930be7Sderaadt mp->id_num = ntohl(mp->id_num);
73ebad6d3cSmickey if (ntohs(mp->addr.sa_family) != AF_INET) {
74df930be7Sderaadt syslog(LOG_WARNING, "Bad address, family %d",
75ebad6d3cSmickey ntohs(mp->addr.sa_family));
76df930be7Sderaadt rp->answer = BADADDR;
77df930be7Sderaadt return;
78df930be7Sderaadt }
79ebad6d3cSmickey if (ntohs(mp->ctl_addr.sa_family) != AF_INET) {
80df930be7Sderaadt syslog(LOG_WARNING, "Bad control address, family %d",
81ebad6d3cSmickey ntohs(mp->ctl_addr.sa_family));
82df930be7Sderaadt rp->answer = BADCTLADDR;
83df930be7Sderaadt return;
84df930be7Sderaadt }
85fbfbd66cSmillert for (s = mp->l_name; *s; s++)
864207a9b6Sderaadt if (!isprint((unsigned char)*s)) {
87fbfbd66cSmillert syslog(LOG_NOTICE, "Illegal user name. Aborting");
88fbfbd66cSmillert rp->answer = FAILED;
89fbfbd66cSmillert return;
90fbfbd66cSmillert }
91ebad6d3cSmickey if (memcmp(&satosin(&rp->addr)->sin_addr,
92ebad6d3cSmickey &satosin(&mp->ctl_addr)->sin_addr,
93ebad6d3cSmickey sizeof(struct in_addr))) {
94ebad6d3cSmickey char buf1[32], buf2[32];
95527d2965Sderaadt
96527d2965Sderaadt strlcpy(buf1, inet_ntoa(satosin(&rp->addr)->sin_addr),
97b68d276fSitojun sizeof(buf1));
98527d2965Sderaadt strlcpy(buf2, inet_ntoa(satosin(&mp->ctl_addr)->sin_addr),
99b68d276fSitojun sizeof(buf2));
100ea0b9ac4Sderaadt syslog(LOG_WARNING, "addresses are different, %s != %s",
101ebad6d3cSmickey buf1, buf2);
102ebad6d3cSmickey }
103ebad6d3cSmickey rp->addr.sa_family = 0;
104df930be7Sderaadt mp->pid = ntohl(mp->pid);
105df930be7Sderaadt if (debug)
106df930be7Sderaadt print_request("process_request", mp);
107df930be7Sderaadt switch (mp->type) {
108df930be7Sderaadt
109df930be7Sderaadt case ANNOUNCE:
110df930be7Sderaadt do_announce(mp, rp);
111df930be7Sderaadt break;
112df930be7Sderaadt
113df930be7Sderaadt case LEAVE_INVITE:
114df930be7Sderaadt ptr = find_request(mp);
115*c9899b11Skrw if (ptr != NULL) {
116df930be7Sderaadt rp->id_num = htonl(ptr->id_num);
117df930be7Sderaadt rp->answer = SUCCESS;
118df930be7Sderaadt } else
119df930be7Sderaadt insert_table(mp, rp);
120df930be7Sderaadt break;
121df930be7Sderaadt
122df930be7Sderaadt case LOOK_UP:
123df930be7Sderaadt ptr = find_match(mp);
124*c9899b11Skrw if (ptr != NULL) {
125df930be7Sderaadt rp->id_num = htonl(ptr->id_num);
126df930be7Sderaadt rp->addr = ptr->addr;
127ebad6d3cSmickey rp->addr.sa_family = ptr->addr.sa_family;
128df930be7Sderaadt rp->answer = SUCCESS;
129df930be7Sderaadt } else
130df930be7Sderaadt rp->answer = NOT_HERE;
131df930be7Sderaadt break;
132df930be7Sderaadt
133df930be7Sderaadt case DELETE:
134df930be7Sderaadt rp->answer = delete_invite(mp->id_num);
135df930be7Sderaadt break;
136df930be7Sderaadt
137df930be7Sderaadt default:
138df930be7Sderaadt rp->answer = UNKNOWN_REQUEST;
139df930be7Sderaadt break;
140df930be7Sderaadt }
141df930be7Sderaadt if (debug)
142df930be7Sderaadt print_response("process_request", rp);
143df930be7Sderaadt }
144df930be7Sderaadt
145ebad6d3cSmickey void
do_announce(CTL_MSG * mp,CTL_RESPONSE * rp)1466bcb9e83Sderaadt do_announce(CTL_MSG *mp, CTL_RESPONSE *rp)
147df930be7Sderaadt {
148df930be7Sderaadt struct hostent *hp;
149df930be7Sderaadt CTL_MSG *ptr;
150df930be7Sderaadt int result;
151df930be7Sderaadt
152df930be7Sderaadt /* see if the user is logged */
153b68d276fSitojun result = find_user(mp->r_name, mp->r_tty, sizeof(mp->r_tty));
154df930be7Sderaadt if (result != SUCCESS) {
155df930be7Sderaadt rp->answer = result;
156df930be7Sderaadt return;
157df930be7Sderaadt }
158df930be7Sderaadt hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
159df930be7Sderaadt sizeof(struct in_addr), AF_INET);
160*c9899b11Skrw if (hp == NULL) {
161df930be7Sderaadt rp->answer = MACHINE_UNKNOWN;
162df930be7Sderaadt return;
163df930be7Sderaadt }
164df930be7Sderaadt ptr = find_request(mp);
165df930be7Sderaadt if (ptr == (CTL_MSG *) 0) {
166df930be7Sderaadt insert_table(mp, rp);
167df930be7Sderaadt rp->answer = announce(mp, hp->h_name);
168df930be7Sderaadt return;
169df930be7Sderaadt }
170df930be7Sderaadt if (mp->id_num > ptr->id_num) {
171df930be7Sderaadt /*
172df930be7Sderaadt * This is an explicit re-announce, so update the id_num
173df930be7Sderaadt * field to avoid duplicates and re-announce the talk.
174df930be7Sderaadt */
175df930be7Sderaadt ptr->id_num = new_id();
176df930be7Sderaadt rp->id_num = htonl(ptr->id_num);
177df930be7Sderaadt rp->answer = announce(mp, hp->h_name);
178df930be7Sderaadt } else {
179df930be7Sderaadt /* a duplicated request, so ignore it */
180df930be7Sderaadt rp->id_num = htonl(ptr->id_num);
181df930be7Sderaadt rp->answer = SUCCESS;
182df930be7Sderaadt }
183df930be7Sderaadt }
184df930be7Sderaadt
185df930be7Sderaadt /*
186df930be7Sderaadt * Search utmp for the local user
187df930be7Sderaadt */
188ebad6d3cSmickey int
find_user(char * name,char * tty,size_t ttyl)1896bcb9e83Sderaadt find_user(char *name, char *tty, size_t ttyl)
190df930be7Sderaadt {
1917835351dSmickey struct utmp ubuf, ubuf1;
192df930be7Sderaadt int status;
19310d9ecc2Sderaadt FILE *fp;
1946f199a93Smillert char line[UT_LINESIZE+1];
195b9fc9a72Sderaadt char ftty[PATH_MAX];
1967835351dSmickey time_t idle, now;
197df930be7Sderaadt
1982689a02fSderaadt time(&now);
1992689a02fSderaadt idle = INT_MAX;
20010d9ecc2Sderaadt if ((fp = fopen(_PATH_UTMP, "r")) == NULL) {
201df930be7Sderaadt fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
202df930be7Sderaadt return (FAILED);
203df930be7Sderaadt }
204df930be7Sderaadt #define SCMPN(a, b) strncmp(a, b, sizeof(a))
205df930be7Sderaadt status = NOT_HERE;
206b68d276fSitojun (void) strlcpy(ftty, _PATH_DEV, sizeof(ftty));
20710d9ecc2Sderaadt while (fread((char *) &ubuf, sizeof(ubuf), 1, fp) == 1)
208df930be7Sderaadt if (SCMPN(ubuf.ut_name, name) == 0) {
209df930be7Sderaadt if (*tty == '\0') {
210df930be7Sderaadt /* no particular tty was requested */
2117835351dSmickey struct stat statb;
2122689a02fSderaadt
2136f199a93Smillert memcpy(line, ubuf.ut_line, UT_LINESIZE);
2146f199a93Smillert line[sizeof(line)-1] = '\0';
215b049587cSmillert ftty[sizeof(_PATH_DEV)-1] = '\0';
216b049587cSmillert strlcat(ftty, line, sizeof(ftty));
217df930be7Sderaadt if (stat(ftty, &statb) == 0) {
2187835351dSmickey if (!(statb.st_mode & S_IWGRP)) {
2192689a02fSderaadt if (status == NOT_HERE)
2207835351dSmickey status = PERMISSION_DENIED;
221bfd07112Sderaadt } else if (now - statb.st_atime < idle) {
2227835351dSmickey idle = now - statb.st_atime;
223df930be7Sderaadt status = SUCCESS;
2247835351dSmickey ubuf1 = ubuf;
225df930be7Sderaadt }
226df930be7Sderaadt }
2276f199a93Smillert } else if (SCMPN(ubuf.ut_line, tty) == 0) {
228df930be7Sderaadt status = SUCCESS;
229df930be7Sderaadt break;
230df930be7Sderaadt }
231df930be7Sderaadt }
23210d9ecc2Sderaadt fclose(fp);
2336f199a93Smillert if (*tty == '\0' && status == SUCCESS) {
2346f199a93Smillert memcpy(line, ubuf1.ut_line, UT_LINESIZE);
2356f199a93Smillert line[sizeof(line)-1] = '\0';
2366f199a93Smillert strlcpy(tty, line, ttyl);
2376f199a93Smillert }
238df930be7Sderaadt return (status);
239df930be7Sderaadt }
240