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