1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25 /*
26 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
27 * All Rights Reserved.
28 */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California.
33 * All Rights Reserved.
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42
43 /*
44 * process.c handles the requests, which can be of three types:
45 *
46 * ANNOUNCE - announce to a user that a talk is wanted
47 *
48 * LEAVE_INVITE - insert the request into the table
49 *
50 * LOOK_UP - look up to see if a request is waiting in
51 * in the table for the local user
52 *
53 * DELETE - delete invitation
54 *
55 */
56
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <fcntl.h>
60 #include <syslog.h>
61 #include <string.h>
62 #include <utmpx.h>
63 #include <unistd.h>
64 #include <stdlib.h>
65 #include <stdio.h>
66 #include "talkd_impl.h"
67
68 static void do_announce(CTL_MSG *request, CTL_RESPONSE *response);
69 static int find_user(char *name, char *tty);
70
71 void
process_request(CTL_MSG * request,CTL_RESPONSE * response)72 process_request(CTL_MSG *request, CTL_RESPONSE *response)
73 {
74 CTL_MSG *ptr;
75
76 response->type = request->type;
77 response->id_num = 0;
78
79 /*
80 * Check if any of the strings within the request structure aren't
81 * NUL terminated, and if so don't bother processing the request
82 * further.
83 */
84 if ((memchr(request->l_name, '\0', sizeof (request->l_name)) == NULL) ||
85 (memchr(request->r_name, '\0', sizeof (request->r_name)) == NULL) ||
86 (memchr(request->r_tty, '\0', sizeof (request->r_tty)) == NULL)) {
87 response->answer = FAILED;
88 openlog("talk", 0, LOG_AUTH);
89 syslog(LOG_CRIT, "malformed talk request\n");
90 closelog();
91 return;
92 }
93
94 switch (request->type) {
95
96 case ANNOUNCE :
97
98 do_announce(request, response);
99 break;
100
101 case LEAVE_INVITE :
102
103 ptr = find_request(request);
104 if (ptr != NULL) {
105 response->id_num = ptr->id_num;
106 response->answer = SUCCESS;
107 } else {
108 insert_table(request, response);
109 }
110 break;
111
112 case LOOK_UP :
113
114 ptr = find_match(request);
115 if (ptr != NULL) {
116 response->id_num = ptr->id_num;
117 response->addr = ptr->addr;
118 response->answer = SUCCESS;
119 } else {
120 response->answer = NOT_HERE;
121 }
122 break;
123
124 case DELETE :
125
126 response->answer = delete_invite(request->id_num);
127 break;
128
129 default :
130
131 response->answer = UNKNOWN_REQUEST;
132 break;
133 }
134 }
135
136 static void
do_announce(CTL_MSG * request,CTL_RESPONSE * response)137 do_announce(CTL_MSG *request, CTL_RESPONSE *response)
138 {
139 struct hostent *hp;
140 CTL_MSG *ptr;
141 int result;
142
143 /*
144 * See if the user is logged.
145 */
146 result = find_user(request->r_name, request->r_tty);
147 if (result != SUCCESS) {
148 response->answer = result;
149 return;
150 }
151
152 hp = gethostbyaddr((const char *)&request->ctl_addr.sin_addr,
153 sizeof (struct in_addr), AF_INET);
154 if (hp == NULL) {
155 response->answer = MACHINE_UNKNOWN;
156 return;
157 }
158
159 ptr = find_request(request);
160 if (ptr == NULL) {
161 insert_table(request, response);
162 response->answer = announce(request, hp->h_name);
163 } else if (request->id_num > ptr->id_num) {
164 /*
165 * This is an explicit re-announce, so update the id_num
166 * field to avoid duplicates and re-announce the talk.
167 */
168 ptr->id_num = response->id_num = new_id();
169 response->answer = announce(request, hp->h_name);
170 } else {
171 /* a duplicated request, so ignore it */
172 response->id_num = ptr->id_num;
173 response->answer = SUCCESS;
174 }
175 }
176
177 /*
178 * Search utmp for the local user.
179 */
180
181 static int
find_user(char * name,char * tty)182 find_user(char *name, char *tty)
183 {
184 struct utmpx *ubuf;
185 int tfd;
186 char dev[MAXPATHLEN];
187 struct stat stbuf;
188 int problem = NOT_HERE;
189
190 setutxent(); /* reset the utmpx file */
191
192 while (ubuf = getutxent()) {
193 if (ubuf->ut_type == USER_PROCESS &&
194 strncmp(ubuf->ut_user, name, sizeof (ubuf->ut_user)) == 0) {
195 /*
196 * Check if this entry is really a tty.
197 */
198 (void) snprintf(dev, sizeof (dev), "/dev/%.*s",
199 sizeof (ubuf->ut_line), ubuf->ut_line);
200 if ((tfd = open(dev, O_WRONLY|O_NOCTTY)) == -1) {
201 continue;
202 }
203 if (!isatty(tfd)) {
204 (void) close(tfd);
205 openlog("talk", 0, LOG_AUTH);
206 syslog(LOG_CRIT, "%.*s in utmp is not a tty\n",
207 sizeof (ubuf->ut_line), ubuf->ut_line);
208 closelog();
209 continue;
210 }
211 if (*tty == '\0') {
212 /*
213 * No particular tty was requested.
214 */
215 if (fstat(tfd, &stbuf) < 0 ||
216 (stbuf.st_mode&020) == 0) {
217 (void) close(tfd);
218 problem = PERMISSION_DENIED;
219 continue;
220 }
221 (void) close(tfd);
222 (void) strlcpy(tty, ubuf->ut_line, TTY_SIZE);
223 endutxent(); /* close the utmpx file */
224 return (SUCCESS);
225 }
226 (void) close(tfd);
227 if (strcmp(ubuf->ut_line, tty) == 0) {
228 endutxent(); /* close the utmpx file */
229 return (SUCCESS);
230 }
231 }
232 }
233
234 endutxent(); /* close the utmpx file */
235 return (problem);
236 }
237