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 /* 41 * process.c handles the requests, which can be of three types: 42 * 43 * ANNOUNCE - announce to a user that a talk is wanted 44 * 45 * LEAVE_INVITE - insert the request into the table 46 * 47 * LOOK_UP - look up to see if a request is waiting in 48 * in the table for the local user 49 * 50 * DELETE - delete invitation 51 * 52 */ 53 54 #include <sys/types.h> 55 #include <sys/stat.h> 56 #include <fcntl.h> 57 #include <syslog.h> 58 #include <string.h> 59 #include <utmpx.h> 60 #include <unistd.h> 61 #include <stdlib.h> 62 #include <stdio.h> 63 #include "talkd_impl.h" 64 65 static void do_announce(CTL_MSG *request, CTL_RESPONSE *response); 66 static int find_user(char *name, char *tty); 67 68 void 69 process_request(CTL_MSG *request, CTL_RESPONSE *response) 70 { 71 CTL_MSG *ptr; 72 73 response->type = request->type; 74 response->id_num = 0; 75 76 /* 77 * Check if any of the strings within the request structure aren't 78 * NUL terminated, and if so don't bother processing the request 79 * further. 80 */ 81 if ((memchr(request->l_name, '\0', sizeof (request->l_name)) == NULL) || 82 (memchr(request->r_name, '\0', sizeof (request->r_name)) == NULL) || 83 (memchr(request->r_tty, '\0', sizeof (request->r_tty)) == NULL)) { 84 response->answer = FAILED; 85 openlog("talk", 0, LOG_AUTH); 86 syslog(LOG_CRIT, "malformed talk request\n"); 87 closelog(); 88 return; 89 } 90 91 switch (request->type) { 92 93 case ANNOUNCE : 94 95 do_announce(request, response); 96 break; 97 98 case LEAVE_INVITE : 99 100 ptr = find_request(request); 101 if (ptr != NULL) { 102 response->id_num = ptr->id_num; 103 response->answer = SUCCESS; 104 } else { 105 insert_table(request, response); 106 } 107 break; 108 109 case LOOK_UP : 110 111 ptr = find_match(request); 112 if (ptr != NULL) { 113 response->id_num = ptr->id_num; 114 response->addr = ptr->addr; 115 response->answer = SUCCESS; 116 } else { 117 response->answer = NOT_HERE; 118 } 119 break; 120 121 case DELETE : 122 123 response->answer = delete_invite(request->id_num); 124 break; 125 126 default : 127 128 response->answer = UNKNOWN_REQUEST; 129 break; 130 } 131 } 132 133 static void 134 do_announce(CTL_MSG *request, CTL_RESPONSE *response) 135 { 136 struct hostent *hp; 137 CTL_MSG *ptr; 138 int result; 139 140 /* 141 * See if the user is logged. 142 */ 143 result = find_user(request->r_name, request->r_tty); 144 if (result != SUCCESS) { 145 response->answer = result; 146 return; 147 } 148 149 hp = gethostbyaddr((const char *)&request->ctl_addr.sin_addr, 150 sizeof (struct in_addr), AF_INET); 151 if (hp == NULL) { 152 response->answer = MACHINE_UNKNOWN; 153 return; 154 } 155 156 ptr = find_request(request); 157 if (ptr == NULL) { 158 insert_table(request, response); 159 response->answer = announce(request, hp->h_name); 160 } else if (request->id_num > ptr->id_num) { 161 /* 162 * This is an explicit re-announce, so update the id_num 163 * field to avoid duplicates and re-announce the talk. 164 */ 165 ptr->id_num = response->id_num = new_id(); 166 response->answer = announce(request, hp->h_name); 167 } else { 168 /* a duplicated request, so ignore it */ 169 response->id_num = ptr->id_num; 170 response->answer = SUCCESS; 171 } 172 } 173 174 /* 175 * Search utmp for the local user. 176 */ 177 178 static int 179 find_user(char *name, char *tty) 180 { 181 struct utmpx *ubuf; 182 int tfd; 183 char dev[MAXPATHLEN]; 184 struct stat stbuf; 185 int problem = NOT_HERE; 186 187 setutxent(); /* reset the utmpx file */ 188 189 while (ubuf = getutxent()) { 190 if (ubuf->ut_type == USER_PROCESS && 191 strncmp(ubuf->ut_user, name, sizeof (ubuf->ut_user)) == 0) { 192 /* 193 * Check if this entry is really a tty. 194 */ 195 (void) snprintf(dev, sizeof (dev), "/dev/%.*s", 196 sizeof (ubuf->ut_line), ubuf->ut_line); 197 if ((tfd = open(dev, O_WRONLY|O_NOCTTY)) == -1) { 198 continue; 199 } 200 if (!isatty(tfd)) { 201 (void) close(tfd); 202 openlog("talk", 0, LOG_AUTH); 203 syslog(LOG_CRIT, "%.*s in utmp is not a tty\n", 204 sizeof (ubuf->ut_line), ubuf->ut_line); 205 closelog(); 206 continue; 207 } 208 if (*tty == '\0') { 209 /* 210 * No particular tty was requested. 211 */ 212 if (fstat(tfd, &stbuf) < 0 || 213 (stbuf.st_mode&020) == 0) { 214 (void) close(tfd); 215 problem = PERMISSION_DENIED; 216 continue; 217 } 218 (void) close(tfd); 219 (void) strlcpy(tty, ubuf->ut_line, TTY_SIZE); 220 endutxent(); /* close the utmpx file */ 221 return (SUCCESS); 222 } 223 (void) close(tfd); 224 if (strcmp(ubuf->ut_line, tty) == 0) { 225 endutxent(); /* close the utmpx file */ 226 return (SUCCESS); 227 } 228 } 229 } 230 231 endutxent(); /* close the utmpx file */ 232 return (problem); 233 } 234