1 /* $OpenBSD: rusers_proc.c,v 1.24 2013/11/13 15:24:21 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 1993 John Brezak 5 * 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. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/socket.h> 32 #include <sys/stat.h> 33 #include <sys/types.h> 34 #include <sys/time.h> 35 #include <paths.h> 36 #include <utmp.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <syslog.h> 40 #include <unistd.h> 41 #include <limits.h> 42 #include <string.h> 43 #include <rpc/rpc.h> 44 #include <rpcsvc/rusers.h> /* New version */ 45 #include <rpcsvc/rnusers.h> /* Old version */ 46 47 extern int utmp_fd; 48 49 typedef char ut_line_t[UT_LINESIZE+1]; 50 typedef char ut_name_t[UT_NAMESIZE+1]; 51 typedef char ut_host_t[UT_HOSTSIZE+1]; 52 53 struct rusers_utmp utmps[MAXUSERS]; 54 struct utmpidle *utmp_idlep[MAXUSERS]; 55 struct utmpidle utmp_idle[MAXUSERS]; 56 struct ru_utmp *ru_utmpp[MAXUSERS]; 57 struct ru_utmp ru_utmp[MAXUSERS]; 58 ut_line_t line[MAXUSERS]; 59 ut_name_t name[MAXUSERS]; 60 ut_host_t host[MAXUSERS]; 61 62 int *rusers_num_svc(void *, struct svc_req *); 63 struct utmpidlearr *rusersproc_names_2_svc(void *, struct svc_req *); 64 struct utmpidlearr *rusersproc_allnames_2_svc(void *, struct svc_req *); 65 struct utmparr *rusersproc_names_1_svc(void *, struct svc_req *); 66 struct utmparr *rusersproc_allnames_1_svc(void *, struct svc_req *); 67 void rusers_service(struct svc_req *, SVCXPRT *); 68 69 extern int from_inetd; 70 71 FILE *ufp; 72 73 static long 74 getidle(char *tty, size_t len) 75 { 76 char devname[PATH_MAX]; 77 struct stat st; 78 long idle; 79 time_t now; 80 81 snprintf(devname, sizeof devname, "%s/%.*s", _PATH_DEV, 82 len, tty); 83 if (stat(devname, &st) < 0) { 84 #ifdef DEBUG 85 printf("%s: %m\n", devname); 86 #endif 87 return (0); 88 } 89 time(&now); 90 #ifdef DEBUG 91 printf("%s: now=%lld atime=%lld\n", devname, (long long)now, 92 (long long)st.st_atime); 93 #endif 94 idle = now - st.st_atime; 95 idle = (idle + 30) / 60; /* secs->mins */ 96 if (idle < 0) 97 idle = 0; 98 99 return (idle); 100 } 101 102 int * 103 rusers_num_svc(void *arg, struct svc_req *rqstp) 104 { 105 static int num_users = 0; 106 struct utmp usr; 107 int fd; 108 109 fd = dup(utmp_fd); 110 if (fd == -1) { 111 syslog(LOG_ERR, "%m"); 112 return (0); 113 } 114 lseek(fd, (off_t)0, SEEK_SET); 115 ufp = fdopen(fd, "r"); 116 if (!ufp) { 117 close(fd); 118 syslog(LOG_ERR, "%m"); 119 return (0); 120 } 121 122 /* only entries with both name and line fields */ 123 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) 124 if (*usr.ut_name && *usr.ut_line) 125 num_users++; 126 127 fclose(ufp); 128 return (&num_users); 129 } 130 131 static utmp_array * 132 do_names_3(int all) 133 { 134 static utmp_array ut; 135 struct utmp usr; 136 int fd, nusers = 0; 137 138 bzero((char *)&ut, sizeof(ut)); 139 ut.utmp_array_val = &utmps[0]; 140 141 fd = dup(utmp_fd); 142 if (fd == -1) { 143 syslog(LOG_ERR, "%m"); 144 return (0); 145 } 146 lseek(fd, (off_t)0, SEEK_SET); 147 ufp = fdopen(fd, "r"); 148 if (!ufp) { 149 close(fd); 150 syslog(LOG_ERR, "%m"); 151 return (NULL); 152 } 153 154 /* only entries with both name and line fields */ 155 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 && 156 nusers < MAXUSERS) 157 if (*usr.ut_name && *usr.ut_line) { 158 utmps[nusers].ut_type = RUSERS_USER_PROCESS; 159 utmps[nusers].ut_time = usr.ut_time; 160 utmps[nusers].ut_idle = getidle(usr.ut_line, 161 sizeof usr.ut_line); 162 utmps[nusers].ut_line = line[nusers]; 163 memset(line[nusers], 0, sizeof(line[nusers])); 164 memcpy(line[nusers], usr.ut_line, UT_LINESIZE); 165 line[nusers][UT_LINESIZE] = '\0'; 166 utmps[nusers].ut_user = name[nusers]; 167 memset(name[nusers], 0, sizeof(name[nusers])); 168 memcpy(name[nusers], usr.ut_name, UT_NAMESIZE); 169 name[nusers][UT_NAMESIZE] = '\0'; 170 utmps[nusers].ut_host = host[nusers]; 171 memset(host[nusers], 0, sizeof(host[nusers])); 172 memcpy(host[nusers], usr.ut_host, UT_HOSTSIZE); 173 host[nusers][UT_HOSTSIZE] = '\0'; 174 nusers++; 175 } 176 ut.utmp_array_len = nusers; 177 178 fclose(ufp); 179 return (&ut); 180 } 181 182 utmp_array * 183 rusersproc_names_3_svc(void *arg, struct svc_req *rqstp) 184 { 185 return (do_names_3(0)); 186 } 187 188 utmp_array * 189 rusersproc_allnames_3_svc(void *arg, struct svc_req *rqstp) 190 { 191 return (do_names_3(1)); 192 } 193 194 static struct utmpidlearr * 195 do_names_2(int all) 196 { 197 static struct utmpidlearr ut; 198 struct utmp usr; 199 int fd, nusers = 0; 200 201 bzero((char *)&ut, sizeof(ut)); 202 ut.uia_arr = utmp_idlep; 203 ut.uia_cnt = 0; 204 205 fd = dup(utmp_fd); 206 if (fd == -1) { 207 syslog(LOG_ERR, "%m"); 208 return (0); 209 } 210 lseek(fd, (off_t)0, SEEK_SET); 211 ufp = fdopen(fd, "r"); 212 if (!ufp) { 213 close(fd); 214 syslog(LOG_ERR, "%m"); 215 return (NULL); 216 } 217 218 /* only entries with both name and line fields */ 219 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 && 220 nusers < MAXUSERS) 221 if (*usr.ut_name && *usr.ut_line) { 222 utmp_idlep[nusers] = &utmp_idle[nusers]; 223 utmp_idle[nusers].ui_utmp.ut_time = usr.ut_time; 224 utmp_idle[nusers].ui_idle = getidle(usr.ut_line, 225 sizeof usr.ut_line); 226 utmp_idle[nusers].ui_utmp.ut_line = line[nusers]; 227 memset(line[nusers], 0, sizeof(line[nusers])); 228 memcpy(line[nusers], usr.ut_line, UT_LINESIZE); 229 line[nusers][UT_LINESIZE] = '\0'; 230 utmp_idle[nusers].ui_utmp.ut_name = name[nusers]; 231 memset(name[nusers], 0, sizeof(name[nusers])); 232 memcpy(name[nusers], usr.ut_name, UT_NAMESIZE); 233 name[nusers][UT_NAMESIZE] = '\0'; 234 utmp_idle[nusers].ui_utmp.ut_host = host[nusers]; 235 memset(host[nusers], 0, sizeof(host[nusers])); 236 memcpy(host[nusers], usr.ut_host, UT_HOSTSIZE); 237 host[nusers][UT_HOSTSIZE] = '\0'; 238 nusers++; 239 } 240 241 ut.uia_cnt = nusers; 242 fclose(ufp); 243 return (&ut); 244 } 245 246 struct utmpidlearr * 247 rusersproc_names_2_svc(void *arg, struct svc_req *rqstp) 248 { 249 return (do_names_2(0)); 250 } 251 252 struct utmpidlearr * 253 rusersproc_allnames_2_svc(void *arg, struct svc_req *rqstp) 254 { 255 return (do_names_2(1)); 256 } 257 258 static struct utmparr * 259 do_names_1(int all) 260 { 261 static struct utmparr ut; 262 struct utmp usr; 263 int fd, nusers = 0; 264 265 bzero((char *)&ut, sizeof(ut)); 266 ut.uta_arr = ru_utmpp; 267 ut.uta_cnt = 0; 268 269 fd = dup(utmp_fd); 270 if (fd == -1) { 271 syslog(LOG_ERR, "%m"); 272 return (0); 273 } 274 lseek(fd, (off_t)0, SEEK_SET); 275 ufp = fdopen(fd, "r"); 276 if (!ufp) { 277 close(fd); 278 syslog(LOG_ERR, "%m"); 279 return (NULL); 280 } 281 282 /* only entries with both name and line fields */ 283 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 && 284 nusers < MAXUSERS) 285 if (*usr.ut_name && *usr.ut_line) { 286 ru_utmpp[nusers] = &ru_utmp[nusers]; 287 ru_utmp[nusers].ut_time = usr.ut_time; 288 ru_utmp[nusers].ut_line = line[nusers]; 289 memcpy(line[nusers], usr.ut_line, UT_LINESIZE); 290 line[nusers][UT_LINESIZE] = '\0'; 291 ru_utmp[nusers].ut_name = name[nusers]; 292 memcpy(name[nusers], usr.ut_name, UT_NAMESIZE); 293 name[nusers][UT_NAMESIZE] = '\0'; 294 ru_utmp[nusers].ut_host = host[nusers]; 295 memcpy(host[nusers], usr.ut_host, UT_HOSTSIZE); 296 host[nusers][UT_HOSTSIZE] = '\0'; 297 nusers++; 298 } 299 300 ut.uta_cnt = nusers; 301 fclose(ufp); 302 return (&ut); 303 } 304 305 struct utmparr * 306 rusersproc_names_1_svc(void *arg, struct svc_req *rqstp) 307 { 308 return (do_names_1(0)); 309 } 310 311 struct utmparr * 312 rusersproc_allnames_1_svc(void *arg, struct svc_req *rqstp) 313 { 314 return (do_names_1(1)); 315 } 316 317 void 318 rusers_service(struct svc_req *rqstp, SVCXPRT *transp) 319 { 320 char *(*local)(void *, struct svc_req *); 321 xdrproc_t xdr_argument, xdr_result; 322 union { 323 int fill; 324 } argument; 325 char *result; 326 327 switch (rqstp->rq_proc) { 328 case NULLPROC: 329 (void)svc_sendreply(transp, xdr_void, (char *)NULL); 330 goto leave; 331 332 case RUSERSPROC_NUM: 333 xdr_argument = (xdrproc_t)xdr_void; 334 xdr_result = (xdrproc_t)xdr_int; 335 switch (rqstp->rq_vers) { 336 case RUSERSVERS_3: 337 case RUSERSVERS_IDLE: 338 case RUSERSVERS_ORIG: 339 local = (char *(*)(void *, struct svc_req *)) 340 rusers_num_svc; 341 break; 342 default: 343 svcerr_progvers(transp, RUSERSVERS_IDLE, RUSERSVERS_3); 344 goto leave; 345 /*NOTREACHED*/ 346 } 347 break; 348 349 case RUSERSPROC_NAMES: 350 xdr_argument = (xdrproc_t)xdr_void; 351 xdr_result = (xdrproc_t)xdr_utmp_array; 352 switch (rqstp->rq_vers) { 353 case RUSERSVERS_3: 354 local = (char *(*)(void *, struct svc_req *)) 355 rusersproc_names_3_svc; 356 break; 357 358 case RUSERSVERS_IDLE: 359 xdr_result = (xdrproc_t)xdr_utmpidlearr; 360 local = (char *(*)(void *, struct svc_req *)) 361 rusersproc_names_2_svc; 362 break; 363 364 case RUSERSVERS_ORIG: 365 xdr_result = (xdrproc_t)xdr_utmpidlearr; 366 local = (char *(*)(void *, struct svc_req *)) 367 rusersproc_names_1_svc; 368 break; 369 370 default: 371 svcerr_progvers(transp, RUSERSVERS_IDLE, RUSERSVERS_3); 372 goto leave; 373 /*NOTREACHED*/ 374 } 375 break; 376 377 case RUSERSPROC_ALLNAMES: 378 xdr_argument = (xdrproc_t)xdr_void; 379 xdr_result = (xdrproc_t)xdr_utmp_array; 380 switch (rqstp->rq_vers) { 381 case RUSERSVERS_3: 382 local = (char *(*)(void *, struct svc_req *)) 383 rusersproc_allnames_3_svc; 384 break; 385 386 case RUSERSVERS_IDLE: 387 xdr_result = (xdrproc_t)xdr_utmpidlearr; 388 local = (char *(*)(void *, struct svc_req *)) 389 rusersproc_allnames_2_svc; 390 break; 391 392 case RUSERSVERS_ORIG: 393 xdr_result = (xdrproc_t)xdr_utmpidlearr; 394 local = (char *(*)(void *, struct svc_req *)) 395 rusersproc_allnames_1_svc; 396 break; 397 398 default: 399 svcerr_progvers(transp, RUSERSVERS_IDLE, RUSERSVERS_3); 400 goto leave; 401 /*NOTREACHED*/ 402 } 403 break; 404 405 default: 406 svcerr_noproc(transp); 407 goto leave; 408 } 409 bzero((char *)&argument, sizeof(argument)); 410 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { 411 svcerr_decode(transp); 412 goto leave; 413 } 414 result = (*local)(&argument, rqstp); 415 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) 416 svcerr_systemerr(transp); 417 418 if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { 419 syslog(LOG_ERR, "unable to free arguments"); 420 exit(1); 421 } 422 leave: 423 if (from_inetd) 424 exit(0); 425 } 426