1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #ifndef lint
33 #if 0
34 static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93";
35 #endif
36 #endif /* not lint */
37
38 /*
39 * process.c handles the requests, which can be of three types:
40 * ANNOUNCE - announce to a user that a talk is wanted
41 * LEAVE_INVITE - insert the request into the table
42 * LOOK_UP - look up to see if a request is waiting in
43 * in the table for the local user
44 * DELETE - delete invitation
45 */
46 #include <sys/param.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <protocols/talkd.h>
51 #include <ctype.h>
52 #include <err.h>
53 #include <netdb.h>
54 #include <paths.h>
55 #include <stdio.h>
56 #include <string.h>
57 #include <syslog.h>
58 #include <utmpx.h>
59
60 #include "extern.h"
61
62 void
process_request(CTL_MSG * mp,CTL_RESPONSE * rp)63 process_request(CTL_MSG *mp, CTL_RESPONSE *rp)
64 {
65 CTL_MSG *ptr;
66 char *s;
67
68 rp->vers = TALK_VERSION;
69 rp->type = mp->type;
70 rp->id_num = htonl(0);
71 if (mp->vers != TALK_VERSION) {
72 syslog(LOG_WARNING, "bad protocol version %d", mp->vers);
73 rp->answer = BADVERSION;
74 return;
75 }
76 mp->id_num = ntohl(mp->id_num);
77 mp->addr.sa_family = ntohs(mp->addr.sa_family);
78 if (mp->addr.sa_family != AF_INET) {
79 syslog(LOG_WARNING, "bad address, family %d",
80 mp->addr.sa_family);
81 rp->answer = BADADDR;
82 return;
83 }
84 mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
85 if (mp->ctl_addr.sa_family != AF_INET) {
86 syslog(LOG_WARNING, "bad control address, family %d",
87 mp->ctl_addr.sa_family);
88 rp->answer = BADCTLADDR;
89 return;
90 }
91 for (s = mp->l_name; *s; s++)
92 if (!isprint(*s)) {
93 syslog(LOG_NOTICE, "illegal user name. Aborting");
94 rp->answer = FAILED;
95 return;
96 }
97 mp->pid = ntohl(mp->pid);
98 if (debug)
99 print_request("process_request", mp);
100 switch (mp->type) {
101
102 case ANNOUNCE:
103 do_announce(mp, rp);
104 break;
105
106 case LEAVE_INVITE:
107 ptr = find_request(mp);
108 if (ptr != (CTL_MSG *)0) {
109 rp->id_num = htonl(ptr->id_num);
110 rp->answer = SUCCESS;
111 } else
112 insert_table(mp, rp);
113 break;
114
115 case LOOK_UP:
116 ptr = find_match(mp);
117 if (ptr != (CTL_MSG *)0) {
118 rp->id_num = htonl(ptr->id_num);
119 rp->addr = ptr->addr;
120 rp->addr.sa_family = htons(ptr->addr.sa_family);
121 rp->answer = SUCCESS;
122 } else
123 rp->answer = NOT_HERE;
124 break;
125
126 case DELETE:
127 rp->answer = delete_invite(mp->id_num);
128 break;
129
130 default:
131 rp->answer = UNKNOWN_REQUEST;
132 break;
133 }
134 if (debug)
135 print_response("process_request", rp);
136 }
137
138 void
do_announce(CTL_MSG * mp,CTL_RESPONSE * rp)139 do_announce(CTL_MSG *mp, CTL_RESPONSE *rp)
140 {
141 struct hostent *hp;
142 CTL_MSG *ptr;
143 int result;
144
145 /* see if the user is logged */
146 result = find_user(mp->r_name, mp->r_tty);
147 if (result != SUCCESS) {
148 rp->answer = result;
149 return;
150 }
151 #define satosin(sa) ((struct sockaddr_in *)(void *)(sa))
152 hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
153 sizeof (struct in_addr), AF_INET);
154 if (hp == (struct hostent *)0) {
155 rp->answer = MACHINE_UNKNOWN;
156 return;
157 }
158 ptr = find_request(mp);
159 if (ptr == (CTL_MSG *) 0) {
160 insert_table(mp, rp);
161 rp->answer = announce(mp, hp->h_name);
162 return;
163 }
164 if (mp->id_num > ptr->id_num) {
165 /*
166 * This is an explicit re-announce, so update the id_num
167 * field to avoid duplicates and re-announce the talk.
168 */
169 ptr->id_num = new_id();
170 rp->id_num = htonl(ptr->id_num);
171 rp->answer = announce(mp, hp->h_name);
172 } else {
173 /* a duplicated request, so ignore it */
174 rp->id_num = htonl(ptr->id_num);
175 rp->answer = SUCCESS;
176 }
177 }
178
179 /*
180 * Search utmp for the local user
181 */
182 int
find_user(const char * name,char * tty)183 find_user(const char *name, char *tty)
184 {
185 struct utmpx *ut;
186 int status;
187 struct stat statb;
188 time_t best = 0;
189 char ftty[sizeof(_PATH_DEV) - 1 + sizeof(ut->ut_line)];
190
191 setutxent();
192 status = NOT_HERE;
193 (void) strcpy(ftty, _PATH_DEV);
194 while ((ut = getutxent()) != NULL)
195 if (ut->ut_type == USER_PROCESS &&
196 strcmp(ut->ut_user, name) == 0) {
197 if (*tty == '\0' || best != 0) {
198 if (best == 0)
199 status = PERMISSION_DENIED;
200 /* no particular tty was requested */
201 (void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
202 ut->ut_line);
203 if (stat(ftty, &statb) == 0) {
204 if (!(statb.st_mode & 020))
205 continue;
206 if (statb.st_atime > best) {
207 best = statb.st_atime;
208 (void) strcpy(tty, ut->ut_line);
209 status = SUCCESS;
210 continue;
211 }
212 }
213 }
214 if (strcmp(ut->ut_line, tty) == 0) {
215 status = SUCCESS;
216 break;
217 }
218 }
219 endutxent();
220 return (status);
221 }
222