GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ypserv/ypserv/ypserv.c Lines: 0 204 0.0 %
Date: 2017-11-13 Branches: 0 124 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ypserv.c,v 1.44 2015/11/17 18:21:48 tedu Exp $ */
2
3
/*
4
 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
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
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <sys/ioctl.h>
32
#include <netinet/in.h>
33
#include <rpcsvc/yp.h>
34
#include "ypv1.h"
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <netdb.h>
39
#include <signal.h>
40
#include <errno.h>
41
#include <util.h>
42
#include <unistd.h>
43
#include <fcntl.h>
44
#include <rpc/pmap_clnt.h>
45
#include <ndbm.h>
46
#include <syslog.h>
47
#include "acl.h"
48
#include "yplog.h"
49
#include "ypdef.h"
50
#include "ypserv.h"
51
#include <sys/wait.h>
52
53
void ypdb_init(void);
54
55
#ifdef DEBUG
56
#define RPC_SVC_FG
57
#endif
58
59
#define _RPCSVC_CLOSEDOWN 120
60
static int _rpcpmstart;		/* Started by a port monitor ? */
61
static int _rpcfdtype;		/* Whether Stream or Datagram ? */
62
static int _rpcsvcdirty;	/* Still serving ? */
63
64
int	usedns = FALSE;
65
char   *aclfile = NULL;
66
67
void	sig_child(int);
68
void	sig_hup(int);
69
volatile sig_atomic_t wantsighup;
70
71
static void
72
_msgout(char *msg)
73
{
74
#ifdef RPC_SVC_FG
75
	if (_rpcpmstart)
76
		syslog(LOG_ERR, "%s", msg);
77
	else
78
		(void) fprintf(stderr, "%s\n", msg);
79
#else
80
	syslog(LOG_ERR, "%s", msg);
81
#endif
82
}
83
84
/* ARGSUSED */
85
static void
86
closedown(int sig)
87
{
88
	int save_errno = errno;
89
90
	if (_rpcsvcdirty == 0) {
91
		int i, openfd;
92
93
		if (_rpcfdtype == SOCK_DGRAM)
94
			exit(0);
95
		for (i = 0, openfd = 0; i < svc_max_pollfd && openfd < 2; i++)
96
			if (svc_pollfd[i].fd != -1)
97
				openfd++;
98
		if (openfd <= (_rpcpmstart ? 0 : 1))
99
			_exit(0);
100
	}
101
	(void) alarm(_RPCSVC_CLOSEDOWN);
102
	errno = save_errno;
103
}
104
105
static void
106
ypprog_1(struct svc_req *rqstp, SVCXPRT *transp)
107
{
108
	union {
109
		domainname ypoldproc_domain_1_arg;
110
		domainname ypoldproc_domain_nonack_1_arg;
111
		yprequest ypoldproc_match_1_arg;
112
		yprequest ypoldproc_first_1_arg;
113
		yprequest ypoldproc_next_1_arg;
114
		yprequest ypoldproc_poll_1_arg;
115
		yprequest ypoldproc_push_1_arg;
116
		yprequest ypoldproc_pull_1_arg;
117
		yprequest ypoldproc_get_1_arg;
118
	} argument;
119
	char *result;
120
	xdrproc_t xdr_argument, xdr_result;
121
	char *(*local)(char *, struct svc_req *);
122
123
	_rpcsvcdirty = 1;
124
	switch (rqstp->rq_proc) {
125
	case YPOLDPROC_NULL:
126
		xdr_argument = (xdrproc_t) xdr_void;
127
		xdr_result = (xdrproc_t) xdr_void;
128
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_null_1_svc;
129
		break;
130
131
	case YPOLDPROC_DOMAIN:
132
		xdr_argument = (xdrproc_t) xdr_domainname;
133
		xdr_result = (xdrproc_t) xdr_bool;
134
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_domain_1_svc;
135
		break;
136
137
	case YPOLDPROC_DOMAIN_NONACK:
138
		xdr_argument = (xdrproc_t) xdr_domainname;
139
		xdr_result = (xdrproc_t) xdr_bool;
140
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_domain_nonack_1_svc;
141
		break;
142
143
	case YPOLDPROC_MATCH:
144
		xdr_argument = (xdrproc_t) xdr_yprequest;
145
		xdr_result = (xdrproc_t) xdr_ypresponse;
146
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_match_1_svc;
147
		break;
148
149
	case YPOLDPROC_FIRST:
150
		xdr_argument = (xdrproc_t) xdr_yprequest;
151
		xdr_result = (xdrproc_t) xdr_ypresponse;
152
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_first_1_svc;
153
		break;
154
155
	case YPOLDPROC_NEXT:
156
		xdr_argument = (xdrproc_t) xdr_yprequest;
157
		xdr_result = (xdrproc_t) xdr_ypresponse;
158
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_next_1_svc;
159
		break;
160
161
	case YPOLDPROC_POLL:
162
		xdr_argument = (xdrproc_t) xdr_yprequest;
163
		xdr_result = (xdrproc_t) xdr_ypresponse;
164
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_poll_1_svc;
165
		break;
166
167
	case YPOLDPROC_PUSH:
168
		xdr_argument = (xdrproc_t) xdr_yprequest;
169
		xdr_result = (xdrproc_t) xdr_void;
170
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_push_1_svc;
171
		break;
172
173
	case YPOLDPROC_PULL:
174
		xdr_argument = (xdrproc_t) xdr_yprequest;
175
		xdr_result = (xdrproc_t) xdr_void;
176
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_pull_1_svc;
177
		break;
178
179
	case YPOLDPROC_GET:
180
		xdr_argument = (xdrproc_t) xdr_yprequest;
181
		xdr_result = (xdrproc_t) xdr_void;
182
		local = (char *(*)(char *, struct svc_req *)) ypoldproc_get_1_svc;
183
		break;
184
185
	default:
186
		svcerr_noproc(transp);
187
		_rpcsvcdirty = 0;
188
		return;
189
	}
190
	(void) memset(&argument, 0, sizeof(argument));
191
	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
192
		svcerr_decode(transp);
193
		_rpcsvcdirty = 0;
194
		return;
195
	}
