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