1290931Srodrigc/* $OpenBSD: yp.c,v 1.14 2015/02/11 01:26:00 pelikan Exp $ */ 2290931Srodrigc/* $FreeBSD: stable/11/usr.sbin/ypldap/yp.c 351694 2019-09-02 10:20:57Z kib $ */ 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; 326351694Skib char *key; 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 } 345351694Skib key = calloc(arg->key.keydat_len + 1, 1); 346351694Skib if (key == NULL) 347351694Skib return (NULL); 348290931Srodrigc (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len); 349290931Srodrigc 350290931Srodrigc if (strcmp(arg->map, "passwd.byname") == 0 || 351290931Srodrigc strcmp(arg->map, "master.passwd.byname") == 0) { 352290931Srodrigc ukey.ue_line = key; 353290931Srodrigc if ((ue = RB_FIND(user_name_tree, env->sc_user_names, 354290931Srodrigc &ukey)) == NULL) { 355290931Srodrigc res.stat = YP_NOKEY; 356351694Skib goto out; 357290931Srodrigc } 358290931Srodrigc 359290931Srodrigc yp_make_val(&res, ue->ue_line, 1); 360351694Skib goto out; 361290931Srodrigc } else if (strcmp(arg->map, "passwd.byuid") == 0 || 362290931Srodrigc strcmp(arg->map, "master.passwd.byuid") == 0) { 363290931Srodrigc ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr); 364290931Srodrigc if (estr) { 365290931Srodrigc res.stat = YP_BADARGS; 366351694Skib goto out; 367290931Srodrigc } 368290931Srodrigc 369290931Srodrigc if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids, 370290931Srodrigc &ukey)) == NULL) { 371290931Srodrigc res.stat = YP_NOKEY; 372351694Skib goto out; 373290931Srodrigc } 374290931Srodrigc 375290931Srodrigc yp_make_val(&res, ue->ue_line, 1); 376290931Srodrigc return (&res); 377290931Srodrigc } else if (strcmp(arg->map, "group.bygid") == 0) { 378290931Srodrigc gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr); 379290931Srodrigc if (estr) { 380290931Srodrigc res.stat = YP_BADARGS; 381351694Skib goto out; 382290931Srodrigc } 383290931Srodrigc if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids, 384290931Srodrigc &gkey)) == NULL) { 385290931Srodrigc res.stat = YP_NOKEY; 386351694Skib goto out; 387290931Srodrigc } 388290931Srodrigc 389290931Srodrigc yp_make_val(&res, ge->ge_line, 1); 390290931Srodrigc return (&res); 391290931Srodrigc } else if (strcmp(arg->map, "group.byname") == 0) { 392290931Srodrigc gkey.ge_line = key; 393290931Srodrigc if ((ge = RB_FIND(group_name_tree, env->sc_group_names, 394290931Srodrigc &gkey)) == NULL) { 395290931Srodrigc res.stat = YP_NOKEY; 396351694Skib goto out; 397290931Srodrigc } 398290931Srodrigc 399290931Srodrigc yp_make_val(&res, ge->ge_line, 1); 400290931Srodrigc return (&res); 401290931Srodrigc } else if (strcmp(arg->map, "netid.byname") == 0) { 402290931Srodrigc bp = cp = key; 403290931Srodrigc 404290931Srodrigc if (strncmp(bp, "unix.", strlen("unix.")) != 0) { 405290931Srodrigc res.stat = YP_BADARGS; 406351694Skib goto out; 407290931Srodrigc } 408290931Srodrigc 409290931Srodrigc bp += strlen("unix."); 410290931Srodrigc 411290931Srodrigc if (*bp == '\0') { 412290931Srodrigc res.stat = YP_BADARGS; 413351694Skib goto out; 414290931Srodrigc } 415290931Srodrigc 416290931Srodrigc if (!(cp = strsep(&bp, "@"))) { 417290931Srodrigc res.stat = YP_BADARGS; 418351694Skib goto out; 419290931Srodrigc } 420290931Srodrigc 421290931Srodrigc if (strcmp(bp, arg->domain) != 0) { 422290931Srodrigc res.stat = YP_BADARGS; 423351694Skib goto out; 424290931Srodrigc } 425290931Srodrigc 426290931Srodrigc ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr); 427290931Srodrigc if (estr) { 428290931Srodrigc res.stat = YP_BADARGS; 429351694Skib goto out; 430290931Srodrigc } 431290931Srodrigc 432290931Srodrigc if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids, 433290931Srodrigc &ukey)) == NULL) { 434290931Srodrigc res.stat = YP_NOKEY; 435351694Skib goto out; 436290931Srodrigc } 437290931Srodrigc 438290931Srodrigc yp_make_val(&res, ue->ue_netid_line, 0); 439351694Skib goto out; 440290931Srodrigc 441290931Srodrigc } else { 442290931Srodrigc log_debug("unknown map %s", arg->map); 443290931Srodrigc res.stat = YP_NOMAP; 444351694Skib goto out; 445290931Srodrigc } 446351694Skibout: 447351694Skib free(key); 448351694Skib return (&res); 449290931Srodrigc} 450290931Srodrigc 451290931Srodrigcypresp_key_val * 452290931Srodrigcypproc_first_2_svc(ypreq_nokey *arg, struct svc_req *req) 453290931Srodrigc{ 454290931Srodrigc static struct ypresp_key_val res; 455290931Srodrigc 456290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 457290931Srodrigc return (&res); 458290931Srodrigc 459290931Srodrigc if (strcmp(arg->map, "passwd.byname") == 0 || 460290931Srodrigc strcmp(arg->map, "master.passwd.byname") == 0) { 461290931Srodrigc if (env->sc_user_lines == NULL) 462290931Srodrigc return (NULL); 463290931Srodrigc 464290931Srodrigc yp_make_keyval(&res, env->sc_user_lines, env->sc_user_lines); 465290931Srodrigc } else if (strcmp(arg->map, "group.byname") == 0) { 466290931Srodrigc if (env->sc_group_lines == NULL) 467290931Srodrigc return (NULL); 468290931Srodrigc 469290931Srodrigc yp_make_keyval(&res, env->sc_group_lines, env->sc_group_lines); 470290931Srodrigc } else { 471290931Srodrigc log_debug("unknown map %s", arg->map); 472290931Srodrigc res.stat = YP_NOMAP; 473290931Srodrigc } 474290931Srodrigc 475290931Srodrigc return (&res); 476290931Srodrigc} 477290931Srodrigc 478290931Srodrigcypresp_key_val * 479290931Srodrigcypproc_next_2_svc(ypreq_key *arg, struct svc_req *req) 480290931Srodrigc{ 481290931Srodrigc struct userent ukey; 482290931Srodrigc struct userent *ue; 483290931Srodrigc struct groupent gkey; 484290931Srodrigc struct groupent *ge; 485290931Srodrigc char *line; 486290931Srodrigc static struct ypresp_key_val res; 487351694Skib char *key; 488290931Srodrigc 489290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 490290931Srodrigc return (&res); 491290931Srodrigc 492351694Skib key = NULL; 493290931Srodrigc if (strcmp(arg->map, "passwd.byname") == 0 || 494290931Srodrigc strcmp(arg->map, "master.passwd.byname") == 0) { 495351694Skib key = calloc(arg->key.keydat_len + 1, 1); 496351694Skib if (key == NULL) { 497351694Skib res.stat = YP_YPERR; 498351694Skib return (&res); 499351694Skib } 500290931Srodrigc (void)strncpy(key, arg->key.keydat_val, 501290931Srodrigc arg->key.keydat_len); 502290931Srodrigc ukey.ue_line = key; 503290931Srodrigc if ((ue = RB_FIND(user_name_tree, env->sc_user_names, 504290931Srodrigc &ukey)) == NULL) { 505290931Srodrigc /* 506290931Srodrigc * canacar's trick: 507290931Srodrigc * the user might have been deleted in between calls 508290931Srodrigc * to next since the tree may be modified by a reload. 509290931Srodrigc * next should still return the next user in 510290931Srodrigc * lexicographical order, hence insert the search key 511290931Srodrigc * and look up the next field, then remove it again. 512290931Srodrigc */ 513290931Srodrigc RB_INSERT(user_name_tree, env->sc_user_names, &ukey); 514290931Srodrigc if ((ue = RB_NEXT(user_name_tree, &env->sc_user_names, 515290931Srodrigc &ukey)) == NULL) { 516290931Srodrigc RB_REMOVE(user_name_tree, env->sc_user_names, 517290931Srodrigc &ukey); 518290931Srodrigc res.stat = YP_NOKEY; 519351694Skib free(key); 520290931Srodrigc return (&res); 521290931Srodrigc } 522290931Srodrigc RB_REMOVE(user_name_tree, env->sc_user_names, &ukey); 523290931Srodrigc } 524290931Srodrigc line = ue->ue_line + (strlen(ue->ue_line) + 1); 525290931Srodrigc line = line + (strlen(line) + 1); 526290931Srodrigc yp_make_keyval(&res, line, line); 527351694Skib free(key); 528290931Srodrigc return (&res); 529290931Srodrigc 530290931Srodrigc 531290931Srodrigc } else if (strcmp(arg->map, "group.byname") == 0) { 532351694Skib key = calloc(arg->key.keydat_len + 1, 1); 533351694Skib if (key == NULL) { 534351694Skib res.stat = YP_YPERR; 535351694Skib return (&res); 536351694Skib } 537290931Srodrigc (void)strncpy(key, arg->key.keydat_val, 538290931Srodrigc arg->key.keydat_len); 539290931Srodrigc 540290931Srodrigc gkey.ge_line = key; 541290931Srodrigc if ((ge = RB_FIND(group_name_tree, env->sc_group_names, 542290931Srodrigc &gkey)) == NULL) { 543290931Srodrigc /* 544290931Srodrigc * canacar's trick reloaded. 545290931Srodrigc */ 546290931Srodrigc RB_INSERT(group_name_tree, env->sc_group_names, &gkey); 547290931Srodrigc if ((ge = RB_NEXT(group_name_tree, &env->sc_group_names, 548290931Srodrigc &gkey)) == NULL) { 549290931Srodrigc RB_REMOVE(group_name_tree, env->sc_group_names, 550290931Srodrigc &gkey); 551290931Srodrigc res.stat = YP_NOKEY; 552351694Skib free(key); 553290931Srodrigc return (&res); 554290931Srodrigc } 555290931Srodrigc RB_REMOVE(group_name_tree, env->sc_group_names, &gkey); 556290931Srodrigc } 557290931Srodrigc 558290931Srodrigc line = ge->ge_line + (strlen(ge->ge_line) + 1); 559290931Srodrigc line = line + (strlen(line) + 1); 560290931Srodrigc yp_make_keyval(&res, line, line); 561351694Skib free(key); 562290931Srodrigc return (&res); 563290931Srodrigc } else { 564290931Srodrigc log_debug("unknown map %s", arg->map); 565290931Srodrigc res.stat = YP_NOMAP; 566290931Srodrigc return (&res); 567290931Srodrigc } 568290931Srodrigc} 569290931Srodrigc 570290931Srodrigcypresp_all * 571290931Srodrigcypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req) 572290931Srodrigc{ 573290931Srodrigc static struct ypresp_all res; 574290931Srodrigc 575290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 576290931Srodrigc return (&res); 577290931Srodrigc 578290931Srodrigc svcerr_auth(req->rq_xprt, AUTH_FAILED); 579290931Srodrigc return (NULL); 580290931Srodrigc} 581290931Srodrigc 582290931Srodrigcypresp_master * 583290931Srodrigcypproc_master_2_svc(ypreq_nokey *arg, struct svc_req *req) 584290931Srodrigc{ 585290931Srodrigc static struct ypresp_master res; 586296376Saraujo static char master[YPMAXPEER + 1]; 587290931Srodrigc 588309872Saraujo memset(&res, 0, sizeof(res)); 589290931Srodrigc if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) 590290931Srodrigc return (&res); 591296376Saraujo 592296376Saraujo if (gethostname(master, sizeof(master)) == 0) { 593296376Saraujo res.peer = (peername)master; 594296376Saraujo res.stat = YP_TRUE; 595296376Saraujo } else 596296376Saraujo res.stat = YP_NOKEY; 597290931Srodrigc 598290931Srodrigc return (&res); 599290931Srodrigc} 600290931Srodrigc 601290931Srodrigcypresp_maplist * 602290931Srodrigcypproc_maplist_2_svc(domainname *arg, struct svc_req *req) 603290931Srodrigc{ 604290931Srodrigc size_t i; 605290931Srodrigc static struct { 606290931Srodrigc char *name; 607290931Srodrigc int cond; 608290931Srodrigc } mapnames[] = { 609290931Srodrigc { "passwd.byname", YPMAP_PASSWD_BYNAME }, 610290931Srodrigc { "passwd.byuid", YPMAP_PASSWD_BYUID }, 611290931Srodrigc { "master.passwd.byname", YPMAP_MASTER_PASSWD_BYNAME }, 612290931Srodrigc { "master.passwd.byuid", YPMAP_MASTER_PASSWD_BYUID }, 613290931Srodrigc { "group.byname", YPMAP_GROUP_BYNAME }, 614290931Srodrigc { "group.bygid", YPMAP_GROUP_BYGID }, 615290931Srodrigc { "netid.byname", YPMAP_NETID_BYNAME }, 616290931Srodrigc }; 617290931Srodrigc static ypresp_maplist res; 618298177Saraujo static struct ypmaplist maps[nitems(mapnames)]; 619290931Srodrigc 620290931Srodrigc if (yp_valid_domain(*arg, (struct ypresp_val *)&res) == -1) 621290931Srodrigc return (&res); 622290931Srodrigc 623290931Srodrigc res.stat = YP_TRUE; 624290931Srodrigc res.maps = NULL; 625298177Saraujo for (i = 0; i < nitems(mapnames); i++) { 626290931Srodrigc if (!(env->sc_flags & mapnames[i].cond)) 627290931Srodrigc continue; 628290931Srodrigc maps[i].map = mapnames[i].name; 629290931Srodrigc maps[i].next = res.maps; 630290931Srodrigc res.maps = &maps[i]; 631290931Srodrigc } 632290931Srodrigc 633290931Srodrigc return (&res); 634290931Srodrigc} 635290931Srodrigc 636290931Srodrigcvoid 637290931Srodrigcyp_make_val(struct ypresp_val *res, char *line, int replacecolon) 638290931Srodrigc{ 639290931Srodrigc static char buf[LINE_WIDTH]; 640290931Srodrigc 641309872Saraujo memset(buf, 0, sizeof(buf)); 642290931Srodrigc 643290931Srodrigc if (replacecolon) 644290931Srodrigc line[strlen(line)] = ':'; 645290931Srodrigc (void)strlcpy(buf, line, sizeof(buf)); 646290931Srodrigc if (replacecolon) 647290931Srodrigc line[strcspn(line, ":")] = '\0'; 648290931Srodrigc log_debug("sending out %s", buf); 649290931Srodrigc 650290931Srodrigc res->stat = YP_TRUE; 651290931Srodrigc res->val.valdat_len = strlen(buf); 652290931Srodrigc res->val.valdat_val = buf; 653290931Srodrigc} 654290931Srodrigc 655290931Srodrigcvoid 656290931Srodrigcyp_make_keyval(struct ypresp_key_val *res, char *key, char *line) 657290931Srodrigc{ 658290931Srodrigc static char keybuf[YPMAXRECORD+1]; 659290931Srodrigc static char buf[LINE_WIDTH]; 660290931Srodrigc 661309872Saraujo memset(keybuf, 0, sizeof(keybuf)); 662309872Saraujo memset(buf, 0, sizeof(buf)); 663290931Srodrigc 664290931Srodrigc (void)strlcpy(keybuf, key, sizeof(keybuf)); 665290931Srodrigc res->key.keydat_len = strlen(keybuf); 666290931Srodrigc res->key.keydat_val = keybuf; 667290931Srodrigc 668290931Srodrigc if (*line == '\0') { 669290931Srodrigc res->stat = YP_NOMORE; 670290931Srodrigc return; 671290931Srodrigc } 672290931Srodrigc res->stat = YP_TRUE; 673290931Srodrigc line[strlen(line)] = ':'; 674290931Srodrigc (void)strlcpy(buf, line, sizeof(buf)); 675290931Srodrigc line[strcspn(line, ":")] = '\0'; 676290931Srodrigc log_debug("sending out %s => %s", keybuf, buf); 677290931Srodrigc 678290931Srodrigc res->val.valdat_len = strlen(buf); 679290931Srodrigc res->val.valdat_val = buf; 680290931Srodrigc} 681