196
	result = (*local)((char *)&argument, rqstp);
197
	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
198
		svcerr_systemerr(transp);
199
	}
200
	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
201
		_msgout("unable to free arguments");
202
		exit(1);
203
	}
204
	_rpcsvcdirty = 0;
205
}
206
207
static void
208
ypprog_2(struct svc_req *rqstp, SVCXPRT *transp)
209
{
210
	union {
211
		domainname ypproc_domain_2_arg;
212
		domainname ypproc_domain_nonack_2_arg;
213
		ypreq_key ypproc_match_2_arg;
214
		ypreq_nokey ypproc_first_2_arg;
215
		ypreq_key ypproc_next_2_arg;
216
		ypreq_xfr ypproc_xfr_2_arg;
217
		ypreq_nokey ypproc_all_2_arg;
218
		ypreq_nokey ypproc_master_2_arg;
219
		ypreq_nokey ypproc_order_2_arg;
220
		domainname ypproc_maplist_2_arg;
221
	} argument;
222
	char *result;
223
	xdrproc_t xdr_argument, xdr_result;
224
	char *(*local)(char *, struct svc_req *);
225
226
	_rpcsvcdirty = 1;
227
	switch (rqstp->rq_proc) {
228
	case YPPROC_NULL:
229
		xdr_argument = (xdrproc_t) xdr_void;
230
		xdr_result = (xdrproc_t) xdr_void;
231
		local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc;
232
		break;
233
234
	case YPPROC_DOMAIN:
235
		xdr_argument = (xdrproc_t) xdr_domainname;
236
		xdr_result = (xdrproc_t) xdr_bool;
237
		local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc;
238
		break;
239
240
	case YPPROC_DOMAIN_NONACK:
241
		xdr_argument = (xdrproc_t) xdr_domainname;
242
		xdr_result = (xdrproc_t) xdr_bool;
243
		local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc;
244
		break;
245
246
	case YPPROC_MATCH:
247
		xdr_argument = (xdrproc_t) xdr_ypreq_key;
248
		xdr_result = (xdrproc_t) xdr_ypresp_val;
249
		local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc;
250
		break;
251
252
	case YPPROC_FIRST:
253
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
254
		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
255
		local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc;
256
		break;
257
258
	case YPPROC_NEXT:
259
		xdr_argument = (xdrproc_t) xdr_ypreq_key;
260
		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
261
		local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc;
262
		break;
263
264
	case YPPROC_XFR:
265
		xdr_argument = (xdrproc_t) xdr_ypreq_xfr;
266
		xdr_result = (xdrproc_t) xdr_ypresp_xfr;
267
		local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc;
268
		break;
269
270
	case YPPROC_CLEAR:
271
		xdr_argument = (xdrproc_t) xdr_void;
272
		xdr_result = (xdrproc_t) xdr_void;
273
		local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc;
274
		break;
275
276
	case YPPROC_ALL:
277
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
278
		xdr_result = (xdrproc_t) xdr_ypresp_all;
279
		local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc;
280
		break;
281
282
	case YPPROC_MASTER:
283
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
284
		xdr_result = (xdrproc_t) xdr_ypresp_master;
285
		local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc;
286
		break;
287
288
	case YPPROC_ORDER:
289
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
290
		xdr_result = (xdrproc_t) xdr_ypresp_order;
291
		local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc;
292
		break;
293
294
	case YPPROC_MAPLIST:
295
		xdr_argument = (xdrproc_t) xdr_domainname;
296
		xdr_result = (xdrproc_t) xdr_ypresp_maplist;
297
		local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc;
298
		break;
299
300
	default:
301
		svcerr_noproc(transp);
302
		_rpcsvcdirty = 0;
303
		return;
304
	}
305
	(void) memset(&argument, 0, sizeof(argument));
306
	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
307
		svcerr_decode(transp);
308
		_rpcsvcdirty = 0;
309
		return;
310
	}
