138032Speter/* 2261194Sgshapiro * Copyright (c) 1998-2008 Proofpoint, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1992, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 1538032Speter 16266527SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.713 2013-11-22 20:51:55 ca Exp $") 1764562Sgshapiro 1890792Sgshapiro#if LDAPMAP 1990792Sgshapiro# include <sm/ldap.h> 20363466Sgshapiro#endif 2190792Sgshapiro 2290792Sgshapiro#if NDBM 2338032Speter# include <ndbm.h> 2438032Speter# ifdef R_FIRST 2538032Speter ERROR README: You are running the Berkeley DB version of ndbm.h. See 2638032Speter ERROR README: the README file about tweaking Berkeley DB so it can 2738032Speter ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile 2838032Speter ERROR README: and use -DNEWDB instead. 2964562Sgshapiro# endif /* R_FIRST */ 3064562Sgshapiro#endif /* NDBM */ 3190792Sgshapiro#if NEWDB 32110560Sgshapiro# include "sm/bdb.h" 33363466Sgshapiro#endif 3490792Sgshapiro#if NIS 3538032Speter struct dom_binding; /* forward reference needed on IRIX */ 3638032Speter# include <rpcsvc/ypclnt.h> 3790792Sgshapiro# if NDBM 3838032Speter# define NDBM_YP_COMPAT /* create YP-compatible NDBM files */ 39363466Sgshapiro# endif 4064562Sgshapiro#endif /* NIS */ 41363466Sgshapiro#if CDB 42363466Sgshapiro# include <cdb.h> 43363466Sgshapiro#endif 4438032Speter 45168515Sgshapiro#include "map.h" 46168515Sgshapiro 4790792Sgshapiro#if NEWDB 4864562Sgshapiro# if DB_VERSION_MAJOR < 2 4964562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); 50363466Sgshapiro# endif 5164562Sgshapiro# if DB_VERSION_MAJOR == 2 5264562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); 53363466Sgshapiro# endif 5464562Sgshapiro# if DB_VERSION_MAJOR > 2 5564562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, void **)); 56363466Sgshapiro# endif 5764562Sgshapiro#endif /* NEWDB */ 5873188Sgshapirostatic bool extract_canonname __P((char *, char *, char *, char[], int)); 5990792Sgshapirostatic void map_close __P((STAB *, int)); 6090792Sgshapirostatic void map_init __P((STAB *, int)); 6164562Sgshapiro#ifdef LDAPMAP 6290792Sgshapirostatic STAB * ldapmap_findconn __P((SM_LDAP_STRUCT *)); 63363466Sgshapiro#endif 6490792Sgshapiro#if NISPLUS 6564562Sgshapirostatic bool nisplus_getcanonname __P((char *, int, int *)); 66363466Sgshapiro#endif 6790792Sgshapiro#if NIS 6864562Sgshapirostatic bool nis_getcanonname __P((char *, int, int *)); 69363466Sgshapiro#endif 7064562Sgshapiro#if NETINFO 7164562Sgshapirostatic bool ni_getcanonname __P((char *, int, int *)); 72363466Sgshapiro#endif 7364562Sgshapirostatic bool text_getcanonname __P((char *, int, int *)); 74132943Sgshapiro#if SOCKETMAP 75132943Sgshapirostatic STAB *socket_map_findconn __P((const char*)); 7664562Sgshapiro 77132943Sgshapiro/* XXX arbitrary limit for sanity */ 78132943Sgshapiro# define SOCKETMAP_MAXL 1000000 79132943Sgshapiro#endif /* SOCKETMAP */ 80132943Sgshapiro 8190792Sgshapiro/* default error message for trying to open a map in write mode */ 8290792Sgshapiro#ifdef ENOSYS 8390792Sgshapiro# define SM_EMAPCANTWRITE ENOSYS 8490792Sgshapiro#else /* ENOSYS */ 8590792Sgshapiro# ifdef EFTYPE 8690792Sgshapiro# define SM_EMAPCANTWRITE EFTYPE 87363466Sgshapiro# else 8890792Sgshapiro# define SM_EMAPCANTWRITE ENXIO 89363466Sgshapiro# endif 9090792Sgshapiro#endif /* ENOSYS */ 9190792Sgshapiro 9238032Speter/* 9338032Speter** MAP.C -- implementations for various map classes. 9438032Speter** 9538032Speter** Each map class implements a series of functions: 9638032Speter** 9738032Speter** bool map_parse(MAP *map, char *args) 9890792Sgshapiro** Parse the arguments from the config file. Return true 9990792Sgshapiro** if they were ok, false otherwise. Fill in map with the 10038032Speter** values. 10138032Speter** 10238032Speter** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 10338032Speter** Look up the key in the given map. If found, do any 10438032Speter** rewriting the map wants (including "args" if desired) 10538032Speter** and return the value. Set *pstat to the appropriate status 10638032Speter** on error and return NULL. Args will be NULL if called 10738032Speter** from the alias routines, although this should probably 10838032Speter** not be relied upon. It is suggested you call map_rewrite 10938032Speter** to return the results -- it takes care of null termination 11038032Speter** and uses a dynamically expanded buffer as needed. 11138032Speter** 11238032Speter** void map_store(MAP *map, char *key, char *value) 11338032Speter** Store the key:value pair in the map. 11438032Speter** 11538032Speter** bool map_open(MAP *map, int mode) 11638032Speter** Open the map for the indicated mode. Mode should 11790792Sgshapiro** be either O_RDONLY or O_RDWR. Return true if it 11890792Sgshapiro** was opened successfully, false otherwise. If the open 11990792Sgshapiro** failed and the MF_OPTIONAL flag is not set, it should 12038032Speter** also print an error. If the MF_ALIAS bit is set 12138032Speter** and this map class understands the @:@ convention, it 12238032Speter** should call aliaswait() before returning. 12338032Speter** 12438032Speter** void map_close(MAP *map) 12538032Speter** Close the map. 12638032Speter** 12738032Speter** This file also includes the implementation for getcanonname. 12838032Speter** It is currently implemented in a pretty ad-hoc manner; it ought 12938032Speter** to be more properly integrated into the map structure. 13038032Speter*/ 13138032Speter 13238032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 13338032Speter# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 134363466Sgshapiro#else 13538032Speter# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 136363466Sgshapiro#endif 13738032Speter 13890792Sgshapiro/* 13938032Speter** MAP_PARSEARGS -- parse config line arguments for database lookup 14038032Speter** 14138032Speter** This is a generic version of the map_parse method. 14238032Speter** 14338032Speter** Parameters: 14438032Speter** map -- the map being initialized. 14538032Speter** ap -- a pointer to the args on the config line. 14638032Speter** 14738032Speter** Returns: 14890792Sgshapiro** true -- if everything parsed OK. 14990792Sgshapiro** false -- otherwise. 15038032Speter** 15138032Speter** Side Effects: 15238032Speter** null terminates the filename; stores it in map 15338032Speter*/ 15438032Speter 15538032Speterbool 15638032Spetermap_parseargs(map, ap) 15738032Speter MAP *map; 15838032Speter char *ap; 15938032Speter{ 16038032Speter register char *p = ap; 16138032Speter 16264562Sgshapiro /* 16390792Sgshapiro ** There is no check whether there is really an argument, 16490792Sgshapiro ** but that's not important enough to warrant extra code. 16564562Sgshapiro */ 16690792Sgshapiro 16790792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 16864562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 16938032Speter for (;;) 17038032Speter { 171363466Sgshapiro while (SM_ISSPACE(*p)) 17238032Speter p++; 17338032Speter if (*p != '-') 17438032Speter break; 17538032Speter switch (*++p) 17638032Speter { 17738032Speter case 'A': 17838032Speter map->map_mflags |= MF_APPEND; 17938032Speter break; 18038032Speter 18138032Speter case 'a': 18238032Speter map->map_app = ++p; 18338032Speter break; 18438032Speter 185363466Sgshapiro case 'D': 186363466Sgshapiro map->map_mflags |= MF_DEFER; 187363466Sgshapiro break; 188363466Sgshapiro 189285229Sgshapiro case 'd': 190285229Sgshapiro { 191285229Sgshapiro char *h; 192285229Sgshapiro 193285229Sgshapiro ++p; 194285229Sgshapiro h = strchr(p, ' '); 195285229Sgshapiro if (h != NULL) 196285229Sgshapiro *h = '\0'; 197285229Sgshapiro map->map_timeout = convtime(p, 's'); 198285229Sgshapiro if (h != NULL) 199285229Sgshapiro *h = ' '; 200285229Sgshapiro } 201285229Sgshapiro break; 202285229Sgshapiro 203363466Sgshapiro case 'f': 204363466Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 20538032Speter break; 20638032Speter 20738032Speter case 'k': 20838032Speter while (isascii(*++p) && isspace(*p)) 20938032Speter continue; 21038032Speter map->map_keycolnm = p; 21138032Speter break; 21238032Speter 213363466Sgshapiro case 'm': 214363466Sgshapiro map->map_mflags |= MF_MATCHONLY; 215363466Sgshapiro break; 216363466Sgshapiro 217363466Sgshapiro case 'N': 218363466Sgshapiro map->map_mflags |= MF_INCLNULL; 219363466Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 220363466Sgshapiro break; 221363466Sgshapiro 222363466Sgshapiro case 'O': 223363466Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 224363466Sgshapiro break; 225363466Sgshapiro 226363466Sgshapiro case 'o': 227363466Sgshapiro map->map_mflags |= MF_OPTIONAL; 228363466Sgshapiro break; 229363466Sgshapiro 230363466Sgshapiro case 'q': 231363466Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 232363466Sgshapiro break; 233363466Sgshapiro 234363466Sgshapiro case 'S': 235363466Sgshapiro map->map_spacesub = *++p; 236363466Sgshapiro break; 237363466Sgshapiro 238363466Sgshapiro case 'T': 239363466Sgshapiro map->map_tapp = ++p; 240363466Sgshapiro break; 241363466Sgshapiro 242363466Sgshapiro case 't': 243363466Sgshapiro map->map_mflags |= MF_NODEFER; 244363466Sgshapiro break; 245363466Sgshapiro 24638032Speter case 'v': 24738032Speter while (isascii(*++p) && isspace(*p)) 24838032Speter continue; 24938032Speter map->map_valcolnm = p; 25038032Speter break; 25138032Speter 25238032Speter case 'z': 25338032Speter if (*++p != '\\') 25438032Speter map->map_coldelim = *p; 25538032Speter else 25638032Speter { 25738032Speter switch (*++p) 25838032Speter { 25938032Speter case 'n': 26038032Speter map->map_coldelim = '\n'; 26138032Speter break; 26238032Speter 26338032Speter case 't': 26438032Speter map->map_coldelim = '\t'; 26538032Speter break; 26638032Speter 26738032Speter default: 26838032Speter map->map_coldelim = '\\'; 26938032Speter } 27038032Speter } 27138032Speter break; 27238032Speter 27364562Sgshapiro default: 27464562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 27564562Sgshapiro break; 27638032Speter } 277363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 27838032Speter p++; 27938032Speter if (*p != '\0') 28038032Speter *p++ = '\0'; 28138032Speter } 28238032Speter if (map->map_app != NULL) 28338032Speter map->map_app = newstr(map->map_app); 28438032Speter if (map->map_tapp != NULL) 28538032Speter map->map_tapp = newstr(map->map_tapp); 28638032Speter if (map->map_keycolnm != NULL) 28738032Speter map->map_keycolnm = newstr(map->map_keycolnm); 28838032Speter if (map->map_valcolnm != NULL) 28938032Speter map->map_valcolnm = newstr(map->map_valcolnm); 29038032Speter 29138032Speter if (*p != '\0') 29238032Speter { 29338032Speter map->map_file = p; 294363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 29538032Speter p++; 29638032Speter if (*p != '\0') 29738032Speter *p++ = '\0'; 29838032Speter map->map_file = newstr(map->map_file); 29938032Speter } 30038032Speter 301363466Sgshapiro while (*p != '\0' && SM_ISSPACE(*p)) 30238032Speter p++; 30338032Speter if (*p != '\0') 30438032Speter map->map_rebuild = newstr(p); 30538032Speter 30638032Speter if (map->map_file == NULL && 30738032Speter !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 30838032Speter { 30938032Speter syserr("No file name for %s map %s", 31038032Speter map->map_class->map_cname, map->map_mname); 31190792Sgshapiro return false; 31238032Speter } 31390792Sgshapiro return true; 31438032Speter} 31590792Sgshapiro/* 31638032Speter** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 31738032Speter** 31838032Speter** It also adds the map_app string. It can be used as a utility 31938032Speter** in the map_lookup method. 32038032Speter** 32138032Speter** Parameters: 32238032Speter** map -- the map that causes this. 32338032Speter** s -- the string to rewrite, NOT necessarily null terminated. 32438032Speter** slen -- the length of s. 32538032Speter** av -- arguments to interpolate into buf. 32638032Speter** 32738032Speter** Returns: 32838032Speter** Pointer to rewritten result. This is static data that 32938032Speter** should be copied if it is to be saved! 33038032Speter*/ 33138032Speter 33238032Speterchar * 33338032Spetermap_rewrite(map, s, slen, av) 33438032Speter register MAP *map; 33538032Speter register const char *s; 33638032Speter size_t slen; 33738032Speter char **av; 33838032Speter{ 33938032Speter register char *bp; 34038032Speter register char c; 34138032Speter char **avp; 34238032Speter register char *ap; 34338032Speter size_t l; 34438032Speter size_t len; 34538032Speter static size_t buflen = 0; 34638032Speter static char *buf = NULL; 34738032Speter 34838032Speter if (tTd(39, 1)) 34938032Speter { 35090792Sgshapiro sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s); 35138032Speter if (av == NULL) 35290792Sgshapiro sm_dprintf(" (nullv)"); 35338032Speter else 35438032Speter { 35538032Speter for (avp = av; *avp != NULL; avp++) 35690792Sgshapiro sm_dprintf("\n\t%s", *avp); 35738032Speter } 35890792Sgshapiro sm_dprintf("\n"); 35938032Speter } 36038032Speter 36138032Speter /* count expected size of output (can safely overestimate) */ 36238032Speter l = len = slen; 36338032Speter if (av != NULL) 36438032Speter { 36538032Speter const char *sp = s; 36638032Speter 36738032Speter while (l-- > 0 && (c = *sp++) != '\0') 36838032Speter { 36938032Speter if (c != '%') 37038032Speter continue; 37138032Speter if (l-- <= 0) 37238032Speter break; 37338032Speter c = *sp++; 37438032Speter if (!(isascii(c) && isdigit(c))) 37538032Speter continue; 37638032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 37738032Speter continue; 37838032Speter if (*avp == NULL) 37938032Speter continue; 38038032Speter len += strlen(*avp); 38138032Speter } 38238032Speter } 38338032Speter if (map->map_app != NULL) 38438032Speter len += strlen(map->map_app); 38538032Speter if (buflen < ++len) 38638032Speter { 38738032Speter /* need to malloc additional space */ 38838032Speter buflen = len; 38938032Speter if (buf != NULL) 39077349Sgshapiro sm_free(buf); 39190792Sgshapiro buf = sm_pmalloc_x(buflen); 39238032Speter } 39338032Speter 39438032Speter bp = buf; 39538032Speter if (av == NULL) 39638032Speter { 39764562Sgshapiro memmove(bp, s, slen); 39838032Speter bp += slen; 39964562Sgshapiro 40064562Sgshapiro /* assert(len > slen); */ 40164562Sgshapiro len -= slen; 40238032Speter } 40338032Speter else 40438032Speter { 40538032Speter while (slen-- > 0 && (c = *s++) != '\0') 40638032Speter { 40738032Speter if (c != '%') 40838032Speter { 40938032Speter pushc: 410120256Sgshapiro if (len-- <= 1) 41190792Sgshapiro break; 41238032Speter *bp++ = c; 41338032Speter continue; 41438032Speter } 41538032Speter if (slen-- <= 0 || (c = *s++) == '\0') 41638032Speter c = '%'; 41738032Speter if (c == '%') 41838032Speter goto pushc; 41938032Speter if (!(isascii(c) && isdigit(c))) 42038032Speter { 421120256Sgshapiro if (len-- <= 1) 422120256Sgshapiro break; 42338032Speter *bp++ = '%'; 42438032Speter goto pushc; 42538032Speter } 42638032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 42738032Speter continue; 42838032Speter if (*avp == NULL) 42938032Speter continue; 43038032Speter 43138032Speter /* transliterate argument into output string */ 43264562Sgshapiro for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len) 43338032Speter *bp++ = c; 43438032Speter } 43538032Speter } 43664562Sgshapiro if (map->map_app != NULL && len > 0) 43790792Sgshapiro (void) sm_strlcpy(bp, map->map_app, len); 43838032Speter else 43938032Speter *bp = '\0'; 44038032Speter if (tTd(39, 1)) 44190792Sgshapiro sm_dprintf("map_rewrite => %s\n", buf); 44238032Speter return buf; 44338032Speter} 44490792Sgshapiro/* 44564562Sgshapiro** INITMAPS -- rebuild alias maps 44638032Speter** 44738032Speter** Parameters: 44864562Sgshapiro** none. 44938032Speter** 45038032Speter** Returns: 45138032Speter** none. 45238032Speter*/ 45338032Speter 45438032Spetervoid 45564562Sgshapiroinitmaps() 45638032Speter{ 45738032Speter#if XDEBUG 45838032Speter checkfd012("entering initmaps"); 459363466Sgshapiro#endif 46038032Speter stabapply(map_init, 0); 46138032Speter#if XDEBUG 46238032Speter checkfd012("exiting initmaps"); 463363466Sgshapiro#endif 46438032Speter} 46590792Sgshapiro/* 46664562Sgshapiro** MAP_INIT -- rebuild a map 46764562Sgshapiro** 46864562Sgshapiro** Parameters: 46964562Sgshapiro** s -- STAB entry: if map: try to rebuild 47064562Sgshapiro** unused -- unused variable 47164562Sgshapiro** 47264562Sgshapiro** Returns: 47364562Sgshapiro** none. 47464562Sgshapiro** 47564562Sgshapiro** Side Effects: 47664562Sgshapiro** will close already open rebuildable map. 47764562Sgshapiro*/ 47838032Speter 47964562Sgshapiro/* ARGSUSED1 */ 48064562Sgshapirostatic void 48164562Sgshapiromap_init(s, unused) 48238032Speter register STAB *s; 48364562Sgshapiro int unused; 48438032Speter{ 48538032Speter register MAP *map; 48638032Speter 48738032Speter /* has to be a map */ 48890792Sgshapiro if (s->s_symtype != ST_MAP) 48938032Speter return; 49038032Speter 49138032Speter map = &s->s_map; 49238032Speter if (!bitset(MF_VALID, map->map_mflags)) 49338032Speter return; 49438032Speter 49538032Speter if (tTd(38, 2)) 49690792Sgshapiro sm_dprintf("map_init(%s:%s, %s)\n", 49738032Speter map->map_class->map_cname == NULL ? "NULL" : 49838032Speter map->map_class->map_cname, 49938032Speter map->map_mname == NULL ? "NULL" : map->map_mname, 50064562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 50138032Speter 50264562Sgshapiro if (!bitset(MF_ALIAS, map->map_mflags) || 50364562Sgshapiro !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 50438032Speter { 50538032Speter if (tTd(38, 3)) 50690792Sgshapiro sm_dprintf("\tnot rebuildable\n"); 50738032Speter return; 50838032Speter } 50938032Speter 51038032Speter /* if already open, close it (for nested open) */ 51138032Speter if (bitset(MF_OPEN, map->map_mflags)) 51238032Speter { 51377349Sgshapiro map->map_mflags |= MF_CLOSING; 51438032Speter map->map_class->map_close(map); 51577349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 51638032Speter } 51738032Speter 51890792Sgshapiro (void) rebuildaliases(map, false); 51964562Sgshapiro return; 52064562Sgshapiro} 52190792Sgshapiro/* 52264562Sgshapiro** OPENMAP -- open a map 52364562Sgshapiro** 52464562Sgshapiro** Parameters: 52564562Sgshapiro** map -- map to open (it must not be open). 52664562Sgshapiro** 52764562Sgshapiro** Returns: 52864562Sgshapiro** whether open succeeded. 52964562Sgshapiro*/ 53064562Sgshapiro 53164562Sgshapirobool 53264562Sgshapiroopenmap(map) 53364562Sgshapiro MAP *map; 53464562Sgshapiro{ 53590792Sgshapiro bool restore = false; 53664562Sgshapiro bool savehold = HoldErrs; 53764562Sgshapiro bool savequick = QuickAbort; 53864562Sgshapiro int saveerrors = Errors; 53964562Sgshapiro 54064562Sgshapiro if (!bitset(MF_VALID, map->map_mflags)) 54190792Sgshapiro return false; 54264562Sgshapiro 54364562Sgshapiro /* better safe than sorry... */ 54464562Sgshapiro if (bitset(MF_OPEN, map->map_mflags)) 54590792Sgshapiro return true; 54664562Sgshapiro 54764562Sgshapiro /* Don't send a map open error out via SMTP */ 54864562Sgshapiro if ((OnlyOneError || QuickAbort) && 54964562Sgshapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 55038032Speter { 55190792Sgshapiro restore = true; 55290792Sgshapiro HoldErrs = true; 55390792Sgshapiro QuickAbort = false; 55438032Speter } 55538032Speter 55664562Sgshapiro errno = 0; 55738032Speter if (map->map_class->map_open(map, O_RDONLY)) 55838032Speter { 55938032Speter if (tTd(38, 4)) 56090792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: valid\n", 56138032Speter map->map_class->map_cname == NULL ? "NULL" : 56238032Speter map->map_class->map_cname, 56338032Speter map->map_mname == NULL ? "NULL" : 56438032Speter map->map_mname, 56538032Speter map->map_file == NULL ? "NULL" : 56638032Speter map->map_file); 56738032Speter map->map_mflags |= MF_OPEN; 56890792Sgshapiro map->map_pid = CurrentPid; 56938032Speter } 57038032Speter else 57138032Speter { 57238032Speter if (tTd(38, 4)) 57390792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n", 57438032Speter map->map_class->map_cname == NULL ? "NULL" : 57538032Speter map->map_class->map_cname, 57638032Speter map->map_mname == NULL ? "NULL" : 57738032Speter map->map_mname, 57838032Speter map->map_file == NULL ? "NULL" : 57938032Speter map->map_file, 58064562Sgshapiro errno == 0 ? "" : ": ", 58190792Sgshapiro errno == 0 ? "" : sm_errstring(errno)); 58238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 58338032Speter { 58438032Speter extern MAPCLASS BogusMapClass; 58538032Speter 58690792Sgshapiro map->map_orgclass = map->map_class; 58738032Speter map->map_class = &BogusMapClass; 58890792Sgshapiro map->map_mflags |= MF_OPEN|MF_OPENBOGUS; 58990792Sgshapiro map->map_pid = CurrentPid; 59038032Speter } 59164562Sgshapiro else 59264562Sgshapiro { 59364562Sgshapiro /* don't try again */ 59464562Sgshapiro map->map_mflags &= ~MF_VALID; 59564562Sgshapiro } 59638032Speter } 59764562Sgshapiro 59864562Sgshapiro if (restore) 59964562Sgshapiro { 60064562Sgshapiro Errors = saveerrors; 60164562Sgshapiro HoldErrs = savehold; 60264562Sgshapiro QuickAbort = savequick; 60364562Sgshapiro } 60464562Sgshapiro 60564562Sgshapiro return bitset(MF_OPEN, map->map_mflags); 60638032Speter} 60790792Sgshapiro/* 60842575Speter** CLOSEMAPS -- close all open maps opened by the current pid. 60942575Speter** 61042575Speter** Parameters: 61190792Sgshapiro** bogus -- only close bogus maps. 61242575Speter** 61342575Speter** Returns: 61442575Speter** none. 61542575Speter*/ 61642575Speter 61742575Spetervoid 61890792Sgshapiroclosemaps(bogus) 61990792Sgshapiro bool bogus; 62042575Speter{ 62190792Sgshapiro stabapply(map_close, bogus); 62242575Speter} 62390792Sgshapiro/* 62464562Sgshapiro** MAP_CLOSE -- close a map opened by the current pid. 62564562Sgshapiro** 62664562Sgshapiro** Parameters: 62790792Sgshapiro** s -- STAB entry: if map: try to close 62890792Sgshapiro** bogus -- only close bogus maps or MCF_NOTPERSIST maps. 62964562Sgshapiro** 63064562Sgshapiro** Returns: 63164562Sgshapiro** none. 63264562Sgshapiro*/ 63342575Speter 63464562Sgshapirostatic void 63590792Sgshapiromap_close(s, bogus) 63642575Speter register STAB *s; 63790792Sgshapiro int bogus; /* int because of stabapply(), used as bool */ 63842575Speter{ 63942575Speter MAP *map; 64090792Sgshapiro extern MAPCLASS BogusMapClass; 64142575Speter 64290792Sgshapiro if (s->s_symtype != ST_MAP) 64342575Speter return; 64464562Sgshapiro 64542575Speter map = &s->s_map; 64642575Speter 64790792Sgshapiro /* 64890792Sgshapiro ** close the map iff: 64990792Sgshapiro ** it is valid and open and opened by this process 65090792Sgshapiro ** and (!bogus or it's a bogus map or it is not persistent) 65190792Sgshapiro ** negate this: return iff 65290792Sgshapiro ** it is not valid or it is not open or not opened by this process 65390792Sgshapiro ** or (bogus and it's not a bogus map and it's not not-persistent) 65490792Sgshapiro */ 65590792Sgshapiro 65642575Speter if (!bitset(MF_VALID, map->map_mflags) || 65742575Speter !bitset(MF_OPEN, map->map_mflags) || 65877349Sgshapiro bitset(MF_CLOSING, map->map_mflags) || 65990792Sgshapiro map->map_pid != CurrentPid || 66090792Sgshapiro (bogus && map->map_class != &BogusMapClass && 66190792Sgshapiro !bitset(MCF_NOTPERSIST, map->map_class->map_cflags))) 66242575Speter return; 66364562Sgshapiro 66490792Sgshapiro if (map->map_class == &BogusMapClass && map->map_orgclass != NULL && 66590792Sgshapiro map->map_orgclass != &BogusMapClass) 66690792Sgshapiro map->map_class = map->map_orgclass; 66742575Speter if (tTd(38, 5)) 66890792Sgshapiro sm_dprintf("closemaps: closing %s (%s)\n", 66964562Sgshapiro map->map_mname == NULL ? "NULL" : map->map_mname, 67064562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 67164562Sgshapiro 67290792Sgshapiro if (!bitset(MF_OPENBOGUS, map->map_mflags)) 67390792Sgshapiro { 67490792Sgshapiro map->map_mflags |= MF_CLOSING; 67590792Sgshapiro map->map_class->map_close(map); 67690792Sgshapiro } 67790792Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING); 67842575Speter} 679168515Sgshapiro 680168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 681168515Sgshapiroextern int getdomainname(); 682168515Sgshapiro 683168515Sgshapiro/* this is mainly for backward compatibility in Sun environment */ 684168515Sgshapirostatic char * 685168515Sgshapirosun_init_domain() 686168515Sgshapiro{ 687168515Sgshapiro /* 688168515Sgshapiro ** Get the domain name from the kernel. 689168515Sgshapiro ** If it does not start with a leading dot, then remove 690168515Sgshapiro ** the first component. Since leading dots are funny Unix 691168515Sgshapiro ** files, we treat a leading "+" the same as a leading dot. 692168515Sgshapiro ** Finally, force there to be at least one dot in the domain name 693168515Sgshapiro ** (i.e. top-level domains are not allowed, like "com", must be 694168515Sgshapiro ** something like "sun.com"). 695168515Sgshapiro */ 696168515Sgshapiro 697168515Sgshapiro char buf[MAXNAME]; 698168515Sgshapiro char *period, *autodomain; 699168515Sgshapiro 700168515Sgshapiro if (getdomainname(buf, sizeof buf) < 0) 701168515Sgshapiro return NULL; 702168515Sgshapiro 703168515Sgshapiro if (buf[0] == '\0') 704168515Sgshapiro return NULL; 705168515Sgshapiro 706168515Sgshapiro if (tTd(0, 20)) 707168515Sgshapiro printf("domainname = %s\n", buf); 708168515Sgshapiro 709168515Sgshapiro if (buf[0] == '+') 710168515Sgshapiro buf[0] = '.'; 711168515Sgshapiro period = strchr(buf, '.'); 712168515Sgshapiro if (period == NULL) 713168515Sgshapiro autodomain = buf; 714168515Sgshapiro else 715168515Sgshapiro autodomain = period + 1; 716168515Sgshapiro if (strchr(autodomain, '.') == NULL) 717168515Sgshapiro return newstr(buf); 718168515Sgshapiro else 719168515Sgshapiro return newstr(autodomain); 720168515Sgshapiro} 721168515Sgshapiro#endif /* SUN_EXTENSIONS && SUN_INIT_DOMAIN */ 722168515Sgshapiro 72390792Sgshapiro/* 72438032Speter** GETCANONNAME -- look up name using service switch 72538032Speter** 72638032Speter** Parameters: 72738032Speter** host -- the host name to look up. 72838032Speter** hbsize -- the size of the host buffer. 72938032Speter** trymx -- if set, try MX records. 73090792Sgshapiro** pttl -- pointer to return TTL (can be NULL). 73138032Speter** 73238032Speter** Returns: 733363466Sgshapiro** >0 -- if the host was found. 734363466Sgshapiro** 0 -- otherwise. 73538032Speter*/ 73638032Speter 737363466Sgshapiroint 73890792Sgshapirogetcanonname(host, hbsize, trymx, pttl) 73938032Speter char *host; 74038032Speter int hbsize; 74138032Speter bool trymx; 74290792Sgshapiro int *pttl; 74338032Speter{ 74438032Speter int nmaps; 74538032Speter int mapno; 74690792Sgshapiro bool found = false; 74790792Sgshapiro bool got_tempfail = false; 748203004Sgshapiro auto int status = EX_UNAVAILABLE; 74938032Speter char *maptype[MAXMAPSTACK]; 75038032Speter short mapreturn[MAXMAPACTIONS]; 751168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 752168515Sgshapiro bool should_try_nis_domain = false; 753168515Sgshapiro static char *nis_domain = NULL; 754168515Sgshapiro#endif 755363466Sgshapiro bool secure = true; /* consider all maps secure by default */ 75638032Speter 75738032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 758363466Sgshapiro if (pttl != NULL) 75990792Sgshapiro *pttl = SM_DEFAULT_TTL; 76038032Speter for (mapno = 0; mapno < nmaps; mapno++) 76138032Speter { 76238032Speter int i; 76338032Speter 76438032Speter if (tTd(38, 20)) 76590792Sgshapiro sm_dprintf("getcanonname(%s), trying %s\n", 76638032Speter host, maptype[mapno]); 76738032Speter if (strcmp("files", maptype[mapno]) == 0) 76838032Speter { 76964562Sgshapiro found = text_getcanonname(host, hbsize, &status); 77038032Speter } 77190792Sgshapiro#if NIS 77238032Speter else if (strcmp("nis", maptype[mapno]) == 0) 77338032Speter { 77464562Sgshapiro found = nis_getcanonname(host, hbsize, &status); 775168515Sgshapiro# if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 776168515Sgshapiro if (nis_domain == NULL) 777168515Sgshapiro nis_domain = sun_init_domain(); 778363466Sgshapiro# endif 77938032Speter } 78064562Sgshapiro#endif /* NIS */ 78190792Sgshapiro#if NISPLUS 78238032Speter else if (strcmp("nisplus", maptype[mapno]) == 0) 78338032Speter { 78464562Sgshapiro found = nisplus_getcanonname(host, hbsize, &status); 785168515Sgshapiro# if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 786168515Sgshapiro if (nis_domain == NULL) 787168515Sgshapiro nis_domain = sun_init_domain(); 788363466Sgshapiro# endif 78938032Speter } 79064562Sgshapiro#endif /* NISPLUS */ 79138032Speter#if NAMED_BIND 79238032Speter else if (strcmp("dns", maptype[mapno]) == 0) 79338032Speter { 794363466Sgshapiro int r; 795363466Sgshapiro 796363466Sgshapiro r = dns_getcanonname(host, hbsize, trymx, &status, 797363466Sgshapiro pttl); 798363466Sgshapiro secure = HOST_SECURE == r; 799363466Sgshapiro found = r > 0; 80038032Speter } 80164562Sgshapiro#endif /* NAMED_BIND */ 80238032Speter#if NETINFO 80338032Speter else if (strcmp("netinfo", maptype[mapno]) == 0) 80438032Speter { 80564562Sgshapiro found = ni_getcanonname(host, hbsize, &status); 80638032Speter } 80764562Sgshapiro#endif /* NETINFO */ 80838032Speter else 80938032Speter { 81090792Sgshapiro found = false; 81164562Sgshapiro status = EX_UNAVAILABLE; 81238032Speter } 81338032Speter 81438032Speter /* 81538032Speter ** Heuristic: if $m is not set, we are running during system 81638032Speter ** startup. In this case, when a name is apparently found 81738032Speter ** but has no dot, treat is as not found. This avoids 81838032Speter ** problems if /etc/hosts has no FQDN but is listed first 81938032Speter ** in the service switch. 82038032Speter */ 82138032Speter 82238032Speter if (found && 82338032Speter (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 82438032Speter break; 82538032Speter 826168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 827168515Sgshapiro if (found) 828168515Sgshapiro should_try_nis_domain = true; 829168515Sgshapiro /* but don't break, as we need to try all methods first */ 830168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 831168515Sgshapiro 83238032Speter /* see if we should continue */ 83364562Sgshapiro if (status == EX_TEMPFAIL) 83438032Speter { 83538032Speter i = MA_TRYAGAIN; 83690792Sgshapiro got_tempfail = true; 83738032Speter } 83864562Sgshapiro else if (status == EX_NOTFOUND) 83938032Speter i = MA_NOTFOUND; 84038032Speter else 84138032Speter i = MA_UNAVAIL; 84238032Speter if (bitset(1 << mapno, mapreturn[i])) 84338032Speter break; 84438032Speter } 84538032Speter 84638032Speter if (found) 84738032Speter { 84838032Speter char *d; 84938032Speter 85038032Speter if (tTd(38, 20)) 851363466Sgshapiro sm_dprintf("getcanonname(%s), found, ad=%d\n", host, secure); 85238032Speter 85338032Speter /* 85438032Speter ** If returned name is still single token, compensate 85538032Speter ** by tagging on $m. This is because some sites set 85638032Speter ** up their DNS or NIS databases wrong. 85738032Speter */ 85838032Speter 85938032Speter if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 86038032Speter { 86138032Speter d = macvalue('m', CurEnv); 86238032Speter if (d != NULL && 86338032Speter hbsize > (int) (strlen(host) + strlen(d) + 1)) 86438032Speter { 86538032Speter if (host[strlen(host) - 1] != '.') 86690792Sgshapiro (void) sm_strlcat2(host, ".", d, 86790792Sgshapiro hbsize); 86890792Sgshapiro else 86990792Sgshapiro (void) sm_strlcat(host, d, hbsize); 87038032Speter } 87138032Speter else 872168515Sgshapiro { 873168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 874168515Sgshapiro if (VendorCode == VENDOR_SUN && 875168515Sgshapiro should_try_nis_domain) 876168515Sgshapiro { 877168515Sgshapiro goto try_nis_domain; 878168515Sgshapiro } 879168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 880363466Sgshapiro return HOST_NOTFOUND; 881168515Sgshapiro } 88238032Speter } 883363466Sgshapiro return secure ? HOST_SECURE : HOST_OK; 88438032Speter } 88538032Speter 886168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 887168515Sgshapiro if (VendorCode == VENDOR_SUN && should_try_nis_domain) 888168515Sgshapiro { 889168515Sgshapiro try_nis_domain: 890168515Sgshapiro if (nis_domain != NULL && 891168515Sgshapiro strlen(nis_domain) + strlen(host) + 1 < hbsize) 892168515Sgshapiro { 893168515Sgshapiro (void) sm_strlcat2(host, ".", nis_domain, hbsize); 894363466Sgshapiro return HOST_OK; 895168515Sgshapiro } 896168515Sgshapiro } 897168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 898168515Sgshapiro 89938032Speter if (tTd(38, 20)) 90090792Sgshapiro sm_dprintf("getcanonname(%s), failed, status=%d\n", host, 90190792Sgshapiro status); 90238032Speter 90338032Speter if (got_tempfail) 90473188Sgshapiro SM_SET_H_ERRNO(TRY_AGAIN); 90538032Speter else 90673188Sgshapiro SM_SET_H_ERRNO(HOST_NOT_FOUND); 90790792Sgshapiro 908363466Sgshapiro return HOST_NOTFOUND; 90938032Speter} 91090792Sgshapiro/* 91138032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 91238032Speter** 91338032Speter** Parameters: 91438032Speter** name -- the name against which to match. 91573188Sgshapiro** dot -- where to reinsert '.' to get FQDN 91638032Speter** line -- the /etc/hosts line. 91738032Speter** cbuf -- the location to store the result. 91838032Speter** cbuflen -- the size of cbuf. 91938032Speter** 92038032Speter** Returns: 92190792Sgshapiro** true -- if the line matched the desired name. 92290792Sgshapiro** false -- otherwise. 92338032Speter*/ 92438032Speter 92564562Sgshapirostatic bool 92673188Sgshapiroextract_canonname(name, dot, line, cbuf, cbuflen) 92738032Speter char *name; 92873188Sgshapiro char *dot; 92938032Speter char *line; 93038032Speter char cbuf[]; 93138032Speter int cbuflen; 93238032Speter{ 93338032Speter int i; 93438032Speter char *p; 93590792Sgshapiro bool found = false; 93638032Speter 93738032Speter cbuf[0] = '\0'; 93838032Speter if (line[0] == '#') 93990792Sgshapiro return false; 94038032Speter 94138032Speter for (i = 1; ; i++) 94238032Speter { 94338032Speter char nbuf[MAXNAME + 1]; 94438032Speter 945168515Sgshapiro p = get_column(line, i, '\0', nbuf, sizeof(nbuf)); 94638032Speter if (p == NULL) 94738032Speter break; 94838032Speter if (*p == '\0') 94938032Speter continue; 95038032Speter if (cbuf[0] == '\0' || 95138032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 95238032Speter { 95390792Sgshapiro (void) sm_strlcpy(cbuf, p, cbuflen); 95438032Speter } 95590792Sgshapiro if (sm_strcasecmp(name, p) == 0) 95690792Sgshapiro found = true; 95773188Sgshapiro else if (dot != NULL) 95873188Sgshapiro { 95973188Sgshapiro /* try looking for the FQDN as well */ 96073188Sgshapiro *dot = '.'; 96190792Sgshapiro if (sm_strcasecmp(name, p) == 0) 96290792Sgshapiro found = true; 96373188Sgshapiro *dot = '\0'; 96473188Sgshapiro } 96538032Speter } 96638032Speter if (found && strchr(cbuf, '.') == NULL) 96738032Speter { 96838032Speter /* try to add a domain on the end of the name */ 96938032Speter char *domain = macvalue('m', CurEnv); 97038032Speter 97138032Speter if (domain != NULL && 97264562Sgshapiro strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 97338032Speter { 97464562Sgshapiro p = &cbuf[i]; 97538032Speter *p++ = '.'; 97690792Sgshapiro (void) sm_strlcpy(p, domain, cbuflen - i - 1); 97738032Speter } 97838032Speter } 97938032Speter return found; 98038032Speter} 98190792Sgshapiro 98290792Sgshapiro/* 98390792Sgshapiro** DNS modules 98490792Sgshapiro*/ 98590792Sgshapiro 98690792Sgshapiro#if NAMED_BIND 98790792Sgshapiro# if DNSMAP 98890792Sgshapiro 98990792Sgshapiro# include "sm_resolve.h" 99090792Sgshapiro# if NETINET || NETINET6 99190792Sgshapiro# include <arpa/inet.h> 992363466Sgshapiro# endif 99390792Sgshapiro 99490792Sgshapiro/* 99590792Sgshapiro** DNS_MAP_OPEN -- stub to check proper value for dns map type 99690792Sgshapiro*/ 99790792Sgshapiro 99890792Sgshapirobool 99990792Sgshapirodns_map_open(map, mode) 100090792Sgshapiro MAP *map; 100190792Sgshapiro int mode; 100290792Sgshapiro{ 100390792Sgshapiro if (tTd(38,2)) 100490792Sgshapiro sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode); 100590792Sgshapiro 100690792Sgshapiro mode &= O_ACCMODE; 100790792Sgshapiro if (mode != O_RDONLY) 100890792Sgshapiro { 100990792Sgshapiro /* issue a pseudo-error message */ 101090792Sgshapiro errno = SM_EMAPCANTWRITE; 101190792Sgshapiro return false; 101290792Sgshapiro } 101390792Sgshapiro return true; 101490792Sgshapiro} 101590792Sgshapiro 101690792Sgshapiro/* 101790792Sgshapiro** DNS_MAP_PARSEARGS -- parse dns map definition args. 101890792Sgshapiro** 101990792Sgshapiro** Parameters: 102090792Sgshapiro** map -- pointer to MAP 102190792Sgshapiro** args -- pointer to the args on the config line. 102290792Sgshapiro** 102390792Sgshapiro** Returns: 102490792Sgshapiro** true -- if everything parsed OK. 102590792Sgshapiro** false -- otherwise. 102690792Sgshapiro*/ 102790792Sgshapiro 1028168515Sgshapiro#define map_sizelimit map_lockfd /* overload field */ 102990792Sgshapiro 103090792Sgshapirostruct dns_map 103190792Sgshapiro{ 103290792Sgshapiro int dns_m_type; 1033363466Sgshapiro unsigned int dns_m_options; 103490792Sgshapiro}; 103590792Sgshapiro 103690792Sgshapirobool 103790792Sgshapirodns_map_parseargs(map,args) 103890792Sgshapiro MAP *map; 103990792Sgshapiro char *args; 104090792Sgshapiro{ 104190792Sgshapiro register char *p = args; 104290792Sgshapiro struct dns_map *map_p; 104390792Sgshapiro 1044168515Sgshapiro map_p = (struct dns_map *) xalloc(sizeof(*map_p)); 1045363466Sgshapiro memset(map_p, '\0', sizeof(*map_p)); 104690792Sgshapiro map_p->dns_m_type = -1; 104790792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 104890792Sgshapiro 104990792Sgshapiro for (;;) 105090792Sgshapiro { 1051363466Sgshapiro while (SM_ISSPACE(*p)) 105290792Sgshapiro p++; 105390792Sgshapiro if (*p != '-') 105490792Sgshapiro break; 105590792Sgshapiro switch (*++p) 105690792Sgshapiro { 1057363466Sgshapiro#if DNSSEC_TEST 1058363466Sgshapiro case '@': 1059363466Sgshapiro ++p; 1060363466Sgshapiro if (nsportip(p) < 0) 1061363466Sgshapiro syserr("dns map %s: nsportip(%s)=failed", 1062363466Sgshapiro map->map_mname, p); 106390792Sgshapiro break; 1064363466Sgshapiro#endif /* DNSSEC_TEST */ 106590792Sgshapiro 106690792Sgshapiro case 'A': 106790792Sgshapiro map->map_mflags |= MF_APPEND; 106890792Sgshapiro break; 106990792Sgshapiro 107090792Sgshapiro case 'a': 107190792Sgshapiro map->map_app = ++p; 107290792Sgshapiro break; 107390792Sgshapiro 1074363466Sgshapiro case 'B': /* base domain */ 1075363466Sgshapiro { 1076363466Sgshapiro char *h; 1077363466Sgshapiro 1078363466Sgshapiro while (isascii(*++p) && isspace(*p)) 1079363466Sgshapiro continue; 1080363466Sgshapiro h = strchr(p, ' '); 1081363466Sgshapiro if (h != NULL) 1082363466Sgshapiro *h = '\0'; 1083363466Sgshapiro 1084363466Sgshapiro /* 1085363466Sgshapiro ** slight abuse of map->map_file; it isn't 1086363466Sgshapiro ** used otherwise in this map type. 1087363466Sgshapiro */ 1088363466Sgshapiro 1089363466Sgshapiro map->map_file = newstr(p); 1090363466Sgshapiro if (h != NULL) 1091363466Sgshapiro *h = ' '; 1092363466Sgshapiro } 109390792Sgshapiro break; 109490792Sgshapiro 109590792Sgshapiro case 'd': 109690792Sgshapiro { 109790792Sgshapiro char *h; 109890792Sgshapiro 109990792Sgshapiro ++p; 110090792Sgshapiro h = strchr(p, ' '); 110190792Sgshapiro if (h != NULL) 110290792Sgshapiro *h = '\0'; 110390792Sgshapiro map->map_timeout = convtime(p, 's'); 110490792Sgshapiro if (h != NULL) 110590792Sgshapiro *h = ' '; 110690792Sgshapiro } 110790792Sgshapiro break; 110890792Sgshapiro 1109363466Sgshapiro case 'f': 1110363466Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 1111363466Sgshapiro break; 1112363466Sgshapiro 1113363466Sgshapiro case 'm': 1114363466Sgshapiro map->map_mflags |= MF_MATCHONLY; 1115363466Sgshapiro break; 1116363466Sgshapiro 1117363466Sgshapiro case 'N': 1118363466Sgshapiro map->map_mflags |= MF_INCLNULL; 1119363466Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 1120363466Sgshapiro break; 1121363466Sgshapiro 1122363466Sgshapiro case 'O': 1123363466Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 1124363466Sgshapiro break; 1125363466Sgshapiro 1126363466Sgshapiro case 'o': 1127363466Sgshapiro map->map_mflags |= MF_OPTIONAL; 1128363466Sgshapiro break; 1129363466Sgshapiro 1130363466Sgshapiro case 'q': 1131363466Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 1132363466Sgshapiro break; 1133363466Sgshapiro 1134363466Sgshapiro case 'S': 1135363466Sgshapiro#if defined(RES_USE_EDNS0) && defined(RES_USE_DNSSEC) 1136363466Sgshapiro map_p->dns_m_options |= SM_RES_DNSSEC; 1137363466Sgshapiro#endif 1138363466Sgshapiro break; 1139363466Sgshapiro 114090792Sgshapiro case 'r': 114190792Sgshapiro while (isascii(*++p) && isspace(*p)) 114290792Sgshapiro continue; 114390792Sgshapiro map->map_retry = atoi(p); 114490792Sgshapiro break; 114590792Sgshapiro 1146363466Sgshapiro case 't': 1147363466Sgshapiro map->map_mflags |= MF_NODEFER; 1148363466Sgshapiro break; 1149363466Sgshapiro 1150363466Sgshapiro case 'T': 1151363466Sgshapiro map->map_tapp = ++p; 1152363466Sgshapiro break; 1153363466Sgshapiro 115490792Sgshapiro case 'z': 115590792Sgshapiro if (*++p != '\\') 115690792Sgshapiro map->map_coldelim = *p; 115790792Sgshapiro else 115890792Sgshapiro { 115990792Sgshapiro switch (*++p) 116090792Sgshapiro { 116190792Sgshapiro case 'n': 116290792Sgshapiro map->map_coldelim = '\n'; 116390792Sgshapiro break; 116490792Sgshapiro 116590792Sgshapiro case 't': 116690792Sgshapiro map->map_coldelim = '\t'; 116790792Sgshapiro break; 116890792Sgshapiro 116990792Sgshapiro default: 117090792Sgshapiro map->map_coldelim = '\\'; 117190792Sgshapiro } 117290792Sgshapiro } 117390792Sgshapiro break; 117490792Sgshapiro 117590792Sgshapiro case 'Z': 117690792Sgshapiro while (isascii(*++p) && isspace(*p)) 117790792Sgshapiro continue; 117890792Sgshapiro map->map_sizelimit = atoi(p); 117990792Sgshapiro break; 118090792Sgshapiro 118190792Sgshapiro /* Start of dns_map specific args */ 118290792Sgshapiro case 'R': /* search field */ 118390792Sgshapiro { 118490792Sgshapiro char *h; 118590792Sgshapiro 118690792Sgshapiro while (isascii(*++p) && isspace(*p)) 118790792Sgshapiro continue; 118890792Sgshapiro h = strchr(p, ' '); 118990792Sgshapiro if (h != NULL) 119090792Sgshapiro *h = '\0'; 119190792Sgshapiro map_p->dns_m_type = dns_string_to_type(p); 119290792Sgshapiro if (h != NULL) 119390792Sgshapiro *h = ' '; 119490792Sgshapiro if (map_p->dns_m_type < 0) 119590792Sgshapiro syserr("dns map %s: wrong type %s", 119690792Sgshapiro map->map_mname, p); 119790792Sgshapiro } 119890792Sgshapiro break; 119990792Sgshapiro 120090792Sgshapiro } 1201363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 120290792Sgshapiro p++; 120390792Sgshapiro if (*p != '\0') 120490792Sgshapiro *p++ = '\0'; 120590792Sgshapiro } 120690792Sgshapiro if (map_p->dns_m_type < 0) 120790792Sgshapiro syserr("dns map %s: missing -R type", map->map_mname); 120890792Sgshapiro if (map->map_app != NULL) 120990792Sgshapiro map->map_app = newstr(map->map_app); 121090792Sgshapiro if (map->map_tapp != NULL) 121190792Sgshapiro map->map_tapp = newstr(map->map_tapp); 121290792Sgshapiro 121390792Sgshapiro /* 1214168515Sgshapiro ** Assumption: assert(sizeof(int) <= sizeof(ARBPTR_T)); 121590792Sgshapiro ** Even if this assumption is wrong, we use only one byte, 121690792Sgshapiro ** so it doesn't really matter. 121790792Sgshapiro */ 121890792Sgshapiro 121990792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; 122090792Sgshapiro return true; 122190792Sgshapiro} 122290792Sgshapiro 122390792Sgshapiro/* 122490792Sgshapiro** DNS_MAP_LOOKUP -- perform dns map lookup. 122590792Sgshapiro** 122690792Sgshapiro** Parameters: 122790792Sgshapiro** map -- pointer to MAP 122890792Sgshapiro** name -- name to lookup 122990792Sgshapiro** av -- arguments to interpolate into buf. 123090792Sgshapiro** statp -- pointer to status (EX_) 123190792Sgshapiro** 123290792Sgshapiro** Returns: 123390792Sgshapiro** result of lookup if succeeded. 123490792Sgshapiro** NULL -- otherwise. 123590792Sgshapiro*/ 123690792Sgshapiro 123790792Sgshapirochar * 123890792Sgshapirodns_map_lookup(map, name, av, statp) 123990792Sgshapiro MAP *map; 124090792Sgshapiro char *name; 124190792Sgshapiro char **av; 124290792Sgshapiro int *statp; 124390792Sgshapiro{ 124490792Sgshapiro int resnum = 0; 124590792Sgshapiro char *vp = NULL, *result = NULL; 124690792Sgshapiro size_t vsize; 124790792Sgshapiro struct dns_map *map_p; 124890792Sgshapiro RESOURCE_RECORD_T *rr = NULL; 124990792Sgshapiro DNS_REPLY_T *r = NULL; 1250363466Sgshapiro unsigned int options; 125190792Sgshapiro# if NETINET6 125290792Sgshapiro static char buf6[INET6_ADDRSTRLEN]; 1253363466Sgshapiro# endif 125490792Sgshapiro 125590792Sgshapiro if (tTd(38, 20)) 125690792Sgshapiro sm_dprintf("dns_map_lookup(%s, %s)\n", 125790792Sgshapiro map->map_mname, name); 125890792Sgshapiro 125990792Sgshapiro map_p = (struct dns_map *)(map->map_db1); 1260363466Sgshapiro options = map_p->dns_m_options; 126190792Sgshapiro if (map->map_file != NULL && *map->map_file != '\0') 126290792Sgshapiro { 126390792Sgshapiro size_t len; 126490792Sgshapiro char *appdomain; 126590792Sgshapiro 126690792Sgshapiro len = strlen(map->map_file) + strlen(name) + 2; 126790792Sgshapiro appdomain = (char *) sm_malloc(len); 126890792Sgshapiro if (appdomain == NULL) 126990792Sgshapiro { 127090792Sgshapiro *statp = EX_UNAVAILABLE; 127190792Sgshapiro return NULL; 127290792Sgshapiro } 127390792Sgshapiro (void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file); 1274363466Sgshapiro r = dns_lookup_map(appdomain, C_IN, map_p->dns_m_type, 1275363466Sgshapiro map->map_timeout, map->map_retry, options); 127690792Sgshapiro sm_free(appdomain); 127790792Sgshapiro } 127890792Sgshapiro else 127990792Sgshapiro { 1280363466Sgshapiro r = dns_lookup_map(name, C_IN, map_p->dns_m_type, 1281363466Sgshapiro map->map_timeout, map->map_retry, options); 128290792Sgshapiro } 128390792Sgshapiro 128490792Sgshapiro if (r == NULL) 128590792Sgshapiro { 128690792Sgshapiro result = NULL; 1287120256Sgshapiro if (h_errno == TRY_AGAIN || transienterror(errno)) 128890792Sgshapiro *statp = EX_TEMPFAIL; 128990792Sgshapiro else 129090792Sgshapiro *statp = EX_NOTFOUND; 129190792Sgshapiro goto cleanup; 129290792Sgshapiro } 129390792Sgshapiro *statp = EX_OK; 129490792Sgshapiro for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next) 129590792Sgshapiro { 129690792Sgshapiro char *type = NULL; 129790792Sgshapiro char *value = NULL; 129890792Sgshapiro 129990792Sgshapiro switch (rr->rr_type) 130090792Sgshapiro { 130190792Sgshapiro case T_NS: 130290792Sgshapiro type = "T_NS"; 130390792Sgshapiro value = rr->rr_u.rr_txt; 130490792Sgshapiro break; 130590792Sgshapiro case T_CNAME: 130690792Sgshapiro type = "T_CNAME"; 130790792Sgshapiro value = rr->rr_u.rr_txt; 130890792Sgshapiro break; 130990792Sgshapiro case T_AFSDB: 131090792Sgshapiro type = "T_AFSDB"; 131190792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 131290792Sgshapiro break; 131390792Sgshapiro case T_SRV: 131490792Sgshapiro type = "T_SRV"; 131590792Sgshapiro value = rr->rr_u.rr_srv->srv_r_target; 131690792Sgshapiro break; 131790792Sgshapiro case T_PTR: 131890792Sgshapiro type = "T_PTR"; 131990792Sgshapiro value = rr->rr_u.rr_txt; 132090792Sgshapiro break; 132190792Sgshapiro case T_TXT: 132290792Sgshapiro type = "T_TXT"; 132390792Sgshapiro value = rr->rr_u.rr_txt; 132490792Sgshapiro break; 132590792Sgshapiro case T_MX: 132690792Sgshapiro type = "T_MX"; 132790792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 132890792Sgshapiro break; 132990792Sgshapiro# if NETINET 133090792Sgshapiro case T_A: 133190792Sgshapiro type = "T_A"; 133290792Sgshapiro value = inet_ntoa(*(rr->rr_u.rr_a)); 133390792Sgshapiro break; 133490792Sgshapiro# endif /* NETINET */ 133590792Sgshapiro# if NETINET6 133690792Sgshapiro case T_AAAA: 133790792Sgshapiro type = "T_AAAA"; 133890792Sgshapiro value = anynet_ntop(rr->rr_u.rr_aaaa, buf6, 1339168515Sgshapiro sizeof(buf6)); 134090792Sgshapiro break; 134190792Sgshapiro# endif /* NETINET6 */ 1342363466Sgshapiro# ifdef T_TLSA 1343363466Sgshapiro case T_TLSA: 1344363466Sgshapiro type = "T_TLSA"; 1345363466Sgshapiro value = rr->rr_u.rr_txt; 1346363466Sgshapiro break; 1347363466Sgshapiro# endif /* T_TLSA */ 134890792Sgshapiro } 134990792Sgshapiro 135098841Sgshapiro (void) strreplnonprt(value, 'X'); 135190792Sgshapiro if (map_p->dns_m_type != rr->rr_type) 135290792Sgshapiro { 135390792Sgshapiro if (tTd(38, 40)) 135490792Sgshapiro sm_dprintf("\tskipping type %s (%d) value %s\n", 135590792Sgshapiro type != NULL ? type : "<UNKNOWN>", 135690792Sgshapiro rr->rr_type, 135790792Sgshapiro value != NULL ? value : "<NO VALUE>"); 135890792Sgshapiro continue; 135990792Sgshapiro } 136090792Sgshapiro 136190792Sgshapiro# if NETINET6 136290792Sgshapiro if (rr->rr_type == T_AAAA && value == NULL) 136390792Sgshapiro { 136490792Sgshapiro result = NULL; 136590792Sgshapiro *statp = EX_DATAERR; 136690792Sgshapiro if (tTd(38, 40)) 136790792Sgshapiro sm_dprintf("\tbad T_AAAA conversion\n"); 136890792Sgshapiro goto cleanup; 136990792Sgshapiro } 137090792Sgshapiro# endif /* NETINET6 */ 137190792Sgshapiro if (tTd(38, 40)) 137290792Sgshapiro sm_dprintf("\tfound type %s (%d) value %s\n", 137390792Sgshapiro type != NULL ? type : "<UNKNOWN>", 137490792Sgshapiro rr->rr_type, 137590792Sgshapiro value != NULL ? value : "<NO VALUE>"); 137690792Sgshapiro if (value != NULL && 137790792Sgshapiro (map->map_coldelim == '\0' || 137890792Sgshapiro map->map_sizelimit == 1 || 137990792Sgshapiro bitset(MF_MATCHONLY, map->map_mflags))) 138090792Sgshapiro { 138190792Sgshapiro /* Only care about the first match */ 138290792Sgshapiro vp = newstr(value); 138390792Sgshapiro break; 138490792Sgshapiro } 138590792Sgshapiro else if (vp == NULL) 138690792Sgshapiro { 138790792Sgshapiro /* First result */ 138890792Sgshapiro vp = newstr(value); 138990792Sgshapiro } 139090792Sgshapiro else 139190792Sgshapiro { 139290792Sgshapiro /* concatenate the results */ 139390792Sgshapiro int sz; 139490792Sgshapiro char *new; 139590792Sgshapiro 139690792Sgshapiro sz = strlen(vp) + strlen(value) + 2; 139790792Sgshapiro new = xalloc(sz); 139890792Sgshapiro (void) sm_snprintf(new, sz, "%s%c%s", 139990792Sgshapiro vp, map->map_coldelim, value); 140090792Sgshapiro sm_free(vp); 140190792Sgshapiro vp = new; 140290792Sgshapiro if (map->map_sizelimit > 0 && 140390792Sgshapiro ++resnum >= map->map_sizelimit) 140490792Sgshapiro break; 140590792Sgshapiro } 140690792Sgshapiro } 140790792Sgshapiro if (vp == NULL) 140890792Sgshapiro { 140990792Sgshapiro result = NULL; 141090792Sgshapiro *statp = EX_NOTFOUND; 141190792Sgshapiro if (tTd(38, 40)) 141290792Sgshapiro sm_dprintf("\tno match found\n"); 141390792Sgshapiro goto cleanup; 141490792Sgshapiro } 141590792Sgshapiro 141690792Sgshapiro /* Cleanly truncate for rulesets */ 141790792Sgshapiro truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim); 141890792Sgshapiro 141990792Sgshapiro vsize = strlen(vp); 142090792Sgshapiro 142190792Sgshapiro if (LogLevel > 9) 142290792Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s", 142390792Sgshapiro name, vp); 142490792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 142590792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 142690792Sgshapiro else 142790792Sgshapiro result = map_rewrite(map, vp, vsize, av); 142890792Sgshapiro 142990792Sgshapiro cleanup: 143090792Sgshapiro if (vp != NULL) 143190792Sgshapiro sm_free(vp); 1432363466Sgshapiro dns_free_data(r); 143390792Sgshapiro return result; 143490792Sgshapiro} 143590792Sgshapiro# endif /* DNSMAP */ 143690792Sgshapiro#endif /* NAMED_BIND */ 143790792Sgshapiro 143890792Sgshapiro/* 143938032Speter** NDBM modules 144038032Speter*/ 144138032Speter 144290792Sgshapiro#if NDBM 144338032Speter 144438032Speter/* 144538032Speter** NDBM_MAP_OPEN -- DBM-style map open 144638032Speter*/ 144738032Speter 144838032Speterbool 144938032Speterndbm_map_open(map, mode) 145038032Speter MAP *map; 145138032Speter int mode; 145238032Speter{ 145338032Speter register DBM *dbm; 145464562Sgshapiro int save_errno; 145538032Speter int dfd; 145638032Speter int pfd; 145764562Sgshapiro long sff; 145838032Speter int ret; 145938032Speter int smode = S_IREAD; 146098121Sgshapiro char dirfile[MAXPATHLEN]; 146198121Sgshapiro char pagfile[MAXPATHLEN]; 146264562Sgshapiro struct stat st; 146338032Speter struct stat std, stp; 146438032Speter 146538032Speter if (tTd(38, 2)) 146690792Sgshapiro sm_dprintf("ndbm_map_open(%s, %s, %d)\n", 146738032Speter map->map_mname, map->map_file, mode); 146838032Speter map->map_lockfd = -1; 146938032Speter mode &= O_ACCMODE; 147038032Speter 147138032Speter /* do initial file and directory checks */ 1472168515Sgshapiro if (sm_strlcpyn(dirfile, sizeof(dirfile), 2, 1473168515Sgshapiro map->map_file, ".dir") >= sizeof(dirfile) || 1474168515Sgshapiro sm_strlcpyn(pagfile, sizeof(pagfile), 2, 1475168515Sgshapiro map->map_file, ".pag") >= sizeof(pagfile)) 147698121Sgshapiro { 147798121Sgshapiro errno = 0; 147898121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 147998121Sgshapiro syserr("dbm map \"%s\": map file %s name too long", 148098121Sgshapiro map->map_mname, map->map_file); 148198121Sgshapiro return false; 148298121Sgshapiro } 148338032Speter sff = SFF_ROOTOK|SFF_REGONLY; 148438032Speter if (mode == O_RDWR) 148538032Speter { 148638032Speter sff |= SFF_CREAT; 148764562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 148838032Speter sff |= SFF_NOSLINK; 148964562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 149038032Speter sff |= SFF_NOHLINK; 149138032Speter smode = S_IWRITE; 149238032Speter } 149338032Speter else 149438032Speter { 149564562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 149638032Speter sff |= SFF_NOWLINK; 149738032Speter } 149864562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 149938032Speter sff |= SFF_SAFEDIRPATH; 150038032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 150190792Sgshapiro sff, smode, &std); 150238032Speter if (ret == 0) 150338032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 150438032Speter sff, smode, &stp); 150564562Sgshapiro 150638032Speter if (ret != 0) 150738032Speter { 150838032Speter char *prob = "unsafe"; 150938032Speter 151038032Speter /* cannot open this map */ 151138032Speter if (ret == ENOENT) 151238032Speter prob = "missing"; 151338032Speter if (tTd(38, 2)) 151490792Sgshapiro sm_dprintf("\t%s map file: %d\n", prob, ret); 151538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 151638032Speter syserr("dbm map \"%s\": %s map file %s", 151738032Speter map->map_mname, prob, map->map_file); 151890792Sgshapiro return false; 151938032Speter } 152038032Speter if (std.st_mode == ST_MODE_NOFILE) 152138032Speter mode |= O_CREAT|O_EXCL; 152238032Speter 152364562Sgshapiro# if LOCK_ON_OPEN 152438032Speter if (mode == O_RDONLY) 152538032Speter mode |= O_SHLOCK; 152638032Speter else 152738032Speter mode |= O_TRUNC|O_EXLOCK; 152864562Sgshapiro# else /* LOCK_ON_OPEN */ 152938032Speter if ((mode & O_ACCMODE) == O_RDWR) 153038032Speter { 153164562Sgshapiro# if NOFTRUNCATE 153238032Speter /* 153338032Speter ** Warning: race condition. Try to lock the file as 153438032Speter ** quickly as possible after opening it. 153538032Speter ** This may also have security problems on some systems, 153638032Speter ** but there isn't anything we can do about it. 153738032Speter */ 153838032Speter 153938032Speter mode |= O_TRUNC; 154064562Sgshapiro# else /* NOFTRUNCATE */ 154138032Speter /* 154238032Speter ** This ugly code opens the map without truncating it, 154338032Speter ** locks the file, then truncates it. Necessary to 154438032Speter ** avoid race conditions. 154538032Speter */ 154638032Speter 154738032Speter int dirfd; 154838032Speter int pagfd; 154964562Sgshapiro long sff = SFF_CREAT|SFF_OPENASROOT; 155038032Speter 155164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 155238032Speter sff |= SFF_NOSLINK; 155364562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 155438032Speter sff |= SFF_NOHLINK; 155538032Speter 155638032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 155738032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 155838032Speter 155938032Speter if (dirfd < 0 || pagfd < 0) 156038032Speter { 156164562Sgshapiro save_errno = errno; 156238032Speter if (dirfd >= 0) 156338032Speter (void) close(dirfd); 156438032Speter if (pagfd >= 0) 156538032Speter (void) close(pagfd); 156638032Speter errno = save_errno; 156738032Speter syserr("ndbm_map_open: cannot create database %s", 156838032Speter map->map_file); 156990792Sgshapiro return false; 157038032Speter } 157138032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 157238032Speter ftruncate(pagfd, (off_t) 0) < 0) 157338032Speter { 157464562Sgshapiro save_errno = errno; 157538032Speter (void) close(dirfd); 157638032Speter (void) close(pagfd); 157738032Speter errno = save_errno; 157838032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 157938032Speter map->map_file); 158090792Sgshapiro return false; 158138032Speter } 158238032Speter 158338032Speter /* if new file, get "before" bits for later filechanged check */ 158438032Speter if (std.st_mode == ST_MODE_NOFILE && 158538032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 158638032Speter { 158764562Sgshapiro save_errno = errno; 158838032Speter (void) close(dirfd); 158938032Speter (void) close(pagfd); 159038032Speter errno = save_errno; 159138032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 159238032Speter map->map_file); 159390792Sgshapiro return false; 159438032Speter } 159538032Speter 159638032Speter /* have to save the lock for the duration (bletch) */ 159738032Speter map->map_lockfd = dirfd; 159864562Sgshapiro (void) close(pagfd); 159938032Speter 160038032Speter /* twiddle bits for dbm_open */ 160138032Speter mode &= ~(O_CREAT|O_EXCL); 160264562Sgshapiro# endif /* NOFTRUNCATE */ 160338032Speter } 160464562Sgshapiro# endif /* LOCK_ON_OPEN */ 160538032Speter 160638032Speter /* open the database */ 160738032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 160838032Speter if (dbm == NULL) 160938032Speter { 161064562Sgshapiro save_errno = errno; 161138032Speter if (bitset(MF_ALIAS, map->map_mflags) && 161290792Sgshapiro aliaswait(map, ".pag", false)) 161390792Sgshapiro return true; 161464562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 161538032Speter if (map->map_lockfd >= 0) 161664562Sgshapiro (void) close(map->map_lockfd); 1617363466Sgshapiro# endif 161838032Speter errno = save_errno; 161938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 162038032Speter syserr("Cannot open DBM database %s", map->map_file); 162190792Sgshapiro return false; 162238032Speter } 162338032Speter dfd = dbm_dirfno(dbm); 162438032Speter pfd = dbm_pagfno(dbm); 162538032Speter if (dfd == pfd) 162638032Speter { 162738032Speter /* heuristic: if files are linked, this is actually gdbm */ 162838032Speter dbm_close(dbm); 162964562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 163038032Speter if (map->map_lockfd >= 0) 163164562Sgshapiro (void) close(map->map_lockfd); 1632363466Sgshapiro# endif 163338032Speter errno = 0; 163438032Speter syserr("dbm map \"%s\": cannot support GDBM", 163538032Speter map->map_mname); 163690792Sgshapiro return false; 163738032Speter } 163838032Speter 163938032Speter if (filechanged(dirfile, dfd, &std) || 164038032Speter filechanged(pagfile, pfd, &stp)) 164138032Speter { 164264562Sgshapiro save_errno = errno; 164338032Speter dbm_close(dbm); 164464562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 164538032Speter if (map->map_lockfd >= 0) 164664562Sgshapiro (void) close(map->map_lockfd); 1647363466Sgshapiro# endif 164838032Speter errno = save_errno; 164938032Speter syserr("ndbm_map_open(%s): file changed after open", 165038032Speter map->map_file); 165190792Sgshapiro return false; 165238032Speter } 165338032Speter 165438032Speter map->map_db1 = (ARBPTR_T) dbm; 165564562Sgshapiro 165664562Sgshapiro /* 165764562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 165864562Sgshapiro ** as aliaswait() will call map_lookup() which requires 165964562Sgshapiro ** map_mtime to be set 166064562Sgshapiro */ 166164562Sgshapiro 166277349Sgshapiro if (fstat(pfd, &st) >= 0) 166364562Sgshapiro map->map_mtime = st.st_mtime; 166464562Sgshapiro 166538032Speter if (mode == O_RDONLY) 166638032Speter { 166764562Sgshapiro# if LOCK_ON_OPEN 166838032Speter if (dfd >= 0) 166938032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 167038032Speter if (pfd >= 0) 167138032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 167264562Sgshapiro# endif /* LOCK_ON_OPEN */ 167338032Speter if (bitset(MF_ALIAS, map->map_mflags) && 167490792Sgshapiro !aliaswait(map, ".pag", true)) 167590792Sgshapiro return false; 167638032Speter } 167738032Speter else 167838032Speter { 167938032Speter map->map_mflags |= MF_LOCKED; 168042575Speter if (geteuid() == 0 && TrustedUid != 0) 168138032Speter { 168264562Sgshapiro# if HASFCHOWN 168342575Speter if (fchown(dfd, TrustedUid, -1) < 0 || 168442575Speter fchown(pfd, TrustedUid, -1) < 0) 168538032Speter { 168638032Speter int err = errno; 168738032Speter 168838032Speter sm_syslog(LOG_ALERT, NOQID, 168938032Speter "ownership change on %s failed: %s", 169090792Sgshapiro map->map_file, sm_errstring(err)); 169138032Speter message("050 ownership change on %s failed: %s", 169290792Sgshapiro map->map_file, sm_errstring(err)); 169338032Speter } 169490792Sgshapiro# else /* HASFCHOWN */ 169590792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 169690792Sgshapiro "no fchown(): cannot change ownership on %s", 169790792Sgshapiro map->map_file); 169890792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 169990792Sgshapiro map->map_file); 170064562Sgshapiro# endif /* HASFCHOWN */ 170138032Speter } 170238032Speter } 170390792Sgshapiro return true; 170438032Speter} 170538032Speter 170638032Speter 170738032Speter/* 170838032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 170938032Speter*/ 171038032Speter 171138032Speterchar * 171238032Speterndbm_map_lookup(map, name, av, statp) 171338032Speter MAP *map; 171438032Speter char *name; 171538032Speter char **av; 171638032Speter int *statp; 171738032Speter{ 171838032Speter datum key, val; 171977349Sgshapiro int dfd, pfd; 172038032Speter char keybuf[MAXNAME + 1]; 172138032Speter struct stat stbuf; 172238032Speter 172338032Speter if (tTd(38, 20)) 172490792Sgshapiro sm_dprintf("ndbm_map_lookup(%s, %s)\n", 172538032Speter map->map_mname, name); 172638032Speter 172738032Speter key.dptr = name; 172838032Speter key.dsize = strlen(name); 172938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 173038032Speter { 1731168515Sgshapiro if (key.dsize > sizeof(keybuf) - 1) 1732168515Sgshapiro key.dsize = sizeof(keybuf) - 1; 173364562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 173438032Speter keybuf[key.dsize] = '\0'; 173538032Speter makelower(keybuf); 173638032Speter key.dptr = keybuf; 173738032Speter } 173838032Speterlockdbm: 173977349Sgshapiro dfd = dbm_dirfno((DBM *) map->map_db1); 174077349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 174177349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_SH); 174277349Sgshapiro pfd = dbm_pagfno((DBM *) map->map_db1); 174377349Sgshapiro if (pfd < 0 || fstat(pfd, &stbuf) < 0 || 174477349Sgshapiro stbuf.st_mtime > map->map_mtime) 174538032Speter { 174638032Speter /* Reopen the database to sync the cache */ 174738032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 174838032Speter : O_RDONLY; 174938032Speter 175077349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 175177349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 175277349Sgshapiro map->map_mflags |= MF_CLOSING; 175338032Speter map->map_class->map_close(map); 175477349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 175538032Speter if (map->map_class->map_open(map, omode)) 175638032Speter { 175738032Speter map->map_mflags |= MF_OPEN; 175890792Sgshapiro map->map_pid = CurrentPid; 1759203004Sgshapiro if ((omode & O_ACCMODE) == O_RDWR) 176038032Speter map->map_mflags |= MF_WRITABLE; 176138032Speter goto lockdbm; 176238032Speter } 176338032Speter else 176438032Speter { 176538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 176638032Speter { 176738032Speter extern MAPCLASS BogusMapClass; 176838032Speter 176938032Speter *statp = EX_TEMPFAIL; 177090792Sgshapiro map->map_orgclass = map->map_class; 177138032Speter map->map_class = &BogusMapClass; 177238032Speter map->map_mflags |= MF_OPEN; 177390792Sgshapiro map->map_pid = CurrentPid; 177438032Speter syserr("Cannot reopen NDBM database %s", 177538032Speter map->map_file); 177638032Speter } 177738032Speter return NULL; 177838032Speter } 177938032Speter } 178038032Speter val.dptr = NULL; 178138032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 178238032Speter { 178338032Speter val = dbm_fetch((DBM *) map->map_db1, key); 178438032Speter if (val.dptr != NULL) 178538032Speter map->map_mflags &= ~MF_TRY1NULL; 178638032Speter } 178738032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 178838032Speter { 178938032Speter key.dsize++; 179038032Speter val = dbm_fetch((DBM *) map->map_db1, key); 179138032Speter if (val.dptr != NULL) 179238032Speter map->map_mflags &= ~MF_TRY0NULL; 179338032Speter } 179477349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 179577349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 179638032Speter if (val.dptr == NULL) 179738032Speter return NULL; 179838032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 179938032Speter return map_rewrite(map, name, strlen(name), NULL); 180038032Speter else 180138032Speter return map_rewrite(map, val.dptr, val.dsize, av); 180238032Speter} 180338032Speter 180438032Speter 180538032Speter/* 180638032Speter** NDBM_MAP_STORE -- store a datum in the database 180738032Speter*/ 180838032Speter 180938032Spetervoid 181038032Speterndbm_map_store(map, lhs, rhs) 181138032Speter register MAP *map; 181238032Speter char *lhs; 181338032Speter char *rhs; 181438032Speter{ 181538032Speter datum key; 181638032Speter datum data; 181764562Sgshapiro int status; 181838032Speter char keybuf[MAXNAME + 1]; 181938032Speter 182038032Speter if (tTd(38, 12)) 182190792Sgshapiro sm_dprintf("ndbm_map_store(%s, %s, %s)\n", 182238032Speter map->map_mname, lhs, rhs); 182338032Speter 182438032Speter key.dsize = strlen(lhs); 182538032Speter key.dptr = lhs; 182638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 182738032Speter { 1828168515Sgshapiro if (key.dsize > sizeof(keybuf) - 1) 1829168515Sgshapiro key.dsize = sizeof(keybuf) - 1; 183064562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 183138032Speter keybuf[key.dsize] = '\0'; 183238032Speter makelower(keybuf); 183338032Speter key.dptr = keybuf; 183438032Speter } 183538032Speter 183638032Speter data.dsize = strlen(rhs); 183738032Speter data.dptr = rhs; 183838032Speter 183938032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 184038032Speter { 184138032Speter key.dsize++; 184238032Speter data.dsize++; 184338032Speter } 184438032Speter 184564562Sgshapiro status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 184664562Sgshapiro if (status > 0) 184738032Speter { 184838032Speter if (!bitset(MF_APPEND, map->map_mflags)) 184938032Speter message("050 Warning: duplicate alias name %s", lhs); 185038032Speter else 185138032Speter { 185238032Speter static char *buf = NULL; 185338032Speter static int bufsiz = 0; 185438032Speter auto int xstat; 185538032Speter datum old; 185638032Speter 185738032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 185890792Sgshapiro (char **) NULL, &xstat); 185938032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 186038032Speter { 186138032Speter old.dsize = strlen(old.dptr); 186238032Speter if (data.dsize + old.dsize + 2 > bufsiz) 186338032Speter { 186438032Speter if (buf != NULL) 186590792Sgshapiro (void) sm_free(buf); 186638032Speter bufsiz = data.dsize + old.dsize + 2; 186790792Sgshapiro buf = sm_pmalloc_x(bufsiz); 186838032Speter } 186990792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 187090792Sgshapiro data.dptr, ",", old.dptr); 187138032Speter data.dsize = data.dsize + old.dsize + 1; 187238032Speter data.dptr = buf; 187338032Speter if (tTd(38, 9)) 187490792Sgshapiro sm_dprintf("ndbm_map_store append=%s\n", 1875363466Sgshapiro data.dptr); 187638032Speter } 187738032Speter } 187864562Sgshapiro status = dbm_store((DBM *) map->map_db1, 187964562Sgshapiro key, data, DBM_REPLACE); 188038032Speter } 188164562Sgshapiro if (status != 0) 188264562Sgshapiro syserr("readaliases: dbm put (%s): %d", lhs, status); 188338032Speter} 188438032Speter 188538032Speter 188638032Speter/* 188738032Speter** NDBM_MAP_CLOSE -- close the database 188838032Speter*/ 188938032Speter 189038032Spetervoid 189138032Speterndbm_map_close(map) 189238032Speter register MAP *map; 189338032Speter{ 189438032Speter if (tTd(38, 9)) 189590792Sgshapiro sm_dprintf("ndbm_map_close(%s, %s, %lx)\n", 189638032Speter map->map_mname, map->map_file, map->map_mflags); 189738032Speter 189838032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 189938032Speter { 190064562Sgshapiro# ifdef NDBM_YP_COMPAT 190138032Speter bool inclnull; 190242575Speter char buf[MAXHOSTNAMELEN]; 190338032Speter 190438032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 190538032Speter map->map_mflags &= ~MF_INCLNULL; 190638032Speter 190738032Speter if (strstr(map->map_file, "/yp/") != NULL) 190838032Speter { 190938032Speter long save_mflags = map->map_mflags; 191038032Speter 191138032Speter map->map_mflags |= MF_NOFOLDCASE; 191238032Speter 1913168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%010ld", curtime()); 191438032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 191538032Speter 1916168515Sgshapiro (void) gethostname(buf, sizeof(buf)); 191738032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 191838032Speter 191938032Speter map->map_mflags = save_mflags; 192038032Speter } 192138032Speter 192238032Speter if (inclnull) 192338032Speter map->map_mflags |= MF_INCLNULL; 192464562Sgshapiro# endif /* NDBM_YP_COMPAT */ 192538032Speter 192638032Speter /* write out the distinguished alias */ 192738032Speter ndbm_map_store(map, "@", "@"); 192838032Speter } 192938032Speter dbm_close((DBM *) map->map_db1); 193038032Speter 193138032Speter /* release lock (if needed) */ 193264562Sgshapiro# if !LOCK_ON_OPEN 193338032Speter if (map->map_lockfd >= 0) 193438032Speter (void) close(map->map_lockfd); 1935363466Sgshapiro# endif 193638032Speter} 193738032Speter 193864562Sgshapiro#endif /* NDBM */ 193990792Sgshapiro/* 194038032Speter** NEWDB (Hash and BTree) Modules 194138032Speter*/ 194238032Speter 194390792Sgshapiro#if NEWDB 194438032Speter 194538032Speter/* 194638032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 194738032Speter** 194838032Speter** These do rather bizarre locking. If you can lock on open, 194938032Speter** do that to avoid the condition of opening a database that 195038032Speter** is being rebuilt. If you don't, we'll try to fake it, but 195138032Speter** there will be a race condition. If opening for read-only, 195238032Speter** we immediately release the lock to avoid freezing things up. 195338032Speter** We really ought to hold the lock, but guarantee that we won't 195438032Speter** be pokey about it. That's hard to do. 195538032Speter*/ 195638032Speter 195738032Speter/* these should be K line arguments */ 195864562Sgshapiro# if DB_VERSION_MAJOR < 2 195964562Sgshapiro# define db_cachesize cachesize 196064562Sgshapiro# define h_nelem nelem 196164562Sgshapiro# ifndef DB_CACHE_SIZE 196264562Sgshapiro# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 1963363466Sgshapiro# endif 196464562Sgshapiro# ifndef DB_HASH_NELEM 196564562Sgshapiro# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 1966363466Sgshapiro# endif 196764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 196838032Speter 196938032Speterbool 197038032Speterbt_map_open(map, mode) 197138032Speter MAP *map; 197238032Speter int mode; 197338032Speter{ 197464562Sgshapiro# if DB_VERSION_MAJOR < 2 197538032Speter BTREEINFO btinfo; 1976363466Sgshapiro# endif 197764562Sgshapiro# if DB_VERSION_MAJOR == 2 197838032Speter DB_INFO btinfo; 1979363466Sgshapiro# endif 198064562Sgshapiro# if DB_VERSION_MAJOR > 2 198164562Sgshapiro void *btinfo = NULL; 1982363466Sgshapiro# endif 198338032Speter 198438032Speter if (tTd(38, 2)) 198590792Sgshapiro sm_dprintf("bt_map_open(%s, %s, %d)\n", 198638032Speter map->map_mname, map->map_file, mode); 198738032Speter 198864562Sgshapiro# if DB_VERSION_MAJOR < 3 1989168515Sgshapiro memset(&btinfo, '\0', sizeof(btinfo)); 199064562Sgshapiro# ifdef DB_CACHE_SIZE 199138032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 1992363466Sgshapiro# endif 199364562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 199464562Sgshapiro 199538032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 199638032Speter} 199738032Speter 199838032Speterbool 199938032Speterhash_map_open(map, mode) 200038032Speter MAP *map; 200138032Speter int mode; 200238032Speter{ 200364562Sgshapiro# if DB_VERSION_MAJOR < 2 200438032Speter HASHINFO hinfo; 2005363466Sgshapiro# endif 200664562Sgshapiro# if DB_VERSION_MAJOR == 2 200738032Speter DB_INFO hinfo; 2008363466Sgshapiro# endif 200964562Sgshapiro# if DB_VERSION_MAJOR > 2 201064562Sgshapiro void *hinfo = NULL; 2011363466Sgshapiro# endif 201238032Speter 201338032Speter if (tTd(38, 2)) 201490792Sgshapiro sm_dprintf("hash_map_open(%s, %s, %d)\n", 201538032Speter map->map_mname, map->map_file, mode); 201638032Speter 201764562Sgshapiro# if DB_VERSION_MAJOR < 3 2018168515Sgshapiro memset(&hinfo, '\0', sizeof(hinfo)); 201964562Sgshapiro# ifdef DB_HASH_NELEM 202038032Speter hinfo.h_nelem = DB_HASH_NELEM; 2021363466Sgshapiro# endif 202264562Sgshapiro# ifdef DB_CACHE_SIZE 202338032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 2024363466Sgshapiro# endif 202564562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 202664562Sgshapiro 202738032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 202838032Speter} 202938032Speter 203064562Sgshapirostatic bool 203138032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 203238032Speter MAP *map; 203338032Speter int mode; 203438032Speter char *mapclassname; 203538032Speter DBTYPE dbtype; 203664562Sgshapiro# if DB_VERSION_MAJOR < 2 203738032Speter const void *openinfo; 2038363466Sgshapiro# endif 203964562Sgshapiro# if DB_VERSION_MAJOR == 2 204038032Speter DB_INFO *openinfo; 2041363466Sgshapiro# endif 204264562Sgshapiro# if DB_VERSION_MAJOR > 2 204364562Sgshapiro void **openinfo; 2044363466Sgshapiro# endif 204538032Speter{ 204638032Speter DB *db = NULL; 204738032Speter int i; 204838032Speter int omode; 204938032Speter int smode = S_IREAD; 205038032Speter int fd; 205164562Sgshapiro long sff; 205264562Sgshapiro int save_errno; 205338032Speter struct stat st; 205498121Sgshapiro char buf[MAXPATHLEN]; 205538032Speter 205638032Speter /* do initial file and directory checks */ 2057168515Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf)) 205898121Sgshapiro { 205998121Sgshapiro errno = 0; 206098121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 206198121Sgshapiro syserr("map \"%s\": map file %s name too long", 206298121Sgshapiro map->map_mname, map->map_file); 206398121Sgshapiro return false; 206498121Sgshapiro } 206538032Speter i = strlen(buf); 206638032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 206798121Sgshapiro { 2068168515Sgshapiro if (sm_strlcat(buf, ".db", sizeof(buf)) >= sizeof(buf)) 206998121Sgshapiro { 207098121Sgshapiro errno = 0; 207198121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 207298121Sgshapiro syserr("map \"%s\": map file %s name too long", 207398121Sgshapiro map->map_mname, map->map_file); 207498121Sgshapiro return false; 207598121Sgshapiro } 207698121Sgshapiro } 207738032Speter 207838032Speter mode &= O_ACCMODE; 207938032Speter omode = mode; 208038032Speter 208138032Speter sff = SFF_ROOTOK|SFF_REGONLY; 208238032Speter if (mode == O_RDWR) 208338032Speter { 208438032Speter sff |= SFF_CREAT; 208564562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 208638032Speter sff |= SFF_NOSLINK; 208764562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 208838032Speter sff |= SFF_NOHLINK; 208938032Speter smode = S_IWRITE; 209038032Speter } 209138032Speter else 209238032Speter { 209364562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 209438032Speter sff |= SFF_NOWLINK; 209538032Speter } 209664562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 209738032Speter sff |= SFF_SAFEDIRPATH; 209838032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 209964562Sgshapiro 210038032Speter if (i != 0) 210138032Speter { 210238032Speter char *prob = "unsafe"; 210338032Speter 210438032Speter /* cannot open this map */ 210538032Speter if (i == ENOENT) 210638032Speter prob = "missing"; 210738032Speter if (tTd(38, 2)) 210890792Sgshapiro sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i)); 210938032Speter errno = i; 211038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 211138032Speter syserr("%s map \"%s\": %s map file %s", 211238032Speter mapclassname, map->map_mname, prob, buf); 211390792Sgshapiro return false; 211438032Speter } 211538032Speter if (st.st_mode == ST_MODE_NOFILE) 211638032Speter omode |= O_CREAT|O_EXCL; 211738032Speter 211838032Speter map->map_lockfd = -1; 211938032Speter 212064562Sgshapiro# if LOCK_ON_OPEN 212138032Speter if (mode == O_RDWR) 212238032Speter omode |= O_TRUNC|O_EXLOCK; 212338032Speter else 212438032Speter omode |= O_SHLOCK; 212564562Sgshapiro# else /* LOCK_ON_OPEN */ 212638032Speter /* 212738032Speter ** Pre-lock the file to avoid race conditions. In particular, 212838032Speter ** since dbopen returns NULL if the file is zero length, we 212938032Speter ** must have a locked instance around the dbopen. 213038032Speter */ 213138032Speter 213238032Speter fd = open(buf, omode, DBMMODE); 213338032Speter if (fd < 0) 213438032Speter { 213538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 213638032Speter syserr("db_map_open: cannot pre-open database %s", buf); 213790792Sgshapiro return false; 213838032Speter } 213938032Speter 214038032Speter /* make sure no baddies slipped in just before the open... */ 214138032Speter if (filechanged(buf, fd, &st)) 214238032Speter { 214364562Sgshapiro save_errno = errno; 214438032Speter (void) close(fd); 214538032Speter errno = save_errno; 214638032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 214790792Sgshapiro return false; 214838032Speter } 214938032Speter 215038032Speter /* if new file, get the "before" bits for later filechanged check */ 215138032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 215238032Speter { 215364562Sgshapiro save_errno = errno; 215438032Speter (void) close(fd); 215538032Speter errno = save_errno; 215638032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 215738032Speter buf); 215890792Sgshapiro return false; 215938032Speter } 216038032Speter 216138032Speter /* actually lock the pre-opened file */ 216238032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 216338032Speter syserr("db_map_open: cannot lock %s", buf); 216438032Speter 216538032Speter /* set up mode bits for dbopen */ 216638032Speter if (mode == O_RDWR) 216738032Speter omode |= O_TRUNC; 216838032Speter omode &= ~(O_EXCL|O_CREAT); 216964562Sgshapiro# endif /* LOCK_ON_OPEN */ 217038032Speter 217164562Sgshapiro# if DB_VERSION_MAJOR < 2 217238032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 217364562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 217438032Speter { 217538032Speter int flags = 0; 217664562Sgshapiro# if DB_VERSION_MAJOR > 2 217764562Sgshapiro int ret; 2178363466Sgshapiro# endif 217938032Speter 218038032Speter if (mode == O_RDONLY) 218138032Speter flags |= DB_RDONLY; 218238032Speter if (bitset(O_CREAT, omode)) 218338032Speter flags |= DB_CREATE; 218438032Speter if (bitset(O_TRUNC, omode)) 218538032Speter flags |= DB_TRUNCATE; 2186110560Sgshapiro SM_DB_FLAG_ADD(flags); 218738032Speter 218864562Sgshapiro# if DB_VERSION_MAJOR > 2 218964562Sgshapiro ret = db_create(&db, NULL, 0); 219064562Sgshapiro# ifdef DB_CACHE_SIZE 219164562Sgshapiro if (ret == 0 && db != NULL) 219264562Sgshapiro { 219364562Sgshapiro ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 219464562Sgshapiro if (ret != 0) 219564562Sgshapiro { 219664562Sgshapiro (void) db->close(db, 0); 219764562Sgshapiro db = NULL; 219864562Sgshapiro } 219964562Sgshapiro } 220064562Sgshapiro# endif /* DB_CACHE_SIZE */ 220164562Sgshapiro# ifdef DB_HASH_NELEM 220264562Sgshapiro if (dbtype == DB_HASH && ret == 0 && db != NULL) 220364562Sgshapiro { 220464562Sgshapiro ret = db->set_h_nelem(db, DB_HASH_NELEM); 220564562Sgshapiro if (ret != 0) 220664562Sgshapiro { 220764562Sgshapiro (void) db->close(db, 0); 220864562Sgshapiro db = NULL; 220964562Sgshapiro } 221064562Sgshapiro } 221164562Sgshapiro# endif /* DB_HASH_NELEM */ 221264562Sgshapiro if (ret == 0 && db != NULL) 221364562Sgshapiro { 2214110560Sgshapiro ret = db->open(db, 2215110560Sgshapiro DBTXN /* transaction for DB 4.1 */ 2216110560Sgshapiro buf, NULL, dbtype, flags, DBMMODE); 221764562Sgshapiro if (ret != 0) 221864562Sgshapiro { 221973188Sgshapiro#ifdef DB_OLD_VERSION 222073188Sgshapiro if (ret == DB_OLD_VERSION) 222173188Sgshapiro ret = EINVAL; 222273188Sgshapiro#endif /* DB_OLD_VERSION */ 222364562Sgshapiro (void) db->close(db, 0); 222464562Sgshapiro db = NULL; 222564562Sgshapiro } 222664562Sgshapiro } 222764562Sgshapiro errno = ret; 222864562Sgshapiro# else /* DB_VERSION_MAJOR > 2 */ 222938032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 223038032Speter NULL, openinfo, &db); 223164562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 223238032Speter } 223364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 223464562Sgshapiro save_errno = errno; 223538032Speter 223664562Sgshapiro# if !LOCK_ON_OPEN 223738032Speter if (mode == O_RDWR) 223838032Speter map->map_lockfd = fd; 223938032Speter else 224038032Speter (void) close(fd); 224164562Sgshapiro# endif /* !LOCK_ON_OPEN */ 224238032Speter 224338032Speter if (db == NULL) 224438032Speter { 224538032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 224690792Sgshapiro aliaswait(map, ".db", false)) 224790792Sgshapiro return true; 224864562Sgshapiro# if !LOCK_ON_OPEN 224938032Speter if (map->map_lockfd >= 0) 225038032Speter (void) close(map->map_lockfd); 2251363466Sgshapiro# endif 225264562Sgshapiro errno = save_errno; 225338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 225438032Speter syserr("Cannot open %s database %s", 225538032Speter mapclassname, buf); 225690792Sgshapiro return false; 225738032Speter } 225838032Speter 225964562Sgshapiro# if DB_VERSION_MAJOR < 2 226038032Speter fd = db->fd(db); 2261363466Sgshapiro# else 226238032Speter fd = -1; 226338032Speter errno = db->fd(db, &fd); 226464562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 226538032Speter if (filechanged(buf, fd, &st)) 226638032Speter { 226764562Sgshapiro save_errno = errno; 226864562Sgshapiro# if DB_VERSION_MAJOR < 2 226964562Sgshapiro (void) db->close(db); 2270363466Sgshapiro# else 227138032Speter errno = db->close(db, 0); 227264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 227364562Sgshapiro# if !LOCK_ON_OPEN 227438032Speter if (map->map_lockfd >= 0) 227564562Sgshapiro (void) close(map->map_lockfd); 2276363466Sgshapiro# endif 227738032Speter errno = save_errno; 227838032Speter syserr("db_map_open(%s): file changed after open", buf); 227990792Sgshapiro return false; 228038032Speter } 228138032Speter 228238032Speter if (mode == O_RDWR) 228338032Speter map->map_mflags |= MF_LOCKED; 228464562Sgshapiro# if LOCK_ON_OPEN 228538032Speter if (fd >= 0 && mode == O_RDONLY) 228638032Speter { 228738032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 228838032Speter } 228964562Sgshapiro# endif /* LOCK_ON_OPEN */ 229038032Speter 229138032Speter /* try to make sure that at least the database header is on disk */ 229238032Speter if (mode == O_RDWR) 229338032Speter { 229438032Speter (void) db->sync(db, 0); 229542575Speter if (geteuid() == 0 && TrustedUid != 0) 229638032Speter { 229764562Sgshapiro# if HASFCHOWN 229842575Speter if (fchown(fd, TrustedUid, -1) < 0) 229938032Speter { 230038032Speter int err = errno; 230138032Speter 230238032Speter sm_syslog(LOG_ALERT, NOQID, 230338032Speter "ownership change on %s failed: %s", 230490792Sgshapiro buf, sm_errstring(err)); 230538032Speter message("050 ownership change on %s failed: %s", 230690792Sgshapiro buf, sm_errstring(err)); 230738032Speter } 230890792Sgshapiro# else /* HASFCHOWN */ 230990792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 231090792Sgshapiro "no fchown(): cannot change ownership on %s", 231190792Sgshapiro map->map_file); 231290792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 231390792Sgshapiro map->map_file); 231464562Sgshapiro# endif /* HASFCHOWN */ 231538032Speter } 231638032Speter } 231738032Speter 231864562Sgshapiro map->map_db2 = (ARBPTR_T) db; 231964562Sgshapiro 232064562Sgshapiro /* 232164562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 232264562Sgshapiro ** as aliaswait() will call map_lookup() which requires 232364562Sgshapiro ** map_mtime to be set 232464562Sgshapiro */ 232564562Sgshapiro 232638032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 232738032Speter map->map_mtime = st.st_mtime; 232838032Speter 232938032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 233090792Sgshapiro !aliaswait(map, ".db", true)) 233190792Sgshapiro return false; 233290792Sgshapiro return true; 233338032Speter} 233438032Speter 233538032Speter 233638032Speter/* 233738032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 233838032Speter*/ 233938032Speter 234038032Speterchar * 234138032Speterdb_map_lookup(map, name, av, statp) 234238032Speter MAP *map; 234338032Speter char *name; 234438032Speter char **av; 234538032Speter int *statp; 234638032Speter{ 234738032Speter DBT key, val; 234838032Speter register DB *db = (DB *) map->map_db2; 234938032Speter int i; 235038032Speter int st; 235164562Sgshapiro int save_errno; 235238032Speter int fd; 235338032Speter struct stat stbuf; 235438032Speter char keybuf[MAXNAME + 1]; 235598121Sgshapiro char buf[MAXPATHLEN]; 235638032Speter 2357168515Sgshapiro memset(&key, '\0', sizeof(key)); 2358168515Sgshapiro memset(&val, '\0', sizeof(val)); 235938032Speter 236038032Speter if (tTd(38, 20)) 236190792Sgshapiro sm_dprintf("db_map_lookup(%s, %s)\n", 236238032Speter map->map_mname, name); 236338032Speter 2364168515Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf)) 236598121Sgshapiro { 236698121Sgshapiro errno = 0; 236798121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 236898121Sgshapiro syserr("map \"%s\": map file %s name too long", 236998121Sgshapiro map->map_mname, map->map_file); 237098121Sgshapiro return NULL; 237198121Sgshapiro } 237298121Sgshapiro i = strlen(buf); 237338032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 237438032Speter buf[i - 3] = '\0'; 237538032Speter 237638032Speter key.size = strlen(name); 2377168515Sgshapiro if (key.size > sizeof(keybuf) - 1) 2378168515Sgshapiro key.size = sizeof(keybuf) - 1; 237938032Speter key.data = keybuf; 238064562Sgshapiro memmove(keybuf, name, key.size); 238138032Speter keybuf[key.size] = '\0'; 238238032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 238338032Speter makelower(keybuf); 238438032Speter lockdb: 238564562Sgshapiro# if DB_VERSION_MAJOR < 2 238638032Speter fd = db->fd(db); 2387363466Sgshapiro# else 238838032Speter fd = -1; 238938032Speter errno = db->fd(db, &fd); 239064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 239138032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 239238032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 239338032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 239438032Speter { 239538032Speter /* Reopen the database to sync the cache */ 239638032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 239738032Speter : O_RDONLY; 239838032Speter 239964562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 240064562Sgshapiro (void) lockfile(fd, buf, ".db", LOCK_UN); 240177349Sgshapiro map->map_mflags |= MF_CLOSING; 240238032Speter map->map_class->map_close(map); 240377349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 240438032Speter if (map->map_class->map_open(map, omode)) 240538032Speter { 240638032Speter map->map_mflags |= MF_OPEN; 240790792Sgshapiro map->map_pid = CurrentPid; 2408203004Sgshapiro if ((omode & O_ACCMODE) == O_RDWR) 240938032Speter map->map_mflags |= MF_WRITABLE; 241038032Speter db = (DB *) map->map_db2; 241138032Speter goto lockdb; 241238032Speter } 241338032Speter else 241438032Speter { 241538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 241638032Speter { 241738032Speter extern MAPCLASS BogusMapClass; 241838032Speter 241938032Speter *statp = EX_TEMPFAIL; 242090792Sgshapiro map->map_orgclass = map->map_class; 242138032Speter map->map_class = &BogusMapClass; 242238032Speter map->map_mflags |= MF_OPEN; 242390792Sgshapiro map->map_pid = CurrentPid; 242438032Speter syserr("Cannot reopen DB database %s", 242538032Speter map->map_file); 242638032Speter } 242738032Speter return NULL; 242838032Speter } 242938032Speter } 243038032Speter 243138032Speter st = 1; 243238032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 243338032Speter { 243464562Sgshapiro# if DB_VERSION_MAJOR < 2 243538032Speter st = db->get(db, &key, &val, 0); 243664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 243738032Speter errno = db->get(db, NULL, &key, &val, 0); 243838032Speter switch (errno) 243938032Speter { 244038032Speter case DB_NOTFOUND: 244138032Speter case DB_KEYEMPTY: 244238032Speter st = 1; 244338032Speter break; 244438032Speter 244538032Speter case 0: 244638032Speter st = 0; 244738032Speter break; 244838032Speter 244938032Speter default: 245038032Speter st = -1; 245138032Speter break; 245238032Speter } 245364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 245438032Speter if (st == 0) 245538032Speter map->map_mflags &= ~MF_TRY1NULL; 245638032Speter } 245738032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 245838032Speter { 245938032Speter key.size++; 246064562Sgshapiro# if DB_VERSION_MAJOR < 2 246138032Speter st = db->get(db, &key, &val, 0); 246264562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 246338032Speter errno = db->get(db, NULL, &key, &val, 0); 246438032Speter switch (errno) 246538032Speter { 246638032Speter case DB_NOTFOUND: 246738032Speter case DB_KEYEMPTY: 246838032Speter st = 1; 246938032Speter break; 247038032Speter 247138032Speter case 0: 247238032Speter st = 0; 247338032Speter break; 247438032Speter 247538032Speter default: 247638032Speter st = -1; 247738032Speter break; 247838032Speter } 247964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 248038032Speter if (st == 0) 248138032Speter map->map_mflags &= ~MF_TRY0NULL; 248238032Speter } 248364562Sgshapiro save_errno = errno; 248438032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 248538032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 248638032Speter if (st != 0) 248738032Speter { 248864562Sgshapiro errno = save_errno; 248938032Speter if (st < 0) 249038032Speter syserr("db_map_lookup: get (%s)", name); 249138032Speter return NULL; 249238032Speter } 249338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 249438032Speter return map_rewrite(map, name, strlen(name), NULL); 249538032Speter else 249638032Speter return map_rewrite(map, val.data, val.size, av); 249738032Speter} 249838032Speter 249938032Speter 250038032Speter/* 250138032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 250238032Speter*/ 250338032Speter 250438032Spetervoid 250538032Speterdb_map_store(map, lhs, rhs) 250638032Speter register MAP *map; 250738032Speter char *lhs; 250838032Speter char *rhs; 250938032Speter{ 251064562Sgshapiro int status; 251138032Speter DBT key; 251238032Speter DBT data; 251338032Speter register DB *db = map->map_db2; 251438032Speter char keybuf[MAXNAME + 1]; 251538032Speter 2516168515Sgshapiro memset(&key, '\0', sizeof(key)); 2517168515Sgshapiro memset(&data, '\0', sizeof(data)); 251838032Speter 251938032Speter if (tTd(38, 12)) 252090792Sgshapiro sm_dprintf("db_map_store(%s, %s, %s)\n", 252138032Speter map->map_mname, lhs, rhs); 252238032Speter 252338032Speter key.size = strlen(lhs); 252438032Speter key.data = lhs; 252538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 252638032Speter { 2527168515Sgshapiro if (key.size > sizeof(keybuf) - 1) 2528168515Sgshapiro key.size = sizeof(keybuf) - 1; 252964562Sgshapiro memmove(keybuf, key.data, key.size); 253038032Speter keybuf[key.size] = '\0'; 253138032Speter makelower(keybuf); 253238032Speter key.data = keybuf; 253338032Speter } 253438032Speter 253538032Speter data.size = strlen(rhs); 253638032Speter data.data = rhs; 253738032Speter 253838032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 253938032Speter { 254038032Speter key.size++; 254138032Speter data.size++; 254238032Speter } 254338032Speter 254464562Sgshapiro# if DB_VERSION_MAJOR < 2 254564562Sgshapiro status = db->put(db, &key, &data, R_NOOVERWRITE); 254664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 254738032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 254838032Speter switch (errno) 254938032Speter { 255038032Speter case DB_KEYEXIST: 255164562Sgshapiro status = 1; 255238032Speter break; 255338032Speter 255438032Speter case 0: 255564562Sgshapiro status = 0; 255638032Speter break; 255738032Speter 255838032Speter default: 255964562Sgshapiro status = -1; 256038032Speter break; 256138032Speter } 256264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 256364562Sgshapiro if (status > 0) 256438032Speter { 256538032Speter if (!bitset(MF_APPEND, map->map_mflags)) 256638032Speter message("050 Warning: duplicate alias name %s", lhs); 256738032Speter else 256838032Speter { 256938032Speter static char *buf = NULL; 257038032Speter static int bufsiz = 0; 257138032Speter DBT old; 257238032Speter 2573168515Sgshapiro memset(&old, '\0', sizeof(old)); 257438032Speter 257564562Sgshapiro old.data = db_map_lookup(map, key.data, 257690792Sgshapiro (char **) NULL, &status); 257738032Speter if (old.data != NULL) 257838032Speter { 257938032Speter old.size = strlen(old.data); 258090792Sgshapiro if (data.size + old.size + 2 > (size_t) bufsiz) 258138032Speter { 258238032Speter if (buf != NULL) 258377349Sgshapiro sm_free(buf); 258438032Speter bufsiz = data.size + old.size + 2; 258590792Sgshapiro buf = sm_pmalloc_x(bufsiz); 258638032Speter } 258790792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 258890792Sgshapiro (char *) data.data, ",", 258990792Sgshapiro (char *) old.data); 259038032Speter data.size = data.size + old.size + 1; 259138032Speter data.data = buf; 259238032Speter if (tTd(38, 9)) 259390792Sgshapiro sm_dprintf("db_map_store append=%s\n", 259464562Sgshapiro (char *) data.data); 259538032Speter } 259638032Speter } 259764562Sgshapiro# if DB_VERSION_MAJOR < 2 259864562Sgshapiro status = db->put(db, &key, &data, 0); 2599363466Sgshapiro# else 260064562Sgshapiro status = errno = db->put(db, NULL, &key, &data, 0); 260164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 260238032Speter } 260364562Sgshapiro if (status != 0) 260438032Speter syserr("readaliases: db put (%s)", lhs); 260538032Speter} 260638032Speter 260738032Speter 260838032Speter/* 260938032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 261038032Speter*/ 261138032Speter 261238032Spetervoid 261338032Speterdb_map_close(map) 261438032Speter MAP *map; 261538032Speter{ 261638032Speter register DB *db = map->map_db2; 261738032Speter 261838032Speter if (tTd(38, 9)) 261990792Sgshapiro sm_dprintf("db_map_close(%s, %s, %lx)\n", 262038032Speter map->map_mname, map->map_file, map->map_mflags); 262138032Speter 262238032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 262338032Speter { 262438032Speter /* write out the distinguished alias */ 262538032Speter db_map_store(map, "@", "@"); 262638032Speter } 262738032Speter 262838032Speter (void) db->sync(db, 0); 262938032Speter 263064562Sgshapiro# if !LOCK_ON_OPEN 263138032Speter if (map->map_lockfd >= 0) 263238032Speter (void) close(map->map_lockfd); 263364562Sgshapiro# endif /* !LOCK_ON_OPEN */ 263438032Speter 263564562Sgshapiro# if DB_VERSION_MAJOR < 2 263638032Speter if (db->close(db) != 0) 263764562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 263842575Speter /* 263942575Speter ** Berkeley DB can use internal shared memory 264042575Speter ** locking for its memory pool. Closing a map 264142575Speter ** opened by another process will interfere 264242575Speter ** with the shared memory and locks of the parent 264342575Speter ** process leaving things in a bad state. 264443730Speter */ 264543730Speter 264643730Speter /* 264742575Speter ** If this map was not opened by the current 264843730Speter ** process, do not close the map but recover 264942575Speter ** the file descriptor. 265042575Speter */ 265190792Sgshapiro 265290792Sgshapiro if (map->map_pid != CurrentPid) 265342575Speter { 265442575Speter int fd = -1; 265542575Speter 265642575Speter errno = db->fd(db, &fd); 265742575Speter if (fd >= 0) 265842575Speter (void) close(fd); 265942575Speter return; 266042575Speter } 266142575Speter 266238032Speter if ((errno = db->close(db, 0)) != 0) 266364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 266442575Speter syserr("db_map_close(%s, %s, %lx): db close failure", 266542575Speter map->map_mname, map->map_file, map->map_mflags); 266638032Speter} 266764562Sgshapiro#endif /* NEWDB */ 2668363466Sgshapiro 2669363466Sgshapiro#if CDB 267090792Sgshapiro/* 2671363466Sgshapiro** CDB Modules 2672363466Sgshapiro*/ 2673363466Sgshapiro 2674363466Sgshapirostatic bool smdb_add_extension __P((char *, int, char *, char *)); 2675363466Sgshapiro 2676363466Sgshapiro/* 2677363466Sgshapiro** SMDB_ADD_EXTENSION -- Adds an extension to a file name. 2678363466Sgshapiro** 2679363466Sgshapiro** Just adds a . followed by a string to a db_name if there 2680363466Sgshapiro** is room and the db_name does not already have that extension. 2681363466Sgshapiro** 2682363466Sgshapiro** Parameters: 2683363466Sgshapiro** full_name -- The final file name. 2684363466Sgshapiro** max_full_name_len -- The max length for full_name. 2685363466Sgshapiro** db_name -- The name of the db. 2686363466Sgshapiro** extension -- The extension to add. 2687363466Sgshapiro** 2688363466Sgshapiro** Returns: 2689363466Sgshapiro** SMDBE_OK -- Success. 2690363466Sgshapiro** Anything else is an error. Look up more info about the 2691363466Sgshapiro** error in the comments for the specific open() used. 2692363466Sgshapiro*/ 2693363466Sgshapiro 2694363466Sgshapirostatic bool 2695363466Sgshapirosmdb_add_extension(full_name, max_full_name_len, db_name, extension) 2696363466Sgshapiro char *full_name; 2697363466Sgshapiro int max_full_name_len; 2698363466Sgshapiro char *db_name; 2699363466Sgshapiro char *extension; 2700363466Sgshapiro{ 2701363466Sgshapiro int extension_len; 2702363466Sgshapiro int db_name_len; 2703363466Sgshapiro 2704363466Sgshapiro if (full_name == NULL || db_name == NULL || extension == NULL) 2705363466Sgshapiro return false; /* SMDBE_INVALID_PARAMETER; */ 2706363466Sgshapiro 2707363466Sgshapiro extension_len = strlen(extension); 2708363466Sgshapiro db_name_len = strlen(db_name); 2709363466Sgshapiro 2710363466Sgshapiro if (extension_len + db_name_len + 2 > max_full_name_len) 2711363466Sgshapiro return false; /* SMDBE_DB_NAME_TOO_LONG; */ 2712363466Sgshapiro 2713363466Sgshapiro if (db_name_len < extension_len + 1 || 2714363466Sgshapiro db_name[db_name_len - extension_len - 1] != '.' || 2715363466Sgshapiro strcmp(&db_name[db_name_len - extension_len], extension) != 0) 2716363466Sgshapiro (void) sm_snprintf(full_name, max_full_name_len, "%s.%s", 2717363466Sgshapiro db_name, extension); 2718363466Sgshapiro else 2719363466Sgshapiro (void) sm_strlcpy(full_name, db_name, max_full_name_len); 2720363466Sgshapiro 2721363466Sgshapiro return true; 2722363466Sgshapiro} 2723363466Sgshapiro 2724363466Sgshapirobool 2725363466Sgshapirocdb_map_open(map, mode) 2726363466Sgshapiro MAP *map; 2727363466Sgshapiro int mode; 2728363466Sgshapiro{ 2729363466Sgshapiro int fd, status, omode, smode; 2730363466Sgshapiro long sff; 2731363466Sgshapiro struct stat st; 2732363466Sgshapiro char buf[MAXPATHLEN]; 2733363466Sgshapiro 2734363466Sgshapiro if (tTd(38, 2)) 2735363466Sgshapiro sm_dprintf("cdb_map_open(%s, %s, %d)\n", 2736363466Sgshapiro map->map_mname, map->map_file, mode); 2737363466Sgshapiro map->map_db1 = (ARBPTR_T)NULL; 2738363466Sgshapiro map->map_db2 = (ARBPTR_T)NULL; 2739363466Sgshapiro 2740363466Sgshapiro mode &= O_ACCMODE; 2741363466Sgshapiro omode = mode; 2742363466Sgshapiro 2743363466Sgshapiro /* 2744363466Sgshapiro ** Notes: 2745363466Sgshapiro ** If a temporary file is used, then there must be some check 2746363466Sgshapiro ** that the rename() is "safe" (i.e., does not overwrite some 2747363466Sgshapiro ** "other" file created by an attacker). 2748363466Sgshapiro ** 2749363466Sgshapiro ** The code to add the extension and to set up safefile() 2750363466Sgshapiro ** and open() should be in a common function 2751363466Sgshapiro ** (it would be nice to re-use libsmdb?) 2752363466Sgshapiro */ 2753363466Sgshapiro 2754363466Sgshapiro if (!smdb_add_extension(buf, sizeof(buf), map->map_file, CDBext)) 2755363466Sgshapiro { 2756363466Sgshapiro errno = 0; 2757363466Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 2758363466Sgshapiro syserr("cdb map \"%s\": map file %s name too long", 2759363466Sgshapiro map->map_mname, map->map_file); 2760363466Sgshapiro return false; 2761363466Sgshapiro } 2762363466Sgshapiro 2763363466Sgshapiro sff = SFF_ROOTOK|SFF_REGONLY; 2764363466Sgshapiro if (mode == O_RDWR) 2765363466Sgshapiro { 2766363466Sgshapiro if (sm_strlcat(buf, ".tmp", sizeof buf) >= sizeof buf) 2767363466Sgshapiro { 2768363466Sgshapiro errno = 0; 2769363466Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 2770363466Sgshapiro syserr("cdb map \"%s\": map file %s name too long", 2771363466Sgshapiro map->map_mname, map->map_file); 2772363466Sgshapiro return false; 2773363466Sgshapiro } 2774363466Sgshapiro sff |= SFF_CREAT; 2775363466Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 2776363466Sgshapiro sff |= SFF_NOSLINK; 2777363466Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 2778363466Sgshapiro sff |= SFF_NOHLINK; 2779363466Sgshapiro smode = S_IWRITE; 2780363466Sgshapiro } 2781363466Sgshapiro else 2782363466Sgshapiro { 2783363466Sgshapiro smode = S_IREAD; 2784363466Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 2785363466Sgshapiro sff |= SFF_NOWLINK; 2786363466Sgshapiro } 2787363466Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 2788363466Sgshapiro sff |= SFF_SAFEDIRPATH; 2789363466Sgshapiro status = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 2790363466Sgshapiro if (status != 0) 2791363466Sgshapiro { 2792363466Sgshapiro char *prob = "unsafe"; 2793363466Sgshapiro 2794363466Sgshapiro /* cannot open this map */ 2795363466Sgshapiro if (status == ENOENT) 2796363466Sgshapiro prob = "missing"; 2797363466Sgshapiro errno = status; 2798363466Sgshapiro if (tTd(38, 2)) 2799363466Sgshapiro sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(status)); 2800363466Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 2801363466Sgshapiro syserr("%s map \"%s\": %s map file %s", 2802363466Sgshapiro map->map_mname, prob, buf, sm_errstring(status)); 2803363466Sgshapiro return false; 2804363466Sgshapiro } 2805363466Sgshapiro 2806363466Sgshapiro if (st.st_mode == ST_MODE_NOFILE) 2807363466Sgshapiro omode |= O_CREAT|O_EXCL; 2808363466Sgshapiro# if LOCK_ON_OPEN 2809363466Sgshapiro if (mode == O_RDWR) 2810363466Sgshapiro omode |= O_TRUNC|O_EXLOCK; 2811363466Sgshapiro else 2812363466Sgshapiro omode |= O_SHLOCK; 2813363466Sgshapiro# else 2814363466Sgshapiro if (mode == O_RDWR) 2815363466Sgshapiro omode |= O_TRUNC; 2816363466Sgshapiro# endif /* LOCK_ON_OPEN */ 2817363466Sgshapiro 2818363466Sgshapiro fd = open(buf, omode, DBMMODE); 2819363466Sgshapiro if (fd < 0) 2820363466Sgshapiro { 2821363466Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 2822363466Sgshapiro syserr("cdb_map_open: cannot open database %s", buf); 2823363466Sgshapiro return false; 2824363466Sgshapiro } 2825363466Sgshapiro 2826363466Sgshapiro# if !LOCK_ON_OPEN 2827363466Sgshapiro /* make sure no baddies slipped in just before the open... */ 2828363466Sgshapiro if (filechanged(buf, fd, &st)) 2829363466Sgshapiro { 2830363466Sgshapiro int save_errno; 2831363466Sgshapiro 2832363466Sgshapiro save_errno = errno; 2833363466Sgshapiro (void) close(fd); 2834363466Sgshapiro errno = save_errno; 2835363466Sgshapiro syserr("cdb_map_open(%s): file changed after open", buf); 2836363466Sgshapiro return false; 2837363466Sgshapiro } 2838363466Sgshapiro 2839363466Sgshapiro /* actually lock the opened file */ 2840363466Sgshapiro if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 2841363466Sgshapiro syserr("cdb_map_open: cannot lock %s", buf); 2842363466Sgshapiro# endif /* !LOCK_ON_OPEN */ 2843363466Sgshapiro 2844363466Sgshapiro /* only for aliases! */ 2845363466Sgshapiro if (mode == O_RDWR) 2846363466Sgshapiro { 2847363466Sgshapiro struct cdb_make *cdbmp; 2848363466Sgshapiro 2849363466Sgshapiro cdbmp = (struct cdb_make *) xalloc(sizeof(*cdbmp)); 2850363466Sgshapiro status = cdb_make_start(cdbmp, fd); 2851363466Sgshapiro if (status != 0) 2852363466Sgshapiro { 2853363466Sgshapiro close(fd); 2854363466Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 2855363466Sgshapiro syserr("initialization of cdb map (make) failed"); 2856363466Sgshapiro return false; 2857363466Sgshapiro } 2858363466Sgshapiro 2859363466Sgshapiro map->map_db2 = (ARBPTR_T)cdbmp; 2860363466Sgshapiro return true; 2861363466Sgshapiro } 2862363466Sgshapiro else 2863363466Sgshapiro { 2864363466Sgshapiro struct cdb *cdbp; 2865363466Sgshapiro 2866363466Sgshapiro cdbp = (struct cdb *) xalloc(sizeof(*cdbp)); 2867363466Sgshapiro status = cdb_init(cdbp, fd); 2868363466Sgshapiro if (status != 0) 2869363466Sgshapiro { 2870363466Sgshapiro close(fd); 2871363466Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 2872363466Sgshapiro syserr("initialization of cdb map failed"); 2873363466Sgshapiro return false; 2874363466Sgshapiro } 2875363466Sgshapiro map->map_db1 = (ARBPTR_T)cdbp; 2876363466Sgshapiro return true; 2877363466Sgshapiro } 2878363466Sgshapiro 2879363466Sgshapiro /* NOTREACHED */ 2880363466Sgshapiro return false; 2881363466Sgshapiro} 2882363466Sgshapiro 2883363466Sgshapirochar * 2884363466Sgshapirocdb_map_lookup (map, name, av, statp) 2885363466Sgshapiro MAP * map; 2886363466Sgshapiro char *name; 2887363466Sgshapiro char **av; 2888363466Sgshapiro int *statp; 2889363466Sgshapiro{ 2890363466Sgshapiro char * data; 2891363466Sgshapiro struct cdb *cdbmap; 2892363466Sgshapiro unsigned int klen, dlen; 2893363466Sgshapiro int st; 2894363466Sgshapiro char key[MAXNAME+1]; 2895363466Sgshapiro 2896363466Sgshapiro data = NULL; 2897363466Sgshapiro cdbmap = map->map_db1; 2898363466Sgshapiro if (tTd(38, 20)) 2899363466Sgshapiro sm_dprintf("cdb_map_lookup(%s, %s)\n", map->map_mname, name); 2900363466Sgshapiro 2901363466Sgshapiro klen = strlen(name); 2902363466Sgshapiro if (klen > sizeof(key) - 1) 2903363466Sgshapiro klen = sizeof(key) - 1; 2904363466Sgshapiro memmove(key, name, klen); 2905363466Sgshapiro key[klen] = '\0'; 2906363466Sgshapiro 2907363466Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 2908363466Sgshapiro makelower(key); 2909363466Sgshapiro 2910363466Sgshapiro st = 0; 2911363466Sgshapiro if (bitset(MF_TRY0NULL, map->map_mflags)) 2912363466Sgshapiro { 2913363466Sgshapiro st = cdb_find(cdbmap, key, klen); 2914363466Sgshapiro if (st == 1) 2915363466Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 2916363466Sgshapiro } 2917363466Sgshapiro if (st != 1 && bitset(MF_TRY1NULL, map->map_mflags)) 2918363466Sgshapiro { 2919363466Sgshapiro st = cdb_find(cdbmap, key, klen + 1); 2920363466Sgshapiro if (st == 1) 2921363466Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 2922363466Sgshapiro } 2923363466Sgshapiro if (st != 1) 2924363466Sgshapiro { 2925363466Sgshapiro if (st < 0) 2926363466Sgshapiro syserr("cdb_map_lookup: get (%s)", name); 2927363466Sgshapiro return NULL; 2928363466Sgshapiro } 2929363466Sgshapiro else 2930363466Sgshapiro { 2931363466Sgshapiro dlen = cdb_datalen(cdbmap); 2932363466Sgshapiro data = malloc(dlen + 1); 2933363466Sgshapiro cdb_read(cdbmap, data, dlen, cdb_datapos(cdbmap)); 2934363466Sgshapiro data[dlen] = '\0'; 2935363466Sgshapiro } 2936363466Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 2937363466Sgshapiro return map_rewrite(map, name, strlen(name), NULL); 2938363466Sgshapiro else 2939363466Sgshapiro return map_rewrite(map, data, dlen, av); 2940363466Sgshapiro} 2941363466Sgshapiro 2942363466Sgshapiro/* 2943363466Sgshapiro** CDB_MAP_STORE -- store a datum in the CDB database 2944363466Sgshapiro*/ 2945363466Sgshapiro 2946363466Sgshapirovoid 2947363466Sgshapirocdb_map_store(map, lhs, rhs) 2948363466Sgshapiro MAP *map; 2949363466Sgshapiro char *lhs; 2950363466Sgshapiro char *rhs; 2951363466Sgshapiro{ 2952363466Sgshapiro struct cdb_make *cdbmp; 2953363466Sgshapiro size_t klen; 2954363466Sgshapiro size_t vlen; 2955363466Sgshapiro int status; 2956363466Sgshapiro char keybuf[MAXNAME + 1]; 2957363466Sgshapiro 2958363466Sgshapiro cdbmp = map->map_db2; 2959363466Sgshapiro if (cdbmp == NULL) 2960363466Sgshapiro return; /* XXX */ 2961363466Sgshapiro 2962363466Sgshapiro klen = strlen(lhs); 2963363466Sgshapiro vlen = strlen(rhs); 2964363466Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 2965363466Sgshapiro { 2966363466Sgshapiro if (klen > sizeof(keybuf) - 1) 2967363466Sgshapiro klen = sizeof(keybuf) - 1; 2968363466Sgshapiro memmove(keybuf, lhs, klen); 2969363466Sgshapiro keybuf[klen] = '\0'; 2970363466Sgshapiro makelower(keybuf); 2971363466Sgshapiro lhs = keybuf; 2972363466Sgshapiro } 2973363466Sgshapiro 2974363466Sgshapiro if (bitset(MF_INCLNULL, map->map_mflags)) 2975363466Sgshapiro { 2976363466Sgshapiro klen++; 2977363466Sgshapiro vlen++; 2978363466Sgshapiro } 2979363466Sgshapiro 2980363466Sgshapiro /* flags? */ 2981363466Sgshapiro status = cdb_make_put(cdbmp, lhs, klen, rhs, vlen, 0); 2982363466Sgshapiro /* and now? */ 2983363466Sgshapiro} 2984363466Sgshapiro 2985363466Sgshapirovoid 2986363466Sgshapirocdb_map_close(map) 2987363466Sgshapiro MAP * map; 2988363466Sgshapiro{ 2989363466Sgshapiro struct cdb *cdbp; 2990363466Sgshapiro struct cdb_make *cdbmp; 2991363466Sgshapiro int fd; 2992363466Sgshapiro 2993363466Sgshapiro fd = -1; 2994363466Sgshapiro cdbp = map->map_db1; 2995363466Sgshapiro if (cdbp != NULL) 2996363466Sgshapiro { 2997363466Sgshapiro if (tTd(38, 20)) 2998363466Sgshapiro sm_dprintf("cdb_map_close(%p)\n", (void *)cdbp); 2999363466Sgshapiro fd = cdb_fileno(cdbp); 3000363466Sgshapiro cdb_free(cdbp); 3001363466Sgshapiro sm_free(cdbp); 3002363466Sgshapiro cdbp = NULL; 3003363466Sgshapiro } 3004363466Sgshapiro cdbmp = map->map_db2; 3005363466Sgshapiro if (cdbmp != NULL) 3006363466Sgshapiro { 3007363466Sgshapiro char tmpfn[MAXPATHLEN], cdbfn[MAXPATHLEN]; 3008363466Sgshapiro 3009363466Sgshapiro if (tTd(38, 20)) 3010363466Sgshapiro sm_dprintf("cdb_map_close(%p)\n", (void *)cdbmp); 3011363466Sgshapiro fd = cdb_fileno(cdbmp); 3012363466Sgshapiro 3013363466Sgshapiro /* write out the distinguished alias */ 3014363466Sgshapiro /* XXX Why isn't this in a common place? */ 3015363466Sgshapiro cdb_map_store(map, "@", "@"); 3016363466Sgshapiro 3017363466Sgshapiro if (cdb_make_finish(cdbmp) != 0) 3018363466Sgshapiro syserr("cdb: failed to write %s", map->map_file); 3019363466Sgshapiro if (fd >=0) 3020363466Sgshapiro { 3021363466Sgshapiro if (fsync(fd) == -1) 3022363466Sgshapiro syserr("cdb: fsync(%s) failed", map->map_file); 3023363466Sgshapiro if (close(fd) == -1) 3024363466Sgshapiro syserr("cdb: close(%s) failed", map->map_file); 3025363466Sgshapiro } 3026363466Sgshapiro 3027363466Sgshapiro if (!smdb_add_extension(cdbfn, sizeof(cdbfn), map->map_file, 3028363466Sgshapiro CDBext)) 3029363466Sgshapiro { 3030363466Sgshapiro syserr("cdb: add extension to %s failed", 3031363466Sgshapiro map->map_file); 3032363466Sgshapiro } 3033363466Sgshapiro if (sm_strlcpy(tmpfn, cdbfn, sizeof tmpfn) >= sizeof tmpfn || 3034363466Sgshapiro sm_strlcat(tmpfn, ".tmp", sizeof tmpfn) >= sizeof tmpfn) 3035363466Sgshapiro { 3036363466Sgshapiro syserr("cdb: set temp filename for %s failed", 3037363466Sgshapiro map->map_file); 3038363466Sgshapiro } 3039363466Sgshapiro if (tTd(38, 80)) 3040363466Sgshapiro sm_dprintf("rename(%s, %s)\n", tmpfn, cdbfn); 3041363466Sgshapiro if (rename(tmpfn, cdbfn) == -1) 3042363466Sgshapiro syserr("cdb: rename(%s, %s) failed", tmpfn, cdbfn); 3043363466Sgshapiro sm_free(cdbmp); 3044363466Sgshapiro cdbmp = NULL; 3045363466Sgshapiro } 3046363466Sgshapiro if (fd >=0) 3047363466Sgshapiro close(fd); 3048363466Sgshapiro} 3049363466Sgshapiro#endif /* CDB */ 3050363466Sgshapiro 3051363466Sgshapiro/* 305238032Speter** NIS Modules 305338032Speter*/ 305438032Speter 305590792Sgshapiro#if NIS 305638032Speter 305738032Speter# ifndef YPERR_BUSY 305838032Speter# define YPERR_BUSY 16 3059363466Sgshapiro# endif 306038032Speter 306138032Speter/* 306238032Speter** NIS_MAP_OPEN -- open DBM map 306338032Speter*/ 306438032Speter 306538032Speterbool 306638032Speternis_map_open(map, mode) 306738032Speter MAP *map; 306838032Speter int mode; 306938032Speter{ 307038032Speter int yperr; 307138032Speter register char *p; 307238032Speter auto char *vp; 307338032Speter auto int vsize; 307438032Speter 307538032Speter if (tTd(38, 2)) 307690792Sgshapiro sm_dprintf("nis_map_open(%s, %s, %d)\n", 307738032Speter map->map_mname, map->map_file, mode); 307838032Speter 307938032Speter mode &= O_ACCMODE; 308038032Speter if (mode != O_RDONLY) 308138032Speter { 308238032Speter /* issue a pseudo-error message */ 308390792Sgshapiro errno = SM_EMAPCANTWRITE; 308490792Sgshapiro return false; 308538032Speter } 308638032Speter 308738032Speter p = strchr(map->map_file, '@'); 308838032Speter if (p != NULL) 308938032Speter { 309038032Speter *p++ = '\0'; 309138032Speter if (*p != '\0') 309238032Speter map->map_domain = p; 309338032Speter } 309438032Speter 309538032Speter if (*map->map_file == '\0') 309638032Speter map->map_file = "mail.aliases"; 309738032Speter 309838032Speter if (map->map_domain == NULL) 309938032Speter { 310038032Speter yperr = yp_get_default_domain(&map->map_domain); 310138032Speter if (yperr != 0) 310238032Speter { 310338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 310494334Sgshapiro syserr("451 4.3.5 NIS map %s specified, but NIS not running", 310564562Sgshapiro map->map_file); 310690792Sgshapiro return false; 310738032Speter } 310838032Speter } 310938032Speter 311038032Speter /* check to see if this map actually exists */ 311164562Sgshapiro vp = NULL; 311238032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 311338032Speter &vp, &vsize); 311438032Speter if (tTd(38, 10)) 311590792Sgshapiro sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 311638032Speter map->map_domain, map->map_file, yperr_string(yperr)); 311764562Sgshapiro if (vp != NULL) 311877349Sgshapiro sm_free(vp); 311964562Sgshapiro 312038032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 312138032Speter { 312238032Speter /* 312338032Speter ** We ought to be calling aliaswait() here if this is an 3124363466Sgshapiro ** alias file, but powerful HP-UX NIS servers apparently 312538032Speter ** don't insert the @:@ token into the alias map when it 312638032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 312738032Speter */ 312838032Speter 312964562Sgshapiro# if 0 313038032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 313190792Sgshapiro aliaswait(map, NULL, true)) 3132363466Sgshapiro# endif 313390792Sgshapiro return true; 313438032Speter } 313538032Speter 313638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 313738032Speter { 313894334Sgshapiro syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s", 313938032Speter map->map_file, map->map_domain, yperr_string(yperr)); 314038032Speter } 314138032Speter 314290792Sgshapiro return false; 314338032Speter} 314438032Speter 314538032Speter 314638032Speter/* 314738032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 314838032Speter*/ 314938032Speter 315038032Speter/* ARGSUSED3 */ 315138032Speterchar * 315238032Speternis_map_lookup(map, name, av, statp) 315338032Speter MAP *map; 315438032Speter char *name; 315538032Speter char **av; 315638032Speter int *statp; 315738032Speter{ 315838032Speter char *vp; 315938032Speter auto int vsize; 316038032Speter int buflen; 316138032Speter int yperr; 316238032Speter char keybuf[MAXNAME + 1]; 316390792Sgshapiro char *SM_NONVOLATILE result = NULL; 316438032Speter 316538032Speter if (tTd(38, 20)) 316690792Sgshapiro sm_dprintf("nis_map_lookup(%s, %s)\n", 316738032Speter map->map_mname, name); 316838032Speter 316938032Speter buflen = strlen(name); 3170168515Sgshapiro if (buflen > sizeof(keybuf) - 1) 3171168515Sgshapiro buflen = sizeof(keybuf) - 1; 317264562Sgshapiro memmove(keybuf, name, buflen); 317338032Speter keybuf[buflen] = '\0'; 317438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 317538032Speter makelower(keybuf); 317638032Speter yperr = YPERR_KEY; 317764562Sgshapiro vp = NULL; 317838032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 317938032Speter { 318038032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 318138032Speter &vp, &vsize); 318238032Speter if (yperr == 0) 318338032Speter map->map_mflags &= ~MF_TRY1NULL; 318438032Speter } 318538032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 318638032Speter { 3187363466Sgshapiro SM_FREE(vp); 318838032Speter buflen++; 318938032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 319038032Speter &vp, &vsize); 319138032Speter if (yperr == 0) 319238032Speter map->map_mflags &= ~MF_TRY0NULL; 319338032Speter } 319438032Speter if (yperr != 0) 319538032Speter { 319638032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 319738032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 319864562Sgshapiro if (vp != NULL) 319977349Sgshapiro sm_free(vp); 320038032Speter return NULL; 320138032Speter } 320290792Sgshapiro SM_TRY 320390792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 320490792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 320590792Sgshapiro else 320690792Sgshapiro result = map_rewrite(map, vp, vsize, av); 320790792Sgshapiro SM_FINALLY 320864562Sgshapiro if (vp != NULL) 320977349Sgshapiro sm_free(vp); 321090792Sgshapiro SM_END_TRY 321190792Sgshapiro return result; 321238032Speter} 321338032Speter 321438032Speter 321538032Speter/* 321638032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 321738032Speter*/ 321838032Speter 321964562Sgshapirostatic bool 322038032Speternis_getcanonname(name, hbsize, statp) 322138032Speter char *name; 322238032Speter int hbsize; 322338032Speter int *statp; 322438032Speter{ 322538032Speter char *vp; 322638032Speter auto int vsize; 322738032Speter int keylen; 322838032Speter int yperr; 322990792Sgshapiro static bool try0null = true; 323090792Sgshapiro static bool try1null = true; 323138032Speter static char *yp_domain = NULL; 323238032Speter char host_record[MAXLINE]; 323338032Speter char cbuf[MAXNAME]; 323438032Speter char nbuf[MAXNAME + 1]; 323538032Speter 323638032Speter if (tTd(38, 20)) 323790792Sgshapiro sm_dprintf("nis_getcanonname(%s)\n", name); 323838032Speter 3239168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 324038032Speter { 324138032Speter *statp = EX_UNAVAILABLE; 324290792Sgshapiro return false; 324338032Speter } 324473188Sgshapiro (void) shorten_hostname(nbuf); 324538032Speter keylen = strlen(nbuf); 324638032Speter 324738032Speter if (yp_domain == NULL) 324864562Sgshapiro (void) yp_get_default_domain(&yp_domain); 324938032Speter makelower(nbuf); 325038032Speter yperr = YPERR_KEY; 325164562Sgshapiro vp = NULL; 325238032Speter if (try0null) 325338032Speter { 325438032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 325538032Speter &vp, &vsize); 325638032Speter if (yperr == 0) 325790792Sgshapiro try1null = false; 325838032Speter } 325938032Speter if (yperr == YPERR_KEY && try1null) 326038032Speter { 3261363466Sgshapiro SM_FREE(vp); 326238032Speter keylen++; 326338032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 326438032Speter &vp, &vsize); 326538032Speter if (yperr == 0) 326690792Sgshapiro try0null = false; 326738032Speter } 326838032Speter if (yperr != 0) 326938032Speter { 327038032Speter if (yperr == YPERR_KEY) 327138032Speter *statp = EX_NOHOST; 327238032Speter else if (yperr == YPERR_BUSY) 327338032Speter *statp = EX_TEMPFAIL; 327438032Speter else 327538032Speter *statp = EX_UNAVAILABLE; 327664562Sgshapiro if (vp != NULL) 327777349Sgshapiro sm_free(vp); 327890792Sgshapiro return false; 327938032Speter } 3280168515Sgshapiro (void) sm_strlcpy(host_record, vp, sizeof(host_record)); 328177349Sgshapiro sm_free(vp); 328238032Speter if (tTd(38, 44)) 328390792Sgshapiro sm_dprintf("got record `%s'\n", host_record); 328490792Sgshapiro vp = strpbrk(host_record, "#\n"); 328590792Sgshapiro if (vp != NULL) 328690792Sgshapiro *vp = '\0'; 3287168515Sgshapiro if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof(cbuf))) 328838032Speter { 328938032Speter /* this should not happen, but.... */ 329038032Speter *statp = EX_NOHOST; 329190792Sgshapiro return false; 329238032Speter } 329390792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 329438032Speter { 329538032Speter *statp = EX_UNAVAILABLE; 329690792Sgshapiro return false; 329738032Speter } 329838032Speter *statp = EX_OK; 329990792Sgshapiro return true; 330038032Speter} 330138032Speter 330264562Sgshapiro#endif /* NIS */ 330390792Sgshapiro/* 330438032Speter** NISPLUS Modules 330538032Speter** 330638032Speter** This code donated by Sun Microsystems. 330738032Speter*/ 330838032Speter 330990792Sgshapiro#if NISPLUS 331038032Speter 331164562Sgshapiro# undef NIS /* symbol conflict in nis.h */ 331264562Sgshapiro# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 331364562Sgshapiro# include <rpcsvc/nis.h> 331464562Sgshapiro# include <rpcsvc/nislib.h> 3315249729Sgshapiro# ifndef NIS_TABLE_OBJ 3316249729Sgshapiro# define NIS_TABLE_OBJ TABLE_OBJ 3317363466Sgshapiro# endif 331838032Speter 331964562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 332064562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 332164562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 332264562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 332338032Speter 332438032Speter/* 332538032Speter** NISPLUS_MAP_OPEN -- open nisplus table 332638032Speter*/ 332738032Speter 332838032Speterbool 332938032Speternisplus_map_open(map, mode) 333038032Speter MAP *map; 333138032Speter int mode; 333238032Speter{ 333338032Speter nis_result *res = NULL; 333438032Speter int retry_cnt, max_col, i; 333538032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 333638032Speter 333738032Speter if (tTd(38, 2)) 333890792Sgshapiro sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 333938032Speter map->map_mname, map->map_file, mode); 334038032Speter 334138032Speter mode &= O_ACCMODE; 334238032Speter if (mode != O_RDONLY) 334338032Speter { 334438032Speter errno = EPERM; 334590792Sgshapiro return false; 334638032Speter } 334738032Speter 334838032Speter if (*map->map_file == '\0') 334938032Speter map->map_file = "mail_aliases.org_dir"; 335038032Speter 335138032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 335238032Speter { 335338032Speter /* set default NISPLUS Domain to $m */ 335438032Speter map->map_domain = newstr(nisplus_default_domain()); 335538032Speter if (tTd(38, 2)) 335690792Sgshapiro sm_dprintf("nisplus_map_open(%s): using domain %s\n", 335764562Sgshapiro map->map_file, map->map_domain); 335838032Speter } 335938032Speter if (!PARTIAL_NAME(map->map_file)) 336038032Speter { 336138032Speter map->map_domain = newstr(""); 3362168515Sgshapiro (void) sm_strlcpy(qbuf, map->map_file, sizeof(qbuf)); 336338032Speter } 336438032Speter else 336538032Speter { 336638032Speter /* check to see if this map actually exists */ 3367168515Sgshapiro (void) sm_strlcpyn(qbuf, sizeof(qbuf), 3, 336890792Sgshapiro map->map_file, ".", map->map_domain); 336938032Speter } 337038032Speter 337138032Speter retry_cnt = 0; 337238032Speter while (res == NULL || res->status != NIS_SUCCESS) 337338032Speter { 337438032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 337538032Speter switch (res->status) 337638032Speter { 337738032Speter case NIS_SUCCESS: 337838032Speter break; 337938032Speter 338038032Speter case NIS_TRYAGAIN: 338138032Speter case NIS_RPCERROR: 338238032Speter case NIS_NAMEUNREACHABLE: 338338032Speter if (retry_cnt++ > 4) 338438032Speter { 338538032Speter errno = EAGAIN; 338690792Sgshapiro return false; 338738032Speter } 338838032Speter /* try not to overwhelm hosed server */ 338938032Speter sleep(2); 339038032Speter break; 339138032Speter 339238032Speter default: /* all other nisplus errors */ 339364562Sgshapiro# if 0 339438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 339594334Sgshapiro syserr("451 4.3.5 Cannot find table %s.%s: %s", 339638032Speter map->map_file, map->map_domain, 339738032Speter nis_sperrno(res->status)); 339864562Sgshapiro# endif /* 0 */ 339938032Speter errno = EAGAIN; 340090792Sgshapiro return false; 340138032Speter } 340238032Speter } 340338032Speter 340438032Speter if (NIS_RES_NUMOBJ(res) != 1 || 3405249729Sgshapiro (NIS_RES_OBJECT(res)->zo_data.zo_type != NIS_TABLE_OBJ)) 340638032Speter { 340738032Speter if (tTd(38, 10)) 340890792Sgshapiro sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 340964562Sgshapiro# if 0 341038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 341194334Sgshapiro syserr("451 4.3.5 %s.%s: %s is not a table", 341238032Speter map->map_file, map->map_domain, 341338032Speter nis_sperrno(res->status)); 341464562Sgshapiro# endif /* 0 */ 341538032Speter errno = EBADF; 341690792Sgshapiro return false; 341738032Speter } 341838032Speter /* default key column is column 0 */ 341938032Speter if (map->map_keycolnm == NULL) 342038032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 342138032Speter 342238032Speter max_col = COL_MAX(res); 342338032Speter 342438032Speter /* verify the key column exist */ 342590792Sgshapiro for (i = 0; i < max_col; i++) 342638032Speter { 342764562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 342838032Speter break; 342938032Speter } 343038032Speter if (i == max_col) 343138032Speter { 343238032Speter if (tTd(38, 2)) 343390792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 343438032Speter map->map_file, map->map_keycolnm); 343538032Speter errno = ENOENT; 343690792Sgshapiro return false; 343738032Speter } 343838032Speter 343938032Speter /* default value column is the last column */ 344038032Speter if (map->map_valcolnm == NULL) 344138032Speter { 344238032Speter map->map_valcolno = max_col - 1; 344390792Sgshapiro return true; 344438032Speter } 344538032Speter 344664562Sgshapiro for (i = 0; i< max_col; i++) 344738032Speter { 344838032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 344938032Speter { 345038032Speter map->map_valcolno = i; 345190792Sgshapiro return true; 345238032Speter } 345338032Speter } 345438032Speter 345538032Speter if (tTd(38, 2)) 345690792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 345764562Sgshapiro map->map_file, map->map_keycolnm); 345838032Speter errno = ENOENT; 345990792Sgshapiro return false; 346038032Speter} 346138032Speter 346238032Speter 346338032Speter/* 346438032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 346538032Speter*/ 346638032Speter 346738032Speterchar * 346838032Speternisplus_map_lookup(map, name, av, statp) 346938032Speter MAP *map; 347038032Speter char *name; 347138032Speter char **av; 347238032Speter int *statp; 347338032Speter{ 347438032Speter char *p; 347538032Speter auto int vsize; 347638032Speter char *skp; 347738032Speter int skleft; 347838032Speter char search_key[MAXNAME + 4]; 347938032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 348038032Speter nis_result *result; 348138032Speter 348238032Speter if (tTd(38, 20)) 348390792Sgshapiro sm_dprintf("nisplus_map_lookup(%s, %s)\n", 348438032Speter map->map_mname, name); 348538032Speter 348638032Speter if (!bitset(MF_OPEN, map->map_mflags)) 348738032Speter { 348838032Speter if (nisplus_map_open(map, O_RDONLY)) 348942575Speter { 349038032Speter map->map_mflags |= MF_OPEN; 349190792Sgshapiro map->map_pid = CurrentPid; 349242575Speter } 349338032Speter else 349438032Speter { 349538032Speter *statp = EX_UNAVAILABLE; 349638032Speter return NULL; 349738032Speter } 349838032Speter } 349938032Speter 350038032Speter /* 350138032Speter ** Copy the name to the key buffer, escaping double quote characters 350238032Speter ** by doubling them and quoting "]" and "," to avoid having the 350338032Speter ** NIS+ parser choke on them. 350438032Speter */ 350538032Speter 3506168515Sgshapiro skleft = sizeof(search_key) - 4; 350738032Speter skp = search_key; 350838032Speter for (p = name; *p != '\0' && skleft > 0; p++) 350938032Speter { 351038032Speter switch (*p) 351138032Speter { 351238032Speter case ']': 351338032Speter case ',': 351438032Speter /* quote the character */ 351538032Speter *skp++ = '"'; 351638032Speter *skp++ = *p; 351738032Speter *skp++ = '"'; 351838032Speter skleft -= 3; 351938032Speter break; 352038032Speter 352138032Speter case '"': 352238032Speter /* double the quote */ 352338032Speter *skp++ = '"'; 352438032Speter skleft--; 352564562Sgshapiro /* FALLTHROUGH */ 352638032Speter 352738032Speter default: 352838032Speter *skp++ = *p; 352938032Speter skleft--; 353038032Speter break; 353138032Speter } 353238032Speter } 353338032Speter *skp = '\0'; 353438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 353538032Speter makelower(search_key); 353638032Speter 353738032Speter /* construct the query */ 353838032Speter if (PARTIAL_NAME(map->map_file)) 3539168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s.%s", 354038032Speter map->map_keycolnm, search_key, map->map_file, 354138032Speter map->map_domain); 354238032Speter else 3543168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s", 354438032Speter map->map_keycolnm, search_key, map->map_file); 354538032Speter 354638032Speter if (tTd(38, 20)) 354790792Sgshapiro sm_dprintf("qbuf=%s\n", qbuf); 354838032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 354938032Speter if (result->status == NIS_SUCCESS) 355038032Speter { 355138032Speter int count; 355238032Speter char *str; 355338032Speter 355438032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 355538032Speter { 355638032Speter if (LogLevel > 10) 355738032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 355864562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 355964562Sgshapiro map->map_file, count); 356038032Speter 356138032Speter /* ignore second entry */ 356238032Speter if (tTd(38, 20)) 356390792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 356438032Speter name, count); 356538032Speter } 356638032Speter 356738032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 356838032Speter /* set the length of the result */ 356938032Speter if (p == NULL) 357038032Speter p = ""; 357138032Speter vsize = strlen(p); 357238032Speter if (tTd(38, 20)) 357390792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), found %s\n", 357438032Speter name, p); 357538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 357638032Speter str = map_rewrite(map, name, strlen(name), NULL); 357738032Speter else 357838032Speter str = map_rewrite(map, p, vsize, av); 357938032Speter nis_freeresult(result); 358038032Speter *statp = EX_OK; 358138032Speter return str; 358238032Speter } 358338032Speter else 358438032Speter { 358538032Speter if (result->status == NIS_NOTFOUND) 358638032Speter *statp = EX_NOTFOUND; 358738032Speter else if (result->status == NIS_TRYAGAIN) 358838032Speter *statp = EX_TEMPFAIL; 358938032Speter else 359038032Speter { 359138032Speter *statp = EX_UNAVAILABLE; 359238032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 359338032Speter } 359438032Speter } 359538032Speter if (tTd(38, 20)) 359690792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 359738032Speter nis_freeresult(result); 359838032Speter return NULL; 359938032Speter} 360038032Speter 360138032Speter 360238032Speter 360338032Speter/* 360438032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 360538032Speter*/ 360638032Speter 360764562Sgshapirostatic bool 360838032Speternisplus_getcanonname(name, hbsize, statp) 360938032Speter char *name; 361038032Speter int hbsize; 361138032Speter int *statp; 361238032Speter{ 361338032Speter char *vp; 361438032Speter auto int vsize; 361538032Speter nis_result *result; 361638032Speter char *p; 361738032Speter char nbuf[MAXNAME + 1]; 361838032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 361938032Speter 3620168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 362138032Speter { 362238032Speter *statp = EX_UNAVAILABLE; 362390792Sgshapiro return false; 362438032Speter } 362573188Sgshapiro (void) shorten_hostname(nbuf); 362638032Speter 362738032Speter p = strchr(nbuf, '.'); 362838032Speter if (p == NULL) 362938032Speter { 363038032Speter /* single token */ 3631168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 363290792Sgshapiro "[name=%s],hosts.org_dir", nbuf); 363338032Speter } 363438032Speter else if (p[1] != '\0') 363538032Speter { 363638032Speter /* multi token -- take only first token in nbuf */ 363738032Speter *p = '\0'; 3638168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 363990792Sgshapiro "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 364038032Speter } 364138032Speter else 364238032Speter { 364338032Speter *statp = EX_NOHOST; 364490792Sgshapiro return false; 364538032Speter } 364638032Speter 364738032Speter if (tTd(38, 20)) 364894334Sgshapiro sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 364990792Sgshapiro name, qbuf); 365038032Speter 365138032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 365290792Sgshapiro NULL, NULL); 365338032Speter 365438032Speter if (result->status == NIS_SUCCESS) 365538032Speter { 365638032Speter int count; 365738032Speter char *domain; 365838032Speter 365938032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 366038032Speter { 366138032Speter if (LogLevel > 10) 366238032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 366364562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 366464562Sgshapiro count); 366538032Speter 366638032Speter /* ignore second entry */ 366738032Speter if (tTd(38, 20)) 366894334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 366990792Sgshapiro name, count); 367038032Speter } 367138032Speter 367238032Speter if (tTd(38, 20)) 367394334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 367490792Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 367538032Speter 367638032Speter 367738032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 367838032Speter vsize = strlen(vp); 367938032Speter if (tTd(38, 20)) 368090792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found %s\n", 368190792Sgshapiro name, vp); 368238032Speter if (strchr(vp, '.') != NULL) 368338032Speter { 368438032Speter domain = ""; 368538032Speter } 368638032Speter else 368738032Speter { 368838032Speter domain = macvalue('m', CurEnv); 368938032Speter if (domain == NULL) 369038032Speter domain = ""; 369138032Speter } 369238032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 369338032Speter { 369438032Speter if (domain[0] == '\0') 369590792Sgshapiro (void) sm_strlcpy(name, vp, hbsize); 369638032Speter else 369790792Sgshapiro (void) sm_snprintf(name, hbsize, 369890792Sgshapiro "%s.%s", vp, domain); 369938032Speter *statp = EX_OK; 370038032Speter } 370138032Speter else 370238032Speter *statp = EX_NOHOST; 370338032Speter nis_freeresult(result); 370490792Sgshapiro return true; 370538032Speter } 370638032Speter else 370738032Speter { 370838032Speter if (result->status == NIS_NOTFOUND) 370938032Speter *statp = EX_NOHOST; 371038032Speter else if (result->status == NIS_TRYAGAIN) 371138032Speter *statp = EX_TEMPFAIL; 371238032Speter else 371338032Speter *statp = EX_UNAVAILABLE; 371438032Speter } 371538032Speter if (tTd(38, 20)) 371690792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 371790792Sgshapiro name, result->status, *statp); 371838032Speter nis_freeresult(result); 371990792Sgshapiro return false; 372038032Speter} 372138032Speter 372238032Speterchar * 372338032Speternisplus_default_domain() 372438032Speter{ 372538032Speter static char default_domain[MAXNAME + 1] = ""; 372638032Speter char *p; 372738032Speter 372838032Speter if (default_domain[0] != '\0') 372964562Sgshapiro return default_domain; 373038032Speter 373138032Speter p = nis_local_directory(); 3732168515Sgshapiro (void) sm_strlcpy(default_domain, p, sizeof(default_domain)); 373338032Speter return default_domain; 373438032Speter} 373538032Speter 373638032Speter#endif /* NISPLUS */ 373790792Sgshapiro/* 373838032Speter** LDAP Modules 373938032Speter*/ 374038032Speter 374164562Sgshapiro/* 374264562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 374364562Sgshapiro*/ 374464562Sgshapiro 374564562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 374664562Sgshapiro 374790792Sgshapiro# if PH_MAP 374864562Sgshapiro# define ph_map_dequote ldapmap_dequote 3749363466Sgshapiro# endif 375064562Sgshapiro 375190792Sgshapirostatic char *ldapmap_dequote __P((char *)); 375290792Sgshapiro 375390792Sgshapirostatic char * 375464562Sgshapiroldapmap_dequote(str) 375564562Sgshapiro char *str; 375664562Sgshapiro{ 375764562Sgshapiro char *p; 375864562Sgshapiro char *start; 375964562Sgshapiro 376064562Sgshapiro if (str == NULL) 376164562Sgshapiro return NULL; 376264562Sgshapiro 376364562Sgshapiro p = str; 376464562Sgshapiro if (*p == '"') 376564562Sgshapiro { 376664562Sgshapiro /* Should probably swallow initial whitespace here */ 376764562Sgshapiro start = ++p; 376864562Sgshapiro } 376964562Sgshapiro else 377064562Sgshapiro return str; 377164562Sgshapiro while (*p != '"' && *p != '\0') 377264562Sgshapiro p++; 377364562Sgshapiro if (*p != '\0') 377464562Sgshapiro *p = '\0'; 377564562Sgshapiro return start; 377664562Sgshapiro} 377764562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 377864562Sgshapiro 377990792Sgshapiro#if LDAPMAP 378038032Speter 378190792Sgshapirostatic SM_LDAP_STRUCT *LDAPDefaults = NULL; 378238032Speter 378338032Speter/* 378464562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 378538032Speter** 378664562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 378764562Sgshapiro** single server connection to a host (with the same host, port, 378864562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 378938032Speter*/ 379038032Speter 379138032Speterbool 379264562Sgshapiroldapmap_open(map, mode) 379338032Speter MAP *map; 379438032Speter int mode; 379538032Speter{ 379690792Sgshapiro SM_LDAP_STRUCT *lmap; 379764562Sgshapiro STAB *s; 3798132943Sgshapiro char *id; 379964562Sgshapiro 380038032Speter if (tTd(38, 2)) 380190792Sgshapiro sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 380238032Speter 3803168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3804168515Sgshapiro HASLDAPGETALIASBYNAME 3805168515Sgshapiro if (VendorCode == VENDOR_SUN && 3806168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3807168515Sgshapiro { 3808168515Sgshapiro return true; 3809168515Sgshapiro } 3810168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3811168515Sgshapiro 381238032Speter mode &= O_ACCMODE; 381364562Sgshapiro 381464562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 381538032Speter if (mode != O_RDONLY) 381638032Speter { 381738032Speter /* issue a pseudo-error message */ 381890792Sgshapiro errno = SM_EMAPCANTWRITE; 381990792Sgshapiro return false; 382038032Speter } 382164562Sgshapiro 382290792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 382364562Sgshapiro 382464562Sgshapiro s = ldapmap_findconn(lmap); 382577349Sgshapiro if (s->s_lmap != NULL) 382664562Sgshapiro { 382764562Sgshapiro /* Already have a connection open to this LDAP server */ 382890792Sgshapiro lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 382990792Sgshapiro lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 383077349Sgshapiro 383177349Sgshapiro /* Add this map as head of linked list */ 383277349Sgshapiro lmap->ldap_next = s->s_lmap; 383377349Sgshapiro s->s_lmap = map; 383477349Sgshapiro 383566494Sgshapiro if (tTd(38, 2)) 383690792Sgshapiro sm_dprintf("using cached connection\n"); 383790792Sgshapiro return true; 383864562Sgshapiro } 383964562Sgshapiro 384066494Sgshapiro if (tTd(38, 2)) 384190792Sgshapiro sm_dprintf("opening new connection\n"); 384266494Sgshapiro 3843132943Sgshapiro if (lmap->ldap_host != NULL) 3844132943Sgshapiro id = lmap->ldap_host; 3845132943Sgshapiro else if (lmap->ldap_uri != NULL) 3846132943Sgshapiro id = lmap->ldap_uri; 3847132943Sgshapiro else 3848132943Sgshapiro id = "localhost"; 3849132943Sgshapiro 3850203004Sgshapiro if (tTd(74, 104)) 3851203004Sgshapiro { 3852203004Sgshapiro extern MAPCLASS NullMapClass; 3853203004Sgshapiro 3854203004Sgshapiro /* debug mode: don't actually open an LDAP connection */ 3855203004Sgshapiro map->map_orgclass = map->map_class; 3856203004Sgshapiro map->map_class = &NullMapClass; 3857203004Sgshapiro map->map_mflags |= MF_OPEN; 3858203004Sgshapiro map->map_pid = CurrentPid; 3859203004Sgshapiro return true; 3860203004Sgshapiro } 3861203004Sgshapiro 386264562Sgshapiro /* No connection yet, connect */ 386390792Sgshapiro if (!sm_ldap_start(map->map_mname, lmap)) 386438032Speter { 386590792Sgshapiro if (errno == ETIMEDOUT) 386638032Speter { 386738032Speter if (LogLevel > 1) 386838032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 3869244833Sgshapiro "timeout connecting to LDAP server %.100s", 3870132943Sgshapiro id); 387138032Speter } 387238032Speter 387338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 387438032Speter { 387564562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3876132943Sgshapiro { 387764562Sgshapiro syserr("%s failed to %s in map %s", 387864562Sgshapiro# if USE_LDAP_INIT 387990792Sgshapiro "ldap_init/ldap_bind", 3880363466Sgshapiro# else 388164562Sgshapiro "ldap_open", 3882363466Sgshapiro# endif 3883132943Sgshapiro id, map->map_mname); 3884132943Sgshapiro } 388564562Sgshapiro else 3886132943Sgshapiro { 388794334Sgshapiro syserr("451 4.3.5 %s failed to %s in map %s", 388864562Sgshapiro# if USE_LDAP_INIT 388990792Sgshapiro "ldap_init/ldap_bind", 3890363466Sgshapiro# else 389164562Sgshapiro "ldap_open", 3892363466Sgshapiro# endif 3893132943Sgshapiro id, map->map_mname); 3894132943Sgshapiro } 389538032Speter } 389690792Sgshapiro return false; 389738032Speter } 389838032Speter 389990792Sgshapiro /* Save connection for reuse */ 390090792Sgshapiro s->s_lmap = map; 390190792Sgshapiro return true; 390238032Speter} 390338032Speter 390438032Speter/* 390564562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 390638032Speter*/ 390738032Speter 390838032Spetervoid 390964562Sgshapiroldapmap_close(map) 391038032Speter MAP *map; 391138032Speter{ 391290792Sgshapiro SM_LDAP_STRUCT *lmap; 391364562Sgshapiro STAB *s; 391443730Speter 391564562Sgshapiro if (tTd(38, 2)) 391690792Sgshapiro sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 391764562Sgshapiro 391890792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 391964562Sgshapiro 392064562Sgshapiro /* Check if already closed */ 392164562Sgshapiro if (lmap->ldap_ld == NULL) 392264562Sgshapiro return; 392364562Sgshapiro 392477349Sgshapiro /* Close the LDAP connection */ 392590792Sgshapiro sm_ldap_close(lmap); 392677349Sgshapiro 392777349Sgshapiro /* Mark all the maps that share the connection as closed */ 392864562Sgshapiro s = ldapmap_findconn(lmap); 392964562Sgshapiro 393077349Sgshapiro while (s->s_lmap != NULL) 393177349Sgshapiro { 393277349Sgshapiro MAP *smap = s->s_lmap; 393364562Sgshapiro 393477349Sgshapiro if (tTd(38, 2) && smap != map) 393590792Sgshapiro sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 393690792Sgshapiro map->map_mname, smap->map_mname); 393777349Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 393890792Sgshapiro lmap = (SM_LDAP_STRUCT *) smap->map_db1; 393964562Sgshapiro lmap->ldap_ld = NULL; 394077349Sgshapiro s->s_lmap = lmap->ldap_next; 394177349Sgshapiro lmap->ldap_next = NULL; 394243730Speter } 394338032Speter} 394438032Speter 394564562Sgshapiro# ifdef SUNET_ID 394643730Speter/* 394790792Sgshapiro** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 394842575Speter** This only makes sense at Stanford University. 394938032Speter*/ 395038032Speter 395190792Sgshapirostatic char * 395238032Spetersunet_id_hash(str) 395338032Speter char *str; 395438032Speter{ 395538032Speter char *p, *p_last; 395638032Speter 395738032Speter p = str; 395838032Speter p_last = p; 395938032Speter while (*p != '\0') 396038032Speter { 3961203004Sgshapiro if (isascii(*p) && (islower(*p) || isdigit(*p))) 396238032Speter { 396338032Speter *p_last = *p; 396438032Speter p_last++; 396538032Speter } 3966203004Sgshapiro else if (isascii(*p) && isupper(*p)) 396738032Speter { 396838032Speter *p_last = tolower(*p); 396938032Speter p_last++; 397038032Speter } 397138032Speter ++p; 397238032Speter } 397338032Speter if (*p_last != '\0') 397438032Speter *p_last = '\0'; 397564562Sgshapiro return str; 397638032Speter} 3977168515Sgshapiro# define SM_CONVERT_ID(str) sunet_id_hash(str) 3978168515Sgshapiro# else /* SUNET_ID */ 3979168515Sgshapiro# define SM_CONVERT_ID(str) makelower(str) 398064562Sgshapiro# endif /* SUNET_ID */ 398138032Speter 398238032Speter/* 398364562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 398438032Speter*/ 398538032Speter 398638032Speterchar * 398764562Sgshapiroldapmap_lookup(map, name, av, statp) 398838032Speter MAP *map; 398938032Speter char *name; 399038032Speter char **av; 399138032Speter int *statp; 399238032Speter{ 3993132943Sgshapiro int flags; 3994168515Sgshapiro int i; 399594334Sgshapiro int plen = 0; 399694334Sgshapiro int psize = 0; 399764562Sgshapiro int msgid; 399890792Sgshapiro int save_errno; 399990792Sgshapiro char *vp, *p; 400064562Sgshapiro char *result = NULL; 4001132943Sgshapiro SM_RPOOL_T *rpool; 400290792Sgshapiro SM_LDAP_STRUCT *lmap = NULL; 4003168515Sgshapiro char *argv[SM_LDAP_ARGS]; 4004157001Sgshapiro char keybuf[MAXKEY]; 4005168515Sgshapiro#if SM_LDAP_ARGS != MAX_MAP_ARGS 4006168515Sgshapiro# ERROR _SM_LDAP_ARGS must be the same as _MAX_MAP_ARGS 4007363466Sgshapiro#endif 400838032Speter 4009168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 4010168515Sgshapiro HASLDAPGETALIASBYNAME 4011168515Sgshapiro if (VendorCode == VENDOR_SUN && 4012168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 4013168515Sgshapiro { 4014168515Sgshapiro int rc; 4015173340Sgshapiro#if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2) 4016173340Sgshapiro extern char *__getldapaliasbyname(); 4017173340Sgshapiro char *answer; 401838032Speter 4019173340Sgshapiro answer = __getldapaliasbyname(name, &rc); 4020173340Sgshapiro#else 4021173340Sgshapiro char answer[MAXNAME + 1]; 4022173340Sgshapiro 4023168515Sgshapiro rc = __getldapaliasbyname(name, answer, sizeof(answer)); 4024173340Sgshapiro#endif 4025168515Sgshapiro if (rc != 0) 4026168515Sgshapiro { 4027168515Sgshapiro if (tTd(38, 20)) 4028168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n", 4029168515Sgshapiro name, errno); 4030168515Sgshapiro *statp = EX_NOTFOUND; 4031168515Sgshapiro return NULL; 4032168515Sgshapiro } 4033168515Sgshapiro *statp = EX_OK; 4034168515Sgshapiro if (tTd(38, 20)) 4035168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name, 4036168515Sgshapiro answer); 4037168515Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 4038168515Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 4039168515Sgshapiro else 4040168515Sgshapiro result = map_rewrite(map, answer, strlen(answer), av); 4041173340Sgshapiro#if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2) 4042173340Sgshapiro free(answer); 4043173340Sgshapiro#endif 4044168515Sgshapiro return result; 4045168515Sgshapiro } 4046168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 4047168515Sgshapiro 404838032Speter /* Get ldap struct pointer from map */ 404990792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 405090792Sgshapiro sm_ldap_setopts(lmap->ldap_ld, lmap); 405138032Speter 4052168515Sgshapiro if (lmap->ldap_multi_args) 4053168515Sgshapiro { 4054168515Sgshapiro SM_REQUIRE(av != NULL); 4055168515Sgshapiro memset(argv, '\0', sizeof(argv)); 4056168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && av[i] != NULL; i++) 4057168515Sgshapiro { 4058168515Sgshapiro argv[i] = sm_strdup(av[i]); 4059168515Sgshapiro if (argv[i] == NULL) 4060168515Sgshapiro { 4061168515Sgshapiro int save_errno, j; 406238032Speter 4063168515Sgshapiro save_errno = errno; 4064168515Sgshapiro for (j = 0; j < i && argv[j] != NULL; j++) 4065168515Sgshapiro SM_FREE(argv[j]); 4066168515Sgshapiro *statp = EX_TEMPFAIL; 4067168515Sgshapiro errno = save_errno; 4068168515Sgshapiro return NULL; 4069168515Sgshapiro } 4070168515Sgshapiro 4071168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 4072168515Sgshapiro SM_CONVERT_ID(av[i]); 4073168515Sgshapiro } 4074168515Sgshapiro } 4075168515Sgshapiro else 407664562Sgshapiro { 4077168515Sgshapiro (void) sm_strlcpy(keybuf, name, sizeof(keybuf)); 4078168515Sgshapiro 4079168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 4080168515Sgshapiro SM_CONVERT_ID(keybuf); 408164562Sgshapiro } 408238032Speter 4083168515Sgshapiro if (tTd(38, 20)) 408438032Speter { 4085168515Sgshapiro if (lmap->ldap_multi_args) 4086168515Sgshapiro { 4087168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, argv)\n", 4088168515Sgshapiro map->map_mname); 4089168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS; i++) 4090168515Sgshapiro { 4091168515Sgshapiro sm_dprintf(" argv[%d] = %s\n", i, 4092168515Sgshapiro argv[i] == NULL ? "NULL" : argv[i]); 4093168515Sgshapiro } 4094168515Sgshapiro } 4095168515Sgshapiro else 4096168515Sgshapiro { 4097168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, %s)\n", 4098168515Sgshapiro map->map_mname, name); 4099168515Sgshapiro } 4100168515Sgshapiro } 4101168515Sgshapiro 4102168515Sgshapiro if (lmap->ldap_multi_args) 4103168515Sgshapiro { 4104168515Sgshapiro msgid = sm_ldap_search_m(lmap, argv); 4105168515Sgshapiro 4106168515Sgshapiro /* free the argv array and its content, no longer needed */ 4107168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && argv[i] != NULL; i++) 4108168515Sgshapiro SM_FREE(argv[i]); 4109168515Sgshapiro } 4110168515Sgshapiro else 4111168515Sgshapiro msgid = sm_ldap_search(lmap, keybuf); 4112168515Sgshapiro if (msgid == SM_LDAP_ERR) 4113168515Sgshapiro { 411490792Sgshapiro errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 411577349Sgshapiro save_errno = errno; 411664562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 411738032Speter { 4118168515Sgshapiro /* 4119168515Sgshapiro ** Do not include keybuf as this error may be shown 4120168515Sgshapiro ** to outsiders. 4121168515Sgshapiro */ 4122168515Sgshapiro 412364562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 4124168515Sgshapiro syserr("Error in ldap_search in map %s", 4125168515Sgshapiro map->map_mname); 412664562Sgshapiro else 4127168515Sgshapiro syserr("451 4.3.5 Error in ldap_search in map %s", 4128168515Sgshapiro map->map_mname); 412938032Speter } 413064562Sgshapiro *statp = EX_TEMPFAIL; 413190792Sgshapiro switch (save_errno - E_LDAPBASE) 413290792Sgshapiro { 413394334Sgshapiro# ifdef LDAP_SERVER_DOWN 413490792Sgshapiro case LDAP_SERVER_DOWN: 4135363466Sgshapiro# endif 413690792Sgshapiro case LDAP_TIMEOUT: 413790792Sgshapiro case LDAP_UNAVAILABLE: 413866494Sgshapiro /* server disappeared, try reopen on next search */ 413977349Sgshapiro ldapmap_close(map); 414090792Sgshapiro break; 414166494Sgshapiro } 414277349Sgshapiro errno = save_errno; 414364562Sgshapiro return NULL; 414464562Sgshapiro } 4145168515Sgshapiro#if SM_LDAP_ERROR_ON_MISSING_ARGS 4146168515Sgshapiro else if (msgid == SM_LDAP_ERR_ARG_MISS) 4147168515Sgshapiro { 4148168515Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 4149168515Sgshapiro syserr("Error in ldap_search in map %s, too few arguments", 4150168515Sgshapiro map->map_mname); 4151168515Sgshapiro else 4152168515Sgshapiro syserr("554 5.3.5 Error in ldap_search in map %s, too few arguments", 4153168515Sgshapiro map->map_mname); 4154168515Sgshapiro *statp = EX_CONFIG; 4155168515Sgshapiro return NULL; 4156168515Sgshapiro } 4157168515Sgshapiro#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 415864562Sgshapiro 415964562Sgshapiro *statp = EX_NOTFOUND; 416064562Sgshapiro vp = NULL; 416164562Sgshapiro 4162132943Sgshapiro flags = 0; 4163132943Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 4164132943Sgshapiro flags |= SM_LDAP_SINGLEMATCH; 4165132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 4166132943Sgshapiro flags |= SM_LDAP_MATCHONLY; 4167157001Sgshapiro# if _FFR_LDAP_SINGLEDN 4168157001Sgshapiro if (bitset(MF_SINGLEDN, map->map_mflags)) 4169157001Sgshapiro flags |= SM_LDAP_SINGLEDN; 4170363466Sgshapiro# endif 417190792Sgshapiro 4172132943Sgshapiro /* Create an rpool for search related memory usage */ 4173132943Sgshapiro rpool = sm_rpool_new_x(NULL); 417490792Sgshapiro 4175132943Sgshapiro p = NULL; 4176132943Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 4177132943Sgshapiro rpool, &p, &plen, &psize, NULL); 4178132943Sgshapiro save_errno = errno; 417990792Sgshapiro 4180132943Sgshapiro /* Copy result so rpool can be freed */ 4181132943Sgshapiro if (*statp == EX_OK && p != NULL) 4182132943Sgshapiro vp = newstr(p); 4183132943Sgshapiro sm_rpool_free(rpool); 418490792Sgshapiro 4185132943Sgshapiro /* need to restart LDAP connection? */ 4186132943Sgshapiro if (*statp == EX_RESTART) 418764562Sgshapiro { 4188132943Sgshapiro *statp = EX_TEMPFAIL; 4189132943Sgshapiro ldapmap_close(map); 419038032Speter } 419138032Speter 4192132943Sgshapiro errno = save_errno; 4193132943Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 419438032Speter { 419564562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 419664562Sgshapiro { 419764562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 4198244833Sgshapiro syserr("Error getting LDAP results, map=%s, name=%s", 4199244833Sgshapiro map->map_mname, name); 420064562Sgshapiro else 4201244833Sgshapiro syserr("451 4.3.5 Error getting LDAP results, map=%s, name=%s", 4202244833Sgshapiro map->map_mname, name); 420364562Sgshapiro } 420477349Sgshapiro errno = save_errno; 420564562Sgshapiro return NULL; 420638032Speter } 420790792Sgshapiro 420864562Sgshapiro /* Did we match anything? */ 420971345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 421064562Sgshapiro return NULL; 421138032Speter 421264562Sgshapiro if (*statp == EX_OK) 421364562Sgshapiro { 421464562Sgshapiro if (LogLevel > 9) 421564562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 4216244833Sgshapiro "ldap=%s, %.100s=>%s", map->map_mname, name, 421771345Sgshapiro vp == NULL ? "<NULL>" : vp); 421864562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 421964562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 422064562Sgshapiro else 422171345Sgshapiro { 422271345Sgshapiro /* vp != NULL according to test above */ 422364562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 422471345Sgshapiro } 422571345Sgshapiro if (vp != NULL) 422690792Sgshapiro sm_free(vp); /* XXX */ 422764562Sgshapiro } 422864562Sgshapiro return result; 422938032Speter} 423038032Speter 423138032Speter/* 423264562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 423364562Sgshapiro** 423464562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 423566494Sgshapiro** secret, and PID so we don't have multiple connections open to 423666494Sgshapiro** the same server for different maps. Need a separate connection 423766494Sgshapiro** per PID since a parent process may close the map before the 423866494Sgshapiro** child is done with it. 423964562Sgshapiro** 424064562Sgshapiro** Parameters: 424164562Sgshapiro** lmap -- LDAP map information 424264562Sgshapiro** 424364562Sgshapiro** Returns: 424464562Sgshapiro** Symbol table entry for the LDAP connection. 424538032Speter*/ 424638032Speter 424764562Sgshapirostatic STAB * 424864562Sgshapiroldapmap_findconn(lmap) 424990792Sgshapiro SM_LDAP_STRUCT *lmap; 425038032Speter{ 425194334Sgshapiro char *format; 425264562Sgshapiro char *nbuf; 4253132943Sgshapiro char *id; 425490792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 425538032Speter 4256132943Sgshapiro if (lmap->ldap_host != NULL) 4257132943Sgshapiro id = lmap->ldap_host; 4258132943Sgshapiro else if (lmap->ldap_uri != NULL) 4259132943Sgshapiro id = lmap->ldap_uri; 4260132943Sgshapiro else 4261132943Sgshapiro id = "localhost"; 4262132943Sgshapiro 426394334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 426494334Sgshapiro nbuf = sm_stringf_x(format, 4265132943Sgshapiro id, 426690792Sgshapiro CONDELSE, 426790792Sgshapiro lmap->ldap_port, 426890792Sgshapiro CONDELSE, 426994334Sgshapiro lmap->ldap_version, 427094334Sgshapiro CONDELSE, 427190792Sgshapiro (lmap->ldap_binddn == NULL ? "" 427290792Sgshapiro : lmap->ldap_binddn), 427390792Sgshapiro CONDELSE, 427490792Sgshapiro (lmap->ldap_secret == NULL ? "" 427590792Sgshapiro : lmap->ldap_secret), 427690792Sgshapiro (int) CurrentPid); 427790792Sgshapiro SM_TRY 427890792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 427990792Sgshapiro SM_FINALLY 428090792Sgshapiro sm_free(nbuf); 428190792Sgshapiro SM_END_TRY 428264562Sgshapiro return s; 428364562Sgshapiro} 428438032Speter/* 428564562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 428664562Sgshapiro*/ 428738032Speter 428890792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 428964562Sgshapiro{ 429064562Sgshapiro { "none", LDAP_AUTH_NONE }, 429164562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 429264562Sgshapiro# ifdef LDAP_AUTH_KRBV4 429364562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 4294363466Sgshapiro# endif 429564562Sgshapiro { NULL, 0 } 429664562Sgshapiro}; 429738032Speter 429890792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 429964562Sgshapiro{ 430064562Sgshapiro { "never", LDAP_DEREF_NEVER }, 430164562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 430264562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 430364562Sgshapiro { "find", LDAP_DEREF_FINDING }, 430464562Sgshapiro { NULL, 0 } 430564562Sgshapiro}; 430638032Speter 430790792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 430864562Sgshapiro{ 430964562Sgshapiro { "base", LDAP_SCOPE_BASE }, 431064562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 431164562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 431264562Sgshapiro { NULL, 0 } 431364562Sgshapiro}; 431438032Speter 431564562Sgshapirobool 431664562Sgshapiroldapmap_parseargs(map, args) 431764562Sgshapiro MAP *map; 431864562Sgshapiro char *args; 431964562Sgshapiro{ 432090792Sgshapiro bool secretread = true; 4321132943Sgshapiro bool attrssetup = false; 432264562Sgshapiro int i; 432364562Sgshapiro register char *p = args; 432490792Sgshapiro SM_LDAP_STRUCT *lmap; 432564562Sgshapiro struct lamvalues *lam; 432664562Sgshapiro struct ladvalues *lad; 432764562Sgshapiro struct lssvalues *lss; 432890792Sgshapiro char ldapfilt[MAXLINE]; 432964562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 433064562Sgshapiro 433164562Sgshapiro /* Get ldap struct pointer from map */ 433290792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 433364562Sgshapiro 433464562Sgshapiro /* Check if setting the initial LDAP defaults */ 433564562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 433664562Sgshapiro { 433790792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 4338168515Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof(*lmap)); 433964562Sgshapiro if (LDAPDefaults == NULL) 434090792Sgshapiro sm_ldap_clear(lmap); 434164562Sgshapiro else 434264562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 434364562Sgshapiro } 434464562Sgshapiro 434564562Sgshapiro /* there is no check whether there is really an argument */ 434664562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 434764562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 434890792Sgshapiro 434990792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 435090792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 435190792Sgshapiro { 435290792Sgshapiro /* Comma separate if used as an alias file */ 435390792Sgshapiro map->map_coldelim = ','; 435490792Sgshapiro if (*args == '\0') 435590792Sgshapiro { 435690792Sgshapiro int n; 435790792Sgshapiro char *lc; 435890792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 435990792Sgshapiro char lcbuf[MAXLINE]; 436090792Sgshapiro 436190792Sgshapiro /* Get $j */ 4362168515Sgshapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope); 436390792Sgshapiro if (jbuf[0] == '\0') 436490792Sgshapiro { 436590792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 4366168515Sgshapiro sizeof(jbuf)); 436790792Sgshapiro } 436890792Sgshapiro 436990792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 437090792Sgshapiro if (lc == NULL) 437190792Sgshapiro lc = ""; 437290792Sgshapiro else 437390792Sgshapiro { 4374168515Sgshapiro expand(lc, lcbuf, sizeof(lcbuf), CurEnv); 437590792Sgshapiro lc = lcbuf; 437690792Sgshapiro } 437790792Sgshapiro 4378168515Sgshapiro n = sm_snprintf(ldapfilt, sizeof(ldapfilt), 437990792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 438090792Sgshapiro lc, jbuf); 4381168515Sgshapiro if (n >= sizeof(ldapfilt)) 438290792Sgshapiro { 438390792Sgshapiro syserr("%s: Default LDAP string too long", 438490792Sgshapiro map->map_mname); 438590792Sgshapiro return false; 438690792Sgshapiro } 438790792Sgshapiro 438890792Sgshapiro /* default args for an alias LDAP entry */ 438990792Sgshapiro lmap->ldap_filter = ldapfilt; 4390132943Sgshapiro lmap->ldap_attr[0] = "objectClass"; 4391132943Sgshapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 4392132943Sgshapiro lmap->ldap_attr_needobjclass[0] = NULL; 4393132943Sgshapiro lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 4394132943Sgshapiro lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 4395132943Sgshapiro lmap->ldap_attr_needobjclass[1] = NULL; 4396132943Sgshapiro lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 4397132943Sgshapiro lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 4398132943Sgshapiro lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 4399132943Sgshapiro lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 4400132943Sgshapiro lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 4401132943Sgshapiro lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 4402132943Sgshapiro lmap->ldap_attr[4] = NULL; 4403132943Sgshapiro lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 4404132943Sgshapiro lmap->ldap_attr_needobjclass[4] = NULL; 4405132943Sgshapiro attrssetup = true; 440690792Sgshapiro } 440790792Sgshapiro } 440890792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 440990792Sgshapiro { 441090792Sgshapiro /* Space separate if used as a file class file */ 441190792Sgshapiro map->map_coldelim = ' '; 441290792Sgshapiro } 441390792Sgshapiro 4414363466Sgshapiro# if LDAP_NETWORK_TIMEOUT 4415363466Sgshapiro if (0 == lmap->ldap_networktmo) 4416363466Sgshapiro lmap->ldap_networktmo = (LDAP_NETWORK_TIMEOUT > 1) 4417363466Sgshapiro ? LDAP_NETWORK_TIMEOUT : 60; 4418363466Sgshapiro# endif 4419203004Sgshapiro 442038032Speter for (;;) 442138032Speter { 4422363466Sgshapiro while (SM_ISSPACE(*p)) 442338032Speter p++; 442438032Speter if (*p != '-') 442538032Speter break; 442638032Speter switch (*++p) 442738032Speter { 4428173340Sgshapiro case 'A': 4429173340Sgshapiro map->map_mflags |= MF_APPEND; 443038032Speter break; 443138032Speter 4432173340Sgshapiro case 'a': 4433173340Sgshapiro map->map_app = ++p; 443438032Speter break; 443538032Speter 4436173340Sgshapiro case 'D': 4437173340Sgshapiro map->map_mflags |= MF_DEFER; 443838032Speter break; 443938032Speter 444038032Speter case 'f': 444138032Speter map->map_mflags |= MF_NOFOLDCASE; 444238032Speter break; 444338032Speter 444438032Speter case 'm': 444538032Speter map->map_mflags |= MF_MATCHONLY; 444638032Speter break; 444738032Speter 4448173340Sgshapiro case 'N': 4449173340Sgshapiro map->map_mflags |= MF_INCLNULL; 4450173340Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 445138032Speter break; 445238032Speter 4453173340Sgshapiro case 'O': 4454173340Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 4455173340Sgshapiro break; 4456173340Sgshapiro 4457173340Sgshapiro case 'o': 4458173340Sgshapiro map->map_mflags |= MF_OPTIONAL; 4459173340Sgshapiro break; 4460173340Sgshapiro 446138032Speter case 'q': 446238032Speter map->map_mflags |= MF_KEEPQUOTES; 446338032Speter break; 446438032Speter 4465173340Sgshapiro case 'S': 4466173340Sgshapiro map->map_spacesub = *++p; 446738032Speter break; 446838032Speter 446938032Speter case 'T': 447038032Speter map->map_tapp = ++p; 447138032Speter break; 447238032Speter 447364562Sgshapiro case 't': 447464562Sgshapiro map->map_mflags |= MF_NODEFER; 447564562Sgshapiro break; 447664562Sgshapiro 447764562Sgshapiro case 'z': 447864562Sgshapiro if (*++p != '\\') 447964562Sgshapiro map->map_coldelim = *p; 448064562Sgshapiro else 448164562Sgshapiro { 448264562Sgshapiro switch (*++p) 448364562Sgshapiro { 448464562Sgshapiro case 'n': 448564562Sgshapiro map->map_coldelim = '\n'; 448664562Sgshapiro break; 448764562Sgshapiro 448864562Sgshapiro case 't': 448964562Sgshapiro map->map_coldelim = '\t'; 449064562Sgshapiro break; 449164562Sgshapiro 449264562Sgshapiro default: 449364562Sgshapiro map->map_coldelim = '\\'; 449464562Sgshapiro } 449564562Sgshapiro } 449664562Sgshapiro break; 449764562Sgshapiro 449864562Sgshapiro /* Start of ldapmap specific args */ 4499173340Sgshapiro case '1': 4500173340Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 4501173340Sgshapiro break; 450290792Sgshapiro 4503173340Sgshapiro# if _FFR_LDAP_SINGLEDN 4504173340Sgshapiro case '2': 4505173340Sgshapiro map->map_mflags |= MF_SINGLEDN; 4506173340Sgshapiro break; 4507173340Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 450890792Sgshapiro 4509173340Sgshapiro case 'b': /* search base */ 4510173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4511173340Sgshapiro continue; 4512173340Sgshapiro lmap->ldap_base = p; 4513173340Sgshapiro break; 4514173340Sgshapiro 4515363466Sgshapiro# if LDAP_NETWORK_TIMEOUT 4516173340Sgshapiro case 'c': /* network (connect) timeout */ 4517173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4518173340Sgshapiro continue; 4519203004Sgshapiro lmap->ldap_networktmo = atoi(p); 4520173340Sgshapiro break; 4521363466Sgshapiro# endif /* LDAP_NETWORK_TIMEOUT */ 4522173340Sgshapiro 4523173340Sgshapiro case 'd': /* Dn to bind to server as */ 4524173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4525173340Sgshapiro continue; 4526173340Sgshapiro lmap->ldap_binddn = p; 4527173340Sgshapiro break; 4528173340Sgshapiro 4529173340Sgshapiro case 'H': /* Use LDAP URI */ 4530173340Sgshapiro# if !USE_LDAP_INIT 4531173340Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 4532173340Sgshapiro map->map_mname); 4533173340Sgshapiro return false; 4534173340Sgshapiro# else /* !USE_LDAP_INIT */ 4535173340Sgshapiro if (lmap->ldap_host != NULL) 4536173340Sgshapiro { 4537173340Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 4538173340Sgshapiro map->map_mname); 4539173340Sgshapiro return false; 454090792Sgshapiro } 4541173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4542173340Sgshapiro continue; 4543173340Sgshapiro lmap->ldap_uri = p; 454490792Sgshapiro break; 4545173340Sgshapiro# endif /* !USE_LDAP_INIT */ 454690792Sgshapiro 4547173340Sgshapiro case 'h': /* ldap host */ 4548173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4549173340Sgshapiro continue; 4550173340Sgshapiro if (lmap->ldap_uri != NULL) 4551173340Sgshapiro { 4552173340Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 4553173340Sgshapiro map->map_mname); 4554173340Sgshapiro return false; 4555173340Sgshapiro } 4556173340Sgshapiro lmap->ldap_host = p; 4557173340Sgshapiro break; 4558173340Sgshapiro 4559173340Sgshapiro case 'K': 4560173340Sgshapiro lmap->ldap_multi_args = true; 4561173340Sgshapiro break; 4562173340Sgshapiro 456338032Speter case 'k': /* search field */ 456438032Speter while (isascii(*++p) && isspace(*p)) 456538032Speter continue; 456664562Sgshapiro lmap->ldap_filter = p; 456738032Speter break; 456838032Speter 4569173340Sgshapiro case 'l': /* time limit */ 457038032Speter while (isascii(*++p) && isspace(*p)) 457138032Speter continue; 4572173340Sgshapiro lmap->ldap_timelimit = atoi(p); 4573173340Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 457438032Speter break; 457538032Speter 4576173340Sgshapiro case 'M': /* Method for binding */ 4577173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4578173340Sgshapiro continue; 4579173340Sgshapiro 4580173340Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 4581173340Sgshapiro p += 10; 4582173340Sgshapiro 4583173340Sgshapiro for (lam = LDAPAuthMethods; 4584173340Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 4585173340Sgshapiro { 4586173340Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 4587173340Sgshapiro strlen(lam->lam_name)) == 0) 4588173340Sgshapiro break; 4589173340Sgshapiro } 4590173340Sgshapiro if (lam->lam_name != NULL) 4591173340Sgshapiro lmap->ldap_method = lam->lam_code; 4592173340Sgshapiro else 4593173340Sgshapiro { 4594173340Sgshapiro /* bad config line */ 4595173340Sgshapiro if (!bitset(MCF_OPTFILE, 4596173340Sgshapiro map->map_class->map_cflags)) 4597173340Sgshapiro { 4598173340Sgshapiro char *ptr; 4599173340Sgshapiro 4600173340Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 4601173340Sgshapiro *ptr = '\0'; 4602173340Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 4603173340Sgshapiro p, map->map_mname); 4604173340Sgshapiro if (ptr != NULL) 4605173340Sgshapiro *ptr = ' '; 4606173340Sgshapiro return false; 4607173340Sgshapiro } 4608173340Sgshapiro } 460964562Sgshapiro break; 461064562Sgshapiro 4611173340Sgshapiro case 'n': /* retrieve attribute names only */ 4612173340Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 4613157001Sgshapiro break; 4614157001Sgshapiro 4615173340Sgshapiro /* 4616173340Sgshapiro ** This is a string that is dependent on the 4617173340Sgshapiro ** method used defined by 'M'. 4618173340Sgshapiro */ 4619173340Sgshapiro 4620173340Sgshapiro case 'P': /* Secret password for binding */ 4621173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4622173340Sgshapiro continue; 4623173340Sgshapiro lmap->ldap_secret = p; 4624173340Sgshapiro secretread = false; 4625173340Sgshapiro break; 4626173340Sgshapiro 4627173340Sgshapiro case 'p': /* ldap port */ 4628173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4629173340Sgshapiro continue; 4630173340Sgshapiro lmap->ldap_port = atoi(p); 4631173340Sgshapiro break; 4632173340Sgshapiro 463338032Speter /* args stolen from ldapsearch.c */ 463438032Speter case 'R': /* don't auto chase referrals */ 463564562Sgshapiro# ifdef LDAP_REFERRALS 463638032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 4637363466Sgshapiro# else 463890792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 463964562Sgshapiro# endif /* LDAP_REFERRALS */ 464038032Speter break; 464138032Speter 464264562Sgshapiro case 'r': /* alias dereferencing */ 464364562Sgshapiro while (isascii(*++p) && isspace(*p)) 464464562Sgshapiro continue; 464564562Sgshapiro 464690792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 464764562Sgshapiro p += 11; 464864562Sgshapiro 464964562Sgshapiro for (lad = LDAPAliasDereference; 465064562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 465138032Speter { 465290792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 465390792Sgshapiro strlen(lad->lad_name)) == 0) 465464562Sgshapiro break; 465538032Speter } 465664562Sgshapiro if (lad->lad_name != NULL) 465764562Sgshapiro lmap->ldap_deref = lad->lad_code; 465864562Sgshapiro else 465938032Speter { 466064562Sgshapiro /* bad config line */ 466164562Sgshapiro if (!bitset(MCF_OPTFILE, 466264562Sgshapiro map->map_class->map_cflags)) 466364562Sgshapiro { 466464562Sgshapiro char *ptr; 466564562Sgshapiro 466664562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 466764562Sgshapiro *ptr = '\0'; 466873188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 466964562Sgshapiro p, map->map_mname); 467064562Sgshapiro if (ptr != NULL) 467164562Sgshapiro *ptr = ' '; 467290792Sgshapiro return false; 467364562Sgshapiro } 467438032Speter } 467564562Sgshapiro break; 467664562Sgshapiro 467764562Sgshapiro case 's': /* search scope */ 467864562Sgshapiro while (isascii(*++p) && isspace(*p)) 467964562Sgshapiro continue; 468064562Sgshapiro 468190792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 468264562Sgshapiro p += 11; 468364562Sgshapiro 468464562Sgshapiro for (lss = LDAPSearchScope; 468564562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 468638032Speter { 468790792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 468890792Sgshapiro strlen(lss->lss_name)) == 0) 468964562Sgshapiro break; 469038032Speter } 469164562Sgshapiro if (lss->lss_name != NULL) 469264562Sgshapiro lmap->ldap_scope = lss->lss_code; 469338032Speter else 469464562Sgshapiro { 469564562Sgshapiro /* bad config line */ 469664562Sgshapiro if (!bitset(MCF_OPTFILE, 469764562Sgshapiro map->map_class->map_cflags)) 469838032Speter { 469938032Speter char *ptr; 470038032Speter 470138032Speter if ((ptr = strchr(p, ' ')) != NULL) 470238032Speter *ptr = '\0'; 470373188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 470438032Speter p, map->map_mname); 470538032Speter if (ptr != NULL) 470638032Speter *ptr = ' '; 470790792Sgshapiro return false; 470838032Speter } 470938032Speter } 471038032Speter break; 471138032Speter 4712173340Sgshapiro case 'V': 4713173340Sgshapiro if (*++p != '\\') 4714173340Sgshapiro lmap->ldap_attrsep = *p; 471564562Sgshapiro else 471664562Sgshapiro { 4717173340Sgshapiro switch (*++p) 471864562Sgshapiro { 4719173340Sgshapiro case 'n': 4720173340Sgshapiro lmap->ldap_attrsep = '\n'; 4721173340Sgshapiro break; 472264562Sgshapiro 4723173340Sgshapiro case 't': 4724173340Sgshapiro lmap->ldap_attrsep = '\t'; 4725173340Sgshapiro break; 4726173340Sgshapiro 4727173340Sgshapiro default: 4728173340Sgshapiro lmap->ldap_attrsep = '\\'; 472964562Sgshapiro } 473064562Sgshapiro } 473164562Sgshapiro break; 473264562Sgshapiro 4733173340Sgshapiro case 'v': /* attr to return */ 473494334Sgshapiro while (isascii(*++p) && isspace(*p)) 473594334Sgshapiro continue; 4736173340Sgshapiro lmap->ldap_attr[0] = p; 4737173340Sgshapiro lmap->ldap_attr[1] = NULL; 473894334Sgshapiro break; 473994334Sgshapiro 474094334Sgshapiro case 'w': 474194334Sgshapiro /* -w should be for passwd, -P should be for version */ 474294334Sgshapiro while (isascii(*++p) && isspace(*p)) 474394334Sgshapiro continue; 474494334Sgshapiro lmap->ldap_version = atoi(p); 4745132943Sgshapiro# ifdef LDAP_VERSION_MAX 474694334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 474794334Sgshapiro { 474894334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 474994334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 475094334Sgshapiro map->map_mname); 475194334Sgshapiro return false; 475294334Sgshapiro } 4753132943Sgshapiro# endif /* LDAP_VERSION_MAX */ 4754132943Sgshapiro# ifdef LDAP_VERSION_MIN 475594334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 475694334Sgshapiro { 475794334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 475894334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 475994334Sgshapiro map->map_mname); 476094334Sgshapiro return false; 476194334Sgshapiro } 4762132943Sgshapiro# endif /* LDAP_VERSION_MIN */ 476394334Sgshapiro break; 476494334Sgshapiro 4765363466Sgshapiro case 'x': 4766363466Sgshapiro# if _FFR_SM_LDAP_DBG 4767363466Sgshapiro while (isascii(*++p) && isspace(*p)) 4768363466Sgshapiro continue; 4769363466Sgshapiro lmap->ldap_debug = atoi(p); 4770363466Sgshapiro# endif 4771363466Sgshapiro break; 4772363466Sgshapiro 4773173340Sgshapiro case 'Z': 4774173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4775173340Sgshapiro continue; 4776173340Sgshapiro lmap->ldap_sizelimit = atoi(p); 4777168515Sgshapiro break; 4778168515Sgshapiro 477964562Sgshapiro default: 478064562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 478164562Sgshapiro break; 478238032Speter } 478338032Speter 478464562Sgshapiro /* need to account for quoted strings here */ 4785363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 478638032Speter { 478738032Speter if (*p == '"') 478838032Speter { 478938032Speter while (*++p != '"' && *p != '\0') 479038032Speter continue; 479138032Speter if (*p != '\0') 479238032Speter p++; 479338032Speter } 479438032Speter else 479538032Speter p++; 479638032Speter } 479738032Speter 479838032Speter if (*p != '\0') 479938032Speter *p++ = '\0'; 480038032Speter } 480138032Speter 480238032Speter if (map->map_app != NULL) 480364562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 480438032Speter if (map->map_tapp != NULL) 480564562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 480638032Speter 480738032Speter /* 480842575Speter ** We need to swallow up all the stuff into a struct 480942575Speter ** and dump it into map->map_dbptr1 481038032Speter */ 481138032Speter 4812132943Sgshapiro if (lmap->ldap_host != NULL && 481364562Sgshapiro (LDAPDefaults == NULL || 481464562Sgshapiro LDAPDefaults == lmap || 4815132943Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 4816132943Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 4817132943Sgshapiro map->map_domain = lmap->ldap_host; 481864562Sgshapiro 4819132943Sgshapiro if (lmap->ldap_uri != NULL && 4820132943Sgshapiro (LDAPDefaults == NULL || 4821132943Sgshapiro LDAPDefaults == lmap || 4822132943Sgshapiro LDAPDefaults->ldap_uri != lmap->ldap_uri)) 4823132943Sgshapiro lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 4824132943Sgshapiro map->map_domain = lmap->ldap_uri; 4825132943Sgshapiro 482664562Sgshapiro if (lmap->ldap_binddn != NULL && 482764562Sgshapiro (LDAPDefaults == NULL || 482864562Sgshapiro LDAPDefaults == lmap || 482964562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 483064562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 483164562Sgshapiro 483264562Sgshapiro if (lmap->ldap_secret != NULL && 483364562Sgshapiro (LDAPDefaults == NULL || 483464562Sgshapiro LDAPDefaults == lmap || 483564562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 483638032Speter { 483790792Sgshapiro SM_FILE_T *sfd; 483864562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 483938032Speter 484064562Sgshapiro if (DontLockReadFiles) 484164562Sgshapiro sff |= SFF_NOLOCK; 484238032Speter 484364562Sgshapiro /* need to use method to map secret to passwd string */ 484464562Sgshapiro switch (lmap->ldap_method) 484564562Sgshapiro { 484664562Sgshapiro case LDAP_AUTH_NONE: 484764562Sgshapiro /* Do nothing */ 484864562Sgshapiro break; 484938032Speter 485064562Sgshapiro case LDAP_AUTH_SIMPLE: 485138032Speter 485264562Sgshapiro /* 485364562Sgshapiro ** Secret is the name of a file with 485464562Sgshapiro ** the first line as the password. 485564562Sgshapiro */ 485664562Sgshapiro 485764562Sgshapiro /* Already read in the secret? */ 485864562Sgshapiro if (secretread) 485964562Sgshapiro break; 486064562Sgshapiro 486164562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 486264562Sgshapiro O_RDONLY, 0, sff); 486364562Sgshapiro if (sfd == NULL) 486464562Sgshapiro { 486564562Sgshapiro syserr("LDAP map: cannot open secret %s", 486664562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 486790792Sgshapiro return false; 486864562Sgshapiro } 4869168515Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof(m_tmp), 487066494Sgshapiro sfd, TimeOuts.to_fileopen, 487166494Sgshapiro "ldapmap_parseargs"); 487290792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 487398121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 487498121Sgshapiro { 487598121Sgshapiro syserr("LDAP map: secret in %s too long", 487698121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 487798121Sgshapiro return false; 487898121Sgshapiro } 487964562Sgshapiro if (lmap->ldap_secret != NULL && 488064562Sgshapiro strlen(m_tmp) > 0) 488164562Sgshapiro { 488264562Sgshapiro /* chomp newline */ 488364562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 488464562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 488564562Sgshapiro 488664562Sgshapiro lmap->ldap_secret = m_tmp; 488764562Sgshapiro } 488864562Sgshapiro break; 488964562Sgshapiro 489064562Sgshapiro# ifdef LDAP_AUTH_KRBV4 489164562Sgshapiro case LDAP_AUTH_KRBV4: 489264562Sgshapiro 489364562Sgshapiro /* 489464562Sgshapiro ** Secret is where the ticket file is 489564562Sgshapiro ** stashed 489664562Sgshapiro */ 489764562Sgshapiro 4898168515Sgshapiro (void) sm_snprintf(m_tmp, sizeof(m_tmp), 489990792Sgshapiro "KRBTKFILE=%s", 490090792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 490164562Sgshapiro lmap->ldap_secret = m_tmp; 490264562Sgshapiro break; 490364562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 490464562Sgshapiro 490564562Sgshapiro default: /* Should NEVER get here */ 490664562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 490790792Sgshapiro return false; 490890792Sgshapiro /* NOTREACHED */ 490964562Sgshapiro break; 491064562Sgshapiro } 491138032Speter } 491238032Speter 491364562Sgshapiro if (lmap->ldap_secret != NULL && 491464562Sgshapiro (LDAPDefaults == NULL || 491564562Sgshapiro LDAPDefaults == lmap || 491664562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 491764562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 491838032Speter 491964562Sgshapiro if (lmap->ldap_base != NULL && 492064562Sgshapiro (LDAPDefaults == NULL || 492164562Sgshapiro LDAPDefaults == lmap || 492264562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 492364562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 492464562Sgshapiro 492564562Sgshapiro /* 492664562Sgshapiro ** Save the server from extra work. If request is for a single 492764562Sgshapiro ** match, tell the server to only return enough records to 492864562Sgshapiro ** determine if there is a single match or not. This can not 492964562Sgshapiro ** be one since the server would only return one and we wouldn't 493064562Sgshapiro ** know if there were others available. 493164562Sgshapiro */ 493264562Sgshapiro 493364562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 493464562Sgshapiro lmap->ldap_sizelimit = 2; 493564562Sgshapiro 493664562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 493764562Sgshapiro if (lmap == LDAPDefaults) 493890792Sgshapiro return true; 493964562Sgshapiro 494064562Sgshapiro if (lmap->ldap_filter != NULL) 494164562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 494238032Speter else 494338032Speter { 494438032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 494538032Speter { 494638032Speter syserr("No filter given in map %s", map->map_mname); 494790792Sgshapiro return false; 494838032Speter } 494938032Speter } 495064562Sgshapiro 4951132943Sgshapiro if (!attrssetup && lmap->ldap_attr[0] != NULL) 495238032Speter { 495390792Sgshapiro bool recurse = false; 495494334Sgshapiro bool normalseen = false; 495590792Sgshapiro 495664562Sgshapiro i = 0; 495764562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 495864562Sgshapiro lmap->ldap_attr[0] = NULL; 495964562Sgshapiro 496094334Sgshapiro /* Prime the attr list with the objectClass attribute */ 496194334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 496294334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 496394334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 496494334Sgshapiro i++; 496594334Sgshapiro 496664562Sgshapiro while (p != NULL) 496738032Speter { 496864562Sgshapiro char *v; 496964562Sgshapiro 4970363466Sgshapiro while (SM_ISSPACE(*p)) 497164562Sgshapiro p++; 497264562Sgshapiro if (*p == '\0') 497364562Sgshapiro break; 497464562Sgshapiro v = p; 497564562Sgshapiro p = strchr(v, ','); 497664562Sgshapiro if (p != NULL) 497764562Sgshapiro *p++ = '\0'; 497864562Sgshapiro 497971345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 498064562Sgshapiro { 498164562Sgshapiro syserr("Too many return attributes in %s (max %d)", 498264562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 498390792Sgshapiro return false; 498464562Sgshapiro } 498564562Sgshapiro if (*v != '\0') 498690792Sgshapiro { 498794334Sgshapiro int j; 498894334Sgshapiro int use; 498990792Sgshapiro char *type; 499094334Sgshapiro char *needobjclass; 499190792Sgshapiro 499290792Sgshapiro type = strchr(v, ':'); 499390792Sgshapiro if (type != NULL) 499494334Sgshapiro { 499590792Sgshapiro *type++ = '\0'; 499694334Sgshapiro needobjclass = strchr(type, ':'); 499794334Sgshapiro if (needobjclass != NULL) 499894334Sgshapiro *needobjclass++ = '\0'; 499994334Sgshapiro } 500094334Sgshapiro else 500194334Sgshapiro { 500294334Sgshapiro needobjclass = NULL; 500394334Sgshapiro } 500490792Sgshapiro 500594334Sgshapiro use = i; 500690792Sgshapiro 500794334Sgshapiro /* allow override on "objectClass" type */ 500894334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 500994334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 501090792Sgshapiro { 501194334Sgshapiro use = 0; 501294334Sgshapiro } 501394334Sgshapiro else 501494334Sgshapiro { 501594334Sgshapiro /* 501694334Sgshapiro ** Don't add something to attribute 501794334Sgshapiro ** list twice. 501894334Sgshapiro */ 501994334Sgshapiro 502094334Sgshapiro for (j = 1; j < i; j++) 502190792Sgshapiro { 502294334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 502394334Sgshapiro { 502494334Sgshapiro syserr("Duplicate attribute (%s) in %s", 502594334Sgshapiro v, map->map_mname); 502694334Sgshapiro return false; 502794334Sgshapiro } 502890792Sgshapiro } 502994334Sgshapiro 503094334Sgshapiro lmap->ldap_attr[use] = newstr(v); 503194334Sgshapiro if (needobjclass != NULL && 503294334Sgshapiro *needobjclass != '\0' && 503394334Sgshapiro *needobjclass != '*') 503490792Sgshapiro { 503594334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 503694334Sgshapiro } 503794334Sgshapiro else 503894334Sgshapiro { 503994334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 504094334Sgshapiro } 504194334Sgshapiro 504294334Sgshapiro } 504394334Sgshapiro 504494334Sgshapiro if (type != NULL && *type != '\0') 504594334Sgshapiro { 504694334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 504794334Sgshapiro { 504890792Sgshapiro recurse = true; 504994334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 505090792Sgshapiro } 505190792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 505290792Sgshapiro { 505390792Sgshapiro recurse = true; 505494334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 505590792Sgshapiro } 505690792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 505790792Sgshapiro { 505890792Sgshapiro recurse = true; 505994334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 506090792Sgshapiro } 506194334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 506290792Sgshapiro { 506394334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 506494334Sgshapiro normalseen = true; 506590792Sgshapiro } 506690792Sgshapiro else 506790792Sgshapiro { 506890792Sgshapiro syserr("Unknown attribute type (%s) in %s", 506990792Sgshapiro type, map->map_mname); 507090792Sgshapiro return false; 507190792Sgshapiro } 507290792Sgshapiro } 507390792Sgshapiro else 507494334Sgshapiro { 507594334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 507694334Sgshapiro normalseen = true; 507794334Sgshapiro } 507890792Sgshapiro i++; 507990792Sgshapiro } 508038032Speter } 508164562Sgshapiro lmap->ldap_attr[i] = NULL; 5082141858Sgshapiro 5083141858Sgshapiro /* Set in case needed in future code */ 5084132943Sgshapiro attrssetup = true; 5085141858Sgshapiro 508694334Sgshapiro if (recurse && !normalseen) 508790792Sgshapiro { 508894334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 508990792Sgshapiro map->map_mname); 509090792Sgshapiro return false; 509190792Sgshapiro } 509290792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 509390792Sgshapiro { 509490792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 509590792Sgshapiro map->map_mname); 509690792Sgshapiro return false; 509790792Sgshapiro } 509838032Speter } 509938032Speter map->map_db1 = (ARBPTR_T) lmap; 510090792Sgshapiro return true; 510138032Speter} 510238032Speter 510364562Sgshapiro/* 510464562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 510564562Sgshapiro** 510664562Sgshapiro** Parameters: 510764562Sgshapiro** spec -- map argument string from LDAPDefaults option 510864562Sgshapiro** 510964562Sgshapiro** Returns: 511064562Sgshapiro** None. 511164562Sgshapiro*/ 511264562Sgshapiro 511364562Sgshapirovoid 511464562Sgshapiroldapmap_set_defaults(spec) 511564562Sgshapiro char *spec; 511664562Sgshapiro{ 511773188Sgshapiro STAB *class; 511864562Sgshapiro MAP map; 511964562Sgshapiro 512064562Sgshapiro /* Allocate and set the default values */ 512164562Sgshapiro if (LDAPDefaults == NULL) 5122168515Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof(*LDAPDefaults)); 512390792Sgshapiro sm_ldap_clear(LDAPDefaults); 512464562Sgshapiro 5125168515Sgshapiro memset(&map, '\0', sizeof(map)); 512673188Sgshapiro 512773188Sgshapiro /* look up the class */ 512873188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 512973188Sgshapiro if (class == NULL) 513073188Sgshapiro { 513173188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 513273188Sgshapiro return; 513373188Sgshapiro } 513473188Sgshapiro map.map_class = &class->s_mapclass; 513564562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 513673188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 513764562Sgshapiro 513864562Sgshapiro (void) ldapmap_parseargs(&map, spec); 513964562Sgshapiro 514064562Sgshapiro /* These should never be set in LDAPDefaults */ 514164562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 514264562Sgshapiro map.map_spacesub != SpaceSub || 514364562Sgshapiro map.map_app != NULL || 514464562Sgshapiro map.map_tapp != NULL) 514564562Sgshapiro { 514664562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 5147363466Sgshapiro SM_FREE(map.map_app); 5148363466Sgshapiro SM_FREE(map.map_tapp); 514964562Sgshapiro } 515064562Sgshapiro 515164562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 515264562Sgshapiro { 515364562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 515494334Sgshapiro 515564562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 515664562Sgshapiro LDAPDefaults->ldap_filter = NULL; 515764562Sgshapiro } 515864562Sgshapiro 515964562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 516064562Sgshapiro { 516164562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 516264562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 516364562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 516464562Sgshapiro } 516564562Sgshapiro} 516664562Sgshapiro#endif /* LDAPMAP */ 516790792Sgshapiro/* 516864562Sgshapiro** PH map 516964562Sgshapiro*/ 517064562Sgshapiro 517190792Sgshapiro#if PH_MAP 517264562Sgshapiro 517364562Sgshapiro/* 517464562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 517564562Sgshapiro** This code is intended to replace the so-called "ph mailer". 5176168515Sgshapiro** Contributed by Mark D. Roth. Contact him for support. 517764562Sgshapiro*/ 517864562Sgshapiro 517990792Sgshapiro/* what version of the ph map code we're running */ 5180110560Sgshapirostatic char phmap_id[128]; 518164562Sgshapiro 518290792Sgshapiro/* sendmail version for phmap id string */ 518390792Sgshapiroextern const char Version[]; 518490792Sgshapiro 5185132943Sgshapiro/* assume we're using nph-1.2.x if not specified */ 5186110560Sgshapiro# ifndef NPH_VERSION 5187132943Sgshapiro# define NPH_VERSION 10200 5188110560Sgshapiro# endif 5189110560Sgshapiro 5190110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 5191110560Sgshapiro# if NPH_VERSION < 10200 5192110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 5193110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 5194110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 5195110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 5196110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 5197110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 5198110560Sgshapiro 519964562Sgshapiro/* 520064562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 520164562Sgshapiro*/ 520264562Sgshapiro 520364562Sgshapirobool 520464562Sgshapiroph_map_parseargs(map, args) 520564562Sgshapiro MAP *map; 520664562Sgshapiro char *args; 520764562Sgshapiro{ 520890792Sgshapiro register bool done; 520990792Sgshapiro register char *p = args; 521064562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 521164562Sgshapiro 521290792Sgshapiro /* initialize version string */ 5213168515Sgshapiro (void) sm_snprintf(phmap_id, sizeof(phmap_id), 521490792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 521590792Sgshapiro Version, libphclient_version); 521690792Sgshapiro 5217168515Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof(*pmap)); 521864562Sgshapiro 521964562Sgshapiro /* defaults */ 522064562Sgshapiro pmap->ph_servers = NULL; 522164562Sgshapiro pmap->ph_field_list = NULL; 522290792Sgshapiro pmap->ph = NULL; 522364562Sgshapiro pmap->ph_timeout = 0; 522490792Sgshapiro pmap->ph_fastclose = 0; 522564562Sgshapiro 522664562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 522764562Sgshapiro for (;;) 522864562Sgshapiro { 5229363466Sgshapiro while (SM_ISSPACE(*p)) 523064562Sgshapiro p++; 523164562Sgshapiro if (*p != '-') 523264562Sgshapiro break; 523364562Sgshapiro switch (*++p) 523464562Sgshapiro { 523564562Sgshapiro case 'N': 523664562Sgshapiro map->map_mflags |= MF_INCLNULL; 523764562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 523864562Sgshapiro break; 523964562Sgshapiro 524064562Sgshapiro case 'O': 524164562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 524264562Sgshapiro break; 524364562Sgshapiro 524464562Sgshapiro case 'o': 524564562Sgshapiro map->map_mflags |= MF_OPTIONAL; 524664562Sgshapiro break; 524764562Sgshapiro 524864562Sgshapiro case 'f': 524964562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 525064562Sgshapiro break; 525164562Sgshapiro 525264562Sgshapiro case 'm': 525364562Sgshapiro map->map_mflags |= MF_MATCHONLY; 525464562Sgshapiro break; 525564562Sgshapiro 525664562Sgshapiro case 'A': 525764562Sgshapiro map->map_mflags |= MF_APPEND; 525864562Sgshapiro break; 525964562Sgshapiro 526064562Sgshapiro case 'q': 526164562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 526264562Sgshapiro break; 526364562Sgshapiro 526464562Sgshapiro case 't': 526564562Sgshapiro map->map_mflags |= MF_NODEFER; 526664562Sgshapiro break; 526764562Sgshapiro 526864562Sgshapiro case 'a': 526964562Sgshapiro map->map_app = ++p; 527064562Sgshapiro break; 527164562Sgshapiro 527264562Sgshapiro case 'T': 527364562Sgshapiro map->map_tapp = ++p; 527464562Sgshapiro break; 527564562Sgshapiro 527664562Sgshapiro case 'l': 527764562Sgshapiro while (isascii(*++p) && isspace(*p)) 527864562Sgshapiro continue; 527964562Sgshapiro pmap->ph_timeout = atoi(p); 528064562Sgshapiro break; 528164562Sgshapiro 528264562Sgshapiro case 'S': 528364562Sgshapiro map->map_spacesub = *++p; 528464562Sgshapiro break; 528564562Sgshapiro 528664562Sgshapiro case 'D': 528764562Sgshapiro map->map_mflags |= MF_DEFER; 528864562Sgshapiro break; 528964562Sgshapiro 529064562Sgshapiro case 'h': /* PH server list */ 529164562Sgshapiro while (isascii(*++p) && isspace(*p)) 529264562Sgshapiro continue; 529364562Sgshapiro pmap->ph_servers = p; 529464562Sgshapiro break; 529564562Sgshapiro 529690792Sgshapiro case 'k': /* fields to search for */ 529764562Sgshapiro while (isascii(*++p) && isspace(*p)) 529864562Sgshapiro continue; 529964562Sgshapiro pmap->ph_field_list = p; 530064562Sgshapiro break; 530164562Sgshapiro 530264562Sgshapiro default: 530390792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 530464562Sgshapiro } 530564562Sgshapiro 530664562Sgshapiro /* try to account for quoted strings */ 5307363466Sgshapiro done = SM_ISSPACE(*p); 530864562Sgshapiro while (*p != '\0' && !done) 530964562Sgshapiro { 531064562Sgshapiro if (*p == '"') 531164562Sgshapiro { 531264562Sgshapiro while (*++p != '"' && *p != '\0') 531364562Sgshapiro continue; 531464562Sgshapiro if (*p != '\0') 531564562Sgshapiro p++; 531664562Sgshapiro } 531764562Sgshapiro else 531864562Sgshapiro p++; 5319363466Sgshapiro done = SM_ISSPACE(*p); 532064562Sgshapiro } 532164562Sgshapiro 532264562Sgshapiro if (*p != '\0') 532364562Sgshapiro *p++ = '\0'; 532464562Sgshapiro } 532564562Sgshapiro 532664562Sgshapiro if (map->map_app != NULL) 532764562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 532864562Sgshapiro if (map->map_tapp != NULL) 532964562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 533064562Sgshapiro 533164562Sgshapiro if (pmap->ph_field_list != NULL) 533264562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 533364562Sgshapiro 533464562Sgshapiro if (pmap->ph_servers != NULL) 533564562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 533664562Sgshapiro else 533764562Sgshapiro { 533864562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 533990792Sgshapiro return false; 534064562Sgshapiro } 534164562Sgshapiro 534264562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 534390792Sgshapiro return true; 534464562Sgshapiro} 534564562Sgshapiro 534664562Sgshapiro/* 534764562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 534864562Sgshapiro*/ 534964562Sgshapiro 535090792Sgshapirovoid 535190792Sgshapiroph_map_close(map) 535264562Sgshapiro MAP *map; 535364562Sgshapiro{ 535464562Sgshapiro PH_MAP_STRUCT *pmap; 535564562Sgshapiro 535664562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 535790792Sgshapiro if (tTd(38, 9)) 535894334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 535990792Sgshapiro map->map_mname, pmap->ph_fastclose); 536064562Sgshapiro 536190792Sgshapiro 536290792Sgshapiro if (pmap->ph != NULL) 536364562Sgshapiro { 536490792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 536590792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 536690792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 536764562Sgshapiro } 536890792Sgshapiro 536964562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 537064562Sgshapiro} 537164562Sgshapiro 537264562Sgshapirostatic jmp_buf PHTimeout; 537364562Sgshapiro 537464562Sgshapiro/* ARGSUSED */ 537564562Sgshapirostatic void 537690792Sgshapiroph_timeout(unused) 537790792Sgshapiro int unused; 537864562Sgshapiro{ 537977349Sgshapiro /* 538077349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 538177349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 538277349Sgshapiro ** DOING. 538377349Sgshapiro */ 538477349Sgshapiro 538577349Sgshapiro errno = ETIMEDOUT; 538664562Sgshapiro longjmp(PHTimeout, 1); 538764562Sgshapiro} 538864562Sgshapiro 538990792Sgshapirostatic void 5390110560Sgshapiro#if NPH_VERSION >= 10200 5391110560Sgshapiroph_map_send_debug(appdata, text) 5392110560Sgshapiro void *appdata; 5393110560Sgshapiro#else 539490792Sgshapiroph_map_send_debug(text) 5395110560Sgshapiro#endif 539690792Sgshapiro char *text; 539764562Sgshapiro{ 539890792Sgshapiro if (LogLevel > 9) 539990792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 540090792Sgshapiro "ph_map_send_debug: ==> %s", text); 540190792Sgshapiro if (tTd(38, 20)) 540290792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 540390792Sgshapiro} 540464562Sgshapiro 540590792Sgshapirostatic void 5406110560Sgshapiro#if NPH_VERSION >= 10200 5407110560Sgshapiroph_map_recv_debug(appdata, text) 5408110560Sgshapiro void *appdata; 5409110560Sgshapiro#else 541090792Sgshapiroph_map_recv_debug(text) 5411110560Sgshapiro#endif 541290792Sgshapiro char *text; 541390792Sgshapiro{ 541490792Sgshapiro if (LogLevel > 10) 541590792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 541690792Sgshapiro "ph_map_recv_debug: <== %s", text); 541790792Sgshapiro if (tTd(38, 21)) 541890792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 541964562Sgshapiro} 542064562Sgshapiro 542190792Sgshapiro/* 542264562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 542364562Sgshapiro*/ 542464562Sgshapirobool 542564562Sgshapiroph_map_open(map, mode) 542664562Sgshapiro MAP *map; 542764562Sgshapiro int mode; 542864562Sgshapiro{ 542990792Sgshapiro PH_MAP_STRUCT *pmap; 543090792Sgshapiro register SM_EVENT *ev = NULL; 543164562Sgshapiro int save_errno = 0; 543290792Sgshapiro char *hostlist, *host; 543364562Sgshapiro 543464562Sgshapiro if (tTd(38, 2)) 543590792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 543664562Sgshapiro 543764562Sgshapiro mode &= O_ACCMODE; 543864562Sgshapiro if (mode != O_RDONLY) 543964562Sgshapiro { 544064562Sgshapiro /* issue a pseudo-error message */ 544190792Sgshapiro errno = SM_EMAPCANTWRITE; 544290792Sgshapiro return false; 544364562Sgshapiro } 544464562Sgshapiro 544566494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 544666494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 544766494Sgshapiro { 544866494Sgshapiro if (tTd(9, 1)) 544990792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 545090792Sgshapiro map->map_mname); 545166494Sgshapiro 545266494Sgshapiro /* 545390792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 545490792Sgshapiro ** a temporary failure using the bogus map and 545590792Sgshapiro ** map->map_tapp instead of the default permanent error. 545666494Sgshapiro */ 545766494Sgshapiro 545866494Sgshapiro map->map_mflags &= ~MF_DEFER; 545990792Sgshapiro return false; 546066494Sgshapiro } 546166494Sgshapiro 546264562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 546390792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 546464562Sgshapiro 546590792Sgshapiro /* try each host in the list */ 546664562Sgshapiro hostlist = newstr(pmap->ph_servers); 546790792Sgshapiro for (host = strtok(hostlist, " "); 546890792Sgshapiro host != NULL; 546990792Sgshapiro host = strtok(NULL, " ")) 547064562Sgshapiro { 547190792Sgshapiro /* set timeout */ 547264562Sgshapiro if (pmap->ph_timeout != 0) 547364562Sgshapiro { 547464562Sgshapiro if (setjmp(PHTimeout) != 0) 547564562Sgshapiro { 547664562Sgshapiro ev = NULL; 547764562Sgshapiro if (LogLevel > 1) 547864562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 547964562Sgshapiro "timeout connecting to PH server %.100s", 548090792Sgshapiro host); 548164562Sgshapiro errno = ETIMEDOUT; 548264562Sgshapiro goto ph_map_open_abort; 548364562Sgshapiro } 548490792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 548564562Sgshapiro } 548690792Sgshapiro 548790792Sgshapiro /* open connection to server */ 5488110560Sgshapiro if (ph_open(&(pmap->ph), host, 5489110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 5490110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 5491110560Sgshapiro#if NPH_VERSION >= 10200 5492110560Sgshapiro , NULL 5493110560Sgshapiro#endif 5494110560Sgshapiro ) == 0 5495110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 549664562Sgshapiro { 549764562Sgshapiro if (ev != NULL) 549890792Sgshapiro sm_clrevent(ev); 549990792Sgshapiro sm_free(hostlist); /* XXX */ 550090792Sgshapiro return true; 550164562Sgshapiro } 550290792Sgshapiro 550364562Sgshapiro ph_map_open_abort: 550490792Sgshapiro save_errno = errno; 550564562Sgshapiro if (ev != NULL) 550690792Sgshapiro sm_clrevent(ev); 5507110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 550890792Sgshapiro ph_map_close(map); 550990792Sgshapiro errno = save_errno; 551090792Sgshapiro } 551164562Sgshapiro 551266494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 551364562Sgshapiro { 551466494Sgshapiro if (errno == 0) 551564562Sgshapiro errno = EAGAIN; 551666494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 551766494Sgshapiro map->map_mname); 551864562Sgshapiro } 551966494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 552064562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 552166494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 552266494Sgshapiro map->map_mname); 552390792Sgshapiro sm_free(hostlist); /* XXX */ 552490792Sgshapiro return false; 552564562Sgshapiro} 552664562Sgshapiro 552764562Sgshapiro/* 552864562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 552964562Sgshapiro*/ 553064562Sgshapiro 553164562Sgshapirochar * 553264562Sgshapiroph_map_lookup(map, key, args, pstat) 553364562Sgshapiro MAP *map; 553464562Sgshapiro char *key; 553564562Sgshapiro char **args; 553664562Sgshapiro int *pstat; 553764562Sgshapiro{ 553890792Sgshapiro int i, save_errno = 0; 553990792Sgshapiro register SM_EVENT *ev = NULL; 554064562Sgshapiro PH_MAP_STRUCT *pmap; 554190792Sgshapiro char *value = NULL; 554264562Sgshapiro 554364562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 554464562Sgshapiro 554564562Sgshapiro *pstat = EX_OK; 554664562Sgshapiro 554790792Sgshapiro /* set timeout */ 554864562Sgshapiro if (pmap->ph_timeout != 0) 554964562Sgshapiro { 555064562Sgshapiro if (setjmp(PHTimeout) != 0) 555164562Sgshapiro { 555264562Sgshapiro ev = NULL; 555364562Sgshapiro if (LogLevel > 1) 555464562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 555564562Sgshapiro "timeout during PH lookup of %.100s", 555664562Sgshapiro key); 555764562Sgshapiro errno = ETIMEDOUT; 555864562Sgshapiro *pstat = EX_TEMPFAIL; 555964562Sgshapiro goto ph_map_lookup_abort; 556064562Sgshapiro } 556190792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 556264562Sgshapiro } 556364562Sgshapiro 556490792Sgshapiro /* perform lookup */ 556590792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 556690792Sgshapiro if (i == -1) 556790792Sgshapiro *pstat = EX_TEMPFAIL; 5568110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 556990792Sgshapiro *pstat = EX_UNAVAILABLE; 557064562Sgshapiro 557164562Sgshapiro ph_map_lookup_abort: 557264562Sgshapiro if (ev != NULL) 557390792Sgshapiro sm_clrevent(ev); 557464562Sgshapiro 557564562Sgshapiro /* 557690792Sgshapiro ** Close the connection if the timer popped 557764562Sgshapiro ** or we got a temporary PH error 557864562Sgshapiro */ 557964562Sgshapiro 558064562Sgshapiro if (*pstat == EX_TEMPFAIL) 558190792Sgshapiro { 558290792Sgshapiro save_errno = errno; 5583110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 558490792Sgshapiro ph_map_close(map); 558590792Sgshapiro errno = save_errno; 558690792Sgshapiro } 558764562Sgshapiro 558864562Sgshapiro if (*pstat == EX_OK) 558964562Sgshapiro { 559064562Sgshapiro if (tTd(38,20)) 559190792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 559264562Sgshapiro 559364562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 559490792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 559564562Sgshapiro else 559690792Sgshapiro return map_rewrite(map, value, strlen(value), args); 559764562Sgshapiro } 559864562Sgshapiro 559964562Sgshapiro return NULL; 560064562Sgshapiro} 560164562Sgshapiro#endif /* PH_MAP */ 5602168515Sgshapiro 560390792Sgshapiro/* 560442575Speter** syslog map 560538032Speter*/ 560638032Speter 560738032Speter#define map_prio map_lockfd /* overload field */ 560838032Speter 560938032Speter/* 561042575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 561138032Speter*/ 561238032Speter 561338032Speterbool 561438032Spetersyslog_map_parseargs(map, args) 561538032Speter MAP *map; 561638032Speter char *args; 561738032Speter{ 561838032Speter char *p = args; 561938032Speter char *priority = NULL; 562038032Speter 562164562Sgshapiro /* there is no check whether there is really an argument */ 562264562Sgshapiro while (*p != '\0') 562338032Speter { 5624363466Sgshapiro while (SM_ISSPACE(*p)) 562538032Speter p++; 562638032Speter if (*p != '-') 562738032Speter break; 562864562Sgshapiro ++p; 562964562Sgshapiro if (*p == 'D') 563064562Sgshapiro { 563164562Sgshapiro map->map_mflags |= MF_DEFER; 563264562Sgshapiro ++p; 563364562Sgshapiro } 563464562Sgshapiro else if (*p == 'S') 563564562Sgshapiro { 563664562Sgshapiro map->map_spacesub = *++p; 563764562Sgshapiro if (*p != '\0') 563864562Sgshapiro p++; 563964562Sgshapiro } 564064562Sgshapiro else if (*p == 'L') 564164562Sgshapiro { 5642363466Sgshapiro while (*++p != '\0' && SM_ISSPACE(*p)) 564364562Sgshapiro continue; 564464562Sgshapiro if (*p == '\0') 564564562Sgshapiro break; 564664562Sgshapiro priority = p; 5647363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 564864562Sgshapiro p++; 564964562Sgshapiro if (*p != '\0') 565064562Sgshapiro *p++ = '\0'; 565164562Sgshapiro } 565264562Sgshapiro else 565364562Sgshapiro { 565464562Sgshapiro syserr("Illegal option %c map syslog", *p); 565564562Sgshapiro ++p; 565664562Sgshapiro } 565738032Speter } 565838032Speter 565938032Speter if (priority == NULL) 566038032Speter map->map_prio = LOG_INFO; 566138032Speter else 566238032Speter { 566390792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 566438032Speter priority += 4; 566538032Speter 566638032Speter#ifdef LOG_EMERG 566790792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 566838032Speter map->map_prio = LOG_EMERG; 566938032Speter else 567064562Sgshapiro#endif /* LOG_EMERG */ 567138032Speter#ifdef LOG_ALERT 567290792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 567338032Speter map->map_prio = LOG_ALERT; 567438032Speter else 567564562Sgshapiro#endif /* LOG_ALERT */ 567638032Speter#ifdef LOG_CRIT 567790792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 567838032Speter map->map_prio = LOG_CRIT; 567938032Speter else 568064562Sgshapiro#endif /* LOG_CRIT */ 568138032Speter#ifdef LOG_ERR 568290792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 568338032Speter map->map_prio = LOG_ERR; 568438032Speter else 568564562Sgshapiro#endif /* LOG_ERR */ 568638032Speter#ifdef LOG_WARNING 568790792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 568838032Speter map->map_prio = LOG_WARNING; 568938032Speter else 569064562Sgshapiro#endif /* LOG_WARNING */ 569138032Speter#ifdef LOG_NOTICE 569290792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 569338032Speter map->map_prio = LOG_NOTICE; 569438032Speter else 569564562Sgshapiro#endif /* LOG_NOTICE */ 569638032Speter#ifdef LOG_INFO 569790792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 569838032Speter map->map_prio = LOG_INFO; 569938032Speter else 570064562Sgshapiro#endif /* LOG_INFO */ 570138032Speter#ifdef LOG_DEBUG 570290792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 570338032Speter map->map_prio = LOG_DEBUG; 570438032Speter else 570564562Sgshapiro#endif /* LOG_DEBUG */ 570638032Speter { 570790792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 570838032Speter priority); 570990792Sgshapiro return false; 571038032Speter } 571138032Speter } 571290792Sgshapiro return true; 571338032Speter} 571438032Speter 571538032Speter/* 571642575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 571738032Speter*/ 571838032Speter 571938032Speterchar * 572038032Spetersyslog_map_lookup(map, string, args, statp) 572138032Speter MAP *map; 572238032Speter char *string; 572338032Speter char **args; 572438032Speter int *statp; 572538032Speter{ 572638032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 572738032Speter 572838032Speter if (ptr != NULL) 572938032Speter { 573038032Speter if (tTd(38, 20)) 573190792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 573264562Sgshapiro map->map_mname, map->map_prio, ptr); 573338032Speter 573438032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 573538032Speter } 573638032Speter 573738032Speter *statp = EX_OK; 573838032Speter return ""; 573938032Speter} 574038032Speter 5741168515Sgshapiro#if _FFR_DPRINTF_MAP 574290792Sgshapiro/* 5743168515Sgshapiro** dprintf map 5744168515Sgshapiro*/ 5745168515Sgshapiro 5746168515Sgshapiro#define map_dbg_level map_lockfd /* overload field */ 5747168515Sgshapiro 5748168515Sgshapiro/* 5749168515Sgshapiro** DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages. 5750168515Sgshapiro*/ 5751168515Sgshapiro 5752168515Sgshapirobool 5753168515Sgshapirodprintf_map_parseargs(map, args) 5754168515Sgshapiro MAP *map; 5755168515Sgshapiro char *args; 5756168515Sgshapiro{ 5757168515Sgshapiro char *p = args; 5758168515Sgshapiro char *dbg_level = NULL; 5759168515Sgshapiro 5760168515Sgshapiro /* there is no check whether there is really an argument */ 5761168515Sgshapiro while (*p != '\0') 5762168515Sgshapiro { 5763363466Sgshapiro while (SM_ISSPACE(*p)) 5764168515Sgshapiro p++; 5765168515Sgshapiro if (*p != '-') 5766168515Sgshapiro break; 5767168515Sgshapiro ++p; 5768168515Sgshapiro if (*p == 'D') 5769168515Sgshapiro { 5770168515Sgshapiro map->map_mflags |= MF_DEFER; 5771168515Sgshapiro ++p; 5772168515Sgshapiro } 5773168515Sgshapiro else if (*p == 'S') 5774168515Sgshapiro { 5775168515Sgshapiro map->map_spacesub = *++p; 5776168515Sgshapiro if (*p != '\0') 5777168515Sgshapiro p++; 5778168515Sgshapiro } 5779168515Sgshapiro else if (*p == 'd') 5780168515Sgshapiro { 5781363466Sgshapiro while (*++p != '\0' && SM_ISSPACE(*p)) 5782168515Sgshapiro continue; 5783168515Sgshapiro if (*p == '\0') 5784168515Sgshapiro break; 5785168515Sgshapiro dbg_level = p; 5786363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 5787168515Sgshapiro p++; 5788168515Sgshapiro if (*p != '\0') 5789168515Sgshapiro *p++ = '\0'; 5790168515Sgshapiro } 5791168515Sgshapiro else 5792168515Sgshapiro { 5793168515Sgshapiro syserr("Illegal option %c map dprintf", *p); 5794168515Sgshapiro ++p; 5795168515Sgshapiro } 5796168515Sgshapiro } 5797168515Sgshapiro 5798168515Sgshapiro if (dbg_level == NULL) 5799168515Sgshapiro map->map_dbg_level = 0; 5800168515Sgshapiro else 5801168515Sgshapiro { 5802168515Sgshapiro if (!(isascii(*dbg_level) && isdigit(*dbg_level))) 5803168515Sgshapiro { 5804168515Sgshapiro syserr("dprintf map \"%s\", file %s: -d should specify a number, not %s", 5805168515Sgshapiro map->map_mname, map->map_file, 5806168515Sgshapiro dbg_level); 5807168515Sgshapiro return false; 5808168515Sgshapiro } 5809168515Sgshapiro map->map_dbg_level = atoi(dbg_level); 5810168515Sgshapiro } 5811168515Sgshapiro return true; 5812168515Sgshapiro} 5813168515Sgshapiro 5814168515Sgshapiro/* 5815168515Sgshapiro** DPRINTF_MAP_LOOKUP -- rewrite and print message. Always return empty string 5816168515Sgshapiro*/ 5817168515Sgshapiro 5818168515Sgshapirochar * 5819168515Sgshapirodprintf_map_lookup(map, string, args, statp) 5820168515Sgshapiro MAP *map; 5821168515Sgshapiro char *string; 5822168515Sgshapiro char **args; 5823168515Sgshapiro int *statp; 5824168515Sgshapiro{ 5825168515Sgshapiro char *ptr = map_rewrite(map, string, strlen(string), args); 5826168515Sgshapiro 5827168515Sgshapiro if (ptr != NULL && tTd(85, map->map_dbg_level)) 5828168515Sgshapiro sm_dprintf("%s\n", ptr); 5829168515Sgshapiro *statp = EX_OK; 5830168515Sgshapiro return ""; 5831168515Sgshapiro} 5832168515Sgshapiro#endif /* _FFR_DPRINTF_MAP */ 5833168515Sgshapiro 5834168515Sgshapiro/* 583538032Speter** HESIOD Modules 583638032Speter*/ 583738032Speter 583890792Sgshapiro#if HESIOD 583938032Speter 584038032Speterbool 584138032Speterhes_map_open(map, mode) 584238032Speter MAP *map; 584338032Speter int mode; 584438032Speter{ 584538032Speter if (tTd(38, 2)) 584690792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 584738032Speter map->map_mname, map->map_file, mode); 584838032Speter 584938032Speter if (mode != O_RDONLY) 585038032Speter { 585138032Speter /* issue a pseudo-error message */ 585290792Sgshapiro errno = SM_EMAPCANTWRITE; 585390792Sgshapiro return false; 585438032Speter } 585538032Speter 585664562Sgshapiro# ifdef HESIOD_INIT 585738032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 585890792Sgshapiro return true; 585938032Speter 586038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 586194334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 586290792Sgshapiro sm_errstring(errno)); 586390792Sgshapiro return false; 586464562Sgshapiro# else /* HESIOD_INIT */ 586538032Speter if (hes_error() == HES_ER_UNINIT) 586638032Speter hes_init(); 586738032Speter switch (hes_error()) 586838032Speter { 586938032Speter case HES_ER_OK: 587038032Speter case HES_ER_NOTFOUND: 587190792Sgshapiro return true; 587238032Speter } 587338032Speter 587438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 587594334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 587638032Speter 587790792Sgshapiro return false; 587864562Sgshapiro# endif /* HESIOD_INIT */ 587938032Speter} 588038032Speter 588138032Speterchar * 588238032Speterhes_map_lookup(map, name, av, statp) 588338032Speter MAP *map; 588438032Speter char *name; 588538032Speter char **av; 588638032Speter int *statp; 588738032Speter{ 588838032Speter char **hp; 588938032Speter 589038032Speter if (tTd(38, 20)) 589190792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 589238032Speter 589338032Speter if (name[0] == '\\') 589438032Speter { 589538032Speter char *np; 589638032Speter int nl; 589777349Sgshapiro int save_errno; 589838032Speter char nbuf[MAXNAME]; 589938032Speter 590038032Speter nl = strlen(name); 5901168515Sgshapiro if (nl < sizeof(nbuf) - 1) 590238032Speter np = nbuf; 590338032Speter else 590438032Speter np = xalloc(strlen(name) + 2); 590538032Speter np[0] = '\\'; 5906168515Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof(nbuf)) - 1); 590764562Sgshapiro# ifdef HESIOD_INIT 590838032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 5909363466Sgshapiro# else 591038032Speter hp = hes_resolve(np, map->map_file); 591164562Sgshapiro# endif /* HESIOD_INIT */ 591277349Sgshapiro save_errno = errno; 591338032Speter if (np != nbuf) 591490792Sgshapiro sm_free(np); /* XXX */ 591577349Sgshapiro errno = save_errno; 591638032Speter } 591738032Speter else 591838032Speter { 591964562Sgshapiro# ifdef HESIOD_INIT 592038032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 5921363466Sgshapiro# else 592238032Speter hp = hes_resolve(name, map->map_file); 592364562Sgshapiro# endif /* HESIOD_INIT */ 592438032Speter } 592564562Sgshapiro# ifdef HESIOD_INIT 592677349Sgshapiro if (hp == NULL || *hp == NULL) 592738032Speter { 592838032Speter switch (errno) 592938032Speter { 593038032Speter case ENOENT: 593138032Speter *statp = EX_NOTFOUND; 593238032Speter break; 593338032Speter case ECONNREFUSED: 593438032Speter *statp = EX_TEMPFAIL; 593538032Speter break; 593690792Sgshapiro case EMSGSIZE: 593738032Speter case ENOMEM: 593838032Speter default: 593938032Speter *statp = EX_UNAVAILABLE; 594038032Speter break; 594138032Speter } 594282017Sgshapiro if (hp != NULL) 594382017Sgshapiro hesiod_free_list(HesiodContext, hp); 594438032Speter return NULL; 594538032Speter } 594664562Sgshapiro# else /* HESIOD_INIT */ 594738032Speter if (hp == NULL || hp[0] == NULL) 594838032Speter { 594938032Speter switch (hes_error()) 595038032Speter { 595138032Speter case HES_ER_OK: 595238032Speter *statp = EX_OK; 595338032Speter break; 595438032Speter 595538032Speter case HES_ER_NOTFOUND: 595638032Speter *statp = EX_NOTFOUND; 595738032Speter break; 595838032Speter 595938032Speter case HES_ER_CONFIG: 596038032Speter *statp = EX_UNAVAILABLE; 596138032Speter break; 596238032Speter 596338032Speter case HES_ER_NET: 596438032Speter *statp = EX_TEMPFAIL; 596538032Speter break; 596638032Speter } 596738032Speter return NULL; 596838032Speter } 596964562Sgshapiro# endif /* HESIOD_INIT */ 597038032Speter 597138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 597238032Speter return map_rewrite(map, name, strlen(name), NULL); 597338032Speter else 597438032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 597538032Speter} 597638032Speter 597790792Sgshapiro/* 597890792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 597990792Sgshapiro*/ 598090792Sgshapiro 598190792Sgshapirovoid 598290792Sgshapirohes_map_close(map) 598390792Sgshapiro MAP *map; 598490792Sgshapiro{ 598590792Sgshapiro if (tTd(38, 20)) 598690792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 598790792Sgshapiro 598890792Sgshapiro# ifdef HESIOD_INIT 598990792Sgshapiro /* Free the hesiod context */ 599090792Sgshapiro if (HesiodContext != NULL) 599190792Sgshapiro { 599290792Sgshapiro hesiod_end(HesiodContext); 599390792Sgshapiro HesiodContext = NULL; 599490792Sgshapiro } 599590792Sgshapiro# endif /* HESIOD_INIT */ 599690792Sgshapiro} 599790792Sgshapiro 599864562Sgshapiro#endif /* HESIOD */ 599990792Sgshapiro/* 600038032Speter** NeXT NETINFO Modules 600138032Speter*/ 600238032Speter 600338032Speter#if NETINFO 600438032Speter 600538032Speter# define NETINFO_DEFAULT_DIR "/aliases" 600638032Speter# define NETINFO_DEFAULT_PROPERTY "members" 600738032Speter 600838032Speter/* 600938032Speter** NI_MAP_OPEN -- open NetInfo Aliases 601038032Speter*/ 601138032Speter 601238032Speterbool 601338032Speterni_map_open(map, mode) 601438032Speter MAP *map; 601538032Speter int mode; 601638032Speter{ 601738032Speter if (tTd(38, 2)) 601890792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 601938032Speter map->map_mname, map->map_file, mode); 602038032Speter mode &= O_ACCMODE; 602138032Speter 602238032Speter if (*map->map_file == '\0') 602338032Speter map->map_file = NETINFO_DEFAULT_DIR; 602438032Speter 602538032Speter if (map->map_valcolnm == NULL) 602638032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 602738032Speter 602890792Sgshapiro if (map->map_coldelim == '\0') 602990792Sgshapiro { 603090792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 603190792Sgshapiro map->map_coldelim = ','; 603290792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 603390792Sgshapiro map->map_coldelim = ' '; 603490792Sgshapiro } 603590792Sgshapiro return true; 603638032Speter} 603738032Speter 603838032Speter 603938032Speter/* 604038032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 604138032Speter*/ 604238032Speter 604338032Speterchar * 604438032Speterni_map_lookup(map, name, av, statp) 604538032Speter MAP *map; 604638032Speter char *name; 604738032Speter char **av; 604838032Speter int *statp; 604938032Speter{ 605038032Speter char *res; 605138032Speter char *propval; 605238032Speter 605338032Speter if (tTd(38, 20)) 605490792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 605538032Speter 605638032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 605738032Speter map->map_valcolnm, map->map_coldelim); 605838032Speter 605938032Speter if (propval == NULL) 606038032Speter return NULL; 606138032Speter 606290792Sgshapiro SM_TRY 606390792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 606490792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 606590792Sgshapiro else 606690792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 606790792Sgshapiro SM_FINALLY 606890792Sgshapiro sm_free(propval); 606990792Sgshapiro SM_END_TRY 607038032Speter return res; 607138032Speter} 607238032Speter 607338032Speter 607464562Sgshapirostatic bool 607538032Speterni_getcanonname(name, hbsize, statp) 607638032Speter char *name; 607738032Speter int hbsize; 607838032Speter int *statp; 607938032Speter{ 608038032Speter char *vptr; 608138032Speter char *ptr; 608238032Speter char nbuf[MAXNAME + 1]; 608338032Speter 608438032Speter if (tTd(38, 20)) 608590792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 608638032Speter 6087168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 608838032Speter { 608938032Speter *statp = EX_UNAVAILABLE; 609090792Sgshapiro return false; 609138032Speter } 609273188Sgshapiro (void) shorten_hostname(nbuf); 609338032Speter 609438032Speter /* we only accept single token search key */ 609538032Speter if (strchr(nbuf, '.')) 609638032Speter { 609738032Speter *statp = EX_NOHOST; 609890792Sgshapiro return false; 609938032Speter } 610038032Speter 610138032Speter /* Do the search */ 610238032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 610338032Speter 610438032Speter if (vptr == NULL) 610538032Speter { 610638032Speter *statp = EX_NOHOST; 610790792Sgshapiro return false; 610838032Speter } 610938032Speter 611038032Speter /* Only want the first machine name */ 611138032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 611238032Speter *ptr = '\0'; 611338032Speter 611490792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 611538032Speter { 611677349Sgshapiro sm_free(vptr); 611790792Sgshapiro *statp = EX_UNAVAILABLE; 611890792Sgshapiro return true; 611938032Speter } 612077349Sgshapiro sm_free(vptr); 612190792Sgshapiro *statp = EX_OK; 612290792Sgshapiro return false; 612338032Speter} 612490792Sgshapiro#endif /* NETINFO */ 612538032Speter/* 612638032Speter** TEXT (unindexed text file) Modules 612738032Speter** 612838032Speter** This code donated by Sun Microsystems. 612938032Speter*/ 613038032Speter 613138032Speter#define map_sff map_lockfd /* overload field */ 613238032Speter 613338032Speter 613438032Speter/* 613538032Speter** TEXT_MAP_OPEN -- open text table 613638032Speter*/ 613738032Speter 613838032Speterbool 613938032Spetertext_map_open(map, mode) 614038032Speter MAP *map; 614138032Speter int mode; 614238032Speter{ 614364562Sgshapiro long sff; 614438032Speter int i; 614538032Speter 614638032Speter if (tTd(38, 2)) 614790792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 614838032Speter map->map_mname, map->map_file, mode); 614938032Speter 615038032Speter mode &= O_ACCMODE; 615138032Speter if (mode != O_RDONLY) 615238032Speter { 615338032Speter errno = EPERM; 615490792Sgshapiro return false; 615538032Speter } 615638032Speter 615738032Speter if (*map->map_file == '\0') 615838032Speter { 615938032Speter syserr("text map \"%s\": file name required", 616038032Speter map->map_mname); 616190792Sgshapiro return false; 616238032Speter } 616338032Speter 616438032Speter if (map->map_file[0] != '/') 616538032Speter { 616638032Speter syserr("text map \"%s\": file name must be fully qualified", 616738032Speter map->map_mname); 616890792Sgshapiro return false; 616938032Speter } 617038032Speter 617138032Speter sff = SFF_ROOTOK|SFF_REGONLY; 617264562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 617338032Speter sff |= SFF_NOWLINK; 617464562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 617538032Speter sff |= SFF_SAFEDIRPATH; 617638032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 617738032Speter sff, S_IRUSR, NULL)) != 0) 617838032Speter { 617964562Sgshapiro int save_errno = errno; 618064562Sgshapiro 618138032Speter /* cannot open this map */ 618238032Speter if (tTd(38, 2)) 618390792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 618464562Sgshapiro errno = save_errno; 618538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 618638032Speter syserr("text map \"%s\": unsafe map file %s", 618738032Speter map->map_mname, map->map_file); 618890792Sgshapiro return false; 618938032Speter } 619038032Speter 619138032Speter if (map->map_keycolnm == NULL) 619238032Speter map->map_keycolno = 0; 619338032Speter else 619438032Speter { 619538032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 619638032Speter { 619738032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 619838032Speter map->map_mname, map->map_file, 619938032Speter map->map_keycolnm); 620090792Sgshapiro return false; 620138032Speter } 620238032Speter map->map_keycolno = atoi(map->map_keycolnm); 620338032Speter } 620438032Speter 620538032Speter if (map->map_valcolnm == NULL) 620638032Speter map->map_valcolno = 0; 620738032Speter else 620838032Speter { 620938032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 621038032Speter { 621138032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 621238032Speter map->map_mname, map->map_file, 621338032Speter map->map_valcolnm); 621490792Sgshapiro return false; 621538032Speter } 621638032Speter map->map_valcolno = atoi(map->map_valcolnm); 621738032Speter } 621838032Speter 621938032Speter if (tTd(38, 2)) 622038032Speter { 622190792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 622238032Speter map->map_mname, map->map_file); 622338032Speter if (map->map_coldelim == '\0') 622490792Sgshapiro sm_dprintf("(white space)\n"); 622538032Speter else 622690792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 622738032Speter } 622838032Speter 622938032Speter map->map_sff = sff; 623090792Sgshapiro return true; 623138032Speter} 623238032Speter 623338032Speter 623438032Speter/* 623538032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 623638032Speter*/ 623738032Speter 623838032Speterchar * 623938032Spetertext_map_lookup(map, name, av, statp) 624038032Speter MAP *map; 624138032Speter char *name; 624238032Speter char **av; 624338032Speter int *statp; 624438032Speter{ 624538032Speter char *vp; 624638032Speter auto int vsize; 624738032Speter int buflen; 624890792Sgshapiro SM_FILE_T *f; 624938032Speter char delim; 625038032Speter int key_idx; 625138032Speter bool found_it; 625264562Sgshapiro long sff = map->map_sff; 625338032Speter char search_key[MAXNAME + 1]; 625438032Speter char linebuf[MAXLINE]; 625538032Speter char buf[MAXNAME + 1]; 625638032Speter 625790792Sgshapiro found_it = false; 625838032Speter if (tTd(38, 20)) 625990792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 626038032Speter 626138032Speter buflen = strlen(name); 6262168515Sgshapiro if (buflen > sizeof(search_key) - 1) 6263168515Sgshapiro buflen = sizeof(search_key) - 1; /* XXX just cut if off? */ 626464562Sgshapiro memmove(search_key, name, buflen); 626538032Speter search_key[buflen] = '\0'; 626638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 626738032Speter makelower(search_key); 626838032Speter 626938032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 627038032Speter if (f == NULL) 627138032Speter { 627238032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 627338032Speter *statp = EX_UNAVAILABLE; 627438032Speter return NULL; 627538032Speter } 627638032Speter key_idx = map->map_keycolno; 627738032Speter delim = map->map_coldelim; 627898121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 6279249729Sgshapiro linebuf, sizeof(linebuf)) >= 0) 628038032Speter { 628138032Speter char *p; 628238032Speter 628338032Speter /* skip comment line */ 628438032Speter if (linebuf[0] == '#') 628538032Speter continue; 628638032Speter p = strchr(linebuf, '\n'); 628738032Speter if (p != NULL) 628838032Speter *p = '\0'; 6289168515Sgshapiro p = get_column(linebuf, key_idx, delim, buf, sizeof(buf)); 629090792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 629138032Speter { 629290792Sgshapiro found_it = true; 629338032Speter break; 629438032Speter } 629538032Speter } 629690792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 629738032Speter if (!found_it) 629838032Speter { 629938032Speter *statp = EX_NOTFOUND; 630038032Speter return NULL; 630138032Speter } 6302168515Sgshapiro vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof(buf)); 630342575Speter if (vp == NULL) 630442575Speter { 630542575Speter *statp = EX_NOTFOUND; 630642575Speter return NULL; 630742575Speter } 630838032Speter vsize = strlen(vp); 630938032Speter *statp = EX_OK; 631038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 631138032Speter return map_rewrite(map, name, strlen(name), NULL); 631238032Speter else 631338032Speter return map_rewrite(map, vp, vsize, av); 631438032Speter} 631538032Speter 631638032Speter/* 631738032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 631838032Speter*/ 631938032Speter 632064562Sgshapirostatic bool 632138032Spetertext_getcanonname(name, hbsize, statp) 632238032Speter char *name; 632338032Speter int hbsize; 632438032Speter int *statp; 632538032Speter{ 632638032Speter bool found; 632773188Sgshapiro char *dot; 632890792Sgshapiro SM_FILE_T *f; 632938032Speter char linebuf[MAXLINE]; 633038032Speter char cbuf[MAXNAME + 1]; 633138032Speter char nbuf[MAXNAME + 1]; 633238032Speter 633338032Speter if (tTd(38, 20)) 633490792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 633538032Speter 6336168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 633738032Speter { 633838032Speter *statp = EX_UNAVAILABLE; 633990792Sgshapiro return false; 634038032Speter } 634173188Sgshapiro dot = shorten_hostname(nbuf); 634238032Speter 634390792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 634490792Sgshapiro NULL); 634538032Speter if (f == NULL) 634638032Speter { 634738032Speter *statp = EX_UNAVAILABLE; 634890792Sgshapiro return false; 634938032Speter } 635090792Sgshapiro found = false; 635190792Sgshapiro while (!found && 635298121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 6353249729Sgshapiro linebuf, sizeof(linebuf)) >= 0) 635438032Speter { 635538032Speter char *p = strpbrk(linebuf, "#\n"); 635638032Speter 635738032Speter if (p != NULL) 635838032Speter *p = '\0'; 635938032Speter if (linebuf[0] != '\0') 636073188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 6361168515Sgshapiro cbuf, sizeof(cbuf)); 636238032Speter } 636390792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 636438032Speter if (!found) 636538032Speter { 636638032Speter *statp = EX_NOHOST; 636790792Sgshapiro return false; 636838032Speter } 636938032Speter 637090792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 637138032Speter { 637290792Sgshapiro *statp = EX_UNAVAILABLE; 637390792Sgshapiro return false; 637438032Speter } 637590792Sgshapiro *statp = EX_OK; 637690792Sgshapiro return true; 637738032Speter} 637890792Sgshapiro/* 637938032Speter** STAB (Symbol Table) Modules 638038032Speter*/ 638138032Speter 638238032Speter 638338032Speter/* 638438032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 638538032Speter*/ 638638032Speter 638738032Speter/* ARGSUSED2 */ 638838032Speterchar * 638938032Speterstab_map_lookup(map, name, av, pstat) 639038032Speter register MAP *map; 639138032Speter char *name; 639238032Speter char **av; 639338032Speter int *pstat; 639438032Speter{ 639538032Speter register STAB *s; 639638032Speter 639738032Speter if (tTd(38, 20)) 639890792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 639938032Speter map->map_mname, name); 640038032Speter 640138032Speter s = stab(name, ST_ALIAS, ST_FIND); 6402147078Sgshapiro if (s == NULL) 6403147078Sgshapiro return NULL; 6404147078Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 6405147078Sgshapiro return map_rewrite(map, name, strlen(name), NULL); 6406147078Sgshapiro else 6407147078Sgshapiro return map_rewrite(map, s->s_alias, strlen(s->s_alias), av); 640838032Speter} 640938032Speter 641038032Speter/* 641138032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 641238032Speter*/ 641338032Speter 641438032Spetervoid 641538032Speterstab_map_store(map, lhs, rhs) 641638032Speter register MAP *map; 641738032Speter char *lhs; 641838032Speter char *rhs; 641938032Speter{ 642038032Speter register STAB *s; 642138032Speter 642238032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 642338032Speter s->s_alias = newstr(rhs); 642438032Speter} 642538032Speter 642638032Speter 642738032Speter/* 642838032Speter** STAB_MAP_OPEN -- initialize (reads data file) 642938032Speter** 6430223067Sgshapiro** This is a weird case -- it is only intended as a fallback for 643138032Speter** aliases. For this reason, opens for write (only during a 643238032Speter** "newaliases") always fails, and opens for read open the 643338032Speter** actual underlying text file instead of the database. 643438032Speter*/ 643538032Speter 643638032Speterbool 643738032Speterstab_map_open(map, mode) 643838032Speter register MAP *map; 643938032Speter int mode; 644038032Speter{ 644190792Sgshapiro SM_FILE_T *af; 644264562Sgshapiro long sff; 644338032Speter struct stat st; 644438032Speter 644538032Speter if (tTd(38, 2)) 644690792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 644738032Speter map->map_mname, map->map_file, mode); 644838032Speter 644938032Speter mode &= O_ACCMODE; 645038032Speter if (mode != O_RDONLY) 645138032Speter { 645238032Speter errno = EPERM; 645390792Sgshapiro return false; 645438032Speter } 645538032Speter 645638032Speter sff = SFF_ROOTOK|SFF_REGONLY; 645764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 645838032Speter sff |= SFF_NOWLINK; 645964562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 646038032Speter sff |= SFF_SAFEDIRPATH; 646138032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 646238032Speter if (af == NULL) 646390792Sgshapiro return false; 646490792Sgshapiro readaliases(map, af, false, false); 646538032Speter 646690792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 646738032Speter map->map_mtime = st.st_mtime; 646890792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 646938032Speter 647090792Sgshapiro return true; 647138032Speter} 647290792Sgshapiro/* 647338032Speter** Implicit Modules 647438032Speter** 647538032Speter** Tries several types. For back compatibility of aliases. 647638032Speter*/ 647738032Speter 647838032Speter 647938032Speter/* 648038032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 648138032Speter*/ 648238032Speter 648338032Speterchar * 648438032Speterimpl_map_lookup(map, name, av, pstat) 648538032Speter MAP *map; 648638032Speter char *name; 648738032Speter char **av; 648838032Speter int *pstat; 648938032Speter{ 649038032Speter if (tTd(38, 20)) 649190792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 649238032Speter map->map_mname, name); 649338032Speter 649490792Sgshapiro#if NEWDB 649538032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 649638032Speter return db_map_lookup(map, name, av, pstat); 6497363466Sgshapiro#endif 649890792Sgshapiro#if NDBM 649938032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 650038032Speter return ndbm_map_lookup(map, name, av, pstat); 6501363466Sgshapiro#endif 6502363466Sgshapiro#if CDB 6503363466Sgshapiro if (bitset(MF_IMPL_CDB, map->map_mflags)) 6504363466Sgshapiro return cdb_map_lookup(map, name, av, pstat); 6505363466Sgshapiro#endif 650638032Speter return stab_map_lookup(map, name, av, pstat); 650738032Speter} 650838032Speter 650938032Speter/* 651038032Speter** IMPL_MAP_STORE -- store in open databases 651138032Speter*/ 651238032Speter 651338032Spetervoid 651438032Speterimpl_map_store(map, lhs, rhs) 651538032Speter MAP *map; 651638032Speter char *lhs; 651738032Speter char *rhs; 651838032Speter{ 651938032Speter if (tTd(38, 12)) 652090792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 652138032Speter map->map_mname, lhs, rhs); 652290792Sgshapiro#if NEWDB 652338032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 652438032Speter db_map_store(map, lhs, rhs); 6525363466Sgshapiro#endif 652690792Sgshapiro#if NDBM 652738032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 652838032Speter ndbm_map_store(map, lhs, rhs); 6529363466Sgshapiro#endif 6530363466Sgshapiro#if CDB 6531363466Sgshapiro if (bitset(MF_IMPL_CDB, map->map_mflags)) 6532363466Sgshapiro cdb_map_store(map, lhs, rhs); 6533363466Sgshapiro#endif 653438032Speter stab_map_store(map, lhs, rhs); 653538032Speter} 653638032Speter 653738032Speter/* 653838032Speter** IMPL_MAP_OPEN -- implicit database open 653938032Speter*/ 654038032Speter 654138032Speterbool 654238032Speterimpl_map_open(map, mode) 654338032Speter MAP *map; 654438032Speter int mode; 654538032Speter{ 6546363466Sgshapiro bool wasopt; 6547363466Sgshapiro 654838032Speter if (tTd(38, 2)) 654990792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 655038032Speter map->map_mname, map->map_file, mode); 655138032Speter 655238032Speter mode &= O_ACCMODE; 6553363466Sgshapiro wasopt = bitset(MF_OPTIONAL, map->map_mflags); 6554363466Sgshapiro 6555363466Sgshapiro /* suppress error msgs */ 6556363466Sgshapiro map->map_mflags |= MF_OPTIONAL; 655790792Sgshapiro#if NEWDB 655838032Speter map->map_mflags |= MF_IMPL_HASH; 655938032Speter if (hash_map_open(map, mode)) 656038032Speter { 656138032Speter# ifdef NDBM_YP_COMPAT 656238032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 6563363466Sgshapiro# endif 6564363466Sgshapiro goto ok; 656538032Speter } 656638032Speter else 656738032Speter map->map_mflags &= ~MF_IMPL_HASH; 656864562Sgshapiro#endif /* NEWDB */ 656990792Sgshapiro#if NDBM 657038032Speter map->map_mflags |= MF_IMPL_NDBM; 657138032Speter if (ndbm_map_open(map, mode)) 6572363466Sgshapiro goto ok; 657338032Speter else 657438032Speter map->map_mflags &= ~MF_IMPL_NDBM; 657564562Sgshapiro#endif /* NDBM */ 657638032Speter 6577363466Sgshapiro#if CDB 6578363466Sgshapiro map->map_mflags |= MF_IMPL_CDB; 6579363466Sgshapiro if (cdb_map_open(map, mode)) 6580363466Sgshapiro goto ok; 6581363466Sgshapiro else 6582363466Sgshapiro map->map_mflags &= ~MF_IMPL_CDB; 6583363466Sgshapiro#endif /* CDB */ 6584363466Sgshapiro 6585363466Sgshapiro if (!bitset(MF_ALIAS, map->map_mflags)) 6586363466Sgshapiro goto fail; 6587363466Sgshapiro#if NEWDB || NDBM || CDB 658838032Speter if (Verbose) 658938032Speter message("WARNING: cannot open alias database %s%s", 659038032Speter map->map_file, 659138032Speter mode == O_RDONLY ? "; reading text version" : ""); 6592363466Sgshapiro#else 659338032Speter if (mode != O_RDONLY) 659438032Speter usrerr("Cannot rebuild aliases: no database format defined"); 6595363466Sgshapiro#endif 659638032Speter 6597363466Sgshapiro if (mode == O_RDONLY && stab_map_open(map, mode)) 6598363466Sgshapiro goto ok; 6599363466Sgshapiro 6600363466Sgshapiro fail: 6601363466Sgshapiro if (!wasopt) 6602363466Sgshapiro map->map_mflags &= ~MF_OPTIONAL; 6603363466Sgshapiro return false; 6604363466Sgshapiro 6605363466Sgshapiro ok: 6606363466Sgshapiro if (!wasopt) 6607363466Sgshapiro map->map_mflags &= ~MF_OPTIONAL; 6608363466Sgshapiro return true; 660938032Speter} 661038032Speter 661138032Speter 661238032Speter/* 661338032Speter** IMPL_MAP_CLOSE -- close any open database(s) 661438032Speter*/ 661538032Speter 661638032Spetervoid 661738032Speterimpl_map_close(map) 661838032Speter MAP *map; 661938032Speter{ 662038032Speter if (tTd(38, 9)) 662190792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 662238032Speter map->map_mname, map->map_file, map->map_mflags); 662390792Sgshapiro#if NEWDB 662438032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 662538032Speter { 662638032Speter db_map_close(map); 662738032Speter map->map_mflags &= ~MF_IMPL_HASH; 662838032Speter } 662964562Sgshapiro#endif /* NEWDB */ 663038032Speter 663190792Sgshapiro#if NDBM 663238032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 663338032Speter { 663438032Speter ndbm_map_close(map); 663538032Speter map->map_mflags &= ~MF_IMPL_NDBM; 663638032Speter } 663764562Sgshapiro#endif /* NDBM */ 6638363466Sgshapiro#if CDB 6639363466Sgshapiro if (bitset(MF_IMPL_CDB, map->map_mflags)) 6640363466Sgshapiro { 6641363466Sgshapiro cdb_map_close(map); 6642363466Sgshapiro map->map_mflags &= ~MF_IMPL_CDB; 6643363466Sgshapiro } 6644363466Sgshapiro#endif /* CDB */ 664538032Speter} 6646363466Sgshapiro 664790792Sgshapiro/* 664838032Speter** User map class. 664938032Speter** 665038032Speter** Provides access to the system password file. 665138032Speter*/ 665238032Speter 665338032Speter/* 665438032Speter** USER_MAP_OPEN -- open user map 665538032Speter** 665638032Speter** Really just binds field names to field numbers. 665738032Speter*/ 665838032Speter 665938032Speterbool 666038032Speteruser_map_open(map, mode) 666138032Speter MAP *map; 666238032Speter int mode; 666338032Speter{ 666438032Speter if (tTd(38, 2)) 666590792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 666638032Speter map->map_mname, mode); 666738032Speter 666838032Speter mode &= O_ACCMODE; 666938032Speter if (mode != O_RDONLY) 667038032Speter { 667138032Speter /* issue a pseudo-error message */ 667290792Sgshapiro errno = SM_EMAPCANTWRITE; 667390792Sgshapiro return false; 667438032Speter } 667538032Speter if (map->map_valcolnm == NULL) 667664562Sgshapiro /* EMPTY */ 667738032Speter /* nothing */ ; 667890792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 667938032Speter map->map_valcolno = 1; 668090792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 668138032Speter map->map_valcolno = 2; 668290792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 668338032Speter map->map_valcolno = 3; 668490792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 668538032Speter map->map_valcolno = 4; 668690792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 668738032Speter map->map_valcolno = 5; 668890792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 668938032Speter map->map_valcolno = 6; 669090792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 669138032Speter map->map_valcolno = 7; 669238032Speter else 669338032Speter { 669438032Speter syserr("User map %s: unknown column name %s", 669538032Speter map->map_mname, map->map_valcolnm); 669690792Sgshapiro return false; 669738032Speter } 669890792Sgshapiro return true; 669938032Speter} 670038032Speter 670138032Speter 670238032Speter/* 670338032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 670438032Speter*/ 670538032Speter 670638032Speter/* ARGSUSED3 */ 670738032Speterchar * 670838032Speteruser_map_lookup(map, key, av, statp) 670938032Speter MAP *map; 671038032Speter char *key; 671138032Speter char **av; 671238032Speter int *statp; 671338032Speter{ 671438032Speter auto bool fuzzy; 671590792Sgshapiro SM_MBDB_T user; 671638032Speter 671738032Speter if (tTd(38, 20)) 671890792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 671938032Speter map->map_mname, key); 672038032Speter 672190792Sgshapiro *statp = finduser(key, &fuzzy, &user); 672290792Sgshapiro if (*statp != EX_OK) 672338032Speter return NULL; 672438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 672538032Speter return map_rewrite(map, key, strlen(key), NULL); 672638032Speter else 672738032Speter { 672838032Speter char *rwval = NULL; 672938032Speter char buf[30]; 673038032Speter 673138032Speter switch (map->map_valcolno) 673238032Speter { 673338032Speter case 0: 673438032Speter case 1: 673590792Sgshapiro rwval = user.mbdb_name; 673638032Speter break; 673738032Speter 673838032Speter case 2: 673990792Sgshapiro rwval = "x"; /* passwd no longer supported */ 674038032Speter break; 674138032Speter 674238032Speter case 3: 6743168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 674490792Sgshapiro (int) user.mbdb_uid); 674538032Speter rwval = buf; 674638032Speter break; 674738032Speter 674838032Speter case 4: 6749168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 675090792Sgshapiro (int) user.mbdb_gid); 675138032Speter rwval = buf; 675238032Speter break; 675338032Speter 675438032Speter case 5: 675590792Sgshapiro rwval = user.mbdb_fullname; 675638032Speter break; 675738032Speter 675838032Speter case 6: 675990792Sgshapiro rwval = user.mbdb_homedir; 676038032Speter break; 676138032Speter 676238032Speter case 7: 676390792Sgshapiro rwval = user.mbdb_shell; 676438032Speter break; 6765159609Sgshapiro default: 6766159609Sgshapiro syserr("user_map %s: bogus field %d", 6767159609Sgshapiro map->map_mname, map->map_valcolno); 6768159609Sgshapiro return NULL; 676938032Speter } 677038032Speter return map_rewrite(map, rwval, strlen(rwval), av); 677138032Speter } 677238032Speter} 677390792Sgshapiro/* 677438032Speter** Program map type. 677538032Speter** 677638032Speter** This provides access to arbitrary programs. It should be used 677738032Speter** only very sparingly, since there is no way to bound the cost 677838032Speter** of invoking an arbitrary program. 677938032Speter*/ 678038032Speter 678138032Speterchar * 678238032Speterprog_map_lookup(map, name, av, statp) 678338032Speter MAP *map; 678438032Speter char *name; 678538032Speter char **av; 678638032Speter int *statp; 678738032Speter{ 678838032Speter int i; 678964562Sgshapiro int save_errno; 679038032Speter int fd; 679164562Sgshapiro int status; 679238032Speter auto pid_t pid; 679364562Sgshapiro register char *p; 679438032Speter char *rval; 679538032Speter char *argv[MAXPV + 1]; 679638032Speter char buf[MAXLINE]; 679738032Speter 679838032Speter if (tTd(38, 20)) 679990792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 680038032Speter map->map_mname, name, map->map_file); 680138032Speter 680238032Speter i = 0; 680338032Speter argv[i++] = map->map_file; 680438032Speter if (map->map_rebuild != NULL) 680538032Speter { 6806168515Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof(buf)); 680738032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 680838032Speter { 680938032Speter if (i >= MAXPV - 1) 681038032Speter break; 681138032Speter argv[i++] = p; 681238032Speter } 681338032Speter } 681438032Speter argv[i++] = name; 681538032Speter argv[i] = NULL; 681638032Speter if (tTd(38, 21)) 681738032Speter { 681890792Sgshapiro sm_dprintf("prog_open:"); 681938032Speter for (i = 0; argv[i] != NULL; i++) 682090792Sgshapiro sm_dprintf(" %s", argv[i]); 682190792Sgshapiro sm_dprintf("\n"); 682238032Speter } 682390792Sgshapiro (void) sm_blocksignal(SIGCHLD); 682438032Speter pid = prog_open(argv, &fd, CurEnv); 682538032Speter if (pid < 0) 682638032Speter { 682738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 682838032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 682990792Sgshapiro map->map_mname, sm_errstring(errno)); 683038032Speter else if (tTd(38, 9)) 683190792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 683290792Sgshapiro map->map_mname, sm_errstring(errno)); 683338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 683438032Speter *statp = EX_OSFILE; 683538032Speter return NULL; 683638032Speter } 6837168515Sgshapiro i = read(fd, buf, sizeof(buf) - 1); 683838032Speter if (i < 0) 683938032Speter { 684090792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 684190792Sgshapiro map->map_mname, sm_errstring(errno)); 684238032Speter rval = NULL; 684338032Speter } 684438032Speter else if (i == 0) 684538032Speter { 684638032Speter if (tTd(38, 20)) 684790792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 684890792Sgshapiro map->map_mname); 684938032Speter rval = NULL; 685038032Speter } 685138032Speter else 685238032Speter { 685338032Speter buf[i] = '\0'; 685438032Speter p = strchr(buf, '\n'); 685538032Speter if (p != NULL) 685638032Speter *p = '\0'; 685738032Speter 685838032Speter /* collect the return value */ 685938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 686038032Speter rval = map_rewrite(map, name, strlen(name), NULL); 686138032Speter else 686277349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 686338032Speter 686438032Speter /* now flush any additional output */ 6865168515Sgshapiro while ((i = read(fd, buf, sizeof(buf))) > 0) 686638032Speter continue; 686738032Speter } 686838032Speter 686938032Speter /* wait for the process to terminate */ 687064562Sgshapiro (void) close(fd); 687164562Sgshapiro status = waitfor(pid); 687264562Sgshapiro save_errno = errno; 687390792Sgshapiro (void) sm_releasesignal(SIGCHLD); 687464562Sgshapiro errno = save_errno; 687538032Speter 687664562Sgshapiro if (status == -1) 687738032Speter { 687890792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 687990792Sgshapiro map->map_mname, sm_errstring(errno)); 688038032Speter *statp = EX_SOFTWARE; 688138032Speter rval = NULL; 688238032Speter } 688364562Sgshapiro else if (WIFEXITED(status)) 688438032Speter { 688564562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 688638032Speter rval = NULL; 688738032Speter } 688838032Speter else 688938032Speter { 689038032Speter syserr("prog_map_lookup(%s): child died on signal %d", 689190792Sgshapiro map->map_mname, status); 689238032Speter *statp = EX_UNAVAILABLE; 689338032Speter rval = NULL; 689438032Speter } 689538032Speter return rval; 689638032Speter} 689790792Sgshapiro/* 689838032Speter** Sequenced map type. 689938032Speter** 690038032Speter** Tries each map in order until something matches, much like 690138032Speter** implicit. Stores go to the first map in the list that can 690238032Speter** support storing. 690338032Speter** 690438032Speter** This is slightly unusual in that there are two interfaces. 690538032Speter** The "sequence" interface lets you stack maps arbitrarily. 690638032Speter** The "switch" interface builds a sequence map by looking 690738032Speter** at a system-dependent configuration file such as 690838032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 690938032Speter** 691038032Speter** We don't need an explicit open, since all maps are 691190792Sgshapiro** opened on demand. 691238032Speter*/ 691338032Speter 691438032Speter/* 691538032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 691638032Speter*/ 691738032Speter 691838032Speterbool 691938032Speterseq_map_parse(map, ap) 692038032Speter MAP *map; 692138032Speter char *ap; 692238032Speter{ 692338032Speter int maxmap; 692438032Speter 692538032Speter if (tTd(38, 2)) 692690792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 692738032Speter maxmap = 0; 692838032Speter while (*ap != '\0') 692938032Speter { 693038032Speter register char *p; 693138032Speter STAB *s; 693238032Speter 693338032Speter /* find beginning of map name */ 6934363466Sgshapiro while (SM_ISSPACE(*ap)) 693538032Speter ap++; 693664562Sgshapiro for (p = ap; 693764562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 693864562Sgshapiro p++) 693938032Speter continue; 694038032Speter if (*p != '\0') 694138032Speter *p++ = '\0'; 694238032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 694338032Speter p++; 694438032Speter if (*ap == '\0') 694538032Speter { 694638032Speter ap = p; 694738032Speter continue; 694838032Speter } 694938032Speter s = stab(ap, ST_MAP, ST_FIND); 695038032Speter if (s == NULL) 695138032Speter { 695238032Speter syserr("Sequence map %s: unknown member map %s", 695338032Speter map->map_mname, ap); 695438032Speter } 695590792Sgshapiro else if (maxmap >= MAXMAPSTACK) 695638032Speter { 695738032Speter syserr("Sequence map %s: too many member maps (%d max)", 695838032Speter map->map_mname, MAXMAPSTACK); 695938032Speter maxmap++; 696038032Speter } 696138032Speter else if (maxmap < MAXMAPSTACK) 696238032Speter { 696338032Speter map->map_stack[maxmap++] = &s->s_map; 696438032Speter } 696538032Speter ap = p; 696638032Speter } 696790792Sgshapiro return true; 696838032Speter} 696938032Speter 697038032Speter/* 697138032Speter** SWITCH_MAP_OPEN -- open a switched map 697238032Speter** 697338032Speter** This looks at the system-dependent configuration and builds 697438032Speter** a sequence map that does the same thing. 697538032Speter** 697638032Speter** Every system must define a switch_map_find routine in conf.c 697738032Speter** that will return the list of service types associated with a 697838032Speter** given service class. 697938032Speter*/ 698038032Speter 698138032Speterbool 698238032Speterswitch_map_open(map, mode) 698338032Speter MAP *map; 698438032Speter int mode; 698538032Speter{ 698638032Speter int mapno; 698738032Speter int nmaps; 698838032Speter char *maptype[MAXMAPSTACK]; 698938032Speter 699038032Speter if (tTd(38, 2)) 699190792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 699238032Speter map->map_mname, map->map_file, mode); 699338032Speter 699438032Speter mode &= O_ACCMODE; 699538032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 699638032Speter if (tTd(38, 19)) 699738032Speter { 699890792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 699938032Speter for (mapno = 0; mapno < nmaps; mapno++) 700090792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 700138032Speter } 700238032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 700390792Sgshapiro return false; 700438032Speter 700538032Speter for (mapno = 0; mapno < nmaps; mapno++) 700638032Speter { 700738032Speter register STAB *s; 700838032Speter char nbuf[MAXNAME + 1]; 700938032Speter 701038032Speter if (maptype[mapno] == NULL) 701138032Speter continue; 7012168515Sgshapiro (void) sm_strlcpyn(nbuf, sizeof(nbuf), 3, 701390792Sgshapiro map->map_mname, ".", maptype[mapno]); 701438032Speter s = stab(nbuf, ST_MAP, ST_FIND); 701538032Speter if (s == NULL) 701638032Speter { 701738032Speter syserr("Switch map %s: unknown member map %s", 701838032Speter map->map_mname, nbuf); 701938032Speter } 702038032Speter else 702138032Speter { 702238032Speter map->map_stack[mapno] = &s->s_map; 702338032Speter if (tTd(38, 4)) 702490792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 702590792Sgshapiro mapno, 702690792Sgshapiro s->s_map.map_class->map_cname, 702790792Sgshapiro nbuf); 702838032Speter } 702938032Speter } 703090792Sgshapiro return true; 703138032Speter} 703238032Speter 703390792Sgshapiro#if 0 703438032Speter/* 703538032Speter** SEQ_MAP_CLOSE -- close all underlying maps 703638032Speter*/ 703738032Speter 703838032Spetervoid 703938032Speterseq_map_close(map) 704038032Speter MAP *map; 704138032Speter{ 704238032Speter int mapno; 704338032Speter 704438032Speter if (tTd(38, 9)) 704590792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 704638032Speter 704738032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 704838032Speter { 704938032Speter MAP *mm = map->map_stack[mapno]; 705038032Speter 705138032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 705238032Speter continue; 705377349Sgshapiro mm->map_mflags |= MF_CLOSING; 705438032Speter mm->map_class->map_close(mm); 705577349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 705638032Speter } 705738032Speter} 705890792Sgshapiro#endif /* 0 */ 705938032Speter 706038032Speter/* 706138032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 706238032Speter*/ 706338032Speter 706438032Speterchar * 706538032Speterseq_map_lookup(map, key, args, pstat) 706638032Speter MAP *map; 706738032Speter char *key; 706838032Speter char **args; 706938032Speter int *pstat; 707038032Speter{ 707138032Speter int mapno; 707238032Speter int mapbit = 0x01; 707390792Sgshapiro bool tempfail = false; 707438032Speter 707538032Speter if (tTd(38, 20)) 707690792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 707738032Speter 707838032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 707938032Speter { 708038032Speter MAP *mm = map->map_stack[mapno]; 708138032Speter char *rv; 708238032Speter 708338032Speter if (mm == NULL) 708438032Speter continue; 708564562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 708664562Sgshapiro !openmap(mm)) 708738032Speter { 708838032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 708938032Speter { 709038032Speter *pstat = EX_UNAVAILABLE; 709138032Speter return NULL; 709238032Speter } 709338032Speter continue; 709438032Speter } 709538032Speter *pstat = EX_OK; 709638032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 709738032Speter if (rv != NULL) 709838032Speter return rv; 709938032Speter if (*pstat == EX_TEMPFAIL) 710038032Speter { 710138032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 710238032Speter return NULL; 710390792Sgshapiro tempfail = true; 710438032Speter } 710538032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 710638032Speter break; 710738032Speter } 710838032Speter if (tempfail) 710938032Speter *pstat = EX_TEMPFAIL; 711038032Speter else if (*pstat == EX_OK) 711138032Speter *pstat = EX_NOTFOUND; 711238032Speter return NULL; 711338032Speter} 711438032Speter 711538032Speter/* 711638032Speter** SEQ_MAP_STORE -- sequenced map store 711738032Speter*/ 711838032Speter 711938032Spetervoid 712038032Speterseq_map_store(map, key, val) 712138032Speter MAP *map; 712238032Speter char *key; 712338032Speter char *val; 712438032Speter{ 712538032Speter int mapno; 712638032Speter 712738032Speter if (tTd(38, 12)) 712890792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 712938032Speter map->map_mname, key, val); 713038032Speter 713138032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 713238032Speter { 713338032Speter MAP *mm = map->map_stack[mapno]; 713438032Speter 713538032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 713638032Speter continue; 713738032Speter 713838032Speter mm->map_class->map_store(mm, key, val); 713938032Speter return; 714038032Speter } 714138032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 714238032Speter map->map_mname, key, val); 714338032Speter} 714490792Sgshapiro/* 714538032Speter** NULL stubs 714638032Speter*/ 714738032Speter 714838032Speter/* ARGSUSED */ 714938032Speterbool 715038032Speternull_map_open(map, mode) 715138032Speter MAP *map; 715238032Speter int mode; 715338032Speter{ 715490792Sgshapiro return true; 715538032Speter} 715638032Speter 715738032Speter/* ARGSUSED */ 715838032Spetervoid 715938032Speternull_map_close(map) 716038032Speter MAP *map; 716138032Speter{ 716238032Speter return; 716338032Speter} 716438032Speter 716538032Speterchar * 716638032Speternull_map_lookup(map, key, args, pstat) 716738032Speter MAP *map; 716838032Speter char *key; 716938032Speter char **args; 717038032Speter int *pstat; 717138032Speter{ 717238032Speter *pstat = EX_NOTFOUND; 717338032Speter return NULL; 717438032Speter} 717538032Speter 717638032Speter/* ARGSUSED */ 717738032Spetervoid 717838032Speternull_map_store(map, key, val) 717938032Speter MAP *map; 718038032Speter char *key; 718138032Speter char *val; 718238032Speter{ 718338032Speter return; 718438032Speter} 718538032Speter 7186203004SgshapiroMAPCLASS NullMapClass = 7187203004Sgshapiro{ 7188203004Sgshapiro "null-map", NULL, 0, 7189203004Sgshapiro NULL, null_map_lookup, null_map_store, 7190203004Sgshapiro null_map_open, null_map_close, 7191203004Sgshapiro}; 7192203004Sgshapiro 719338032Speter/* 719438032Speter** BOGUS stubs 719538032Speter*/ 719638032Speter 719738032Speterchar * 719838032Speterbogus_map_lookup(map, key, args, pstat) 719938032Speter MAP *map; 720038032Speter char *key; 720138032Speter char **args; 720238032Speter int *pstat; 720338032Speter{ 720438032Speter *pstat = EX_TEMPFAIL; 720538032Speter return NULL; 720638032Speter} 720738032Speter 720838032SpeterMAPCLASS BogusMapClass = 720938032Speter{ 721090792Sgshapiro "bogus-map", NULL, 0, 721190792Sgshapiro NULL, bogus_map_lookup, null_map_store, 721290792Sgshapiro null_map_open, null_map_close, 721338032Speter}; 721490792Sgshapiro/* 721564562Sgshapiro** MACRO modules 721664562Sgshapiro*/ 721764562Sgshapiro 721864562Sgshapirochar * 721964562Sgshapiromacro_map_lookup(map, name, av, statp) 722064562Sgshapiro MAP *map; 722164562Sgshapiro char *name; 722264562Sgshapiro char **av; 722364562Sgshapiro int *statp; 722464562Sgshapiro{ 722564562Sgshapiro int mid; 722664562Sgshapiro 722764562Sgshapiro if (tTd(38, 20)) 722890792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 722964562Sgshapiro name == NULL ? "NULL" : name); 723064562Sgshapiro 723164562Sgshapiro if (name == NULL || 723264562Sgshapiro *name == '\0' || 723390792Sgshapiro (mid = macid(name)) == 0) 723464562Sgshapiro { 723564562Sgshapiro *statp = EX_CONFIG; 723664562Sgshapiro return NULL; 723764562Sgshapiro } 723864562Sgshapiro 723964562Sgshapiro if (av[1] == NULL) 724090792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 724164562Sgshapiro else 724290792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 724364562Sgshapiro 724464562Sgshapiro *statp = EX_OK; 724564562Sgshapiro return ""; 724664562Sgshapiro} 724790792Sgshapiro/* 724838032Speter** REGEX modules 724938032Speter*/ 725038032Speter 725190792Sgshapiro#if MAP_REGEX 725238032Speter 725338032Speter# include <regex.h> 725438032Speter 725538032Speter# define DEFAULT_DELIM CONDELSE 725638032Speter# define END_OF_FIELDS -1 725738032Speter# define ERRBUF_SIZE 80 725838032Speter# define MAX_MATCH 32 725938032Speter 726064562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 726138032Speter 726238032Speterstruct regex_map 726338032Speter{ 726471345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 726538032Speter int *regex_subfields; /* move to type MAP */ 726664562Sgshapiro char *regex_delim; /* move to type MAP */ 726738032Speter}; 726838032Speter 7269141858Sgshapirostatic int parse_fields __P((char *, int *, int, int)); 7270141858Sgshapirostatic char *regex_map_rewrite __P((MAP *, const char*, size_t, char **)); 7271141858Sgshapiro 727238032Speterstatic int 727338032Speterparse_fields(s, ibuf, blen, nr_substrings) 727438032Speter char *s; 727538032Speter int *ibuf; /* array */ 727638032Speter int blen; /* number of elements in ibuf */ 727738032Speter int nr_substrings; /* number of substrings in the pattern */ 727838032Speter{ 727938032Speter register char *cp; 728038032Speter int i = 0; 728190792Sgshapiro bool lastone = false; 728238032Speter 728338032Speter blen--; /* for terminating END_OF_FIELDS */ 728438032Speter cp = s; 728538032Speter do 728638032Speter { 728738032Speter for (;; cp++) 728838032Speter { 728938032Speter if (*cp == ',') 729038032Speter { 729138032Speter *cp = '\0'; 729238032Speter break; 729338032Speter } 729438032Speter if (*cp == '\0') 729538032Speter { 729690792Sgshapiro lastone = true; 729738032Speter break; 729838032Speter } 729938032Speter } 730038032Speter if (i < blen) 730138032Speter { 730238032Speter int val = atoi(s); 730338032Speter 730438032Speter if (val < 0 || val >= nr_substrings) 730538032Speter { 730638032Speter syserr("field (%d) out of range, only %d substrings in pattern", 730738032Speter val, nr_substrings); 730838032Speter return -1; 730938032Speter } 731038032Speter ibuf[i++] = val; 731138032Speter } 731238032Speter else 731338032Speter { 731490792Sgshapiro syserr("too many fields, %d max", blen); 731538032Speter return -1; 731638032Speter } 731738032Speter s = ++cp; 731838032Speter } while (!lastone); 731938032Speter ibuf[i] = END_OF_FIELDS; 732038032Speter return i; 732138032Speter} 732238032Speter 732338032Speterbool 732438032Speterregex_map_init(map, ap) 732538032Speter MAP *map; 732638032Speter char *ap; 732738032Speter{ 732838032Speter int regerr; 732938032Speter struct regex_map *map_p; 733038032Speter register char *p; 733138032Speter char *sub_param = NULL; 733238032Speter int pflags; 733390792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 733438032Speter 733538032Speter if (tTd(38, 2)) 733690792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 733764562Sgshapiro map->map_mname, ap); 733838032Speter 733938032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 734038032Speter p = ap; 7341168515Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof(*map_p)); 734271345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 734338032Speter 734438032Speter for (;;) 734564562Sgshapiro { 7346363466Sgshapiro while (SM_ISSPACE(*p)) 734738032Speter p++; 734838032Speter if (*p != '-') 734938032Speter break; 735038032Speter switch (*++p) 735138032Speter { 735238032Speter case 'n': /* not */ 735338032Speter map->map_mflags |= MF_REGEX_NOT; 735438032Speter break; 735538032Speter 735638032Speter case 'f': /* case sensitive */ 735738032Speter map->map_mflags |= MF_NOFOLDCASE; 735838032Speter pflags &= ~REG_ICASE; 735938032Speter break; 736038032Speter 736138032Speter case 'b': /* basic regular expressions */ 736238032Speter pflags &= ~REG_EXTENDED; 736338032Speter break; 736438032Speter 736538032Speter case 's': /* substring match () syntax */ 736638032Speter sub_param = ++p; 736738032Speter pflags &= ~REG_NOSUB; 736838032Speter break; 736938032Speter 737038032Speter case 'd': /* delimiter */ 737164562Sgshapiro map_p->regex_delim = ++p; 737238032Speter break; 737338032Speter 737438032Speter case 'a': /* map append */ 737538032Speter map->map_app = ++p; 737638032Speter break; 737738032Speter 737838032Speter case 'm': /* matchonly */ 737938032Speter map->map_mflags |= MF_MATCHONLY; 738038032Speter break; 738138032Speter 7382120256Sgshapiro case 'q': 7383120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 7384120256Sgshapiro break; 7385120256Sgshapiro 738664562Sgshapiro case 'S': 738764562Sgshapiro map->map_spacesub = *++p; 738864562Sgshapiro break; 738964562Sgshapiro 739064562Sgshapiro case 'D': 739164562Sgshapiro map->map_mflags |= MF_DEFER; 739264562Sgshapiro break; 739364562Sgshapiro 739438032Speter } 7395363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 739664562Sgshapiro p++; 739764562Sgshapiro if (*p != '\0') 739864562Sgshapiro *p++ = '\0'; 739938032Speter } 740038032Speter if (tTd(38, 3)) 740190792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 740238032Speter 740371345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 740438032Speter { 740538032Speter /* Errorhandling */ 740638032Speter char errbuf[ERRBUF_SIZE]; 740738032Speter 740871345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 7409168515Sgshapiro errbuf, sizeof(errbuf)); 741090792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 741190792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 741290792Sgshapiro sm_free(map_p); /* XXX */ 741390792Sgshapiro return false; 741438032Speter } 741538032Speter 741638032Speter if (map->map_app != NULL) 741738032Speter map->map_app = newstr(map->map_app); 741864562Sgshapiro if (map_p->regex_delim != NULL) 741964562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 742038032Speter else 742164562Sgshapiro map_p->regex_delim = defdstr; 742238032Speter 742338032Speter if (!bitset(REG_NOSUB, pflags)) 742438032Speter { 742538032Speter /* substring matching */ 742638032Speter int substrings; 742764562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 742838032Speter 742971345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 743038032Speter 743138032Speter if (tTd(38, 3)) 743290792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 743364562Sgshapiro substrings); 743438032Speter 743538032Speter if (substrings >= MAX_MATCH) 743638032Speter { 743790792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 743890792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 743990792Sgshapiro sm_free(map_p); /* XXX */ 744090792Sgshapiro return false; 744138032Speter } 744238032Speter if (sub_param != NULL && sub_param[0] != '\0') 744338032Speter { 744438032Speter /* optional parameter -sfields */ 744538032Speter if (parse_fields(sub_param, fields, 744638032Speter MAX_MATCH + 1, substrings) == -1) 744790792Sgshapiro return false; 744838032Speter } 744938032Speter else 745038032Speter { 745138032Speter int i; 745238032Speter 745390792Sgshapiro /* set default fields */ 745438032Speter for (i = 0; i < substrings; i++) 745538032Speter fields[i] = i; 745638032Speter fields[i] = END_OF_FIELDS; 745738032Speter } 745838032Speter map_p->regex_subfields = fields; 745938032Speter if (tTd(38, 3)) 746038032Speter { 746138032Speter int *ip; 746238032Speter 746390792Sgshapiro sm_dprintf("regex_map_init: subfields"); 746438032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 746590792Sgshapiro sm_dprintf(" %d", *ip); 746690792Sgshapiro sm_dprintf("\n"); 746738032Speter } 746838032Speter } 746990792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 747090792Sgshapiro return true; 747138032Speter} 747238032Speter 747338032Speterstatic char * 747438032Speterregex_map_rewrite(map, s, slen, av) 747538032Speter MAP *map; 747638032Speter const char *s; 747738032Speter size_t slen; 747838032Speter char **av; 747938032Speter{ 748038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 748138032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 748238032Speter else 748377349Sgshapiro return map_rewrite(map, s, slen, av); 748438032Speter} 748538032Speter 748638032Speterchar * 748738032Speterregex_map_lookup(map, name, av, statp) 748838032Speter MAP *map; 748938032Speter char *name; 749038032Speter char **av; 749138032Speter int *statp; 749238032Speter{ 749338032Speter int reg_res; 749438032Speter struct regex_map *map_p; 749538032Speter regmatch_t pmatch[MAX_MATCH]; 749638032Speter 749738032Speter if (tTd(38, 20)) 749838032Speter { 749938032Speter char **cpp; 750038032Speter 750190792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 750264562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 750390792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 750438032Speter } 750538032Speter 750638032Speter map_p = (struct regex_map *)(map->map_db1); 750771345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 750864562Sgshapiro name, MAX_MATCH, pmatch, 0); 750938032Speter 751038032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 751138032Speter { 751238032Speter /* option -n */ 751338032Speter if (reg_res == REG_NOMATCH) 751490792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 751538032Speter else 751638032Speter return NULL; 751738032Speter } 751838032Speter if (reg_res == REG_NOMATCH) 751938032Speter return NULL; 752038032Speter 752138032Speter if (map_p->regex_subfields != NULL) 752238032Speter { 752338032Speter /* option -s */ 752438032Speter static char retbuf[MAXNAME]; 752538032Speter int fields[MAX_MATCH + 1]; 752690792Sgshapiro bool first = true; 752738032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 752890792Sgshapiro bool quotemode = false, bslashmode = false; 752938032Speter register char *dp, *sp; 753038032Speter char *endp, *ldp; 753138032Speter int *ip; 753238032Speter 753338032Speter dp = retbuf; 753438032Speter ldp = retbuf + sizeof(retbuf) - 1; 753538032Speter 753638032Speter if (av[1] != NULL) 753738032Speter { 753838032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 753971345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 754038032Speter { 754138032Speter *statp = EX_CONFIG; 754238032Speter return NULL; 754338032Speter } 754438032Speter ip = fields; 754538032Speter } 754638032Speter else 754738032Speter ip = map_p->regex_subfields; 754838032Speter 754938032Speter for ( ; *ip != END_OF_FIELDS; ip++) 755038032Speter { 755138032Speter if (!first) 755238032Speter { 755364562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 755438032Speter { 755538032Speter if (dp < ldp) 755638032Speter *dp++ = *sp; 755738032Speter } 755838032Speter } 755938032Speter else 756090792Sgshapiro first = false; 756138032Speter 756271345Sgshapiro if (*ip >= MAX_MATCH || 756371345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 756438032Speter continue; 756538032Speter 756638032Speter sp = name + pmatch[*ip].rm_so; 756738032Speter endp = name + pmatch[*ip].rm_eo; 756838032Speter for (; endp > sp; sp++) 756938032Speter { 757038032Speter if (dp < ldp) 757138032Speter { 757264562Sgshapiro if (bslashmode) 757364562Sgshapiro { 757438032Speter *dp++ = *sp; 757590792Sgshapiro bslashmode = false; 757638032Speter } 757764562Sgshapiro else if (quotemode && *sp != '"' && 757838032Speter *sp != '\\') 757938032Speter { 758038032Speter *dp++ = *sp; 758138032Speter } 758290792Sgshapiro else switch (*dp++ = *sp) 758338032Speter { 758490792Sgshapiro case '\\': 758590792Sgshapiro bslashmode = true; 758638032Speter break; 758738032Speter 758890792Sgshapiro case '(': 758938032Speter cmntcnt++; 759038032Speter break; 759138032Speter 759290792Sgshapiro case ')': 759338032Speter cmntcnt--; 759438032Speter break; 759538032Speter 759690792Sgshapiro case '<': 759738032Speter anglecnt++; 759838032Speter break; 759938032Speter 760090792Sgshapiro case '>': 760138032Speter anglecnt--; 760238032Speter break; 760338032Speter 760490792Sgshapiro case ' ': 760538032Speter spacecnt++; 760638032Speter break; 760738032Speter 760890792Sgshapiro case '"': 760938032Speter quotemode = !quotemode; 761038032Speter break; 761138032Speter } 761238032Speter } 761338032Speter } 761438032Speter } 761538032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 761638032Speter bslashmode || spacecnt != 0) 761738032Speter { 761864562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 761964562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 762064562Sgshapiro map->map_mname, name); 762138032Speter return NULL; 762238032Speter } 762338032Speter 762438032Speter *dp = '\0'; 762538032Speter 762638032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 762738032Speter } 762838032Speter return regex_map_rewrite(map, "", (size_t)0, av); 762938032Speter} 763038032Speter#endif /* MAP_REGEX */ 763190792Sgshapiro/* 763264562Sgshapiro** NSD modules 763364562Sgshapiro*/ 763490792Sgshapiro#if MAP_NSD 763564562Sgshapiro 763664562Sgshapiro# include <ndbm.h> 763764562Sgshapiro# define _DATUM_DEFINED 763864562Sgshapiro# include <ns_api.h> 763964562Sgshapiro 764064562Sgshapirotypedef struct ns_map_list 764164562Sgshapiro{ 764290792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 764390792Sgshapiro char *mapname; 764490792Sgshapiro struct ns_map_list *next; 764564562Sgshapiro} ns_map_list_t; 764664562Sgshapiro 764764562Sgshapirostatic ns_map_t * 764864562Sgshapirons_map_t_find(mapname) 764964562Sgshapiro char *mapname; 765064562Sgshapiro{ 765164562Sgshapiro static ns_map_list_t *ns_maps = NULL; 765264562Sgshapiro ns_map_list_t *ns_map; 765364562Sgshapiro 765464562Sgshapiro /* walk the list of maps looking for the correctly named map */ 765564562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 765664562Sgshapiro { 765764562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 765864562Sgshapiro break; 765964562Sgshapiro } 766064562Sgshapiro 766164562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 766264562Sgshapiro if (ns_map == NULL) 766364562Sgshapiro { 7664168515Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof(*ns_map)); 766564562Sgshapiro ns_map->mapname = newstr(mapname); 7666168515Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof(*ns_map->map)); 7667168515Sgshapiro memset(ns_map->map, '\0', sizeof(*ns_map->map)); 766864562Sgshapiro ns_map->next = ns_maps; 766964562Sgshapiro ns_maps = ns_map; 767064562Sgshapiro } 767164562Sgshapiro return ns_map->map; 767264562Sgshapiro} 767364562Sgshapiro 767464562Sgshapirochar * 767564562Sgshapironsd_map_lookup(map, name, av, statp) 767664562Sgshapiro MAP *map; 767764562Sgshapiro char *name; 767864562Sgshapiro char **av; 767964562Sgshapiro int *statp; 768064562Sgshapiro{ 768171345Sgshapiro int buflen, r; 768264562Sgshapiro char *p; 768364562Sgshapiro ns_map_t *ns_map; 768464562Sgshapiro char keybuf[MAXNAME + 1]; 768564562Sgshapiro char buf[MAXLINE]; 768664562Sgshapiro 768764562Sgshapiro if (tTd(38, 20)) 768890792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 768964562Sgshapiro 769064562Sgshapiro buflen = strlen(name); 7691168515Sgshapiro if (buflen > sizeof(keybuf) - 1) 7692168515Sgshapiro buflen = sizeof(keybuf) - 1; /* XXX simply cut off? */ 769364562Sgshapiro memmove(keybuf, name, buflen); 769464562Sgshapiro keybuf[buflen] = '\0'; 769564562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 769664562Sgshapiro makelower(keybuf); 769764562Sgshapiro 769864562Sgshapiro ns_map = ns_map_t_find(map->map_file); 769964562Sgshapiro if (ns_map == NULL) 770064562Sgshapiro { 770164562Sgshapiro if (tTd(38, 20)) 770290792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 770371345Sgshapiro *statp = EX_UNAVAILABLE; 770464562Sgshapiro return NULL; 770564562Sgshapiro } 770698121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 7707168515Sgshapiro buf, sizeof(buf)); 770871345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 770971345Sgshapiro { 771071345Sgshapiro *statp = EX_TEMPFAIL; 771164562Sgshapiro return NULL; 771271345Sgshapiro } 771377349Sgshapiro if (r == NS_BADREQ 771477349Sgshapiro# ifdef NS_NOPERM 771577349Sgshapiro || r == NS_NOPERM 7716363466Sgshapiro# endif 771777349Sgshapiro ) 771871345Sgshapiro { 771971345Sgshapiro *statp = EX_CONFIG; 772071345Sgshapiro return NULL; 772171345Sgshapiro } 772271345Sgshapiro if (r != NS_SUCCESS) 772371345Sgshapiro { 772471345Sgshapiro *statp = EX_NOTFOUND; 772571345Sgshapiro return NULL; 772671345Sgshapiro } 772764562Sgshapiro 772871345Sgshapiro *statp = EX_OK; 772971345Sgshapiro 773064562Sgshapiro /* Null out trailing \n */ 773164562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 773264562Sgshapiro *p = '\0'; 773364562Sgshapiro 773464562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 773564562Sgshapiro} 773664562Sgshapiro#endif /* MAP_NSD */ 773764562Sgshapiro 773864562Sgshapirochar * 773964562Sgshapiroarith_map_lookup(map, name, av, statp) 774064562Sgshapiro MAP *map; 774164562Sgshapiro char *name; 774264562Sgshapiro char **av; 774364562Sgshapiro int *statp; 774464562Sgshapiro{ 774564562Sgshapiro long r; 774664562Sgshapiro long v[2]; 774790792Sgshapiro bool res = false; 774864562Sgshapiro bool boolres; 774964562Sgshapiro static char result[16]; 775064562Sgshapiro char **cpp; 775164562Sgshapiro 775264562Sgshapiro if (tTd(38, 2)) 775364562Sgshapiro { 775490792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 775564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 775690792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 775764562Sgshapiro } 775864562Sgshapiro r = 0; 775990792Sgshapiro boolres = false; 776064562Sgshapiro cpp = av; 776164562Sgshapiro *statp = EX_OK; 776264562Sgshapiro 776364562Sgshapiro /* 776464562Sgshapiro ** read arguments for arith map 776564562Sgshapiro ** - no check is made whether they are really numbers 776664562Sgshapiro ** - just ignores args after the second 776764562Sgshapiro */ 776890792Sgshapiro 776964562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 777064562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 777164562Sgshapiro 777264562Sgshapiro /* operator and (at least) two operands given? */ 777364562Sgshapiro if (name != NULL && r == 2) 777464562Sgshapiro { 777590792Sgshapiro switch (*name) 777664562Sgshapiro { 777764562Sgshapiro case '|': 777864562Sgshapiro r = v[0] | v[1]; 777964562Sgshapiro break; 778064562Sgshapiro 778164562Sgshapiro case '&': 778264562Sgshapiro r = v[0] & v[1]; 778364562Sgshapiro break; 778464562Sgshapiro 778564562Sgshapiro case '%': 778664562Sgshapiro if (v[1] == 0) 778764562Sgshapiro return NULL; 778864562Sgshapiro r = v[0] % v[1]; 778964562Sgshapiro break; 779064562Sgshapiro case '+': 779164562Sgshapiro r = v[0] + v[1]; 779264562Sgshapiro break; 779364562Sgshapiro 779464562Sgshapiro case '-': 779564562Sgshapiro r = v[0] - v[1]; 779664562Sgshapiro break; 779764562Sgshapiro 779864562Sgshapiro case '*': 779964562Sgshapiro r = v[0] * v[1]; 780064562Sgshapiro break; 780164562Sgshapiro 780264562Sgshapiro case '/': 780364562Sgshapiro if (v[1] == 0) 780464562Sgshapiro return NULL; 780564562Sgshapiro r = v[0] / v[1]; 780664562Sgshapiro break; 780764562Sgshapiro 780864562Sgshapiro case 'l': 780964562Sgshapiro res = v[0] < v[1]; 781090792Sgshapiro boolres = true; 781164562Sgshapiro break; 781264562Sgshapiro 781364562Sgshapiro case '=': 781464562Sgshapiro res = v[0] == v[1]; 781590792Sgshapiro boolres = true; 781664562Sgshapiro break; 781764562Sgshapiro 7818168515Sgshapiro case 'r': 7819168515Sgshapiro r = v[1] - v[0] + 1; 7820168515Sgshapiro if (r <= 0) 7821168515Sgshapiro return NULL; 7822168515Sgshapiro r = get_random() % r + v[0]; 7823168515Sgshapiro break; 7824168515Sgshapiro 782564562Sgshapiro default: 782664562Sgshapiro /* XXX */ 782764562Sgshapiro *statp = EX_CONFIG; 782864562Sgshapiro if (LogLevel > 10) 782964562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 783064562Sgshapiro "arith_map: unknown operator %c", 7831203004Sgshapiro (isascii(*name) && isprint(*name)) ? 7832203004Sgshapiro *name : '?'); 783364562Sgshapiro return NULL; 783464562Sgshapiro } 783564562Sgshapiro if (boolres) 7836168515Sgshapiro (void) sm_snprintf(result, sizeof(result), 783790792Sgshapiro res ? "TRUE" : "FALSE"); 783864562Sgshapiro else 7839168515Sgshapiro (void) sm_snprintf(result, sizeof(result), "%ld", r); 784064562Sgshapiro return result; 784164562Sgshapiro } 784264562Sgshapiro *statp = EX_CONFIG; 784364562Sgshapiro return NULL; 784464562Sgshapiro} 7845132943Sgshapiro 7846261194Sgshapirochar * 7847261194Sgshapiroarpa_map_lookup(map, name, av, statp) 7848261194Sgshapiro MAP *map; 7849261194Sgshapiro char *name; 7850261194Sgshapiro char **av; 7851261194Sgshapiro int *statp; 7852261194Sgshapiro{ 7853261194Sgshapiro int r; 7854261194Sgshapiro char *rval; 7855261194Sgshapiro char result[128]; /* IPv6: 64 + 10 + 1 would be enough */ 7856261194Sgshapiro 7857261194Sgshapiro if (tTd(38, 2)) 7858261194Sgshapiro sm_dprintf("arpa_map_lookup: key '%s'\n", name); 7859261194Sgshapiro *statp = EX_DATAERR; 7860261194Sgshapiro r = 1; 7861261194Sgshapiro memset(result, '\0', sizeof(result)); 7862261194Sgshapiro rval = NULL; 7863261194Sgshapiro 7864261194Sgshapiro# if NETINET6 7865261194Sgshapiro if (sm_strncasecmp(name, "IPv6:", 5) == 0) 7866261194Sgshapiro { 7867261194Sgshapiro struct in6_addr in6_addr; 7868261194Sgshapiro 7869261194Sgshapiro r = anynet_pton(AF_INET6, name, &in6_addr); 7870261194Sgshapiro if (r == 1) 7871261194Sgshapiro { 7872261194Sgshapiro static char hex_digits[] = 7873261194Sgshapiro { '0', '1', '2', '3', '4', '5', '6', '7', '8', 7874261194Sgshapiro '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 7875261194Sgshapiro 7876261194Sgshapiro unsigned char *src; 7877261194Sgshapiro char *dst; 7878261194Sgshapiro int i; 7879261194Sgshapiro 7880261194Sgshapiro src = (unsigned char *) &in6_addr; 7881261194Sgshapiro dst = result; 7882261194Sgshapiro for (i = 15; i >= 0; i--) { 7883261194Sgshapiro *dst++ = hex_digits[src[i] & 0x0f]; 7884261194Sgshapiro *dst++ = '.'; 7885261194Sgshapiro *dst++ = hex_digits[(src[i] >> 4) & 0x0f]; 7886261194Sgshapiro if (i > 0) 7887261194Sgshapiro *dst++ = '.'; 7888261194Sgshapiro } 7889261194Sgshapiro *statp = EX_OK; 7890261194Sgshapiro } 7891261194Sgshapiro } 7892261194Sgshapiro else 7893261194Sgshapiro# endif /* NETINET6 */ 7894261194Sgshapiro# if NETINET 7895261194Sgshapiro { 7896261194Sgshapiro struct in_addr in_addr; 7897261194Sgshapiro 7898285229Sgshapiro r = inet_pton(AF_INET, name, &in_addr); 7899261194Sgshapiro if (r == 1) 7900261194Sgshapiro { 7901261194Sgshapiro unsigned char *src; 7902261194Sgshapiro 7903261194Sgshapiro src = (unsigned char *) &in_addr; 7904261194Sgshapiro (void) snprintf(result, sizeof(result), 7905261194Sgshapiro "%u.%u.%u.%u", 7906261194Sgshapiro src[3], src[2], src[1], src[0]); 7907261194Sgshapiro *statp = EX_OK; 7908261194Sgshapiro } 7909261194Sgshapiro } 7910261194Sgshapiro# endif /* NETINET */ 7911261194Sgshapiro if (r < 0) 7912261194Sgshapiro *statp = EX_UNAVAILABLE; 7913261194Sgshapiro if (tTd(38, 2)) 7914261194Sgshapiro sm_dprintf("arpa_map_lookup: r=%d, result='%s'\n", r, result); 7915261194Sgshapiro if (*statp == EX_OK) 7916261194Sgshapiro { 7917261194Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 7918261194Sgshapiro rval = map_rewrite(map, name, strlen(name), NULL); 7919261194Sgshapiro else 7920261194Sgshapiro rval = map_rewrite(map, result, strlen(result), av); 7921261194Sgshapiro } 7922261194Sgshapiro return rval; 7923261194Sgshapiro} 7924261194Sgshapiro 7925363466Sgshapiro#if _FFR_SETDEBUG_MAP 7926363466Sgshapirochar * 7927363466Sgshapirosetdebug_map_lookup(map, name, av, statp) 7928363466Sgshapiro MAP *map; 7929363466Sgshapiro char *name; 7930363466Sgshapiro char **av; 7931363466Sgshapiro int *statp; 7932363466Sgshapiro{ 7933363466Sgshapiro 7934363466Sgshapiro if (tTd(38, 2)) 7935363466Sgshapiro { 7936363466Sgshapiro char **cpp; 7937363466Sgshapiro 7938363466Sgshapiro sm_dprintf("setdebug_map_lookup: key '%s'\n", name); 7939363466Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 7940363466Sgshapiro sm_dprintf("setdebug_map_lookup: arg '%s'\n", *cpp); 7941363466Sgshapiro } 7942363466Sgshapiro *statp = EX_OK; 7943363466Sgshapiro tTflag(name); 7944363466Sgshapiro return NULL; 7945363466Sgshapiro} 7946363466Sgshapiro#endif 7947363466Sgshapiro 7948363466Sgshapiro#if _FFR_SETOPT_MAP 7949363466Sgshapirochar * 7950363466Sgshapirosetopt_map_lookup(map, name, av, statp) 7951363466Sgshapiro MAP *map; 7952363466Sgshapiro char *name; 7953363466Sgshapiro char **av; 7954363466Sgshapiro int *statp; 7955363466Sgshapiro{ 7956363466Sgshapiro# if !_FFR_SETANYOPT 7957363466Sgshapiro int val; 7958363466Sgshapiro# endif 7959363466Sgshapiro char **cpp; 7960363466Sgshapiro 7961363466Sgshapiro if (tTd(38, 2)) 7962363466Sgshapiro { 7963363466Sgshapiro sm_dprintf("setopt_map_lookup: key '%s'\n", name); 7964363466Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 7965363466Sgshapiro sm_dprintf("setopt_map_lookup: arg '%s'\n", *cpp); 7966363466Sgshapiro } 7967363466Sgshapiro# if _FFR_SETANYOPT 7968363466Sgshapiro /* 7969363466Sgshapiro ** API screwed up... 7970363466Sgshapiro ** first arg is the "short" name and second is the entire string... 7971363466Sgshapiro */ 7972363466Sgshapiro 7973363466Sgshapiro sm_dprintf("setoption: name=%s\n", name); 7974363466Sgshapiro setoption(' ', name, true, false, CurEnv); 7975363466Sgshapiro *statp = EX_OK; 7976363466Sgshapiro return NULL; 7977363466Sgshapiro# else /* _FFR_SETANYOPT */ 7978363466Sgshapiro *statp = EX_CONFIG; 7979363466Sgshapiro 7980363466Sgshapiro cpp = av; 7981363466Sgshapiro if (cpp == NULL || ++cpp == NULL || *cpp == NULL) 7982363466Sgshapiro return NULL; 7983363466Sgshapiro *statp = EX_OK; 7984363466Sgshapiro errno = 0; 7985363466Sgshapiro val = strtol(*cpp, NULL, 0); 7986363466Sgshapiro /* check for valid number? */ 7987363466Sgshapiro 7988363466Sgshapiro /* use a table? */ 7989363466Sgshapiro if (sm_strcasecmp(name, "LogLevel") == 0) 7990363466Sgshapiro { 7991363466Sgshapiro LogLevel = val; 7992363466Sgshapiro sm_dprintf("LogLevel=%d\n", val); 7993363466Sgshapiro return NULL; 7994363466Sgshapiro } 7995363466Sgshapiro# endif /* _FFR_SETANYOPT */ 7996363466Sgshapiro *statp = EX_CONFIG; 7997363466Sgshapiro return NULL; 7998363466Sgshapiro} 7999363466Sgshapiro#endif 8000363466Sgshapiro 8001363466Sgshapiro 8002132943Sgshapiro#if SOCKETMAP 8003132943Sgshapiro 8004132943Sgshapiro# if NETINET || NETINET6 8005132943Sgshapiro# include <arpa/inet.h> 8006363466Sgshapiro# endif 8007132943Sgshapiro 8008132943Sgshapiro# define socket_map_next map_stack[0] 8009132943Sgshapiro 8010132943Sgshapiro/* 8011132943Sgshapiro** SOCKET_MAP_OPEN -- open socket table 8012132943Sgshapiro*/ 8013132943Sgshapiro 8014132943Sgshapirobool 8015132943Sgshapirosocket_map_open(map, mode) 8016132943Sgshapiro MAP *map; 8017132943Sgshapiro int mode; 8018132943Sgshapiro{ 8019132943Sgshapiro STAB *s; 8020132943Sgshapiro int sock = 0; 8021285229Sgshapiro int tmo; 8022132943Sgshapiro SOCKADDR_LEN_T addrlen = 0; 8023132943Sgshapiro int addrno = 0; 8024132943Sgshapiro int save_errno; 8025132943Sgshapiro char *p; 8026132943Sgshapiro char *colon; 8027132943Sgshapiro char *at; 8028132943Sgshapiro struct hostent *hp = NULL; 8029132943Sgshapiro SOCKADDR addr; 8030132943Sgshapiro 8031132943Sgshapiro if (tTd(38, 2)) 8032132943Sgshapiro sm_dprintf("socket_map_open(%s, %s, %d)\n", 8033132943Sgshapiro map->map_mname, map->map_file, mode); 8034132943Sgshapiro 8035132943Sgshapiro mode &= O_ACCMODE; 8036132943Sgshapiro 8037132943Sgshapiro /* sendmail doesn't have the ability to write to SOCKET (yet) */ 8038132943Sgshapiro if (mode != O_RDONLY) 8039132943Sgshapiro { 8040132943Sgshapiro /* issue a pseudo-error message */ 8041132943Sgshapiro errno = SM_EMAPCANTWRITE; 8042132943Sgshapiro return false; 8043132943Sgshapiro } 8044132943Sgshapiro 8045132943Sgshapiro if (*map->map_file == '\0') 8046132943Sgshapiro { 8047132943Sgshapiro syserr("socket map \"%s\": empty or missing socket information", 8048132943Sgshapiro map->map_mname); 8049132943Sgshapiro return false; 8050132943Sgshapiro } 8051132943Sgshapiro 8052132943Sgshapiro s = socket_map_findconn(map->map_file); 8053132943Sgshapiro if (s->s_socketmap != NULL) 8054132943Sgshapiro { 8055132943Sgshapiro /* Copy open connection */ 8056132943Sgshapiro map->map_db1 = s->s_socketmap->map_db1; 8057132943Sgshapiro 8058132943Sgshapiro /* Add this map as head of linked list */ 8059132943Sgshapiro map->socket_map_next = s->s_socketmap; 8060132943Sgshapiro s->s_socketmap = map; 8061132943Sgshapiro 8062132943Sgshapiro if (tTd(38, 2)) 8063132943Sgshapiro sm_dprintf("using cached connection\n"); 8064132943Sgshapiro return true; 8065132943Sgshapiro } 8066132943Sgshapiro 8067132943Sgshapiro if (tTd(38, 2)) 8068132943Sgshapiro sm_dprintf("opening new connection\n"); 8069132943Sgshapiro 8070132943Sgshapiro /* following code is ripped from milter.c */ 8071132943Sgshapiro /* XXX It should be put in a library... */ 8072132943Sgshapiro 8073132943Sgshapiro /* protocol:filename or protocol:port@host */ 8074168515Sgshapiro memset(&addr, '\0', sizeof(addr)); 8075132943Sgshapiro p = map->map_file; 8076132943Sgshapiro colon = strchr(p, ':'); 8077132943Sgshapiro if (colon != NULL) 8078132943Sgshapiro { 8079132943Sgshapiro *colon = '\0'; 8080132943Sgshapiro 8081132943Sgshapiro if (*p == '\0') 8082132943Sgshapiro { 8083132943Sgshapiro# if NETUNIX 8084132943Sgshapiro /* default to AF_UNIX */ 8085132943Sgshapiro addr.sa.sa_family = AF_UNIX; 8086132943Sgshapiro# else /* NETUNIX */ 8087132943Sgshapiro# if NETINET 8088132943Sgshapiro /* default to AF_INET */ 8089132943Sgshapiro addr.sa.sa_family = AF_INET; 8090132943Sgshapiro# else /* NETINET */ 8091132943Sgshapiro# if NETINET6 8092132943Sgshapiro /* default to AF_INET6 */ 8093132943Sgshapiro addr.sa.sa_family = AF_INET6; 8094132943Sgshapiro# else /* NETINET6 */ 8095132943Sgshapiro /* no protocols available */ 8096132943Sgshapiro syserr("socket map \"%s\": no valid socket protocols available", 8097132943Sgshapiro map->map_mname); 8098132943Sgshapiro return false; 8099132943Sgshapiro# endif /* NETINET6 */ 8100132943Sgshapiro# endif /* NETINET */ 8101132943Sgshapiro# endif /* NETUNIX */ 8102132943Sgshapiro } 8103132943Sgshapiro# if NETUNIX 8104132943Sgshapiro else if (sm_strcasecmp(p, "unix") == 0 || 8105132943Sgshapiro sm_strcasecmp(p, "local") == 0) 8106132943Sgshapiro addr.sa.sa_family = AF_UNIX; 8107132943Sgshapiro# endif /* NETUNIX */ 8108132943Sgshapiro# if NETINET 8109132943Sgshapiro else if (sm_strcasecmp(p, "inet") == 0) 8110132943Sgshapiro addr.sa.sa_family = AF_INET; 8111132943Sgshapiro# endif /* NETINET */ 8112132943Sgshapiro# if NETINET6 8113132943Sgshapiro else if (sm_strcasecmp(p, "inet6") == 0) 8114132943Sgshapiro addr.sa.sa_family = AF_INET6; 8115132943Sgshapiro# endif /* NETINET6 */ 8116132943Sgshapiro else 8117132943Sgshapiro { 8118132943Sgshapiro# ifdef EPROTONOSUPPORT 8119132943Sgshapiro errno = EPROTONOSUPPORT; 8120363466Sgshapiro# else 8121132943Sgshapiro errno = EINVAL; 8122132943Sgshapiro# endif /* EPROTONOSUPPORT */ 8123132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 8124132943Sgshapiro map->map_mname, p); 8125132943Sgshapiro return false; 8126132943Sgshapiro } 8127132943Sgshapiro *colon++ = ':'; 8128132943Sgshapiro } 8129132943Sgshapiro else 8130132943Sgshapiro { 8131132943Sgshapiro colon = p; 8132132943Sgshapiro#if NETUNIX 8133132943Sgshapiro /* default to AF_UNIX */ 8134132943Sgshapiro addr.sa.sa_family = AF_UNIX; 8135132943Sgshapiro#else /* NETUNIX */ 8136132943Sgshapiro# if NETINET 8137132943Sgshapiro /* default to AF_INET */ 8138132943Sgshapiro addr.sa.sa_family = AF_INET; 8139132943Sgshapiro# else /* NETINET */ 8140132943Sgshapiro# if NETINET6 8141132943Sgshapiro /* default to AF_INET6 */ 8142132943Sgshapiro addr.sa.sa_family = AF_INET6; 8143132943Sgshapiro# else /* NETINET6 */ 8144132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 8145132943Sgshapiro map->map_mname, p); 8146132943Sgshapiro return false; 8147132943Sgshapiro# endif /* NETINET6 */ 8148132943Sgshapiro# endif /* NETINET */ 8149132943Sgshapiro#endif /* NETUNIX */ 8150132943Sgshapiro } 8151132943Sgshapiro 8152132943Sgshapiro# if NETUNIX 8153132943Sgshapiro if (addr.sa.sa_family == AF_UNIX) 8154132943Sgshapiro { 8155132943Sgshapiro long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 8156132943Sgshapiro 8157132943Sgshapiro at = colon; 8158168515Sgshapiro if (strlen(colon) >= sizeof(addr.sunix.sun_path)) 8159132943Sgshapiro { 8160132943Sgshapiro syserr("socket map \"%s\": local socket name %s too long", 8161132943Sgshapiro map->map_mname, colon); 8162132943Sgshapiro return false; 8163132943Sgshapiro } 8164132943Sgshapiro errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 8165132943Sgshapiro S_IRUSR|S_IWUSR, NULL); 8166132943Sgshapiro 8167132943Sgshapiro if (errno != 0) 8168132943Sgshapiro { 8169132943Sgshapiro /* if not safe, don't create */ 8170132943Sgshapiro syserr("socket map \"%s\": local socket name %s unsafe", 8171132943Sgshapiro map->map_mname, colon); 8172132943Sgshapiro return false; 8173132943Sgshapiro } 8174132943Sgshapiro 8175132943Sgshapiro (void) sm_strlcpy(addr.sunix.sun_path, colon, 8176168515Sgshapiro sizeof(addr.sunix.sun_path)); 8177168515Sgshapiro addrlen = sizeof(struct sockaddr_un); 8178132943Sgshapiro } 8179132943Sgshapiro else 8180132943Sgshapiro# endif /* NETUNIX */ 8181132943Sgshapiro# if NETINET || NETINET6 8182132943Sgshapiro if (false 8183132943Sgshapiro# if NETINET 8184132943Sgshapiro || addr.sa.sa_family == AF_INET 8185363466Sgshapiro# endif 8186132943Sgshapiro# if NETINET6 8187132943Sgshapiro || addr.sa.sa_family == AF_INET6 8188363466Sgshapiro# endif 8189132943Sgshapiro ) 8190132943Sgshapiro { 8191132943Sgshapiro unsigned short port; 8192132943Sgshapiro 8193132943Sgshapiro /* Parse port@host */ 8194132943Sgshapiro at = strchr(colon, '@'); 8195132943Sgshapiro if (at == NULL) 8196132943Sgshapiro { 8197132943Sgshapiro syserr("socket map \"%s\": bad address %s (expected port@host)", 8198132943Sgshapiro map->map_mname, colon); 8199132943Sgshapiro return false; 8200132943Sgshapiro } 8201132943Sgshapiro *at = '\0'; 8202132943Sgshapiro if (isascii(*colon) && isdigit(*colon)) 8203132943Sgshapiro port = htons((unsigned short) atoi(colon)); 8204132943Sgshapiro else 8205132943Sgshapiro { 8206132943Sgshapiro# ifdef NO_GETSERVBYNAME 8207132943Sgshapiro syserr("socket map \"%s\": invalid port number %s", 8208132943Sgshapiro map->map_mname, colon); 8209132943Sgshapiro return false; 8210132943Sgshapiro# else /* NO_GETSERVBYNAME */ 8211132943Sgshapiro register struct servent *sp; 8212132943Sgshapiro 8213132943Sgshapiro sp = getservbyname(colon, "tcp"); 8214132943Sgshapiro if (sp == NULL) 8215132943Sgshapiro { 8216132943Sgshapiro syserr("socket map \"%s\": unknown port name %s", 8217132943Sgshapiro map->map_mname, colon); 8218132943Sgshapiro return false; 8219132943Sgshapiro } 8220132943Sgshapiro port = sp->s_port; 8221132943Sgshapiro# endif /* NO_GETSERVBYNAME */ 8222132943Sgshapiro } 8223132943Sgshapiro *at++ = '@'; 8224132943Sgshapiro if (*at == '[') 8225132943Sgshapiro { 8226132943Sgshapiro char *end; 8227132943Sgshapiro 8228132943Sgshapiro end = strchr(at, ']'); 8229132943Sgshapiro if (end != NULL) 8230132943Sgshapiro { 8231132943Sgshapiro bool found = false; 8232132943Sgshapiro# if NETINET 8233132943Sgshapiro unsigned long hid = INADDR_NONE; 8234363466Sgshapiro# endif 8235132943Sgshapiro# if NETINET6 8236132943Sgshapiro struct sockaddr_in6 hid6; 8237363466Sgshapiro# endif 8238132943Sgshapiro 8239132943Sgshapiro *end = '\0'; 8240132943Sgshapiro# if NETINET 8241132943Sgshapiro if (addr.sa.sa_family == AF_INET && 8242132943Sgshapiro (hid = inet_addr(&at[1])) != INADDR_NONE) 8243132943Sgshapiro { 8244132943Sgshapiro addr.sin.sin_addr.s_addr = hid; 8245132943Sgshapiro addr.sin.sin_port = port; 8246132943Sgshapiro found = true; 8247132943Sgshapiro } 8248132943Sgshapiro# endif /* NETINET */ 8249132943Sgshapiro# if NETINET6 8250168515Sgshapiro (void) memset(&hid6, '\0', sizeof(hid6)); 8251132943Sgshapiro if (addr.sa.sa_family == AF_INET6 && 8252132943Sgshapiro anynet_pton(AF_INET6, &at[1], 8253132943Sgshapiro &hid6.sin6_addr) == 1) 8254132943Sgshapiro { 8255132943Sgshapiro addr.sin6.sin6_addr = hid6.sin6_addr; 8256132943Sgshapiro addr.sin6.sin6_port = port; 8257132943Sgshapiro found = true; 8258132943Sgshapiro } 8259132943Sgshapiro# endif /* NETINET6 */ 8260132943Sgshapiro *end = ']'; 8261132943Sgshapiro if (!found) 8262132943Sgshapiro { 8263132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 8264132943Sgshapiro map->map_mname, at); 8265132943Sgshapiro return false; 8266132943Sgshapiro } 8267132943Sgshapiro } 8268132943Sgshapiro else 8269132943Sgshapiro { 8270132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 8271132943Sgshapiro map->map_mname, at); 8272132943Sgshapiro return false; 8273132943Sgshapiro } 8274132943Sgshapiro } 8275132943Sgshapiro else 8276132943Sgshapiro { 8277132943Sgshapiro hp = sm_gethostbyname(at, addr.sa.sa_family); 8278132943Sgshapiro if (hp == NULL) 8279132943Sgshapiro { 8280132943Sgshapiro syserr("socket map \"%s\": Unknown host name %s", 8281132943Sgshapiro map->map_mname, at); 8282132943Sgshapiro return false; 8283132943Sgshapiro } 8284132943Sgshapiro addr.sa.sa_family = hp->h_addrtype; 8285132943Sgshapiro switch (hp->h_addrtype) 8286132943Sgshapiro { 8287132943Sgshapiro# if NETINET 8288132943Sgshapiro case AF_INET: 8289132943Sgshapiro memmove(&addr.sin.sin_addr, 8290132943Sgshapiro hp->h_addr, INADDRSZ); 8291132943Sgshapiro addr.sin.sin_port = port; 8292168515Sgshapiro addrlen = sizeof(struct sockaddr_in); 8293132943Sgshapiro addrno = 1; 8294132943Sgshapiro break; 8295132943Sgshapiro# endif /* NETINET */ 8296132943Sgshapiro 8297132943Sgshapiro# if NETINET6 8298132943Sgshapiro case AF_INET6: 8299132943Sgshapiro memmove(&addr.sin6.sin6_addr, 8300132943Sgshapiro hp->h_addr, IN6ADDRSZ); 8301132943Sgshapiro addr.sin6.sin6_port = port; 8302168515Sgshapiro addrlen = sizeof(struct sockaddr_in6); 8303132943Sgshapiro addrno = 1; 8304132943Sgshapiro break; 8305132943Sgshapiro# endif /* NETINET6 */ 8306132943Sgshapiro 8307132943Sgshapiro default: 8308132943Sgshapiro syserr("socket map \"%s\": Unknown protocol for %s (%d)", 8309132943Sgshapiro map->map_mname, at, hp->h_addrtype); 8310132943Sgshapiro# if NETINET6 8311132943Sgshapiro freehostent(hp); 8312363466Sgshapiro# endif 8313132943Sgshapiro return false; 8314132943Sgshapiro } 8315132943Sgshapiro } 8316132943Sgshapiro } 8317132943Sgshapiro else 8318132943Sgshapiro# endif /* NETINET || NETINET6 */ 8319132943Sgshapiro { 8320132943Sgshapiro syserr("socket map \"%s\": unknown socket protocol", 8321132943Sgshapiro map->map_mname); 8322132943Sgshapiro return false; 8323132943Sgshapiro } 8324132943Sgshapiro 8325132943Sgshapiro /* nope, actually connecting */ 8326132943Sgshapiro for (;;) 8327132943Sgshapiro { 8328132943Sgshapiro sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 8329132943Sgshapiro if (sock < 0) 8330132943Sgshapiro { 8331132943Sgshapiro save_errno = errno; 8332132943Sgshapiro if (tTd(38, 5)) 8333132943Sgshapiro sm_dprintf("socket map \"%s\": error creating socket: %s\n", 8334132943Sgshapiro map->map_mname, 8335132943Sgshapiro sm_errstring(save_errno)); 8336132943Sgshapiro# if NETINET6 8337132943Sgshapiro if (hp != NULL) 8338132943Sgshapiro freehostent(hp); 8339132943Sgshapiro# endif /* NETINET6 */ 8340132943Sgshapiro return false; 8341132943Sgshapiro } 8342132943Sgshapiro 8343132943Sgshapiro if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 8344132943Sgshapiro break; 8345132943Sgshapiro 8346132943Sgshapiro /* couldn't connect.... try next address */ 8347132943Sgshapiro save_errno = errno; 8348132943Sgshapiro p = CurHostName; 8349132943Sgshapiro CurHostName = at; 8350132943Sgshapiro if (tTd(38, 5)) 8351132943Sgshapiro sm_dprintf("socket_open (%s): open %s failed: %s\n", 8352132943Sgshapiro map->map_mname, at, sm_errstring(save_errno)); 8353132943Sgshapiro CurHostName = p; 8354132943Sgshapiro (void) close(sock); 8355132943Sgshapiro 8356132943Sgshapiro /* try next address */ 8357132943Sgshapiro if (hp != NULL && hp->h_addr_list[addrno] != NULL) 8358132943Sgshapiro { 8359132943Sgshapiro switch (addr.sa.sa_family) 8360132943Sgshapiro { 8361132943Sgshapiro# if NETINET 8362132943Sgshapiro case AF_INET: 8363132943Sgshapiro memmove(&addr.sin.sin_addr, 8364132943Sgshapiro hp->h_addr_list[addrno++], 8365132943Sgshapiro INADDRSZ); 8366132943Sgshapiro break; 8367132943Sgshapiro# endif /* NETINET */ 8368132943Sgshapiro 8369132943Sgshapiro# if NETINET6 8370132943Sgshapiro case AF_INET6: 8371132943Sgshapiro memmove(&addr.sin6.sin6_addr, 8372132943Sgshapiro hp->h_addr_list[addrno++], 8373132943Sgshapiro IN6ADDRSZ); 8374132943Sgshapiro break; 8375132943Sgshapiro# endif /* NETINET6 */ 8376132943Sgshapiro 8377132943Sgshapiro default: 8378132943Sgshapiro if (tTd(38, 5)) 8379132943Sgshapiro sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 8380132943Sgshapiro map->map_mname, at, 8381132943Sgshapiro hp->h_addrtype); 8382132943Sgshapiro# if NETINET6 8383132943Sgshapiro freehostent(hp); 8384363466Sgshapiro# endif 8385132943Sgshapiro return false; 8386132943Sgshapiro } 8387132943Sgshapiro continue; 8388132943Sgshapiro } 8389132943Sgshapiro p = CurHostName; 8390132943Sgshapiro CurHostName = at; 8391132943Sgshapiro if (tTd(38, 5)) 8392132943Sgshapiro sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 8393132943Sgshapiro map->map_mname, sm_errstring(save_errno)); 8394132943Sgshapiro CurHostName = p; 8395132943Sgshapiro# if NETINET6 8396132943Sgshapiro if (hp != NULL) 8397132943Sgshapiro freehostent(hp); 8398363466Sgshapiro# endif 8399132943Sgshapiro return false; 8400132943Sgshapiro } 8401132943Sgshapiro# if NETINET6 8402132943Sgshapiro if (hp != NULL) 8403132943Sgshapiro { 8404132943Sgshapiro freehostent(hp); 8405132943Sgshapiro hp = NULL; 8406132943Sgshapiro } 8407132943Sgshapiro# endif /* NETINET6 */ 8408132943Sgshapiro if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 8409132943Sgshapiro SM_TIME_DEFAULT, 8410132943Sgshapiro (void *) &sock, 8411132943Sgshapiro SM_IO_RDWR, 8412132943Sgshapiro NULL)) == NULL) 8413132943Sgshapiro { 8414132943Sgshapiro close(sock); 8415132943Sgshapiro if (tTd(38, 2)) 8416132943Sgshapiro sm_dprintf("socket_open (%s): failed to create stream: %s\n", 8417132943Sgshapiro map->map_mname, sm_errstring(errno)); 8418132943Sgshapiro return false; 8419132943Sgshapiro } 8420132943Sgshapiro 8421285229Sgshapiro tmo = map->map_timeout; 8422285229Sgshapiro if (tmo == 0) 8423285229Sgshapiro tmo = 30000; /* default: 30s */ 8424285229Sgshapiro else 8425285229Sgshapiro tmo *= 1000; /* s -> ms */ 8426285229Sgshapiro sm_io_setinfo(map->map_db1, SM_IO_WHAT_TIMEOUT, &tmo); 8427285229Sgshapiro 8428132943Sgshapiro /* Save connection for reuse */ 8429132943Sgshapiro s->s_socketmap = map; 8430132943Sgshapiro return true; 8431132943Sgshapiro} 8432132943Sgshapiro 8433132943Sgshapiro/* 8434132943Sgshapiro** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 8435132943Sgshapiro** 8436132943Sgshapiro** Cache SOCKET connections based on the connection specifier 8437132943Sgshapiro** and PID so we don't have multiple connections open to 8438132943Sgshapiro** the same server for different maps. Need a separate connection 8439132943Sgshapiro** per PID since a parent process may close the map before the 8440132943Sgshapiro** child is done with it. 8441132943Sgshapiro** 8442132943Sgshapiro** Parameters: 8443132943Sgshapiro** conn -- SOCKET map connection specifier 8444132943Sgshapiro** 8445132943Sgshapiro** Returns: 8446132943Sgshapiro** Symbol table entry for the SOCKET connection. 8447132943Sgshapiro*/ 8448132943Sgshapiro 8449132943Sgshapirostatic STAB * 8450132943Sgshapirosocket_map_findconn(conn) 8451132943Sgshapiro const char *conn; 8452132943Sgshapiro{ 8453132943Sgshapiro char *nbuf; 8454132943Sgshapiro STAB *SM_NONVOLATILE s = NULL; 8455132943Sgshapiro 8456132943Sgshapiro nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 8457132943Sgshapiro SM_TRY 8458132943Sgshapiro s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 8459132943Sgshapiro SM_FINALLY 8460132943Sgshapiro sm_free(nbuf); 8461132943Sgshapiro SM_END_TRY 8462132943Sgshapiro return s; 8463132943Sgshapiro} 8464132943Sgshapiro 8465132943Sgshapiro/* 8466132943Sgshapiro** SOCKET_MAP_CLOSE -- close the socket 8467132943Sgshapiro*/ 8468132943Sgshapiro 8469132943Sgshapirovoid 8470132943Sgshapirosocket_map_close(map) 8471132943Sgshapiro MAP *map; 8472132943Sgshapiro{ 8473132943Sgshapiro STAB *s; 8474132943Sgshapiro MAP *smap; 8475132943Sgshapiro 8476132943Sgshapiro if (tTd(38, 20)) 8477132943Sgshapiro sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 8478132943Sgshapiro (long) CurrentPid); 8479132943Sgshapiro 8480132943Sgshapiro /* Check if already closed */ 8481132943Sgshapiro if (map->map_db1 == NULL) 8482132943Sgshapiro { 8483132943Sgshapiro if (tTd(38, 20)) 8484132943Sgshapiro sm_dprintf("socket_map_close(%s) already closed\n", 8485132943Sgshapiro map->map_file); 8486132943Sgshapiro return; 8487132943Sgshapiro } 8488132943Sgshapiro sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 8489132943Sgshapiro 8490132943Sgshapiro /* Mark all the maps that share the connection as closed */ 8491132943Sgshapiro s = socket_map_findconn(map->map_file); 8492132943Sgshapiro smap = s->s_socketmap; 8493132943Sgshapiro while (smap != NULL) 8494132943Sgshapiro { 8495132943Sgshapiro MAP *next; 8496132943Sgshapiro 8497132943Sgshapiro if (tTd(38, 2) && smap != map) 8498132943Sgshapiro sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 8499132943Sgshapiro map->map_mname, smap->map_mname); 8500132943Sgshapiro 8501132943Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 8502132943Sgshapiro smap->map_db1 = NULL; 8503132943Sgshapiro next = smap->socket_map_next; 8504132943Sgshapiro smap->socket_map_next = NULL; 8505132943Sgshapiro smap = next; 8506132943Sgshapiro } 8507132943Sgshapiro s->s_socketmap = NULL; 8508132943Sgshapiro} 8509132943Sgshapiro 8510132943Sgshapiro/* 8511132943Sgshapiro** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 8512132943Sgshapiro*/ 8513132943Sgshapiro 8514132943Sgshapirochar * 8515132943Sgshapirosocket_map_lookup(map, name, av, statp) 8516132943Sgshapiro MAP *map; 8517132943Sgshapiro char *name; 8518132943Sgshapiro char **av; 8519132943Sgshapiro int *statp; 8520132943Sgshapiro{ 8521132943Sgshapiro unsigned int nettolen, replylen, recvlen; 8522363466Sgshapiro int ret; 8523147078Sgshapiro char *replybuf, *rval, *value, *status, *key; 8524132943Sgshapiro SM_FILE_T *f; 8525147078Sgshapiro char keybuf[MAXNAME + 1]; 8526132943Sgshapiro 8527132943Sgshapiro replybuf = NULL; 8528132943Sgshapiro rval = NULL; 8529132943Sgshapiro f = (SM_FILE_T *)map->map_db1; 8530132943Sgshapiro if (tTd(38, 20)) 8531132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s) %s\n", 8532132943Sgshapiro map->map_mname, name, map->map_file); 8533132943Sgshapiro 8534147078Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 8535147078Sgshapiro { 8536147078Sgshapiro nettolen = strlen(name); 8537168515Sgshapiro if (nettolen > sizeof(keybuf) - 1) 8538168515Sgshapiro nettolen = sizeof(keybuf) - 1; 8539147078Sgshapiro memmove(keybuf, name, nettolen); 8540147078Sgshapiro keybuf[nettolen] = '\0'; 8541147078Sgshapiro makelower(keybuf); 8542147078Sgshapiro key = keybuf; 8543147078Sgshapiro } 8544147078Sgshapiro else 8545147078Sgshapiro key = name; 8546147078Sgshapiro 8547147078Sgshapiro nettolen = strlen(map->map_mname) + 1 + strlen(key); 8548132943Sgshapiro SM_ASSERT(nettolen > strlen(map->map_mname)); 8549147078Sgshapiro SM_ASSERT(nettolen > strlen(key)); 8550132943Sgshapiro if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 8551147078Sgshapiro nettolen, map->map_mname, key) == SM_IO_EOF) || 8552132943Sgshapiro (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 8553132943Sgshapiro (sm_io_error(f))) 8554132943Sgshapiro { 8555132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 8556132943Sgshapiro map->map_mname); 8557132943Sgshapiro *statp = EX_TEMPFAIL; 8558132943Sgshapiro goto errcl; 8559132943Sgshapiro } 8560132943Sgshapiro 8561363466Sgshapiro if ((ret = sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen)) != 1) 8562132943Sgshapiro { 8563285229Sgshapiro if (errno == EAGAIN) 8564285229Sgshapiro { 8565285229Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): read timeout", 8566285229Sgshapiro map->map_mname); 8567285229Sgshapiro } 8568363466Sgshapiro else if (SM_IO_EOF == ret) 8569363466Sgshapiro { 8570363466Sgshapiro if (LogLevel > 9) 8571363466Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 8572363466Sgshapiro "socket_map_lookup(%s): EOF", 8573363466Sgshapiro map->map_mname); 8574363466Sgshapiro } 8575285229Sgshapiro else 8576285229Sgshapiro { 8577285229Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply %d", 8578285229Sgshapiro map->map_mname, errno); 8579285229Sgshapiro } 8580132943Sgshapiro *statp = EX_TEMPFAIL; 8581132943Sgshapiro goto errcl; 8582132943Sgshapiro } 8583132943Sgshapiro if (replylen > SOCKETMAP_MAXL) 8584132943Sgshapiro { 8585132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 8586132943Sgshapiro map->map_mname, replylen); 8587132943Sgshapiro *statp = EX_TEMPFAIL; 8588132943Sgshapiro goto errcl; 8589132943Sgshapiro } 8590132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 8591132943Sgshapiro { 8592132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 8593132943Sgshapiro map->map_mname); 8594132943Sgshapiro *statp = EX_TEMPFAIL; 8595132943Sgshapiro goto error; 8596132943Sgshapiro } 8597132943Sgshapiro 8598132943Sgshapiro replybuf = (char *) sm_malloc(replylen + 1); 8599132943Sgshapiro if (replybuf == NULL) 8600132943Sgshapiro { 8601132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 8602132943Sgshapiro map->map_mname, replylen + 1); 8603132943Sgshapiro *statp = EX_OSERR; 8604132943Sgshapiro goto error; 8605132943Sgshapiro } 8606132943Sgshapiro 8607132943Sgshapiro recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 8608132943Sgshapiro if (recvlen < replylen) 8609132943Sgshapiro { 8610132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 8611132943Sgshapiro map->map_mname, recvlen, replylen); 8612132943Sgshapiro *statp = EX_TEMPFAIL; 8613132943Sgshapiro goto errcl; 8614132943Sgshapiro } 8615132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 8616132943Sgshapiro { 8617132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 8618132943Sgshapiro map->map_mname); 8619132943Sgshapiro *statp = EX_TEMPFAIL; 8620132943Sgshapiro goto errcl; 8621132943Sgshapiro } 8622132943Sgshapiro status = replybuf; 8623132943Sgshapiro replybuf[recvlen] = '\0'; 8624132943Sgshapiro value = strchr(replybuf, ' '); 8625132943Sgshapiro if (value != NULL) 8626132943Sgshapiro { 8627132943Sgshapiro *value = '\0'; 8628132943Sgshapiro value++; 8629132943Sgshapiro } 8630132943Sgshapiro if (strcmp(status, "OK") == 0) 8631132943Sgshapiro { 8632132943Sgshapiro *statp = EX_OK; 8633132943Sgshapiro 8634132943Sgshapiro /* collect the return value */ 8635132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 8636147078Sgshapiro rval = map_rewrite(map, key, strlen(key), NULL); 8637132943Sgshapiro else 8638132943Sgshapiro rval = map_rewrite(map, value, strlen(value), av); 8639132943Sgshapiro } 8640132943Sgshapiro else if (strcmp(status, "NOTFOUND") == 0) 8641132943Sgshapiro { 8642132943Sgshapiro *statp = EX_NOTFOUND; 8643132943Sgshapiro if (tTd(38, 20)) 8644132943Sgshapiro sm_dprintf("socket_map_lookup(%s): %s not found\n", 8645147078Sgshapiro map->map_mname, key); 8646132943Sgshapiro } 8647132943Sgshapiro else 8648132943Sgshapiro { 8649132943Sgshapiro if (tTd(38, 5)) 8650132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 8651147078Sgshapiro map->map_mname, key, status, 8652132943Sgshapiro value ? value : ""); 8653132943Sgshapiro if ((strcmp(status, "TEMP") == 0) || 8654132943Sgshapiro (strcmp(status, "TIMEOUT") == 0)) 8655132943Sgshapiro *statp = EX_TEMPFAIL; 8656132943Sgshapiro else if(strcmp(status, "PERM") == 0) 8657132943Sgshapiro *statp = EX_UNAVAILABLE; 8658132943Sgshapiro else 8659132943Sgshapiro *statp = EX_PROTOCOL; 8660132943Sgshapiro } 8661132943Sgshapiro 8662132943Sgshapiro if (replybuf != NULL) 8663132943Sgshapiro sm_free(replybuf); 8664132943Sgshapiro return rval; 8665132943Sgshapiro 8666132943Sgshapiro errcl: 8667132943Sgshapiro socket_map_close(map); 8668132943Sgshapiro error: 8669132943Sgshapiro if (replybuf != NULL) 8670132943Sgshapiro sm_free(replybuf); 8671132943Sgshapiro return rval; 8672132943Sgshapiro} 8673132943Sgshapiro#endif /* SOCKETMAP */ 8674