xref: /netbsd/usr.sbin/ypserv/ypserv/ypserv_db.c (revision 904e7e1c)
1 /*	$NetBSD: ypserv_db.c,v 1.23 2020/10/13 13:56:34 kamil Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
5  * Copyright (c) 1996 Charles D. Cranor
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 #ifndef lint
32 __RCSID("$NetBSD: ypserv_db.c,v 1.23 2020/10/13 13:56:34 kamil Exp $");
33 #endif
34 
35 /*
36  * major revision/cleanup of Mats' version done by
37  * Chuck Cranor <chuck@netbsd> Jan 1996.
38  */
39 
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/queue.h>
43 #include <sys/stat.h>
44 #include <sys/param.h>
45 
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <arpa/nameser.h>
49 
50 #include <errno.h>
51 #include <string.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <netdb.h>
55 #include <resolv.h>
56 #include <syslog.h>
57 
58 #include <rpc/rpc.h>
59 #include <rpcsvc/yp_prot.h>
60 #include <rpcsvc/ypclnt.h>
61 
62 #include "ypdb.h"
63 #include "ypdef.h"
64 #include "ypserv.h"
65 
66 LIST_HEAD(domainlist, opt_domain);	/* LIST of domains */
67 LIST_HEAD(maplist, opt_map);		/* LIST of maps (in a domain) */
68 TAILQ_HEAD(mapq, opt_map);		/* TAILQ of maps (LRU) */
69 
70 struct opt_map {
71 	char	*map;			/* map name (malloc'd) */
72 	DBM	*db;			/* database */
73 	struct opt_domain *dom;		/* back ptr to our domain */
74 	int	host_lookup;		/* host lookup */
75 	int	secure;			/* is this map secure? */
76 	dev_t	dbdev;			/* device db is on */
77 	ino_t	dbino;			/* inode of db */
78 	time_t	dbmtime;		/* time of last db modification */
79 	TAILQ_ENTRY(opt_map) mapsq;	/* map queue pointers */
80 	LIST_ENTRY(opt_map) mapsl;	/* map list pointers */
81 };
82 
83 struct opt_domain {
84 	char	*domain;		/* domain name (malloc'd) */
85 	struct maplist dmaps;		/* the domain's active maps */
86 	LIST_ENTRY(opt_domain) domsl;	/* global linked list of domains */
87 };
88 
89 struct domainlist doms;			/* global list of domains */
90 struct mapq     maps;			/* global queue of maps (LRU) */
91 
92 extern int      usedns;
93 
94 int	yp_private(datum, int);
95 void	ypdb_close_db(DBM *);
96 void	ypdb_close_last(void);
97 void	ypdb_close_map(struct opt_map *);
98 DBM    *ypdb_open_db(const char *, const char *, u_int *, struct opt_map **);
99 u_int	lookup_host(int, int, DBM *, char *, struct ypresp_val *);
100 
101 /*
102  * ypdb_init: init the queues and lists
103  */
104 void
ypdb_init(void)105 ypdb_init(void)
106 {
107 
108 	LIST_INIT(&doms);
109 	TAILQ_INIT(&maps);
110 }
111 
112 /*
113  * yp_private:
114  * Check if key is a YP private key.  Return TRUE if it is and
115  * ypprivate is FALSE.
116  */
117 int
yp_private(datum key,int ypprivate)118 yp_private(datum key, int ypprivate)
119 {
120 
121 	if (ypprivate)
122 		return (FALSE);
123 
124 	if (key.dsize == 0 || key.dptr == NULL)
125 		return (FALSE);
126 
127 	if (key.dsize == YP_LAST_LEN &&
128 	    strncmp(key.dptr, YP_LAST_KEY, YP_LAST_LEN) == 0)
129 		return (TRUE);
130 
131 	if (key.dsize == YP_INPUT_LEN &&
132 	    strncmp(key.dptr, YP_INPUT_KEY, YP_INPUT_LEN) == 0)
133 		return (TRUE);
134 
135 	if (key.dsize == YP_OUTPUT_LEN &&
136 	    strncmp(key.dptr, YP_OUTPUT_KEY, YP_OUTPUT_LEN) == 0)
137 		return (TRUE);
138 
139 	if (key.dsize == YP_MASTER_LEN &&
140 	    strncmp(key.dptr, YP_MASTER_KEY, YP_MASTER_LEN) == 0)
141 		return (TRUE);
142 
143 	if (key.dsize == YP_DOMAIN_LEN &&
144 	    strncmp(key.dptr, YP_DOMAIN_KEY, YP_DOMAIN_LEN) == 0)
145 		return (TRUE);
146 
147 	if (key.dsize == YP_INTERDOMAIN_LEN &&
148 	    strncmp(key.dptr, YP_INTERDOMAIN_KEY, YP_INTERDOMAIN_LEN) == 0)
149 		return (TRUE);
150 
151 	if (key.dsize == YP_SECURE_LEN &&
152 	    strncmp(key.dptr, YP_SECURE_KEY, YP_SECURE_LEN) == 0)
153 		return (TRUE);
154 
155 	return (FALSE);
156 }
157 
158 /*
159  * Close specified map.
160  */
161 void
ypdb_close_map(struct opt_map * map)162 ypdb_close_map(struct opt_map *map)
163 {
164 	TAILQ_REMOVE(&maps, map, mapsq);	/* remove from LRU tailq */
165 	LIST_REMOVE(map, mapsl);		/* remove from domain list */
166 
167 #ifdef DEBUG
168 	syslog(LOG_DEBUG,
169 	    "ypdb_close_map: closing map %s in domain %s [db=%p]",
170 	    map->map, map->dom->domain, map->db);
171 #endif
172 
173 	ypdb_close(map->db);			/* close DB */
174 	free(map->map);				/* free map name */
175 	free(map);				/* free map */
176 }
177 
178 /*
179  * Close least recently used map. This routine is called when we have
180  * no more file descriptors free, or we want to close all maps.
181  */
182 void
ypdb_close_last(void)183 ypdb_close_last(void)
184 {
185 	struct opt_map *last;
186 
187 	if (TAILQ_EMPTY(&maps)) {
188 		syslog(LOG_ERR,
189 		    "ypdb_close_last: LRU list is empty!");
190 		return;
191 	}
192 	last = TAILQ_LAST(&maps, mapq);
193 	ypdb_close_map(last);
194 }
195 
196 /*
197  * Close all open maps.
198  */
199 void
ypdb_close_all(void)200 ypdb_close_all(void)
201 {
202 
203 #ifdef DEBUG
204 	syslog(LOG_DEBUG, "ypdb_close_all(): start");
205 #endif
206 
207 	while (!TAILQ_EMPTY(&maps))
208 		ypdb_close_last();
209 
210 #ifdef DEBUG
211 	syslog(LOG_DEBUG, "ypdb_close_all(): done");
212 #endif
213 }
214 
215 /*
216  * Close Database if Open/Close Optimization isn't turned on.
217  */
218 void
219 /*ARGSUSED*/
ypdb_close_db(DBM * db)220 ypdb_close_db(DBM *db)
221 {
222 
223 #ifdef DEBUG
224 	syslog(LOG_DEBUG, "ypdb_close_db(%p)", db);
225 #endif
226 
227 #ifndef OPTIMIZE_DB
228 	ypdb_close_all();
229 #endif /* not OPTIMIZE_DB */
230 }
231 
232 /*
233  * ypdb_open_db
234  */
235 DBM *
ypdb_open_db(const char * domain,const char * map,u_int * status,struct opt_map ** map_info)236 ypdb_open_db(const char *domain, const char *map, u_int *status,
237 	     struct opt_map **map_info)
238 {
239 	static const char *domain_key = YP_INTERDOMAIN_KEY;
240 	static const char *secure_key = YP_SECURE_KEY;
241 	char map_path[MAXPATHLEN];
242 	struct stat finfo;
243 	struct opt_domain *d = NULL;
244 	struct opt_map *m = NULL;
245 	DBM *db;
246 	datum k, v;
247 
248 	*status = YP_TRUE;	/* defaults to true */
249 
250 	/*
251 	 * check for illegal domain and map names
252 	 */
253 	if (_yp_invalid_domain(domain)) {
254 		*status = YP_NODOM;
255 		return (NULL);
256 	}
257 	if (_yp_invalid_map(map)) {
258 		*status = YP_NOMAP;
259 		return (NULL);
260 	}
261 
262 	/*
263 	 * check for domain, file.
264 	 */
265 	(void)snprintf(map_path, sizeof(map_path), "%s/%s", YP_DB_PATH, domain);
266 	if (stat(map_path, &finfo) < 0 || !S_ISDIR(finfo.st_mode)) {
267 #ifdef DEBUG
268 		syslog(LOG_DEBUG,
269 		    "ypdb_open_db: no domain %s (map=%s)", domain, map);
270 #endif
271 		*status = YP_NODOM;
272 	} else {
273 		(void)snprintf(map_path, sizeof(map_path), "%s/%s/%s%s",
274 		    YP_DB_PATH, domain, map, YPDB_SUFFIX);
275 		if (stat(map_path, &finfo) < 0) {
276 #ifdef DEBUG
277 			syslog(LOG_DEBUG,
278 			    "ypdb_open_db: no map %s (domain=%s)", map,
279 			    domain);
280 #endif
281 			*status = YP_NOMAP;
282 		}
283 	}
284 
285 	/*
286 	 * check for preloaded domain, map
287 	 */
288 	for (d = doms.lh_first; d != NULL; d = d->domsl.le_next)
289 		if (strcmp(domain, d->domain) == 0)
290 			break;
291 
292 	if (d)
293 		for (m = d->dmaps.lh_first; m != NULL; m = m->mapsl.le_next)
294 			if (strcmp(map, m->map) == 0)
295 				break;
296 
297 	/*
298 	 * map found open?
299 	 */
300 	if (m) {
301 #ifdef DEBUG
302 		syslog(LOG_DEBUG,
303 		    "ypdb_open_db: cached open: domain=%s, map=%s, db=%p,",
304 		    domain, map, m->db);
305 		syslog(LOG_DEBUG,
306 		    "\tdbdev %d new %d; dbino %d new %d; dbmtime %ld new %ld",
307 		    m->dbdev, finfo.st_dev, m->dbino, finfo.st_ino,
308 		    (long) m->dbmtime, (long) finfo.st_mtime);
309 #endif
310 		/*
311 		 * if status != YP_TRUE, then this cached database is now
312 		 * non-existent
313 		 */
314 		if (*status != YP_TRUE) {
315 #ifdef DEBUG
316 			syslog(LOG_DEBUG,
317 			    "ypdb_open_db: cached db is now unavailable - "
318 			    "closing: status %s",
319 			    yperr_string(ypprot_err(*status)));
320 #endif
321 			ypdb_close_map(m);
322 			return (NULL);
323 		}
324 
325 		/*
326 		 * is this the same db?
327 		 */
328 		if (finfo.st_dev == m->dbdev && finfo.st_ino == m->dbino &&
329 		    finfo.st_mtime == m->dbmtime) {
330 			TAILQ_REMOVE(&maps, m, mapsq); /* adjust LRU queue */
331 			TAILQ_INSERT_HEAD(&maps, m, mapsq);
332 			if (map_info)
333 				*map_info = m;
334 			return (m->db);
335 		} else {
336 #ifdef DEBUG
337 			syslog(LOG_DEBUG,
338 			    "ypdb_open_db: db changed; closing");
339 #endif
340 			ypdb_close_map(m);
341 			m = NULL;
342 		}
343 	}
344 
345 	/*
346 	 * not cached and non-existent, return
347 	 */
348 	if (*status != YP_TRUE)
349 		return (NULL);
350 
351 	/*
352 	 * open map
353 	 */
354 	(void)snprintf(map_path, sizeof(map_path), "%s/%s/%s",
355 	    YP_DB_PATH, domain, map);
356 #ifdef OPTIMIZE_DB
357 retryopen:
358 #endif /* OPTIMIZE_DB */
359 	db = ypdb_open(map_path);
360 #ifdef OPTIMIZE_DB
361 	if (db == NULL) {
362 #ifdef DEBUG
363 		syslog(LOG_DEBUG,
364 		    "ypdb_open_db: errno %d (%s)", errno, strerror(errno));
365 #endif /* DEBUG */
366 		if ((errno == ENFILE) || (errno == EMFILE)) {
367 			ypdb_close_last();
368 			goto retryopen;
369 		}
370 	}
371 #endif /* OPTIMIZE_DB */
372 
373 	*status = YP_NOMAP;	/* see note below */
374 
375 	if (db == NULL) {
376 #ifdef DEBUG
377 		syslog(LOG_DEBUG,
378 		    "ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)",
379 		    map, domain);
380 #endif
381 		return (NULL);
382 	}
383 
384 	/*
385 	 * note: status now YP_NOMAP
386 	 */
387 	if (d == NULL) {	/* allocate new domain? */
388 		d = (struct opt_domain *) malloc(sizeof(*d));
389 		if (d)
390 			d->domain = strdup(domain);
391 		if (d == NULL || d->domain == NULL) {
392 			syslog(LOG_ERR,
393 			    "ypdb_open_db: MALLOC failed");
394 			ypdb_close(db);
395 			if (d)
396 				free(d);
397 			return (NULL);
398 		}
399 		LIST_INIT(&d->dmaps);
400 		LIST_INSERT_HEAD(&doms, d, domsl);
401 #ifdef DEBUG
402 		syslog(LOG_DEBUG,
403 		    "ypdb_open_db: NEW DOMAIN %s", domain);
404 #endif
405 	}
406 
407 	/*
408 	 * m must be NULL since we couldn't find a map.  allocate new one
409 	 */
410 	m = (struct opt_map *) malloc(sizeof(*m));
411 	if (m)
412 		m->map = strdup(map);
413 
414 	if (m == NULL || m->map == NULL) {
415 		if (m)
416 			free(m);
417 		syslog(LOG_ERR, "ypdb_open_db: MALLOC failed");
418 		ypdb_close(db);
419 		return (NULL);
420 	}
421 	m->db = db;
422 	m->dom = d;
423 	m->host_lookup = FALSE;
424 	m->dbdev = finfo.st_dev;
425 	m->dbino = finfo.st_ino;
426 	m->dbmtime = finfo.st_mtime;
427 	TAILQ_INSERT_HEAD(&maps, m, mapsq);
428 	LIST_INSERT_HEAD(&d->dmaps, m, mapsl);
429 	if (strcmp(map, YP_HOSTNAME) == 0 || strcmp(map, YP_HOSTADDR) == 0) {
430 		if (!usedns) {
431 			k.dptr = domain_key;
432 			k.dsize = YP_INTERDOMAIN_LEN;
433 			v = ypdb_fetch(db, k);
434 			if (v.dptr)
435 				m->host_lookup = TRUE;
436 		} else
437 			m->host_lookup = TRUE;
438 	}
439 
440 	m->secure = FALSE;
441 	k.dptr = secure_key;
442 	k.dsize = YP_SECURE_LEN;
443 	v = ypdb_fetch(db, k);
444 	if (v.dptr != NULL)
445 		m->secure = TRUE;
446 
447 	*status = YP_TRUE;
448 
449 	if (map_info)
450 		*map_info = m;
451 
452 #ifdef DEBUG
453 	syslog(LOG_DEBUG,
454 	    "ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=%p",
455 	    domain, map, m->host_lookup, m->secure, m->db);
456 #endif
457 
458 	return (m->db);
459 }
460 
461 /*
462  * lookup host
463  */
464 u_int
465 /*ARGSUSED*/
lookup_host(int nametable,int host_lookup,DBM * db,char * keystr,struct ypresp_val * result)466 lookup_host(int nametable, int host_lookup, DBM *db, char *keystr,
467 	    struct ypresp_val *result)
468 {
469 	struct hostent *host;
470 	struct in_addr *addr_name;
471 	struct in_addr addr_addr;
472 	static char val[BUFSIZ + 1];	/* match libc */
473 	static char hostname[MAXHOSTNAMELEN];
474 	char tmpbuf[MAXHOSTNAMELEN + 20];
475 	char *v, *ptr;
476 	int l;
477 
478 	if (!host_lookup)
479 		return (YP_NOKEY);
480 
481 	if ((_res.options & RES_INIT) == 0)
482 		(void)res_init();
483 
484 	if (nametable) {
485 		host = gethostbyname(keystr);
486 		if (host == NULL || host->h_addrtype != AF_INET)
487 			return (YP_NOKEY);
488 
489 		addr_name = (struct in_addr *)(void *)host->h_addr_list[0];
490 
491 		v = val;
492 
493 		for (; host->h_addr_list[0] != NULL; host->h_addr_list++) {
494 			addr_name = (struct in_addr *)(void *)host->h_addr_list[0];
495 			(void)snprintf(tmpbuf, sizeof(tmpbuf), "%s %s\n",
496 			    inet_ntoa(*addr_name), host->h_name);
497 			if (v - val + strlen(tmpbuf) + 1 > sizeof(val))
498 				break;
499 			(void)strlcpy(v, tmpbuf, sizeof(val) - (v - val));
500 			v = v + strlen(tmpbuf);
501 		}
502 		result->valdat.dptr = val;
503 		result->valdat.dsize = v - val;
504 		return (YP_TRUE);
505 	}
506 	if (inet_aton(keystr, &addr_addr) == -1)
507 		return (YP_NOKEY);
508 
509 	host = gethostbyaddr((void *)&addr_addr, sizeof(addr_addr), AF_INET);
510 	if (host == NULL)
511 		return (YP_NOKEY);
512 
513 	(void)strlcpy(hostname, host->h_name, sizeof(hostname));
514 	host = gethostbyname(hostname);
515 	if (host == NULL)
516 		return (YP_NOKEY);
517 
518 	l = 0;
519 	for (; host->h_addr_list[0] != NULL; host->h_addr_list++)
520 		if (!memcmp(host->h_addr_list[0], &addr_addr,
521 		    sizeof(addr_addr)))
522 			l++;
523 
524 	if (l == 0) {
525 		syslog(LOG_NOTICE,
526 		    "address %s not listed for host %s\n",
527 		    inet_ntoa(addr_addr), hostname);
528 		return (YP_NOKEY);
529 	}
530 
531 	(void)snprintf(val, sizeof(val), "%s %s", keystr, host->h_name);
532 	l = strlen(val);
533 	v = val + l;
534 	while ((ptr = *(host->h_aliases)) != NULL) {
535 		l = strlen(ptr);
536 		if ((v - val) + l + 1 > BUFSIZ)
537 			break;
538 		(void)strlcpy(v, " ", sizeof(val) - (v - val));
539 		v += 1;
540 		(void)strlcpy(v, ptr, sizeof(val) - (v - val));
541 		v += l;
542 		host->h_aliases++;
543 	}
544 	result->valdat.dptr = val;
545 	result->valdat.dsize = v - val;
546 
547 	return (YP_TRUE);
548 }
549 
550 struct ypresp_val
ypdb_get_record(const char * domain,const char * map,datum key,int ypprivate)551 ypdb_get_record(const char *domain, const char *map, datum key, int ypprivate)
552 {
553 	static struct ypresp_val res;
554 	static char keystr[YPMAXRECORD + 1];
555 	DBM *db;
556 	datum k, v;
557 	int host_lookup, hn;
558 	struct opt_map *map_info = NULL;
559 
560 	host_lookup = 0;	/* XXX gcc -Wuninitialized */
561 
562 	(void)memset(&res, 0, sizeof(res));
563 
564 	db = ypdb_open_db(domain, map, &res.status, &map_info);
565 	if (db == NULL || (int)res.status < 0)
566 		return (res);
567 
568 	if (map_info)
569 		host_lookup = map_info->host_lookup;
570 
571 	k.dptr = key.dptr;
572 	k.dsize = key.dsize;
573 
574 	if (yp_private(k, ypprivate)) {
575 		res.status = YP_NOKEY;
576 		goto done;
577 	}
578 	v = ypdb_fetch(db, k);
579 
580 	if (v.dptr == NULL) {
581 		res.status = YP_NOKEY;
582 		if ((hn = strcmp(map, YP_HOSTNAME)) != 0 &&
583 		    strcmp(map, YP_HOSTADDR) != 0)
584 			return (res);
585 
586 		/* note: lookup_host needs null terminated string */
587 		(void)strlcpy(keystr, key.dptr, (size_t)key.dsize + 1);
588 		res.status = lookup_host((hn == 0) ? TRUE : FALSE,
589 		    host_lookup, db, keystr, &res);
590 	} else {
591 		res.valdat.dptr = v.dptr;
592 		res.valdat.dsize = v.dsize;
593 	}
594 
595  done:
596 	ypdb_close_db(db);
597 	return (res);
598 }
599 
600 struct ypresp_key_val
ypdb_get_first(const char * domain,const char * map,int ypprivate)601 ypdb_get_first(const char *domain, const char *map, int ypprivate)
602 {
603 	static struct ypresp_key_val res;
604 	DBM *db;
605 	datum k, v;
606 
607 	(void)memset(&res, 0, sizeof(res));
608 
609 	db = ypdb_open_db(domain, map, &res.status, NULL);
610 
611 	if (db != NULL && (int)res.status >= 0) {
612 		k = ypdb_firstkey(db);
613 
614 		while (yp_private(k, ypprivate))
615 			k = ypdb_nextkey(db);
616 
617 		if (k.dptr == NULL)
618 			res.status = YP_NOKEY;
619 		else {
620 			res.keydat.dptr = k.dptr;
621 			res.keydat.dsize = k.dsize;
622 			v = ypdb_fetch(db, k);
623 			if (v.dptr == NULL)
624 				res.status = YP_NOKEY;
625 			else {
626 				res.valdat.dptr = v.dptr;
627 				res.valdat.dsize = v.dsize;
628 			}
629 		}
630 	}
631 
632 	if (db != NULL)
633 		ypdb_close_db(db);
634 
635 	return (res);
636 }
637 
638 struct ypresp_key_val
ypdb_get_next(const char * domain,const char * map,datum key,int ypprivate)639 ypdb_get_next(const char *domain, const char *map, datum key, int ypprivate)
640 {
641 	static struct ypresp_key_val res;
642 	DBM *db;
643 	datum k, v, n;
644 
645 	(void)memset(&res, 0, sizeof(res));
646 
647 	db = ypdb_open_db(domain, map, &res.status, NULL);
648 
649 	if (db != NULL && (int)res.status >= 0) {
650 		n.dptr = key.dptr;
651 		n.dsize = key.dsize;
652 		v.dptr = NULL;
653 		v.dsize = 0;
654 		k.dptr = NULL;
655 		k.dsize = 0;
656 
657 		n = ypdb_setkey(db, n);
658 
659 		if (n.dptr != NULL)
660 			k = ypdb_nextkey(db);
661 		else
662 			k.dptr = NULL;
663 
664 		if (k.dptr != NULL)
665 			while (yp_private(k, ypprivate))
666 				k = ypdb_nextkey(db);
667 
668 		if (k.dptr == NULL)
669 			res.status = YP_NOMORE;
670 		else {
671 			res.keydat.dptr = k.dptr;
672 			res.keydat.dsize = k.dsize;
673 			v = ypdb_fetch(db, k);
674 			if (v.dptr == NULL)
675 				res.status = YP_NOMORE;
676 			else {
677 				res.valdat.dptr = v.dptr;
678 				res.valdat.dsize = v.dsize;
679 			}
680 		}
681 	}
682 
683 	if (db != NULL)
684 		ypdb_close_db(db);
685 
686 	return (res);
687 }
688 
689 struct ypresp_order
ypdb_get_order(const char * domain,const char * map)690 ypdb_get_order(const char *domain, const char *map)
691 {
692 	static struct ypresp_order res;
693 	static const char *order_key = YP_LAST_KEY;
694 	char order[MAX_LAST_LEN + 1];
695 	DBM *db;
696 	datum k, v;
697 
698 	(void)memset(&res, 0, sizeof(res));
699 
700 	db = ypdb_open_db(domain, map, &res.status, NULL);
701 
702 	if (db != NULL && (int)res.status >= 0) {
703 		k.dptr = order_key;
704 		k.dsize = YP_LAST_LEN;
705 
706 		v = ypdb_fetch(db, k);
707 		if (v.dptr == NULL)
708 			res.status = YP_NOKEY;
709 		else {
710 			(void)strlcpy(order, v.dptr, (size_t)v.dsize + 1);
711 			res.ordernum = (u_int) atol(order);
712 		}
713 	}
714 
715 	if (db != NULL)
716 		ypdb_close_db(db);
717 
718 	return (res);
719 }
720 
721 struct ypresp_master
ypdb_get_master(const char * domain,const char * map)722 ypdb_get_master(const char *domain, const char *map)
723 {
724 	static struct ypresp_master res;
725 	static const char *master_key = YP_MASTER_KEY;
726 	static char master[MAX_MASTER_LEN + 1];
727 	DBM *db;
728 	datum k, v;
729 
730 	(void)memset(&res, 0, sizeof(res));
731 
732 	db = ypdb_open_db(domain, map, &res.status, NULL);
733 
734 	if (db != NULL && (int)res.status >= 0) {
735 		k.dptr = master_key;
736 		k.dsize = YP_MASTER_LEN;
737 
738 		v = ypdb_fetch(db, k);
739 		if (v.dptr == NULL)
740 			res.status = YP_NOKEY;
741 		else {
742 			(void)strlcpy(master, v.dptr, (size_t)v.dsize + 1);
743 			res.master = &master[0];
744 		}
745 	}
746 
747 	if (db != NULL)
748 		ypdb_close_db(db);
749 
750 	return (res);
751 }
752 
753 bool_t
ypdb_xdr_get_all(XDR * xdrs,struct ypreq_nokey * req)754 ypdb_xdr_get_all(XDR *xdrs, struct ypreq_nokey *req)
755 {
756 	static struct ypresp_all resp;
757 	DBM *db;
758 	datum k, v;
759 
760 	(void)memset(&resp, 0, sizeof(resp));
761 
762 	/*
763 	 * open db, and advance past any private keys we may see
764 	 */
765 	db = ypdb_open_db(req->domain, req->map,
766 	    &resp.ypresp_all_u.val.status, NULL);
767 
768 	if (db == NULL || (int)resp.ypresp_all_u.val.status < 0)
769 		return (FALSE);
770 
771 	k = ypdb_firstkey(db);
772 	while (yp_private(k, FALSE))
773 		k = ypdb_nextkey(db);
774 
775 	for (;;) {
776 		if (k.dptr == NULL)
777 			break;
778 
779 		v = ypdb_fetch(db, k);
780 
781 		if (v.dptr == NULL)
782 			break;
783 
784 		resp.more = TRUE;
785 		resp.ypresp_all_u.val.status = YP_TRUE;
786 		resp.ypresp_all_u.val.keydat.dptr = k.dptr;
787 		resp.ypresp_all_u.val.keydat.dsize = k.dsize;
788 		resp.ypresp_all_u.val.valdat.dptr = v.dptr;
789 		resp.ypresp_all_u.val.valdat.dsize = v.dsize;
790 
791 		if (!xdr_ypresp_all(xdrs, &resp)) {
792 #ifdef DEBUG
793 			syslog(LOG_DEBUG,
794 			    "ypdb_xdr_get_all: xdr_ypresp_all failed");
795 #endif
796 			return (FALSE);
797 		}
798 
799 		/* advance past private keys */
800 		k = ypdb_nextkey(db);
801 		while (yp_private(k, FALSE))
802 			k = ypdb_nextkey(db);
803 	}
804 
805 	(void)memset(&resp, 0, sizeof(resp));
806 	resp.ypresp_all_u.val.status = YP_NOKEY;
807 	resp.more = FALSE;
808 
809 	if (!xdr_ypresp_all(xdrs, &resp)) {
810 #ifdef DEBUG
811 		syslog(LOG_DEBUG,
812 		    "ypdb_xdr_get_all: final xdr_ypresp_all failed");
813 #endif
814 		return (FALSE);
815 	}
816 
817 	if (db != NULL)
818 		ypdb_close_db(db);
819 
820 	return (TRUE);
821 }
822 
823 int
ypdb_secure(const char * domain,const char * map)824 ypdb_secure(const char *domain, const char *map)
825 {
826 	DBM *db;
827 	int secure;
828 	u_int status;
829 	struct opt_map *map_info = NULL;
830 
831 	secure = FALSE;
832 
833 	db = ypdb_open_db(domain, map, &status, &map_info);
834 	if (db == NULL || (int)status < 0)
835 		return (secure);
836 	if (map_info != NULL)
837 		secure = map_info->secure;
838 
839 	ypdb_close_db(db);
840 	return (secure);
841 }
842