311
	result = (*local)((char *)&argument, rqstp);
312
	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
313
		svcerr_systemerr(transp);
314
	}
315
	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
316
		_msgout("unable to free arguments");
317
		exit(1);
318
	}
319
	_rpcsvcdirty = 0;
320
}
321
322
static void
323
hup(void)
324
{
325
	/* Handle the log. */
326
	ypcloselog();
327
	ypopenlog();
328
329
	acl_reset();
330
	if (aclfile != NULL) {
331
		yplog("sig_hup: reread %s", aclfile);
332
		(void)acl_init(aclfile);
333
	} else {
334
		yplog("sig_hup: reread %s", YP_SECURENET_FILE);
335
		(void)acl_securenet(YP_SECURENET_FILE);
336
	}
337
338
	ypdb_close_all();
339
}
340
341
static void
342
my_svc_run(void)
343
{
344
	struct pollfd *pfd = NULL, *newp;
345
	int nready, saved_max_pollfd = 0;
346
347
	for (;;) {
348
		if (wantsighup) {
349
			wantsighup = 0;
350
			hup();
351
		}
352
		if (svc_max_pollfd > saved_max_pollfd) {
353
			newp = reallocarray(pfd, svc_max_pollfd, sizeof(*pfd));
354
			if (newp == NULL) {
355
				free(pfd);
356
				perror("svc_run: - realloc failed");
357
				return;
358
			}
359
			pfd = newp;
360
			saved_max_pollfd = svc_max_pollfd;
361
		}
362
		memcpy(pfd, svc_pollfd, sizeof(*pfd) * svc_max_pollfd);
363
364
		nready = poll(pfd, svc_max_pollfd, INFTIM);
365
		switch (nready) {
366
		case -1:
367
			if (errno == EINTR)
368
				continue;
369
			perror("svc_run: - poll failed");
370
			free(pfd);
371
			return;
372
		case 0:
373
			continue;
374
		default:
375
			svc_getreq_poll(pfd, nready);
376
		}
377
	}
378
}
379
380
static void
381
usage(void)
382
{
383
	(void)fprintf(stderr, "usage: ypserv [-1dx] [-a aclfile]\n");
384
	exit(1);
385
}
386
387
int
388
main(int argc, char *argv[])
389
{
390
	int xflag = 0, allowv1 = 0, ch, sock, proto;
391
	struct sockaddr_in saddr;
392
	socklen_t asize = sizeof(saddr);
393
	extern char *optarg;
394
	SVCXPRT *transp = NULL;
395
396
	while ((ch = getopt(argc, argv, "1a:dx")) != -1)
397
		switch (ch) {
398
		case '1':
399
			allowv1 = TRUE;
400
			break;
401
		case 'a':
402
			aclfile = optarg;
403
			break;
404
		case 'd':
405
			usedns = TRUE;
406
			break;
407
		case 'x':
408
			xflag = TRUE;
409
			break;
410
		default:
411
			usage();
412
			break;
413
		}
414
415
	if (geteuid() != 0) {
416
		(void)fprintf(stderr, "ypserv: must be root to run.\n");
417
		exit(1);
418
	}
419
420
	if (aclfile != NULL)
421
		(void)acl_init(aclfile);
422
	else
423
		(void)acl_securenet(YP_SECURENET_FILE);
424
425
	if (xflag)
426
		exit(1);
427
428
	if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
429
		socklen_t ssize = sizeof(int);
430
431
		if (saddr.sin_family != AF_INET)
432
			exit(1);
433
		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
434
		    &_rpcfdtype, &ssize) == -1)
