1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef lint 31 #if 0 32 static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93"; 33 #endif 34 static const char rcsid[] = 35 "$FreeBSD$"; 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 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 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 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