GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: libexec/rpc.rusersd/rusers_proc.c Lines: 0 170 0.0 %
Date: 2017-11-07 Branches: 0 67 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rusers_proc.c,v 1.26 2017/04/27 21:28:00 millert 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, int 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, 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(&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(&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, 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(&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(&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, 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(&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(&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, 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(&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
}