435
			exit(1);
436
		sock = 0;
437
		_rpcpmstart = 1;
438
		proto = 0;
439
		openlog("ypserv", LOG_PID, LOG_DAEMON);
440
	} else {
441
#ifndef RPC_SVC_FG
442
		int i;
443
		pid_t pid;
444
445
		pid = fork();
446
		if (pid < 0) {
447
			perror("cannot fork");
448
			exit(1);
449
		}
450
		if (pid)
451
			exit(0);
452
		closefrom(0);
453
		i = open("/dev/console", O_RDWR);
454
		(void) dup2(i, 1);
455
		(void) dup2(i, 2);
456
		i = open("/dev/tty", O_RDWR);
457
		if (i >= 0) {
458
			(void) ioctl(i, TIOCNOTTY, NULL);
459
			(void) close(i);
460
		}
461
		openlog("ypserv", LOG_PID, LOG_DAEMON);
462
#endif
463
		sock = RPC_ANYSOCK;
464
		(void) pmap_unset(YPPROG, YPVERS);
465
		(void) pmap_unset(YPPROG, YPOLDVERS);
466
	}
467
468
	ypopenlog();	/* open log file */
469
	ypdb_init();	/* init db stuff */
470
471
	chdir("/");
472
473
	(void)signal(SIGCHLD, sig_child);
474
	(void)signal(SIGHUP, sig_hup);
475
476
	if (_rpcfdtype == 0 || _rpcfdtype == SOCK_DGRAM) {
477
		transp = svcudp_create(sock);
478
		if (transp == NULL) {
479
			_msgout("cannot create udp service.");
480
			exit(1);
481
		}
482
		if (transp->xp_port >= IPPORT_RESERVED) {
483
			_msgout("cannot allocate udp privileged port.");
484
			exit(1);
485
		}
486
		if (!_rpcpmstart)
487
			proto = IPPROTO_UDP;
488
		if (allowv1) {
489
			if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
490
				_msgout("unable to register (YPPROG, YPOLDVERS, udp).");
491
				exit(1);
492
			}
493
		}
494
		if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
495
			_msgout("unable to register (YPPROG, YPVERS, udp).");
496
			exit(1);
497
		}
498
	}
499
500
	if (_rpcfdtype == 0 || _rpcfdtype == SOCK_STREAM) {
501
		if (_rpcpmstart)
502
			transp = svcfd_create(sock, 0, 0);
503
		else
504
			transp = svctcp_create(sock, 0, 0);
505
		if (transp == NULL) {
506
			_msgout("cannot create tcp service.");
507
			exit(1);
508
		}
509
		if (transp->xp_port >= IPPORT_RESERVED) {
510
			_msgout("cannot allocate tcp privileged port.");
511
			exit(1);
512
		}
513
		if (!_rpcpmstart)
514
			proto = IPPROTO_TCP;
515
		if (allowv1) {
516
			if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
517
				_msgout("unable to register (YPPROG, YPOLDVERS, tcp).");
518
				exit(1);
519
			}
520
		}
521
		if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
522
			_msgout("unable to register (YPPROG, YPVERS, tcp).");
523
			exit(1);
524
		}
525
	}
526
527
	if (transp == NULL) {
528
		_msgout("could not create a handle");
529
		exit(1);
530
	}
531
	if (_rpcpmstart) {
532
		(void) signal(SIGALRM, closedown);
533
		(void) alarm(_RPCSVC_CLOSEDOWN);
534
	}
535
	my_svc_run();
536
	_msgout("svc_run returned");
537
	exit(1);
538
	/* NOTREACHED */
539
}
540
541
/* ARGSUSED */
542
void
543
sig_child(int signo)
544
{
545
	int save_errno = errno;
546
547
	while (wait3(NULL, WNOHANG, NULL) > 0)
548
		;
549
	errno = save_errno;
550
}
551
552
/* ARGSUSED */
553
void
554
sig_hup(int signo)
555
{
556
	wantsighup = 1;
557
}