1 /* $NetBSD: rusers_proc.c,v 1.29 2018/03/01 06:24:12 snj 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/cdefs.h> 32 #ifndef lint 33 __RCSID("$NetBSD: rusers_proc.c,v 1.29 2018/03/01 06:24:12 snj Exp $"); 34 #endif /* not lint */ 35 36 #include <sys/types.h> 37 #include <sys/time.h> 38 #include <sys/socket.h> 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 42 #include <stdio.h> 43 #include <string.h> 44 #include <stdlib.h> 45 #include <time.h> 46 #include <unistd.h> 47 #include <signal.h> 48 #include <syslog.h> 49 #include <utmp.h> 50 51 #include <rpc/rpc.h> 52 53 #include "rusers_proc.h" 54 #include "utmpentry.h" 55 56 #include <rpcsvc/rusers.h> /* New version */ 57 static size_t maxusers3 = 0; 58 static struct rusers_utmp *utmps; 59 60 #include <rpcsvc/rnusers.h> /* Old version */ 61 static size_t maxusers2 = 0; 62 static struct utmpidle **utmp_idlep; 63 static struct utmpidle *utmp_idle; 64 65 typedef char *(*rusersproc)(void *, struct svc_req *); 66 67 #ifndef _PATH_DEV 68 #define _PATH_DEV "/dev" 69 #endif 70 71 72 extern int from_inetd; 73 74 static int getarrays2(int); 75 static int getarrays3(int); 76 static int getidle(const char *, char *); 77 static int *rusers_num_svc(void *, struct svc_req *); 78 static utmp_array *do_names_3(int); 79 static struct utmpidlearr *do_names_2(int); 80 81 /* XXX */ 82 struct utmpidlearr *rusersproc_names_2_svc(void *, struct svc_req *); 83 struct utmpidlearr *rusersproc_allnames_2_svc(void *, struct svc_req *); 84 85 86 static int 87 getarrays2(int ne) 88 { 89 struct utmpidle **nutmp_idlep; 90 struct utmpidle *nutmp_idle; 91 92 /* Limit to MAXUSERS for version 2 */ 93 if (ne > MAXUSERS) 94 ne = MAXUSERS; 95 96 if (maxusers2 == 0) { 97 nutmp_idlep = malloc(sizeof(*nutmp_idlep) * ne); 98 nutmp_idle = malloc(sizeof(*nutmp_idle) * ne); 99 } else { 100 nutmp_idlep = realloc(utmp_idlep, sizeof(*nutmp_idlep) * ne); 101 nutmp_idle = realloc(utmp_idle, sizeof(*nutmp_idle) * ne); 102 } 103 104 if (nutmp_idlep == NULL || nutmp_idle == NULL) { 105 syslog(LOG_WARNING, "Cannot allocate data for %u users (%m)", 106 ne); 107 free(nutmp_idlep); 108 free(nutmp_idle); 109 return 0; 110 } 111 112 utmp_idlep = nutmp_idlep; 113 utmp_idle = nutmp_idle; 114 return maxusers2 = ne; 115 } 116 117 static int 118 getarrays3(int ne) 119 { 120 struct rusers_utmp *nutmps; 121 122 if (maxusers3 == 0) { 123 nutmps = malloc(sizeof(*nutmps) * ne); 124 } else { 125 nutmps = realloc(utmps, sizeof(*nutmps) * ne); 126 } 127 128 if (nutmps == NULL) { 129 syslog(LOG_WARNING, "Cannot allocate data for %u users (%m)", 130 ne); 131 return 0; 132 } 133 134 utmps = nutmps; 135 return maxusers3 = ne; 136 } 137 138 static int 139 /*ARGUSED*/ 140 getidle(const char *tty, char *display) 141 { 142 struct stat st; 143 char dev_name[PATH_MAX]; 144 time_t now; 145 long idle; 146 147 idle = 0; 148 if (*tty == 'X') { 149 long kbd_idle, mouse_idle; 150 #if !defined(i386) 151 kbd_idle = getidle("kbd", NULL); 152 #else 153 /* 154 * XXX Icky i386 console hack. 155 */ 156 kbd_idle = getidle("vga", NULL); 157 #endif 158 mouse_idle = getidle("mouse", NULL); 159 idle = (kbd_idle < mouse_idle) ? kbd_idle : mouse_idle; 160 } else { 161 snprintf(dev_name, sizeof dev_name, "%s/%s", _PATH_DEV, tty); 162 if (stat(dev_name, &st) == -1) { 163 syslog(LOG_WARNING, "Cannot stat %s (%m)", dev_name); 164 return 0; 165 } 166 (void)time(&now); 167 #ifdef DEBUG 168 printf("%s: now=%ld atime=%ld\n", dev_name, 169 (long)now, (long)st.st_atime); 170 #endif 171 idle = now - st.st_atime; 172 idle = (idle + 30) / 60; /* secs->mins */ 173 } 174 if (idle < 0) 175 idle = 0; 176 177 return idle; 178 } 179 180 static struct utmpentry *ue = NULL; 181 static int nusers = 0; 182 183 static int * 184 /*ARGSUSED*/ 185 rusers_num_svc(void *arg, struct svc_req *rqstp) 186 { 187 nusers = getutentries(NULL, &ue); 188 return &nusers; 189 } 190 191 static utmp_array * 192 do_names_3(int all) 193 { 194 static utmp_array ut; 195 struct utmpentry *e; 196 size_t nu; 197 int idle; 198 199 nusers = getutentries(NULL, &ue); 200 nusers = getarrays3(nusers); 201 202 (void)memset(&ut, 0, sizeof(ut)); 203 ut.utmp_array_val = utmps; 204 205 for (nu = 0, e = ue; e != NULL && nu < (size_t)nusers; e = e->next) { 206 if ((idle = getidle(e->line, e->host)) > 0 && !all) 207 continue; 208 utmps[nu].ut_type = RUSERS_USER_PROCESS; 209 utmps[nu].ut_time = e->tv.tv_sec; 210 utmps[nu].ut_idle = idle; 211 utmps[nu].ut_line = e->line; 212 utmps[nu].ut_user = e->name; 213 utmps[nu].ut_host = e->host; 214 nu++; 215 } 216 217 ut.utmp_array_len = nu; 218 219 return &ut; 220 } 221 222 utmp_array * 223 /*ARGSUSED*/ 224 rusersproc_names_3_svc(void *arg, struct svc_req *rqstp) 225 { 226 227 return do_names_3(0); 228 } 229 230 utmp_array * 231 /*ARGSUSED*/ 232 rusersproc_allnames_3_svc(void *arg, struct svc_req *rqstp) 233 { 234 235 return do_names_3(1); 236 } 237 238 static struct utmpidlearr * 239 do_names_2(int all) 240 { 241 static struct utmpidlearr ut; 242 struct utmpentry *e; 243 size_t nu; 244 int idle; 245 246 nusers = getutentries(NULL, &ue); 247 nusers = getarrays2(nusers); 248 (void)memset(&ut, 0, sizeof(ut)); 249 ut.uia_arr = utmp_idlep; 250 ut.uia_cnt = 0; 251 252 for (nu = 0, e = ue; e != NULL && nu < (size_t)nusers; e = e->next) { 253 if ((idle = getidle(e->line, e->host)) > 0 && !all) 254 continue; 255 utmp_idlep[nu] = &utmp_idle[nu]; 256 utmp_idle[nu].ui_utmp.ut_time = e->tv.tv_sec; 257 utmp_idle[nu].ui_idle = idle; 258 (void)strncpy(utmp_idle[nu].ui_utmp.ut_line, e->line, 259 sizeof(utmp_idle[nu].ui_utmp.ut_line)); 260 (void)strncpy(utmp_idle[nu].ui_utmp.ut_name, e->name, 261 sizeof(utmp_idle[nu].ui_utmp.ut_name)); 262 (void)strncpy(utmp_idle[nu].ui_utmp.ut_host, e->host, 263 sizeof(utmp_idle[nu].ui_utmp.ut_host)); 264 nu++; 265 } 266 267 ut.uia_cnt = nu; 268 return &ut; 269 } 270 271 struct utmpidlearr * 272 /*ARGSUSED*/ 273 rusersproc_names_2_svc(void *arg, struct svc_req *rqstp) 274 { 275 return do_names_2(0); 276 } 277 278 struct utmpidlearr * 279 /*ARGSUSED*/ 280 rusersproc_allnames_2_svc(void *arg, struct svc_req *rqstp) 281 { 282 return do_names_2(1); 283 } 284 285 void 286 rusers_service(struct svc_req *rqstp, SVCXPRT *transp) 287 { 288 union { 289 int fill; 290 } argument; 291 char *result; 292 xdrproc_t xdr_argument, xdr_result; 293 rusersproc local; 294 295 switch (rqstp->rq_proc) { 296 case NULLPROC: 297 (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 298 goto leave; 299 300 case RUSERSPROC_NUM: 301 xdr_argument = (xdrproc_t)xdr_void; 302 xdr_result = (xdrproc_t)xdr_int; 303 switch (rqstp->rq_vers) { 304 case RUSERSVERS_3: 305 case RUSERSVERS_IDLE: 306 local = (char *(*)(void *, struct svc_req *)) 307 rusers_num_svc; 308 break; 309 default: 310 svcerr_progvers(transp, RUSERSVERS_IDLE, RUSERSVERS_3); 311 goto leave; 312 /*NOTREACHED*/ 313 } 314 break; 315 316 case RUSERSPROC_NAMES: 317 xdr_argument = (xdrproc_t)xdr_void; 318 xdr_result = (xdrproc_t)xdr_utmp_array; 319 switch (rqstp->rq_vers) { 320 case RUSERSVERS_3: 321 local = (rusersproc)rusersproc_names_3_svc; 322 break; 323 324 case RUSERSVERS_IDLE: 325 xdr_result = (xdrproc_t)xdr_utmpidlearr; 326 local = (rusersproc)rusersproc_names_2_svc; 327 break; 328 329 default: 330 svcerr_progvers(transp, RUSERSVERS_IDLE, RUSERSVERS_3); 331 goto leave; 332 /*NOTREACHED*/ 333 } 334 break; 335 336 case RUSERSPROC_ALLNAMES: 337 xdr_argument = (xdrproc_t)xdr_void; 338 xdr_result = (xdrproc_t)xdr_utmp_array; 339 switch (rqstp->rq_vers) { 340 case RUSERSVERS_3: 341 local = (rusersproc)rusersproc_allnames_3_svc; 342 break; 343 344 case RUSERSVERS_IDLE: 345 xdr_result = (xdrproc_t)xdr_utmpidlearr; 346 local = (rusersproc)rusersproc_allnames_2_svc; 347 break; 348 349 default: 350 svcerr_progvers(transp, RUSERSVERS_IDLE, RUSERSVERS_3); 351 goto leave; 352 /*NOTREACHED*/ 353 } 354 break; 355 356 default: 357 svcerr_noproc(transp); 358 goto leave; 359 } 360 (void)memset(&argument, 0, sizeof(argument)); 361 if (!svc_getargs(transp, xdr_argument, (caddr_t)(void *)&argument)) { 362 svcerr_decode(transp); 363 goto leave; 364 } 365 result = (*local)(&argument, rqstp); 366 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 367 svcerr_systemerr(transp); 368 } 369 if (!svc_freeargs(transp, xdr_argument, (caddr_t)(void *)&argument)) { 370 syslog(LOG_ERR, "unable to free arguments"); 371 exit(1); 372 } 373 leave: 374 if (from_inetd) 375 exit(0); 376 } 377