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 #endif /* not lint */ 34 35 /* 36 * process.c handles the requests, which can be of three types: 37 * ANNOUNCE - announce to a user that a talk is wanted 38 * LEAVE_INVITE - insert the request into the table 39 * LOOK_UP - look up to see if a request is waiting in 40 * in the table for the local user 41 * DELETE - delete invitation 42 */ 43 #include <sys/param.h> 44 #include <sys/stat.h> 45 #include <sys/socket.h> 46 #include <netinet/in.h> 47 #include <protocols/talkd.h> 48 #include <ctype.h> 49 #include <err.h> 50 #include <netdb.h> 51 #include <paths.h> 52 #include <stdio.h> 53 #include <string.h> 54 #include <syslog.h> 55 #include <utmpx.h> 56 57 #include "extern.h" 58 59 void 60 process_request(CTL_MSG *mp, CTL_RESPONSE *rp) 61 { 62 CTL_MSG *ptr; 63 char *s; 64 65 rp->vers = TALK_VERSION; 66 rp->type = mp->type; 67 rp->id_num = htonl(0); 68 if (mp->vers != TALK_VERSION) { 69 syslog(LOG_WARNING, "bad protocol version %d", mp->vers); 70 rp->answer = BADVERSION; 71 return; 72 } 73 mp->id_num = ntohl(mp->id_num); 74 mp->addr.sa_family = ntohs(mp->addr.sa_family); 75 if (mp->addr.sa_family != AF_INET) { 76 syslog(LOG_WARNING, "bad address, family %d", 77 mp->addr.sa_family); 78 rp->answer = BADADDR; 79 return; 80 } 81 mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); 82 if (mp->ctl_addr.sa_family != AF_INET) { 83 syslog(LOG_WARNING, "bad control address, family %d", 84 mp->ctl_addr.sa_family); 85 rp->answer = BADCTLADDR; 86 return; 87 } 88 for (s = mp->l_name; *s; s++) 89 if (!isprint(*s)) { 90 syslog(LOG_NOTICE, "illegal user name. Aborting"); 91 rp->answer = FAILED; 92 return; 93 } 94 mp->pid = ntohl(mp->pid); 95 if (debug) 96 print_request("process_request", mp); 97 switch (mp->type) { 98 99 case ANNOUNCE: 100 do_announce(mp, rp); 101 break; 102 103 case LEAVE_INVITE: 104 ptr = find_request(mp); 105 if (ptr != (CTL_MSG *)0) { 106 rp->id_num = htonl(ptr->id_num); 107 rp->answer = SUCCESS; 108 } else 109 insert_table(mp, rp); 110 break; 111 112 case LOOK_UP: 113 ptr = find_match(mp); 114 if (ptr != (CTL_MSG *)0) { 115 rp->id_num = htonl(ptr->id_num); 116 rp->addr = ptr->addr; 117 rp->addr.sa_family = htons(ptr->addr.sa_family); 118 rp->answer = SUCCESS; 119 } else 120 rp->answer = NOT_HERE; 121 break; 122 123 case DELETE: 124 rp->answer = delete_invite(mp->id_num); 125 break; 126 127 default: 128 rp->answer = UNKNOWN_REQUEST; 129 break; 130 } 131 if (debug) 132 print_response("process_request", rp); 133 } 134 135 void 136 do_announce(CTL_MSG *mp, CTL_RESPONSE *rp) 137 { 138 struct hostent *hp; 139 CTL_MSG *ptr; 140 int result; 141 142 /* see if the user is logged */ 143 result = find_user(mp->r_name, mp->r_tty); 144 if (result != SUCCESS) { 145 rp->answer = result; 146 return; 147 } 148 #define satosin(sa) ((struct sockaddr_in *)(void *)(sa)) 149 hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr, 150 sizeof (struct in_addr), AF_INET); 151 if (hp == (struct hostent *)0) { 152 rp->answer = MACHINE_UNKNOWN; 153 return; 154 } 155 ptr = find_request(mp); 156 if (ptr == (CTL_MSG *) 0) { 157 insert_table(mp, rp); 158 rp->answer = announce(mp, hp->h_name); 159 return; 160 } 161 if (mp->id_num > ptr->id_num) { 162 /* 163 * This is an explicit re-announce, so update the id_num 164 * field to avoid duplicates and re-announce the talk. 165 */ 166 ptr->id_num = new_id(); 167 rp->id_num = htonl(ptr->id_num); 168 rp->answer = announce(mp, hp->h_name); 169 } else { 170 /* a duplicated request, so ignore it */ 171 rp->id_num = htonl(ptr->id_num); 172 rp->answer = SUCCESS; 173 } 174 } 175 176 /* 177 * Search utmp for the local user 178 */ 179 int 180 find_user(const char *name, char *tty) 181 { 182 struct utmpx *ut; 183 int status; 184 struct stat statb; 185 time_t best = 0; 186 char ftty[sizeof(_PATH_DEV) - 1 + sizeof(ut->ut_line)]; 187 188 setutxent(); 189 status = NOT_HERE; 190 (void) strcpy(ftty, _PATH_DEV); 191 while ((ut = getutxent()) != NULL) 192 if (ut->ut_type == USER_PROCESS && 193 strcmp(ut->ut_user, name) == 0) { 194 if (*tty == '\0' || best != 0) { 195 if (best == 0) 196 status = PERMISSION_DENIED; 197 /* no particular tty was requested */ 198 (void) strcpy(ftty + sizeof(_PATH_DEV) - 1, 199 ut->ut_line); 200 if (stat(ftty, &statb) == 0) { 201 if (!(statb.st_mode & 020)) 202 continue; 203 if (statb.st_atime > best) { 204 best = statb.st_atime; 205 (void) strcpy(tty, ut->ut_line); 206 status = SUCCESS; 207 continue; 208 } 209 } 210 } 211 if (strcmp(ut->ut_line, tty) == 0) { 212 status = SUCCESS; 213 break; 214 } 215 } 216 endutxent(); 217 return (status); 218 } 219