1 /* $OpenBSD: yp.c,v 1.22 2023/07/18 13:06:33 claudio Exp $ */
2 /*
3 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/socket.h>
21 #include <sys/select.h>
22 #include <sys/tree.h>
23 #include <sys/stat.h>
24
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27
28 #include <errno.h>
29 #include <event.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <limits.h>
37
38 #include <rpc/rpc.h>
39 #include <rpc/xdr.h>
40 #include <rpc/pmap_clnt.h>
41 #include <rpc/pmap_prot.h>
42 #include <rpc/pmap_rmt.h>
43 #include <rpcsvc/yp.h>
44 #include <rpcsvc/ypclnt.h>
45
46 #include "ypldap.h"
47 #include "log.h"
48
49 #define BINDINGDIR "/var/yp/binding"
50
51 void yp_dispatch(struct svc_req *, SVCXPRT *);
52 void yp_disable_events(void);
53 void yp_fd_event(int, short, void *);
54 int yp_check(struct svc_req *);
55 int yp_valid_domain(char *, struct ypresp_val *);
56 void yp_make_val(struct ypresp_val *, char *, int);
57 void yp_make_keyval(struct ypresp_key_val *, char *, char *);
58 int yp_write_binding(int, int);
59
60 static struct env *env;
61
62 struct yp_event {
63 TAILQ_ENTRY(yp_event) ye_entry;
64 struct event ye_event;
65 };
66
67 struct yp_data {
68 SVCXPRT *yp_trans_udp;
69 SVCXPRT *yp_trans_tcp;
70 TAILQ_HEAD(, yp_event) yd_events;
71 };
72
73 void
yp_disable_events(void)74 yp_disable_events(void)
75 {
76 struct yp_event *ye;
77
78 while ((ye = TAILQ_FIRST(&env->sc_yp->yd_events)) != NULL) {
79 TAILQ_REMOVE(&env->sc_yp->yd_events, ye, ye_entry);
80 event_del(&ye->ye_event);
81 free(ye);
82 }
83 }
84
85 void
yp_enable_events(void)86 yp_enable_events(void)
87 {
88 int i;
89 extern fd_set *__svc_fdset;
90 extern int __svc_fdsetsize;
91 struct yp_event *ye;
92
93 for (i = 0; i < __svc_fdsetsize; i++) {
94 if (FD_ISSET(i, __svc_fdset)) {
95 if ((ye = calloc(1, sizeof(*ye))) == NULL)
96 fatal(NULL);
97 event_set(&ye->ye_event, i, EV_READ, yp_fd_event, NULL);
98 event_add(&ye->ye_event, NULL);
99 TAILQ_INSERT_TAIL(&env->sc_yp->yd_events, ye, ye_entry);
100 }
101 }
102 }
103
104 void
yp_fd_event(int fd,short event,void * p)105 yp_fd_event(int fd, short event, void *p)
106 {
107 svc_getreq_common(fd);
108 yp_disable_events();
109 yp_enable_events();
110 }
111
112 void
yp_init(struct env * x_env)113 yp_init(struct env *x_env)
114 {
115 struct sockaddr_in addr;
116 struct yp_data *yp;
117 int s, udpport, tcpport;
118
119 if ((yp = calloc(1, sizeof(*yp))) == NULL)
120 fatal(NULL);
121 TAILQ_INIT(&yp->yd_events);
122
123 env = x_env;
124 env->sc_yp = yp;
125
126 switch (env->sc_bind_mode) {
127 case BIND_MODE_LOCAL:
128 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
129 addr.sin_len = sizeof(struct sockaddr_in);
130 addr.sin_family = AF_INET;
131
132 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
133 if (s == -1)
134 fatal("cannot create udp socket");
135 addr.sin_port = 0;
136 if (bindresvport(s, &addr))
137 fatal("cannot bind udp socket");
138 if ((yp->yp_trans_udp = svcudp_create(s)) == NULL)
139 fatal("cannot create udp service");
140 udpport = ntohs(addr.sin_port);
141
142 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
143 if (s == -1)
144 fatal("cannot create tcp socket");
145 addr.sin_port = 0;
146 if (bindresvport(s, &addr))
147 fatal("cannot bind tcp socket");
148 if ((yp->yp_trans_tcp = svctcp_create(s, 0, 0)) == NULL)
149 fatal("cannot create tcp service");
150 tcpport = ntohs(addr.sin_port);
151
152 /* protocol 0 means don't register with portmap */
153 if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS,
154 yp_dispatch, 0)) {
155 fatal("unable to register (YPPROG, YPVERS, udp)");
156 }
157 if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS,
158 yp_dispatch, 0)) {
159 fatal("unable to register (YPPROG, YPVERS, tcp)");
160 }
161
162 if (yp_write_binding(udpport, tcpport))
163 fatal("cannot write yp binding file");
164
165 break;
166
167 case BIND_MODE_PORTMAP:
168 (void)pmap_unset(YPPROG, YPVERS);
169
170 if ((yp->yp_trans_udp = svcudp_create(RPC_ANYSOCK)) == NULL)
171 fatal("cannot create udp service");
172 if ((yp->yp_trans_tcp = svctcp_create(RPC_ANYSOCK, 0, 0)) ==
173 NULL)
174 fatal("cannot create tcp service");
175
176 if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS,
177 yp_dispatch, IPPROTO_UDP)) {
178 fatal("unable to register (YPPROG, YPVERS, udp)");
179 }
180 if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS,
181 yp_dispatch, IPPROTO_TCP)) {
182 fatal("unable to register (YPPROG, YPVERS, tcp)");
183 }
184 break;
185 }
186 }
187
188 int
yp_write_binding(int udpport,int tcpport)189 yp_write_binding(int udpport, int tcpport)
190 {
191 char path[PATH_MAX];
192 struct ypbind_resp ybr;
193 struct iovec iov[3];
194 struct in_addr bindaddr;
195 u_short ypbind, ypserv_tcp, ypserv_udp;
196 ssize_t total;
197 int fd;
198
199 snprintf(path, sizeof path, "%s/%s.%ld", BINDINGDIR, env->sc_domainname,
200 YPVERS);
201 fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644);
202 if (fd == -1) {
203 (void)mkdir(BINDINGDIR, 0755);
204 fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC,
205 0644);
206 if (fd == -1)
207 return -1;
208 }
209
210 if (fchmod(fd, 0644) == -1)
211 return -1;
212
213 iov[0].iov_base = (caddr_t)&ypbind;
214 iov[0].iov_len = sizeof ypbind;
215 iov[1].iov_base = (caddr_t)&ybr;
216 iov[1].iov_len = sizeof ybr;
217 iov[2].iov_base = (caddr_t)&ypserv_tcp;
218 iov[2].iov_len = sizeof ypserv_tcp;
219
220 bindaddr.s_addr = htonl(INADDR_LOOPBACK);
221 ypserv_tcp = htons(tcpport);
222 ypserv_udp = htons(udpport);
223 ypbind = 0;
224 memset(&ybr, 0, sizeof ybr);
225 ybr.ypbind_status = YPBIND_SUCC_VAL;
226 memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
227 &bindaddr,
228 sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr));
229 memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
230 &ypserv_udp,
231 sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port));
232
233 total = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
234 if (writev(fd, iov, sizeof(iov)/sizeof(iov[0])) !=
235 total) {
236 close(fd);
237 unlink(path);
238 return -1;
239 }
240
241 return 0;
242 }
243
244 /*
245 * lots of inspiration from ypserv by Mats O Jansson
246 */
247 void
yp_dispatch(struct svc_req * req,SVCXPRT * trans)248 yp_dispatch(struct svc_req *req, SVCXPRT *trans)
249 {
250 xdrproc_t xdr_argument;
251 xdrproc_t xdr_result;
252 char *result;
253 char *(*cb)(char *, struct svc_req *);
254 union {
255 domainname ypproc_domain_2_arg;
256 domainname ypproc_domain_nonack_2_arg;
257 ypreq_key ypproc_match_2_arg;
258 ypreq_nokey ypproc_first_2_arg;
259 ypreq_key ypproc_next_2_arg;
260 ypreq_xfr ypproc_xfr_2_arg;
261 ypreq_nokey ypproc_all_2_arg;
262 ypreq_nokey ypproc_master_2_arg;
263 ypreq_nokey ypproc_order_2_arg;
264 domainname ypproc_maplist_2_arg;
265 } argument;
266
267 xdr_argument = (xdrproc_t) xdr_void;
268 xdr_result = (xdrproc_t) xdr_void;
269 cb = NULL;
270 switch (req->rq_proc) {
271 case YPPROC_NULL:
272 xdr_argument = (xdrproc_t) xdr_void;
273 xdr_result = (xdrproc_t) xdr_void;
274 if (yp_check(req) == -1)
275 return;
276 result = NULL;
277 if (!svc_sendreply(trans, (xdrproc_t) xdr_void,
278 (void *)&result))
279 svcerr_systemerr(trans);
280 return;
281 case YPPROC_DOMAIN:
282 xdr_argument = (xdrproc_t) xdr_domainname;
283 xdr_result = (xdrproc_t) xdr_bool;
284 if (yp_check(req) == -1)
285 return;
286 cb = (void *)ypproc_domain_2_svc;
287 break;
288 case YPPROC_DOMAIN_NONACK:
289 xdr_argument = (xdrproc_t) xdr_domainname;
290 xdr_result = (xdrproc_t) xdr_bool;
291 if (yp_check(req) == -1)
292 return;
293 cb = (void *)ypproc_domain_nonack_2_svc;
294 break;
295 case YPPROC_MATCH:
296 xdr_argument = (xdrproc_t) xdr_ypreq_key;
297 xdr_result = (xdrproc_t) xdr_ypresp_val;
298 if (yp_check(req) == -1)
299 return;
300 cb = (void *)ypproc_match_2_svc;
301 break;
302 case YPPROC_FIRST:
303 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
304 xdr_result = (xdrproc_t) xdr_ypresp_key_val;
305 if (yp_check(req) == -1)
306 return;
307 cb = (void *)ypproc_first_2_svc;
308 break;
309 case YPPROC_NEXT:
310 xdr_argument = (xdrproc_t) xdr_ypreq_key;
311 xdr_result = (xdrproc_t) xdr_ypresp_key_val;
312 if (yp_check(req) == -1)
313 return;
314 cb = (void *)ypproc_next_2_svc;
315 break;
316 case YPPROC_XFR:
317 if (yp_check(req) == -1)
318 return;
319 svcerr_noproc(trans);
320 return;
321 case YPPROC_CLEAR:
322 log_debug("ypproc_clear");
323 if (yp_check(req) == -1)
324 return;
325 svcerr_noproc(trans);
326 return;
327 case YPPROC_ALL:
328 log_debug("ypproc_all");
329 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
330 xdr_result = (xdrproc_t) xdr_ypresp_all;
331 if (yp_check(req) == -1)
332 return;
333 cb = (void *)ypproc_all_2_svc;
334 break;
335 case YPPROC_MASTER:
336 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
337 xdr_result = (xdrproc_t) xdr_ypresp_master;
338 if (yp_check(req) == -1)
339 return;
340 cb = (void *)ypproc_master_2_svc;
341 break;
342 case YPPROC_ORDER:
343 log_debug("ypproc_order");
344 if (yp_check(req) == -1)
345 return;
346 svcerr_noproc(trans);
347 return;
348 case YPPROC_MAPLIST:
349 xdr_argument = (xdrproc_t) xdr_domainname;
350 xdr_result = (xdrproc_t) xdr_ypresp_maplist;
351 if (yp_check(req) == -1)
352 return;
353 cb = (void *)ypproc_maplist_2_svc;
354 break;
355 default:
356 svcerr_noproc(trans);
357 return;
358 }
359 (void)memset(&argument, 0, sizeof(argument));
360
361 if (!svc_getargs(trans, xdr_argument, (caddr_t)&argument)) {
362 svcerr_decode(trans);
363 return;
364 }
365 result = (*cb)((char *)&argument, req);
366 if (result != NULL && !svc_sendreply(trans, xdr_result, result))
367 svcerr_systemerr(trans);
368 if (!svc_freeargs(trans, xdr_argument, (caddr_t)&argument)) {
369 /*
370 * ypserv does it too.
371 */
372 fatal("unable to free arguments");
373 }
374 }
375
376 int
yp_check(struct svc_req * req)377 yp_check(struct svc_req *req)
378 {
379 #ifdef notyet
380 struct sockaddr_in *caller;
381
382 caller = svc_getcaller(req->rq_xprt);
383 /*
384 * We might want to know who we allow here.
385 */
386 #endif
387 return (0);
388 }
389
390 int
yp_valid_domain(char * domain,struct ypresp_val * res)391 yp_valid_domain(char *domain, struct ypresp_val *res)
392 {
393 if (domain == NULL) {
394 log_debug("NULL domain !");
395 return (-1);
396 }
397 if (strcmp(domain, env->sc_domainname) != 0) {
398 res->stat = YP_NODOM;
399 return (-1);
400 }
401 return (0);
402 }
403
404 bool_t *
ypproc_domain_2_svc(domainname * arg,struct svc_req * req)405 ypproc_domain_2_svc(domainname *arg, struct svc_req *req)
406 {
407 static bool_t res;
408
409 res = (bool_t)1;
410 if (strcmp(*arg, env->sc_domainname) != 0)
411 res = (bool_t)0;
412 return (&res);
413 }
414
415 bool_t *
ypproc_domain_nonack_2_svc(domainname * arg,struct svc_req * req)416 ypproc_domain_nonack_2_svc(domainname *arg, struct svc_req *req)
417 {
418 static bool_t res;
419
420 if (strcmp(*arg, env->sc_domainname) != 0)
421 return NULL;
422 res = (bool_t)1;
423 return (&res);
424 }
425
426 ypresp_val *
ypproc_match_2_svc(ypreq_key * arg,struct svc_req * req)427 ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req)
428 {
429 struct userent ukey;
430 struct userent *ue;
431 struct groupent gkey;
432 struct groupent *ge;
433 static struct ypresp_val res;
434 const char *estr;
435 char *bp, *cp;
436 char key[YPMAXRECORD+1];
437
438 log_debug("matching '%.*s' in map %s", arg->key.keydat_len,
439 arg->key.keydat_val, arg->map);
440
441 if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
442 return (&res);
443
444 if (env->sc_user_names == NULL) {
445 /*
446 * tree not ready.
447 */
448 return (NULL);
449 }
450
451 if (arg->key.keydat_len > YPMAXRECORD) {
452 log_debug("argument too long");
453 return (NULL);
454 }
455 memset(key, 0, sizeof(key));
456 (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len);
457
458 if (strcmp(arg->map, "passwd.byname") == 0 ||
459 strcmp(arg->map, "master.passwd.byname") == 0) {
460 ukey.ue_line = key;
461 if ((ue = RB_FIND(user_name_tree, env->sc_user_names,
462 &ukey)) == NULL) {
463 res.stat = YP_NOKEY;
464 return (&res);
465 }
466
467 yp_make_val(&res, ue->ue_line, 1);
468 return (&res);
469 } else if (strcmp(arg->map, "passwd.byuid") == 0 ||
470 strcmp(arg->map, "master.passwd.byuid") == 0) {
471 ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr);
472 if (estr) {
473 res.stat = YP_BADARGS;
474 return (&res);
475 }
476
477 if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
478 &ukey)) == NULL) {
479 res.stat = YP_NOKEY;
480 return (&res);
481 }
482
483 yp_make_val(&res, ue->ue_line, 1);
484 return (&res);
485 } else if (strcmp(arg->map, "group.bygid") == 0) {
486 gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr);
487 if (estr) {
488 res.stat = YP_BADARGS;
489 return (&res);
490 }
491 if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids,
492 &gkey)) == NULL) {
493 res.stat = YP_NOKEY;
494 return (&res);
495 }
496
497 yp_make_val(&res, ge->ge_line, 1);
498 return (&res);
499 } else if (strcmp(arg->map, "group.byname") == 0) {
500 gkey.ge_line = key;
501 if ((ge = RB_FIND(group_name_tree, env->sc_group_names,
502 &gkey)) == NULL) {
503 res.stat = YP_NOKEY;
504 return (&res);
505 }
506
507 yp_make_val(&res, ge->ge_line, 1);
508 return (&res);
509 } else if (strcmp(arg->map, "netid.byname") == 0) {
510 bp = cp = key;
511
512 if (strncmp(bp, "unix.", strlen("unix.")) != 0) {
513 res.stat = YP_BADARGS;
514 return (&res);
515 }
516
517 bp += strlen("unix.");
518
519 if (*bp == '\0') {
520 res.stat = YP_BADARGS;
521 return (&res);
522 }
523
524 if (!(cp = strsep(&bp, "@"))) {
525 res.stat = YP_BADARGS;
526 return (&res);
527 }
528
529 if (strcmp(bp, arg->domain) != 0) {
530 res.stat = YP_BADARGS;
531 return (&res);
532 }
533
534 ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr);
535 if (estr) {
536 res.stat = YP_BADARGS;
537 return (&res);
538 }
539
540 if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
541 &ukey)) == NULL) {
542 res.stat = YP_NOKEY;
543 return (&res);
544 }
545
546 yp_make_val(&res, ue->ue_netid_line, 0);
547 return (&res);
548
549 } else {
550 log_debug("unknown map %s", arg->map);
551 res.stat = YP_NOMAP;
552 return (&res);
553 }
554 }
555
556 ypresp_key_val *
ypproc_first_2_svc(ypreq_nokey * arg,struct svc_req * req)557 ypproc_first_2_svc(ypreq_nokey *arg, struct svc_req *req)
558 {
559 static struct ypresp_key_val res;
560
561 if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
562 return (&res);
563
564 if (strcmp(arg->map, "passwd.byname") == 0 ||
565 strcmp(arg->map, "master.passwd.byname") == 0) {
566 if (env->sc_user_lines == NULL)
567 return (NULL);
568
569 yp_make_keyval(&res, env->sc_user_lines, env->sc_user_lines);
570 } else if (strcmp(arg->map, "group.byname") == 0) {
571 if (env->sc_group_lines == NULL)
572 return (NULL);
573
574 yp_make_keyval(&res, env->sc_group_lines, env->sc_group_lines);
575 } else {
576 log_debug("unknown map %s", arg->map);
577 res.stat = YP_NOMAP;
578 }
579
580 return (&res);
581 }
582
583 ypresp_key_val *
ypproc_next_2_svc(ypreq_key * arg,struct svc_req * req)584 ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
585 {
586 struct userent ukey;
587 struct userent *ue;
588 struct groupent gkey;
589 struct groupent *ge;
590 char *line;
591 static struct ypresp_key_val res;
592 char key[YPMAXRECORD+1];
593
594 if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
595 return (&res);
596
597 if (strcmp(arg->map, "passwd.byname") == 0 ||
598 strcmp(arg->map, "master.passwd.byname") == 0) {
599 memset(key, 0, sizeof(key));
600 (void)strncpy(key, arg->key.keydat_val,
601 arg->key.keydat_len);
602 ukey.ue_line = key;
603 if ((ue = RB_NFIND(user_name_tree, env->sc_user_names,
604 &ukey)) == NULL) {
605 res.stat = YP_NOKEY;
606 return (&res);
607 }
608 line = ue->ue_line + (strlen(ue->ue_line) + 1);
609 line = line + (strlen(line) + 1);
610 yp_make_keyval(&res, line, line);
611 return (&res);
612
613
614 } else if (strcmp(arg->map, "group.byname") == 0) {
615 memset(key, 0, sizeof(key));
616 (void)strncpy(key, arg->key.keydat_val,
617 arg->key.keydat_len);
618
619 gkey.ge_line = key;
620 if ((ge = RB_NFIND(group_name_tree, env->sc_group_names,
621 &gkey)) == NULL) {
622 res.stat = YP_NOKEY;
623 return (&res);
624 }
625
626 line = ge->ge_line + (strlen(ge->ge_line) + 1);
627 line = line + (strlen(line) + 1);
628 yp_make_keyval(&res, line, line);
629 return (&res);
630 } else {
631 log_debug("unknown map %s", arg->map);
632 res.stat = YP_NOMAP;
633 return (&res);
634 }
635 }
636
637 ypresp_all *
ypproc_all_2_svc(ypreq_nokey * arg,struct svc_req * req)638 ypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req)
639 {
640 static struct ypresp_all res;
641
642 if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
643 return (&res);
644
645 svcerr_auth(req->rq_xprt, AUTH_FAILED);
646 return (NULL);
647 }
648
649 ypresp_master *
ypproc_master_2_svc(ypreq_nokey * arg,struct svc_req * req)650 ypproc_master_2_svc(ypreq_nokey *arg, struct svc_req *req)
651 {
652 static struct ypresp_master res;
653 static char master[YPMAXPEER + 1];
654
655 memset(&res, 0, sizeof(res));
656 if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
657 return (&res);
658 if (gethostname(master, sizeof(master)) == 0) {
659 res.peer = (peername)master;
660 res.stat = YP_TRUE;
661 } else
662 res.stat = YP_NOKEY;
663 return (&res);
664 }
665
666 ypresp_maplist *
ypproc_maplist_2_svc(domainname * arg,struct svc_req * req)667 ypproc_maplist_2_svc(domainname *arg, struct svc_req *req)
668 {
669 size_t i;
670 static struct {
671 char *name;
672 int cond;
673 } mapnames[] = {
674 { "passwd.byname", YPMAP_PASSWD_BYNAME },
675 { "passwd.byuid", YPMAP_PASSWD_BYUID },
676 { "master.passwd.byname", YPMAP_MASTER_PASSWD_BYNAME },
677 { "master.passwd.byuid", YPMAP_MASTER_PASSWD_BYUID },
678 { "group.byname", YPMAP_GROUP_BYNAME },
679 { "group.bygid", YPMAP_GROUP_BYGID },
680 { "netid.byname", YPMAP_NETID_BYNAME },
681 };
682 static ypresp_maplist res;
683 static struct ypmaplist maps[sizeof(mapnames) / sizeof(mapnames[0])];
684
685 if (yp_valid_domain(*arg, (struct ypresp_val *)&res) == -1)
686 return (&res);
687
688 res.stat = YP_TRUE;
689 res.maps = NULL;
690 for (i = 0; i < sizeof(mapnames) / sizeof(mapnames[0]); i++) {
691 if (!(env->sc_flags & mapnames[i].cond))
692 continue;
693 maps[i].map = mapnames[i].name;
694 maps[i].next = res.maps;
695 res.maps = &maps[i];
696 }
697
698 return (&res);
699 }
700
701 void
yp_make_val(struct ypresp_val * res,char * line,int replacecolon)702 yp_make_val(struct ypresp_val *res, char *line, int replacecolon)
703 {
704 static char buf[LINE_WIDTH];
705
706 memset(buf, 0, sizeof(buf));
707
708 if (replacecolon)
709 line[strlen(line)] = ':';
710 (void)strlcpy(buf, line, sizeof(buf));
711 if (replacecolon)
712 line[strcspn(line, ":")] = '\0';
713 log_debug("sending out %s", buf);
714
715 res->stat = YP_TRUE;
716 res->val.valdat_len = strlen(buf);
717 res->val.valdat_val = buf;
718 }
719
720 void
yp_make_keyval(struct ypresp_key_val * res,char * key,char * line)721 yp_make_keyval(struct ypresp_key_val *res, char *key, char *line)
722 {
723 static char keybuf[YPMAXRECORD+1];
724 static char buf[LINE_WIDTH];
725
726 memset(keybuf, 0, sizeof(keybuf));
727 memset(buf, 0, sizeof(buf));
728
729 (void)strlcpy(keybuf, key, sizeof(keybuf));
730 res->key.keydat_len = strlen(keybuf);
731 res->key.keydat_val = keybuf;
732
733 if (*line == '\0') {
734 res->stat = YP_NOMORE;
735 return;
736 }
737 res->stat = YP_TRUE;
738 line[strlen(line)] = ':';
739 (void)strlcpy(buf, line, sizeof(buf));
740 line[strcspn(line, ":")] = '\0';
741 log_debug("sending out %s => %s", keybuf, buf);
742
743 res->val.valdat_len = strlen(buf);
744 res->val.valdat_val = buf;
745 }
746