map.c revision 168515
138032Speter/* 2168515Sgshapiro * Copyright (c) 1998-2006 Sendmail, 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 16168515SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.696 2007/04/03 21:33:14 ca Exp $") 1764562Sgshapiro 1890792Sgshapiro#if LDAPMAP 1990792Sgshapiro# include <sm/ldap.h> 2090792Sgshapiro#endif /* LDAPMAP */ 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" 3364562Sgshapiro#endif /* NEWDB */ 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 */ 3964562Sgshapiro# endif /* NDBM */ 4064562Sgshapiro#endif /* NIS */ 4138032Speter 42168515Sgshapiro#include "map.h" 43168515Sgshapiro 4490792Sgshapiro#if NEWDB 4564562Sgshapiro# if DB_VERSION_MAJOR < 2 4664562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); 4764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 4864562Sgshapiro# if DB_VERSION_MAJOR == 2 4964562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); 5064562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 5164562Sgshapiro# if DB_VERSION_MAJOR > 2 5264562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, void **)); 5364562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 5464562Sgshapiro#endif /* NEWDB */ 5573188Sgshapirostatic bool extract_canonname __P((char *, char *, char *, char[], int)); 5690792Sgshapirostatic void map_close __P((STAB *, int)); 5790792Sgshapirostatic void map_init __P((STAB *, int)); 5864562Sgshapiro#ifdef LDAPMAP 5990792Sgshapirostatic STAB * ldapmap_findconn __P((SM_LDAP_STRUCT *)); 6064562Sgshapiro#endif /* LDAPMAP */ 6190792Sgshapiro#if NISPLUS 6264562Sgshapirostatic bool nisplus_getcanonname __P((char *, int, int *)); 6364562Sgshapiro#endif /* NISPLUS */ 6490792Sgshapiro#if NIS 6564562Sgshapirostatic bool nis_getcanonname __P((char *, int, int *)); 6664562Sgshapiro#endif /* NIS */ 6764562Sgshapiro#if NETINFO 6864562Sgshapirostatic bool ni_getcanonname __P((char *, int, int *)); 6964562Sgshapiro#endif /* NETINFO */ 7064562Sgshapirostatic bool text_getcanonname __P((char *, int, int *)); 71132943Sgshapiro#if SOCKETMAP 72132943Sgshapirostatic STAB *socket_map_findconn __P((const char*)); 7364562Sgshapiro 74132943Sgshapiro/* XXX arbitrary limit for sanity */ 75132943Sgshapiro# define SOCKETMAP_MAXL 1000000 76132943Sgshapiro#endif /* SOCKETMAP */ 77132943Sgshapiro 7890792Sgshapiro/* default error message for trying to open a map in write mode */ 7990792Sgshapiro#ifdef ENOSYS 8090792Sgshapiro# define SM_EMAPCANTWRITE ENOSYS 8190792Sgshapiro#else /* ENOSYS */ 8290792Sgshapiro# ifdef EFTYPE 8390792Sgshapiro# define SM_EMAPCANTWRITE EFTYPE 8490792Sgshapiro# else /* EFTYPE */ 8590792Sgshapiro# define SM_EMAPCANTWRITE ENXIO 8690792Sgshapiro# endif /* EFTYPE */ 8790792Sgshapiro#endif /* ENOSYS */ 8890792Sgshapiro 8938032Speter/* 9038032Speter** MAP.C -- implementations for various map classes. 9138032Speter** 9238032Speter** Each map class implements a series of functions: 9338032Speter** 9438032Speter** bool map_parse(MAP *map, char *args) 9590792Sgshapiro** Parse the arguments from the config file. Return true 9690792Sgshapiro** if they were ok, false otherwise. Fill in map with the 9738032Speter** values. 9838032Speter** 9938032Speter** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 10038032Speter** Look up the key in the given map. If found, do any 10138032Speter** rewriting the map wants (including "args" if desired) 10238032Speter** and return the value. Set *pstat to the appropriate status 10338032Speter** on error and return NULL. Args will be NULL if called 10438032Speter** from the alias routines, although this should probably 10538032Speter** not be relied upon. It is suggested you call map_rewrite 10638032Speter** to return the results -- it takes care of null termination 10738032Speter** and uses a dynamically expanded buffer as needed. 10838032Speter** 10938032Speter** void map_store(MAP *map, char *key, char *value) 11038032Speter** Store the key:value pair in the map. 11138032Speter** 11238032Speter** bool map_open(MAP *map, int mode) 11338032Speter** Open the map for the indicated mode. Mode should 11490792Sgshapiro** be either O_RDONLY or O_RDWR. Return true if it 11590792Sgshapiro** was opened successfully, false otherwise. If the open 11690792Sgshapiro** failed and the MF_OPTIONAL flag is not set, it should 11738032Speter** also print an error. If the MF_ALIAS bit is set 11838032Speter** and this map class understands the @:@ convention, it 11938032Speter** should call aliaswait() before returning. 12038032Speter** 12138032Speter** void map_close(MAP *map) 12238032Speter** Close the map. 12338032Speter** 12438032Speter** This file also includes the implementation for getcanonname. 12538032Speter** It is currently implemented in a pretty ad-hoc manner; it ought 12638032Speter** to be more properly integrated into the map structure. 12738032Speter*/ 12838032Speter 12938032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 13038032Speter# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 13164562Sgshapiro#else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 13238032Speter# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 13364562Sgshapiro#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 13438032Speter 13590792Sgshapiro/* 13638032Speter** MAP_PARSEARGS -- parse config line arguments for database lookup 13738032Speter** 13838032Speter** This is a generic version of the map_parse method. 13938032Speter** 14038032Speter** Parameters: 14138032Speter** map -- the map being initialized. 14238032Speter** ap -- a pointer to the args on the config line. 14338032Speter** 14438032Speter** Returns: 14590792Sgshapiro** true -- if everything parsed OK. 14690792Sgshapiro** false -- otherwise. 14738032Speter** 14838032Speter** Side Effects: 14938032Speter** null terminates the filename; stores it in map 15038032Speter*/ 15138032Speter 15238032Speterbool 15338032Spetermap_parseargs(map, ap) 15438032Speter MAP *map; 15538032Speter char *ap; 15638032Speter{ 15738032Speter register char *p = ap; 15838032Speter 15964562Sgshapiro /* 16090792Sgshapiro ** There is no check whether there is really an argument, 16190792Sgshapiro ** but that's not important enough to warrant extra code. 16264562Sgshapiro */ 16390792Sgshapiro 16490792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 16564562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 16638032Speter for (;;) 16738032Speter { 16838032Speter while (isascii(*p) && isspace(*p)) 16938032Speter p++; 17038032Speter if (*p != '-') 17138032Speter break; 17238032Speter switch (*++p) 17338032Speter { 17438032Speter case 'N': 17538032Speter map->map_mflags |= MF_INCLNULL; 17638032Speter map->map_mflags &= ~MF_TRY0NULL; 17738032Speter break; 17838032Speter 17938032Speter case 'O': 18038032Speter map->map_mflags &= ~MF_TRY1NULL; 18138032Speter break; 18238032Speter 18338032Speter case 'o': 18438032Speter map->map_mflags |= MF_OPTIONAL; 18538032Speter break; 18638032Speter 18738032Speter case 'f': 18838032Speter map->map_mflags |= MF_NOFOLDCASE; 18938032Speter break; 19038032Speter 19138032Speter case 'm': 19238032Speter map->map_mflags |= MF_MATCHONLY; 19338032Speter break; 19438032Speter 19538032Speter case 'A': 19638032Speter map->map_mflags |= MF_APPEND; 19738032Speter break; 19838032Speter 19938032Speter case 'q': 20038032Speter map->map_mflags |= MF_KEEPQUOTES; 20138032Speter break; 20238032Speter 20338032Speter case 'a': 20438032Speter map->map_app = ++p; 20538032Speter break; 20638032Speter 20738032Speter case 'T': 20838032Speter map->map_tapp = ++p; 20938032Speter break; 21038032Speter 21138032Speter case 'k': 21238032Speter while (isascii(*++p) && isspace(*p)) 21338032Speter continue; 21438032Speter map->map_keycolnm = p; 21538032Speter break; 21638032Speter 21738032Speter case 'v': 21838032Speter while (isascii(*++p) && isspace(*p)) 21938032Speter continue; 22038032Speter map->map_valcolnm = p; 22138032Speter break; 22238032Speter 22338032Speter case 'z': 22438032Speter if (*++p != '\\') 22538032Speter map->map_coldelim = *p; 22638032Speter else 22738032Speter { 22838032Speter switch (*++p) 22938032Speter { 23038032Speter case 'n': 23138032Speter map->map_coldelim = '\n'; 23238032Speter break; 23338032Speter 23438032Speter case 't': 23538032Speter map->map_coldelim = '\t'; 23638032Speter break; 23738032Speter 23838032Speter default: 23938032Speter map->map_coldelim = '\\'; 24038032Speter } 24138032Speter } 24238032Speter break; 24338032Speter 24438032Speter case 't': 24538032Speter map->map_mflags |= MF_NODEFER; 24638032Speter break; 24738032Speter 24864562Sgshapiro 24964562Sgshapiro case 'S': 25064562Sgshapiro map->map_spacesub = *++p; 25138032Speter break; 25238032Speter 25364562Sgshapiro case 'D': 25464562Sgshapiro map->map_mflags |= MF_DEFER; 25538032Speter break; 25664562Sgshapiro 25764562Sgshapiro default: 25864562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 25964562Sgshapiro break; 26038032Speter } 26138032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 26238032Speter p++; 26338032Speter if (*p != '\0') 26438032Speter *p++ = '\0'; 26538032Speter } 26638032Speter if (map->map_app != NULL) 26738032Speter map->map_app = newstr(map->map_app); 26838032Speter if (map->map_tapp != NULL) 26938032Speter map->map_tapp = newstr(map->map_tapp); 27038032Speter if (map->map_keycolnm != NULL) 27138032Speter map->map_keycolnm = newstr(map->map_keycolnm); 27238032Speter if (map->map_valcolnm != NULL) 27338032Speter map->map_valcolnm = newstr(map->map_valcolnm); 27438032Speter 27538032Speter if (*p != '\0') 27638032Speter { 27738032Speter map->map_file = p; 27838032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 27938032Speter p++; 28038032Speter if (*p != '\0') 28138032Speter *p++ = '\0'; 28238032Speter map->map_file = newstr(map->map_file); 28338032Speter } 28438032Speter 28538032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 28638032Speter p++; 28738032Speter if (*p != '\0') 28838032Speter map->map_rebuild = newstr(p); 28938032Speter 29038032Speter if (map->map_file == NULL && 29138032Speter !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 29238032Speter { 29338032Speter syserr("No file name for %s map %s", 29438032Speter map->map_class->map_cname, map->map_mname); 29590792Sgshapiro return false; 29638032Speter } 29790792Sgshapiro return true; 29838032Speter} 29990792Sgshapiro/* 30038032Speter** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 30138032Speter** 30238032Speter** It also adds the map_app string. It can be used as a utility 30338032Speter** in the map_lookup method. 30438032Speter** 30538032Speter** Parameters: 30638032Speter** map -- the map that causes this. 30738032Speter** s -- the string to rewrite, NOT necessarily null terminated. 30838032Speter** slen -- the length of s. 30938032Speter** av -- arguments to interpolate into buf. 31038032Speter** 31138032Speter** Returns: 31238032Speter** Pointer to rewritten result. This is static data that 31338032Speter** should be copied if it is to be saved! 31438032Speter*/ 31538032Speter 31638032Speterchar * 31738032Spetermap_rewrite(map, s, slen, av) 31838032Speter register MAP *map; 31938032Speter register const char *s; 32038032Speter size_t slen; 32138032Speter char **av; 32238032Speter{ 32338032Speter register char *bp; 32438032Speter register char c; 32538032Speter char **avp; 32638032Speter register char *ap; 32738032Speter size_t l; 32838032Speter size_t len; 32938032Speter static size_t buflen = 0; 33038032Speter static char *buf = NULL; 33138032Speter 33238032Speter if (tTd(39, 1)) 33338032Speter { 33490792Sgshapiro sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s); 33538032Speter if (av == NULL) 33690792Sgshapiro sm_dprintf(" (nullv)"); 33738032Speter else 33838032Speter { 33938032Speter for (avp = av; *avp != NULL; avp++) 34090792Sgshapiro sm_dprintf("\n\t%s", *avp); 34138032Speter } 34290792Sgshapiro sm_dprintf("\n"); 34338032Speter } 34438032Speter 34538032Speter /* count expected size of output (can safely overestimate) */ 34638032Speter l = len = slen; 34738032Speter if (av != NULL) 34838032Speter { 34938032Speter const char *sp = s; 35038032Speter 35138032Speter while (l-- > 0 && (c = *sp++) != '\0') 35238032Speter { 35338032Speter if (c != '%') 35438032Speter continue; 35538032Speter if (l-- <= 0) 35638032Speter break; 35738032Speter c = *sp++; 35838032Speter if (!(isascii(c) && isdigit(c))) 35938032Speter continue; 36038032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 36138032Speter continue; 36238032Speter if (*avp == NULL) 36338032Speter continue; 36438032Speter len += strlen(*avp); 36538032Speter } 36638032Speter } 36738032Speter if (map->map_app != NULL) 36838032Speter len += strlen(map->map_app); 36938032Speter if (buflen < ++len) 37038032Speter { 37138032Speter /* need to malloc additional space */ 37238032Speter buflen = len; 37338032Speter if (buf != NULL) 37477349Sgshapiro sm_free(buf); 37590792Sgshapiro buf = sm_pmalloc_x(buflen); 37638032Speter } 37738032Speter 37838032Speter bp = buf; 37938032Speter if (av == NULL) 38038032Speter { 38164562Sgshapiro memmove(bp, s, slen); 38238032Speter bp += slen; 38364562Sgshapiro 38464562Sgshapiro /* assert(len > slen); */ 38564562Sgshapiro len -= slen; 38638032Speter } 38738032Speter else 38838032Speter { 38938032Speter while (slen-- > 0 && (c = *s++) != '\0') 39038032Speter { 39138032Speter if (c != '%') 39238032Speter { 39338032Speter pushc: 394120256Sgshapiro if (len-- <= 1) 39590792Sgshapiro break; 39638032Speter *bp++ = c; 39738032Speter continue; 39838032Speter } 39938032Speter if (slen-- <= 0 || (c = *s++) == '\0') 40038032Speter c = '%'; 40138032Speter if (c == '%') 40238032Speter goto pushc; 40338032Speter if (!(isascii(c) && isdigit(c))) 40438032Speter { 405120256Sgshapiro if (len-- <= 1) 406120256Sgshapiro break; 40738032Speter *bp++ = '%'; 40838032Speter goto pushc; 40938032Speter } 41038032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 41138032Speter continue; 41238032Speter if (*avp == NULL) 41338032Speter continue; 41438032Speter 41538032Speter /* transliterate argument into output string */ 41664562Sgshapiro for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len) 41738032Speter *bp++ = c; 41838032Speter } 41938032Speter } 42064562Sgshapiro if (map->map_app != NULL && len > 0) 42190792Sgshapiro (void) sm_strlcpy(bp, map->map_app, len); 42238032Speter else 42338032Speter *bp = '\0'; 42438032Speter if (tTd(39, 1)) 42590792Sgshapiro sm_dprintf("map_rewrite => %s\n", buf); 42638032Speter return buf; 42738032Speter} 42890792Sgshapiro/* 42964562Sgshapiro** INITMAPS -- rebuild alias maps 43038032Speter** 43138032Speter** Parameters: 43264562Sgshapiro** none. 43338032Speter** 43438032Speter** Returns: 43538032Speter** none. 43638032Speter*/ 43738032Speter 43838032Spetervoid 43964562Sgshapiroinitmaps() 44038032Speter{ 44138032Speter#if XDEBUG 44238032Speter checkfd012("entering initmaps"); 44364562Sgshapiro#endif /* XDEBUG */ 44438032Speter stabapply(map_init, 0); 44538032Speter#if XDEBUG 44638032Speter checkfd012("exiting initmaps"); 44764562Sgshapiro#endif /* XDEBUG */ 44838032Speter} 44990792Sgshapiro/* 45064562Sgshapiro** MAP_INIT -- rebuild a map 45164562Sgshapiro** 45264562Sgshapiro** Parameters: 45364562Sgshapiro** s -- STAB entry: if map: try to rebuild 45464562Sgshapiro** unused -- unused variable 45564562Sgshapiro** 45664562Sgshapiro** Returns: 45764562Sgshapiro** none. 45864562Sgshapiro** 45964562Sgshapiro** Side Effects: 46064562Sgshapiro** will close already open rebuildable map. 46164562Sgshapiro*/ 46238032Speter 46364562Sgshapiro/* ARGSUSED1 */ 46464562Sgshapirostatic void 46564562Sgshapiromap_init(s, unused) 46638032Speter register STAB *s; 46764562Sgshapiro int unused; 46838032Speter{ 46938032Speter register MAP *map; 47038032Speter 47138032Speter /* has to be a map */ 47290792Sgshapiro if (s->s_symtype != ST_MAP) 47338032Speter return; 47438032Speter 47538032Speter map = &s->s_map; 47638032Speter if (!bitset(MF_VALID, map->map_mflags)) 47738032Speter return; 47838032Speter 47938032Speter if (tTd(38, 2)) 48090792Sgshapiro sm_dprintf("map_init(%s:%s, %s)\n", 48138032Speter map->map_class->map_cname == NULL ? "NULL" : 48238032Speter map->map_class->map_cname, 48338032Speter map->map_mname == NULL ? "NULL" : map->map_mname, 48464562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 48538032Speter 48664562Sgshapiro if (!bitset(MF_ALIAS, map->map_mflags) || 48764562Sgshapiro !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 48838032Speter { 48938032Speter if (tTd(38, 3)) 49090792Sgshapiro sm_dprintf("\tnot rebuildable\n"); 49138032Speter return; 49238032Speter } 49338032Speter 49438032Speter /* if already open, close it (for nested open) */ 49538032Speter if (bitset(MF_OPEN, map->map_mflags)) 49638032Speter { 49777349Sgshapiro map->map_mflags |= MF_CLOSING; 49838032Speter map->map_class->map_close(map); 49977349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 50038032Speter } 50138032Speter 50290792Sgshapiro (void) rebuildaliases(map, false); 50364562Sgshapiro return; 50464562Sgshapiro} 50590792Sgshapiro/* 50664562Sgshapiro** OPENMAP -- open a map 50764562Sgshapiro** 50864562Sgshapiro** Parameters: 50964562Sgshapiro** map -- map to open (it must not be open). 51064562Sgshapiro** 51164562Sgshapiro** Returns: 51264562Sgshapiro** whether open succeeded. 51364562Sgshapiro*/ 51464562Sgshapiro 51564562Sgshapirobool 51664562Sgshapiroopenmap(map) 51764562Sgshapiro MAP *map; 51864562Sgshapiro{ 51990792Sgshapiro bool restore = false; 52064562Sgshapiro bool savehold = HoldErrs; 52164562Sgshapiro bool savequick = QuickAbort; 52264562Sgshapiro int saveerrors = Errors; 52364562Sgshapiro 52464562Sgshapiro if (!bitset(MF_VALID, map->map_mflags)) 52590792Sgshapiro return false; 52664562Sgshapiro 52764562Sgshapiro /* better safe than sorry... */ 52864562Sgshapiro if (bitset(MF_OPEN, map->map_mflags)) 52990792Sgshapiro return true; 53064562Sgshapiro 53164562Sgshapiro /* Don't send a map open error out via SMTP */ 53264562Sgshapiro if ((OnlyOneError || QuickAbort) && 53364562Sgshapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 53438032Speter { 53590792Sgshapiro restore = true; 53690792Sgshapiro HoldErrs = true; 53790792Sgshapiro QuickAbort = false; 53838032Speter } 53938032Speter 54064562Sgshapiro errno = 0; 54138032Speter if (map->map_class->map_open(map, O_RDONLY)) 54238032Speter { 54338032Speter if (tTd(38, 4)) 54490792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: valid\n", 54538032Speter map->map_class->map_cname == NULL ? "NULL" : 54638032Speter map->map_class->map_cname, 54738032Speter map->map_mname == NULL ? "NULL" : 54838032Speter map->map_mname, 54938032Speter map->map_file == NULL ? "NULL" : 55038032Speter map->map_file); 55138032Speter map->map_mflags |= MF_OPEN; 55290792Sgshapiro map->map_pid = CurrentPid; 55338032Speter } 55438032Speter else 55538032Speter { 55638032Speter if (tTd(38, 4)) 55790792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n", 55838032Speter map->map_class->map_cname == NULL ? "NULL" : 55938032Speter map->map_class->map_cname, 56038032Speter map->map_mname == NULL ? "NULL" : 56138032Speter map->map_mname, 56238032Speter map->map_file == NULL ? "NULL" : 56338032Speter map->map_file, 56464562Sgshapiro errno == 0 ? "" : ": ", 56590792Sgshapiro errno == 0 ? "" : sm_errstring(errno)); 56638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 56738032Speter { 56838032Speter extern MAPCLASS BogusMapClass; 56938032Speter 57090792Sgshapiro map->map_orgclass = map->map_class; 57138032Speter map->map_class = &BogusMapClass; 57290792Sgshapiro map->map_mflags |= MF_OPEN|MF_OPENBOGUS; 57390792Sgshapiro map->map_pid = CurrentPid; 57438032Speter } 57564562Sgshapiro else 57664562Sgshapiro { 57764562Sgshapiro /* don't try again */ 57864562Sgshapiro map->map_mflags &= ~MF_VALID; 57964562Sgshapiro } 58038032Speter } 58164562Sgshapiro 58264562Sgshapiro if (restore) 58364562Sgshapiro { 58464562Sgshapiro Errors = saveerrors; 58564562Sgshapiro HoldErrs = savehold; 58664562Sgshapiro QuickAbort = savequick; 58764562Sgshapiro } 58864562Sgshapiro 58964562Sgshapiro return bitset(MF_OPEN, map->map_mflags); 59038032Speter} 59190792Sgshapiro/* 59242575Speter** CLOSEMAPS -- close all open maps opened by the current pid. 59342575Speter** 59442575Speter** Parameters: 59590792Sgshapiro** bogus -- only close bogus maps. 59642575Speter** 59742575Speter** Returns: 59842575Speter** none. 59942575Speter*/ 60042575Speter 60142575Spetervoid 60290792Sgshapiroclosemaps(bogus) 60390792Sgshapiro bool bogus; 60442575Speter{ 60590792Sgshapiro stabapply(map_close, bogus); 60642575Speter} 60790792Sgshapiro/* 60864562Sgshapiro** MAP_CLOSE -- close a map opened by the current pid. 60964562Sgshapiro** 61064562Sgshapiro** Parameters: 61190792Sgshapiro** s -- STAB entry: if map: try to close 61290792Sgshapiro** bogus -- only close bogus maps or MCF_NOTPERSIST maps. 61364562Sgshapiro** 61464562Sgshapiro** Returns: 61564562Sgshapiro** none. 61664562Sgshapiro*/ 61742575Speter 61842575Speter/* ARGSUSED1 */ 61964562Sgshapirostatic void 62090792Sgshapiromap_close(s, bogus) 62142575Speter register STAB *s; 62290792Sgshapiro int bogus; /* int because of stabapply(), used as bool */ 62342575Speter{ 62442575Speter MAP *map; 62590792Sgshapiro extern MAPCLASS BogusMapClass; 62642575Speter 62790792Sgshapiro if (s->s_symtype != ST_MAP) 62842575Speter return; 62964562Sgshapiro 63042575Speter map = &s->s_map; 63142575Speter 63290792Sgshapiro /* 63390792Sgshapiro ** close the map iff: 63490792Sgshapiro ** it is valid and open and opened by this process 63590792Sgshapiro ** and (!bogus or it's a bogus map or it is not persistent) 63690792Sgshapiro ** negate this: return iff 63790792Sgshapiro ** it is not valid or it is not open or not opened by this process 63890792Sgshapiro ** or (bogus and it's not a bogus map and it's not not-persistent) 63990792Sgshapiro */ 64090792Sgshapiro 64142575Speter if (!bitset(MF_VALID, map->map_mflags) || 64242575Speter !bitset(MF_OPEN, map->map_mflags) || 64377349Sgshapiro bitset(MF_CLOSING, map->map_mflags) || 64490792Sgshapiro map->map_pid != CurrentPid || 64590792Sgshapiro (bogus && map->map_class != &BogusMapClass && 64690792Sgshapiro !bitset(MCF_NOTPERSIST, map->map_class->map_cflags))) 64742575Speter return; 64864562Sgshapiro 64990792Sgshapiro if (map->map_class == &BogusMapClass && map->map_orgclass != NULL && 65090792Sgshapiro map->map_orgclass != &BogusMapClass) 65190792Sgshapiro map->map_class = map->map_orgclass; 65242575Speter if (tTd(38, 5)) 65390792Sgshapiro sm_dprintf("closemaps: closing %s (%s)\n", 65464562Sgshapiro map->map_mname == NULL ? "NULL" : map->map_mname, 65564562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 65664562Sgshapiro 65790792Sgshapiro if (!bitset(MF_OPENBOGUS, map->map_mflags)) 65890792Sgshapiro { 65990792Sgshapiro map->map_mflags |= MF_CLOSING; 66090792Sgshapiro map->map_class->map_close(map); 66190792Sgshapiro } 66290792Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING); 66342575Speter} 664168515Sgshapiro 665168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 666168515Sgshapiroextern int getdomainname(); 667168515Sgshapiro 668168515Sgshapiro/* this is mainly for backward compatibility in Sun environment */ 669168515Sgshapirostatic char * 670168515Sgshapirosun_init_domain() 671168515Sgshapiro{ 672168515Sgshapiro /* 673168515Sgshapiro ** Get the domain name from the kernel. 674168515Sgshapiro ** If it does not start with a leading dot, then remove 675168515Sgshapiro ** the first component. Since leading dots are funny Unix 676168515Sgshapiro ** files, we treat a leading "+" the same as a leading dot. 677168515Sgshapiro ** Finally, force there to be at least one dot in the domain name 678168515Sgshapiro ** (i.e. top-level domains are not allowed, like "com", must be 679168515Sgshapiro ** something like "sun.com"). 680168515Sgshapiro */ 681168515Sgshapiro 682168515Sgshapiro char buf[MAXNAME]; 683168515Sgshapiro char *period, *autodomain; 684168515Sgshapiro 685168515Sgshapiro if (getdomainname(buf, sizeof buf) < 0) 686168515Sgshapiro return NULL; 687168515Sgshapiro 688168515Sgshapiro if (buf[0] == '\0') 689168515Sgshapiro return NULL; 690168515Sgshapiro 691168515Sgshapiro if (tTd(0, 20)) 692168515Sgshapiro printf("domainname = %s\n", buf); 693168515Sgshapiro 694168515Sgshapiro if (buf[0] == '+') 695168515Sgshapiro buf[0] = '.'; 696168515Sgshapiro period = strchr(buf, '.'); 697168515Sgshapiro if (period == NULL) 698168515Sgshapiro autodomain = buf; 699168515Sgshapiro else 700168515Sgshapiro autodomain = period + 1; 701168515Sgshapiro if (strchr(autodomain, '.') == NULL) 702168515Sgshapiro return newstr(buf); 703168515Sgshapiro else 704168515Sgshapiro return newstr(autodomain); 705168515Sgshapiro} 706168515Sgshapiro#endif /* SUN_EXTENSIONS && SUN_INIT_DOMAIN */ 707168515Sgshapiro 70890792Sgshapiro/* 70938032Speter** GETCANONNAME -- look up name using service switch 71038032Speter** 71138032Speter** Parameters: 71238032Speter** host -- the host name to look up. 71338032Speter** hbsize -- the size of the host buffer. 71438032Speter** trymx -- if set, try MX records. 71590792Sgshapiro** pttl -- pointer to return TTL (can be NULL). 71638032Speter** 71738032Speter** Returns: 71890792Sgshapiro** true -- if the host was found. 71990792Sgshapiro** false -- otherwise. 72038032Speter*/ 72138032Speter 72238032Speterbool 72390792Sgshapirogetcanonname(host, hbsize, trymx, pttl) 72438032Speter char *host; 72538032Speter int hbsize; 72638032Speter bool trymx; 72790792Sgshapiro int *pttl; 72838032Speter{ 72938032Speter int nmaps; 73038032Speter int mapno; 73190792Sgshapiro bool found = false; 73290792Sgshapiro bool got_tempfail = false; 73364562Sgshapiro auto int status; 73438032Speter char *maptype[MAXMAPSTACK]; 73538032Speter short mapreturn[MAXMAPACTIONS]; 736168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 737168515Sgshapiro bool should_try_nis_domain = false; 738168515Sgshapiro static char *nis_domain = NULL; 739168515Sgshapiro#endif 74038032Speter 74138032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 74290792Sgshapiro if (pttl != 0) 74390792Sgshapiro *pttl = SM_DEFAULT_TTL; 74438032Speter for (mapno = 0; mapno < nmaps; mapno++) 74538032Speter { 74638032Speter int i; 74738032Speter 74838032Speter if (tTd(38, 20)) 74990792Sgshapiro sm_dprintf("getcanonname(%s), trying %s\n", 75038032Speter host, maptype[mapno]); 75138032Speter if (strcmp("files", maptype[mapno]) == 0) 75238032Speter { 75364562Sgshapiro found = text_getcanonname(host, hbsize, &status); 75438032Speter } 75590792Sgshapiro#if NIS 75638032Speter else if (strcmp("nis", maptype[mapno]) == 0) 75738032Speter { 75864562Sgshapiro found = nis_getcanonname(host, hbsize, &status); 759168515Sgshapiro# if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 760168515Sgshapiro if (nis_domain == NULL) 761168515Sgshapiro nis_domain = sun_init_domain(); 762168515Sgshapiro# endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 76338032Speter } 76464562Sgshapiro#endif /* NIS */ 76590792Sgshapiro#if NISPLUS 76638032Speter else if (strcmp("nisplus", maptype[mapno]) == 0) 76738032Speter { 76864562Sgshapiro found = nisplus_getcanonname(host, hbsize, &status); 769168515Sgshapiro# if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 770168515Sgshapiro if (nis_domain == NULL) 771168515Sgshapiro nis_domain = sun_init_domain(); 772168515Sgshapiro# endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 77338032Speter } 77464562Sgshapiro#endif /* NISPLUS */ 77538032Speter#if NAMED_BIND 77638032Speter else if (strcmp("dns", maptype[mapno]) == 0) 77738032Speter { 77890792Sgshapiro found = dns_getcanonname(host, hbsize, trymx, &status, pttl); 77938032Speter } 78064562Sgshapiro#endif /* NAMED_BIND */ 78138032Speter#if NETINFO 78238032Speter else if (strcmp("netinfo", maptype[mapno]) == 0) 78338032Speter { 78464562Sgshapiro found = ni_getcanonname(host, hbsize, &status); 78538032Speter } 78664562Sgshapiro#endif /* NETINFO */ 78738032Speter else 78838032Speter { 78990792Sgshapiro found = false; 79064562Sgshapiro status = EX_UNAVAILABLE; 79138032Speter } 79238032Speter 79338032Speter /* 79438032Speter ** Heuristic: if $m is not set, we are running during system 79538032Speter ** startup. In this case, when a name is apparently found 79638032Speter ** but has no dot, treat is as not found. This avoids 79738032Speter ** problems if /etc/hosts has no FQDN but is listed first 79838032Speter ** in the service switch. 79938032Speter */ 80038032Speter 80138032Speter if (found && 80238032Speter (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 80338032Speter break; 80438032Speter 805168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 806168515Sgshapiro if (found) 807168515Sgshapiro should_try_nis_domain = true; 808168515Sgshapiro /* but don't break, as we need to try all methods first */ 809168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 810168515Sgshapiro 81138032Speter /* see if we should continue */ 81264562Sgshapiro if (status == EX_TEMPFAIL) 81338032Speter { 81438032Speter i = MA_TRYAGAIN; 81590792Sgshapiro got_tempfail = true; 81638032Speter } 81764562Sgshapiro else if (status == EX_NOTFOUND) 81838032Speter i = MA_NOTFOUND; 81938032Speter else 82038032Speter i = MA_UNAVAIL; 82138032Speter if (bitset(1 << mapno, mapreturn[i])) 82238032Speter break; 82338032Speter } 82438032Speter 82538032Speter if (found) 82638032Speter { 82738032Speter char *d; 82838032Speter 82938032Speter if (tTd(38, 20)) 83090792Sgshapiro sm_dprintf("getcanonname(%s), found\n", host); 83138032Speter 83238032Speter /* 83338032Speter ** If returned name is still single token, compensate 83438032Speter ** by tagging on $m. This is because some sites set 83538032Speter ** up their DNS or NIS databases wrong. 83638032Speter */ 83738032Speter 83838032Speter if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 83938032Speter { 84038032Speter d = macvalue('m', CurEnv); 84138032Speter if (d != NULL && 84238032Speter hbsize > (int) (strlen(host) + strlen(d) + 1)) 84338032Speter { 84438032Speter if (host[strlen(host) - 1] != '.') 84590792Sgshapiro (void) sm_strlcat2(host, ".", d, 84690792Sgshapiro hbsize); 84790792Sgshapiro else 84890792Sgshapiro (void) sm_strlcat(host, d, hbsize); 84938032Speter } 85038032Speter else 851168515Sgshapiro { 852168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 853168515Sgshapiro if (VendorCode == VENDOR_SUN && 854168515Sgshapiro should_try_nis_domain) 855168515Sgshapiro { 856168515Sgshapiro goto try_nis_domain; 857168515Sgshapiro } 858168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 85990792Sgshapiro return false; 860168515Sgshapiro } 86138032Speter } 86290792Sgshapiro return true; 86338032Speter } 86438032Speter 865168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 866168515Sgshapiro if (VendorCode == VENDOR_SUN && should_try_nis_domain) 867168515Sgshapiro { 868168515Sgshapiro try_nis_domain: 869168515Sgshapiro if (nis_domain != NULL && 870168515Sgshapiro strlen(nis_domain) + strlen(host) + 1 < hbsize) 871168515Sgshapiro { 872168515Sgshapiro (void) sm_strlcat2(host, ".", nis_domain, hbsize); 873168515Sgshapiro return true; 874168515Sgshapiro } 875168515Sgshapiro } 876168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 877168515Sgshapiro 87838032Speter if (tTd(38, 20)) 87990792Sgshapiro sm_dprintf("getcanonname(%s), failed, status=%d\n", host, 88090792Sgshapiro status); 88138032Speter 88238032Speter if (got_tempfail) 88373188Sgshapiro SM_SET_H_ERRNO(TRY_AGAIN); 88438032Speter else 88573188Sgshapiro SM_SET_H_ERRNO(HOST_NOT_FOUND); 88690792Sgshapiro 88790792Sgshapiro return false; 88838032Speter} 88990792Sgshapiro/* 89038032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 89138032Speter** 89238032Speter** Parameters: 89338032Speter** name -- the name against which to match. 89473188Sgshapiro** dot -- where to reinsert '.' to get FQDN 89538032Speter** line -- the /etc/hosts line. 89638032Speter** cbuf -- the location to store the result. 89738032Speter** cbuflen -- the size of cbuf. 89838032Speter** 89938032Speter** Returns: 90090792Sgshapiro** true -- if the line matched the desired name. 90190792Sgshapiro** false -- otherwise. 90238032Speter*/ 90338032Speter 90464562Sgshapirostatic bool 90573188Sgshapiroextract_canonname(name, dot, line, cbuf, cbuflen) 90638032Speter char *name; 90773188Sgshapiro char *dot; 90838032Speter char *line; 90938032Speter char cbuf[]; 91038032Speter int cbuflen; 91138032Speter{ 91238032Speter int i; 91338032Speter char *p; 91490792Sgshapiro bool found = false; 91538032Speter 91638032Speter cbuf[0] = '\0'; 91738032Speter if (line[0] == '#') 91890792Sgshapiro return false; 91938032Speter 92038032Speter for (i = 1; ; i++) 92138032Speter { 92238032Speter char nbuf[MAXNAME + 1]; 92338032Speter 924168515Sgshapiro p = get_column(line, i, '\0', nbuf, sizeof(nbuf)); 92538032Speter if (p == NULL) 92638032Speter break; 92738032Speter if (*p == '\0') 92838032Speter continue; 92938032Speter if (cbuf[0] == '\0' || 93038032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 93138032Speter { 93290792Sgshapiro (void) sm_strlcpy(cbuf, p, cbuflen); 93338032Speter } 93490792Sgshapiro if (sm_strcasecmp(name, p) == 0) 93590792Sgshapiro found = true; 93673188Sgshapiro else if (dot != NULL) 93773188Sgshapiro { 93873188Sgshapiro /* try looking for the FQDN as well */ 93973188Sgshapiro *dot = '.'; 94090792Sgshapiro if (sm_strcasecmp(name, p) == 0) 94190792Sgshapiro found = true; 94273188Sgshapiro *dot = '\0'; 94373188Sgshapiro } 94438032Speter } 94538032Speter if (found && strchr(cbuf, '.') == NULL) 94638032Speter { 94738032Speter /* try to add a domain on the end of the name */ 94838032Speter char *domain = macvalue('m', CurEnv); 94938032Speter 95038032Speter if (domain != NULL && 95164562Sgshapiro strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 95238032Speter { 95364562Sgshapiro p = &cbuf[i]; 95438032Speter *p++ = '.'; 95590792Sgshapiro (void) sm_strlcpy(p, domain, cbuflen - i - 1); 95638032Speter } 95738032Speter } 95838032Speter return found; 95938032Speter} 96090792Sgshapiro 96190792Sgshapiro/* 96290792Sgshapiro** DNS modules 96390792Sgshapiro*/ 96490792Sgshapiro 96590792Sgshapiro#if NAMED_BIND 96690792Sgshapiro# if DNSMAP 96790792Sgshapiro 96890792Sgshapiro# include "sm_resolve.h" 96990792Sgshapiro# if NETINET || NETINET6 97090792Sgshapiro# include <arpa/inet.h> 97190792Sgshapiro# endif /* NETINET || NETINET6 */ 97290792Sgshapiro 97390792Sgshapiro/* 97490792Sgshapiro** DNS_MAP_OPEN -- stub to check proper value for dns map type 97590792Sgshapiro*/ 97690792Sgshapiro 97790792Sgshapirobool 97890792Sgshapirodns_map_open(map, mode) 97990792Sgshapiro MAP *map; 98090792Sgshapiro int mode; 98190792Sgshapiro{ 98290792Sgshapiro if (tTd(38,2)) 98390792Sgshapiro sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode); 98490792Sgshapiro 98590792Sgshapiro mode &= O_ACCMODE; 98690792Sgshapiro if (mode != O_RDONLY) 98790792Sgshapiro { 98890792Sgshapiro /* issue a pseudo-error message */ 98990792Sgshapiro errno = SM_EMAPCANTWRITE; 99090792Sgshapiro return false; 99190792Sgshapiro } 99290792Sgshapiro return true; 99390792Sgshapiro} 99490792Sgshapiro 99590792Sgshapiro/* 99690792Sgshapiro** DNS_MAP_PARSEARGS -- parse dns map definition args. 99790792Sgshapiro** 99890792Sgshapiro** Parameters: 99990792Sgshapiro** map -- pointer to MAP 100090792Sgshapiro** args -- pointer to the args on the config line. 100190792Sgshapiro** 100290792Sgshapiro** Returns: 100390792Sgshapiro** true -- if everything parsed OK. 100490792Sgshapiro** false -- otherwise. 100590792Sgshapiro*/ 100690792Sgshapiro 1007168515Sgshapiro#define map_sizelimit map_lockfd /* overload field */ 100890792Sgshapiro 100990792Sgshapirostruct dns_map 101090792Sgshapiro{ 101190792Sgshapiro int dns_m_type; 101290792Sgshapiro}; 101390792Sgshapiro 101490792Sgshapirobool 101590792Sgshapirodns_map_parseargs(map,args) 101690792Sgshapiro MAP *map; 101790792Sgshapiro char *args; 101890792Sgshapiro{ 101990792Sgshapiro register char *p = args; 102090792Sgshapiro struct dns_map *map_p; 102190792Sgshapiro 1022168515Sgshapiro map_p = (struct dns_map *) xalloc(sizeof(*map_p)); 102390792Sgshapiro map_p->dns_m_type = -1; 102490792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 102590792Sgshapiro 102690792Sgshapiro for (;;) 102790792Sgshapiro { 102890792Sgshapiro while (isascii(*p) && isspace(*p)) 102990792Sgshapiro p++; 103090792Sgshapiro if (*p != '-') 103190792Sgshapiro break; 103290792Sgshapiro switch (*++p) 103390792Sgshapiro { 103490792Sgshapiro case 'N': 103590792Sgshapiro map->map_mflags |= MF_INCLNULL; 103690792Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 103790792Sgshapiro break; 103890792Sgshapiro 103990792Sgshapiro case 'O': 104090792Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 104190792Sgshapiro break; 104290792Sgshapiro 104390792Sgshapiro case 'o': 104490792Sgshapiro map->map_mflags |= MF_OPTIONAL; 104590792Sgshapiro break; 104690792Sgshapiro 104790792Sgshapiro case 'f': 104890792Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 104990792Sgshapiro break; 105090792Sgshapiro 105190792Sgshapiro case 'm': 105290792Sgshapiro map->map_mflags |= MF_MATCHONLY; 105390792Sgshapiro break; 105490792Sgshapiro 105590792Sgshapiro case 'A': 105690792Sgshapiro map->map_mflags |= MF_APPEND; 105790792Sgshapiro break; 105890792Sgshapiro 105990792Sgshapiro case 'q': 106090792Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 106190792Sgshapiro break; 106290792Sgshapiro 106390792Sgshapiro case 't': 106490792Sgshapiro map->map_mflags |= MF_NODEFER; 106590792Sgshapiro break; 106690792Sgshapiro 106790792Sgshapiro case 'a': 106890792Sgshapiro map->map_app = ++p; 106990792Sgshapiro break; 107090792Sgshapiro 107190792Sgshapiro case 'T': 107290792Sgshapiro map->map_tapp = ++p; 107390792Sgshapiro break; 107490792Sgshapiro 107590792Sgshapiro case 'd': 107690792Sgshapiro { 107790792Sgshapiro char *h; 107890792Sgshapiro 107990792Sgshapiro ++p; 108090792Sgshapiro h = strchr(p, ' '); 108190792Sgshapiro if (h != NULL) 108290792Sgshapiro *h = '\0'; 108390792Sgshapiro map->map_timeout = convtime(p, 's'); 108490792Sgshapiro if (h != NULL) 108590792Sgshapiro *h = ' '; 108690792Sgshapiro } 108790792Sgshapiro break; 108890792Sgshapiro 108990792Sgshapiro case 'r': 109090792Sgshapiro while (isascii(*++p) && isspace(*p)) 109190792Sgshapiro continue; 109290792Sgshapiro map->map_retry = atoi(p); 109390792Sgshapiro break; 109490792Sgshapiro 109590792Sgshapiro case 'z': 109690792Sgshapiro if (*++p != '\\') 109790792Sgshapiro map->map_coldelim = *p; 109890792Sgshapiro else 109990792Sgshapiro { 110090792Sgshapiro switch (*++p) 110190792Sgshapiro { 110290792Sgshapiro case 'n': 110390792Sgshapiro map->map_coldelim = '\n'; 110490792Sgshapiro break; 110590792Sgshapiro 110690792Sgshapiro case 't': 110790792Sgshapiro map->map_coldelim = '\t'; 110890792Sgshapiro break; 110990792Sgshapiro 111090792Sgshapiro default: 111190792Sgshapiro map->map_coldelim = '\\'; 111290792Sgshapiro } 111390792Sgshapiro } 111490792Sgshapiro break; 111590792Sgshapiro 111690792Sgshapiro case 'Z': 111790792Sgshapiro while (isascii(*++p) && isspace(*p)) 111890792Sgshapiro continue; 111990792Sgshapiro map->map_sizelimit = atoi(p); 112090792Sgshapiro break; 112190792Sgshapiro 112290792Sgshapiro /* Start of dns_map specific args */ 112390792Sgshapiro case 'R': /* search field */ 112490792Sgshapiro { 112590792Sgshapiro char *h; 112690792Sgshapiro 112790792Sgshapiro while (isascii(*++p) && isspace(*p)) 112890792Sgshapiro continue; 112990792Sgshapiro h = strchr(p, ' '); 113090792Sgshapiro if (h != NULL) 113190792Sgshapiro *h = '\0'; 113290792Sgshapiro map_p->dns_m_type = dns_string_to_type(p); 113390792Sgshapiro if (h != NULL) 113490792Sgshapiro *h = ' '; 113590792Sgshapiro if (map_p->dns_m_type < 0) 113690792Sgshapiro syserr("dns map %s: wrong type %s", 113790792Sgshapiro map->map_mname, p); 113890792Sgshapiro } 113990792Sgshapiro break; 114090792Sgshapiro 114190792Sgshapiro case 'B': /* base domain */ 114290792Sgshapiro { 114390792Sgshapiro char *h; 114490792Sgshapiro 114590792Sgshapiro while (isascii(*++p) && isspace(*p)) 114690792Sgshapiro continue; 114790792Sgshapiro h = strchr(p, ' '); 114890792Sgshapiro if (h != NULL) 114990792Sgshapiro *h = '\0'; 115090792Sgshapiro 115190792Sgshapiro /* 115290792Sgshapiro ** slight abuse of map->map_file; it isn't 115390792Sgshapiro ** used otherwise in this map type. 115490792Sgshapiro */ 115590792Sgshapiro 115690792Sgshapiro map->map_file = newstr(p); 115790792Sgshapiro if (h != NULL) 115890792Sgshapiro *h = ' '; 115990792Sgshapiro } 116090792Sgshapiro break; 116190792Sgshapiro } 116290792Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 116390792Sgshapiro p++; 116490792Sgshapiro if (*p != '\0') 116590792Sgshapiro *p++ = '\0'; 116690792Sgshapiro } 116790792Sgshapiro if (map_p->dns_m_type < 0) 116890792Sgshapiro syserr("dns map %s: missing -R type", map->map_mname); 116990792Sgshapiro if (map->map_app != NULL) 117090792Sgshapiro map->map_app = newstr(map->map_app); 117190792Sgshapiro if (map->map_tapp != NULL) 117290792Sgshapiro map->map_tapp = newstr(map->map_tapp); 117390792Sgshapiro 117490792Sgshapiro /* 1175168515Sgshapiro ** Assumption: assert(sizeof(int) <= sizeof(ARBPTR_T)); 117690792Sgshapiro ** Even if this assumption is wrong, we use only one byte, 117790792Sgshapiro ** so it doesn't really matter. 117890792Sgshapiro */ 117990792Sgshapiro 118090792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; 118190792Sgshapiro return true; 118290792Sgshapiro} 118390792Sgshapiro 118490792Sgshapiro/* 118590792Sgshapiro** DNS_MAP_LOOKUP -- perform dns map lookup. 118690792Sgshapiro** 118790792Sgshapiro** Parameters: 118890792Sgshapiro** map -- pointer to MAP 118990792Sgshapiro** name -- name to lookup 119090792Sgshapiro** av -- arguments to interpolate into buf. 119190792Sgshapiro** statp -- pointer to status (EX_) 119290792Sgshapiro** 119390792Sgshapiro** Returns: 119490792Sgshapiro** result of lookup if succeeded. 119590792Sgshapiro** NULL -- otherwise. 119690792Sgshapiro*/ 119790792Sgshapiro 119890792Sgshapirochar * 119990792Sgshapirodns_map_lookup(map, name, av, statp) 120090792Sgshapiro MAP *map; 120190792Sgshapiro char *name; 120290792Sgshapiro char **av; 120390792Sgshapiro int *statp; 120490792Sgshapiro{ 120590792Sgshapiro int resnum = 0; 120690792Sgshapiro char *vp = NULL, *result = NULL; 120790792Sgshapiro size_t vsize; 120890792Sgshapiro struct dns_map *map_p; 120990792Sgshapiro RESOURCE_RECORD_T *rr = NULL; 121090792Sgshapiro DNS_REPLY_T *r = NULL; 121190792Sgshapiro# if NETINET6 121290792Sgshapiro static char buf6[INET6_ADDRSTRLEN]; 121390792Sgshapiro# endif /* NETINET6 */ 121490792Sgshapiro 121590792Sgshapiro if (tTd(38, 20)) 121690792Sgshapiro sm_dprintf("dns_map_lookup(%s, %s)\n", 121790792Sgshapiro map->map_mname, name); 121890792Sgshapiro 121990792Sgshapiro map_p = (struct dns_map *)(map->map_db1); 122090792Sgshapiro if (map->map_file != NULL && *map->map_file != '\0') 122190792Sgshapiro { 122290792Sgshapiro size_t len; 122390792Sgshapiro char *appdomain; 122490792Sgshapiro 122590792Sgshapiro len = strlen(map->map_file) + strlen(name) + 2; 122690792Sgshapiro appdomain = (char *) sm_malloc(len); 122790792Sgshapiro if (appdomain == NULL) 122890792Sgshapiro { 122990792Sgshapiro *statp = EX_UNAVAILABLE; 123090792Sgshapiro return NULL; 123190792Sgshapiro } 123290792Sgshapiro (void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file); 123390792Sgshapiro r = dns_lookup_int(appdomain, C_IN, map_p->dns_m_type, 123490792Sgshapiro map->map_timeout, map->map_retry); 123590792Sgshapiro sm_free(appdomain); 123690792Sgshapiro } 123790792Sgshapiro else 123890792Sgshapiro { 123990792Sgshapiro r = dns_lookup_int(name, C_IN, map_p->dns_m_type, 124090792Sgshapiro map->map_timeout, map->map_retry); 124190792Sgshapiro } 124290792Sgshapiro 124390792Sgshapiro if (r == NULL) 124490792Sgshapiro { 124590792Sgshapiro result = NULL; 1246120256Sgshapiro if (h_errno == TRY_AGAIN || transienterror(errno)) 124790792Sgshapiro *statp = EX_TEMPFAIL; 124890792Sgshapiro else 124990792Sgshapiro *statp = EX_NOTFOUND; 125090792Sgshapiro goto cleanup; 125190792Sgshapiro } 125290792Sgshapiro *statp = EX_OK; 125390792Sgshapiro for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next) 125490792Sgshapiro { 125590792Sgshapiro char *type = NULL; 125690792Sgshapiro char *value = NULL; 125790792Sgshapiro 125890792Sgshapiro switch (rr->rr_type) 125990792Sgshapiro { 126090792Sgshapiro case T_NS: 126190792Sgshapiro type = "T_NS"; 126290792Sgshapiro value = rr->rr_u.rr_txt; 126390792Sgshapiro break; 126490792Sgshapiro case T_CNAME: 126590792Sgshapiro type = "T_CNAME"; 126690792Sgshapiro value = rr->rr_u.rr_txt; 126790792Sgshapiro break; 126890792Sgshapiro case T_AFSDB: 126990792Sgshapiro type = "T_AFSDB"; 127090792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 127190792Sgshapiro break; 127290792Sgshapiro case T_SRV: 127390792Sgshapiro type = "T_SRV"; 127490792Sgshapiro value = rr->rr_u.rr_srv->srv_r_target; 127590792Sgshapiro break; 127690792Sgshapiro case T_PTR: 127790792Sgshapiro type = "T_PTR"; 127890792Sgshapiro value = rr->rr_u.rr_txt; 127990792Sgshapiro break; 128090792Sgshapiro case T_TXT: 128190792Sgshapiro type = "T_TXT"; 128290792Sgshapiro value = rr->rr_u.rr_txt; 128390792Sgshapiro break; 128490792Sgshapiro case T_MX: 128590792Sgshapiro type = "T_MX"; 128690792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 128790792Sgshapiro break; 128890792Sgshapiro# if NETINET 128990792Sgshapiro case T_A: 129090792Sgshapiro type = "T_A"; 129190792Sgshapiro value = inet_ntoa(*(rr->rr_u.rr_a)); 129290792Sgshapiro break; 129390792Sgshapiro# endif /* NETINET */ 129490792Sgshapiro# if NETINET6 129590792Sgshapiro case T_AAAA: 129690792Sgshapiro type = "T_AAAA"; 129790792Sgshapiro value = anynet_ntop(rr->rr_u.rr_aaaa, buf6, 1298168515Sgshapiro sizeof(buf6)); 129990792Sgshapiro break; 130090792Sgshapiro# endif /* NETINET6 */ 130190792Sgshapiro } 130290792Sgshapiro 130398841Sgshapiro (void) strreplnonprt(value, 'X'); 130490792Sgshapiro if (map_p->dns_m_type != rr->rr_type) 130590792Sgshapiro { 130690792Sgshapiro if (tTd(38, 40)) 130790792Sgshapiro sm_dprintf("\tskipping type %s (%d) value %s\n", 130890792Sgshapiro type != NULL ? type : "<UNKNOWN>", 130990792Sgshapiro rr->rr_type, 131090792Sgshapiro value != NULL ? value : "<NO VALUE>"); 131190792Sgshapiro continue; 131290792Sgshapiro } 131390792Sgshapiro 131490792Sgshapiro# if NETINET6 131590792Sgshapiro if (rr->rr_type == T_AAAA && value == NULL) 131690792Sgshapiro { 131790792Sgshapiro result = NULL; 131890792Sgshapiro *statp = EX_DATAERR; 131990792Sgshapiro if (tTd(38, 40)) 132090792Sgshapiro sm_dprintf("\tbad T_AAAA conversion\n"); 132190792Sgshapiro goto cleanup; 132290792Sgshapiro } 132390792Sgshapiro# endif /* NETINET6 */ 132490792Sgshapiro if (tTd(38, 40)) 132590792Sgshapiro sm_dprintf("\tfound type %s (%d) value %s\n", 132690792Sgshapiro type != NULL ? type : "<UNKNOWN>", 132790792Sgshapiro rr->rr_type, 132890792Sgshapiro value != NULL ? value : "<NO VALUE>"); 132990792Sgshapiro if (value != NULL && 133090792Sgshapiro (map->map_coldelim == '\0' || 133190792Sgshapiro map->map_sizelimit == 1 || 133290792Sgshapiro bitset(MF_MATCHONLY, map->map_mflags))) 133390792Sgshapiro { 133490792Sgshapiro /* Only care about the first match */ 133590792Sgshapiro vp = newstr(value); 133690792Sgshapiro break; 133790792Sgshapiro } 133890792Sgshapiro else if (vp == NULL) 133990792Sgshapiro { 134090792Sgshapiro /* First result */ 134190792Sgshapiro vp = newstr(value); 134290792Sgshapiro } 134390792Sgshapiro else 134490792Sgshapiro { 134590792Sgshapiro /* concatenate the results */ 134690792Sgshapiro int sz; 134790792Sgshapiro char *new; 134890792Sgshapiro 134990792Sgshapiro sz = strlen(vp) + strlen(value) + 2; 135090792Sgshapiro new = xalloc(sz); 135190792Sgshapiro (void) sm_snprintf(new, sz, "%s%c%s", 135290792Sgshapiro vp, map->map_coldelim, value); 135390792Sgshapiro sm_free(vp); 135490792Sgshapiro vp = new; 135590792Sgshapiro if (map->map_sizelimit > 0 && 135690792Sgshapiro ++resnum >= map->map_sizelimit) 135790792Sgshapiro break; 135890792Sgshapiro } 135990792Sgshapiro } 136090792Sgshapiro if (vp == NULL) 136190792Sgshapiro { 136290792Sgshapiro result = NULL; 136390792Sgshapiro *statp = EX_NOTFOUND; 136490792Sgshapiro if (tTd(38, 40)) 136590792Sgshapiro sm_dprintf("\tno match found\n"); 136690792Sgshapiro goto cleanup; 136790792Sgshapiro } 136890792Sgshapiro 136990792Sgshapiro /* Cleanly truncate for rulesets */ 137090792Sgshapiro truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim); 137190792Sgshapiro 137290792Sgshapiro vsize = strlen(vp); 137390792Sgshapiro 137490792Sgshapiro if (LogLevel > 9) 137590792Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s", 137690792Sgshapiro name, vp); 137790792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 137890792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 137990792Sgshapiro else 138090792Sgshapiro result = map_rewrite(map, vp, vsize, av); 138190792Sgshapiro 138290792Sgshapiro cleanup: 138390792Sgshapiro if (vp != NULL) 138490792Sgshapiro sm_free(vp); 138590792Sgshapiro if (r != NULL) 138690792Sgshapiro dns_free_data(r); 138790792Sgshapiro return result; 138890792Sgshapiro} 138990792Sgshapiro# endif /* DNSMAP */ 139090792Sgshapiro#endif /* NAMED_BIND */ 139190792Sgshapiro 139290792Sgshapiro/* 139338032Speter** NDBM modules 139438032Speter*/ 139538032Speter 139690792Sgshapiro#if NDBM 139738032Speter 139838032Speter/* 139938032Speter** NDBM_MAP_OPEN -- DBM-style map open 140038032Speter*/ 140138032Speter 140238032Speterbool 140338032Speterndbm_map_open(map, mode) 140438032Speter MAP *map; 140538032Speter int mode; 140638032Speter{ 140738032Speter register DBM *dbm; 140864562Sgshapiro int save_errno; 140938032Speter int dfd; 141038032Speter int pfd; 141164562Sgshapiro long sff; 141238032Speter int ret; 141338032Speter int smode = S_IREAD; 141498121Sgshapiro char dirfile[MAXPATHLEN]; 141598121Sgshapiro char pagfile[MAXPATHLEN]; 141664562Sgshapiro struct stat st; 141738032Speter struct stat std, stp; 141838032Speter 141938032Speter if (tTd(38, 2)) 142090792Sgshapiro sm_dprintf("ndbm_map_open(%s, %s, %d)\n", 142138032Speter map->map_mname, map->map_file, mode); 142238032Speter map->map_lockfd = -1; 142338032Speter mode &= O_ACCMODE; 142438032Speter 142538032Speter /* do initial file and directory checks */ 1426168515Sgshapiro if (sm_strlcpyn(dirfile, sizeof(dirfile), 2, 1427168515Sgshapiro map->map_file, ".dir") >= sizeof(dirfile) || 1428168515Sgshapiro sm_strlcpyn(pagfile, sizeof(pagfile), 2, 1429168515Sgshapiro map->map_file, ".pag") >= sizeof(pagfile)) 143098121Sgshapiro { 143198121Sgshapiro errno = 0; 143298121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 143398121Sgshapiro syserr("dbm map \"%s\": map file %s name too long", 143498121Sgshapiro map->map_mname, map->map_file); 143598121Sgshapiro return false; 143698121Sgshapiro } 143738032Speter sff = SFF_ROOTOK|SFF_REGONLY; 143838032Speter if (mode == O_RDWR) 143938032Speter { 144038032Speter sff |= SFF_CREAT; 144164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 144238032Speter sff |= SFF_NOSLINK; 144364562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 144438032Speter sff |= SFF_NOHLINK; 144538032Speter smode = S_IWRITE; 144638032Speter } 144738032Speter else 144838032Speter { 144964562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 145038032Speter sff |= SFF_NOWLINK; 145138032Speter } 145264562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 145338032Speter sff |= SFF_SAFEDIRPATH; 145438032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 145590792Sgshapiro sff, smode, &std); 145638032Speter if (ret == 0) 145738032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 145838032Speter sff, smode, &stp); 145964562Sgshapiro 146038032Speter if (ret != 0) 146138032Speter { 146238032Speter char *prob = "unsafe"; 146338032Speter 146438032Speter /* cannot open this map */ 146538032Speter if (ret == ENOENT) 146638032Speter prob = "missing"; 146738032Speter if (tTd(38, 2)) 146890792Sgshapiro sm_dprintf("\t%s map file: %d\n", prob, ret); 146938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 147038032Speter syserr("dbm map \"%s\": %s map file %s", 147138032Speter map->map_mname, prob, map->map_file); 147290792Sgshapiro return false; 147338032Speter } 147438032Speter if (std.st_mode == ST_MODE_NOFILE) 147538032Speter mode |= O_CREAT|O_EXCL; 147638032Speter 147764562Sgshapiro# if LOCK_ON_OPEN 147838032Speter if (mode == O_RDONLY) 147938032Speter mode |= O_SHLOCK; 148038032Speter else 148138032Speter mode |= O_TRUNC|O_EXLOCK; 148264562Sgshapiro# else /* LOCK_ON_OPEN */ 148338032Speter if ((mode & O_ACCMODE) == O_RDWR) 148438032Speter { 148564562Sgshapiro# if NOFTRUNCATE 148638032Speter /* 148738032Speter ** Warning: race condition. Try to lock the file as 148838032Speter ** quickly as possible after opening it. 148938032Speter ** This may also have security problems on some systems, 149038032Speter ** but there isn't anything we can do about it. 149138032Speter */ 149238032Speter 149338032Speter mode |= O_TRUNC; 149464562Sgshapiro# else /* NOFTRUNCATE */ 149538032Speter /* 149638032Speter ** This ugly code opens the map without truncating it, 149738032Speter ** locks the file, then truncates it. Necessary to 149838032Speter ** avoid race conditions. 149938032Speter */ 150038032Speter 150138032Speter int dirfd; 150238032Speter int pagfd; 150364562Sgshapiro long sff = SFF_CREAT|SFF_OPENASROOT; 150438032Speter 150564562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 150638032Speter sff |= SFF_NOSLINK; 150764562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 150838032Speter sff |= SFF_NOHLINK; 150938032Speter 151038032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 151138032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 151238032Speter 151338032Speter if (dirfd < 0 || pagfd < 0) 151438032Speter { 151564562Sgshapiro save_errno = errno; 151638032Speter if (dirfd >= 0) 151738032Speter (void) close(dirfd); 151838032Speter if (pagfd >= 0) 151938032Speter (void) close(pagfd); 152038032Speter errno = save_errno; 152138032Speter syserr("ndbm_map_open: cannot create database %s", 152238032Speter map->map_file); 152390792Sgshapiro return false; 152438032Speter } 152538032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 152638032Speter ftruncate(pagfd, (off_t) 0) < 0) 152738032Speter { 152864562Sgshapiro save_errno = errno; 152938032Speter (void) close(dirfd); 153038032Speter (void) close(pagfd); 153138032Speter errno = save_errno; 153238032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 153338032Speter map->map_file); 153490792Sgshapiro return false; 153538032Speter } 153638032Speter 153738032Speter /* if new file, get "before" bits for later filechanged check */ 153838032Speter if (std.st_mode == ST_MODE_NOFILE && 153938032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 154038032Speter { 154164562Sgshapiro save_errno = errno; 154238032Speter (void) close(dirfd); 154338032Speter (void) close(pagfd); 154438032Speter errno = save_errno; 154538032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 154638032Speter map->map_file); 154790792Sgshapiro return false; 154838032Speter } 154938032Speter 155038032Speter /* have to save the lock for the duration (bletch) */ 155138032Speter map->map_lockfd = dirfd; 155264562Sgshapiro (void) close(pagfd); 155338032Speter 155438032Speter /* twiddle bits for dbm_open */ 155538032Speter mode &= ~(O_CREAT|O_EXCL); 155664562Sgshapiro# endif /* NOFTRUNCATE */ 155738032Speter } 155864562Sgshapiro# endif /* LOCK_ON_OPEN */ 155938032Speter 156038032Speter /* open the database */ 156138032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 156238032Speter if (dbm == NULL) 156338032Speter { 156464562Sgshapiro save_errno = errno; 156538032Speter if (bitset(MF_ALIAS, map->map_mflags) && 156690792Sgshapiro aliaswait(map, ".pag", false)) 156790792Sgshapiro return true; 156864562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 156938032Speter if (map->map_lockfd >= 0) 157064562Sgshapiro (void) close(map->map_lockfd); 157164562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 157238032Speter errno = save_errno; 157338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 157438032Speter syserr("Cannot open DBM database %s", map->map_file); 157590792Sgshapiro return false; 157638032Speter } 157738032Speter dfd = dbm_dirfno(dbm); 157838032Speter pfd = dbm_pagfno(dbm); 157938032Speter if (dfd == pfd) 158038032Speter { 158138032Speter /* heuristic: if files are linked, this is actually gdbm */ 158238032Speter dbm_close(dbm); 158364562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 158438032Speter if (map->map_lockfd >= 0) 158564562Sgshapiro (void) close(map->map_lockfd); 158664562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 158738032Speter errno = 0; 158838032Speter syserr("dbm map \"%s\": cannot support GDBM", 158938032Speter map->map_mname); 159090792Sgshapiro return false; 159138032Speter } 159238032Speter 159338032Speter if (filechanged(dirfile, dfd, &std) || 159438032Speter filechanged(pagfile, pfd, &stp)) 159538032Speter { 159664562Sgshapiro save_errno = errno; 159738032Speter dbm_close(dbm); 159864562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 159938032Speter if (map->map_lockfd >= 0) 160064562Sgshapiro (void) close(map->map_lockfd); 160164562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 160238032Speter errno = save_errno; 160338032Speter syserr("ndbm_map_open(%s): file changed after open", 160438032Speter map->map_file); 160590792Sgshapiro return false; 160638032Speter } 160738032Speter 160838032Speter map->map_db1 = (ARBPTR_T) dbm; 160964562Sgshapiro 161064562Sgshapiro /* 161164562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 161264562Sgshapiro ** as aliaswait() will call map_lookup() which requires 161364562Sgshapiro ** map_mtime to be set 161464562Sgshapiro */ 161564562Sgshapiro 161677349Sgshapiro if (fstat(pfd, &st) >= 0) 161764562Sgshapiro map->map_mtime = st.st_mtime; 161864562Sgshapiro 161938032Speter if (mode == O_RDONLY) 162038032Speter { 162164562Sgshapiro# if LOCK_ON_OPEN 162238032Speter if (dfd >= 0) 162338032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 162438032Speter if (pfd >= 0) 162538032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 162664562Sgshapiro# endif /* LOCK_ON_OPEN */ 162738032Speter if (bitset(MF_ALIAS, map->map_mflags) && 162890792Sgshapiro !aliaswait(map, ".pag", true)) 162990792Sgshapiro return false; 163038032Speter } 163138032Speter else 163238032Speter { 163338032Speter map->map_mflags |= MF_LOCKED; 163442575Speter if (geteuid() == 0 && TrustedUid != 0) 163538032Speter { 163664562Sgshapiro# if HASFCHOWN 163742575Speter if (fchown(dfd, TrustedUid, -1) < 0 || 163842575Speter fchown(pfd, TrustedUid, -1) < 0) 163938032Speter { 164038032Speter int err = errno; 164138032Speter 164238032Speter sm_syslog(LOG_ALERT, NOQID, 164338032Speter "ownership change on %s failed: %s", 164490792Sgshapiro map->map_file, sm_errstring(err)); 164538032Speter message("050 ownership change on %s failed: %s", 164690792Sgshapiro map->map_file, sm_errstring(err)); 164738032Speter } 164890792Sgshapiro# else /* HASFCHOWN */ 164990792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 165090792Sgshapiro "no fchown(): cannot change ownership on %s", 165190792Sgshapiro map->map_file); 165290792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 165390792Sgshapiro map->map_file); 165464562Sgshapiro# endif /* HASFCHOWN */ 165538032Speter } 165638032Speter } 165790792Sgshapiro return true; 165838032Speter} 165938032Speter 166038032Speter 166138032Speter/* 166238032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 166338032Speter*/ 166438032Speter 166538032Speterchar * 166638032Speterndbm_map_lookup(map, name, av, statp) 166738032Speter MAP *map; 166838032Speter char *name; 166938032Speter char **av; 167038032Speter int *statp; 167138032Speter{ 167238032Speter datum key, val; 167377349Sgshapiro int dfd, pfd; 167438032Speter char keybuf[MAXNAME + 1]; 167538032Speter struct stat stbuf; 167638032Speter 167738032Speter if (tTd(38, 20)) 167890792Sgshapiro sm_dprintf("ndbm_map_lookup(%s, %s)\n", 167938032Speter map->map_mname, name); 168038032Speter 168138032Speter key.dptr = name; 168238032Speter key.dsize = strlen(name); 168338032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 168438032Speter { 1685168515Sgshapiro if (key.dsize > sizeof(keybuf) - 1) 1686168515Sgshapiro key.dsize = sizeof(keybuf) - 1; 168764562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 168838032Speter keybuf[key.dsize] = '\0'; 168938032Speter makelower(keybuf); 169038032Speter key.dptr = keybuf; 169138032Speter } 169238032Speterlockdbm: 169377349Sgshapiro dfd = dbm_dirfno((DBM *) map->map_db1); 169477349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 169577349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_SH); 169677349Sgshapiro pfd = dbm_pagfno((DBM *) map->map_db1); 169777349Sgshapiro if (pfd < 0 || fstat(pfd, &stbuf) < 0 || 169877349Sgshapiro stbuf.st_mtime > map->map_mtime) 169938032Speter { 170038032Speter /* Reopen the database to sync the cache */ 170138032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 170238032Speter : O_RDONLY; 170338032Speter 170477349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 170577349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 170677349Sgshapiro map->map_mflags |= MF_CLOSING; 170738032Speter map->map_class->map_close(map); 170877349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 170938032Speter if (map->map_class->map_open(map, omode)) 171038032Speter { 171138032Speter map->map_mflags |= MF_OPEN; 171290792Sgshapiro map->map_pid = CurrentPid; 171338032Speter if ((omode && O_ACCMODE) == O_RDWR) 171438032Speter map->map_mflags |= MF_WRITABLE; 171538032Speter goto lockdbm; 171638032Speter } 171738032Speter else 171838032Speter { 171938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 172038032Speter { 172138032Speter extern MAPCLASS BogusMapClass; 172238032Speter 172338032Speter *statp = EX_TEMPFAIL; 172490792Sgshapiro map->map_orgclass = map->map_class; 172538032Speter map->map_class = &BogusMapClass; 172638032Speter map->map_mflags |= MF_OPEN; 172790792Sgshapiro map->map_pid = CurrentPid; 172838032Speter syserr("Cannot reopen NDBM database %s", 172938032Speter map->map_file); 173038032Speter } 173138032Speter return NULL; 173238032Speter } 173338032Speter } 173438032Speter val.dptr = NULL; 173538032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 173638032Speter { 173738032Speter val = dbm_fetch((DBM *) map->map_db1, key); 173838032Speter if (val.dptr != NULL) 173938032Speter map->map_mflags &= ~MF_TRY1NULL; 174038032Speter } 174138032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 174238032Speter { 174338032Speter key.dsize++; 174438032Speter val = dbm_fetch((DBM *) map->map_db1, key); 174538032Speter if (val.dptr != NULL) 174638032Speter map->map_mflags &= ~MF_TRY0NULL; 174738032Speter } 174877349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 174977349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 175038032Speter if (val.dptr == NULL) 175138032Speter return NULL; 175238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 175338032Speter return map_rewrite(map, name, strlen(name), NULL); 175438032Speter else 175538032Speter return map_rewrite(map, val.dptr, val.dsize, av); 175638032Speter} 175738032Speter 175838032Speter 175938032Speter/* 176038032Speter** NDBM_MAP_STORE -- store a datum in the database 176138032Speter*/ 176238032Speter 176338032Spetervoid 176438032Speterndbm_map_store(map, lhs, rhs) 176538032Speter register MAP *map; 176638032Speter char *lhs; 176738032Speter char *rhs; 176838032Speter{ 176938032Speter datum key; 177038032Speter datum data; 177164562Sgshapiro int status; 177238032Speter char keybuf[MAXNAME + 1]; 177338032Speter 177438032Speter if (tTd(38, 12)) 177590792Sgshapiro sm_dprintf("ndbm_map_store(%s, %s, %s)\n", 177638032Speter map->map_mname, lhs, rhs); 177738032Speter 177838032Speter key.dsize = strlen(lhs); 177938032Speter key.dptr = lhs; 178038032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 178138032Speter { 1782168515Sgshapiro if (key.dsize > sizeof(keybuf) - 1) 1783168515Sgshapiro key.dsize = sizeof(keybuf) - 1; 178464562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 178538032Speter keybuf[key.dsize] = '\0'; 178638032Speter makelower(keybuf); 178738032Speter key.dptr = keybuf; 178838032Speter } 178938032Speter 179038032Speter data.dsize = strlen(rhs); 179138032Speter data.dptr = rhs; 179238032Speter 179338032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 179438032Speter { 179538032Speter key.dsize++; 179638032Speter data.dsize++; 179738032Speter } 179838032Speter 179964562Sgshapiro status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 180064562Sgshapiro if (status > 0) 180138032Speter { 180238032Speter if (!bitset(MF_APPEND, map->map_mflags)) 180338032Speter message("050 Warning: duplicate alias name %s", lhs); 180438032Speter else 180538032Speter { 180638032Speter static char *buf = NULL; 180738032Speter static int bufsiz = 0; 180838032Speter auto int xstat; 180938032Speter datum old; 181038032Speter 181138032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 181290792Sgshapiro (char **) NULL, &xstat); 181338032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 181438032Speter { 181538032Speter old.dsize = strlen(old.dptr); 181638032Speter if (data.dsize + old.dsize + 2 > bufsiz) 181738032Speter { 181838032Speter if (buf != NULL) 181990792Sgshapiro (void) sm_free(buf); 182038032Speter bufsiz = data.dsize + old.dsize + 2; 182190792Sgshapiro buf = sm_pmalloc_x(bufsiz); 182238032Speter } 182390792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 182490792Sgshapiro data.dptr, ",", old.dptr); 182538032Speter data.dsize = data.dsize + old.dsize + 1; 182638032Speter data.dptr = buf; 182738032Speter if (tTd(38, 9)) 182890792Sgshapiro sm_dprintf("ndbm_map_store append=%s\n", 182964562Sgshapiro data.dptr); 183038032Speter } 183138032Speter } 183264562Sgshapiro status = dbm_store((DBM *) map->map_db1, 183364562Sgshapiro key, data, DBM_REPLACE); 183438032Speter } 183564562Sgshapiro if (status != 0) 183664562Sgshapiro syserr("readaliases: dbm put (%s): %d", lhs, status); 183738032Speter} 183838032Speter 183938032Speter 184038032Speter/* 184138032Speter** NDBM_MAP_CLOSE -- close the database 184238032Speter*/ 184338032Speter 184438032Spetervoid 184538032Speterndbm_map_close(map) 184638032Speter register MAP *map; 184738032Speter{ 184838032Speter if (tTd(38, 9)) 184990792Sgshapiro sm_dprintf("ndbm_map_close(%s, %s, %lx)\n", 185038032Speter map->map_mname, map->map_file, map->map_mflags); 185138032Speter 185238032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 185338032Speter { 185464562Sgshapiro# ifdef NDBM_YP_COMPAT 185538032Speter bool inclnull; 185642575Speter char buf[MAXHOSTNAMELEN]; 185738032Speter 185838032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 185938032Speter map->map_mflags &= ~MF_INCLNULL; 186038032Speter 186138032Speter if (strstr(map->map_file, "/yp/") != NULL) 186238032Speter { 186338032Speter long save_mflags = map->map_mflags; 186438032Speter 186538032Speter map->map_mflags |= MF_NOFOLDCASE; 186638032Speter 1867168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%010ld", curtime()); 186838032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 186938032Speter 1870168515Sgshapiro (void) gethostname(buf, sizeof(buf)); 187138032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 187238032Speter 187338032Speter map->map_mflags = save_mflags; 187438032Speter } 187538032Speter 187638032Speter if (inclnull) 187738032Speter map->map_mflags |= MF_INCLNULL; 187864562Sgshapiro# endif /* NDBM_YP_COMPAT */ 187938032Speter 188038032Speter /* write out the distinguished alias */ 188138032Speter ndbm_map_store(map, "@", "@"); 188238032Speter } 188338032Speter dbm_close((DBM *) map->map_db1); 188438032Speter 188538032Speter /* release lock (if needed) */ 188664562Sgshapiro# if !LOCK_ON_OPEN 188738032Speter if (map->map_lockfd >= 0) 188838032Speter (void) close(map->map_lockfd); 188964562Sgshapiro# endif /* !LOCK_ON_OPEN */ 189038032Speter} 189138032Speter 189264562Sgshapiro#endif /* NDBM */ 189390792Sgshapiro/* 189438032Speter** NEWDB (Hash and BTree) Modules 189538032Speter*/ 189638032Speter 189790792Sgshapiro#if NEWDB 189838032Speter 189938032Speter/* 190038032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 190138032Speter** 190238032Speter** These do rather bizarre locking. If you can lock on open, 190338032Speter** do that to avoid the condition of opening a database that 190438032Speter** is being rebuilt. If you don't, we'll try to fake it, but 190538032Speter** there will be a race condition. If opening for read-only, 190638032Speter** we immediately release the lock to avoid freezing things up. 190738032Speter** We really ought to hold the lock, but guarantee that we won't 190838032Speter** be pokey about it. That's hard to do. 190938032Speter*/ 191038032Speter 191138032Speter/* these should be K line arguments */ 191264562Sgshapiro# if DB_VERSION_MAJOR < 2 191364562Sgshapiro# define db_cachesize cachesize 191464562Sgshapiro# define h_nelem nelem 191564562Sgshapiro# ifndef DB_CACHE_SIZE 191664562Sgshapiro# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 191764562Sgshapiro# endif /* ! DB_CACHE_SIZE */ 191864562Sgshapiro# ifndef DB_HASH_NELEM 191964562Sgshapiro# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 192064562Sgshapiro# endif /* ! DB_HASH_NELEM */ 192164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 192238032Speter 192338032Speterbool 192438032Speterbt_map_open(map, mode) 192538032Speter MAP *map; 192638032Speter int mode; 192738032Speter{ 192864562Sgshapiro# if DB_VERSION_MAJOR < 2 192938032Speter BTREEINFO btinfo; 193064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 193164562Sgshapiro# if DB_VERSION_MAJOR == 2 193238032Speter DB_INFO btinfo; 193364562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 193464562Sgshapiro# if DB_VERSION_MAJOR > 2 193564562Sgshapiro void *btinfo = NULL; 193664562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 193738032Speter 193838032Speter if (tTd(38, 2)) 193990792Sgshapiro sm_dprintf("bt_map_open(%s, %s, %d)\n", 194038032Speter map->map_mname, map->map_file, mode); 194138032Speter 194264562Sgshapiro# if DB_VERSION_MAJOR < 3 1943168515Sgshapiro memset(&btinfo, '\0', sizeof(btinfo)); 194464562Sgshapiro# ifdef DB_CACHE_SIZE 194538032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 194664562Sgshapiro# endif /* DB_CACHE_SIZE */ 194764562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 194864562Sgshapiro 194938032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 195038032Speter} 195138032Speter 195238032Speterbool 195338032Speterhash_map_open(map, mode) 195438032Speter MAP *map; 195538032Speter int mode; 195638032Speter{ 195764562Sgshapiro# if DB_VERSION_MAJOR < 2 195838032Speter HASHINFO hinfo; 195964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 196064562Sgshapiro# if DB_VERSION_MAJOR == 2 196138032Speter DB_INFO hinfo; 196264562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 196364562Sgshapiro# if DB_VERSION_MAJOR > 2 196464562Sgshapiro void *hinfo = NULL; 196564562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 196638032Speter 196738032Speter if (tTd(38, 2)) 196890792Sgshapiro sm_dprintf("hash_map_open(%s, %s, %d)\n", 196938032Speter map->map_mname, map->map_file, mode); 197038032Speter 197164562Sgshapiro# if DB_VERSION_MAJOR < 3 1972168515Sgshapiro memset(&hinfo, '\0', sizeof(hinfo)); 197364562Sgshapiro# ifdef DB_HASH_NELEM 197438032Speter hinfo.h_nelem = DB_HASH_NELEM; 197564562Sgshapiro# endif /* DB_HASH_NELEM */ 197664562Sgshapiro# ifdef DB_CACHE_SIZE 197738032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 197864562Sgshapiro# endif /* DB_CACHE_SIZE */ 197964562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 198064562Sgshapiro 198138032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 198238032Speter} 198338032Speter 198464562Sgshapirostatic bool 198538032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 198638032Speter MAP *map; 198738032Speter int mode; 198838032Speter char *mapclassname; 198938032Speter DBTYPE dbtype; 199064562Sgshapiro# if DB_VERSION_MAJOR < 2 199138032Speter const void *openinfo; 199264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 199364562Sgshapiro# if DB_VERSION_MAJOR == 2 199438032Speter DB_INFO *openinfo; 199564562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 199664562Sgshapiro# if DB_VERSION_MAJOR > 2 199764562Sgshapiro void **openinfo; 199864562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 199938032Speter{ 200038032Speter DB *db = NULL; 200138032Speter int i; 200238032Speter int omode; 200338032Speter int smode = S_IREAD; 200438032Speter int fd; 200564562Sgshapiro long sff; 200664562Sgshapiro int save_errno; 200738032Speter struct stat st; 200898121Sgshapiro char buf[MAXPATHLEN]; 200938032Speter 201038032Speter /* do initial file and directory checks */ 2011168515Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf)) 201298121Sgshapiro { 201398121Sgshapiro errno = 0; 201498121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 201598121Sgshapiro syserr("map \"%s\": map file %s name too long", 201698121Sgshapiro map->map_mname, map->map_file); 201798121Sgshapiro return false; 201898121Sgshapiro } 201938032Speter i = strlen(buf); 202038032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 202198121Sgshapiro { 2022168515Sgshapiro if (sm_strlcat(buf, ".db", sizeof(buf)) >= sizeof(buf)) 202398121Sgshapiro { 202498121Sgshapiro errno = 0; 202598121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 202698121Sgshapiro syserr("map \"%s\": map file %s name too long", 202798121Sgshapiro map->map_mname, map->map_file); 202898121Sgshapiro return false; 202998121Sgshapiro } 203098121Sgshapiro } 203138032Speter 203238032Speter mode &= O_ACCMODE; 203338032Speter omode = mode; 203438032Speter 203538032Speter sff = SFF_ROOTOK|SFF_REGONLY; 203638032Speter if (mode == O_RDWR) 203738032Speter { 203838032Speter sff |= SFF_CREAT; 203964562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 204038032Speter sff |= SFF_NOSLINK; 204164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 204238032Speter sff |= SFF_NOHLINK; 204338032Speter smode = S_IWRITE; 204438032Speter } 204538032Speter else 204638032Speter { 204764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 204838032Speter sff |= SFF_NOWLINK; 204938032Speter } 205064562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 205138032Speter sff |= SFF_SAFEDIRPATH; 205238032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 205364562Sgshapiro 205438032Speter if (i != 0) 205538032Speter { 205638032Speter char *prob = "unsafe"; 205738032Speter 205838032Speter /* cannot open this map */ 205938032Speter if (i == ENOENT) 206038032Speter prob = "missing"; 206138032Speter if (tTd(38, 2)) 206290792Sgshapiro sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i)); 206338032Speter errno = i; 206438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 206538032Speter syserr("%s map \"%s\": %s map file %s", 206638032Speter mapclassname, map->map_mname, prob, buf); 206790792Sgshapiro return false; 206838032Speter } 206938032Speter if (st.st_mode == ST_MODE_NOFILE) 207038032Speter omode |= O_CREAT|O_EXCL; 207138032Speter 207238032Speter map->map_lockfd = -1; 207338032Speter 207464562Sgshapiro# if LOCK_ON_OPEN 207538032Speter if (mode == O_RDWR) 207638032Speter omode |= O_TRUNC|O_EXLOCK; 207738032Speter else 207838032Speter omode |= O_SHLOCK; 207964562Sgshapiro# else /* LOCK_ON_OPEN */ 208038032Speter /* 208138032Speter ** Pre-lock the file to avoid race conditions. In particular, 208238032Speter ** since dbopen returns NULL if the file is zero length, we 208338032Speter ** must have a locked instance around the dbopen. 208438032Speter */ 208538032Speter 208638032Speter fd = open(buf, omode, DBMMODE); 208738032Speter if (fd < 0) 208838032Speter { 208938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 209038032Speter syserr("db_map_open: cannot pre-open database %s", buf); 209190792Sgshapiro return false; 209238032Speter } 209338032Speter 209438032Speter /* make sure no baddies slipped in just before the open... */ 209538032Speter if (filechanged(buf, fd, &st)) 209638032Speter { 209764562Sgshapiro save_errno = errno; 209838032Speter (void) close(fd); 209938032Speter errno = save_errno; 210038032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 210190792Sgshapiro return false; 210238032Speter } 210338032Speter 210438032Speter /* if new file, get the "before" bits for later filechanged check */ 210538032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 210638032Speter { 210764562Sgshapiro save_errno = errno; 210838032Speter (void) close(fd); 210938032Speter errno = save_errno; 211038032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 211138032Speter buf); 211290792Sgshapiro return false; 211338032Speter } 211438032Speter 211538032Speter /* actually lock the pre-opened file */ 211638032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 211738032Speter syserr("db_map_open: cannot lock %s", buf); 211838032Speter 211938032Speter /* set up mode bits for dbopen */ 212038032Speter if (mode == O_RDWR) 212138032Speter omode |= O_TRUNC; 212238032Speter omode &= ~(O_EXCL|O_CREAT); 212364562Sgshapiro# endif /* LOCK_ON_OPEN */ 212438032Speter 212564562Sgshapiro# if DB_VERSION_MAJOR < 2 212638032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 212764562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 212838032Speter { 212938032Speter int flags = 0; 213064562Sgshapiro# if DB_VERSION_MAJOR > 2 213164562Sgshapiro int ret; 213264562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 213338032Speter 213438032Speter if (mode == O_RDONLY) 213538032Speter flags |= DB_RDONLY; 213638032Speter if (bitset(O_CREAT, omode)) 213738032Speter flags |= DB_CREATE; 213838032Speter if (bitset(O_TRUNC, omode)) 213938032Speter flags |= DB_TRUNCATE; 2140110560Sgshapiro SM_DB_FLAG_ADD(flags); 214138032Speter 214264562Sgshapiro# if DB_VERSION_MAJOR > 2 214364562Sgshapiro ret = db_create(&db, NULL, 0); 214464562Sgshapiro# ifdef DB_CACHE_SIZE 214564562Sgshapiro if (ret == 0 && db != NULL) 214664562Sgshapiro { 214764562Sgshapiro ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 214864562Sgshapiro if (ret != 0) 214964562Sgshapiro { 215064562Sgshapiro (void) db->close(db, 0); 215164562Sgshapiro db = NULL; 215264562Sgshapiro } 215364562Sgshapiro } 215464562Sgshapiro# endif /* DB_CACHE_SIZE */ 215564562Sgshapiro# ifdef DB_HASH_NELEM 215664562Sgshapiro if (dbtype == DB_HASH && ret == 0 && db != NULL) 215764562Sgshapiro { 215864562Sgshapiro ret = db->set_h_nelem(db, DB_HASH_NELEM); 215964562Sgshapiro if (ret != 0) 216064562Sgshapiro { 216164562Sgshapiro (void) db->close(db, 0); 216264562Sgshapiro db = NULL; 216364562Sgshapiro } 216464562Sgshapiro } 216564562Sgshapiro# endif /* DB_HASH_NELEM */ 216664562Sgshapiro if (ret == 0 && db != NULL) 216764562Sgshapiro { 2168110560Sgshapiro ret = db->open(db, 2169110560Sgshapiro DBTXN /* transaction for DB 4.1 */ 2170110560Sgshapiro buf, NULL, dbtype, flags, DBMMODE); 217164562Sgshapiro if (ret != 0) 217264562Sgshapiro { 217373188Sgshapiro#ifdef DB_OLD_VERSION 217473188Sgshapiro if (ret == DB_OLD_VERSION) 217573188Sgshapiro ret = EINVAL; 217673188Sgshapiro#endif /* DB_OLD_VERSION */ 217764562Sgshapiro (void) db->close(db, 0); 217864562Sgshapiro db = NULL; 217964562Sgshapiro } 218064562Sgshapiro } 218164562Sgshapiro errno = ret; 218264562Sgshapiro# else /* DB_VERSION_MAJOR > 2 */ 218338032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 218438032Speter NULL, openinfo, &db); 218564562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 218638032Speter } 218764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 218864562Sgshapiro save_errno = errno; 218938032Speter 219064562Sgshapiro# if !LOCK_ON_OPEN 219138032Speter if (mode == O_RDWR) 219238032Speter map->map_lockfd = fd; 219338032Speter else 219438032Speter (void) close(fd); 219564562Sgshapiro# endif /* !LOCK_ON_OPEN */ 219638032Speter 219738032Speter if (db == NULL) 219838032Speter { 219938032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 220090792Sgshapiro aliaswait(map, ".db", false)) 220190792Sgshapiro return true; 220264562Sgshapiro# if !LOCK_ON_OPEN 220338032Speter if (map->map_lockfd >= 0) 220438032Speter (void) close(map->map_lockfd); 220564562Sgshapiro# endif /* !LOCK_ON_OPEN */ 220664562Sgshapiro errno = save_errno; 220738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 220838032Speter syserr("Cannot open %s database %s", 220938032Speter mapclassname, buf); 221090792Sgshapiro return false; 221138032Speter } 221238032Speter 221364562Sgshapiro# if DB_VERSION_MAJOR < 2 221438032Speter fd = db->fd(db); 221564562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 221638032Speter fd = -1; 221738032Speter errno = db->fd(db, &fd); 221864562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 221938032Speter if (filechanged(buf, fd, &st)) 222038032Speter { 222164562Sgshapiro save_errno = errno; 222264562Sgshapiro# if DB_VERSION_MAJOR < 2 222364562Sgshapiro (void) db->close(db); 222464562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 222538032Speter errno = db->close(db, 0); 222664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 222764562Sgshapiro# if !LOCK_ON_OPEN 222838032Speter if (map->map_lockfd >= 0) 222964562Sgshapiro (void) close(map->map_lockfd); 223064562Sgshapiro# endif /* !LOCK_ON_OPEN */ 223138032Speter errno = save_errno; 223238032Speter syserr("db_map_open(%s): file changed after open", buf); 223390792Sgshapiro return false; 223438032Speter } 223538032Speter 223638032Speter if (mode == O_RDWR) 223738032Speter map->map_mflags |= MF_LOCKED; 223864562Sgshapiro# if LOCK_ON_OPEN 223938032Speter if (fd >= 0 && mode == O_RDONLY) 224038032Speter { 224138032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 224238032Speter } 224364562Sgshapiro# endif /* LOCK_ON_OPEN */ 224438032Speter 224538032Speter /* try to make sure that at least the database header is on disk */ 224638032Speter if (mode == O_RDWR) 224738032Speter { 224838032Speter (void) db->sync(db, 0); 224942575Speter if (geteuid() == 0 && TrustedUid != 0) 225038032Speter { 225164562Sgshapiro# if HASFCHOWN 225242575Speter if (fchown(fd, TrustedUid, -1) < 0) 225338032Speter { 225438032Speter int err = errno; 225538032Speter 225638032Speter sm_syslog(LOG_ALERT, NOQID, 225738032Speter "ownership change on %s failed: %s", 225890792Sgshapiro buf, sm_errstring(err)); 225938032Speter message("050 ownership change on %s failed: %s", 226090792Sgshapiro buf, sm_errstring(err)); 226138032Speter } 226290792Sgshapiro# else /* HASFCHOWN */ 226390792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 226490792Sgshapiro "no fchown(): cannot change ownership on %s", 226590792Sgshapiro map->map_file); 226690792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 226790792Sgshapiro map->map_file); 226864562Sgshapiro# endif /* HASFCHOWN */ 226938032Speter } 227038032Speter } 227138032Speter 227264562Sgshapiro map->map_db2 = (ARBPTR_T) db; 227364562Sgshapiro 227464562Sgshapiro /* 227564562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 227664562Sgshapiro ** as aliaswait() will call map_lookup() which requires 227764562Sgshapiro ** map_mtime to be set 227864562Sgshapiro */ 227964562Sgshapiro 228038032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 228138032Speter map->map_mtime = st.st_mtime; 228238032Speter 228338032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 228490792Sgshapiro !aliaswait(map, ".db", true)) 228590792Sgshapiro return false; 228690792Sgshapiro return true; 228738032Speter} 228838032Speter 228938032Speter 229038032Speter/* 229138032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 229238032Speter*/ 229338032Speter 229438032Speterchar * 229538032Speterdb_map_lookup(map, name, av, statp) 229638032Speter MAP *map; 229738032Speter char *name; 229838032Speter char **av; 229938032Speter int *statp; 230038032Speter{ 230138032Speter DBT key, val; 230238032Speter register DB *db = (DB *) map->map_db2; 230338032Speter int i; 230438032Speter int st; 230564562Sgshapiro int save_errno; 230638032Speter int fd; 230738032Speter struct stat stbuf; 230838032Speter char keybuf[MAXNAME + 1]; 230998121Sgshapiro char buf[MAXPATHLEN]; 231038032Speter 2311168515Sgshapiro memset(&key, '\0', sizeof(key)); 2312168515Sgshapiro memset(&val, '\0', sizeof(val)); 231338032Speter 231438032Speter if (tTd(38, 20)) 231590792Sgshapiro sm_dprintf("db_map_lookup(%s, %s)\n", 231638032Speter map->map_mname, name); 231738032Speter 2318168515Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf)) 231998121Sgshapiro { 232098121Sgshapiro errno = 0; 232198121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 232298121Sgshapiro syserr("map \"%s\": map file %s name too long", 232398121Sgshapiro map->map_mname, map->map_file); 232498121Sgshapiro return NULL; 232598121Sgshapiro } 232698121Sgshapiro i = strlen(buf); 232738032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 232838032Speter buf[i - 3] = '\0'; 232938032Speter 233038032Speter key.size = strlen(name); 2331168515Sgshapiro if (key.size > sizeof(keybuf) - 1) 2332168515Sgshapiro key.size = sizeof(keybuf) - 1; 233338032Speter key.data = keybuf; 233464562Sgshapiro memmove(keybuf, name, key.size); 233538032Speter keybuf[key.size] = '\0'; 233638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 233738032Speter makelower(keybuf); 233838032Speter lockdb: 233964562Sgshapiro# if DB_VERSION_MAJOR < 2 234038032Speter fd = db->fd(db); 234164562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 234238032Speter fd = -1; 234338032Speter errno = db->fd(db, &fd); 234464562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 234538032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 234638032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 234738032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 234838032Speter { 234938032Speter /* Reopen the database to sync the cache */ 235038032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 235138032Speter : O_RDONLY; 235238032Speter 235364562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 235464562Sgshapiro (void) lockfile(fd, buf, ".db", LOCK_UN); 235577349Sgshapiro map->map_mflags |= MF_CLOSING; 235638032Speter map->map_class->map_close(map); 235777349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 235838032Speter if (map->map_class->map_open(map, omode)) 235938032Speter { 236038032Speter map->map_mflags |= MF_OPEN; 236190792Sgshapiro map->map_pid = CurrentPid; 236238032Speter if ((omode && O_ACCMODE) == O_RDWR) 236338032Speter map->map_mflags |= MF_WRITABLE; 236438032Speter db = (DB *) map->map_db2; 236538032Speter goto lockdb; 236638032Speter } 236738032Speter else 236838032Speter { 236938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 237038032Speter { 237138032Speter extern MAPCLASS BogusMapClass; 237238032Speter 237338032Speter *statp = EX_TEMPFAIL; 237490792Sgshapiro map->map_orgclass = map->map_class; 237538032Speter map->map_class = &BogusMapClass; 237638032Speter map->map_mflags |= MF_OPEN; 237790792Sgshapiro map->map_pid = CurrentPid; 237838032Speter syserr("Cannot reopen DB database %s", 237938032Speter map->map_file); 238038032Speter } 238138032Speter return NULL; 238238032Speter } 238338032Speter } 238438032Speter 238538032Speter st = 1; 238638032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 238738032Speter { 238864562Sgshapiro# if DB_VERSION_MAJOR < 2 238938032Speter st = db->get(db, &key, &val, 0); 239064562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 239138032Speter errno = db->get(db, NULL, &key, &val, 0); 239238032Speter switch (errno) 239338032Speter { 239438032Speter case DB_NOTFOUND: 239538032Speter case DB_KEYEMPTY: 239638032Speter st = 1; 239738032Speter break; 239838032Speter 239938032Speter case 0: 240038032Speter st = 0; 240138032Speter break; 240238032Speter 240338032Speter default: 240438032Speter st = -1; 240538032Speter break; 240638032Speter } 240764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 240838032Speter if (st == 0) 240938032Speter map->map_mflags &= ~MF_TRY1NULL; 241038032Speter } 241138032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 241238032Speter { 241338032Speter key.size++; 241464562Sgshapiro# if DB_VERSION_MAJOR < 2 241538032Speter st = db->get(db, &key, &val, 0); 241664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 241738032Speter errno = db->get(db, NULL, &key, &val, 0); 241838032Speter switch (errno) 241938032Speter { 242038032Speter case DB_NOTFOUND: 242138032Speter case DB_KEYEMPTY: 242238032Speter st = 1; 242338032Speter break; 242438032Speter 242538032Speter case 0: 242638032Speter st = 0; 242738032Speter break; 242838032Speter 242938032Speter default: 243038032Speter st = -1; 243138032Speter break; 243238032Speter } 243364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 243438032Speter if (st == 0) 243538032Speter map->map_mflags &= ~MF_TRY0NULL; 243638032Speter } 243764562Sgshapiro save_errno = errno; 243838032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 243938032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 244038032Speter if (st != 0) 244138032Speter { 244264562Sgshapiro errno = save_errno; 244338032Speter if (st < 0) 244438032Speter syserr("db_map_lookup: get (%s)", name); 244538032Speter return NULL; 244638032Speter } 244738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 244838032Speter return map_rewrite(map, name, strlen(name), NULL); 244938032Speter else 245038032Speter return map_rewrite(map, val.data, val.size, av); 245138032Speter} 245238032Speter 245338032Speter 245438032Speter/* 245538032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 245638032Speter*/ 245738032Speter 245838032Spetervoid 245938032Speterdb_map_store(map, lhs, rhs) 246038032Speter register MAP *map; 246138032Speter char *lhs; 246238032Speter char *rhs; 246338032Speter{ 246464562Sgshapiro int status; 246538032Speter DBT key; 246638032Speter DBT data; 246738032Speter register DB *db = map->map_db2; 246838032Speter char keybuf[MAXNAME + 1]; 246938032Speter 2470168515Sgshapiro memset(&key, '\0', sizeof(key)); 2471168515Sgshapiro memset(&data, '\0', sizeof(data)); 247238032Speter 247338032Speter if (tTd(38, 12)) 247490792Sgshapiro sm_dprintf("db_map_store(%s, %s, %s)\n", 247538032Speter map->map_mname, lhs, rhs); 247638032Speter 247738032Speter key.size = strlen(lhs); 247838032Speter key.data = lhs; 247938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 248038032Speter { 2481168515Sgshapiro if (key.size > sizeof(keybuf) - 1) 2482168515Sgshapiro key.size = sizeof(keybuf) - 1; 248364562Sgshapiro memmove(keybuf, key.data, key.size); 248438032Speter keybuf[key.size] = '\0'; 248538032Speter makelower(keybuf); 248638032Speter key.data = keybuf; 248738032Speter } 248838032Speter 248938032Speter data.size = strlen(rhs); 249038032Speter data.data = rhs; 249138032Speter 249238032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 249338032Speter { 249438032Speter key.size++; 249538032Speter data.size++; 249638032Speter } 249738032Speter 249864562Sgshapiro# if DB_VERSION_MAJOR < 2 249964562Sgshapiro status = db->put(db, &key, &data, R_NOOVERWRITE); 250064562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 250138032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 250238032Speter switch (errno) 250338032Speter { 250438032Speter case DB_KEYEXIST: 250564562Sgshapiro status = 1; 250638032Speter break; 250738032Speter 250838032Speter case 0: 250964562Sgshapiro status = 0; 251038032Speter break; 251138032Speter 251238032Speter default: 251364562Sgshapiro status = -1; 251438032Speter break; 251538032Speter } 251664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 251764562Sgshapiro if (status > 0) 251838032Speter { 251938032Speter if (!bitset(MF_APPEND, map->map_mflags)) 252038032Speter message("050 Warning: duplicate alias name %s", lhs); 252138032Speter else 252238032Speter { 252338032Speter static char *buf = NULL; 252438032Speter static int bufsiz = 0; 252538032Speter DBT old; 252638032Speter 2527168515Sgshapiro memset(&old, '\0', sizeof(old)); 252838032Speter 252964562Sgshapiro old.data = db_map_lookup(map, key.data, 253090792Sgshapiro (char **) NULL, &status); 253138032Speter if (old.data != NULL) 253238032Speter { 253338032Speter old.size = strlen(old.data); 253490792Sgshapiro if (data.size + old.size + 2 > (size_t) bufsiz) 253538032Speter { 253638032Speter if (buf != NULL) 253777349Sgshapiro sm_free(buf); 253838032Speter bufsiz = data.size + old.size + 2; 253990792Sgshapiro buf = sm_pmalloc_x(bufsiz); 254038032Speter } 254190792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 254290792Sgshapiro (char *) data.data, ",", 254390792Sgshapiro (char *) old.data); 254438032Speter data.size = data.size + old.size + 1; 254538032Speter data.data = buf; 254638032Speter if (tTd(38, 9)) 254790792Sgshapiro sm_dprintf("db_map_store append=%s\n", 254864562Sgshapiro (char *) data.data); 254938032Speter } 255038032Speter } 255164562Sgshapiro# if DB_VERSION_MAJOR < 2 255264562Sgshapiro status = db->put(db, &key, &data, 0); 255364562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 255464562Sgshapiro status = errno = db->put(db, NULL, &key, &data, 0); 255564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 255638032Speter } 255764562Sgshapiro if (status != 0) 255838032Speter syserr("readaliases: db put (%s)", lhs); 255938032Speter} 256038032Speter 256138032Speter 256238032Speter/* 256338032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 256438032Speter*/ 256538032Speter 256638032Spetervoid 256738032Speterdb_map_close(map) 256838032Speter MAP *map; 256938032Speter{ 257038032Speter register DB *db = map->map_db2; 257138032Speter 257238032Speter if (tTd(38, 9)) 257390792Sgshapiro sm_dprintf("db_map_close(%s, %s, %lx)\n", 257438032Speter map->map_mname, map->map_file, map->map_mflags); 257538032Speter 257638032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 257738032Speter { 257838032Speter /* write out the distinguished alias */ 257938032Speter db_map_store(map, "@", "@"); 258038032Speter } 258138032Speter 258238032Speter (void) db->sync(db, 0); 258338032Speter 258464562Sgshapiro# if !LOCK_ON_OPEN 258538032Speter if (map->map_lockfd >= 0) 258638032Speter (void) close(map->map_lockfd); 258764562Sgshapiro# endif /* !LOCK_ON_OPEN */ 258838032Speter 258964562Sgshapiro# if DB_VERSION_MAJOR < 2 259038032Speter if (db->close(db) != 0) 259164562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 259242575Speter /* 259342575Speter ** Berkeley DB can use internal shared memory 259442575Speter ** locking for its memory pool. Closing a map 259542575Speter ** opened by another process will interfere 259642575Speter ** with the shared memory and locks of the parent 259742575Speter ** process leaving things in a bad state. 259843730Speter */ 259943730Speter 260043730Speter /* 260142575Speter ** If this map was not opened by the current 260243730Speter ** process, do not close the map but recover 260342575Speter ** the file descriptor. 260442575Speter */ 260590792Sgshapiro 260690792Sgshapiro if (map->map_pid != CurrentPid) 260742575Speter { 260842575Speter int fd = -1; 260942575Speter 261042575Speter errno = db->fd(db, &fd); 261142575Speter if (fd >= 0) 261242575Speter (void) close(fd); 261342575Speter return; 261442575Speter } 261542575Speter 261638032Speter if ((errno = db->close(db, 0)) != 0) 261764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 261842575Speter syserr("db_map_close(%s, %s, %lx): db close failure", 261942575Speter map->map_mname, map->map_file, map->map_mflags); 262038032Speter} 262164562Sgshapiro#endif /* NEWDB */ 262290792Sgshapiro/* 262338032Speter** NIS Modules 262438032Speter*/ 262538032Speter 262690792Sgshapiro#if NIS 262738032Speter 262838032Speter# ifndef YPERR_BUSY 262938032Speter# define YPERR_BUSY 16 263064562Sgshapiro# endif /* ! YPERR_BUSY */ 263138032Speter 263238032Speter/* 263338032Speter** NIS_MAP_OPEN -- open DBM map 263438032Speter*/ 263538032Speter 263638032Speterbool 263738032Speternis_map_open(map, mode) 263838032Speter MAP *map; 263938032Speter int mode; 264038032Speter{ 264138032Speter int yperr; 264238032Speter register char *p; 264338032Speter auto char *vp; 264438032Speter auto int vsize; 264538032Speter 264638032Speter if (tTd(38, 2)) 264790792Sgshapiro sm_dprintf("nis_map_open(%s, %s, %d)\n", 264838032Speter map->map_mname, map->map_file, mode); 264938032Speter 265038032Speter mode &= O_ACCMODE; 265138032Speter if (mode != O_RDONLY) 265238032Speter { 265338032Speter /* issue a pseudo-error message */ 265490792Sgshapiro errno = SM_EMAPCANTWRITE; 265590792Sgshapiro return false; 265638032Speter } 265738032Speter 265838032Speter p = strchr(map->map_file, '@'); 265938032Speter if (p != NULL) 266038032Speter { 266138032Speter *p++ = '\0'; 266238032Speter if (*p != '\0') 266338032Speter map->map_domain = p; 266438032Speter } 266538032Speter 266638032Speter if (*map->map_file == '\0') 266738032Speter map->map_file = "mail.aliases"; 266838032Speter 266938032Speter if (map->map_domain == NULL) 267038032Speter { 267138032Speter yperr = yp_get_default_domain(&map->map_domain); 267238032Speter if (yperr != 0) 267338032Speter { 267438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 267594334Sgshapiro syserr("451 4.3.5 NIS map %s specified, but NIS not running", 267664562Sgshapiro map->map_file); 267790792Sgshapiro return false; 267838032Speter } 267938032Speter } 268038032Speter 268138032Speter /* check to see if this map actually exists */ 268264562Sgshapiro vp = NULL; 268338032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 268438032Speter &vp, &vsize); 268538032Speter if (tTd(38, 10)) 268690792Sgshapiro sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 268738032Speter map->map_domain, map->map_file, yperr_string(yperr)); 268864562Sgshapiro if (vp != NULL) 268977349Sgshapiro sm_free(vp); 269064562Sgshapiro 269138032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 269238032Speter { 269338032Speter /* 269438032Speter ** We ought to be calling aliaswait() here if this is an 269538032Speter ** alias file, but powerful HP-UX NIS servers apparently 269638032Speter ** don't insert the @:@ token into the alias map when it 269738032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 269838032Speter */ 269938032Speter 270064562Sgshapiro# if 0 270138032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 270290792Sgshapiro aliaswait(map, NULL, true)) 270364562Sgshapiro# endif /* 0 */ 270490792Sgshapiro return true; 270538032Speter } 270638032Speter 270738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 270838032Speter { 270994334Sgshapiro syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s", 271038032Speter map->map_file, map->map_domain, yperr_string(yperr)); 271138032Speter } 271238032Speter 271390792Sgshapiro return false; 271438032Speter} 271538032Speter 271638032Speter 271738032Speter/* 271838032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 271938032Speter*/ 272038032Speter 272138032Speter/* ARGSUSED3 */ 272238032Speterchar * 272338032Speternis_map_lookup(map, name, av, statp) 272438032Speter MAP *map; 272538032Speter char *name; 272638032Speter char **av; 272738032Speter int *statp; 272838032Speter{ 272938032Speter char *vp; 273038032Speter auto int vsize; 273138032Speter int buflen; 273238032Speter int yperr; 273338032Speter char keybuf[MAXNAME + 1]; 273490792Sgshapiro char *SM_NONVOLATILE result = NULL; 273538032Speter 273638032Speter if (tTd(38, 20)) 273790792Sgshapiro sm_dprintf("nis_map_lookup(%s, %s)\n", 273838032Speter map->map_mname, name); 273938032Speter 274038032Speter buflen = strlen(name); 2741168515Sgshapiro if (buflen > sizeof(keybuf) - 1) 2742168515Sgshapiro buflen = sizeof(keybuf) - 1; 274364562Sgshapiro memmove(keybuf, name, buflen); 274438032Speter keybuf[buflen] = '\0'; 274538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 274638032Speter makelower(keybuf); 274738032Speter yperr = YPERR_KEY; 274864562Sgshapiro vp = NULL; 274938032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 275038032Speter { 275138032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 275238032Speter &vp, &vsize); 275338032Speter if (yperr == 0) 275438032Speter map->map_mflags &= ~MF_TRY1NULL; 275538032Speter } 275638032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 275738032Speter { 275890792Sgshapiro SM_FREE_CLR(vp); 275938032Speter buflen++; 276038032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 276138032Speter &vp, &vsize); 276238032Speter if (yperr == 0) 276338032Speter map->map_mflags &= ~MF_TRY0NULL; 276438032Speter } 276538032Speter if (yperr != 0) 276638032Speter { 276738032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 276838032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 276964562Sgshapiro if (vp != NULL) 277077349Sgshapiro sm_free(vp); 277138032Speter return NULL; 277238032Speter } 277390792Sgshapiro SM_TRY 277490792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 277590792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 277690792Sgshapiro else 277790792Sgshapiro result = map_rewrite(map, vp, vsize, av); 277890792Sgshapiro SM_FINALLY 277964562Sgshapiro if (vp != NULL) 278077349Sgshapiro sm_free(vp); 278190792Sgshapiro SM_END_TRY 278290792Sgshapiro return result; 278338032Speter} 278438032Speter 278538032Speter 278638032Speter/* 278738032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 278838032Speter*/ 278938032Speter 279064562Sgshapirostatic bool 279138032Speternis_getcanonname(name, hbsize, statp) 279238032Speter char *name; 279338032Speter int hbsize; 279438032Speter int *statp; 279538032Speter{ 279638032Speter char *vp; 279738032Speter auto int vsize; 279838032Speter int keylen; 279938032Speter int yperr; 280090792Sgshapiro static bool try0null = true; 280190792Sgshapiro static bool try1null = true; 280238032Speter static char *yp_domain = NULL; 280338032Speter char host_record[MAXLINE]; 280438032Speter char cbuf[MAXNAME]; 280538032Speter char nbuf[MAXNAME + 1]; 280638032Speter 280738032Speter if (tTd(38, 20)) 280890792Sgshapiro sm_dprintf("nis_getcanonname(%s)\n", name); 280938032Speter 2810168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 281138032Speter { 281238032Speter *statp = EX_UNAVAILABLE; 281390792Sgshapiro return false; 281438032Speter } 281573188Sgshapiro (void) shorten_hostname(nbuf); 281638032Speter keylen = strlen(nbuf); 281738032Speter 281838032Speter if (yp_domain == NULL) 281964562Sgshapiro (void) yp_get_default_domain(&yp_domain); 282038032Speter makelower(nbuf); 282138032Speter yperr = YPERR_KEY; 282264562Sgshapiro vp = NULL; 282338032Speter if (try0null) 282438032Speter { 282538032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 282638032Speter &vp, &vsize); 282738032Speter if (yperr == 0) 282890792Sgshapiro try1null = false; 282938032Speter } 283038032Speter if (yperr == YPERR_KEY && try1null) 283138032Speter { 283290792Sgshapiro SM_FREE_CLR(vp); 283338032Speter keylen++; 283438032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 283538032Speter &vp, &vsize); 283638032Speter if (yperr == 0) 283790792Sgshapiro try0null = false; 283838032Speter } 283938032Speter if (yperr != 0) 284038032Speter { 284138032Speter if (yperr == YPERR_KEY) 284238032Speter *statp = EX_NOHOST; 284338032Speter else if (yperr == YPERR_BUSY) 284438032Speter *statp = EX_TEMPFAIL; 284538032Speter else 284638032Speter *statp = EX_UNAVAILABLE; 284764562Sgshapiro if (vp != NULL) 284877349Sgshapiro sm_free(vp); 284990792Sgshapiro return false; 285038032Speter } 2851168515Sgshapiro (void) sm_strlcpy(host_record, vp, sizeof(host_record)); 285277349Sgshapiro sm_free(vp); 285338032Speter if (tTd(38, 44)) 285490792Sgshapiro sm_dprintf("got record `%s'\n", host_record); 285590792Sgshapiro vp = strpbrk(host_record, "#\n"); 285690792Sgshapiro if (vp != NULL) 285790792Sgshapiro *vp = '\0'; 2858168515Sgshapiro if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof(cbuf))) 285938032Speter { 286038032Speter /* this should not happen, but.... */ 286138032Speter *statp = EX_NOHOST; 286290792Sgshapiro return false; 286338032Speter } 286490792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 286538032Speter { 286638032Speter *statp = EX_UNAVAILABLE; 286790792Sgshapiro return false; 286838032Speter } 286938032Speter *statp = EX_OK; 287090792Sgshapiro return true; 287138032Speter} 287238032Speter 287364562Sgshapiro#endif /* NIS */ 287490792Sgshapiro/* 287538032Speter** NISPLUS Modules 287638032Speter** 287738032Speter** This code donated by Sun Microsystems. 287838032Speter*/ 287938032Speter 288090792Sgshapiro#if NISPLUS 288138032Speter 288264562Sgshapiro# undef NIS /* symbol conflict in nis.h */ 288364562Sgshapiro# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 288464562Sgshapiro# include <rpcsvc/nis.h> 288564562Sgshapiro# include <rpcsvc/nislib.h> 288638032Speter 288764562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 288864562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 288964562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 289064562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 289138032Speter 289238032Speter/* 289338032Speter** NISPLUS_MAP_OPEN -- open nisplus table 289438032Speter*/ 289538032Speter 289638032Speterbool 289738032Speternisplus_map_open(map, mode) 289838032Speter MAP *map; 289938032Speter int mode; 290038032Speter{ 290138032Speter nis_result *res = NULL; 290238032Speter int retry_cnt, max_col, i; 290338032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 290438032Speter 290538032Speter if (tTd(38, 2)) 290690792Sgshapiro sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 290738032Speter map->map_mname, map->map_file, mode); 290838032Speter 290938032Speter mode &= O_ACCMODE; 291038032Speter if (mode != O_RDONLY) 291138032Speter { 291238032Speter errno = EPERM; 291390792Sgshapiro return false; 291438032Speter } 291538032Speter 291638032Speter if (*map->map_file == '\0') 291738032Speter map->map_file = "mail_aliases.org_dir"; 291838032Speter 291938032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 292038032Speter { 292138032Speter /* set default NISPLUS Domain to $m */ 292238032Speter map->map_domain = newstr(nisplus_default_domain()); 292338032Speter if (tTd(38, 2)) 292490792Sgshapiro sm_dprintf("nisplus_map_open(%s): using domain %s\n", 292564562Sgshapiro map->map_file, map->map_domain); 292638032Speter } 292738032Speter if (!PARTIAL_NAME(map->map_file)) 292838032Speter { 292938032Speter map->map_domain = newstr(""); 2930168515Sgshapiro (void) sm_strlcpy(qbuf, map->map_file, sizeof(qbuf)); 293138032Speter } 293238032Speter else 293338032Speter { 293438032Speter /* check to see if this map actually exists */ 2935168515Sgshapiro (void) sm_strlcpyn(qbuf, sizeof(qbuf), 3, 293690792Sgshapiro map->map_file, ".", map->map_domain); 293738032Speter } 293838032Speter 293938032Speter retry_cnt = 0; 294038032Speter while (res == NULL || res->status != NIS_SUCCESS) 294138032Speter { 294238032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 294338032Speter switch (res->status) 294438032Speter { 294538032Speter case NIS_SUCCESS: 294638032Speter break; 294738032Speter 294838032Speter case NIS_TRYAGAIN: 294938032Speter case NIS_RPCERROR: 295038032Speter case NIS_NAMEUNREACHABLE: 295138032Speter if (retry_cnt++ > 4) 295238032Speter { 295338032Speter errno = EAGAIN; 295490792Sgshapiro return false; 295538032Speter } 295638032Speter /* try not to overwhelm hosed server */ 295738032Speter sleep(2); 295838032Speter break; 295938032Speter 296038032Speter default: /* all other nisplus errors */ 296164562Sgshapiro# if 0 296238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 296394334Sgshapiro syserr("451 4.3.5 Cannot find table %s.%s: %s", 296438032Speter map->map_file, map->map_domain, 296538032Speter nis_sperrno(res->status)); 296664562Sgshapiro# endif /* 0 */ 296738032Speter errno = EAGAIN; 296890792Sgshapiro return false; 296938032Speter } 297038032Speter } 297138032Speter 297238032Speter if (NIS_RES_NUMOBJ(res) != 1 || 297338032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 297438032Speter { 297538032Speter if (tTd(38, 10)) 297690792Sgshapiro sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 297764562Sgshapiro# if 0 297838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 297994334Sgshapiro syserr("451 4.3.5 %s.%s: %s is not a table", 298038032Speter map->map_file, map->map_domain, 298138032Speter nis_sperrno(res->status)); 298264562Sgshapiro# endif /* 0 */ 298338032Speter errno = EBADF; 298490792Sgshapiro return false; 298538032Speter } 298638032Speter /* default key column is column 0 */ 298738032Speter if (map->map_keycolnm == NULL) 298838032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 298938032Speter 299038032Speter max_col = COL_MAX(res); 299138032Speter 299238032Speter /* verify the key column exist */ 299390792Sgshapiro for (i = 0; i < max_col; i++) 299438032Speter { 299564562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 299638032Speter break; 299738032Speter } 299838032Speter if (i == max_col) 299938032Speter { 300038032Speter if (tTd(38, 2)) 300190792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 300238032Speter map->map_file, map->map_keycolnm); 300338032Speter errno = ENOENT; 300490792Sgshapiro return false; 300538032Speter } 300638032Speter 300738032Speter /* default value column is the last column */ 300838032Speter if (map->map_valcolnm == NULL) 300938032Speter { 301038032Speter map->map_valcolno = max_col - 1; 301190792Sgshapiro return true; 301238032Speter } 301338032Speter 301464562Sgshapiro for (i = 0; i< max_col; i++) 301538032Speter { 301638032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 301738032Speter { 301838032Speter map->map_valcolno = i; 301990792Sgshapiro return true; 302038032Speter } 302138032Speter } 302238032Speter 302338032Speter if (tTd(38, 2)) 302490792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 302564562Sgshapiro map->map_file, map->map_keycolnm); 302638032Speter errno = ENOENT; 302790792Sgshapiro return false; 302838032Speter} 302938032Speter 303038032Speter 303138032Speter/* 303238032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 303338032Speter*/ 303438032Speter 303538032Speterchar * 303638032Speternisplus_map_lookup(map, name, av, statp) 303738032Speter MAP *map; 303838032Speter char *name; 303938032Speter char **av; 304038032Speter int *statp; 304138032Speter{ 304238032Speter char *p; 304338032Speter auto int vsize; 304438032Speter char *skp; 304538032Speter int skleft; 304638032Speter char search_key[MAXNAME + 4]; 304738032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 304838032Speter nis_result *result; 304938032Speter 305038032Speter if (tTd(38, 20)) 305190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s, %s)\n", 305238032Speter map->map_mname, name); 305338032Speter 305438032Speter if (!bitset(MF_OPEN, map->map_mflags)) 305538032Speter { 305638032Speter if (nisplus_map_open(map, O_RDONLY)) 305742575Speter { 305838032Speter map->map_mflags |= MF_OPEN; 305990792Sgshapiro map->map_pid = CurrentPid; 306042575Speter } 306138032Speter else 306238032Speter { 306338032Speter *statp = EX_UNAVAILABLE; 306438032Speter return NULL; 306538032Speter } 306638032Speter } 306738032Speter 306838032Speter /* 306938032Speter ** Copy the name to the key buffer, escaping double quote characters 307038032Speter ** by doubling them and quoting "]" and "," to avoid having the 307138032Speter ** NIS+ parser choke on them. 307238032Speter */ 307338032Speter 3074168515Sgshapiro skleft = sizeof(search_key) - 4; 307538032Speter skp = search_key; 307638032Speter for (p = name; *p != '\0' && skleft > 0; p++) 307738032Speter { 307838032Speter switch (*p) 307938032Speter { 308038032Speter case ']': 308138032Speter case ',': 308238032Speter /* quote the character */ 308338032Speter *skp++ = '"'; 308438032Speter *skp++ = *p; 308538032Speter *skp++ = '"'; 308638032Speter skleft -= 3; 308738032Speter break; 308838032Speter 308938032Speter case '"': 309038032Speter /* double the quote */ 309138032Speter *skp++ = '"'; 309238032Speter skleft--; 309364562Sgshapiro /* FALLTHROUGH */ 309438032Speter 309538032Speter default: 309638032Speter *skp++ = *p; 309738032Speter skleft--; 309838032Speter break; 309938032Speter } 310038032Speter } 310138032Speter *skp = '\0'; 310238032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 310338032Speter makelower(search_key); 310438032Speter 310538032Speter /* construct the query */ 310638032Speter if (PARTIAL_NAME(map->map_file)) 3107168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s.%s", 310838032Speter map->map_keycolnm, search_key, map->map_file, 310938032Speter map->map_domain); 311038032Speter else 3111168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s", 311238032Speter map->map_keycolnm, search_key, map->map_file); 311338032Speter 311438032Speter if (tTd(38, 20)) 311590792Sgshapiro sm_dprintf("qbuf=%s\n", qbuf); 311638032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 311738032Speter if (result->status == NIS_SUCCESS) 311838032Speter { 311938032Speter int count; 312038032Speter char *str; 312138032Speter 312238032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 312338032Speter { 312438032Speter if (LogLevel > 10) 312538032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 312664562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 312764562Sgshapiro map->map_file, count); 312838032Speter 312938032Speter /* ignore second entry */ 313038032Speter if (tTd(38, 20)) 313190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 313238032Speter name, count); 313338032Speter } 313438032Speter 313538032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 313638032Speter /* set the length of the result */ 313738032Speter if (p == NULL) 313838032Speter p = ""; 313938032Speter vsize = strlen(p); 314038032Speter if (tTd(38, 20)) 314190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), found %s\n", 314238032Speter name, p); 314338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 314438032Speter str = map_rewrite(map, name, strlen(name), NULL); 314538032Speter else 314638032Speter str = map_rewrite(map, p, vsize, av); 314738032Speter nis_freeresult(result); 314838032Speter *statp = EX_OK; 314938032Speter return str; 315038032Speter } 315138032Speter else 315238032Speter { 315338032Speter if (result->status == NIS_NOTFOUND) 315438032Speter *statp = EX_NOTFOUND; 315538032Speter else if (result->status == NIS_TRYAGAIN) 315638032Speter *statp = EX_TEMPFAIL; 315738032Speter else 315838032Speter { 315938032Speter *statp = EX_UNAVAILABLE; 316038032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 316138032Speter } 316238032Speter } 316338032Speter if (tTd(38, 20)) 316490792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 316538032Speter nis_freeresult(result); 316638032Speter return NULL; 316738032Speter} 316838032Speter 316938032Speter 317038032Speter 317138032Speter/* 317238032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 317338032Speter*/ 317438032Speter 317564562Sgshapirostatic bool 317638032Speternisplus_getcanonname(name, hbsize, statp) 317738032Speter char *name; 317838032Speter int hbsize; 317938032Speter int *statp; 318038032Speter{ 318138032Speter char *vp; 318238032Speter auto int vsize; 318338032Speter nis_result *result; 318438032Speter char *p; 318538032Speter char nbuf[MAXNAME + 1]; 318638032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 318738032Speter 3188168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 318938032Speter { 319038032Speter *statp = EX_UNAVAILABLE; 319190792Sgshapiro return false; 319238032Speter } 319373188Sgshapiro (void) shorten_hostname(nbuf); 319438032Speter 319538032Speter p = strchr(nbuf, '.'); 319638032Speter if (p == NULL) 319738032Speter { 319838032Speter /* single token */ 3199168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 320090792Sgshapiro "[name=%s],hosts.org_dir", nbuf); 320138032Speter } 320238032Speter else if (p[1] != '\0') 320338032Speter { 320438032Speter /* multi token -- take only first token in nbuf */ 320538032Speter *p = '\0'; 3206168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 320790792Sgshapiro "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 320838032Speter } 320938032Speter else 321038032Speter { 321138032Speter *statp = EX_NOHOST; 321290792Sgshapiro return false; 321338032Speter } 321438032Speter 321538032Speter if (tTd(38, 20)) 321694334Sgshapiro sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 321790792Sgshapiro name, qbuf); 321838032Speter 321938032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 322090792Sgshapiro NULL, NULL); 322138032Speter 322238032Speter if (result->status == NIS_SUCCESS) 322338032Speter { 322438032Speter int count; 322538032Speter char *domain; 322638032Speter 322738032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 322838032Speter { 322938032Speter if (LogLevel > 10) 323038032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 323164562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 323264562Sgshapiro count); 323338032Speter 323438032Speter /* ignore second entry */ 323538032Speter if (tTd(38, 20)) 323694334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 323790792Sgshapiro name, count); 323838032Speter } 323938032Speter 324038032Speter if (tTd(38, 20)) 324194334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 324290792Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 324338032Speter 324438032Speter 324538032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 324638032Speter vsize = strlen(vp); 324738032Speter if (tTd(38, 20)) 324890792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found %s\n", 324990792Sgshapiro name, vp); 325038032Speter if (strchr(vp, '.') != NULL) 325138032Speter { 325238032Speter domain = ""; 325338032Speter } 325438032Speter else 325538032Speter { 325638032Speter domain = macvalue('m', CurEnv); 325738032Speter if (domain == NULL) 325838032Speter domain = ""; 325938032Speter } 326038032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 326138032Speter { 326238032Speter if (domain[0] == '\0') 326390792Sgshapiro (void) sm_strlcpy(name, vp, hbsize); 326438032Speter else 326590792Sgshapiro (void) sm_snprintf(name, hbsize, 326690792Sgshapiro "%s.%s", vp, domain); 326738032Speter *statp = EX_OK; 326838032Speter } 326938032Speter else 327038032Speter *statp = EX_NOHOST; 327138032Speter nis_freeresult(result); 327290792Sgshapiro return true; 327338032Speter } 327438032Speter else 327538032Speter { 327638032Speter if (result->status == NIS_NOTFOUND) 327738032Speter *statp = EX_NOHOST; 327838032Speter else if (result->status == NIS_TRYAGAIN) 327938032Speter *statp = EX_TEMPFAIL; 328038032Speter else 328138032Speter *statp = EX_UNAVAILABLE; 328238032Speter } 328338032Speter if (tTd(38, 20)) 328490792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 328590792Sgshapiro name, result->status, *statp); 328638032Speter nis_freeresult(result); 328790792Sgshapiro return false; 328838032Speter} 328938032Speter 329038032Speterchar * 329138032Speternisplus_default_domain() 329238032Speter{ 329338032Speter static char default_domain[MAXNAME + 1] = ""; 329438032Speter char *p; 329538032Speter 329638032Speter if (default_domain[0] != '\0') 329764562Sgshapiro return default_domain; 329838032Speter 329938032Speter p = nis_local_directory(); 3300168515Sgshapiro (void) sm_strlcpy(default_domain, p, sizeof(default_domain)); 330138032Speter return default_domain; 330238032Speter} 330338032Speter 330438032Speter#endif /* NISPLUS */ 330590792Sgshapiro/* 330638032Speter** LDAP Modules 330738032Speter*/ 330838032Speter 330964562Sgshapiro/* 331064562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 331164562Sgshapiro*/ 331264562Sgshapiro 331364562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 331464562Sgshapiro 331590792Sgshapiro# if PH_MAP 331664562Sgshapiro# define ph_map_dequote ldapmap_dequote 331764562Sgshapiro# endif /* PH_MAP */ 331864562Sgshapiro 331990792Sgshapirostatic char *ldapmap_dequote __P((char *)); 332090792Sgshapiro 332190792Sgshapirostatic char * 332264562Sgshapiroldapmap_dequote(str) 332364562Sgshapiro char *str; 332464562Sgshapiro{ 332564562Sgshapiro char *p; 332664562Sgshapiro char *start; 332764562Sgshapiro 332864562Sgshapiro if (str == NULL) 332964562Sgshapiro return NULL; 333064562Sgshapiro 333164562Sgshapiro p = str; 333264562Sgshapiro if (*p == '"') 333364562Sgshapiro { 333464562Sgshapiro /* Should probably swallow initial whitespace here */ 333564562Sgshapiro start = ++p; 333664562Sgshapiro } 333764562Sgshapiro else 333864562Sgshapiro return str; 333964562Sgshapiro while (*p != '"' && *p != '\0') 334064562Sgshapiro p++; 334164562Sgshapiro if (*p != '\0') 334264562Sgshapiro *p = '\0'; 334364562Sgshapiro return start; 334464562Sgshapiro} 334564562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 334664562Sgshapiro 334790792Sgshapiro#if LDAPMAP 334838032Speter 334990792Sgshapirostatic SM_LDAP_STRUCT *LDAPDefaults = NULL; 335038032Speter 335138032Speter/* 335264562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 335338032Speter** 335464562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 335564562Sgshapiro** single server connection to a host (with the same host, port, 335664562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 335738032Speter*/ 335838032Speter 335938032Speterbool 336064562Sgshapiroldapmap_open(map, mode) 336138032Speter MAP *map; 336238032Speter int mode; 336338032Speter{ 336490792Sgshapiro SM_LDAP_STRUCT *lmap; 336564562Sgshapiro STAB *s; 3366132943Sgshapiro char *id; 336764562Sgshapiro 336838032Speter if (tTd(38, 2)) 336990792Sgshapiro sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 337038032Speter 3371168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3372168515Sgshapiro HASLDAPGETALIASBYNAME 3373168515Sgshapiro if (VendorCode == VENDOR_SUN && 3374168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3375168515Sgshapiro { 3376168515Sgshapiro return true; 3377168515Sgshapiro } 3378168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3379168515Sgshapiro 338038032Speter mode &= O_ACCMODE; 338164562Sgshapiro 338264562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 338338032Speter if (mode != O_RDONLY) 338438032Speter { 338538032Speter /* issue a pseudo-error message */ 338690792Sgshapiro errno = SM_EMAPCANTWRITE; 338790792Sgshapiro return false; 338838032Speter } 338964562Sgshapiro 339090792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 339164562Sgshapiro 339264562Sgshapiro s = ldapmap_findconn(lmap); 339377349Sgshapiro if (s->s_lmap != NULL) 339464562Sgshapiro { 339564562Sgshapiro /* Already have a connection open to this LDAP server */ 339690792Sgshapiro lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 339790792Sgshapiro lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 339877349Sgshapiro 339977349Sgshapiro /* Add this map as head of linked list */ 340077349Sgshapiro lmap->ldap_next = s->s_lmap; 340177349Sgshapiro s->s_lmap = map; 340277349Sgshapiro 340366494Sgshapiro if (tTd(38, 2)) 340490792Sgshapiro sm_dprintf("using cached connection\n"); 340590792Sgshapiro return true; 340664562Sgshapiro } 340764562Sgshapiro 340866494Sgshapiro if (tTd(38, 2)) 340990792Sgshapiro sm_dprintf("opening new connection\n"); 341066494Sgshapiro 3411132943Sgshapiro if (lmap->ldap_host != NULL) 3412132943Sgshapiro id = lmap->ldap_host; 3413132943Sgshapiro else if (lmap->ldap_uri != NULL) 3414132943Sgshapiro id = lmap->ldap_uri; 3415132943Sgshapiro else 3416132943Sgshapiro id = "localhost"; 3417132943Sgshapiro 341864562Sgshapiro /* No connection yet, connect */ 341990792Sgshapiro if (!sm_ldap_start(map->map_mname, lmap)) 342038032Speter { 342190792Sgshapiro if (errno == ETIMEDOUT) 342238032Speter { 342338032Speter if (LogLevel > 1) 342438032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 342564562Sgshapiro "timeout conning to LDAP server %.100s", 3426132943Sgshapiro id); 342738032Speter } 342838032Speter 342938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 343038032Speter { 343164562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3432132943Sgshapiro { 343364562Sgshapiro syserr("%s failed to %s in map %s", 343464562Sgshapiro# if USE_LDAP_INIT 343590792Sgshapiro "ldap_init/ldap_bind", 343664562Sgshapiro# else /* USE_LDAP_INIT */ 343764562Sgshapiro "ldap_open", 343864562Sgshapiro# endif /* USE_LDAP_INIT */ 3439132943Sgshapiro id, map->map_mname); 3440132943Sgshapiro } 344164562Sgshapiro else 3442132943Sgshapiro { 344394334Sgshapiro syserr("451 4.3.5 %s failed to %s in map %s", 344464562Sgshapiro# if USE_LDAP_INIT 344590792Sgshapiro "ldap_init/ldap_bind", 344664562Sgshapiro# else /* USE_LDAP_INIT */ 344764562Sgshapiro "ldap_open", 344864562Sgshapiro# endif /* USE_LDAP_INIT */ 3449132943Sgshapiro id, map->map_mname); 3450132943Sgshapiro } 345138032Speter } 345290792Sgshapiro return false; 345338032Speter } 345438032Speter 345590792Sgshapiro /* Save connection for reuse */ 345690792Sgshapiro s->s_lmap = map; 345790792Sgshapiro return true; 345838032Speter} 345938032Speter 346038032Speter/* 346164562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 346238032Speter*/ 346338032Speter 346438032Spetervoid 346564562Sgshapiroldapmap_close(map) 346638032Speter MAP *map; 346738032Speter{ 346890792Sgshapiro SM_LDAP_STRUCT *lmap; 346964562Sgshapiro STAB *s; 347043730Speter 347164562Sgshapiro if (tTd(38, 2)) 347290792Sgshapiro sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 347364562Sgshapiro 347490792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 347564562Sgshapiro 347664562Sgshapiro /* Check if already closed */ 347764562Sgshapiro if (lmap->ldap_ld == NULL) 347864562Sgshapiro return; 347964562Sgshapiro 348077349Sgshapiro /* Close the LDAP connection */ 348190792Sgshapiro sm_ldap_close(lmap); 348277349Sgshapiro 348377349Sgshapiro /* Mark all the maps that share the connection as closed */ 348464562Sgshapiro s = ldapmap_findconn(lmap); 348564562Sgshapiro 348677349Sgshapiro while (s->s_lmap != NULL) 348777349Sgshapiro { 348877349Sgshapiro MAP *smap = s->s_lmap; 348964562Sgshapiro 349077349Sgshapiro if (tTd(38, 2) && smap != map) 349190792Sgshapiro sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 349290792Sgshapiro map->map_mname, smap->map_mname); 349377349Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 349490792Sgshapiro lmap = (SM_LDAP_STRUCT *) smap->map_db1; 349564562Sgshapiro lmap->ldap_ld = NULL; 349677349Sgshapiro s->s_lmap = lmap->ldap_next; 349777349Sgshapiro lmap->ldap_next = NULL; 349843730Speter } 349938032Speter} 350038032Speter 350164562Sgshapiro# ifdef SUNET_ID 350243730Speter/* 350390792Sgshapiro** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 350442575Speter** This only makes sense at Stanford University. 350538032Speter*/ 350638032Speter 350790792Sgshapirostatic char * 350838032Spetersunet_id_hash(str) 350938032Speter char *str; 351038032Speter{ 351138032Speter char *p, *p_last; 351238032Speter 351338032Speter p = str; 351438032Speter p_last = p; 351538032Speter while (*p != '\0') 351638032Speter { 351738032Speter if (islower(*p) || isdigit(*p)) 351838032Speter { 351938032Speter *p_last = *p; 352038032Speter p_last++; 352138032Speter } 352238032Speter else if (isupper(*p)) 352338032Speter { 352438032Speter *p_last = tolower(*p); 352538032Speter p_last++; 352638032Speter } 352738032Speter ++p; 352838032Speter } 352938032Speter if (*p_last != '\0') 353038032Speter *p_last = '\0'; 353164562Sgshapiro return str; 353238032Speter} 3533168515Sgshapiro# define SM_CONVERT_ID(str) sunet_id_hash(str) 3534168515Sgshapiro# else /* SUNET_ID */ 3535168515Sgshapiro# define SM_CONVERT_ID(str) makelower(str) 353664562Sgshapiro# endif /* SUNET_ID */ 353738032Speter 353838032Speter/* 353964562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 354038032Speter*/ 354138032Speter 354238032Speterchar * 354364562Sgshapiroldapmap_lookup(map, name, av, statp) 354438032Speter MAP *map; 354538032Speter char *name; 354638032Speter char **av; 354738032Speter int *statp; 354838032Speter{ 3549132943Sgshapiro int flags; 3550168515Sgshapiro int i; 355194334Sgshapiro int plen = 0; 355294334Sgshapiro int psize = 0; 355364562Sgshapiro int msgid; 355490792Sgshapiro int save_errno; 355590792Sgshapiro char *vp, *p; 355664562Sgshapiro char *result = NULL; 3557132943Sgshapiro SM_RPOOL_T *rpool; 355890792Sgshapiro SM_LDAP_STRUCT *lmap = NULL; 3559168515Sgshapiro char *argv[SM_LDAP_ARGS]; 3560157001Sgshapiro char keybuf[MAXKEY]; 3561168515Sgshapiro#if SM_LDAP_ARGS != MAX_MAP_ARGS 3562168515Sgshapiro# ERROR _SM_LDAP_ARGS must be the same as _MAX_MAP_ARGS 3563168515Sgshapiro#endif /* SM_LDAP_ARGS != MAX_MAP_ARGS */ 356438032Speter 3565168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3566168515Sgshapiro HASLDAPGETALIASBYNAME 3567168515Sgshapiro if (VendorCode == VENDOR_SUN && 3568168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3569168515Sgshapiro { 3570168515Sgshapiro char answer[MAXNAME + 1]; 3571168515Sgshapiro int rc; 357238032Speter 3573168515Sgshapiro rc = __getldapaliasbyname(name, answer, sizeof(answer)); 3574168515Sgshapiro if (rc != 0) 3575168515Sgshapiro { 3576168515Sgshapiro if (tTd(38, 20)) 3577168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n", 3578168515Sgshapiro name, errno); 3579168515Sgshapiro *statp = EX_NOTFOUND; 3580168515Sgshapiro return NULL; 3581168515Sgshapiro } 3582168515Sgshapiro *statp = EX_OK; 3583168515Sgshapiro if (tTd(38, 20)) 3584168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name, 3585168515Sgshapiro answer); 3586168515Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3587168515Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 3588168515Sgshapiro else 3589168515Sgshapiro result = map_rewrite(map, answer, strlen(answer), av); 3590168515Sgshapiro return result; 3591168515Sgshapiro } 3592168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3593168515Sgshapiro 359438032Speter /* Get ldap struct pointer from map */ 359590792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 359690792Sgshapiro sm_ldap_setopts(lmap->ldap_ld, lmap); 359738032Speter 3598168515Sgshapiro if (lmap->ldap_multi_args) 3599168515Sgshapiro { 3600168515Sgshapiro SM_REQUIRE(av != NULL); 3601168515Sgshapiro memset(argv, '\0', sizeof(argv)); 3602168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && av[i] != NULL; i++) 3603168515Sgshapiro { 3604168515Sgshapiro argv[i] = sm_strdup(av[i]); 3605168515Sgshapiro if (argv[i] == NULL) 3606168515Sgshapiro { 3607168515Sgshapiro int save_errno, j; 360838032Speter 3609168515Sgshapiro save_errno = errno; 3610168515Sgshapiro for (j = 0; j < i && argv[j] != NULL; j++) 3611168515Sgshapiro SM_FREE(argv[j]); 3612168515Sgshapiro *statp = EX_TEMPFAIL; 3613168515Sgshapiro errno = save_errno; 3614168515Sgshapiro return NULL; 3615168515Sgshapiro } 3616168515Sgshapiro 3617168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 3618168515Sgshapiro SM_CONVERT_ID(av[i]); 3619168515Sgshapiro } 3620168515Sgshapiro } 3621168515Sgshapiro else 362264562Sgshapiro { 3623168515Sgshapiro (void) sm_strlcpy(keybuf, name, sizeof(keybuf)); 3624168515Sgshapiro 3625168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 3626168515Sgshapiro SM_CONVERT_ID(keybuf); 362764562Sgshapiro } 362838032Speter 3629168515Sgshapiro if (tTd(38, 20)) 363038032Speter { 3631168515Sgshapiro if (lmap->ldap_multi_args) 3632168515Sgshapiro { 3633168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, argv)\n", 3634168515Sgshapiro map->map_mname); 3635168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS; i++) 3636168515Sgshapiro { 3637168515Sgshapiro sm_dprintf(" argv[%d] = %s\n", i, 3638168515Sgshapiro argv[i] == NULL ? "NULL" : argv[i]); 3639168515Sgshapiro } 3640168515Sgshapiro } 3641168515Sgshapiro else 3642168515Sgshapiro { 3643168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, %s)\n", 3644168515Sgshapiro map->map_mname, name); 3645168515Sgshapiro } 3646168515Sgshapiro } 3647168515Sgshapiro 3648168515Sgshapiro if (lmap->ldap_multi_args) 3649168515Sgshapiro { 3650168515Sgshapiro msgid = sm_ldap_search_m(lmap, argv); 3651168515Sgshapiro 3652168515Sgshapiro /* free the argv array and its content, no longer needed */ 3653168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && argv[i] != NULL; i++) 3654168515Sgshapiro SM_FREE(argv[i]); 3655168515Sgshapiro } 3656168515Sgshapiro else 3657168515Sgshapiro msgid = sm_ldap_search(lmap, keybuf); 3658168515Sgshapiro if (msgid == SM_LDAP_ERR) 3659168515Sgshapiro { 366090792Sgshapiro errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 366177349Sgshapiro save_errno = errno; 366264562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 366338032Speter { 3664168515Sgshapiro /* 3665168515Sgshapiro ** Do not include keybuf as this error may be shown 3666168515Sgshapiro ** to outsiders. 3667168515Sgshapiro */ 3668168515Sgshapiro 366964562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3670168515Sgshapiro syserr("Error in ldap_search in map %s", 3671168515Sgshapiro map->map_mname); 367264562Sgshapiro else 3673168515Sgshapiro syserr("451 4.3.5 Error in ldap_search in map %s", 3674168515Sgshapiro map->map_mname); 367538032Speter } 367664562Sgshapiro *statp = EX_TEMPFAIL; 367790792Sgshapiro switch (save_errno - E_LDAPBASE) 367890792Sgshapiro { 367994334Sgshapiro# ifdef LDAP_SERVER_DOWN 368090792Sgshapiro case LDAP_SERVER_DOWN: 368194334Sgshapiro# endif /* LDAP_SERVER_DOWN */ 368290792Sgshapiro case LDAP_TIMEOUT: 368390792Sgshapiro case LDAP_UNAVAILABLE: 368466494Sgshapiro /* server disappeared, try reopen on next search */ 368577349Sgshapiro ldapmap_close(map); 368690792Sgshapiro break; 368766494Sgshapiro } 368877349Sgshapiro errno = save_errno; 368964562Sgshapiro return NULL; 369064562Sgshapiro } 3691168515Sgshapiro#if SM_LDAP_ERROR_ON_MISSING_ARGS 3692168515Sgshapiro else if (msgid == SM_LDAP_ERR_ARG_MISS) 3693168515Sgshapiro { 3694168515Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3695168515Sgshapiro syserr("Error in ldap_search in map %s, too few arguments", 3696168515Sgshapiro map->map_mname); 3697168515Sgshapiro else 3698168515Sgshapiro syserr("554 5.3.5 Error in ldap_search in map %s, too few arguments", 3699168515Sgshapiro map->map_mname); 3700168515Sgshapiro *statp = EX_CONFIG; 3701168515Sgshapiro return NULL; 3702168515Sgshapiro } 3703168515Sgshapiro#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 370464562Sgshapiro 370564562Sgshapiro *statp = EX_NOTFOUND; 370664562Sgshapiro vp = NULL; 370764562Sgshapiro 3708132943Sgshapiro flags = 0; 3709132943Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 3710132943Sgshapiro flags |= SM_LDAP_SINGLEMATCH; 3711132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3712132943Sgshapiro flags |= SM_LDAP_MATCHONLY; 3713157001Sgshapiro# if _FFR_LDAP_SINGLEDN 3714157001Sgshapiro if (bitset(MF_SINGLEDN, map->map_mflags)) 3715157001Sgshapiro flags |= SM_LDAP_SINGLEDN; 3716157001Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 371790792Sgshapiro 3718132943Sgshapiro /* Create an rpool for search related memory usage */ 3719132943Sgshapiro rpool = sm_rpool_new_x(NULL); 372090792Sgshapiro 3721132943Sgshapiro p = NULL; 3722132943Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 3723132943Sgshapiro rpool, &p, &plen, &psize, NULL); 3724132943Sgshapiro save_errno = errno; 372590792Sgshapiro 3726132943Sgshapiro /* Copy result so rpool can be freed */ 3727132943Sgshapiro if (*statp == EX_OK && p != NULL) 3728132943Sgshapiro vp = newstr(p); 3729132943Sgshapiro sm_rpool_free(rpool); 373090792Sgshapiro 3731132943Sgshapiro /* need to restart LDAP connection? */ 3732132943Sgshapiro if (*statp == EX_RESTART) 373364562Sgshapiro { 3734132943Sgshapiro *statp = EX_TEMPFAIL; 3735132943Sgshapiro ldapmap_close(map); 373638032Speter } 373738032Speter 3738132943Sgshapiro errno = save_errno; 3739132943Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 374038032Speter { 374164562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 374264562Sgshapiro { 374364562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 374464562Sgshapiro syserr("Error getting LDAP results in map %s", 374564562Sgshapiro map->map_mname); 374664562Sgshapiro else 374794334Sgshapiro syserr("451 4.3.5 Error getting LDAP results in map %s", 374864562Sgshapiro map->map_mname); 374964562Sgshapiro } 375077349Sgshapiro errno = save_errno; 375164562Sgshapiro return NULL; 375238032Speter } 375390792Sgshapiro 375464562Sgshapiro /* Did we match anything? */ 375571345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 375664562Sgshapiro return NULL; 375738032Speter 375864562Sgshapiro if (*statp == EX_OK) 375964562Sgshapiro { 376064562Sgshapiro if (LogLevel > 9) 376164562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 376271345Sgshapiro "ldap %.100s => %s", name, 376371345Sgshapiro vp == NULL ? "<NULL>" : vp); 376464562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 376564562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 376664562Sgshapiro else 376771345Sgshapiro { 376871345Sgshapiro /* vp != NULL according to test above */ 376964562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 377071345Sgshapiro } 377171345Sgshapiro if (vp != NULL) 377290792Sgshapiro sm_free(vp); /* XXX */ 377364562Sgshapiro } 377464562Sgshapiro return result; 377538032Speter} 377638032Speter 377738032Speter/* 377864562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 377964562Sgshapiro** 378064562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 378166494Sgshapiro** secret, and PID so we don't have multiple connections open to 378266494Sgshapiro** the same server for different maps. Need a separate connection 378366494Sgshapiro** per PID since a parent process may close the map before the 378466494Sgshapiro** child is done with it. 378564562Sgshapiro** 378664562Sgshapiro** Parameters: 378764562Sgshapiro** lmap -- LDAP map information 378864562Sgshapiro** 378964562Sgshapiro** Returns: 379064562Sgshapiro** Symbol table entry for the LDAP connection. 379138032Speter*/ 379238032Speter 379364562Sgshapirostatic STAB * 379464562Sgshapiroldapmap_findconn(lmap) 379590792Sgshapiro SM_LDAP_STRUCT *lmap; 379638032Speter{ 379794334Sgshapiro char *format; 379864562Sgshapiro char *nbuf; 3799132943Sgshapiro char *id; 380090792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 380138032Speter 3802132943Sgshapiro if (lmap->ldap_host != NULL) 3803132943Sgshapiro id = lmap->ldap_host; 3804132943Sgshapiro else if (lmap->ldap_uri != NULL) 3805132943Sgshapiro id = lmap->ldap_uri; 3806132943Sgshapiro else 3807132943Sgshapiro id = "localhost"; 3808132943Sgshapiro 380994334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 381094334Sgshapiro nbuf = sm_stringf_x(format, 3811132943Sgshapiro id, 381290792Sgshapiro CONDELSE, 381390792Sgshapiro lmap->ldap_port, 381490792Sgshapiro CONDELSE, 381594334Sgshapiro lmap->ldap_version, 381694334Sgshapiro CONDELSE, 381790792Sgshapiro (lmap->ldap_binddn == NULL ? "" 381890792Sgshapiro : lmap->ldap_binddn), 381990792Sgshapiro CONDELSE, 382090792Sgshapiro (lmap->ldap_secret == NULL ? "" 382190792Sgshapiro : lmap->ldap_secret), 382290792Sgshapiro (int) CurrentPid); 382390792Sgshapiro SM_TRY 382490792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 382590792Sgshapiro SM_FINALLY 382690792Sgshapiro sm_free(nbuf); 382790792Sgshapiro SM_END_TRY 382864562Sgshapiro return s; 382964562Sgshapiro} 383038032Speter/* 383164562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 383264562Sgshapiro*/ 383338032Speter 383490792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 383564562Sgshapiro{ 383664562Sgshapiro { "none", LDAP_AUTH_NONE }, 383764562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 383864562Sgshapiro# ifdef LDAP_AUTH_KRBV4 383964562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 384064562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 384164562Sgshapiro { NULL, 0 } 384264562Sgshapiro}; 384338032Speter 384490792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 384564562Sgshapiro{ 384664562Sgshapiro { "never", LDAP_DEREF_NEVER }, 384764562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 384864562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 384964562Sgshapiro { "find", LDAP_DEREF_FINDING }, 385064562Sgshapiro { NULL, 0 } 385164562Sgshapiro}; 385238032Speter 385390792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 385464562Sgshapiro{ 385564562Sgshapiro { "base", LDAP_SCOPE_BASE }, 385664562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 385764562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 385864562Sgshapiro { NULL, 0 } 385964562Sgshapiro}; 386038032Speter 386164562Sgshapirobool 386264562Sgshapiroldapmap_parseargs(map, args) 386364562Sgshapiro MAP *map; 386464562Sgshapiro char *args; 386564562Sgshapiro{ 386690792Sgshapiro bool secretread = true; 3867132943Sgshapiro bool attrssetup = false; 386864562Sgshapiro int i; 386964562Sgshapiro register char *p = args; 387090792Sgshapiro SM_LDAP_STRUCT *lmap; 387164562Sgshapiro struct lamvalues *lam; 387264562Sgshapiro struct ladvalues *lad; 387364562Sgshapiro struct lssvalues *lss; 387490792Sgshapiro char ldapfilt[MAXLINE]; 387564562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 387664562Sgshapiro 387764562Sgshapiro /* Get ldap struct pointer from map */ 387890792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 387964562Sgshapiro 388064562Sgshapiro /* Check if setting the initial LDAP defaults */ 388164562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 388264562Sgshapiro { 388390792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 3884168515Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof(*lmap)); 388564562Sgshapiro if (LDAPDefaults == NULL) 388690792Sgshapiro sm_ldap_clear(lmap); 388764562Sgshapiro else 388864562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 388964562Sgshapiro } 389064562Sgshapiro 389164562Sgshapiro /* there is no check whether there is really an argument */ 389264562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 389364562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 389490792Sgshapiro 389590792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 389690792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 389790792Sgshapiro { 389890792Sgshapiro /* Comma separate if used as an alias file */ 389990792Sgshapiro map->map_coldelim = ','; 390090792Sgshapiro if (*args == '\0') 390190792Sgshapiro { 390290792Sgshapiro int n; 390390792Sgshapiro char *lc; 390490792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 390590792Sgshapiro char lcbuf[MAXLINE]; 390690792Sgshapiro 390790792Sgshapiro /* Get $j */ 3908168515Sgshapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope); 390990792Sgshapiro if (jbuf[0] == '\0') 391090792Sgshapiro { 391190792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 3912168515Sgshapiro sizeof(jbuf)); 391390792Sgshapiro } 391490792Sgshapiro 391590792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 391690792Sgshapiro if (lc == NULL) 391790792Sgshapiro lc = ""; 391890792Sgshapiro else 391990792Sgshapiro { 3920168515Sgshapiro expand(lc, lcbuf, sizeof(lcbuf), CurEnv); 392190792Sgshapiro lc = lcbuf; 392290792Sgshapiro } 392390792Sgshapiro 3924168515Sgshapiro n = sm_snprintf(ldapfilt, sizeof(ldapfilt), 392590792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 392690792Sgshapiro lc, jbuf); 3927168515Sgshapiro if (n >= sizeof(ldapfilt)) 392890792Sgshapiro { 392990792Sgshapiro syserr("%s: Default LDAP string too long", 393090792Sgshapiro map->map_mname); 393190792Sgshapiro return false; 393290792Sgshapiro } 393390792Sgshapiro 393490792Sgshapiro /* default args for an alias LDAP entry */ 393590792Sgshapiro lmap->ldap_filter = ldapfilt; 3936132943Sgshapiro lmap->ldap_attr[0] = "objectClass"; 3937132943Sgshapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 3938132943Sgshapiro lmap->ldap_attr_needobjclass[0] = NULL; 3939132943Sgshapiro lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 3940132943Sgshapiro lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 3941132943Sgshapiro lmap->ldap_attr_needobjclass[1] = NULL; 3942132943Sgshapiro lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 3943132943Sgshapiro lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 3944132943Sgshapiro lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 3945132943Sgshapiro lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 3946132943Sgshapiro lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 3947132943Sgshapiro lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 3948132943Sgshapiro lmap->ldap_attr[4] = NULL; 3949132943Sgshapiro lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 3950132943Sgshapiro lmap->ldap_attr_needobjclass[4] = NULL; 3951132943Sgshapiro attrssetup = true; 395290792Sgshapiro } 395390792Sgshapiro } 395490792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 395590792Sgshapiro { 395690792Sgshapiro /* Space separate if used as a file class file */ 395790792Sgshapiro map->map_coldelim = ' '; 395890792Sgshapiro } 395990792Sgshapiro 396038032Speter for (;;) 396138032Speter { 396238032Speter while (isascii(*p) && isspace(*p)) 396338032Speter p++; 396438032Speter if (*p != '-') 396538032Speter break; 396638032Speter switch (*++p) 396738032Speter { 396838032Speter case 'N': 396938032Speter map->map_mflags |= MF_INCLNULL; 397038032Speter map->map_mflags &= ~MF_TRY0NULL; 397138032Speter break; 397238032Speter 397338032Speter case 'O': 397438032Speter map->map_mflags &= ~MF_TRY1NULL; 397538032Speter break; 397638032Speter 397738032Speter case 'o': 397838032Speter map->map_mflags |= MF_OPTIONAL; 397938032Speter break; 398038032Speter 398138032Speter case 'f': 398238032Speter map->map_mflags |= MF_NOFOLDCASE; 398338032Speter break; 398438032Speter 398538032Speter case 'm': 398638032Speter map->map_mflags |= MF_MATCHONLY; 398738032Speter break; 398838032Speter 398938032Speter case 'A': 399038032Speter map->map_mflags |= MF_APPEND; 399138032Speter break; 399238032Speter 399338032Speter case 'q': 399438032Speter map->map_mflags |= MF_KEEPQUOTES; 399538032Speter break; 399638032Speter 399738032Speter case 'a': 399838032Speter map->map_app = ++p; 399938032Speter break; 400038032Speter 400138032Speter case 'T': 400238032Speter map->map_tapp = ++p; 400338032Speter break; 400438032Speter 400564562Sgshapiro case 't': 400664562Sgshapiro map->map_mflags |= MF_NODEFER; 400764562Sgshapiro break; 400864562Sgshapiro 400964562Sgshapiro case 'S': 401064562Sgshapiro map->map_spacesub = *++p; 401164562Sgshapiro break; 401264562Sgshapiro 401364562Sgshapiro case 'D': 401464562Sgshapiro map->map_mflags |= MF_DEFER; 401564562Sgshapiro break; 401664562Sgshapiro 401764562Sgshapiro case 'z': 401864562Sgshapiro if (*++p != '\\') 401964562Sgshapiro map->map_coldelim = *p; 402064562Sgshapiro else 402164562Sgshapiro { 402264562Sgshapiro switch (*++p) 402364562Sgshapiro { 402464562Sgshapiro case 'n': 402564562Sgshapiro map->map_coldelim = '\n'; 402664562Sgshapiro break; 402764562Sgshapiro 402864562Sgshapiro case 't': 402964562Sgshapiro map->map_coldelim = '\t'; 403064562Sgshapiro break; 403164562Sgshapiro 403264562Sgshapiro default: 403364562Sgshapiro map->map_coldelim = '\\'; 403464562Sgshapiro } 403564562Sgshapiro } 403664562Sgshapiro break; 403764562Sgshapiro 403864562Sgshapiro /* Start of ldapmap specific args */ 403990792Sgshapiro case 'V': 404090792Sgshapiro if (*++p != '\\') 404190792Sgshapiro lmap->ldap_attrsep = *p; 404290792Sgshapiro else 404390792Sgshapiro { 404490792Sgshapiro switch (*++p) 404590792Sgshapiro { 404690792Sgshapiro case 'n': 404790792Sgshapiro lmap->ldap_attrsep = '\n'; 404890792Sgshapiro break; 404990792Sgshapiro 405090792Sgshapiro case 't': 405190792Sgshapiro lmap->ldap_attrsep = '\t'; 405290792Sgshapiro break; 405390792Sgshapiro 405490792Sgshapiro default: 405590792Sgshapiro lmap->ldap_attrsep = '\\'; 405690792Sgshapiro } 405790792Sgshapiro } 405890792Sgshapiro break; 405990792Sgshapiro 406038032Speter case 'k': /* search field */ 406138032Speter while (isascii(*++p) && isspace(*p)) 406238032Speter continue; 406364562Sgshapiro lmap->ldap_filter = p; 406438032Speter break; 406538032Speter 406638032Speter case 'v': /* attr to return */ 406738032Speter while (isascii(*++p) && isspace(*p)) 406838032Speter continue; 406964562Sgshapiro lmap->ldap_attr[0] = p; 407064562Sgshapiro lmap->ldap_attr[1] = NULL; 407138032Speter break; 407238032Speter 407364562Sgshapiro case '1': 407464562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 407564562Sgshapiro break; 407664562Sgshapiro 4077157001Sgshapiro# if _FFR_LDAP_SINGLEDN 4078157001Sgshapiro case '2': 4079157001Sgshapiro map->map_mflags |= MF_SINGLEDN; 4080157001Sgshapiro break; 4081157001Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 4082157001Sgshapiro 408338032Speter /* args stolen from ldapsearch.c */ 408438032Speter case 'R': /* don't auto chase referrals */ 408564562Sgshapiro# ifdef LDAP_REFERRALS 408638032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 408764562Sgshapiro# else /* LDAP_REFERRALS */ 408890792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 408964562Sgshapiro# endif /* LDAP_REFERRALS */ 409038032Speter break; 409138032Speter 409264562Sgshapiro case 'n': /* retrieve attribute names only */ 409364562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 409438032Speter break; 409538032Speter 409664562Sgshapiro case 'r': /* alias dereferencing */ 409764562Sgshapiro while (isascii(*++p) && isspace(*p)) 409864562Sgshapiro continue; 409964562Sgshapiro 410090792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 410164562Sgshapiro p += 11; 410264562Sgshapiro 410364562Sgshapiro for (lad = LDAPAliasDereference; 410464562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 410538032Speter { 410690792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 410790792Sgshapiro strlen(lad->lad_name)) == 0) 410864562Sgshapiro break; 410938032Speter } 411064562Sgshapiro if (lad->lad_name != NULL) 411164562Sgshapiro lmap->ldap_deref = lad->lad_code; 411264562Sgshapiro else 411338032Speter { 411464562Sgshapiro /* bad config line */ 411564562Sgshapiro if (!bitset(MCF_OPTFILE, 411664562Sgshapiro map->map_class->map_cflags)) 411764562Sgshapiro { 411864562Sgshapiro char *ptr; 411964562Sgshapiro 412064562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 412164562Sgshapiro *ptr = '\0'; 412273188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 412364562Sgshapiro p, map->map_mname); 412464562Sgshapiro if (ptr != NULL) 412564562Sgshapiro *ptr = ' '; 412690792Sgshapiro return false; 412764562Sgshapiro } 412838032Speter } 412964562Sgshapiro break; 413064562Sgshapiro 413164562Sgshapiro case 's': /* search scope */ 413264562Sgshapiro while (isascii(*++p) && isspace(*p)) 413364562Sgshapiro continue; 413464562Sgshapiro 413590792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 413664562Sgshapiro p += 11; 413764562Sgshapiro 413864562Sgshapiro for (lss = LDAPSearchScope; 413964562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 414038032Speter { 414190792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 414290792Sgshapiro strlen(lss->lss_name)) == 0) 414364562Sgshapiro break; 414438032Speter } 414564562Sgshapiro if (lss->lss_name != NULL) 414664562Sgshapiro lmap->ldap_scope = lss->lss_code; 414738032Speter else 414864562Sgshapiro { 414964562Sgshapiro /* bad config line */ 415064562Sgshapiro if (!bitset(MCF_OPTFILE, 415164562Sgshapiro map->map_class->map_cflags)) 415238032Speter { 415338032Speter char *ptr; 415438032Speter 415538032Speter if ((ptr = strchr(p, ' ')) != NULL) 415638032Speter *ptr = '\0'; 415773188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 415838032Speter p, map->map_mname); 415938032Speter if (ptr != NULL) 416038032Speter *ptr = ' '; 416190792Sgshapiro return false; 416238032Speter } 416338032Speter } 416438032Speter break; 416538032Speter 416638032Speter case 'h': /* ldap host */ 416738032Speter while (isascii(*++p) && isspace(*p)) 416838032Speter continue; 4169132943Sgshapiro if (lmap->ldap_uri != NULL) 417094334Sgshapiro { 417194334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 417294334Sgshapiro map->map_mname); 417394334Sgshapiro return false; 417494334Sgshapiro } 4175132943Sgshapiro lmap->ldap_host = p; 417638032Speter break; 417738032Speter 417838032Speter case 'b': /* search base */ 417938032Speter while (isascii(*++p) && isspace(*p)) 418038032Speter continue; 418164562Sgshapiro lmap->ldap_base = p; 418238032Speter break; 418338032Speter 418438032Speter case 'p': /* ldap port */ 418538032Speter while (isascii(*++p) && isspace(*p)) 418638032Speter continue; 418764562Sgshapiro lmap->ldap_port = atoi(p); 418838032Speter break; 418938032Speter 419038032Speter case 'l': /* time limit */ 419138032Speter while (isascii(*++p) && isspace(*p)) 419238032Speter continue; 419364562Sgshapiro lmap->ldap_timelimit = atoi(p); 419464562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 419538032Speter break; 419638032Speter 419764562Sgshapiro case 'Z': 419864562Sgshapiro while (isascii(*++p) && isspace(*p)) 419964562Sgshapiro continue; 420064562Sgshapiro lmap->ldap_sizelimit = atoi(p); 420164562Sgshapiro break; 420264562Sgshapiro 420364562Sgshapiro case 'd': /* Dn to bind to server as */ 420464562Sgshapiro while (isascii(*++p) && isspace(*p)) 420564562Sgshapiro continue; 420664562Sgshapiro lmap->ldap_binddn = p; 420764562Sgshapiro break; 420864562Sgshapiro 420964562Sgshapiro case 'M': /* Method for binding */ 421064562Sgshapiro while (isascii(*++p) && isspace(*p)) 421164562Sgshapiro continue; 421264562Sgshapiro 421390792Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 421464562Sgshapiro p += 10; 421564562Sgshapiro 421664562Sgshapiro for (lam = LDAPAuthMethods; 421764562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 421864562Sgshapiro { 421990792Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 422090792Sgshapiro strlen(lam->lam_name)) == 0) 422164562Sgshapiro break; 422264562Sgshapiro } 422364562Sgshapiro if (lam->lam_name != NULL) 422464562Sgshapiro lmap->ldap_method = lam->lam_code; 422564562Sgshapiro else 422664562Sgshapiro { 422764562Sgshapiro /* bad config line */ 422864562Sgshapiro if (!bitset(MCF_OPTFILE, 422964562Sgshapiro map->map_class->map_cflags)) 423064562Sgshapiro { 423164562Sgshapiro char *ptr; 423264562Sgshapiro 423364562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 423464562Sgshapiro *ptr = '\0'; 423573188Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 423664562Sgshapiro p, map->map_mname); 423764562Sgshapiro if (ptr != NULL) 423864562Sgshapiro *ptr = ' '; 423990792Sgshapiro return false; 424064562Sgshapiro } 424164562Sgshapiro } 424264562Sgshapiro 424364562Sgshapiro break; 424464562Sgshapiro 424564562Sgshapiro /* 424664562Sgshapiro ** This is a string that is dependent on the 424764562Sgshapiro ** method used defined above. 424864562Sgshapiro */ 424964562Sgshapiro 425064562Sgshapiro case 'P': /* Secret password for binding */ 425164562Sgshapiro while (isascii(*++p) && isspace(*p)) 425264562Sgshapiro continue; 425364562Sgshapiro lmap->ldap_secret = p; 425490792Sgshapiro secretread = false; 425564562Sgshapiro break; 425664562Sgshapiro 425794334Sgshapiro case 'H': /* Use LDAP URI */ 425894334Sgshapiro# if !USE_LDAP_INIT 425994334Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 426094334Sgshapiro map->map_mname); 426194334Sgshapiro return false; 4262132943Sgshapiro# else /* !USE_LDAP_INIT */ 4263132943Sgshapiro if (lmap->ldap_host != NULL) 426494334Sgshapiro { 426594334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 426694334Sgshapiro map->map_mname); 426794334Sgshapiro return false; 426894334Sgshapiro } 426994334Sgshapiro while (isascii(*++p) && isspace(*p)) 427094334Sgshapiro continue; 4271132943Sgshapiro lmap->ldap_uri = p; 427294334Sgshapiro break; 427394334Sgshapiro# endif /* !USE_LDAP_INIT */ 427494334Sgshapiro 427594334Sgshapiro case 'w': 427694334Sgshapiro /* -w should be for passwd, -P should be for version */ 427794334Sgshapiro while (isascii(*++p) && isspace(*p)) 427894334Sgshapiro continue; 427994334Sgshapiro lmap->ldap_version = atoi(p); 4280132943Sgshapiro# ifdef LDAP_VERSION_MAX 428194334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 428294334Sgshapiro { 428394334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 428494334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 428594334Sgshapiro map->map_mname); 428694334Sgshapiro return false; 428794334Sgshapiro } 4288132943Sgshapiro# endif /* LDAP_VERSION_MAX */ 4289132943Sgshapiro# ifdef LDAP_VERSION_MIN 429094334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 429194334Sgshapiro { 429294334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 429394334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 429494334Sgshapiro map->map_mname); 429594334Sgshapiro return false; 429694334Sgshapiro } 4297132943Sgshapiro# endif /* LDAP_VERSION_MIN */ 429894334Sgshapiro break; 429994334Sgshapiro 4300168515Sgshapiro case 'K': 4301168515Sgshapiro lmap->ldap_multi_args = true; 4302168515Sgshapiro break; 4303168515Sgshapiro 430464562Sgshapiro default: 430564562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 430664562Sgshapiro break; 430738032Speter } 430838032Speter 430964562Sgshapiro /* need to account for quoted strings here */ 431064562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 431138032Speter { 431238032Speter if (*p == '"') 431338032Speter { 431438032Speter while (*++p != '"' && *p != '\0') 431538032Speter continue; 431638032Speter if (*p != '\0') 431738032Speter p++; 431838032Speter } 431938032Speter else 432038032Speter p++; 432138032Speter } 432238032Speter 432338032Speter if (*p != '\0') 432438032Speter *p++ = '\0'; 432538032Speter } 432638032Speter 432738032Speter if (map->map_app != NULL) 432864562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 432938032Speter if (map->map_tapp != NULL) 433064562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 433138032Speter 433238032Speter /* 433342575Speter ** We need to swallow up all the stuff into a struct 433442575Speter ** and dump it into map->map_dbptr1 433538032Speter */ 433638032Speter 4337132943Sgshapiro if (lmap->ldap_host != NULL && 433864562Sgshapiro (LDAPDefaults == NULL || 433964562Sgshapiro LDAPDefaults == lmap || 4340132943Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 4341132943Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 4342132943Sgshapiro map->map_domain = lmap->ldap_host; 434364562Sgshapiro 4344132943Sgshapiro if (lmap->ldap_uri != NULL && 4345132943Sgshapiro (LDAPDefaults == NULL || 4346132943Sgshapiro LDAPDefaults == lmap || 4347132943Sgshapiro LDAPDefaults->ldap_uri != lmap->ldap_uri)) 4348132943Sgshapiro lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 4349132943Sgshapiro map->map_domain = lmap->ldap_uri; 4350132943Sgshapiro 435164562Sgshapiro if (lmap->ldap_binddn != NULL && 435264562Sgshapiro (LDAPDefaults == NULL || 435364562Sgshapiro LDAPDefaults == lmap || 435464562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 435564562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 435664562Sgshapiro 435764562Sgshapiro if (lmap->ldap_secret != NULL && 435864562Sgshapiro (LDAPDefaults == NULL || 435964562Sgshapiro LDAPDefaults == lmap || 436064562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 436138032Speter { 436290792Sgshapiro SM_FILE_T *sfd; 436364562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 436438032Speter 436564562Sgshapiro if (DontLockReadFiles) 436664562Sgshapiro sff |= SFF_NOLOCK; 436738032Speter 436864562Sgshapiro /* need to use method to map secret to passwd string */ 436964562Sgshapiro switch (lmap->ldap_method) 437064562Sgshapiro { 437164562Sgshapiro case LDAP_AUTH_NONE: 437264562Sgshapiro /* Do nothing */ 437364562Sgshapiro break; 437438032Speter 437564562Sgshapiro case LDAP_AUTH_SIMPLE: 437638032Speter 437764562Sgshapiro /* 437864562Sgshapiro ** Secret is the name of a file with 437964562Sgshapiro ** the first line as the password. 438064562Sgshapiro */ 438164562Sgshapiro 438264562Sgshapiro /* Already read in the secret? */ 438364562Sgshapiro if (secretread) 438464562Sgshapiro break; 438564562Sgshapiro 438664562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 438764562Sgshapiro O_RDONLY, 0, sff); 438864562Sgshapiro if (sfd == NULL) 438964562Sgshapiro { 439064562Sgshapiro syserr("LDAP map: cannot open secret %s", 439164562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 439290792Sgshapiro return false; 439364562Sgshapiro } 4394168515Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof(m_tmp), 439566494Sgshapiro sfd, TimeOuts.to_fileopen, 439666494Sgshapiro "ldapmap_parseargs"); 439790792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 439898121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 439998121Sgshapiro { 440098121Sgshapiro syserr("LDAP map: secret in %s too long", 440198121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 440298121Sgshapiro return false; 440398121Sgshapiro } 440464562Sgshapiro if (lmap->ldap_secret != NULL && 440564562Sgshapiro strlen(m_tmp) > 0) 440664562Sgshapiro { 440764562Sgshapiro /* chomp newline */ 440864562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 440964562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 441064562Sgshapiro 441164562Sgshapiro lmap->ldap_secret = m_tmp; 441264562Sgshapiro } 441364562Sgshapiro break; 441464562Sgshapiro 441564562Sgshapiro# ifdef LDAP_AUTH_KRBV4 441664562Sgshapiro case LDAP_AUTH_KRBV4: 441764562Sgshapiro 441864562Sgshapiro /* 441964562Sgshapiro ** Secret is where the ticket file is 442064562Sgshapiro ** stashed 442164562Sgshapiro */ 442264562Sgshapiro 4423168515Sgshapiro (void) sm_snprintf(m_tmp, sizeof(m_tmp), 442490792Sgshapiro "KRBTKFILE=%s", 442590792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 442664562Sgshapiro lmap->ldap_secret = m_tmp; 442764562Sgshapiro break; 442864562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 442964562Sgshapiro 443064562Sgshapiro default: /* Should NEVER get here */ 443164562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 443290792Sgshapiro return false; 443390792Sgshapiro /* NOTREACHED */ 443464562Sgshapiro break; 443564562Sgshapiro } 443638032Speter } 443738032Speter 443864562Sgshapiro if (lmap->ldap_secret != NULL && 443964562Sgshapiro (LDAPDefaults == NULL || 444064562Sgshapiro LDAPDefaults == lmap || 444164562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 444264562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 444338032Speter 444464562Sgshapiro if (lmap->ldap_base != NULL && 444564562Sgshapiro (LDAPDefaults == NULL || 444664562Sgshapiro LDAPDefaults == lmap || 444764562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 444864562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 444964562Sgshapiro 445064562Sgshapiro /* 445164562Sgshapiro ** Save the server from extra work. If request is for a single 445264562Sgshapiro ** match, tell the server to only return enough records to 445364562Sgshapiro ** determine if there is a single match or not. This can not 445464562Sgshapiro ** be one since the server would only return one and we wouldn't 445564562Sgshapiro ** know if there were others available. 445664562Sgshapiro */ 445764562Sgshapiro 445864562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 445964562Sgshapiro lmap->ldap_sizelimit = 2; 446064562Sgshapiro 446164562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 446264562Sgshapiro if (lmap == LDAPDefaults) 446390792Sgshapiro return true; 446464562Sgshapiro 446564562Sgshapiro if (lmap->ldap_filter != NULL) 446664562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 446738032Speter else 446838032Speter { 446938032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 447038032Speter { 447138032Speter syserr("No filter given in map %s", map->map_mname); 447290792Sgshapiro return false; 447338032Speter } 447438032Speter } 447564562Sgshapiro 4476132943Sgshapiro if (!attrssetup && lmap->ldap_attr[0] != NULL) 447738032Speter { 447890792Sgshapiro bool recurse = false; 447994334Sgshapiro bool normalseen = false; 448090792Sgshapiro 448164562Sgshapiro i = 0; 448264562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 448364562Sgshapiro lmap->ldap_attr[0] = NULL; 448464562Sgshapiro 448594334Sgshapiro /* Prime the attr list with the objectClass attribute */ 448694334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 448794334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 448894334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 448994334Sgshapiro i++; 449094334Sgshapiro 449164562Sgshapiro while (p != NULL) 449238032Speter { 449364562Sgshapiro char *v; 449464562Sgshapiro 449564562Sgshapiro while (isascii(*p) && isspace(*p)) 449664562Sgshapiro p++; 449764562Sgshapiro if (*p == '\0') 449864562Sgshapiro break; 449964562Sgshapiro v = p; 450064562Sgshapiro p = strchr(v, ','); 450164562Sgshapiro if (p != NULL) 450264562Sgshapiro *p++ = '\0'; 450364562Sgshapiro 450471345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 450564562Sgshapiro { 450664562Sgshapiro syserr("Too many return attributes in %s (max %d)", 450764562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 450890792Sgshapiro return false; 450964562Sgshapiro } 451064562Sgshapiro if (*v != '\0') 451190792Sgshapiro { 451294334Sgshapiro int j; 451394334Sgshapiro int use; 451490792Sgshapiro char *type; 451594334Sgshapiro char *needobjclass; 451690792Sgshapiro 451790792Sgshapiro type = strchr(v, ':'); 451890792Sgshapiro if (type != NULL) 451994334Sgshapiro { 452090792Sgshapiro *type++ = '\0'; 452194334Sgshapiro needobjclass = strchr(type, ':'); 452294334Sgshapiro if (needobjclass != NULL) 452394334Sgshapiro *needobjclass++ = '\0'; 452494334Sgshapiro } 452594334Sgshapiro else 452694334Sgshapiro { 452794334Sgshapiro needobjclass = NULL; 452894334Sgshapiro } 452990792Sgshapiro 453094334Sgshapiro use = i; 453190792Sgshapiro 453294334Sgshapiro /* allow override on "objectClass" type */ 453394334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 453494334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 453590792Sgshapiro { 453694334Sgshapiro use = 0; 453794334Sgshapiro } 453894334Sgshapiro else 453994334Sgshapiro { 454094334Sgshapiro /* 454194334Sgshapiro ** Don't add something to attribute 454294334Sgshapiro ** list twice. 454394334Sgshapiro */ 454494334Sgshapiro 454594334Sgshapiro for (j = 1; j < i; j++) 454690792Sgshapiro { 454794334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 454894334Sgshapiro { 454994334Sgshapiro syserr("Duplicate attribute (%s) in %s", 455094334Sgshapiro v, map->map_mname); 455194334Sgshapiro return false; 455294334Sgshapiro } 455390792Sgshapiro } 455494334Sgshapiro 455594334Sgshapiro lmap->ldap_attr[use] = newstr(v); 455694334Sgshapiro if (needobjclass != NULL && 455794334Sgshapiro *needobjclass != '\0' && 455894334Sgshapiro *needobjclass != '*') 455990792Sgshapiro { 456094334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 456194334Sgshapiro } 456294334Sgshapiro else 456394334Sgshapiro { 456494334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 456594334Sgshapiro } 456694334Sgshapiro 456794334Sgshapiro } 456894334Sgshapiro 456994334Sgshapiro if (type != NULL && *type != '\0') 457094334Sgshapiro { 457194334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 457294334Sgshapiro { 457390792Sgshapiro recurse = true; 457494334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 457590792Sgshapiro } 457690792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 457790792Sgshapiro { 457890792Sgshapiro recurse = true; 457994334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 458090792Sgshapiro } 458190792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 458290792Sgshapiro { 458390792Sgshapiro recurse = true; 458494334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 458590792Sgshapiro } 458694334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 458790792Sgshapiro { 458894334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 458994334Sgshapiro normalseen = true; 459090792Sgshapiro } 459190792Sgshapiro else 459290792Sgshapiro { 459390792Sgshapiro syserr("Unknown attribute type (%s) in %s", 459490792Sgshapiro type, map->map_mname); 459590792Sgshapiro return false; 459690792Sgshapiro } 459790792Sgshapiro } 459890792Sgshapiro else 459994334Sgshapiro { 460094334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 460194334Sgshapiro normalseen = true; 460294334Sgshapiro } 460390792Sgshapiro i++; 460490792Sgshapiro } 460538032Speter } 460664562Sgshapiro lmap->ldap_attr[i] = NULL; 4607141858Sgshapiro 4608141858Sgshapiro /* Set in case needed in future code */ 4609132943Sgshapiro attrssetup = true; 4610141858Sgshapiro 461194334Sgshapiro if (recurse && !normalseen) 461290792Sgshapiro { 461394334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 461490792Sgshapiro map->map_mname); 461590792Sgshapiro return false; 461690792Sgshapiro } 461790792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 461890792Sgshapiro { 461990792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 462090792Sgshapiro map->map_mname); 462190792Sgshapiro return false; 462290792Sgshapiro } 462338032Speter } 462438032Speter map->map_db1 = (ARBPTR_T) lmap; 462590792Sgshapiro return true; 462638032Speter} 462738032Speter 462864562Sgshapiro/* 462964562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 463064562Sgshapiro** 463164562Sgshapiro** Parameters: 463264562Sgshapiro** spec -- map argument string from LDAPDefaults option 463364562Sgshapiro** 463464562Sgshapiro** Returns: 463564562Sgshapiro** None. 463664562Sgshapiro*/ 463764562Sgshapiro 463864562Sgshapirovoid 463964562Sgshapiroldapmap_set_defaults(spec) 464064562Sgshapiro char *spec; 464164562Sgshapiro{ 464273188Sgshapiro STAB *class; 464364562Sgshapiro MAP map; 464464562Sgshapiro 464564562Sgshapiro /* Allocate and set the default values */ 464664562Sgshapiro if (LDAPDefaults == NULL) 4647168515Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof(*LDAPDefaults)); 464890792Sgshapiro sm_ldap_clear(LDAPDefaults); 464964562Sgshapiro 4650168515Sgshapiro memset(&map, '\0', sizeof(map)); 465173188Sgshapiro 465273188Sgshapiro /* look up the class */ 465373188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 465473188Sgshapiro if (class == NULL) 465573188Sgshapiro { 465673188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 465773188Sgshapiro return; 465873188Sgshapiro } 465973188Sgshapiro map.map_class = &class->s_mapclass; 466064562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 466173188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 466264562Sgshapiro 466364562Sgshapiro (void) ldapmap_parseargs(&map, spec); 466464562Sgshapiro 466564562Sgshapiro /* These should never be set in LDAPDefaults */ 466664562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 466764562Sgshapiro map.map_spacesub != SpaceSub || 466864562Sgshapiro map.map_app != NULL || 466964562Sgshapiro map.map_tapp != NULL) 467064562Sgshapiro { 467164562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 467290792Sgshapiro SM_FREE_CLR(map.map_app); 467390792Sgshapiro SM_FREE_CLR(map.map_tapp); 467464562Sgshapiro } 467564562Sgshapiro 467664562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 467764562Sgshapiro { 467864562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 467994334Sgshapiro 468064562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 468164562Sgshapiro LDAPDefaults->ldap_filter = NULL; 468264562Sgshapiro } 468364562Sgshapiro 468464562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 468564562Sgshapiro { 468664562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 468764562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 468864562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 468964562Sgshapiro } 469064562Sgshapiro} 469164562Sgshapiro#endif /* LDAPMAP */ 469290792Sgshapiro/* 469364562Sgshapiro** PH map 469464562Sgshapiro*/ 469564562Sgshapiro 469690792Sgshapiro#if PH_MAP 469764562Sgshapiro 469864562Sgshapiro/* 469964562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 470064562Sgshapiro** This code is intended to replace the so-called "ph mailer". 4701168515Sgshapiro** Contributed by Mark D. Roth. Contact him for support. 470264562Sgshapiro*/ 470364562Sgshapiro 470490792Sgshapiro/* what version of the ph map code we're running */ 4705110560Sgshapirostatic char phmap_id[128]; 470664562Sgshapiro 470790792Sgshapiro/* sendmail version for phmap id string */ 470890792Sgshapiroextern const char Version[]; 470990792Sgshapiro 4710132943Sgshapiro/* assume we're using nph-1.2.x if not specified */ 4711110560Sgshapiro# ifndef NPH_VERSION 4712132943Sgshapiro# define NPH_VERSION 10200 4713110560Sgshapiro# endif 4714110560Sgshapiro 4715110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 4716110560Sgshapiro# if NPH_VERSION < 10200 4717110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 4718110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 4719110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 4720110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 4721110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 4722110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 4723110560Sgshapiro 472464562Sgshapiro/* 472564562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 472664562Sgshapiro*/ 472764562Sgshapiro 472864562Sgshapirobool 472964562Sgshapiroph_map_parseargs(map, args) 473064562Sgshapiro MAP *map; 473164562Sgshapiro char *args; 473264562Sgshapiro{ 473390792Sgshapiro register bool done; 473490792Sgshapiro register char *p = args; 473564562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 473664562Sgshapiro 473790792Sgshapiro /* initialize version string */ 4738168515Sgshapiro (void) sm_snprintf(phmap_id, sizeof(phmap_id), 473990792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 474090792Sgshapiro Version, libphclient_version); 474190792Sgshapiro 4742168515Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof(*pmap)); 474364562Sgshapiro 474464562Sgshapiro /* defaults */ 474564562Sgshapiro pmap->ph_servers = NULL; 474664562Sgshapiro pmap->ph_field_list = NULL; 474790792Sgshapiro pmap->ph = NULL; 474864562Sgshapiro pmap->ph_timeout = 0; 474990792Sgshapiro pmap->ph_fastclose = 0; 475064562Sgshapiro 475164562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 475264562Sgshapiro for (;;) 475364562Sgshapiro { 475464562Sgshapiro while (isascii(*p) && isspace(*p)) 475564562Sgshapiro p++; 475664562Sgshapiro if (*p != '-') 475764562Sgshapiro break; 475864562Sgshapiro switch (*++p) 475964562Sgshapiro { 476064562Sgshapiro case 'N': 476164562Sgshapiro map->map_mflags |= MF_INCLNULL; 476264562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 476364562Sgshapiro break; 476464562Sgshapiro 476564562Sgshapiro case 'O': 476664562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 476764562Sgshapiro break; 476864562Sgshapiro 476964562Sgshapiro case 'o': 477064562Sgshapiro map->map_mflags |= MF_OPTIONAL; 477164562Sgshapiro break; 477264562Sgshapiro 477364562Sgshapiro case 'f': 477464562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 477564562Sgshapiro break; 477664562Sgshapiro 477764562Sgshapiro case 'm': 477864562Sgshapiro map->map_mflags |= MF_MATCHONLY; 477964562Sgshapiro break; 478064562Sgshapiro 478164562Sgshapiro case 'A': 478264562Sgshapiro map->map_mflags |= MF_APPEND; 478364562Sgshapiro break; 478464562Sgshapiro 478564562Sgshapiro case 'q': 478664562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 478764562Sgshapiro break; 478864562Sgshapiro 478964562Sgshapiro case 't': 479064562Sgshapiro map->map_mflags |= MF_NODEFER; 479164562Sgshapiro break; 479264562Sgshapiro 479364562Sgshapiro case 'a': 479464562Sgshapiro map->map_app = ++p; 479564562Sgshapiro break; 479664562Sgshapiro 479764562Sgshapiro case 'T': 479864562Sgshapiro map->map_tapp = ++p; 479964562Sgshapiro break; 480064562Sgshapiro 480164562Sgshapiro case 'l': 480264562Sgshapiro while (isascii(*++p) && isspace(*p)) 480364562Sgshapiro continue; 480464562Sgshapiro pmap->ph_timeout = atoi(p); 480564562Sgshapiro break; 480664562Sgshapiro 480764562Sgshapiro case 'S': 480864562Sgshapiro map->map_spacesub = *++p; 480964562Sgshapiro break; 481064562Sgshapiro 481164562Sgshapiro case 'D': 481264562Sgshapiro map->map_mflags |= MF_DEFER; 481364562Sgshapiro break; 481464562Sgshapiro 481564562Sgshapiro case 'h': /* PH server list */ 481664562Sgshapiro while (isascii(*++p) && isspace(*p)) 481764562Sgshapiro continue; 481864562Sgshapiro pmap->ph_servers = p; 481964562Sgshapiro break; 482064562Sgshapiro 482190792Sgshapiro case 'k': /* fields to search for */ 482264562Sgshapiro while (isascii(*++p) && isspace(*p)) 482364562Sgshapiro continue; 482464562Sgshapiro pmap->ph_field_list = p; 482564562Sgshapiro break; 482664562Sgshapiro 482764562Sgshapiro default: 482890792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 482964562Sgshapiro } 483064562Sgshapiro 483164562Sgshapiro /* try to account for quoted strings */ 483264562Sgshapiro done = isascii(*p) && isspace(*p); 483364562Sgshapiro while (*p != '\0' && !done) 483464562Sgshapiro { 483564562Sgshapiro if (*p == '"') 483664562Sgshapiro { 483764562Sgshapiro while (*++p != '"' && *p != '\0') 483864562Sgshapiro continue; 483964562Sgshapiro if (*p != '\0') 484064562Sgshapiro p++; 484164562Sgshapiro } 484264562Sgshapiro else 484364562Sgshapiro p++; 484464562Sgshapiro done = isascii(*p) && isspace(*p); 484564562Sgshapiro } 484664562Sgshapiro 484764562Sgshapiro if (*p != '\0') 484864562Sgshapiro *p++ = '\0'; 484964562Sgshapiro } 485064562Sgshapiro 485164562Sgshapiro if (map->map_app != NULL) 485264562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 485364562Sgshapiro if (map->map_tapp != NULL) 485464562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 485564562Sgshapiro 485664562Sgshapiro if (pmap->ph_field_list != NULL) 485764562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 485864562Sgshapiro 485964562Sgshapiro if (pmap->ph_servers != NULL) 486064562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 486164562Sgshapiro else 486264562Sgshapiro { 486364562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 486490792Sgshapiro return false; 486564562Sgshapiro } 486664562Sgshapiro 486764562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 486890792Sgshapiro return true; 486964562Sgshapiro} 487064562Sgshapiro 487164562Sgshapiro/* 487264562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 487364562Sgshapiro*/ 487464562Sgshapiro 487590792Sgshapirovoid 487690792Sgshapiroph_map_close(map) 487764562Sgshapiro MAP *map; 487864562Sgshapiro{ 487964562Sgshapiro PH_MAP_STRUCT *pmap; 488064562Sgshapiro 488164562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 488290792Sgshapiro if (tTd(38, 9)) 488394334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 488490792Sgshapiro map->map_mname, pmap->ph_fastclose); 488564562Sgshapiro 488690792Sgshapiro 488790792Sgshapiro if (pmap->ph != NULL) 488864562Sgshapiro { 488990792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 489090792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 489190792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 489264562Sgshapiro } 489390792Sgshapiro 489464562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 489564562Sgshapiro} 489664562Sgshapiro 489764562Sgshapirostatic jmp_buf PHTimeout; 489864562Sgshapiro 489964562Sgshapiro/* ARGSUSED */ 490064562Sgshapirostatic void 490190792Sgshapiroph_timeout(unused) 490290792Sgshapiro int unused; 490364562Sgshapiro{ 490477349Sgshapiro /* 490577349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 490677349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 490777349Sgshapiro ** DOING. 490877349Sgshapiro */ 490977349Sgshapiro 491077349Sgshapiro errno = ETIMEDOUT; 491164562Sgshapiro longjmp(PHTimeout, 1); 491264562Sgshapiro} 491364562Sgshapiro 491490792Sgshapirostatic void 4915110560Sgshapiro#if NPH_VERSION >= 10200 4916110560Sgshapiroph_map_send_debug(appdata, text) 4917110560Sgshapiro void *appdata; 4918110560Sgshapiro#else 491990792Sgshapiroph_map_send_debug(text) 4920110560Sgshapiro#endif 492190792Sgshapiro char *text; 492264562Sgshapiro{ 492390792Sgshapiro if (LogLevel > 9) 492490792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 492590792Sgshapiro "ph_map_send_debug: ==> %s", text); 492690792Sgshapiro if (tTd(38, 20)) 492790792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 492890792Sgshapiro} 492964562Sgshapiro 493090792Sgshapirostatic void 4931110560Sgshapiro#if NPH_VERSION >= 10200 4932110560Sgshapiroph_map_recv_debug(appdata, text) 4933110560Sgshapiro void *appdata; 4934110560Sgshapiro#else 493590792Sgshapiroph_map_recv_debug(text) 4936110560Sgshapiro#endif 493790792Sgshapiro char *text; 493890792Sgshapiro{ 493990792Sgshapiro if (LogLevel > 10) 494090792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 494190792Sgshapiro "ph_map_recv_debug: <== %s", text); 494290792Sgshapiro if (tTd(38, 21)) 494390792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 494464562Sgshapiro} 494564562Sgshapiro 494690792Sgshapiro/* 494764562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 494864562Sgshapiro*/ 494964562Sgshapirobool 495064562Sgshapiroph_map_open(map, mode) 495164562Sgshapiro MAP *map; 495264562Sgshapiro int mode; 495364562Sgshapiro{ 495490792Sgshapiro PH_MAP_STRUCT *pmap; 495590792Sgshapiro register SM_EVENT *ev = NULL; 495664562Sgshapiro int save_errno = 0; 495790792Sgshapiro char *hostlist, *host; 495864562Sgshapiro 495964562Sgshapiro if (tTd(38, 2)) 496090792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 496164562Sgshapiro 496264562Sgshapiro mode &= O_ACCMODE; 496364562Sgshapiro if (mode != O_RDONLY) 496464562Sgshapiro { 496564562Sgshapiro /* issue a pseudo-error message */ 496690792Sgshapiro errno = SM_EMAPCANTWRITE; 496790792Sgshapiro return false; 496864562Sgshapiro } 496964562Sgshapiro 497066494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 497166494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 497266494Sgshapiro { 497366494Sgshapiro if (tTd(9, 1)) 497490792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 497590792Sgshapiro map->map_mname); 497666494Sgshapiro 497766494Sgshapiro /* 497890792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 497990792Sgshapiro ** a temporary failure using the bogus map and 498090792Sgshapiro ** map->map_tapp instead of the default permanent error. 498166494Sgshapiro */ 498266494Sgshapiro 498366494Sgshapiro map->map_mflags &= ~MF_DEFER; 498490792Sgshapiro return false; 498566494Sgshapiro } 498666494Sgshapiro 498764562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 498890792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 498964562Sgshapiro 499090792Sgshapiro /* try each host in the list */ 499164562Sgshapiro hostlist = newstr(pmap->ph_servers); 499290792Sgshapiro for (host = strtok(hostlist, " "); 499390792Sgshapiro host != NULL; 499490792Sgshapiro host = strtok(NULL, " ")) 499564562Sgshapiro { 499690792Sgshapiro /* set timeout */ 499764562Sgshapiro if (pmap->ph_timeout != 0) 499864562Sgshapiro { 499964562Sgshapiro if (setjmp(PHTimeout) != 0) 500064562Sgshapiro { 500164562Sgshapiro ev = NULL; 500264562Sgshapiro if (LogLevel > 1) 500364562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 500464562Sgshapiro "timeout connecting to PH server %.100s", 500590792Sgshapiro host); 500664562Sgshapiro errno = ETIMEDOUT; 500764562Sgshapiro goto ph_map_open_abort; 500864562Sgshapiro } 500990792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 501064562Sgshapiro } 501190792Sgshapiro 501290792Sgshapiro /* open connection to server */ 5013110560Sgshapiro if (ph_open(&(pmap->ph), host, 5014110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 5015110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 5016110560Sgshapiro#if NPH_VERSION >= 10200 5017110560Sgshapiro , NULL 5018110560Sgshapiro#endif 5019110560Sgshapiro ) == 0 5020110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 502164562Sgshapiro { 502264562Sgshapiro if (ev != NULL) 502390792Sgshapiro sm_clrevent(ev); 502490792Sgshapiro sm_free(hostlist); /* XXX */ 502590792Sgshapiro return true; 502664562Sgshapiro } 502790792Sgshapiro 502864562Sgshapiro ph_map_open_abort: 502990792Sgshapiro save_errno = errno; 503064562Sgshapiro if (ev != NULL) 503190792Sgshapiro sm_clrevent(ev); 5032110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 503390792Sgshapiro ph_map_close(map); 503490792Sgshapiro errno = save_errno; 503590792Sgshapiro } 503664562Sgshapiro 503766494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 503864562Sgshapiro { 503966494Sgshapiro if (errno == 0) 504064562Sgshapiro errno = EAGAIN; 504166494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 504266494Sgshapiro map->map_mname); 504364562Sgshapiro } 504466494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 504564562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 504666494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 504766494Sgshapiro map->map_mname); 504890792Sgshapiro sm_free(hostlist); /* XXX */ 504990792Sgshapiro return false; 505064562Sgshapiro} 505164562Sgshapiro 505264562Sgshapiro/* 505364562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 505464562Sgshapiro*/ 505564562Sgshapiro 505664562Sgshapirochar * 505764562Sgshapiroph_map_lookup(map, key, args, pstat) 505864562Sgshapiro MAP *map; 505964562Sgshapiro char *key; 506064562Sgshapiro char **args; 506164562Sgshapiro int *pstat; 506264562Sgshapiro{ 506390792Sgshapiro int i, save_errno = 0; 506490792Sgshapiro register SM_EVENT *ev = NULL; 506564562Sgshapiro PH_MAP_STRUCT *pmap; 506690792Sgshapiro char *value = NULL; 506764562Sgshapiro 506864562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 506964562Sgshapiro 507064562Sgshapiro *pstat = EX_OK; 507164562Sgshapiro 507290792Sgshapiro /* set timeout */ 507364562Sgshapiro if (pmap->ph_timeout != 0) 507464562Sgshapiro { 507564562Sgshapiro if (setjmp(PHTimeout) != 0) 507664562Sgshapiro { 507764562Sgshapiro ev = NULL; 507864562Sgshapiro if (LogLevel > 1) 507964562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 508064562Sgshapiro "timeout during PH lookup of %.100s", 508164562Sgshapiro key); 508264562Sgshapiro errno = ETIMEDOUT; 508364562Sgshapiro *pstat = EX_TEMPFAIL; 508464562Sgshapiro goto ph_map_lookup_abort; 508564562Sgshapiro } 508690792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 508764562Sgshapiro } 508864562Sgshapiro 508990792Sgshapiro /* perform lookup */ 509090792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 509190792Sgshapiro if (i == -1) 509290792Sgshapiro *pstat = EX_TEMPFAIL; 5093110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 509490792Sgshapiro *pstat = EX_UNAVAILABLE; 509564562Sgshapiro 509664562Sgshapiro ph_map_lookup_abort: 509764562Sgshapiro if (ev != NULL) 509890792Sgshapiro sm_clrevent(ev); 509964562Sgshapiro 510064562Sgshapiro /* 510190792Sgshapiro ** Close the connection if the timer popped 510264562Sgshapiro ** or we got a temporary PH error 510364562Sgshapiro */ 510464562Sgshapiro 510564562Sgshapiro if (*pstat == EX_TEMPFAIL) 510690792Sgshapiro { 510790792Sgshapiro save_errno = errno; 5108110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 510990792Sgshapiro ph_map_close(map); 511090792Sgshapiro errno = save_errno; 511190792Sgshapiro } 511264562Sgshapiro 511364562Sgshapiro if (*pstat == EX_OK) 511464562Sgshapiro { 511564562Sgshapiro if (tTd(38,20)) 511690792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 511764562Sgshapiro 511864562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 511990792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 512064562Sgshapiro else 512190792Sgshapiro return map_rewrite(map, value, strlen(value), args); 512264562Sgshapiro } 512364562Sgshapiro 512464562Sgshapiro return NULL; 512564562Sgshapiro} 512664562Sgshapiro#endif /* PH_MAP */ 5127168515Sgshapiro 512890792Sgshapiro/* 512942575Speter** syslog map 513038032Speter*/ 513138032Speter 513238032Speter#define map_prio map_lockfd /* overload field */ 513338032Speter 513438032Speter/* 513542575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 513638032Speter*/ 513738032Speter 513838032Speterbool 513938032Spetersyslog_map_parseargs(map, args) 514038032Speter MAP *map; 514138032Speter char *args; 514238032Speter{ 514338032Speter char *p = args; 514438032Speter char *priority = NULL; 514538032Speter 514664562Sgshapiro /* there is no check whether there is really an argument */ 514764562Sgshapiro while (*p != '\0') 514838032Speter { 514938032Speter while (isascii(*p) && isspace(*p)) 515038032Speter p++; 515138032Speter if (*p != '-') 515238032Speter break; 515364562Sgshapiro ++p; 515464562Sgshapiro if (*p == 'D') 515564562Sgshapiro { 515664562Sgshapiro map->map_mflags |= MF_DEFER; 515764562Sgshapiro ++p; 515864562Sgshapiro } 515964562Sgshapiro else if (*p == 'S') 516064562Sgshapiro { 516164562Sgshapiro map->map_spacesub = *++p; 516264562Sgshapiro if (*p != '\0') 516364562Sgshapiro p++; 516464562Sgshapiro } 516564562Sgshapiro else if (*p == 'L') 516664562Sgshapiro { 516764562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 516864562Sgshapiro continue; 516964562Sgshapiro if (*p == '\0') 517064562Sgshapiro break; 517164562Sgshapiro priority = p; 517264562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 517364562Sgshapiro p++; 517464562Sgshapiro if (*p != '\0') 517564562Sgshapiro *p++ = '\0'; 517664562Sgshapiro } 517764562Sgshapiro else 517864562Sgshapiro { 517964562Sgshapiro syserr("Illegal option %c map syslog", *p); 518064562Sgshapiro ++p; 518164562Sgshapiro } 518238032Speter } 518338032Speter 518438032Speter if (priority == NULL) 518538032Speter map->map_prio = LOG_INFO; 518638032Speter else 518738032Speter { 518890792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 518938032Speter priority += 4; 519038032Speter 519138032Speter#ifdef LOG_EMERG 519290792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 519338032Speter map->map_prio = LOG_EMERG; 519438032Speter else 519564562Sgshapiro#endif /* LOG_EMERG */ 519638032Speter#ifdef LOG_ALERT 519790792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 519838032Speter map->map_prio = LOG_ALERT; 519938032Speter else 520064562Sgshapiro#endif /* LOG_ALERT */ 520138032Speter#ifdef LOG_CRIT 520290792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 520338032Speter map->map_prio = LOG_CRIT; 520438032Speter else 520564562Sgshapiro#endif /* LOG_CRIT */ 520638032Speter#ifdef LOG_ERR 520790792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 520838032Speter map->map_prio = LOG_ERR; 520938032Speter else 521064562Sgshapiro#endif /* LOG_ERR */ 521138032Speter#ifdef LOG_WARNING 521290792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 521338032Speter map->map_prio = LOG_WARNING; 521438032Speter else 521564562Sgshapiro#endif /* LOG_WARNING */ 521638032Speter#ifdef LOG_NOTICE 521790792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 521838032Speter map->map_prio = LOG_NOTICE; 521938032Speter else 522064562Sgshapiro#endif /* LOG_NOTICE */ 522138032Speter#ifdef LOG_INFO 522290792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 522338032Speter map->map_prio = LOG_INFO; 522438032Speter else 522564562Sgshapiro#endif /* LOG_INFO */ 522638032Speter#ifdef LOG_DEBUG 522790792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 522838032Speter map->map_prio = LOG_DEBUG; 522938032Speter else 523064562Sgshapiro#endif /* LOG_DEBUG */ 523138032Speter { 523290792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 523338032Speter priority); 523490792Sgshapiro return false; 523538032Speter } 523638032Speter } 523790792Sgshapiro return true; 523838032Speter} 523938032Speter 524038032Speter/* 524142575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 524238032Speter*/ 524338032Speter 524438032Speterchar * 524538032Spetersyslog_map_lookup(map, string, args, statp) 524638032Speter MAP *map; 524738032Speter char *string; 524838032Speter char **args; 524938032Speter int *statp; 525038032Speter{ 525138032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 525238032Speter 525338032Speter if (ptr != NULL) 525438032Speter { 525538032Speter if (tTd(38, 20)) 525690792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 525764562Sgshapiro map->map_mname, map->map_prio, ptr); 525838032Speter 525938032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 526038032Speter } 526138032Speter 526238032Speter *statp = EX_OK; 526338032Speter return ""; 526438032Speter} 526538032Speter 5266168515Sgshapiro#if _FFR_DPRINTF_MAP 526790792Sgshapiro/* 5268168515Sgshapiro** dprintf map 5269168515Sgshapiro*/ 5270168515Sgshapiro 5271168515Sgshapiro#define map_dbg_level map_lockfd /* overload field */ 5272168515Sgshapiro 5273168515Sgshapiro/* 5274168515Sgshapiro** DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages. 5275168515Sgshapiro*/ 5276168515Sgshapiro 5277168515Sgshapirobool 5278168515Sgshapirodprintf_map_parseargs(map, args) 5279168515Sgshapiro MAP *map; 5280168515Sgshapiro char *args; 5281168515Sgshapiro{ 5282168515Sgshapiro char *p = args; 5283168515Sgshapiro char *dbg_level = NULL; 5284168515Sgshapiro 5285168515Sgshapiro /* there is no check whether there is really an argument */ 5286168515Sgshapiro while (*p != '\0') 5287168515Sgshapiro { 5288168515Sgshapiro while (isascii(*p) && isspace(*p)) 5289168515Sgshapiro p++; 5290168515Sgshapiro if (*p != '-') 5291168515Sgshapiro break; 5292168515Sgshapiro ++p; 5293168515Sgshapiro if (*p == 'D') 5294168515Sgshapiro { 5295168515Sgshapiro map->map_mflags |= MF_DEFER; 5296168515Sgshapiro ++p; 5297168515Sgshapiro } 5298168515Sgshapiro else if (*p == 'S') 5299168515Sgshapiro { 5300168515Sgshapiro map->map_spacesub = *++p; 5301168515Sgshapiro if (*p != '\0') 5302168515Sgshapiro p++; 5303168515Sgshapiro } 5304168515Sgshapiro else if (*p == 'd') 5305168515Sgshapiro { 5306168515Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 5307168515Sgshapiro continue; 5308168515Sgshapiro if (*p == '\0') 5309168515Sgshapiro break; 5310168515Sgshapiro dbg_level = p; 5311168515Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 5312168515Sgshapiro p++; 5313168515Sgshapiro if (*p != '\0') 5314168515Sgshapiro *p++ = '\0'; 5315168515Sgshapiro } 5316168515Sgshapiro else 5317168515Sgshapiro { 5318168515Sgshapiro syserr("Illegal option %c map dprintf", *p); 5319168515Sgshapiro ++p; 5320168515Sgshapiro } 5321168515Sgshapiro } 5322168515Sgshapiro 5323168515Sgshapiro if (dbg_level == NULL) 5324168515Sgshapiro map->map_dbg_level = 0; 5325168515Sgshapiro else 5326168515Sgshapiro { 5327168515Sgshapiro if (!(isascii(*dbg_level) && isdigit(*dbg_level))) 5328168515Sgshapiro { 5329168515Sgshapiro syserr("dprintf map \"%s\", file %s: -d should specify a number, not %s", 5330168515Sgshapiro map->map_mname, map->map_file, 5331168515Sgshapiro dbg_level); 5332168515Sgshapiro return false; 5333168515Sgshapiro } 5334168515Sgshapiro map->map_dbg_level = atoi(dbg_level); 5335168515Sgshapiro } 5336168515Sgshapiro return true; 5337168515Sgshapiro} 5338168515Sgshapiro 5339168515Sgshapiro/* 5340168515Sgshapiro** DPRINTF_MAP_LOOKUP -- rewrite and print message. Always return empty string 5341168515Sgshapiro*/ 5342168515Sgshapiro 5343168515Sgshapirochar * 5344168515Sgshapirodprintf_map_lookup(map, string, args, statp) 5345168515Sgshapiro MAP *map; 5346168515Sgshapiro char *string; 5347168515Sgshapiro char **args; 5348168515Sgshapiro int *statp; 5349168515Sgshapiro{ 5350168515Sgshapiro char *ptr = map_rewrite(map, string, strlen(string), args); 5351168515Sgshapiro 5352168515Sgshapiro if (ptr != NULL && tTd(85, map->map_dbg_level)) 5353168515Sgshapiro sm_dprintf("%s\n", ptr); 5354168515Sgshapiro *statp = EX_OK; 5355168515Sgshapiro return ""; 5356168515Sgshapiro} 5357168515Sgshapiro#endif /* _FFR_DPRINTF_MAP */ 5358168515Sgshapiro 5359168515Sgshapiro/* 536038032Speter** HESIOD Modules 536138032Speter*/ 536238032Speter 536390792Sgshapiro#if HESIOD 536438032Speter 536538032Speterbool 536638032Speterhes_map_open(map, mode) 536738032Speter MAP *map; 536838032Speter int mode; 536938032Speter{ 537038032Speter if (tTd(38, 2)) 537190792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 537238032Speter map->map_mname, map->map_file, mode); 537338032Speter 537438032Speter if (mode != O_RDONLY) 537538032Speter { 537638032Speter /* issue a pseudo-error message */ 537790792Sgshapiro errno = SM_EMAPCANTWRITE; 537890792Sgshapiro return false; 537938032Speter } 538038032Speter 538164562Sgshapiro# ifdef HESIOD_INIT 538238032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 538390792Sgshapiro return true; 538438032Speter 538538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 538694334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 538790792Sgshapiro sm_errstring(errno)); 538890792Sgshapiro return false; 538964562Sgshapiro# else /* HESIOD_INIT */ 539038032Speter if (hes_error() == HES_ER_UNINIT) 539138032Speter hes_init(); 539238032Speter switch (hes_error()) 539338032Speter { 539438032Speter case HES_ER_OK: 539538032Speter case HES_ER_NOTFOUND: 539690792Sgshapiro return true; 539738032Speter } 539838032Speter 539938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 540094334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 540138032Speter 540290792Sgshapiro return false; 540364562Sgshapiro# endif /* HESIOD_INIT */ 540438032Speter} 540538032Speter 540638032Speterchar * 540738032Speterhes_map_lookup(map, name, av, statp) 540838032Speter MAP *map; 540938032Speter char *name; 541038032Speter char **av; 541138032Speter int *statp; 541238032Speter{ 541338032Speter char **hp; 541438032Speter 541538032Speter if (tTd(38, 20)) 541690792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 541738032Speter 541838032Speter if (name[0] == '\\') 541938032Speter { 542038032Speter char *np; 542138032Speter int nl; 542277349Sgshapiro int save_errno; 542338032Speter char nbuf[MAXNAME]; 542438032Speter 542538032Speter nl = strlen(name); 5426168515Sgshapiro if (nl < sizeof(nbuf) - 1) 542738032Speter np = nbuf; 542838032Speter else 542938032Speter np = xalloc(strlen(name) + 2); 543038032Speter np[0] = '\\'; 5431168515Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof(nbuf)) - 1); 543264562Sgshapiro# ifdef HESIOD_INIT 543338032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 543464562Sgshapiro# else /* HESIOD_INIT */ 543538032Speter hp = hes_resolve(np, map->map_file); 543664562Sgshapiro# endif /* HESIOD_INIT */ 543777349Sgshapiro save_errno = errno; 543838032Speter if (np != nbuf) 543990792Sgshapiro sm_free(np); /* XXX */ 544077349Sgshapiro errno = save_errno; 544138032Speter } 544238032Speter else 544338032Speter { 544464562Sgshapiro# ifdef HESIOD_INIT 544538032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 544664562Sgshapiro# else /* HESIOD_INIT */ 544738032Speter hp = hes_resolve(name, map->map_file); 544864562Sgshapiro# endif /* HESIOD_INIT */ 544938032Speter } 545064562Sgshapiro# ifdef HESIOD_INIT 545177349Sgshapiro if (hp == NULL || *hp == NULL) 545238032Speter { 545338032Speter switch (errno) 545438032Speter { 545538032Speter case ENOENT: 545638032Speter *statp = EX_NOTFOUND; 545738032Speter break; 545838032Speter case ECONNREFUSED: 545938032Speter *statp = EX_TEMPFAIL; 546038032Speter break; 546190792Sgshapiro case EMSGSIZE: 546238032Speter case ENOMEM: 546338032Speter default: 546438032Speter *statp = EX_UNAVAILABLE; 546538032Speter break; 546638032Speter } 546782017Sgshapiro if (hp != NULL) 546882017Sgshapiro hesiod_free_list(HesiodContext, hp); 546938032Speter return NULL; 547038032Speter } 547164562Sgshapiro# else /* HESIOD_INIT */ 547238032Speter if (hp == NULL || hp[0] == NULL) 547338032Speter { 547438032Speter switch (hes_error()) 547538032Speter { 547638032Speter case HES_ER_OK: 547738032Speter *statp = EX_OK; 547838032Speter break; 547938032Speter 548038032Speter case HES_ER_NOTFOUND: 548138032Speter *statp = EX_NOTFOUND; 548238032Speter break; 548338032Speter 548438032Speter case HES_ER_CONFIG: 548538032Speter *statp = EX_UNAVAILABLE; 548638032Speter break; 548738032Speter 548838032Speter case HES_ER_NET: 548938032Speter *statp = EX_TEMPFAIL; 549038032Speter break; 549138032Speter } 549238032Speter return NULL; 549338032Speter } 549464562Sgshapiro# endif /* HESIOD_INIT */ 549538032Speter 549638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 549738032Speter return map_rewrite(map, name, strlen(name), NULL); 549838032Speter else 549938032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 550038032Speter} 550138032Speter 550290792Sgshapiro/* 550390792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 550490792Sgshapiro*/ 550590792Sgshapiro 550690792Sgshapirovoid 550790792Sgshapirohes_map_close(map) 550890792Sgshapiro MAP *map; 550990792Sgshapiro{ 551090792Sgshapiro if (tTd(38, 20)) 551190792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 551290792Sgshapiro 551390792Sgshapiro# ifdef HESIOD_INIT 551490792Sgshapiro /* Free the hesiod context */ 551590792Sgshapiro if (HesiodContext != NULL) 551690792Sgshapiro { 551790792Sgshapiro hesiod_end(HesiodContext); 551890792Sgshapiro HesiodContext = NULL; 551990792Sgshapiro } 552090792Sgshapiro# endif /* HESIOD_INIT */ 552190792Sgshapiro} 552290792Sgshapiro 552364562Sgshapiro#endif /* HESIOD */ 552490792Sgshapiro/* 552538032Speter** NeXT NETINFO Modules 552638032Speter*/ 552738032Speter 552838032Speter#if NETINFO 552938032Speter 553038032Speter# define NETINFO_DEFAULT_DIR "/aliases" 553138032Speter# define NETINFO_DEFAULT_PROPERTY "members" 553238032Speter 553338032Speter/* 553438032Speter** NI_MAP_OPEN -- open NetInfo Aliases 553538032Speter*/ 553638032Speter 553738032Speterbool 553838032Speterni_map_open(map, mode) 553938032Speter MAP *map; 554038032Speter int mode; 554138032Speter{ 554238032Speter if (tTd(38, 2)) 554390792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 554438032Speter map->map_mname, map->map_file, mode); 554538032Speter mode &= O_ACCMODE; 554638032Speter 554738032Speter if (*map->map_file == '\0') 554838032Speter map->map_file = NETINFO_DEFAULT_DIR; 554938032Speter 555038032Speter if (map->map_valcolnm == NULL) 555138032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 555238032Speter 555390792Sgshapiro if (map->map_coldelim == '\0') 555490792Sgshapiro { 555590792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 555690792Sgshapiro map->map_coldelim = ','; 555790792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 555890792Sgshapiro map->map_coldelim = ' '; 555990792Sgshapiro } 556090792Sgshapiro return true; 556138032Speter} 556238032Speter 556338032Speter 556438032Speter/* 556538032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 556638032Speter*/ 556738032Speter 556838032Speterchar * 556938032Speterni_map_lookup(map, name, av, statp) 557038032Speter MAP *map; 557138032Speter char *name; 557238032Speter char **av; 557338032Speter int *statp; 557438032Speter{ 557538032Speter char *res; 557638032Speter char *propval; 557738032Speter 557838032Speter if (tTd(38, 20)) 557990792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 558038032Speter 558138032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 558238032Speter map->map_valcolnm, map->map_coldelim); 558338032Speter 558438032Speter if (propval == NULL) 558538032Speter return NULL; 558638032Speter 558790792Sgshapiro SM_TRY 558890792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 558990792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 559090792Sgshapiro else 559190792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 559290792Sgshapiro SM_FINALLY 559390792Sgshapiro sm_free(propval); 559490792Sgshapiro SM_END_TRY 559538032Speter return res; 559638032Speter} 559738032Speter 559838032Speter 559964562Sgshapirostatic bool 560038032Speterni_getcanonname(name, hbsize, statp) 560138032Speter char *name; 560238032Speter int hbsize; 560338032Speter int *statp; 560438032Speter{ 560538032Speter char *vptr; 560638032Speter char *ptr; 560738032Speter char nbuf[MAXNAME + 1]; 560838032Speter 560938032Speter if (tTd(38, 20)) 561090792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 561138032Speter 5612168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 561338032Speter { 561438032Speter *statp = EX_UNAVAILABLE; 561590792Sgshapiro return false; 561638032Speter } 561773188Sgshapiro (void) shorten_hostname(nbuf); 561838032Speter 561938032Speter /* we only accept single token search key */ 562038032Speter if (strchr(nbuf, '.')) 562138032Speter { 562238032Speter *statp = EX_NOHOST; 562390792Sgshapiro return false; 562438032Speter } 562538032Speter 562638032Speter /* Do the search */ 562738032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 562838032Speter 562938032Speter if (vptr == NULL) 563038032Speter { 563138032Speter *statp = EX_NOHOST; 563290792Sgshapiro return false; 563338032Speter } 563438032Speter 563538032Speter /* Only want the first machine name */ 563638032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 563738032Speter *ptr = '\0'; 563838032Speter 563990792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 564038032Speter { 564177349Sgshapiro sm_free(vptr); 564290792Sgshapiro *statp = EX_UNAVAILABLE; 564390792Sgshapiro return true; 564438032Speter } 564577349Sgshapiro sm_free(vptr); 564690792Sgshapiro *statp = EX_OK; 564790792Sgshapiro return false; 564838032Speter} 564990792Sgshapiro#endif /* NETINFO */ 565038032Speter/* 565138032Speter** TEXT (unindexed text file) Modules 565238032Speter** 565338032Speter** This code donated by Sun Microsystems. 565438032Speter*/ 565538032Speter 565638032Speter#define map_sff map_lockfd /* overload field */ 565738032Speter 565838032Speter 565938032Speter/* 566038032Speter** TEXT_MAP_OPEN -- open text table 566138032Speter*/ 566238032Speter 566338032Speterbool 566438032Spetertext_map_open(map, mode) 566538032Speter MAP *map; 566638032Speter int mode; 566738032Speter{ 566864562Sgshapiro long sff; 566938032Speter int i; 567038032Speter 567138032Speter if (tTd(38, 2)) 567290792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 567338032Speter map->map_mname, map->map_file, mode); 567438032Speter 567538032Speter mode &= O_ACCMODE; 567638032Speter if (mode != O_RDONLY) 567738032Speter { 567838032Speter errno = EPERM; 567990792Sgshapiro return false; 568038032Speter } 568138032Speter 568238032Speter if (*map->map_file == '\0') 568338032Speter { 568438032Speter syserr("text map \"%s\": file name required", 568538032Speter map->map_mname); 568690792Sgshapiro return false; 568738032Speter } 568838032Speter 568938032Speter if (map->map_file[0] != '/') 569038032Speter { 569138032Speter syserr("text map \"%s\": file name must be fully qualified", 569238032Speter map->map_mname); 569390792Sgshapiro return false; 569438032Speter } 569538032Speter 569638032Speter sff = SFF_ROOTOK|SFF_REGONLY; 569764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 569838032Speter sff |= SFF_NOWLINK; 569964562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 570038032Speter sff |= SFF_SAFEDIRPATH; 570138032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 570238032Speter sff, S_IRUSR, NULL)) != 0) 570338032Speter { 570464562Sgshapiro int save_errno = errno; 570564562Sgshapiro 570638032Speter /* cannot open this map */ 570738032Speter if (tTd(38, 2)) 570890792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 570964562Sgshapiro errno = save_errno; 571038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 571138032Speter syserr("text map \"%s\": unsafe map file %s", 571238032Speter map->map_mname, map->map_file); 571390792Sgshapiro return false; 571438032Speter } 571538032Speter 571638032Speter if (map->map_keycolnm == NULL) 571738032Speter map->map_keycolno = 0; 571838032Speter else 571938032Speter { 572038032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 572138032Speter { 572238032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 572338032Speter map->map_mname, map->map_file, 572438032Speter map->map_keycolnm); 572590792Sgshapiro return false; 572638032Speter } 572738032Speter map->map_keycolno = atoi(map->map_keycolnm); 572838032Speter } 572938032Speter 573038032Speter if (map->map_valcolnm == NULL) 573138032Speter map->map_valcolno = 0; 573238032Speter else 573338032Speter { 573438032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 573538032Speter { 573638032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 573738032Speter map->map_mname, map->map_file, 573838032Speter map->map_valcolnm); 573990792Sgshapiro return false; 574038032Speter } 574138032Speter map->map_valcolno = atoi(map->map_valcolnm); 574238032Speter } 574338032Speter 574438032Speter if (tTd(38, 2)) 574538032Speter { 574690792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 574738032Speter map->map_mname, map->map_file); 574838032Speter if (map->map_coldelim == '\0') 574990792Sgshapiro sm_dprintf("(white space)\n"); 575038032Speter else 575190792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 575238032Speter } 575338032Speter 575438032Speter map->map_sff = sff; 575590792Sgshapiro return true; 575638032Speter} 575738032Speter 575838032Speter 575938032Speter/* 576038032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 576138032Speter*/ 576238032Speter 576338032Speterchar * 576438032Spetertext_map_lookup(map, name, av, statp) 576538032Speter MAP *map; 576638032Speter char *name; 576738032Speter char **av; 576838032Speter int *statp; 576938032Speter{ 577038032Speter char *vp; 577138032Speter auto int vsize; 577238032Speter int buflen; 577390792Sgshapiro SM_FILE_T *f; 577438032Speter char delim; 577538032Speter int key_idx; 577638032Speter bool found_it; 577764562Sgshapiro long sff = map->map_sff; 577838032Speter char search_key[MAXNAME + 1]; 577938032Speter char linebuf[MAXLINE]; 578038032Speter char buf[MAXNAME + 1]; 578138032Speter 578290792Sgshapiro found_it = false; 578338032Speter if (tTd(38, 20)) 578490792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 578538032Speter 578638032Speter buflen = strlen(name); 5787168515Sgshapiro if (buflen > sizeof(search_key) - 1) 5788168515Sgshapiro buflen = sizeof(search_key) - 1; /* XXX just cut if off? */ 578964562Sgshapiro memmove(search_key, name, buflen); 579038032Speter search_key[buflen] = '\0'; 579138032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 579238032Speter makelower(search_key); 579338032Speter 579438032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 579538032Speter if (f == NULL) 579638032Speter { 579738032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 579838032Speter *statp = EX_UNAVAILABLE; 579938032Speter return NULL; 580038032Speter } 580138032Speter key_idx = map->map_keycolno; 580238032Speter delim = map->map_coldelim; 580398121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 5804168515Sgshapiro linebuf, sizeof(linebuf)) != NULL) 580538032Speter { 580638032Speter char *p; 580738032Speter 580838032Speter /* skip comment line */ 580938032Speter if (linebuf[0] == '#') 581038032Speter continue; 581138032Speter p = strchr(linebuf, '\n'); 581238032Speter if (p != NULL) 581338032Speter *p = '\0'; 5814168515Sgshapiro p = get_column(linebuf, key_idx, delim, buf, sizeof(buf)); 581590792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 581638032Speter { 581790792Sgshapiro found_it = true; 581838032Speter break; 581938032Speter } 582038032Speter } 582190792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 582238032Speter if (!found_it) 582338032Speter { 582438032Speter *statp = EX_NOTFOUND; 582538032Speter return NULL; 582638032Speter } 5827168515Sgshapiro vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof(buf)); 582842575Speter if (vp == NULL) 582942575Speter { 583042575Speter *statp = EX_NOTFOUND; 583142575Speter return NULL; 583242575Speter } 583338032Speter vsize = strlen(vp); 583438032Speter *statp = EX_OK; 583538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 583638032Speter return map_rewrite(map, name, strlen(name), NULL); 583738032Speter else 583838032Speter return map_rewrite(map, vp, vsize, av); 583938032Speter} 584038032Speter 584138032Speter/* 584238032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 584338032Speter*/ 584438032Speter 584564562Sgshapirostatic bool 584638032Spetertext_getcanonname(name, hbsize, statp) 584738032Speter char *name; 584838032Speter int hbsize; 584938032Speter int *statp; 585038032Speter{ 585138032Speter bool found; 585273188Sgshapiro char *dot; 585390792Sgshapiro SM_FILE_T *f; 585438032Speter char linebuf[MAXLINE]; 585538032Speter char cbuf[MAXNAME + 1]; 585638032Speter char nbuf[MAXNAME + 1]; 585738032Speter 585838032Speter if (tTd(38, 20)) 585990792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 586038032Speter 5861168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 586238032Speter { 586338032Speter *statp = EX_UNAVAILABLE; 586490792Sgshapiro return false; 586538032Speter } 586673188Sgshapiro dot = shorten_hostname(nbuf); 586738032Speter 586890792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 586990792Sgshapiro NULL); 587038032Speter if (f == NULL) 587138032Speter { 587238032Speter *statp = EX_UNAVAILABLE; 587390792Sgshapiro return false; 587438032Speter } 587590792Sgshapiro found = false; 587690792Sgshapiro while (!found && 587798121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 5878168515Sgshapiro linebuf, sizeof(linebuf)) != NULL) 587938032Speter { 588038032Speter char *p = strpbrk(linebuf, "#\n"); 588138032Speter 588238032Speter if (p != NULL) 588338032Speter *p = '\0'; 588438032Speter if (linebuf[0] != '\0') 588573188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 5886168515Sgshapiro cbuf, sizeof(cbuf)); 588738032Speter } 588890792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 588938032Speter if (!found) 589038032Speter { 589138032Speter *statp = EX_NOHOST; 589290792Sgshapiro return false; 589338032Speter } 589438032Speter 589590792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 589638032Speter { 589790792Sgshapiro *statp = EX_UNAVAILABLE; 589890792Sgshapiro return false; 589938032Speter } 590090792Sgshapiro *statp = EX_OK; 590190792Sgshapiro return true; 590238032Speter} 590390792Sgshapiro/* 590438032Speter** STAB (Symbol Table) Modules 590538032Speter*/ 590638032Speter 590738032Speter 590838032Speter/* 590938032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 591038032Speter*/ 591138032Speter 591238032Speter/* ARGSUSED2 */ 591338032Speterchar * 591438032Speterstab_map_lookup(map, name, av, pstat) 591538032Speter register MAP *map; 591638032Speter char *name; 591738032Speter char **av; 591838032Speter int *pstat; 591938032Speter{ 592038032Speter register STAB *s; 592138032Speter 592238032Speter if (tTd(38, 20)) 592390792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 592438032Speter map->map_mname, name); 592538032Speter 592638032Speter s = stab(name, ST_ALIAS, ST_FIND); 5927147078Sgshapiro if (s == NULL) 5928147078Sgshapiro return NULL; 5929147078Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 5930147078Sgshapiro return map_rewrite(map, name, strlen(name), NULL); 5931147078Sgshapiro else 5932147078Sgshapiro return map_rewrite(map, s->s_alias, strlen(s->s_alias), av); 593338032Speter} 593438032Speter 593538032Speter/* 593638032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 593738032Speter*/ 593838032Speter 593938032Spetervoid 594038032Speterstab_map_store(map, lhs, rhs) 594138032Speter register MAP *map; 594238032Speter char *lhs; 594338032Speter char *rhs; 594438032Speter{ 594538032Speter register STAB *s; 594638032Speter 594738032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 594838032Speter s->s_alias = newstr(rhs); 594938032Speter} 595038032Speter 595138032Speter 595238032Speter/* 595338032Speter** STAB_MAP_OPEN -- initialize (reads data file) 595438032Speter** 595538032Speter** This is a wierd case -- it is only intended as a fallback for 595638032Speter** aliases. For this reason, opens for write (only during a 595738032Speter** "newaliases") always fails, and opens for read open the 595838032Speter** actual underlying text file instead of the database. 595938032Speter*/ 596038032Speter 596138032Speterbool 596238032Speterstab_map_open(map, mode) 596338032Speter register MAP *map; 596438032Speter int mode; 596538032Speter{ 596690792Sgshapiro SM_FILE_T *af; 596764562Sgshapiro long sff; 596838032Speter struct stat st; 596938032Speter 597038032Speter if (tTd(38, 2)) 597190792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 597238032Speter map->map_mname, map->map_file, mode); 597338032Speter 597438032Speter mode &= O_ACCMODE; 597538032Speter if (mode != O_RDONLY) 597638032Speter { 597738032Speter errno = EPERM; 597890792Sgshapiro return false; 597938032Speter } 598038032Speter 598138032Speter sff = SFF_ROOTOK|SFF_REGONLY; 598264562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 598338032Speter sff |= SFF_NOWLINK; 598464562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 598538032Speter sff |= SFF_SAFEDIRPATH; 598638032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 598738032Speter if (af == NULL) 598890792Sgshapiro return false; 598990792Sgshapiro readaliases(map, af, false, false); 599038032Speter 599190792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 599238032Speter map->map_mtime = st.st_mtime; 599390792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 599438032Speter 599590792Sgshapiro return true; 599638032Speter} 599790792Sgshapiro/* 599838032Speter** Implicit Modules 599938032Speter** 600038032Speter** Tries several types. For back compatibility of aliases. 600138032Speter*/ 600238032Speter 600338032Speter 600438032Speter/* 600538032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 600638032Speter*/ 600738032Speter 600838032Speterchar * 600938032Speterimpl_map_lookup(map, name, av, pstat) 601038032Speter MAP *map; 601138032Speter char *name; 601238032Speter char **av; 601338032Speter int *pstat; 601438032Speter{ 601538032Speter if (tTd(38, 20)) 601690792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 601738032Speter map->map_mname, name); 601838032Speter 601990792Sgshapiro#if NEWDB 602038032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 602138032Speter return db_map_lookup(map, name, av, pstat); 602264562Sgshapiro#endif /* NEWDB */ 602390792Sgshapiro#if NDBM 602438032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 602538032Speter return ndbm_map_lookup(map, name, av, pstat); 602664562Sgshapiro#endif /* NDBM */ 602738032Speter return stab_map_lookup(map, name, av, pstat); 602838032Speter} 602938032Speter 603038032Speter/* 603138032Speter** IMPL_MAP_STORE -- store in open databases 603238032Speter*/ 603338032Speter 603438032Spetervoid 603538032Speterimpl_map_store(map, lhs, rhs) 603638032Speter MAP *map; 603738032Speter char *lhs; 603838032Speter char *rhs; 603938032Speter{ 604038032Speter if (tTd(38, 12)) 604190792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 604238032Speter map->map_mname, lhs, rhs); 604390792Sgshapiro#if NEWDB 604438032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 604538032Speter db_map_store(map, lhs, rhs); 604664562Sgshapiro#endif /* NEWDB */ 604790792Sgshapiro#if NDBM 604838032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 604938032Speter ndbm_map_store(map, lhs, rhs); 605064562Sgshapiro#endif /* NDBM */ 605138032Speter stab_map_store(map, lhs, rhs); 605238032Speter} 605338032Speter 605438032Speter/* 605538032Speter** IMPL_MAP_OPEN -- implicit database open 605638032Speter*/ 605738032Speter 605838032Speterbool 605938032Speterimpl_map_open(map, mode) 606038032Speter MAP *map; 606138032Speter int mode; 606238032Speter{ 606338032Speter if (tTd(38, 2)) 606490792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 606538032Speter map->map_mname, map->map_file, mode); 606638032Speter 606738032Speter mode &= O_ACCMODE; 606890792Sgshapiro#if NEWDB 606938032Speter map->map_mflags |= MF_IMPL_HASH; 607038032Speter if (hash_map_open(map, mode)) 607138032Speter { 607238032Speter# ifdef NDBM_YP_COMPAT 607338032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 607464562Sgshapiro# endif /* NDBM_YP_COMPAT */ 607590792Sgshapiro return true; 607638032Speter } 607738032Speter else 607838032Speter map->map_mflags &= ~MF_IMPL_HASH; 607964562Sgshapiro#endif /* NEWDB */ 608090792Sgshapiro#if NDBM 608138032Speter map->map_mflags |= MF_IMPL_NDBM; 608238032Speter if (ndbm_map_open(map, mode)) 608338032Speter { 608490792Sgshapiro return true; 608538032Speter } 608638032Speter else 608738032Speter map->map_mflags &= ~MF_IMPL_NDBM; 608864562Sgshapiro#endif /* NDBM */ 608938032Speter 609038032Speter#if defined(NEWDB) || defined(NDBM) 609138032Speter if (Verbose) 609238032Speter message("WARNING: cannot open alias database %s%s", 609338032Speter map->map_file, 609438032Speter mode == O_RDONLY ? "; reading text version" : ""); 609564562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 609638032Speter if (mode != O_RDONLY) 609738032Speter usrerr("Cannot rebuild aliases: no database format defined"); 609864562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 609938032Speter 610038032Speter if (mode == O_RDONLY) 610138032Speter return stab_map_open(map, mode); 610238032Speter else 610390792Sgshapiro return false; 610438032Speter} 610538032Speter 610638032Speter 610738032Speter/* 610838032Speter** IMPL_MAP_CLOSE -- close any open database(s) 610938032Speter*/ 611038032Speter 611138032Spetervoid 611238032Speterimpl_map_close(map) 611338032Speter MAP *map; 611438032Speter{ 611538032Speter if (tTd(38, 9)) 611690792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 611738032Speter map->map_mname, map->map_file, map->map_mflags); 611890792Sgshapiro#if NEWDB 611938032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 612038032Speter { 612138032Speter db_map_close(map); 612238032Speter map->map_mflags &= ~MF_IMPL_HASH; 612338032Speter } 612464562Sgshapiro#endif /* NEWDB */ 612538032Speter 612690792Sgshapiro#if NDBM 612738032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 612838032Speter { 612938032Speter ndbm_map_close(map); 613038032Speter map->map_mflags &= ~MF_IMPL_NDBM; 613138032Speter } 613264562Sgshapiro#endif /* NDBM */ 613338032Speter} 613490792Sgshapiro/* 613538032Speter** User map class. 613638032Speter** 613738032Speter** Provides access to the system password file. 613838032Speter*/ 613938032Speter 614038032Speter/* 614138032Speter** USER_MAP_OPEN -- open user map 614238032Speter** 614338032Speter** Really just binds field names to field numbers. 614438032Speter*/ 614538032Speter 614638032Speterbool 614738032Speteruser_map_open(map, mode) 614838032Speter MAP *map; 614938032Speter int mode; 615038032Speter{ 615138032Speter if (tTd(38, 2)) 615290792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 615338032Speter map->map_mname, mode); 615438032Speter 615538032Speter mode &= O_ACCMODE; 615638032Speter if (mode != O_RDONLY) 615738032Speter { 615838032Speter /* issue a pseudo-error message */ 615990792Sgshapiro errno = SM_EMAPCANTWRITE; 616090792Sgshapiro return false; 616138032Speter } 616238032Speter if (map->map_valcolnm == NULL) 616364562Sgshapiro /* EMPTY */ 616438032Speter /* nothing */ ; 616590792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 616638032Speter map->map_valcolno = 1; 616790792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 616838032Speter map->map_valcolno = 2; 616990792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 617038032Speter map->map_valcolno = 3; 617190792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 617238032Speter map->map_valcolno = 4; 617390792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 617438032Speter map->map_valcolno = 5; 617590792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 617638032Speter map->map_valcolno = 6; 617790792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 617838032Speter map->map_valcolno = 7; 617938032Speter else 618038032Speter { 618138032Speter syserr("User map %s: unknown column name %s", 618238032Speter map->map_mname, map->map_valcolnm); 618390792Sgshapiro return false; 618438032Speter } 618590792Sgshapiro return true; 618638032Speter} 618738032Speter 618838032Speter 618938032Speter/* 619038032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 619138032Speter*/ 619238032Speter 619338032Speter/* ARGSUSED3 */ 619438032Speterchar * 619538032Speteruser_map_lookup(map, key, av, statp) 619638032Speter MAP *map; 619738032Speter char *key; 619838032Speter char **av; 619938032Speter int *statp; 620038032Speter{ 620138032Speter auto bool fuzzy; 620290792Sgshapiro SM_MBDB_T user; 620338032Speter 620438032Speter if (tTd(38, 20)) 620590792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 620638032Speter map->map_mname, key); 620738032Speter 620890792Sgshapiro *statp = finduser(key, &fuzzy, &user); 620990792Sgshapiro if (*statp != EX_OK) 621038032Speter return NULL; 621138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 621238032Speter return map_rewrite(map, key, strlen(key), NULL); 621338032Speter else 621438032Speter { 621538032Speter char *rwval = NULL; 621638032Speter char buf[30]; 621738032Speter 621838032Speter switch (map->map_valcolno) 621938032Speter { 622038032Speter case 0: 622138032Speter case 1: 622290792Sgshapiro rwval = user.mbdb_name; 622338032Speter break; 622438032Speter 622538032Speter case 2: 622690792Sgshapiro rwval = "x"; /* passwd no longer supported */ 622738032Speter break; 622838032Speter 622938032Speter case 3: 6230168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 623190792Sgshapiro (int) user.mbdb_uid); 623238032Speter rwval = buf; 623338032Speter break; 623438032Speter 623538032Speter case 4: 6236168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 623790792Sgshapiro (int) user.mbdb_gid); 623838032Speter rwval = buf; 623938032Speter break; 624038032Speter 624138032Speter case 5: 624290792Sgshapiro rwval = user.mbdb_fullname; 624338032Speter break; 624438032Speter 624538032Speter case 6: 624690792Sgshapiro rwval = user.mbdb_homedir; 624738032Speter break; 624838032Speter 624938032Speter case 7: 625090792Sgshapiro rwval = user.mbdb_shell; 625138032Speter break; 6252159609Sgshapiro default: 6253159609Sgshapiro syserr("user_map %s: bogus field %d", 6254159609Sgshapiro map->map_mname, map->map_valcolno); 6255159609Sgshapiro return NULL; 625638032Speter } 625738032Speter return map_rewrite(map, rwval, strlen(rwval), av); 625838032Speter } 625938032Speter} 626090792Sgshapiro/* 626138032Speter** Program map type. 626238032Speter** 626338032Speter** This provides access to arbitrary programs. It should be used 626438032Speter** only very sparingly, since there is no way to bound the cost 626538032Speter** of invoking an arbitrary program. 626638032Speter*/ 626738032Speter 626838032Speterchar * 626938032Speterprog_map_lookup(map, name, av, statp) 627038032Speter MAP *map; 627138032Speter char *name; 627238032Speter char **av; 627338032Speter int *statp; 627438032Speter{ 627538032Speter int i; 627664562Sgshapiro int save_errno; 627738032Speter int fd; 627864562Sgshapiro int status; 627938032Speter auto pid_t pid; 628064562Sgshapiro register char *p; 628138032Speter char *rval; 628238032Speter char *argv[MAXPV + 1]; 628338032Speter char buf[MAXLINE]; 628438032Speter 628538032Speter if (tTd(38, 20)) 628690792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 628738032Speter map->map_mname, name, map->map_file); 628838032Speter 628938032Speter i = 0; 629038032Speter argv[i++] = map->map_file; 629138032Speter if (map->map_rebuild != NULL) 629238032Speter { 6293168515Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof(buf)); 629438032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 629538032Speter { 629638032Speter if (i >= MAXPV - 1) 629738032Speter break; 629838032Speter argv[i++] = p; 629938032Speter } 630038032Speter } 630138032Speter argv[i++] = name; 630238032Speter argv[i] = NULL; 630338032Speter if (tTd(38, 21)) 630438032Speter { 630590792Sgshapiro sm_dprintf("prog_open:"); 630638032Speter for (i = 0; argv[i] != NULL; i++) 630790792Sgshapiro sm_dprintf(" %s", argv[i]); 630890792Sgshapiro sm_dprintf("\n"); 630938032Speter } 631090792Sgshapiro (void) sm_blocksignal(SIGCHLD); 631138032Speter pid = prog_open(argv, &fd, CurEnv); 631238032Speter if (pid < 0) 631338032Speter { 631438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 631538032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 631690792Sgshapiro map->map_mname, sm_errstring(errno)); 631738032Speter else if (tTd(38, 9)) 631890792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 631990792Sgshapiro map->map_mname, sm_errstring(errno)); 632038032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 632138032Speter *statp = EX_OSFILE; 632238032Speter return NULL; 632338032Speter } 6324168515Sgshapiro i = read(fd, buf, sizeof(buf) - 1); 632538032Speter if (i < 0) 632638032Speter { 632790792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 632890792Sgshapiro map->map_mname, sm_errstring(errno)); 632938032Speter rval = NULL; 633038032Speter } 633138032Speter else if (i == 0) 633238032Speter { 633338032Speter if (tTd(38, 20)) 633490792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 633590792Sgshapiro map->map_mname); 633638032Speter rval = NULL; 633738032Speter } 633838032Speter else 633938032Speter { 634038032Speter buf[i] = '\0'; 634138032Speter p = strchr(buf, '\n'); 634238032Speter if (p != NULL) 634338032Speter *p = '\0'; 634438032Speter 634538032Speter /* collect the return value */ 634638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 634738032Speter rval = map_rewrite(map, name, strlen(name), NULL); 634838032Speter else 634977349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 635038032Speter 635138032Speter /* now flush any additional output */ 6352168515Sgshapiro while ((i = read(fd, buf, sizeof(buf))) > 0) 635338032Speter continue; 635438032Speter } 635538032Speter 635638032Speter /* wait for the process to terminate */ 635764562Sgshapiro (void) close(fd); 635864562Sgshapiro status = waitfor(pid); 635964562Sgshapiro save_errno = errno; 636090792Sgshapiro (void) sm_releasesignal(SIGCHLD); 636164562Sgshapiro errno = save_errno; 636238032Speter 636364562Sgshapiro if (status == -1) 636438032Speter { 636590792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 636690792Sgshapiro map->map_mname, sm_errstring(errno)); 636738032Speter *statp = EX_SOFTWARE; 636838032Speter rval = NULL; 636938032Speter } 637064562Sgshapiro else if (WIFEXITED(status)) 637138032Speter { 637264562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 637338032Speter rval = NULL; 637438032Speter } 637538032Speter else 637638032Speter { 637738032Speter syserr("prog_map_lookup(%s): child died on signal %d", 637890792Sgshapiro map->map_mname, status); 637938032Speter *statp = EX_UNAVAILABLE; 638038032Speter rval = NULL; 638138032Speter } 638238032Speter return rval; 638338032Speter} 638490792Sgshapiro/* 638538032Speter** Sequenced map type. 638638032Speter** 638738032Speter** Tries each map in order until something matches, much like 638838032Speter** implicit. Stores go to the first map in the list that can 638938032Speter** support storing. 639038032Speter** 639138032Speter** This is slightly unusual in that there are two interfaces. 639238032Speter** The "sequence" interface lets you stack maps arbitrarily. 639338032Speter** The "switch" interface builds a sequence map by looking 639438032Speter** at a system-dependent configuration file such as 639538032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 639638032Speter** 639738032Speter** We don't need an explicit open, since all maps are 639890792Sgshapiro** opened on demand. 639938032Speter*/ 640038032Speter 640138032Speter/* 640238032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 640338032Speter*/ 640438032Speter 640538032Speterbool 640638032Speterseq_map_parse(map, ap) 640738032Speter MAP *map; 640838032Speter char *ap; 640938032Speter{ 641038032Speter int maxmap; 641138032Speter 641238032Speter if (tTd(38, 2)) 641390792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 641438032Speter maxmap = 0; 641538032Speter while (*ap != '\0') 641638032Speter { 641738032Speter register char *p; 641838032Speter STAB *s; 641938032Speter 642038032Speter /* find beginning of map name */ 642138032Speter while (isascii(*ap) && isspace(*ap)) 642238032Speter ap++; 642364562Sgshapiro for (p = ap; 642464562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 642564562Sgshapiro p++) 642638032Speter continue; 642738032Speter if (*p != '\0') 642838032Speter *p++ = '\0'; 642938032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 643038032Speter p++; 643138032Speter if (*ap == '\0') 643238032Speter { 643338032Speter ap = p; 643438032Speter continue; 643538032Speter } 643638032Speter s = stab(ap, ST_MAP, ST_FIND); 643738032Speter if (s == NULL) 643838032Speter { 643938032Speter syserr("Sequence map %s: unknown member map %s", 644038032Speter map->map_mname, ap); 644138032Speter } 644290792Sgshapiro else if (maxmap >= MAXMAPSTACK) 644338032Speter { 644438032Speter syserr("Sequence map %s: too many member maps (%d max)", 644538032Speter map->map_mname, MAXMAPSTACK); 644638032Speter maxmap++; 644738032Speter } 644838032Speter else if (maxmap < MAXMAPSTACK) 644938032Speter { 645038032Speter map->map_stack[maxmap++] = &s->s_map; 645138032Speter } 645238032Speter ap = p; 645338032Speter } 645490792Sgshapiro return true; 645538032Speter} 645638032Speter 645738032Speter/* 645838032Speter** SWITCH_MAP_OPEN -- open a switched map 645938032Speter** 646038032Speter** This looks at the system-dependent configuration and builds 646138032Speter** a sequence map that does the same thing. 646238032Speter** 646338032Speter** Every system must define a switch_map_find routine in conf.c 646438032Speter** that will return the list of service types associated with a 646538032Speter** given service class. 646638032Speter*/ 646738032Speter 646838032Speterbool 646938032Speterswitch_map_open(map, mode) 647038032Speter MAP *map; 647138032Speter int mode; 647238032Speter{ 647338032Speter int mapno; 647438032Speter int nmaps; 647538032Speter char *maptype[MAXMAPSTACK]; 647638032Speter 647738032Speter if (tTd(38, 2)) 647890792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 647938032Speter map->map_mname, map->map_file, mode); 648038032Speter 648138032Speter mode &= O_ACCMODE; 648238032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 648338032Speter if (tTd(38, 19)) 648438032Speter { 648590792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 648638032Speter for (mapno = 0; mapno < nmaps; mapno++) 648790792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 648838032Speter } 648938032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 649090792Sgshapiro return false; 649138032Speter 649238032Speter for (mapno = 0; mapno < nmaps; mapno++) 649338032Speter { 649438032Speter register STAB *s; 649538032Speter char nbuf[MAXNAME + 1]; 649638032Speter 649738032Speter if (maptype[mapno] == NULL) 649838032Speter continue; 6499168515Sgshapiro (void) sm_strlcpyn(nbuf, sizeof(nbuf), 3, 650090792Sgshapiro map->map_mname, ".", maptype[mapno]); 650138032Speter s = stab(nbuf, ST_MAP, ST_FIND); 650238032Speter if (s == NULL) 650338032Speter { 650438032Speter syserr("Switch map %s: unknown member map %s", 650538032Speter map->map_mname, nbuf); 650638032Speter } 650738032Speter else 650838032Speter { 650938032Speter map->map_stack[mapno] = &s->s_map; 651038032Speter if (tTd(38, 4)) 651190792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 651290792Sgshapiro mapno, 651390792Sgshapiro s->s_map.map_class->map_cname, 651490792Sgshapiro nbuf); 651538032Speter } 651638032Speter } 651790792Sgshapiro return true; 651838032Speter} 651938032Speter 652090792Sgshapiro#if 0 652138032Speter/* 652238032Speter** SEQ_MAP_CLOSE -- close all underlying maps 652338032Speter*/ 652438032Speter 652538032Spetervoid 652638032Speterseq_map_close(map) 652738032Speter MAP *map; 652838032Speter{ 652938032Speter int mapno; 653038032Speter 653138032Speter if (tTd(38, 9)) 653290792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 653338032Speter 653438032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 653538032Speter { 653638032Speter MAP *mm = map->map_stack[mapno]; 653738032Speter 653838032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 653938032Speter continue; 654077349Sgshapiro mm->map_mflags |= MF_CLOSING; 654138032Speter mm->map_class->map_close(mm); 654277349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 654338032Speter } 654438032Speter} 654590792Sgshapiro#endif /* 0 */ 654638032Speter 654738032Speter/* 654838032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 654938032Speter*/ 655038032Speter 655138032Speterchar * 655238032Speterseq_map_lookup(map, key, args, pstat) 655338032Speter MAP *map; 655438032Speter char *key; 655538032Speter char **args; 655638032Speter int *pstat; 655738032Speter{ 655838032Speter int mapno; 655938032Speter int mapbit = 0x01; 656090792Sgshapiro bool tempfail = false; 656138032Speter 656238032Speter if (tTd(38, 20)) 656390792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 656438032Speter 656538032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 656638032Speter { 656738032Speter MAP *mm = map->map_stack[mapno]; 656838032Speter char *rv; 656938032Speter 657038032Speter if (mm == NULL) 657138032Speter continue; 657264562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 657364562Sgshapiro !openmap(mm)) 657438032Speter { 657538032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 657638032Speter { 657738032Speter *pstat = EX_UNAVAILABLE; 657838032Speter return NULL; 657938032Speter } 658038032Speter continue; 658138032Speter } 658238032Speter *pstat = EX_OK; 658338032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 658438032Speter if (rv != NULL) 658538032Speter return rv; 658638032Speter if (*pstat == EX_TEMPFAIL) 658738032Speter { 658838032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 658938032Speter return NULL; 659090792Sgshapiro tempfail = true; 659138032Speter } 659238032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 659338032Speter break; 659438032Speter } 659538032Speter if (tempfail) 659638032Speter *pstat = EX_TEMPFAIL; 659738032Speter else if (*pstat == EX_OK) 659838032Speter *pstat = EX_NOTFOUND; 659938032Speter return NULL; 660038032Speter} 660138032Speter 660238032Speter/* 660338032Speter** SEQ_MAP_STORE -- sequenced map store 660438032Speter*/ 660538032Speter 660638032Spetervoid 660738032Speterseq_map_store(map, key, val) 660838032Speter MAP *map; 660938032Speter char *key; 661038032Speter char *val; 661138032Speter{ 661238032Speter int mapno; 661338032Speter 661438032Speter if (tTd(38, 12)) 661590792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 661638032Speter map->map_mname, key, val); 661738032Speter 661838032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 661938032Speter { 662038032Speter MAP *mm = map->map_stack[mapno]; 662138032Speter 662238032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 662338032Speter continue; 662438032Speter 662538032Speter mm->map_class->map_store(mm, key, val); 662638032Speter return; 662738032Speter } 662838032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 662938032Speter map->map_mname, key, val); 663038032Speter} 663190792Sgshapiro/* 663238032Speter** NULL stubs 663338032Speter*/ 663438032Speter 663538032Speter/* ARGSUSED */ 663638032Speterbool 663738032Speternull_map_open(map, mode) 663838032Speter MAP *map; 663938032Speter int mode; 664038032Speter{ 664190792Sgshapiro return true; 664238032Speter} 664338032Speter 664438032Speter/* ARGSUSED */ 664538032Spetervoid 664638032Speternull_map_close(map) 664738032Speter MAP *map; 664838032Speter{ 664938032Speter return; 665038032Speter} 665138032Speter 665238032Speterchar * 665338032Speternull_map_lookup(map, key, args, pstat) 665438032Speter MAP *map; 665538032Speter char *key; 665638032Speter char **args; 665738032Speter int *pstat; 665838032Speter{ 665938032Speter *pstat = EX_NOTFOUND; 666038032Speter return NULL; 666138032Speter} 666238032Speter 666338032Speter/* ARGSUSED */ 666438032Spetervoid 666538032Speternull_map_store(map, key, val) 666638032Speter MAP *map; 666738032Speter char *key; 666838032Speter char *val; 666938032Speter{ 667038032Speter return; 667138032Speter} 667238032Speter 667338032Speter/* 667438032Speter** BOGUS stubs 667538032Speter*/ 667638032Speter 667738032Speterchar * 667838032Speterbogus_map_lookup(map, key, args, pstat) 667938032Speter MAP *map; 668038032Speter char *key; 668138032Speter char **args; 668238032Speter int *pstat; 668338032Speter{ 668438032Speter *pstat = EX_TEMPFAIL; 668538032Speter return NULL; 668638032Speter} 668738032Speter 668838032SpeterMAPCLASS BogusMapClass = 668938032Speter{ 669090792Sgshapiro "bogus-map", NULL, 0, 669190792Sgshapiro NULL, bogus_map_lookup, null_map_store, 669290792Sgshapiro null_map_open, null_map_close, 669338032Speter}; 669490792Sgshapiro/* 669564562Sgshapiro** MACRO modules 669664562Sgshapiro*/ 669764562Sgshapiro 669864562Sgshapirochar * 669964562Sgshapiromacro_map_lookup(map, name, av, statp) 670064562Sgshapiro MAP *map; 670164562Sgshapiro char *name; 670264562Sgshapiro char **av; 670364562Sgshapiro int *statp; 670464562Sgshapiro{ 670564562Sgshapiro int mid; 670664562Sgshapiro 670764562Sgshapiro if (tTd(38, 20)) 670890792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 670964562Sgshapiro name == NULL ? "NULL" : name); 671064562Sgshapiro 671164562Sgshapiro if (name == NULL || 671264562Sgshapiro *name == '\0' || 671390792Sgshapiro (mid = macid(name)) == 0) 671464562Sgshapiro { 671564562Sgshapiro *statp = EX_CONFIG; 671664562Sgshapiro return NULL; 671764562Sgshapiro } 671864562Sgshapiro 671964562Sgshapiro if (av[1] == NULL) 672090792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 672164562Sgshapiro else 672290792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 672364562Sgshapiro 672464562Sgshapiro *statp = EX_OK; 672564562Sgshapiro return ""; 672664562Sgshapiro} 672790792Sgshapiro/* 672838032Speter** REGEX modules 672938032Speter*/ 673038032Speter 673190792Sgshapiro#if MAP_REGEX 673238032Speter 673338032Speter# include <regex.h> 673438032Speter 673538032Speter# define DEFAULT_DELIM CONDELSE 673638032Speter# define END_OF_FIELDS -1 673738032Speter# define ERRBUF_SIZE 80 673838032Speter# define MAX_MATCH 32 673938032Speter 674064562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 674138032Speter 674238032Speterstruct regex_map 674338032Speter{ 674471345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 674538032Speter int *regex_subfields; /* move to type MAP */ 674664562Sgshapiro char *regex_delim; /* move to type MAP */ 674738032Speter}; 674838032Speter 6749141858Sgshapirostatic int parse_fields __P((char *, int *, int, int)); 6750141858Sgshapirostatic char *regex_map_rewrite __P((MAP *, const char*, size_t, char **)); 6751141858Sgshapiro 675238032Speterstatic int 675338032Speterparse_fields(s, ibuf, blen, nr_substrings) 675438032Speter char *s; 675538032Speter int *ibuf; /* array */ 675638032Speter int blen; /* number of elements in ibuf */ 675738032Speter int nr_substrings; /* number of substrings in the pattern */ 675838032Speter{ 675938032Speter register char *cp; 676038032Speter int i = 0; 676190792Sgshapiro bool lastone = false; 676238032Speter 676338032Speter blen--; /* for terminating END_OF_FIELDS */ 676438032Speter cp = s; 676538032Speter do 676638032Speter { 676738032Speter for (;; cp++) 676838032Speter { 676938032Speter if (*cp == ',') 677038032Speter { 677138032Speter *cp = '\0'; 677238032Speter break; 677338032Speter } 677438032Speter if (*cp == '\0') 677538032Speter { 677690792Sgshapiro lastone = true; 677738032Speter break; 677838032Speter } 677938032Speter } 678038032Speter if (i < blen) 678138032Speter { 678238032Speter int val = atoi(s); 678338032Speter 678438032Speter if (val < 0 || val >= nr_substrings) 678538032Speter { 678638032Speter syserr("field (%d) out of range, only %d substrings in pattern", 678738032Speter val, nr_substrings); 678838032Speter return -1; 678938032Speter } 679038032Speter ibuf[i++] = val; 679138032Speter } 679238032Speter else 679338032Speter { 679490792Sgshapiro syserr("too many fields, %d max", blen); 679538032Speter return -1; 679638032Speter } 679738032Speter s = ++cp; 679838032Speter } while (!lastone); 679938032Speter ibuf[i] = END_OF_FIELDS; 680038032Speter return i; 680138032Speter} 680238032Speter 680338032Speterbool 680438032Speterregex_map_init(map, ap) 680538032Speter MAP *map; 680638032Speter char *ap; 680738032Speter{ 680838032Speter int regerr; 680938032Speter struct regex_map *map_p; 681038032Speter register char *p; 681138032Speter char *sub_param = NULL; 681238032Speter int pflags; 681390792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 681438032Speter 681538032Speter if (tTd(38, 2)) 681690792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 681764562Sgshapiro map->map_mname, ap); 681838032Speter 681938032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 682038032Speter p = ap; 6821168515Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof(*map_p)); 682271345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 682338032Speter 682438032Speter for (;;) 682564562Sgshapiro { 682638032Speter while (isascii(*p) && isspace(*p)) 682738032Speter p++; 682838032Speter if (*p != '-') 682938032Speter break; 683038032Speter switch (*++p) 683138032Speter { 683238032Speter case 'n': /* not */ 683338032Speter map->map_mflags |= MF_REGEX_NOT; 683438032Speter break; 683538032Speter 683638032Speter case 'f': /* case sensitive */ 683738032Speter map->map_mflags |= MF_NOFOLDCASE; 683838032Speter pflags &= ~REG_ICASE; 683938032Speter break; 684038032Speter 684138032Speter case 'b': /* basic regular expressions */ 684238032Speter pflags &= ~REG_EXTENDED; 684338032Speter break; 684438032Speter 684538032Speter case 's': /* substring match () syntax */ 684638032Speter sub_param = ++p; 684738032Speter pflags &= ~REG_NOSUB; 684838032Speter break; 684938032Speter 685038032Speter case 'd': /* delimiter */ 685164562Sgshapiro map_p->regex_delim = ++p; 685238032Speter break; 685338032Speter 685438032Speter case 'a': /* map append */ 685538032Speter map->map_app = ++p; 685638032Speter break; 685738032Speter 685838032Speter case 'm': /* matchonly */ 685938032Speter map->map_mflags |= MF_MATCHONLY; 686038032Speter break; 686138032Speter 6862120256Sgshapiro case 'q': 6863120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 6864120256Sgshapiro break; 6865120256Sgshapiro 686664562Sgshapiro case 'S': 686764562Sgshapiro map->map_spacesub = *++p; 686864562Sgshapiro break; 686964562Sgshapiro 687064562Sgshapiro case 'D': 687164562Sgshapiro map->map_mflags |= MF_DEFER; 687264562Sgshapiro break; 687364562Sgshapiro 687438032Speter } 687564562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 687664562Sgshapiro p++; 687764562Sgshapiro if (*p != '\0') 687864562Sgshapiro *p++ = '\0'; 687938032Speter } 688038032Speter if (tTd(38, 3)) 688190792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 688238032Speter 688371345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 688438032Speter { 688538032Speter /* Errorhandling */ 688638032Speter char errbuf[ERRBUF_SIZE]; 688738032Speter 688871345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 6889168515Sgshapiro errbuf, sizeof(errbuf)); 689090792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 689190792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 689290792Sgshapiro sm_free(map_p); /* XXX */ 689390792Sgshapiro return false; 689438032Speter } 689538032Speter 689638032Speter if (map->map_app != NULL) 689738032Speter map->map_app = newstr(map->map_app); 689864562Sgshapiro if (map_p->regex_delim != NULL) 689964562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 690038032Speter else 690164562Sgshapiro map_p->regex_delim = defdstr; 690238032Speter 690338032Speter if (!bitset(REG_NOSUB, pflags)) 690438032Speter { 690538032Speter /* substring matching */ 690638032Speter int substrings; 690764562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 690838032Speter 690971345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 691038032Speter 691138032Speter if (tTd(38, 3)) 691290792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 691364562Sgshapiro substrings); 691438032Speter 691538032Speter if (substrings >= MAX_MATCH) 691638032Speter { 691790792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 691890792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 691990792Sgshapiro sm_free(map_p); /* XXX */ 692090792Sgshapiro return false; 692138032Speter } 692238032Speter if (sub_param != NULL && sub_param[0] != '\0') 692338032Speter { 692438032Speter /* optional parameter -sfields */ 692538032Speter if (parse_fields(sub_param, fields, 692638032Speter MAX_MATCH + 1, substrings) == -1) 692790792Sgshapiro return false; 692838032Speter } 692938032Speter else 693038032Speter { 693138032Speter int i; 693238032Speter 693390792Sgshapiro /* set default fields */ 693438032Speter for (i = 0; i < substrings; i++) 693538032Speter fields[i] = i; 693638032Speter fields[i] = END_OF_FIELDS; 693738032Speter } 693838032Speter map_p->regex_subfields = fields; 693938032Speter if (tTd(38, 3)) 694038032Speter { 694138032Speter int *ip; 694238032Speter 694390792Sgshapiro sm_dprintf("regex_map_init: subfields"); 694438032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 694590792Sgshapiro sm_dprintf(" %d", *ip); 694690792Sgshapiro sm_dprintf("\n"); 694738032Speter } 694838032Speter } 694990792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 695090792Sgshapiro return true; 695138032Speter} 695238032Speter 695338032Speterstatic char * 695438032Speterregex_map_rewrite(map, s, slen, av) 695538032Speter MAP *map; 695638032Speter const char *s; 695738032Speter size_t slen; 695838032Speter char **av; 695938032Speter{ 696038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 696138032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 696238032Speter else 696377349Sgshapiro return map_rewrite(map, s, slen, av); 696438032Speter} 696538032Speter 696638032Speterchar * 696738032Speterregex_map_lookup(map, name, av, statp) 696838032Speter MAP *map; 696938032Speter char *name; 697038032Speter char **av; 697138032Speter int *statp; 697238032Speter{ 697338032Speter int reg_res; 697438032Speter struct regex_map *map_p; 697538032Speter regmatch_t pmatch[MAX_MATCH]; 697638032Speter 697738032Speter if (tTd(38, 20)) 697838032Speter { 697938032Speter char **cpp; 698038032Speter 698190792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 698264562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 698390792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 698438032Speter } 698538032Speter 698638032Speter map_p = (struct regex_map *)(map->map_db1); 698771345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 698864562Sgshapiro name, MAX_MATCH, pmatch, 0); 698938032Speter 699038032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 699138032Speter { 699238032Speter /* option -n */ 699338032Speter if (reg_res == REG_NOMATCH) 699490792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 699538032Speter else 699638032Speter return NULL; 699738032Speter } 699838032Speter if (reg_res == REG_NOMATCH) 699938032Speter return NULL; 700038032Speter 700138032Speter if (map_p->regex_subfields != NULL) 700238032Speter { 700338032Speter /* option -s */ 700438032Speter static char retbuf[MAXNAME]; 700538032Speter int fields[MAX_MATCH + 1]; 700690792Sgshapiro bool first = true; 700738032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 700890792Sgshapiro bool quotemode = false, bslashmode = false; 700938032Speter register char *dp, *sp; 701038032Speter char *endp, *ldp; 701138032Speter int *ip; 701238032Speter 701338032Speter dp = retbuf; 701438032Speter ldp = retbuf + sizeof(retbuf) - 1; 701538032Speter 701638032Speter if (av[1] != NULL) 701738032Speter { 701838032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 701971345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 702038032Speter { 702138032Speter *statp = EX_CONFIG; 702238032Speter return NULL; 702338032Speter } 702438032Speter ip = fields; 702538032Speter } 702638032Speter else 702738032Speter ip = map_p->regex_subfields; 702838032Speter 702938032Speter for ( ; *ip != END_OF_FIELDS; ip++) 703038032Speter { 703138032Speter if (!first) 703238032Speter { 703364562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 703438032Speter { 703538032Speter if (dp < ldp) 703638032Speter *dp++ = *sp; 703738032Speter } 703838032Speter } 703938032Speter else 704090792Sgshapiro first = false; 704138032Speter 704271345Sgshapiro if (*ip >= MAX_MATCH || 704371345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 704438032Speter continue; 704538032Speter 704638032Speter sp = name + pmatch[*ip].rm_so; 704738032Speter endp = name + pmatch[*ip].rm_eo; 704838032Speter for (; endp > sp; sp++) 704938032Speter { 705038032Speter if (dp < ldp) 705138032Speter { 705264562Sgshapiro if (bslashmode) 705364562Sgshapiro { 705438032Speter *dp++ = *sp; 705590792Sgshapiro bslashmode = false; 705638032Speter } 705764562Sgshapiro else if (quotemode && *sp != '"' && 705838032Speter *sp != '\\') 705938032Speter { 706038032Speter *dp++ = *sp; 706138032Speter } 706290792Sgshapiro else switch (*dp++ = *sp) 706338032Speter { 706490792Sgshapiro case '\\': 706590792Sgshapiro bslashmode = true; 706638032Speter break; 706738032Speter 706890792Sgshapiro case '(': 706938032Speter cmntcnt++; 707038032Speter break; 707138032Speter 707290792Sgshapiro case ')': 707338032Speter cmntcnt--; 707438032Speter break; 707538032Speter 707690792Sgshapiro case '<': 707738032Speter anglecnt++; 707838032Speter break; 707938032Speter 708090792Sgshapiro case '>': 708138032Speter anglecnt--; 708238032Speter break; 708338032Speter 708490792Sgshapiro case ' ': 708538032Speter spacecnt++; 708638032Speter break; 708738032Speter 708890792Sgshapiro case '"': 708938032Speter quotemode = !quotemode; 709038032Speter break; 709138032Speter } 709238032Speter } 709338032Speter } 709438032Speter } 709538032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 709638032Speter bslashmode || spacecnt != 0) 709738032Speter { 709864562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 709964562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 710064562Sgshapiro map->map_mname, name); 710138032Speter return NULL; 710238032Speter } 710338032Speter 710438032Speter *dp = '\0'; 710538032Speter 710638032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 710738032Speter } 710838032Speter return regex_map_rewrite(map, "", (size_t)0, av); 710938032Speter} 711038032Speter#endif /* MAP_REGEX */ 711190792Sgshapiro/* 711264562Sgshapiro** NSD modules 711364562Sgshapiro*/ 711490792Sgshapiro#if MAP_NSD 711564562Sgshapiro 711664562Sgshapiro# include <ndbm.h> 711764562Sgshapiro# define _DATUM_DEFINED 711864562Sgshapiro# include <ns_api.h> 711964562Sgshapiro 712064562Sgshapirotypedef struct ns_map_list 712164562Sgshapiro{ 712290792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 712390792Sgshapiro char *mapname; 712490792Sgshapiro struct ns_map_list *next; 712564562Sgshapiro} ns_map_list_t; 712664562Sgshapiro 712764562Sgshapirostatic ns_map_t * 712864562Sgshapirons_map_t_find(mapname) 712964562Sgshapiro char *mapname; 713064562Sgshapiro{ 713164562Sgshapiro static ns_map_list_t *ns_maps = NULL; 713264562Sgshapiro ns_map_list_t *ns_map; 713364562Sgshapiro 713464562Sgshapiro /* walk the list of maps looking for the correctly named map */ 713564562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 713664562Sgshapiro { 713764562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 713864562Sgshapiro break; 713964562Sgshapiro } 714064562Sgshapiro 714164562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 714264562Sgshapiro if (ns_map == NULL) 714364562Sgshapiro { 7144168515Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof(*ns_map)); 714564562Sgshapiro ns_map->mapname = newstr(mapname); 7146168515Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof(*ns_map->map)); 7147168515Sgshapiro memset(ns_map->map, '\0', sizeof(*ns_map->map)); 714864562Sgshapiro ns_map->next = ns_maps; 714964562Sgshapiro ns_maps = ns_map; 715064562Sgshapiro } 715164562Sgshapiro return ns_map->map; 715264562Sgshapiro} 715364562Sgshapiro 715464562Sgshapirochar * 715564562Sgshapironsd_map_lookup(map, name, av, statp) 715664562Sgshapiro MAP *map; 715764562Sgshapiro char *name; 715864562Sgshapiro char **av; 715964562Sgshapiro int *statp; 716064562Sgshapiro{ 716171345Sgshapiro int buflen, r; 716264562Sgshapiro char *p; 716364562Sgshapiro ns_map_t *ns_map; 716464562Sgshapiro char keybuf[MAXNAME + 1]; 716564562Sgshapiro char buf[MAXLINE]; 716664562Sgshapiro 716764562Sgshapiro if (tTd(38, 20)) 716890792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 716964562Sgshapiro 717064562Sgshapiro buflen = strlen(name); 7171168515Sgshapiro if (buflen > sizeof(keybuf) - 1) 7172168515Sgshapiro buflen = sizeof(keybuf) - 1; /* XXX simply cut off? */ 717364562Sgshapiro memmove(keybuf, name, buflen); 717464562Sgshapiro keybuf[buflen] = '\0'; 717564562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 717664562Sgshapiro makelower(keybuf); 717764562Sgshapiro 717864562Sgshapiro ns_map = ns_map_t_find(map->map_file); 717964562Sgshapiro if (ns_map == NULL) 718064562Sgshapiro { 718164562Sgshapiro if (tTd(38, 20)) 718290792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 718371345Sgshapiro *statp = EX_UNAVAILABLE; 718464562Sgshapiro return NULL; 718564562Sgshapiro } 718698121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 7187168515Sgshapiro buf, sizeof(buf)); 718871345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 718971345Sgshapiro { 719071345Sgshapiro *statp = EX_TEMPFAIL; 719164562Sgshapiro return NULL; 719271345Sgshapiro } 719377349Sgshapiro if (r == NS_BADREQ 719477349Sgshapiro# ifdef NS_NOPERM 719577349Sgshapiro || r == NS_NOPERM 719677349Sgshapiro# endif /* NS_NOPERM */ 719777349Sgshapiro ) 719871345Sgshapiro { 719971345Sgshapiro *statp = EX_CONFIG; 720071345Sgshapiro return NULL; 720171345Sgshapiro } 720271345Sgshapiro if (r != NS_SUCCESS) 720371345Sgshapiro { 720471345Sgshapiro *statp = EX_NOTFOUND; 720571345Sgshapiro return NULL; 720671345Sgshapiro } 720764562Sgshapiro 720871345Sgshapiro *statp = EX_OK; 720971345Sgshapiro 721064562Sgshapiro /* Null out trailing \n */ 721164562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 721264562Sgshapiro *p = '\0'; 721364562Sgshapiro 721464562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 721564562Sgshapiro} 721664562Sgshapiro#endif /* MAP_NSD */ 721764562Sgshapiro 721864562Sgshapirochar * 721964562Sgshapiroarith_map_lookup(map, name, av, statp) 722064562Sgshapiro MAP *map; 722164562Sgshapiro char *name; 722264562Sgshapiro char **av; 722364562Sgshapiro int *statp; 722464562Sgshapiro{ 722564562Sgshapiro long r; 722664562Sgshapiro long v[2]; 722790792Sgshapiro bool res = false; 722864562Sgshapiro bool boolres; 722964562Sgshapiro static char result[16]; 723064562Sgshapiro char **cpp; 723164562Sgshapiro 723264562Sgshapiro if (tTd(38, 2)) 723364562Sgshapiro { 723490792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 723564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 723690792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 723764562Sgshapiro } 723864562Sgshapiro r = 0; 723990792Sgshapiro boolres = false; 724064562Sgshapiro cpp = av; 724164562Sgshapiro *statp = EX_OK; 724264562Sgshapiro 724364562Sgshapiro /* 724464562Sgshapiro ** read arguments for arith map 724564562Sgshapiro ** - no check is made whether they are really numbers 724664562Sgshapiro ** - just ignores args after the second 724764562Sgshapiro */ 724890792Sgshapiro 724964562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 725064562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 725164562Sgshapiro 725264562Sgshapiro /* operator and (at least) two operands given? */ 725364562Sgshapiro if (name != NULL && r == 2) 725464562Sgshapiro { 725590792Sgshapiro switch (*name) 725664562Sgshapiro { 725764562Sgshapiro case '|': 725864562Sgshapiro r = v[0] | v[1]; 725964562Sgshapiro break; 726064562Sgshapiro 726164562Sgshapiro case '&': 726264562Sgshapiro r = v[0] & v[1]; 726364562Sgshapiro break; 726464562Sgshapiro 726564562Sgshapiro case '%': 726664562Sgshapiro if (v[1] == 0) 726764562Sgshapiro return NULL; 726864562Sgshapiro r = v[0] % v[1]; 726964562Sgshapiro break; 727064562Sgshapiro case '+': 727164562Sgshapiro r = v[0] + v[1]; 727264562Sgshapiro break; 727364562Sgshapiro 727464562Sgshapiro case '-': 727564562Sgshapiro r = v[0] - v[1]; 727664562Sgshapiro break; 727764562Sgshapiro 727864562Sgshapiro case '*': 727964562Sgshapiro r = v[0] * v[1]; 728064562Sgshapiro break; 728164562Sgshapiro 728264562Sgshapiro case '/': 728364562Sgshapiro if (v[1] == 0) 728464562Sgshapiro return NULL; 728564562Sgshapiro r = v[0] / v[1]; 728664562Sgshapiro break; 728764562Sgshapiro 728864562Sgshapiro case 'l': 728964562Sgshapiro res = v[0] < v[1]; 729090792Sgshapiro boolres = true; 729164562Sgshapiro break; 729264562Sgshapiro 729364562Sgshapiro case '=': 729464562Sgshapiro res = v[0] == v[1]; 729590792Sgshapiro boolres = true; 729664562Sgshapiro break; 729764562Sgshapiro 7298168515Sgshapiro case 'r': 7299168515Sgshapiro r = v[1] - v[0] + 1; 7300168515Sgshapiro if (r <= 0) 7301168515Sgshapiro return NULL; 7302168515Sgshapiro r = get_random() % r + v[0]; 7303168515Sgshapiro break; 7304168515Sgshapiro 730564562Sgshapiro default: 730664562Sgshapiro /* XXX */ 730764562Sgshapiro *statp = EX_CONFIG; 730864562Sgshapiro if (LogLevel > 10) 730964562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 731064562Sgshapiro "arith_map: unknown operator %c", 731164562Sgshapiro isprint(*name) ? *name : '?'); 731264562Sgshapiro return NULL; 731364562Sgshapiro } 731464562Sgshapiro if (boolres) 7315168515Sgshapiro (void) sm_snprintf(result, sizeof(result), 731690792Sgshapiro res ? "TRUE" : "FALSE"); 731764562Sgshapiro else 7318168515Sgshapiro (void) sm_snprintf(result, sizeof(result), "%ld", r); 731964562Sgshapiro return result; 732064562Sgshapiro } 732164562Sgshapiro *statp = EX_CONFIG; 732264562Sgshapiro return NULL; 732364562Sgshapiro} 7324132943Sgshapiro 7325132943Sgshapiro#if SOCKETMAP 7326132943Sgshapiro 7327132943Sgshapiro# if NETINET || NETINET6 7328132943Sgshapiro# include <arpa/inet.h> 7329132943Sgshapiro# endif /* NETINET || NETINET6 */ 7330132943Sgshapiro 7331132943Sgshapiro# define socket_map_next map_stack[0] 7332132943Sgshapiro 7333132943Sgshapiro/* 7334132943Sgshapiro** SOCKET_MAP_OPEN -- open socket table 7335132943Sgshapiro*/ 7336132943Sgshapiro 7337132943Sgshapirobool 7338132943Sgshapirosocket_map_open(map, mode) 7339132943Sgshapiro MAP *map; 7340132943Sgshapiro int mode; 7341132943Sgshapiro{ 7342132943Sgshapiro STAB *s; 7343132943Sgshapiro int sock = 0; 7344132943Sgshapiro SOCKADDR_LEN_T addrlen = 0; 7345132943Sgshapiro int addrno = 0; 7346132943Sgshapiro int save_errno; 7347132943Sgshapiro char *p; 7348132943Sgshapiro char *colon; 7349132943Sgshapiro char *at; 7350132943Sgshapiro struct hostent *hp = NULL; 7351132943Sgshapiro SOCKADDR addr; 7352132943Sgshapiro 7353132943Sgshapiro if (tTd(38, 2)) 7354132943Sgshapiro sm_dprintf("socket_map_open(%s, %s, %d)\n", 7355132943Sgshapiro map->map_mname, map->map_file, mode); 7356132943Sgshapiro 7357132943Sgshapiro mode &= O_ACCMODE; 7358132943Sgshapiro 7359132943Sgshapiro /* sendmail doesn't have the ability to write to SOCKET (yet) */ 7360132943Sgshapiro if (mode != O_RDONLY) 7361132943Sgshapiro { 7362132943Sgshapiro /* issue a pseudo-error message */ 7363132943Sgshapiro errno = SM_EMAPCANTWRITE; 7364132943Sgshapiro return false; 7365132943Sgshapiro } 7366132943Sgshapiro 7367132943Sgshapiro if (*map->map_file == '\0') 7368132943Sgshapiro { 7369132943Sgshapiro syserr("socket map \"%s\": empty or missing socket information", 7370132943Sgshapiro map->map_mname); 7371132943Sgshapiro return false; 7372132943Sgshapiro } 7373132943Sgshapiro 7374132943Sgshapiro s = socket_map_findconn(map->map_file); 7375132943Sgshapiro if (s->s_socketmap != NULL) 7376132943Sgshapiro { 7377132943Sgshapiro /* Copy open connection */ 7378132943Sgshapiro map->map_db1 = s->s_socketmap->map_db1; 7379132943Sgshapiro 7380132943Sgshapiro /* Add this map as head of linked list */ 7381132943Sgshapiro map->socket_map_next = s->s_socketmap; 7382132943Sgshapiro s->s_socketmap = map; 7383132943Sgshapiro 7384132943Sgshapiro if (tTd(38, 2)) 7385132943Sgshapiro sm_dprintf("using cached connection\n"); 7386132943Sgshapiro return true; 7387132943Sgshapiro } 7388132943Sgshapiro 7389132943Sgshapiro if (tTd(38, 2)) 7390132943Sgshapiro sm_dprintf("opening new connection\n"); 7391132943Sgshapiro 7392132943Sgshapiro /* following code is ripped from milter.c */ 7393132943Sgshapiro /* XXX It should be put in a library... */ 7394132943Sgshapiro 7395132943Sgshapiro /* protocol:filename or protocol:port@host */ 7396168515Sgshapiro memset(&addr, '\0', sizeof(addr)); 7397132943Sgshapiro p = map->map_file; 7398132943Sgshapiro colon = strchr(p, ':'); 7399132943Sgshapiro if (colon != NULL) 7400132943Sgshapiro { 7401132943Sgshapiro *colon = '\0'; 7402132943Sgshapiro 7403132943Sgshapiro if (*p == '\0') 7404132943Sgshapiro { 7405132943Sgshapiro# if NETUNIX 7406132943Sgshapiro /* default to AF_UNIX */ 7407132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7408132943Sgshapiro# else /* NETUNIX */ 7409132943Sgshapiro# if NETINET 7410132943Sgshapiro /* default to AF_INET */ 7411132943Sgshapiro addr.sa.sa_family = AF_INET; 7412132943Sgshapiro# else /* NETINET */ 7413132943Sgshapiro# if NETINET6 7414132943Sgshapiro /* default to AF_INET6 */ 7415132943Sgshapiro addr.sa.sa_family = AF_INET6; 7416132943Sgshapiro# else /* NETINET6 */ 7417132943Sgshapiro /* no protocols available */ 7418132943Sgshapiro syserr("socket map \"%s\": no valid socket protocols available", 7419132943Sgshapiro map->map_mname); 7420132943Sgshapiro return false; 7421132943Sgshapiro# endif /* NETINET6 */ 7422132943Sgshapiro# endif /* NETINET */ 7423132943Sgshapiro# endif /* NETUNIX */ 7424132943Sgshapiro } 7425132943Sgshapiro# if NETUNIX 7426132943Sgshapiro else if (sm_strcasecmp(p, "unix") == 0 || 7427132943Sgshapiro sm_strcasecmp(p, "local") == 0) 7428132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7429132943Sgshapiro# endif /* NETUNIX */ 7430132943Sgshapiro# if NETINET 7431132943Sgshapiro else if (sm_strcasecmp(p, "inet") == 0) 7432132943Sgshapiro addr.sa.sa_family = AF_INET; 7433132943Sgshapiro# endif /* NETINET */ 7434132943Sgshapiro# if NETINET6 7435132943Sgshapiro else if (sm_strcasecmp(p, "inet6") == 0) 7436132943Sgshapiro addr.sa.sa_family = AF_INET6; 7437132943Sgshapiro# endif /* NETINET6 */ 7438132943Sgshapiro else 7439132943Sgshapiro { 7440132943Sgshapiro# ifdef EPROTONOSUPPORT 7441132943Sgshapiro errno = EPROTONOSUPPORT; 7442132943Sgshapiro# else /* EPROTONOSUPPORT */ 7443132943Sgshapiro errno = EINVAL; 7444132943Sgshapiro# endif /* EPROTONOSUPPORT */ 7445132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7446132943Sgshapiro map->map_mname, p); 7447132943Sgshapiro return false; 7448132943Sgshapiro } 7449132943Sgshapiro *colon++ = ':'; 7450132943Sgshapiro } 7451132943Sgshapiro else 7452132943Sgshapiro { 7453132943Sgshapiro colon = p; 7454132943Sgshapiro#if NETUNIX 7455132943Sgshapiro /* default to AF_UNIX */ 7456132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7457132943Sgshapiro#else /* NETUNIX */ 7458132943Sgshapiro# if NETINET 7459132943Sgshapiro /* default to AF_INET */ 7460132943Sgshapiro addr.sa.sa_family = AF_INET; 7461132943Sgshapiro# else /* NETINET */ 7462132943Sgshapiro# if NETINET6 7463132943Sgshapiro /* default to AF_INET6 */ 7464132943Sgshapiro addr.sa.sa_family = AF_INET6; 7465132943Sgshapiro# else /* NETINET6 */ 7466132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7467132943Sgshapiro map->map_mname, p); 7468132943Sgshapiro return false; 7469132943Sgshapiro# endif /* NETINET6 */ 7470132943Sgshapiro# endif /* NETINET */ 7471132943Sgshapiro#endif /* NETUNIX */ 7472132943Sgshapiro } 7473132943Sgshapiro 7474132943Sgshapiro# if NETUNIX 7475132943Sgshapiro if (addr.sa.sa_family == AF_UNIX) 7476132943Sgshapiro { 7477132943Sgshapiro long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 7478132943Sgshapiro 7479132943Sgshapiro at = colon; 7480168515Sgshapiro if (strlen(colon) >= sizeof(addr.sunix.sun_path)) 7481132943Sgshapiro { 7482132943Sgshapiro syserr("socket map \"%s\": local socket name %s too long", 7483132943Sgshapiro map->map_mname, colon); 7484132943Sgshapiro return false; 7485132943Sgshapiro } 7486132943Sgshapiro errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 7487132943Sgshapiro S_IRUSR|S_IWUSR, NULL); 7488132943Sgshapiro 7489132943Sgshapiro if (errno != 0) 7490132943Sgshapiro { 7491132943Sgshapiro /* if not safe, don't create */ 7492132943Sgshapiro syserr("socket map \"%s\": local socket name %s unsafe", 7493132943Sgshapiro map->map_mname, colon); 7494132943Sgshapiro return false; 7495132943Sgshapiro } 7496132943Sgshapiro 7497132943Sgshapiro (void) sm_strlcpy(addr.sunix.sun_path, colon, 7498168515Sgshapiro sizeof(addr.sunix.sun_path)); 7499168515Sgshapiro addrlen = sizeof(struct sockaddr_un); 7500132943Sgshapiro } 7501132943Sgshapiro else 7502132943Sgshapiro# endif /* NETUNIX */ 7503132943Sgshapiro# if NETINET || NETINET6 7504132943Sgshapiro if (false 7505132943Sgshapiro# if NETINET 7506132943Sgshapiro || addr.sa.sa_family == AF_INET 7507132943Sgshapiro# endif /* NETINET */ 7508132943Sgshapiro# if NETINET6 7509132943Sgshapiro || addr.sa.sa_family == AF_INET6 7510132943Sgshapiro# endif /* NETINET6 */ 7511132943Sgshapiro ) 7512132943Sgshapiro { 7513132943Sgshapiro unsigned short port; 7514132943Sgshapiro 7515132943Sgshapiro /* Parse port@host */ 7516132943Sgshapiro at = strchr(colon, '@'); 7517132943Sgshapiro if (at == NULL) 7518132943Sgshapiro { 7519132943Sgshapiro syserr("socket map \"%s\": bad address %s (expected port@host)", 7520132943Sgshapiro map->map_mname, colon); 7521132943Sgshapiro return false; 7522132943Sgshapiro } 7523132943Sgshapiro *at = '\0'; 7524132943Sgshapiro if (isascii(*colon) && isdigit(*colon)) 7525132943Sgshapiro port = htons((unsigned short) atoi(colon)); 7526132943Sgshapiro else 7527132943Sgshapiro { 7528132943Sgshapiro# ifdef NO_GETSERVBYNAME 7529132943Sgshapiro syserr("socket map \"%s\": invalid port number %s", 7530132943Sgshapiro map->map_mname, colon); 7531132943Sgshapiro return false; 7532132943Sgshapiro# else /* NO_GETSERVBYNAME */ 7533132943Sgshapiro register struct servent *sp; 7534132943Sgshapiro 7535132943Sgshapiro sp = getservbyname(colon, "tcp"); 7536132943Sgshapiro if (sp == NULL) 7537132943Sgshapiro { 7538132943Sgshapiro syserr("socket map \"%s\": unknown port name %s", 7539132943Sgshapiro map->map_mname, colon); 7540132943Sgshapiro return false; 7541132943Sgshapiro } 7542132943Sgshapiro port = sp->s_port; 7543132943Sgshapiro# endif /* NO_GETSERVBYNAME */ 7544132943Sgshapiro } 7545132943Sgshapiro *at++ = '@'; 7546132943Sgshapiro if (*at == '[') 7547132943Sgshapiro { 7548132943Sgshapiro char *end; 7549132943Sgshapiro 7550132943Sgshapiro end = strchr(at, ']'); 7551132943Sgshapiro if (end != NULL) 7552132943Sgshapiro { 7553132943Sgshapiro bool found = false; 7554132943Sgshapiro# if NETINET 7555132943Sgshapiro unsigned long hid = INADDR_NONE; 7556132943Sgshapiro# endif /* NETINET */ 7557132943Sgshapiro# if NETINET6 7558132943Sgshapiro struct sockaddr_in6 hid6; 7559132943Sgshapiro# endif /* NETINET6 */ 7560132943Sgshapiro 7561132943Sgshapiro *end = '\0'; 7562132943Sgshapiro# if NETINET 7563132943Sgshapiro if (addr.sa.sa_family == AF_INET && 7564132943Sgshapiro (hid = inet_addr(&at[1])) != INADDR_NONE) 7565132943Sgshapiro { 7566132943Sgshapiro addr.sin.sin_addr.s_addr = hid; 7567132943Sgshapiro addr.sin.sin_port = port; 7568132943Sgshapiro found = true; 7569132943Sgshapiro } 7570132943Sgshapiro# endif /* NETINET */ 7571132943Sgshapiro# if NETINET6 7572168515Sgshapiro (void) memset(&hid6, '\0', sizeof(hid6)); 7573132943Sgshapiro if (addr.sa.sa_family == AF_INET6 && 7574132943Sgshapiro anynet_pton(AF_INET6, &at[1], 7575132943Sgshapiro &hid6.sin6_addr) == 1) 7576132943Sgshapiro { 7577132943Sgshapiro addr.sin6.sin6_addr = hid6.sin6_addr; 7578132943Sgshapiro addr.sin6.sin6_port = port; 7579132943Sgshapiro found = true; 7580132943Sgshapiro } 7581132943Sgshapiro# endif /* NETINET6 */ 7582132943Sgshapiro *end = ']'; 7583132943Sgshapiro if (!found) 7584132943Sgshapiro { 7585132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7586132943Sgshapiro map->map_mname, at); 7587132943Sgshapiro return false; 7588132943Sgshapiro } 7589132943Sgshapiro } 7590132943Sgshapiro else 7591132943Sgshapiro { 7592132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7593132943Sgshapiro map->map_mname, at); 7594132943Sgshapiro return false; 7595132943Sgshapiro } 7596132943Sgshapiro } 7597132943Sgshapiro else 7598132943Sgshapiro { 7599132943Sgshapiro hp = sm_gethostbyname(at, addr.sa.sa_family); 7600132943Sgshapiro if (hp == NULL) 7601132943Sgshapiro { 7602132943Sgshapiro syserr("socket map \"%s\": Unknown host name %s", 7603132943Sgshapiro map->map_mname, at); 7604132943Sgshapiro return false; 7605132943Sgshapiro } 7606132943Sgshapiro addr.sa.sa_family = hp->h_addrtype; 7607132943Sgshapiro switch (hp->h_addrtype) 7608132943Sgshapiro { 7609132943Sgshapiro# if NETINET 7610132943Sgshapiro case AF_INET: 7611132943Sgshapiro memmove(&addr.sin.sin_addr, 7612132943Sgshapiro hp->h_addr, INADDRSZ); 7613132943Sgshapiro addr.sin.sin_port = port; 7614168515Sgshapiro addrlen = sizeof(struct sockaddr_in); 7615132943Sgshapiro addrno = 1; 7616132943Sgshapiro break; 7617132943Sgshapiro# endif /* NETINET */ 7618132943Sgshapiro 7619132943Sgshapiro# if NETINET6 7620132943Sgshapiro case AF_INET6: 7621132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7622132943Sgshapiro hp->h_addr, IN6ADDRSZ); 7623132943Sgshapiro addr.sin6.sin6_port = port; 7624168515Sgshapiro addrlen = sizeof(struct sockaddr_in6); 7625132943Sgshapiro addrno = 1; 7626132943Sgshapiro break; 7627132943Sgshapiro# endif /* NETINET6 */ 7628132943Sgshapiro 7629132943Sgshapiro default: 7630132943Sgshapiro syserr("socket map \"%s\": Unknown protocol for %s (%d)", 7631132943Sgshapiro map->map_mname, at, hp->h_addrtype); 7632132943Sgshapiro# if NETINET6 7633132943Sgshapiro freehostent(hp); 7634132943Sgshapiro# endif /* NETINET6 */ 7635132943Sgshapiro return false; 7636132943Sgshapiro } 7637132943Sgshapiro } 7638132943Sgshapiro } 7639132943Sgshapiro else 7640132943Sgshapiro# endif /* NETINET || NETINET6 */ 7641132943Sgshapiro { 7642132943Sgshapiro syserr("socket map \"%s\": unknown socket protocol", 7643132943Sgshapiro map->map_mname); 7644132943Sgshapiro return false; 7645132943Sgshapiro } 7646132943Sgshapiro 7647132943Sgshapiro /* nope, actually connecting */ 7648132943Sgshapiro for (;;) 7649132943Sgshapiro { 7650132943Sgshapiro sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 7651132943Sgshapiro if (sock < 0) 7652132943Sgshapiro { 7653132943Sgshapiro save_errno = errno; 7654132943Sgshapiro if (tTd(38, 5)) 7655132943Sgshapiro sm_dprintf("socket map \"%s\": error creating socket: %s\n", 7656132943Sgshapiro map->map_mname, 7657132943Sgshapiro sm_errstring(save_errno)); 7658132943Sgshapiro# if NETINET6 7659132943Sgshapiro if (hp != NULL) 7660132943Sgshapiro freehostent(hp); 7661132943Sgshapiro# endif /* NETINET6 */ 7662132943Sgshapiro return false; 7663132943Sgshapiro } 7664132943Sgshapiro 7665132943Sgshapiro if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 7666132943Sgshapiro break; 7667132943Sgshapiro 7668132943Sgshapiro /* couldn't connect.... try next address */ 7669132943Sgshapiro save_errno = errno; 7670132943Sgshapiro p = CurHostName; 7671132943Sgshapiro CurHostName = at; 7672132943Sgshapiro if (tTd(38, 5)) 7673132943Sgshapiro sm_dprintf("socket_open (%s): open %s failed: %s\n", 7674132943Sgshapiro map->map_mname, at, sm_errstring(save_errno)); 7675132943Sgshapiro CurHostName = p; 7676132943Sgshapiro (void) close(sock); 7677132943Sgshapiro 7678132943Sgshapiro /* try next address */ 7679132943Sgshapiro if (hp != NULL && hp->h_addr_list[addrno] != NULL) 7680132943Sgshapiro { 7681132943Sgshapiro switch (addr.sa.sa_family) 7682132943Sgshapiro { 7683132943Sgshapiro# if NETINET 7684132943Sgshapiro case AF_INET: 7685132943Sgshapiro memmove(&addr.sin.sin_addr, 7686132943Sgshapiro hp->h_addr_list[addrno++], 7687132943Sgshapiro INADDRSZ); 7688132943Sgshapiro break; 7689132943Sgshapiro# endif /* NETINET */ 7690132943Sgshapiro 7691132943Sgshapiro# if NETINET6 7692132943Sgshapiro case AF_INET6: 7693132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7694132943Sgshapiro hp->h_addr_list[addrno++], 7695132943Sgshapiro IN6ADDRSZ); 7696132943Sgshapiro break; 7697132943Sgshapiro# endif /* NETINET6 */ 7698132943Sgshapiro 7699132943Sgshapiro default: 7700132943Sgshapiro if (tTd(38, 5)) 7701132943Sgshapiro sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 7702132943Sgshapiro map->map_mname, at, 7703132943Sgshapiro hp->h_addrtype); 7704132943Sgshapiro# if NETINET6 7705132943Sgshapiro freehostent(hp); 7706132943Sgshapiro# endif /* NETINET6 */ 7707132943Sgshapiro return false; 7708132943Sgshapiro } 7709132943Sgshapiro continue; 7710132943Sgshapiro } 7711132943Sgshapiro p = CurHostName; 7712132943Sgshapiro CurHostName = at; 7713132943Sgshapiro if (tTd(38, 5)) 7714132943Sgshapiro sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 7715132943Sgshapiro map->map_mname, sm_errstring(save_errno)); 7716132943Sgshapiro CurHostName = p; 7717132943Sgshapiro# if NETINET6 7718132943Sgshapiro if (hp != NULL) 7719132943Sgshapiro freehostent(hp); 7720132943Sgshapiro# endif /* NETINET6 */ 7721132943Sgshapiro return false; 7722132943Sgshapiro } 7723132943Sgshapiro# if NETINET6 7724132943Sgshapiro if (hp != NULL) 7725132943Sgshapiro { 7726132943Sgshapiro freehostent(hp); 7727132943Sgshapiro hp = NULL; 7728132943Sgshapiro } 7729132943Sgshapiro# endif /* NETINET6 */ 7730132943Sgshapiro if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 7731132943Sgshapiro SM_TIME_DEFAULT, 7732132943Sgshapiro (void *) &sock, 7733132943Sgshapiro SM_IO_RDWR, 7734132943Sgshapiro NULL)) == NULL) 7735132943Sgshapiro { 7736132943Sgshapiro close(sock); 7737132943Sgshapiro if (tTd(38, 2)) 7738132943Sgshapiro sm_dprintf("socket_open (%s): failed to create stream: %s\n", 7739132943Sgshapiro map->map_mname, sm_errstring(errno)); 7740132943Sgshapiro return false; 7741132943Sgshapiro } 7742132943Sgshapiro 7743132943Sgshapiro /* Save connection for reuse */ 7744132943Sgshapiro s->s_socketmap = map; 7745132943Sgshapiro return true; 7746132943Sgshapiro} 7747132943Sgshapiro 7748132943Sgshapiro/* 7749132943Sgshapiro** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 7750132943Sgshapiro** 7751132943Sgshapiro** Cache SOCKET connections based on the connection specifier 7752132943Sgshapiro** and PID so we don't have multiple connections open to 7753132943Sgshapiro** the same server for different maps. Need a separate connection 7754132943Sgshapiro** per PID since a parent process may close the map before the 7755132943Sgshapiro** child is done with it. 7756132943Sgshapiro** 7757132943Sgshapiro** Parameters: 7758132943Sgshapiro** conn -- SOCKET map connection specifier 7759132943Sgshapiro** 7760132943Sgshapiro** Returns: 7761132943Sgshapiro** Symbol table entry for the SOCKET connection. 7762132943Sgshapiro*/ 7763132943Sgshapiro 7764132943Sgshapirostatic STAB * 7765132943Sgshapirosocket_map_findconn(conn) 7766132943Sgshapiro const char *conn; 7767132943Sgshapiro{ 7768132943Sgshapiro char *nbuf; 7769132943Sgshapiro STAB *SM_NONVOLATILE s = NULL; 7770132943Sgshapiro 7771132943Sgshapiro nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 7772132943Sgshapiro SM_TRY 7773132943Sgshapiro s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 7774132943Sgshapiro SM_FINALLY 7775132943Sgshapiro sm_free(nbuf); 7776132943Sgshapiro SM_END_TRY 7777132943Sgshapiro return s; 7778132943Sgshapiro} 7779132943Sgshapiro 7780132943Sgshapiro/* 7781132943Sgshapiro** SOCKET_MAP_CLOSE -- close the socket 7782132943Sgshapiro*/ 7783132943Sgshapiro 7784132943Sgshapirovoid 7785132943Sgshapirosocket_map_close(map) 7786132943Sgshapiro MAP *map; 7787132943Sgshapiro{ 7788132943Sgshapiro STAB *s; 7789132943Sgshapiro MAP *smap; 7790132943Sgshapiro 7791132943Sgshapiro if (tTd(38, 20)) 7792132943Sgshapiro sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 7793132943Sgshapiro (long) CurrentPid); 7794132943Sgshapiro 7795132943Sgshapiro /* Check if already closed */ 7796132943Sgshapiro if (map->map_db1 == NULL) 7797132943Sgshapiro { 7798132943Sgshapiro if (tTd(38, 20)) 7799132943Sgshapiro sm_dprintf("socket_map_close(%s) already closed\n", 7800132943Sgshapiro map->map_file); 7801132943Sgshapiro return; 7802132943Sgshapiro } 7803132943Sgshapiro sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 7804132943Sgshapiro 7805132943Sgshapiro /* Mark all the maps that share the connection as closed */ 7806132943Sgshapiro s = socket_map_findconn(map->map_file); 7807132943Sgshapiro smap = s->s_socketmap; 7808132943Sgshapiro while (smap != NULL) 7809132943Sgshapiro { 7810132943Sgshapiro MAP *next; 7811132943Sgshapiro 7812132943Sgshapiro if (tTd(38, 2) && smap != map) 7813132943Sgshapiro sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 7814132943Sgshapiro map->map_mname, smap->map_mname); 7815132943Sgshapiro 7816132943Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 7817132943Sgshapiro smap->map_db1 = NULL; 7818132943Sgshapiro next = smap->socket_map_next; 7819132943Sgshapiro smap->socket_map_next = NULL; 7820132943Sgshapiro smap = next; 7821132943Sgshapiro } 7822132943Sgshapiro s->s_socketmap = NULL; 7823132943Sgshapiro} 7824132943Sgshapiro 7825132943Sgshapiro/* 7826132943Sgshapiro** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 7827132943Sgshapiro*/ 7828132943Sgshapiro 7829132943Sgshapirochar * 7830132943Sgshapirosocket_map_lookup(map, name, av, statp) 7831132943Sgshapiro MAP *map; 7832132943Sgshapiro char *name; 7833132943Sgshapiro char **av; 7834132943Sgshapiro int *statp; 7835132943Sgshapiro{ 7836132943Sgshapiro unsigned int nettolen, replylen, recvlen; 7837147078Sgshapiro char *replybuf, *rval, *value, *status, *key; 7838132943Sgshapiro SM_FILE_T *f; 7839147078Sgshapiro char keybuf[MAXNAME + 1]; 7840132943Sgshapiro 7841132943Sgshapiro replybuf = NULL; 7842132943Sgshapiro rval = NULL; 7843132943Sgshapiro f = (SM_FILE_T *)map->map_db1; 7844132943Sgshapiro if (tTd(38, 20)) 7845132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s) %s\n", 7846132943Sgshapiro map->map_mname, name, map->map_file); 7847132943Sgshapiro 7848147078Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 7849147078Sgshapiro { 7850147078Sgshapiro nettolen = strlen(name); 7851168515Sgshapiro if (nettolen > sizeof(keybuf) - 1) 7852168515Sgshapiro nettolen = sizeof(keybuf) - 1; 7853147078Sgshapiro memmove(keybuf, name, nettolen); 7854147078Sgshapiro keybuf[nettolen] = '\0'; 7855147078Sgshapiro makelower(keybuf); 7856147078Sgshapiro key = keybuf; 7857147078Sgshapiro } 7858147078Sgshapiro else 7859147078Sgshapiro key = name; 7860147078Sgshapiro 7861147078Sgshapiro nettolen = strlen(map->map_mname) + 1 + strlen(key); 7862132943Sgshapiro SM_ASSERT(nettolen > strlen(map->map_mname)); 7863147078Sgshapiro SM_ASSERT(nettolen > strlen(key)); 7864132943Sgshapiro if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 7865147078Sgshapiro nettolen, map->map_mname, key) == SM_IO_EOF) || 7866132943Sgshapiro (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 7867132943Sgshapiro (sm_io_error(f))) 7868132943Sgshapiro { 7869132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 7870132943Sgshapiro map->map_mname); 7871132943Sgshapiro *statp = EX_TEMPFAIL; 7872132943Sgshapiro goto errcl; 7873132943Sgshapiro } 7874132943Sgshapiro 7875132943Sgshapiro if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) 7876132943Sgshapiro { 7877132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", 7878132943Sgshapiro map->map_mname); 7879132943Sgshapiro *statp = EX_TEMPFAIL; 7880132943Sgshapiro goto errcl; 7881132943Sgshapiro } 7882132943Sgshapiro if (replylen > SOCKETMAP_MAXL) 7883132943Sgshapiro { 7884132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 7885132943Sgshapiro map->map_mname, replylen); 7886132943Sgshapiro *statp = EX_TEMPFAIL; 7887132943Sgshapiro goto errcl; 7888132943Sgshapiro } 7889132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 7890132943Sgshapiro { 7891132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 7892132943Sgshapiro map->map_mname); 7893132943Sgshapiro *statp = EX_TEMPFAIL; 7894132943Sgshapiro goto error; 7895132943Sgshapiro } 7896132943Sgshapiro 7897132943Sgshapiro replybuf = (char *) sm_malloc(replylen + 1); 7898132943Sgshapiro if (replybuf == NULL) 7899132943Sgshapiro { 7900132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 7901132943Sgshapiro map->map_mname, replylen + 1); 7902132943Sgshapiro *statp = EX_OSERR; 7903132943Sgshapiro goto error; 7904132943Sgshapiro } 7905132943Sgshapiro 7906132943Sgshapiro recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 7907132943Sgshapiro if (recvlen < replylen) 7908132943Sgshapiro { 7909132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 7910132943Sgshapiro map->map_mname, recvlen, replylen); 7911132943Sgshapiro *statp = EX_TEMPFAIL; 7912132943Sgshapiro goto errcl; 7913132943Sgshapiro } 7914132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 7915132943Sgshapiro { 7916132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 7917132943Sgshapiro map->map_mname); 7918132943Sgshapiro *statp = EX_TEMPFAIL; 7919132943Sgshapiro goto errcl; 7920132943Sgshapiro } 7921132943Sgshapiro status = replybuf; 7922132943Sgshapiro replybuf[recvlen] = '\0'; 7923132943Sgshapiro value = strchr(replybuf, ' '); 7924132943Sgshapiro if (value != NULL) 7925132943Sgshapiro { 7926132943Sgshapiro *value = '\0'; 7927132943Sgshapiro value++; 7928132943Sgshapiro } 7929132943Sgshapiro if (strcmp(status, "OK") == 0) 7930132943Sgshapiro { 7931132943Sgshapiro *statp = EX_OK; 7932132943Sgshapiro 7933132943Sgshapiro /* collect the return value */ 7934132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 7935147078Sgshapiro rval = map_rewrite(map, key, strlen(key), NULL); 7936132943Sgshapiro else 7937132943Sgshapiro rval = map_rewrite(map, value, strlen(value), av); 7938132943Sgshapiro } 7939132943Sgshapiro else if (strcmp(status, "NOTFOUND") == 0) 7940132943Sgshapiro { 7941132943Sgshapiro *statp = EX_NOTFOUND; 7942132943Sgshapiro if (tTd(38, 20)) 7943132943Sgshapiro sm_dprintf("socket_map_lookup(%s): %s not found\n", 7944147078Sgshapiro map->map_mname, key); 7945132943Sgshapiro } 7946132943Sgshapiro else 7947132943Sgshapiro { 7948132943Sgshapiro if (tTd(38, 5)) 7949132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 7950147078Sgshapiro map->map_mname, key, status, 7951132943Sgshapiro value ? value : ""); 7952132943Sgshapiro if ((strcmp(status, "TEMP") == 0) || 7953132943Sgshapiro (strcmp(status, "TIMEOUT") == 0)) 7954132943Sgshapiro *statp = EX_TEMPFAIL; 7955132943Sgshapiro else if(strcmp(status, "PERM") == 0) 7956132943Sgshapiro *statp = EX_UNAVAILABLE; 7957132943Sgshapiro else 7958132943Sgshapiro *statp = EX_PROTOCOL; 7959132943Sgshapiro } 7960132943Sgshapiro 7961132943Sgshapiro if (replybuf != NULL) 7962132943Sgshapiro sm_free(replybuf); 7963132943Sgshapiro return rval; 7964132943Sgshapiro 7965132943Sgshapiro errcl: 7966132943Sgshapiro socket_map_close(map); 7967132943Sgshapiro error: 7968132943Sgshapiro if (replybuf != NULL) 7969132943Sgshapiro sm_free(replybuf); 7970132943Sgshapiro return rval; 7971132943Sgshapiro} 7972132943Sgshapiro#endif /* SOCKETMAP */ 7973