Index: yp.c =================================================================== RCS file: /cvs/src/usr.sbin/ypldap/yp.c,v retrieving revision 1.14 diff -u -p -r1.14 yp.c --- yp.c 11 Feb 2015 01:26:00 -0000 1.14 +++ yp.c 12 Feb 2015 02:21:09 -0000 @@ -51,6 +51,7 @@ int yp_check(struct svc_req *); int yp_valid_domain(char *, struct ypresp_val *); void yp_make_val(struct ypresp_val *, char *, int); void yp_make_keyval(struct ypresp_key_val *, char *, char *); +bool_t ypdb_xdr_get_all(XDR *xdrs, ypreq_nokey *req); static struct env *env; @@ -218,6 +219,8 @@ yp_dispatch(struct svc_req *req, SVCXPRT return; case YPPROC_ALL: log_debug("ypproc_all"); + xdr_argument = (xdrproc_t) xdr_ypreq_nokey; + xdr_result = (xdrproc_t) ypdb_xdr_get_all; if (yp_check(req) == -1) return; cb = (void *)ypproc_all_2_svc; @@ -548,13 +551,175 @@ ypproc_next_2_svc(ypreq_key *arg, struct ypresp_all * ypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req) { - static struct ypresp_all res; + struct ypresp_val fake; - if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) - return (&res); + if (yp_valid_domain(arg->domain, &fake) == -1) + return (NULL); + if (strcmp(arg->map, "passwd.byname") && + strcmp(arg->map, "passwd.byuid") && + strcmp(arg->map, "group.byname") && + strcmp(arg->map, "group.bygid") && + strcmp(arg->map, "netid.byname")) { + return (NULL); + } + return ((void *) arg); +} - svcerr_auth(req->rq_xprt, AUTH_FAILED); - return (NULL); +static bool_t +ypdb_xdr_get_all_passwd(XDR *xdrs, struct ypresp_all *resp, int byname) +{ + static char key[YPMAXRECORD + 1]; + struct userent *ue; + + RB_FOREACH(ue, user_name_tree, env->sc_user_names) { + size_t len, keylen = strlen(ue->ue_line); + + resp->more = TRUE; + resp->ypresp_all_u.val.stat = TRUE; + + if (byname) { + strlcpy(key, ue->ue_line, sizeof key); + resp->ypresp_all_u.val.key.keydat_val = key; + resp->ypresp_all_u.val.key.keydat_len = keylen; + } + else { + int kl = snprintf(key, sizeof key, "%u", ue->ue_uid); + + if (kl < 0) { + log_warnx("%s: key too long", __func__); + return FALSE; + } + resp->ypresp_all_u.val.key.keydat_val = key; + resp->ypresp_all_u.val.key.keydat_len = kl; + } + + ue->ue_line[keylen] = ':'; + len = strnlen(ue->ue_line, YPMAXRECORD); + resp->ypresp_all_u.val.val.valdat_val = ue->ue_line; + resp->ypresp_all_u.val.val.valdat_len = len; + + if (!xdr_ypresp_all(xdrs, resp)) { + log_warn("%s: %s (%zu bytes)", __func__, key, len); + return FALSE; + } + + ue->ue_line[keylen] = '\0'; + } + return TRUE; +} + +static bool_t +ypdb_xdr_get_all_group(XDR *xdrs, struct ypresp_all *resp, int byname) +{ + static char key[YPMAXRECORD + 1]; + struct groupent *ge; + + RB_FOREACH(ge, group_name_tree, env->sc_group_names) { + size_t len, keylen = strlen(ge->ge_line); + + resp->more = TRUE; + resp->ypresp_all_u.val.stat = TRUE; + if (byname) { + strlcpy(key, ge->ge_line, sizeof key); + resp->ypresp_all_u.val.key.keydat_val = key; + resp->ypresp_all_u.val.key.keydat_len = keylen; + } + else { + int kl = snprintf(key, sizeof key, "%u", ge->ge_gid); + + if (kl < 0) { + log_warnx("%s: key too long", __func__); + return FALSE; + } + resp->ypresp_all_u.val.key.keydat_val = key; + resp->ypresp_all_u.val.key.keydat_len = kl; + } + + ge->ge_line[keylen] = ':'; + len = strnlen(ge->ge_line, YPMAXRECORD); + resp->ypresp_all_u.val.val.valdat_val = ge->ge_line; + resp->ypresp_all_u.val.val.valdat_len = len; + + if (!xdr_ypresp_all(xdrs, resp)) { + log_warn("%s: %s (%zu bytes)", __func__, key, len); + return FALSE; + } + + ge->ge_line[keylen] = '\0'; + } + return TRUE; +} + +static bool_t +ypdb_xdr_get_all_netid_byname(XDR *xdrs, struct ypresp_all *resp) +{ + static char key[YPMAXRECORD + 1]; + struct userent *ue; + + RB_FOREACH(ue, user_name_tree, env->sc_user_names) { + size_t len = strlen(ue->ue_netid_line); + int keylen; + + keylen = snprintf(key, sizeof key, "unix.%u@%s", ue->ue_uid, + env->sc_domainname); + if (keylen < 0) { + log_warnx("%s: key too long", __func__); + return FALSE; + } + + resp->more = TRUE; + resp->ypresp_all_u.val.stat = TRUE; + resp->ypresp_all_u.val.key.keydat_val = key; + resp->ypresp_all_u.val.key.keydat_len = keylen; + + resp->ypresp_all_u.val.val.valdat_val = ue->ue_netid_line; + resp->ypresp_all_u.val.val.valdat_len = len; + + if (!xdr_ypresp_all(xdrs, resp)) { + log_warn("%s: %s (%zu bytes)", __func__, key, len); + return FALSE; + } + } + return TRUE; +} + +bool_t +ypdb_xdr_get_all(XDR *xdrs, ypreq_nokey *req) +{ + static struct ypresp_all resp; + + if (strcmp(req->map, "passwd.byname") == 0) { + if (ypdb_xdr_get_all_passwd(xdrs, &resp, TRUE) == FALSE) + return FALSE; + } + else if (strcmp(req->map, "passwd.byuid") == 0) { + if (ypdb_xdr_get_all_passwd(xdrs, &resp, FALSE) == FALSE) + return FALSE; + } + else if (strcmp(req->map, "group.byname") == 0) { + if (ypdb_xdr_get_all_group(xdrs, &resp, TRUE) == FALSE) + return FALSE; + } + else if (strcmp(req->map, "group.byuid") == 0) { + if (ypdb_xdr_get_all_group(xdrs, &resp, FALSE) == FALSE) + return FALSE; + } + else if (strcmp(req->map, "netid.byname") == 0) { + if (ypdb_xdr_get_all_netid_byname(xdrs, &resp) == FALSE) + return FALSE; + } + else + return FALSE; + + memset(&resp, 0, sizeof resp); + resp.more = FALSE; + resp.ypresp_all_u.val.stat = YP_NOKEY; + + if (!xdr_ypresp_all(xdrs, &resp)) { + log_warn("xdr_ypresp_all: the last entry"); + return FALSE; + } + return TRUE; } ypresp_master *