yp.c revision 290937
1290931Srodrigc/* $OpenBSD: yp.c,v 1.14 2015/02/11 01:26:00 pelikan Exp $ */ 2290931Srodrigc/* $FreeBSD: head/usr.sbin/ypldap/yp.c 290937 2015-11-16 17:06:33Z rodrigc $ */ 3290931Srodrigc/* 4290931Srodrigc * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5290931Srodrigc * 6290931Srodrigc * Permission to use, copy, modify, and distribute this software for any 7290931Srodrigc * purpose with or without fee is hereby granted, provided that the above 8290931Srodrigc * copyright notice and this permission notice appear in all copies. 9290931Srodrigc * 10290931Srodrigc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11290931Srodrigc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12290931Srodrigc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13290931Srodrigc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14290931Srodrigc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15290931Srodrigc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16290931Srodrigc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17290931Srodrigc */ 18290931Srodrigc 19290931Srodrigc#include <sys/types.h> 20290937Srodrigc#include <sys/param.h> 21290931Srodrigc#include <sys/queue.h> 22290931Srodrigc#include <sys/socket.h> 23290931Srodrigc#include <sys/select.h> 24290931Srodrigc#include <sys/tree.h> 25290931Srodrigc 26290931Srodrigc#include <netinet/in.h> 27290931Srodrigc#include <arpa/inet.h> 28290931Srodrigc 29290931Srodrigc#include <errno.h> 30290931Srodrigc#include <event.h> 31290931Srodrigc#include <fcntl.h> 32290931Srodrigc#include <unistd.h> 33290931Srodrigc#include <pwd.h> 34290931Srodrigc#include <stdio.h> 35290931Srodrigc#include <stdlib.h> 36290931Srodrigc#include <string.h> 37290931Srodrigc#include <limits.h> 38290931Srodrigc 39290931Srodrigc#include <rpc/rpc.h> 40290931Srodrigc#include <rpc/xdr.h> 41290931Srodrigc#include <rpc/pmap_clnt.h> 42290931Srodrigc#include <rpc/pmap_prot.h> 43290931Srodrigc#include <rpc/pmap_rmt.h> 44290931Srodrigc#include <rpcsvc/yp.h> 45290931Srodrigc#include <rpcsvc/ypclnt.h> 46290931Srodrigc 47290931Srodrigc#include "ypldap.h" 48290931Srodrigc 49290931Srodrigcvoid yp_dispatch(struct svc_req *, SVCXPRT *); 50290931Srodrigcvoid yp_disable_events(void); 51290931Srodrigcvoid yp_fd_event(int, short, void *); 52290931Srodrigcint yp_check(struct svc_req *); 53290931Srodrigcint yp_valid_domain(char *, struct ypresp_val *); 54290931Srodrigcvoid yp_make_val(struct ypresp_val *, char *, int); 55290931Srodrigcvoid yp_make_keyval(struct ypresp_key_val *, char *, char *); 56290931Srodrigc 57290931Srodrigcstatic struct env *env; 58290931Srodrigc 59290931Srodrigcstruct yp_event { 60290931Srodrigc TAILQ_ENTRY(yp_event) ye_entry; 61290931Srodrigc struct event ye_event; 62290931Srodrigc}; 63290931Srodrigc 64290931Srodrigcstruct yp_data { 65290931Srodrigc SVCXPRT *yp_trans_udp; 66290931Srodrigc SVCXPRT *yp_trans_tcp; 67290931Srodrigc TAILQ_HEAD(, yp_event) yd_events; 68290931Srodrigc}; 69290931Srodrigc 70290931Srodrigcvoid 71290931Srodrigcyp_disable_events(void) 72290931Srodrigc{ 73290931Srodrigc struct yp_event *ye; 74290931Srodrigc 75290931Srodrigc while ((ye = TAILQ_FIRST(&env->sc_yp->yd_events)) != NULL) { 76290931Srodrigc TAILQ_REMOVE(&env->sc_yp->yd_events, ye, ye_entry); 77290931Srodrigc event_del(&ye->ye_event); 78290931Srodrigc free(ye); 79290931Srodrigc } 80290931Srodrigc} 81290931Srodrigc 82290931Srodrigcvoid 83290931Srodrigcyp_enable_events(void) 84290931Srodrigc{ 85290931Srodrigc int i; 86290931Srodrigc extern fd_set *__svc_fdset; 87290931Srodrigc extern int __svc_fdsetsize; 88290931Srodrigc struct yp_event *ye; 89290931Srodrigc 90290931Srodrigc for (i = 0; i < __svc_fdsetsize; i++) { 91290931Srodrigc if (FD_ISSET(i, __svc_fdset)) { 92290931Srodrigc if ((ye = calloc(1, sizeof(*ye))) == NULL) 93290931Srodrigc fatal(NULL); 94290931Srodrigc event_set(&ye->ye_event, i, EV_READ, yp_fd_event, NULL); 95290931Srodrigc event_add(&ye->ye_event, NULL); 96290931Srodrigc TAILQ_INSERT_TAIL(&env->sc_yp->yd_events, ye, ye_entry); 97290931Srodrigc } 98290931Srodrigc } 99290931Srodrigc} 100290931Srodrigc 101290931Srodrigcvoid 102290931Srodrigcyp_fd_event(int fd, short event, void *p) 103290931Srodrigc{ 104290931Srodrigc svc_getreq_common(fd); 105290931Srodrigc yp_disable_events(); 106290931Srodrigc yp_enable_events(); 107290931Srodrigc} 108290931Srodrigc 109290931Srodrigcvoid 110290931Srodrigcyp_init(struct env *x_env) 111290931Srodrigc{ 112290931Srodrigc struct yp_data *yp; 113290931Srodrigc 114290931Srodrigc if ((yp = calloc(1, sizeof(*yp))) == NULL) 115290931Srodrigc fatal(NULL); 116290931Srodrigc TAILQ_INIT(&yp->yd_events); 117290931Srodrigc 118290931Srodrigc env = x_env; 119290931Srodrigc env->sc_yp = yp; 120290931Srodrigc 121290931Srodrigc (void)pmap_unset(YPPROG, YPVERS); 122290931Srodrigc 123290931Srodrigc if ((yp->yp_trans_udp = svcudp_create(RPC_ANYSOCK)) == NULL) 124290931Srodrigc fatal("cannot create udp service"); 125290931Srodrigc if ((yp->yp_trans_tcp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) 126290931Srodrigc fatal("cannot create tcp service"); 127290931Srodrigc 128290931Srodrigc if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS, 129290931Srodrigc yp_dispatch, IPPROTO_UDP)) { 130290931Srodrigc fatal("unable to register (YPPROG, YPVERS, udp)"); 131290931Srodrigc } 132290931Srodrigc if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS, 133290931Srodrigc yp_dispatch, IPPROTO_TCP)) { 134290931Srodrigc fatal("unable to register (YPPROG, YPVERS, tcp)"); 135290931Srodrigc } 136290931Srodrigc} 137290931Srodrigc 138290931Srodrigc/* 139290931Srodrigc * lots of inspiration from ypserv by Mats O Jansson 140290931Srodrigc */ 141290931Srodrigcvoid 142290931Srodrigcyp_dispatch(struct svc_req *req, SVCXPRT *trans) 143290931Srodrigc{ 144290931Srodrigc xdrproc_t xdr_argument; 145290931Srodrigc xdrproc_t xdr_result; 146290931Srodrigc char *result; 147290931Srodrigc char *(*cb)(char *, struct svc_req *); 148290931Srodrigc union { 149290931Srodrigc domainname ypproc_domain_2_arg; 150290931Srodrigc domainname ypproc_domain_nonack_2_arg; 151290931Srodrigc ypreq_key ypproc_match_2_arg; 152290931Srodrigc ypreq_nokey ypproc_first_2_arg; 153290931Srodrigc ypreq_key ypproc_next_2_arg; 154290931Srodrigc ypreq_xfr ypproc_xfr_2_arg; 155290931Srodrigc ypreq_nokey ypproc_all_2_arg; 156290931Srodrigc ypreq_nokey ypproc_master_2_arg; 157290931Srodrigc ypreq_nokey ypproc_order_2_arg; 158290931Srodrigc domainname ypproc_maplist_2_arg; 159290931Srodrigc } argument; 160290931Srodrigc 161290931Srodrigc xdr_argument = (xdrproc_t) xdr_void; 162290931Srodrigc xdr_result = (xdrproc_t) xdr_void; 163290931Srodrigc cb = NULL; 164290931Srodrigc switch (req->rq_proc) { 165290931Srodrigc case YPPROC_NULL: 166290931Srodrigc xdr_argument = (xdrproc_t) xdr_void; 167290931Srodrigc xdr_result = (xdrproc_t) xdr_void; 168290931Srodrigc if (yp_check(req) == -1) 169290931Srodrigc return; 170290931Srodrigc result = NULL; 171290931Srodrigc if (!svc_sendreply(trans, (xdrproc_t) xdr_void, 172290931Srodrigc (void *)&result)) 173290931Srodrigc svcerr_systemerr(trans); 174290931Srodrigc return; 175290931Srodrigc case YPPROC_DOMAIN: 176290931Srodrigc xdr_argument = (xdrproc_t) xdr_domainname; 177290931Srodrigc xdr_result = (xdrproc_t) xdr_bool; 178290931Srodrigc if (yp_check(req) == -1) 179290931Srodrigc return; 180290931Srodrigc cb = (void *)ypproc_domain_2_svc; 181290931Srodrigc break; 182290931Srodrigc case YPPROC_DOMAIN_NONACK: 183290931Srodrigc xdr_argument = (xdrproc_t) xdr_domainname; 184290931Srodrigc xdr_result = (xdrproc_t) xdr_bool; 185290931Srodrigc if (yp_check(req) == -1) 186290931Srodrigc return; 187290931Srodrigc cb = (void *)ypproc_domain_nonack_2_svc; 188290931Srodrigc break; 189290931Srodrigc case YPPROC_MATCH: 190290931Srodrigc xdr_argument = (xdrproc_t) xdr_ypreq_key; 191290931Srodrigc xdr_result = (xdrproc_t) xdr_ypresp_val; 192290931Srodrigc if (yp_check(req) == -1) 193290931Srodrigc return; 194290931Srodrigc cb = (void *)ypproc_match_2_svc; 195290931Srodrigc break; 196290931Srodrigc case YPPROC_FIRST: 197290931Srodrigc xdr_argument = (xdrproc_t) xdr_ypreq_nokey; 198290931Srodrigc xdr_result = (xdrproc_t) xdr_ypresp_key_val; 199290931Srodrigc if (yp_check(req) == -1) 200290931Srodrigc return; 201290931Srodrigc cb = (void *)ypproc_first_2_svc; 202290931Srodrigc break; 203290931Srodrigc case YPPROC_NEXT: 204290931Srodrigc xdr_argument = (xdrproc_t) xdr_ypreq_key; 205290931Srodrigc xdr_result = (xdrproc_t) xdr_ypresp_key_val; 206290931Srodrigc if (yp_check(req) == -1) 207290931Srodrigc return; 208290931Srodrigc cb = (void *)ypproc_next_2_svc; 209290931Srodrigc break; 210290931Srodrigc case YPPROC_XFR: 211290931Srodrigc if (yp_check(req) == -1) 212290931Srodrigc return; 213290931Srodrigc svcerr_noproc(trans); 214290931Srodrigc return; 215290931Srodrigc case YPPROC_CLEAR: 216290931Srodrigc log_debug("ypproc_clear"); 217290931Srodrigc if (yp_check(req) == -1) 218290931Srodrigc return; 219290931Srodrigc svcerr_noproc(trans); 220290931Srodrigc return; 221290931Srodrigc case YPPROC_ALL: 222290931Srodrigc log_debug("ypproc_all"); 223290931Srodrigc if (yp_check(req) == -1) 224290931Srodrigc return; 225290931Srodrigc cb = (void *)ypproc_all_2_svc; 226290931Srodrigc break; 227290931Srodrigc case YPPROC_MASTER: 228290931Srodrigc log_debug("ypproc_master"); 229290931Srodrigc if (yp_check(req) == -1) 230290931Srodrigc return; 231290931Srodrigc cb = (void *)ypproc_master_2_svc; 232290931Srodrigc break; 233290931Srodrigc case YPPROC_ORDER: 234290931Srodrigc log_debug("ypproc_order"); 235290931Srodrigc if (yp_check(req) == -1) 236290931Srodrigc return; 237290931Srodrigc svcerr_noproc(trans); 238290931Srodrigc return; 239290931Srodrigc case YPPROC_MAPLIST: 240290931Srodrigc log_debug("ypproc_maplist"); 241290931Srodrigc if (yp_check(req) == -1) 242290931Srodrigc return; 243290931Srodrigc cb = (void *)ypproc_maplist_2_svc; 244290931Srodrigc break; 245290931Srodrigc default: 246290931Srodrigc svcerr_noproc(trans); 247290931Srodrigc return; 248290931Srodrigc } 249290931Srodrigc (void)memset(&argument, 0, sizeof(argument)); 250290931Srodrigc 251290931Srodrigc if (!svc_getargs(trans, xdr_argument, (caddr_t)&argument)) { 252290931Srodrigc svcerr_decode(trans); 253290931Srodrigc return; 254290931Srodrigc } 255290931Srodrigc result = (*cb)((char *)&argument, req); 256290931Srodrigc if (result != NULL && !svc_sendreply(trans, xdr_result, result)) 257290931Srodrigc svcerr_systemerr(trans); 258290931Srodrigc if (!svc_freeargs(trans, xdr_argument, (caddr_t)&argument)) { 259290931Srodrigc /* 260290931Srodrigc * ypserv does it too. 261290931Srodrigc */ 262290931Srodrigc fatal("unable to free arguments"); 263290931Srodrigc } 264290931Srodrigc} 265290931Srodrigc 266290931Srodrigcint 267290931Srodrigcyp_check(struct svc_req *req) 268290931Srodrigc{ 269290931Srodrigc struct sockaddr_in *caller; 270290931Srodrigc 271290931Srodrigc caller = svc_getcaller(req->rq_xprt); 272290931Srodrigc /* 273290931Srodrigc * We might want to know who we allow here. 274290931Srodrigc */ 275290931Srodrigc return (0); 276290931Srodrigc} 277290931Srodrigc 278290931Srodrigcint 279290931Srodrigcyp_valid_domain(char *domain, struct ypresp_val *res) 280290931Srodrigc{ 281290931Srodrigc if (domain == NULL) { 282290931Srodrigc log_debug("NULL domain !"); 283290931Srodrigc return (-1); 284290931Srodrigc } 285290931Srodrigc if (strcmp(domain, env->sc_domainname) != 0) { 286290931Srodrigc res->stat = YP_NODOM; 287290931Srodrigc return (-1); 288290931Srodrigc } 289290931Srodrigc return (0); 290290931Srodrigc} 291290931Srodrigc 292290931Srodrigcbool_t * 293290931Srodrigcypproc_domain_2_svc(domainname *arg, struct svc_req *req) 294290931Srodrigc{ 295290931Srodrigc static bool_t res; 296290931Srodrigc 297290931Srodrigc res = (bool_t)1; 298290931Srodrigc if (strcmp(*arg, env->sc_domainname) != 0) 299290931Srodrigc res = (bool_t)0; 300290931Srodrigc return (&res); 301290931Srodrigc} 302290931Srodrigc 303290931Srodrigcbool_t * 304290931Srodrigcypproc_domain_nonack_2_svc(domainname *arg, struct svc_req *req) 305290931Srodrigc{ 306290931Srodrigc static bool_t res; 307290931Srodrigc 308290931Srodrigc if (strcmp(*arg, env->sc_domainname) != 0) 309290931Srodrigc return NULL; 310290931Srodrigc res = (bool_t)1; 311290931Srodrigc return (&res); 312290931Srodrigc} 313290931Srodrigc 314290931Srodrigcypresp_val * 315290931Srodrigcypproc_match_2_svc(ypreq_key *arg, struct svc_req *req) 316290931Srodrigc{ 317290931Srodrigc struct userent ukey; 318290931Srodrigc struct userent *ue; 319290931Srodrigc struct groupent gkey; 320290931Srodrigc struct groupent *ge; 321290931Srodrigc static struct ypresp_val res; 322290931Srodrigc const char *estr; 323290931Srodrigc char *bp, *cp; 324290931Srodrigc char key[YPMAXRECORD+1]; 325290931Srodrigc 326290931Srodrigc log_debug("matching '%.*s' in map %s", arg->key.keydat_len, 327290931Srodrigc arg->key.keydat_val, arg->map); 328290931Srodrigc 329290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 330290931Srodrigc return (&res); 331290931Srodrigc 332290931Srodrigc if (env->sc_user_names == NULL) { 333290931Srodrigc /* 334290931Srodrigc * tree not ready. 335290931Srodrigc */ 336290931Srodrigc return (NULL); 337290931Srodrigc } 338290931Srodrigc 339290931Srodrigc if (arg->key.keydat_len > YPMAXRECORD) { 340290931Srodrigc log_debug("argument too long"); 341290931Srodrigc return (NULL); 342290931Srodrigc } 343290931Srodrigc bzero(key, sizeof(key)); 344290931Srodrigc (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len); 345290931Srodrigc 346290931Srodrigc if (strcmp(arg->map, "passwd.byname") == 0 || 347290931Srodrigc strcmp(arg->map, "master.passwd.byname") == 0) { 348290931Srodrigc ukey.ue_line = key; 349290931Srodrigc if ((ue = RB_FIND(user_name_tree, env->sc_user_names, 350290931Srodrigc &ukey)) == NULL) { 351290931Srodrigc res.stat = YP_NOKEY; 352290931Srodrigc return (&res); 353290931Srodrigc } 354290931Srodrigc 355290931Srodrigc yp_make_val(&res, ue->ue_line, 1); 356290931Srodrigc return (&res); 357290931Srodrigc } else if (strcmp(arg->map, "passwd.byuid") == 0 || 358290931Srodrigc strcmp(arg->map, "master.passwd.byuid") == 0) { 359290931Srodrigc ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr); 360290931Srodrigc if (estr) { 361290931Srodrigc res.stat = YP_BADARGS; 362290931Srodrigc return (&res); 363290931Srodrigc } 364290931Srodrigc 365290931Srodrigc if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids, 366290931Srodrigc &ukey)) == NULL) { 367290931Srodrigc res.stat = YP_NOKEY; 368290931Srodrigc return (&res); 369290931Srodrigc } 370290931Srodrigc 371290931Srodrigc yp_make_val(&res, ue->ue_line, 1); 372290931Srodrigc return (&res); 373290931Srodrigc } else if (strcmp(arg->map, "group.bygid") == 0) { 374290931Srodrigc gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr); 375290931Srodrigc if (estr) { 376290931Srodrigc res.stat = YP_BADARGS; 377290931Srodrigc return (&res); 378290931Srodrigc } 379290931Srodrigc if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids, 380290931Srodrigc &gkey)) == NULL) { 381290931Srodrigc res.stat = YP_NOKEY; 382290931Srodrigc return (&res); 383290931Srodrigc } 384290931Srodrigc 385290931Srodrigc yp_make_val(&res, ge->ge_line, 1); 386290931Srodrigc return (&res); 387290931Srodrigc } else if (strcmp(arg->map, "group.byname") == 0) { 388290931Srodrigc gkey.ge_line = key; 389290931Srodrigc if ((ge = RB_FIND(group_name_tree, env->sc_group_names, 390290931Srodrigc &gkey)) == NULL) { 391290931Srodrigc res.stat = YP_NOKEY; 392290931Srodrigc return (&res); 393290931Srodrigc } 394290931Srodrigc 395290931Srodrigc yp_make_val(&res, ge->ge_line, 1); 396290931Srodrigc return (&res); 397290931Srodrigc } else if (strcmp(arg->map, "netid.byname") == 0) { 398290931Srodrigc bp = cp = key; 399290931Srodrigc 400290931Srodrigc if (strncmp(bp, "unix.", strlen("unix.")) != 0) { 401290931Srodrigc res.stat = YP_BADARGS; 402290931Srodrigc return (&res); 403290931Srodrigc } 404290931Srodrigc 405290931Srodrigc bp += strlen("unix."); 406290931Srodrigc 407290931Srodrigc if (*bp == '\0') { 408290931Srodrigc res.stat = YP_BADARGS; 409290931Srodrigc return (&res); 410290931Srodrigc } 411290931Srodrigc 412290931Srodrigc if (!(cp = strsep(&bp, "@"))) { 413290931Srodrigc res.stat = YP_BADARGS; 414290931Srodrigc return (&res); 415290931Srodrigc } 416290931Srodrigc 417290931Srodrigc if (strcmp(bp, arg->domain) != 0) { 418290931Srodrigc res.stat = YP_BADARGS; 419290931Srodrigc return (&res); 420290931Srodrigc } 421290931Srodrigc 422290931Srodrigc ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr); 423290931Srodrigc if (estr) { 424290931Srodrigc res.stat = YP_BADARGS; 425290931Srodrigc return (&res); 426290931Srodrigc } 427290931Srodrigc 428290931Srodrigc if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids, 429290931Srodrigc &ukey)) == NULL) { 430290931Srodrigc res.stat = YP_NOKEY; 431290931Srodrigc return (&res); 432290931Srodrigc } 433290931Srodrigc 434290931Srodrigc yp_make_val(&res, ue->ue_netid_line, 0); 435290931Srodrigc return (&res); 436290931Srodrigc 437290931Srodrigc } else { 438290931Srodrigc log_debug("unknown map %s", arg->map); 439290931Srodrigc res.stat = YP_NOMAP; 440290931Srodrigc return (&res); 441290931Srodrigc } 442290931Srodrigc} 443290931Srodrigc 444290931Srodrigcypresp_key_val * 445290931Srodrigcypproc_first_2_svc(ypreq_nokey *arg, struct svc_req *req) 446290931Srodrigc{ 447290931Srodrigc static struct ypresp_key_val res; 448290931Srodrigc 449290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 450290931Srodrigc return (&res); 451290931Srodrigc 452290931Srodrigc if (strcmp(arg->map, "passwd.byname") == 0 || 453290931Srodrigc strcmp(arg->map, "master.passwd.byname") == 0) { 454290931Srodrigc if (env->sc_user_lines == NULL) 455290931Srodrigc return (NULL); 456290931Srodrigc 457290931Srodrigc yp_make_keyval(&res, env->sc_user_lines, env->sc_user_lines); 458290931Srodrigc } else if (strcmp(arg->map, "group.byname") == 0) { 459290931Srodrigc if (env->sc_group_lines == NULL) 460290931Srodrigc return (NULL); 461290931Srodrigc 462290931Srodrigc yp_make_keyval(&res, env->sc_group_lines, env->sc_group_lines); 463290931Srodrigc } else { 464290931Srodrigc log_debug("unknown map %s", arg->map); 465290931Srodrigc res.stat = YP_NOMAP; 466290931Srodrigc } 467290931Srodrigc 468290931Srodrigc return (&res); 469290931Srodrigc} 470290931Srodrigc 471290931Srodrigcypresp_key_val * 472290931Srodrigcypproc_next_2_svc(ypreq_key *arg, struct svc_req *req) 473290931Srodrigc{ 474290931Srodrigc struct userent ukey; 475290931Srodrigc struct userent *ue; 476290931Srodrigc struct groupent gkey; 477290931Srodrigc struct groupent *ge; 478290931Srodrigc char *line; 479290931Srodrigc static struct ypresp_key_val res; 480290931Srodrigc char key[YPMAXRECORD+1]; 481290931Srodrigc 482290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 483290931Srodrigc return (&res); 484290931Srodrigc 485290931Srodrigc if (strcmp(arg->map, "passwd.byname") == 0 || 486290931Srodrigc strcmp(arg->map, "master.passwd.byname") == 0) { 487290931Srodrigc bzero(key, sizeof(key)); 488290931Srodrigc (void)strncpy(key, arg->key.keydat_val, 489290931Srodrigc arg->key.keydat_len); 490290931Srodrigc ukey.ue_line = key; 491290931Srodrigc if ((ue = RB_FIND(user_name_tree, env->sc_user_names, 492290931Srodrigc &ukey)) == NULL) { 493290931Srodrigc /* 494290931Srodrigc * canacar's trick: 495290931Srodrigc * the user might have been deleted in between calls 496290931Srodrigc * to next since the tree may be modified by a reload. 497290931Srodrigc * next should still return the next user in 498290931Srodrigc * lexicographical order, hence insert the search key 499290931Srodrigc * and look up the next field, then remove it again. 500290931Srodrigc */ 501290931Srodrigc RB_INSERT(user_name_tree, env->sc_user_names, &ukey); 502290931Srodrigc if ((ue = RB_NEXT(user_name_tree, &env->sc_user_names, 503290931Srodrigc &ukey)) == NULL) { 504290931Srodrigc RB_REMOVE(user_name_tree, env->sc_user_names, 505290931Srodrigc &ukey); 506290931Srodrigc res.stat = YP_NOKEY; 507290931Srodrigc return (&res); 508290931Srodrigc } 509290931Srodrigc RB_REMOVE(user_name_tree, env->sc_user_names, &ukey); 510290931Srodrigc } 511290931Srodrigc line = ue->ue_line + (strlen(ue->ue_line) + 1); 512290931Srodrigc line = line + (strlen(line) + 1); 513290931Srodrigc yp_make_keyval(&res, line, line); 514290931Srodrigc return (&res); 515290931Srodrigc 516290931Srodrigc 517290931Srodrigc } else if (strcmp(arg->map, "group.byname") == 0) { 518290931Srodrigc bzero(key, sizeof(key)); 519290931Srodrigc (void)strncpy(key, arg->key.keydat_val, 520290931Srodrigc arg->key.keydat_len); 521290931Srodrigc 522290931Srodrigc gkey.ge_line = key; 523290931Srodrigc if ((ge = RB_FIND(group_name_tree, env->sc_group_names, 524290931Srodrigc &gkey)) == NULL) { 525290931Srodrigc /* 526290931Srodrigc * canacar's trick reloaded. 527290931Srodrigc */ 528290931Srodrigc RB_INSERT(group_name_tree, env->sc_group_names, &gkey); 529290931Srodrigc if ((ge = RB_NEXT(group_name_tree, &env->sc_group_names, 530290931Srodrigc &gkey)) == NULL) { 531290931Srodrigc RB_REMOVE(group_name_tree, env->sc_group_names, 532290931Srodrigc &gkey); 533290931Srodrigc res.stat = YP_NOKEY; 534290931Srodrigc return (&res); 535290931Srodrigc } 536290931Srodrigc RB_REMOVE(group_name_tree, env->sc_group_names, &gkey); 537290931Srodrigc } 538290931Srodrigc 539290931Srodrigc line = ge->ge_line + (strlen(ge->ge_line) + 1); 540290931Srodrigc line = line + (strlen(line) + 1); 541290931Srodrigc yp_make_keyval(&res, line, line); 542290931Srodrigc return (&res); 543290931Srodrigc } else { 544290931Srodrigc log_debug("unknown map %s", arg->map); 545290931Srodrigc res.stat = YP_NOMAP; 546290931Srodrigc return (&res); 547290931Srodrigc } 548290931Srodrigc} 549290931Srodrigc 550290931Srodrigcypresp_all * 551290931Srodrigcypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req) 552290931Srodrigc{ 553290931Srodrigc static struct ypresp_all res; 554290931Srodrigc 555290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 556290931Srodrigc return (&res); 557290931Srodrigc 558290931Srodrigc svcerr_auth(req->rq_xprt, AUTH_FAILED); 559290931Srodrigc return (NULL); 560290931Srodrigc} 561290931Srodrigc 562290931Srodrigcypresp_master * 563290931Srodrigcypproc_master_2_svc(ypreq_nokey *arg, struct svc_req *req) 564290931Srodrigc{ 565290931Srodrigc static struct ypresp_master res; 566290931Srodrigc 567290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 568290931Srodrigc return (&res); 569290931Srodrigc 570290931Srodrigc res.stat = YP_YPERR; 571290931Srodrigc return (&res); 572290931Srodrigc} 573290931Srodrigc 574290931Srodrigcypresp_maplist * 575290931Srodrigcypproc_maplist_2_svc(domainname *arg, struct svc_req *req) 576290931Srodrigc{ 577290931Srodrigc size_t i; 578290931Srodrigc static struct { 579290931Srodrigc char *name; 580290931Srodrigc int cond; 581290931Srodrigc } mapnames[] = { 582290931Srodrigc { "passwd.byname", YPMAP_PASSWD_BYNAME }, 583290931Srodrigc { "passwd.byuid", YPMAP_PASSWD_BYUID }, 584290931Srodrigc { "master.passwd.byname", YPMAP_MASTER_PASSWD_BYNAME }, 585290931Srodrigc { "master.passwd.byuid", YPMAP_MASTER_PASSWD_BYUID }, 586290931Srodrigc { "group.byname", YPMAP_GROUP_BYNAME }, 587290931Srodrigc { "group.bygid", YPMAP_GROUP_BYGID }, 588290931Srodrigc { "netid.byname", YPMAP_NETID_BYNAME }, 589290931Srodrigc }; 590290931Srodrigc static ypresp_maplist res; 591290931Srodrigc static struct ypmaplist maps[sizeof(mapnames) / sizeof(mapnames[0])]; 592290931Srodrigc 593290931Srodrigc if (yp_valid_domain(*arg, (struct ypresp_val *)&res) == -1) 594290931Srodrigc return (&res); 595290931Srodrigc 596290931Srodrigc res.stat = YP_TRUE; 597290931Srodrigc res.maps = NULL; 598290931Srodrigc for (i = 0; i < sizeof(mapnames) / sizeof(mapnames[0]); i++) { 599290931Srodrigc if (!(env->sc_flags & mapnames[i].cond)) 600290931Srodrigc continue; 601290931Srodrigc maps[i].map = mapnames[i].name; 602290931Srodrigc maps[i].next = res.maps; 603290931Srodrigc res.maps = &maps[i]; 604290931Srodrigc } 605290931Srodrigc 606290931Srodrigc return (&res); 607290931Srodrigc} 608290931Srodrigc 609290931Srodrigcvoid 610290931Srodrigcyp_make_val(struct ypresp_val *res, char *line, int replacecolon) 611290931Srodrigc{ 612290931Srodrigc static char buf[LINE_WIDTH]; 613290931Srodrigc 614290931Srodrigc bzero(buf, sizeof(buf)); 615290931Srodrigc 616290931Srodrigc if (replacecolon) 617290931Srodrigc line[strlen(line)] = ':'; 618290931Srodrigc (void)strlcpy(buf, line, sizeof(buf)); 619290931Srodrigc if (replacecolon) 620290931Srodrigc line[strcspn(line, ":")] = '\0'; 621290931Srodrigc log_debug("sending out %s", buf); 622290931Srodrigc 623290931Srodrigc res->stat = YP_TRUE; 624290931Srodrigc res->val.valdat_len = strlen(buf); 625290931Srodrigc res->val.valdat_val = buf; 626290931Srodrigc} 627290931Srodrigc 628290931Srodrigcvoid 629290931Srodrigcyp_make_keyval(struct ypresp_key_val *res, char *key, char *line) 630290931Srodrigc{ 631290931Srodrigc static char keybuf[YPMAXRECORD+1]; 632290931Srodrigc static char buf[LINE_WIDTH]; 633290931Srodrigc 634290931Srodrigc bzero(keybuf, sizeof(keybuf)); 635290931Srodrigc bzero(buf, sizeof(buf)); 636290931Srodrigc 637290931Srodrigc (void)strlcpy(keybuf, key, sizeof(keybuf)); 638290931Srodrigc res->key.keydat_len = strlen(keybuf); 639290931Srodrigc res->key.keydat_val = keybuf; 640290931Srodrigc 641290931Srodrigc if (*line == '\0') { 642290931Srodrigc res->stat = YP_NOMORE; 643290931Srodrigc return; 644290931Srodrigc } 645290931Srodrigc res->stat = YP_TRUE; 646290931Srodrigc line[strlen(line)] = ':'; 647290931Srodrigc (void)strlcpy(buf, line, sizeof(buf)); 648290931Srodrigc line[strcspn(line, ":")] = '\0'; 649290931Srodrigc log_debug("sending out %s => %s", keybuf, buf); 650290931Srodrigc 651290931Srodrigc res->val.valdat_len = strlen(buf); 652290931Srodrigc res->val.valdat_val = buf; 653290931Srodrigc} 654