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