1 1.20 christos /* $NetBSD: yp_match.c,v 1.20 2024/01/03 18:41:53 christos Exp $ */ 2 1.1 jtc 3 1.1 jtc /* 4 1.1 jtc * Copyright (c) 1992, 1993 Theo de Raadt <deraadt (at) fsa.ca> 5 1.1 jtc * All rights reserved. 6 1.1 jtc * 7 1.1 jtc * Redistribution and use in source and binary forms, with or without 8 1.1 jtc * modification, are permitted provided that the following conditions 9 1.1 jtc * are met: 10 1.1 jtc * 1. Redistributions of source code must retain the above copyright 11 1.1 jtc * notice, this list of conditions and the following disclaimer. 12 1.1 jtc * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jtc * notice, this list of conditions and the following disclaimer in the 14 1.1 jtc * documentation and/or other materials provided with the distribution. 15 1.1 jtc * 16 1.1 jtc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 1.1 jtc * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 1.1 jtc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 jtc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 1.1 jtc * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 jtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 jtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 jtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 jtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 jtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 jtc * SUCH DAMAGE. 27 1.1 jtc */ 28 1.1 jtc 29 1.8 christos #include <sys/cdefs.h> 30 1.1 jtc #if defined(LIBC_SCCS) && !defined(lint) 31 1.20 christos __RCSID("$NetBSD: yp_match.c,v 1.20 2024/01/03 18:41:53 christos Exp $"); 32 1.1 jtc #endif 33 1.1 jtc 34 1.9 jtc #include "namespace.h" 35 1.13 lukem 36 1.13 lukem #include <assert.h> 37 1.1 jtc #include <stdlib.h> 38 1.1 jtc #include <string.h> 39 1.10 kleink #include <time.h> 40 1.13 lukem 41 1.1 jtc #include <rpc/rpc.h> 42 1.1 jtc #include <rpcsvc/yp_prot.h> 43 1.1 jtc #include <rpcsvc/ypclnt.h> 44 1.8 christos #include "local.h" 45 1.1 jtc 46 1.1 jtc #define YPMATCHCACHE 47 1.1 jtc 48 1.9 jtc #ifdef __weak_alias 49 1.14 mycroft __weak_alias(yp_match,_yp_match) 50 1.9 jtc #endif 51 1.9 jtc 52 1.1 jtc #ifdef YPMATCHCACHE 53 1.1 jtc int _yplib_cache = 5; 54 1.1 jtc 55 1.1 jtc static struct ypmatch_ent { 56 1.1 jtc struct ypmatch_ent *next; 57 1.1 jtc char *map, *key; 58 1.1 jtc char *val; 59 1.1 jtc int keylen, vallen; 60 1.1 jtc time_t expire_t; 61 1.1 jtc } *ypmc; 62 1.8 christos 63 1.19 matt static bool_t ypmatch_add(const char *, const char *, int, char *, int); 64 1.19 matt static bool_t ypmatch_find(const char *, const char *, int, const char **, 65 1.19 matt int *); 66 1.1 jtc 67 1.1 jtc static bool_t 68 1.19 matt ypmatch_add(const char *map, const char *key, int keylen, char *val, int vallen) 69 1.1 jtc { 70 1.1 jtc struct ypmatch_ent *ep; 71 1.1 jtc time_t t; 72 1.1 jtc 73 1.13 lukem _DIAGASSERT(map != NULL); 74 1.13 lukem _DIAGASSERT(key != NULL); 75 1.13 lukem _DIAGASSERT(val != NULL); 76 1.13 lukem 77 1.1 jtc (void)time(&t); 78 1.1 jtc 79 1.1 jtc for (ep = ypmc; ep; ep = ep->next) 80 1.1 jtc if (ep->expire_t < t) 81 1.1 jtc break; 82 1.1 jtc if (ep == NULL) { 83 1.1 jtc if ((ep = malloc(sizeof *ep)) == NULL) 84 1.1 jtc return 0; 85 1.1 jtc (void)memset(ep, 0, sizeof *ep); 86 1.1 jtc if (ypmc) 87 1.1 jtc ep->next = ypmc; 88 1.1 jtc ypmc = ep; 89 1.1 jtc } 90 1.1 jtc 91 1.1 jtc if (ep->key) { 92 1.1 jtc free(ep->key); 93 1.1 jtc ep->key = NULL; 94 1.1 jtc } 95 1.1 jtc if (ep->val) { 96 1.1 jtc free(ep->val); 97 1.1 jtc ep->val = NULL; 98 1.1 jtc } 99 1.1 jtc 100 1.11 christos if ((ep->key = malloc((size_t)keylen)) == NULL) 101 1.1 jtc return 0; 102 1.1 jtc 103 1.11 christos if ((ep->val = malloc((size_t)vallen)) == NULL) { 104 1.1 jtc free(ep->key); 105 1.1 jtc ep->key = NULL; 106 1.1 jtc return 0; 107 1.1 jtc } 108 1.1 jtc 109 1.1 jtc ep->keylen = keylen; 110 1.1 jtc ep->vallen = vallen; 111 1.1 jtc 112 1.11 christos (void)memcpy(ep->key, key, (size_t)ep->keylen); 113 1.11 christos (void)memcpy(ep->val, val, (size_t)ep->vallen); 114 1.1 jtc 115 1.1 jtc if (ep->map) { 116 1.1 jtc if (strcmp(ep->map, map)) { 117 1.1 jtc free(ep->map); 118 1.1 jtc if ((ep->map = strdup(map)) == NULL) 119 1.1 jtc return 0; 120 1.1 jtc } 121 1.1 jtc } else { 122 1.1 jtc if ((ep->map = strdup(map)) == NULL) 123 1.1 jtc return 0; 124 1.1 jtc } 125 1.1 jtc 126 1.1 jtc ep->expire_t = t + _yplib_cache; 127 1.1 jtc return 1; 128 1.1 jtc } 129 1.1 jtc 130 1.1 jtc static bool_t 131 1.19 matt ypmatch_find(const char *map, const char *key, int keylen, const char **val, 132 1.19 matt int *vallen) 133 1.1 jtc { 134 1.1 jtc struct ypmatch_ent *ep; 135 1.1 jtc time_t t; 136 1.1 jtc 137 1.13 lukem _DIAGASSERT(map != NULL); 138 1.13 lukem _DIAGASSERT(key != NULL); 139 1.13 lukem _DIAGASSERT(val != NULL); 140 1.13 lukem 141 1.1 jtc if (ypmc == NULL) 142 1.1 jtc return 0; 143 1.1 jtc 144 1.1 jtc (void) time(&t); 145 1.1 jtc 146 1.1 jtc for (ep = ypmc; ep; ep = ep->next) { 147 1.1 jtc if (ep->keylen != keylen) 148 1.1 jtc continue; 149 1.1 jtc if (strcmp(ep->map, map)) 150 1.1 jtc continue; 151 1.11 christos if (memcmp(ep->key, key, (size_t)keylen)) 152 1.1 jtc continue; 153 1.1 jtc if (t > ep->expire_t) 154 1.1 jtc continue; 155 1.1 jtc 156 1.1 jtc *val = ep->val; 157 1.1 jtc *vallen = ep->vallen; 158 1.1 jtc return 1; 159 1.1 jtc } 160 1.1 jtc return 0; 161 1.1 jtc } 162 1.1 jtc #endif 163 1.1 jtc 164 1.1 jtc int 165 1.19 matt yp_match(const char *indomain, const char *inmap, const char *inkey, 166 1.19 matt int inkeylen, char **outval, int *outvallen) 167 1.1 jtc { 168 1.1 jtc struct dom_binding *ysd; 169 1.1 jtc struct ypresp_val yprv; 170 1.1 jtc struct ypreq_key yprk; 171 1.3 christos int r, nerrs = 0; 172 1.1 jtc 173 1.13 lukem if (outval == NULL || outvallen == NULL) 174 1.4 lukem return YPERR_BADARGS; 175 1.4 lukem *outval = NULL; 176 1.4 lukem *outvallen = 0; 177 1.2 jtc 178 1.7 lukem if (_yp_invalid_domain(indomain)) 179 1.2 jtc return YPERR_BADARGS; 180 1.2 jtc if (inmap == NULL || *inmap == '\0' 181 1.2 jtc || strlen(inmap) > YPMAXMAP) 182 1.2 jtc return YPERR_BADARGS; 183 1.2 jtc if (inkey == NULL || inkeylen == 0) 184 1.2 jtc return YPERR_BADARGS; 185 1.1 jtc 186 1.1 jtc again: 187 1.1 jtc if (_yp_dobind(indomain, &ysd) != 0) 188 1.1 jtc return YPERR_DOMAIN; 189 1.1 jtc 190 1.1 jtc #ifdef YPMATCHCACHE 191 1.1 jtc if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, 192 1.1 jtc inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) { 193 1.1 jtc *outvallen = yprv.valdat.dsize; 194 1.11 christos if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) 195 1.1 jtc return YPERR_YPERR; 196 1.11 christos (void)memcpy(*outval, yprv.valdat.dptr, (size_t)*outvallen); 197 1.1 jtc (*outval)[*outvallen] = '\0'; 198 1.1 jtc return 0; 199 1.1 jtc } 200 1.1 jtc #endif 201 1.1 jtc 202 1.1 jtc yprk.domain = indomain; 203 1.1 jtc yprk.map = inmap; 204 1.17 christos yprk.keydat.dptr = __UNCONST(inkey); 205 1.1 jtc yprk.keydat.dsize = inkeylen; 206 1.1 jtc 207 1.1 jtc memset(&yprv, 0, sizeof yprv); 208 1.1 jtc 209 1.15 christos r = clnt_call(ysd->dom_client, (rpcproc_t)YPPROC_MATCH, 210 1.12 christos (xdrproc_t)xdr_ypreq_key, &yprk, 211 1.12 christos (xdrproc_t)xdr_ypresp_val, &yprv, 212 1.2 jtc _yplib_timeout); 213 1.1 jtc if (r != RPC_SUCCESS) { 214 1.18 christos if (_yplib_bindtries <= 0 && ++nerrs == _yplib_nerrs) { 215 1.3 christos clnt_perror(ysd->dom_client, "yp_match: clnt_call"); 216 1.3 christos nerrs = 0; 217 1.3 christos } 218 1.18 christos else if (_yplib_bindtries > 0 && ++nerrs == _yplib_bindtries) { 219 1.18 christos return YPERR_YPSERV; 220 1.18 christos } 221 1.1 jtc ysd->dom_vers = -1; 222 1.1 jtc goto again; 223 1.1 jtc } 224 1.1 jtc if (!(r = ypprot_err(yprv.status))) { 225 1.1 jtc *outvallen = yprv.valdat.dsize; 226 1.11 christos if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) 227 1.1 jtc return YPERR_YPERR; 228 1.11 christos (void)memcpy(*outval, yprv.valdat.dptr, (size_t)*outvallen); 229 1.1 jtc (*outval)[*outvallen] = '\0'; 230 1.1 jtc #ifdef YPMATCHCACHE 231 1.1 jtc if (strcmp(_yp_domain, indomain) == 0) 232 1.1 jtc if (!ypmatch_add(inmap, inkey, inkeylen, 233 1.1 jtc *outval, *outvallen)) 234 1.5 lukem r = YPERR_RESRC; 235 1.1 jtc #endif 236 1.1 jtc } 237 1.12 christos xdr_free((xdrproc_t)xdr_ypresp_val, (char *)(void *)&yprv); 238 1.9 jtc __yp_unbind(ysd); 239 1.6 lukem if (r != 0) { 240 1.6 lukem if (*outval) { 241 1.6 lukem free(*outval); 242 1.6 lukem *outval = NULL; 243 1.6 lukem } 244 1.6 lukem } 245 1.1 jtc return r; 246 1.1 jtc } 247