map.c revision 249729
138032Speter/* 2203004Sgshapiro * Copyright (c) 1998-2008 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 16249729SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.711 2013/03/12 15:24:52 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; 733203004Sgshapiro auto int status = EX_UNAVAILABLE; 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; 1713203004Sgshapiro 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; 2362203004Sgshapiro 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> 2886249729Sgshapiro# ifndef NIS_TABLE_OBJ 2887249729Sgshapiro# define NIS_TABLE_OBJ TABLE_OBJ 2888249729Sgshapiro# endif /* NIS_TABLE_OBJ */ 288938032Speter 289064562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 289164562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 289264562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 289364562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 289438032Speter 289538032Speter/* 289638032Speter** NISPLUS_MAP_OPEN -- open nisplus table 289738032Speter*/ 289838032Speter 289938032Speterbool 290038032Speternisplus_map_open(map, mode) 290138032Speter MAP *map; 290238032Speter int mode; 290338032Speter{ 290438032Speter nis_result *res = NULL; 290538032Speter int retry_cnt, max_col, i; 290638032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 290738032Speter 290838032Speter if (tTd(38, 2)) 290990792Sgshapiro sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 291038032Speter map->map_mname, map->map_file, mode); 291138032Speter 291238032Speter mode &= O_ACCMODE; 291338032Speter if (mode != O_RDONLY) 291438032Speter { 291538032Speter errno = EPERM; 291690792Sgshapiro return false; 291738032Speter } 291838032Speter 291938032Speter if (*map->map_file == '\0') 292038032Speter map->map_file = "mail_aliases.org_dir"; 292138032Speter 292238032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 292338032Speter { 292438032Speter /* set default NISPLUS Domain to $m */ 292538032Speter map->map_domain = newstr(nisplus_default_domain()); 292638032Speter if (tTd(38, 2)) 292790792Sgshapiro sm_dprintf("nisplus_map_open(%s): using domain %s\n", 292864562Sgshapiro map->map_file, map->map_domain); 292938032Speter } 293038032Speter if (!PARTIAL_NAME(map->map_file)) 293138032Speter { 293238032Speter map->map_domain = newstr(""); 2933168515Sgshapiro (void) sm_strlcpy(qbuf, map->map_file, sizeof(qbuf)); 293438032Speter } 293538032Speter else 293638032Speter { 293738032Speter /* check to see if this map actually exists */ 2938168515Sgshapiro (void) sm_strlcpyn(qbuf, sizeof(qbuf), 3, 293990792Sgshapiro map->map_file, ".", map->map_domain); 294038032Speter } 294138032Speter 294238032Speter retry_cnt = 0; 294338032Speter while (res == NULL || res->status != NIS_SUCCESS) 294438032Speter { 294538032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 294638032Speter switch (res->status) 294738032Speter { 294838032Speter case NIS_SUCCESS: 294938032Speter break; 295038032Speter 295138032Speter case NIS_TRYAGAIN: 295238032Speter case NIS_RPCERROR: 295338032Speter case NIS_NAMEUNREACHABLE: 295438032Speter if (retry_cnt++ > 4) 295538032Speter { 295638032Speter errno = EAGAIN; 295790792Sgshapiro return false; 295838032Speter } 295938032Speter /* try not to overwhelm hosed server */ 296038032Speter sleep(2); 296138032Speter break; 296238032Speter 296338032Speter default: /* all other nisplus errors */ 296464562Sgshapiro# if 0 296538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 296694334Sgshapiro syserr("451 4.3.5 Cannot find table %s.%s: %s", 296738032Speter map->map_file, map->map_domain, 296838032Speter nis_sperrno(res->status)); 296964562Sgshapiro# endif /* 0 */ 297038032Speter errno = EAGAIN; 297190792Sgshapiro return false; 297238032Speter } 297338032Speter } 297438032Speter 297538032Speter if (NIS_RES_NUMOBJ(res) != 1 || 2976249729Sgshapiro (NIS_RES_OBJECT(res)->zo_data.zo_type != NIS_TABLE_OBJ)) 297738032Speter { 297838032Speter if (tTd(38, 10)) 297990792Sgshapiro sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 298064562Sgshapiro# if 0 298138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 298294334Sgshapiro syserr("451 4.3.5 %s.%s: %s is not a table", 298338032Speter map->map_file, map->map_domain, 298438032Speter nis_sperrno(res->status)); 298564562Sgshapiro# endif /* 0 */ 298638032Speter errno = EBADF; 298790792Sgshapiro return false; 298838032Speter } 298938032Speter /* default key column is column 0 */ 299038032Speter if (map->map_keycolnm == NULL) 299138032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 299238032Speter 299338032Speter max_col = COL_MAX(res); 299438032Speter 299538032Speter /* verify the key column exist */ 299690792Sgshapiro for (i = 0; i < max_col; i++) 299738032Speter { 299864562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 299938032Speter break; 300038032Speter } 300138032Speter if (i == max_col) 300238032Speter { 300338032Speter if (tTd(38, 2)) 300490792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 300538032Speter map->map_file, map->map_keycolnm); 300638032Speter errno = ENOENT; 300790792Sgshapiro return false; 300838032Speter } 300938032Speter 301038032Speter /* default value column is the last column */ 301138032Speter if (map->map_valcolnm == NULL) 301238032Speter { 301338032Speter map->map_valcolno = max_col - 1; 301490792Sgshapiro return true; 301538032Speter } 301638032Speter 301764562Sgshapiro for (i = 0; i< max_col; i++) 301838032Speter { 301938032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 302038032Speter { 302138032Speter map->map_valcolno = i; 302290792Sgshapiro return true; 302338032Speter } 302438032Speter } 302538032Speter 302638032Speter if (tTd(38, 2)) 302790792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 302864562Sgshapiro map->map_file, map->map_keycolnm); 302938032Speter errno = ENOENT; 303090792Sgshapiro return false; 303138032Speter} 303238032Speter 303338032Speter 303438032Speter/* 303538032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 303638032Speter*/ 303738032Speter 303838032Speterchar * 303938032Speternisplus_map_lookup(map, name, av, statp) 304038032Speter MAP *map; 304138032Speter char *name; 304238032Speter char **av; 304338032Speter int *statp; 304438032Speter{ 304538032Speter char *p; 304638032Speter auto int vsize; 304738032Speter char *skp; 304838032Speter int skleft; 304938032Speter char search_key[MAXNAME + 4]; 305038032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 305138032Speter nis_result *result; 305238032Speter 305338032Speter if (tTd(38, 20)) 305490792Sgshapiro sm_dprintf("nisplus_map_lookup(%s, %s)\n", 305538032Speter map->map_mname, name); 305638032Speter 305738032Speter if (!bitset(MF_OPEN, map->map_mflags)) 305838032Speter { 305938032Speter if (nisplus_map_open(map, O_RDONLY)) 306042575Speter { 306138032Speter map->map_mflags |= MF_OPEN; 306290792Sgshapiro map->map_pid = CurrentPid; 306342575Speter } 306438032Speter else 306538032Speter { 306638032Speter *statp = EX_UNAVAILABLE; 306738032Speter return NULL; 306838032Speter } 306938032Speter } 307038032Speter 307138032Speter /* 307238032Speter ** Copy the name to the key buffer, escaping double quote characters 307338032Speter ** by doubling them and quoting "]" and "," to avoid having the 307438032Speter ** NIS+ parser choke on them. 307538032Speter */ 307638032Speter 3077168515Sgshapiro skleft = sizeof(search_key) - 4; 307838032Speter skp = search_key; 307938032Speter for (p = name; *p != '\0' && skleft > 0; p++) 308038032Speter { 308138032Speter switch (*p) 308238032Speter { 308338032Speter case ']': 308438032Speter case ',': 308538032Speter /* quote the character */ 308638032Speter *skp++ = '"'; 308738032Speter *skp++ = *p; 308838032Speter *skp++ = '"'; 308938032Speter skleft -= 3; 309038032Speter break; 309138032Speter 309238032Speter case '"': 309338032Speter /* double the quote */ 309438032Speter *skp++ = '"'; 309538032Speter skleft--; 309664562Sgshapiro /* FALLTHROUGH */ 309738032Speter 309838032Speter default: 309938032Speter *skp++ = *p; 310038032Speter skleft--; 310138032Speter break; 310238032Speter } 310338032Speter } 310438032Speter *skp = '\0'; 310538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 310638032Speter makelower(search_key); 310738032Speter 310838032Speter /* construct the query */ 310938032Speter if (PARTIAL_NAME(map->map_file)) 3110168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s.%s", 311138032Speter map->map_keycolnm, search_key, map->map_file, 311238032Speter map->map_domain); 311338032Speter else 3114168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s", 311538032Speter map->map_keycolnm, search_key, map->map_file); 311638032Speter 311738032Speter if (tTd(38, 20)) 311890792Sgshapiro sm_dprintf("qbuf=%s\n", qbuf); 311938032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 312038032Speter if (result->status == NIS_SUCCESS) 312138032Speter { 312238032Speter int count; 312338032Speter char *str; 312438032Speter 312538032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 312638032Speter { 312738032Speter if (LogLevel > 10) 312838032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 312964562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 313064562Sgshapiro map->map_file, count); 313138032Speter 313238032Speter /* ignore second entry */ 313338032Speter if (tTd(38, 20)) 313490792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 313538032Speter name, count); 313638032Speter } 313738032Speter 313838032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 313938032Speter /* set the length of the result */ 314038032Speter if (p == NULL) 314138032Speter p = ""; 314238032Speter vsize = strlen(p); 314338032Speter if (tTd(38, 20)) 314490792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), found %s\n", 314538032Speter name, p); 314638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 314738032Speter str = map_rewrite(map, name, strlen(name), NULL); 314838032Speter else 314938032Speter str = map_rewrite(map, p, vsize, av); 315038032Speter nis_freeresult(result); 315138032Speter *statp = EX_OK; 315238032Speter return str; 315338032Speter } 315438032Speter else 315538032Speter { 315638032Speter if (result->status == NIS_NOTFOUND) 315738032Speter *statp = EX_NOTFOUND; 315838032Speter else if (result->status == NIS_TRYAGAIN) 315938032Speter *statp = EX_TEMPFAIL; 316038032Speter else 316138032Speter { 316238032Speter *statp = EX_UNAVAILABLE; 316338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 316438032Speter } 316538032Speter } 316638032Speter if (tTd(38, 20)) 316790792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 316838032Speter nis_freeresult(result); 316938032Speter return NULL; 317038032Speter} 317138032Speter 317238032Speter 317338032Speter 317438032Speter/* 317538032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 317638032Speter*/ 317738032Speter 317864562Sgshapirostatic bool 317938032Speternisplus_getcanonname(name, hbsize, statp) 318038032Speter char *name; 318138032Speter int hbsize; 318238032Speter int *statp; 318338032Speter{ 318438032Speter char *vp; 318538032Speter auto int vsize; 318638032Speter nis_result *result; 318738032Speter char *p; 318838032Speter char nbuf[MAXNAME + 1]; 318938032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 319038032Speter 3191168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 319238032Speter { 319338032Speter *statp = EX_UNAVAILABLE; 319490792Sgshapiro return false; 319538032Speter } 319673188Sgshapiro (void) shorten_hostname(nbuf); 319738032Speter 319838032Speter p = strchr(nbuf, '.'); 319938032Speter if (p == NULL) 320038032Speter { 320138032Speter /* single token */ 3202168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 320390792Sgshapiro "[name=%s],hosts.org_dir", nbuf); 320438032Speter } 320538032Speter else if (p[1] != '\0') 320638032Speter { 320738032Speter /* multi token -- take only first token in nbuf */ 320838032Speter *p = '\0'; 3209168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 321090792Sgshapiro "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 321138032Speter } 321238032Speter else 321338032Speter { 321438032Speter *statp = EX_NOHOST; 321590792Sgshapiro return false; 321638032Speter } 321738032Speter 321838032Speter if (tTd(38, 20)) 321994334Sgshapiro sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 322090792Sgshapiro name, qbuf); 322138032Speter 322238032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 322390792Sgshapiro NULL, NULL); 322438032Speter 322538032Speter if (result->status == NIS_SUCCESS) 322638032Speter { 322738032Speter int count; 322838032Speter char *domain; 322938032Speter 323038032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 323138032Speter { 323238032Speter if (LogLevel > 10) 323338032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 323464562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 323564562Sgshapiro count); 323638032Speter 323738032Speter /* ignore second entry */ 323838032Speter if (tTd(38, 20)) 323994334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 324090792Sgshapiro name, count); 324138032Speter } 324238032Speter 324338032Speter if (tTd(38, 20)) 324494334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 324590792Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 324638032Speter 324738032Speter 324838032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 324938032Speter vsize = strlen(vp); 325038032Speter if (tTd(38, 20)) 325190792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found %s\n", 325290792Sgshapiro name, vp); 325338032Speter if (strchr(vp, '.') != NULL) 325438032Speter { 325538032Speter domain = ""; 325638032Speter } 325738032Speter else 325838032Speter { 325938032Speter domain = macvalue('m', CurEnv); 326038032Speter if (domain == NULL) 326138032Speter domain = ""; 326238032Speter } 326338032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 326438032Speter { 326538032Speter if (domain[0] == '\0') 326690792Sgshapiro (void) sm_strlcpy(name, vp, hbsize); 326738032Speter else 326890792Sgshapiro (void) sm_snprintf(name, hbsize, 326990792Sgshapiro "%s.%s", vp, domain); 327038032Speter *statp = EX_OK; 327138032Speter } 327238032Speter else 327338032Speter *statp = EX_NOHOST; 327438032Speter nis_freeresult(result); 327590792Sgshapiro return true; 327638032Speter } 327738032Speter else 327838032Speter { 327938032Speter if (result->status == NIS_NOTFOUND) 328038032Speter *statp = EX_NOHOST; 328138032Speter else if (result->status == NIS_TRYAGAIN) 328238032Speter *statp = EX_TEMPFAIL; 328338032Speter else 328438032Speter *statp = EX_UNAVAILABLE; 328538032Speter } 328638032Speter if (tTd(38, 20)) 328790792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 328890792Sgshapiro name, result->status, *statp); 328938032Speter nis_freeresult(result); 329090792Sgshapiro return false; 329138032Speter} 329238032Speter 329338032Speterchar * 329438032Speternisplus_default_domain() 329538032Speter{ 329638032Speter static char default_domain[MAXNAME + 1] = ""; 329738032Speter char *p; 329838032Speter 329938032Speter if (default_domain[0] != '\0') 330064562Sgshapiro return default_domain; 330138032Speter 330238032Speter p = nis_local_directory(); 3303168515Sgshapiro (void) sm_strlcpy(default_domain, p, sizeof(default_domain)); 330438032Speter return default_domain; 330538032Speter} 330638032Speter 330738032Speter#endif /* NISPLUS */ 330890792Sgshapiro/* 330938032Speter** LDAP Modules 331038032Speter*/ 331138032Speter 331264562Sgshapiro/* 331364562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 331464562Sgshapiro*/ 331564562Sgshapiro 331664562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 331764562Sgshapiro 331890792Sgshapiro# if PH_MAP 331964562Sgshapiro# define ph_map_dequote ldapmap_dequote 332064562Sgshapiro# endif /* PH_MAP */ 332164562Sgshapiro 332290792Sgshapirostatic char *ldapmap_dequote __P((char *)); 332390792Sgshapiro 332490792Sgshapirostatic char * 332564562Sgshapiroldapmap_dequote(str) 332664562Sgshapiro char *str; 332764562Sgshapiro{ 332864562Sgshapiro char *p; 332964562Sgshapiro char *start; 333064562Sgshapiro 333164562Sgshapiro if (str == NULL) 333264562Sgshapiro return NULL; 333364562Sgshapiro 333464562Sgshapiro p = str; 333564562Sgshapiro if (*p == '"') 333664562Sgshapiro { 333764562Sgshapiro /* Should probably swallow initial whitespace here */ 333864562Sgshapiro start = ++p; 333964562Sgshapiro } 334064562Sgshapiro else 334164562Sgshapiro return str; 334264562Sgshapiro while (*p != '"' && *p != '\0') 334364562Sgshapiro p++; 334464562Sgshapiro if (*p != '\0') 334564562Sgshapiro *p = '\0'; 334664562Sgshapiro return start; 334764562Sgshapiro} 334864562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 334964562Sgshapiro 335090792Sgshapiro#if LDAPMAP 335138032Speter 335290792Sgshapirostatic SM_LDAP_STRUCT *LDAPDefaults = NULL; 335338032Speter 335438032Speter/* 335564562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 335638032Speter** 335764562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 335864562Sgshapiro** single server connection to a host (with the same host, port, 335964562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 336038032Speter*/ 336138032Speter 336238032Speterbool 336364562Sgshapiroldapmap_open(map, mode) 336438032Speter MAP *map; 336538032Speter int mode; 336638032Speter{ 336790792Sgshapiro SM_LDAP_STRUCT *lmap; 336864562Sgshapiro STAB *s; 3369132943Sgshapiro char *id; 337064562Sgshapiro 337138032Speter if (tTd(38, 2)) 337290792Sgshapiro sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 337338032Speter 3374168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3375168515Sgshapiro HASLDAPGETALIASBYNAME 3376168515Sgshapiro if (VendorCode == VENDOR_SUN && 3377168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3378168515Sgshapiro { 3379168515Sgshapiro return true; 3380168515Sgshapiro } 3381168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3382168515Sgshapiro 338338032Speter mode &= O_ACCMODE; 338464562Sgshapiro 338564562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 338638032Speter if (mode != O_RDONLY) 338738032Speter { 338838032Speter /* issue a pseudo-error message */ 338990792Sgshapiro errno = SM_EMAPCANTWRITE; 339090792Sgshapiro return false; 339138032Speter } 339264562Sgshapiro 339390792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 339464562Sgshapiro 339564562Sgshapiro s = ldapmap_findconn(lmap); 339677349Sgshapiro if (s->s_lmap != NULL) 339764562Sgshapiro { 339864562Sgshapiro /* Already have a connection open to this LDAP server */ 339990792Sgshapiro lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 340090792Sgshapiro lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 340177349Sgshapiro 340277349Sgshapiro /* Add this map as head of linked list */ 340377349Sgshapiro lmap->ldap_next = s->s_lmap; 340477349Sgshapiro s->s_lmap = map; 340577349Sgshapiro 340666494Sgshapiro if (tTd(38, 2)) 340790792Sgshapiro sm_dprintf("using cached connection\n"); 340890792Sgshapiro return true; 340964562Sgshapiro } 341064562Sgshapiro 341166494Sgshapiro if (tTd(38, 2)) 341290792Sgshapiro sm_dprintf("opening new connection\n"); 341366494Sgshapiro 3414132943Sgshapiro if (lmap->ldap_host != NULL) 3415132943Sgshapiro id = lmap->ldap_host; 3416132943Sgshapiro else if (lmap->ldap_uri != NULL) 3417132943Sgshapiro id = lmap->ldap_uri; 3418132943Sgshapiro else 3419132943Sgshapiro id = "localhost"; 3420132943Sgshapiro 3421203004Sgshapiro if (tTd(74, 104)) 3422203004Sgshapiro { 3423203004Sgshapiro extern MAPCLASS NullMapClass; 3424203004Sgshapiro 3425203004Sgshapiro /* debug mode: don't actually open an LDAP connection */ 3426203004Sgshapiro map->map_orgclass = map->map_class; 3427203004Sgshapiro map->map_class = &NullMapClass; 3428203004Sgshapiro map->map_mflags |= MF_OPEN; 3429203004Sgshapiro map->map_pid = CurrentPid; 3430203004Sgshapiro return true; 3431203004Sgshapiro } 3432203004Sgshapiro 343364562Sgshapiro /* No connection yet, connect */ 343490792Sgshapiro if (!sm_ldap_start(map->map_mname, lmap)) 343538032Speter { 343690792Sgshapiro if (errno == ETIMEDOUT) 343738032Speter { 343838032Speter if (LogLevel > 1) 343938032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 3440244833Sgshapiro "timeout connecting to LDAP server %.100s", 3441132943Sgshapiro id); 344238032Speter } 344338032Speter 344438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 344538032Speter { 344664562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3447132943Sgshapiro { 344864562Sgshapiro syserr("%s failed to %s in map %s", 344964562Sgshapiro# if USE_LDAP_INIT 345090792Sgshapiro "ldap_init/ldap_bind", 345164562Sgshapiro# else /* USE_LDAP_INIT */ 345264562Sgshapiro "ldap_open", 345364562Sgshapiro# endif /* USE_LDAP_INIT */ 3454132943Sgshapiro id, map->map_mname); 3455132943Sgshapiro } 345664562Sgshapiro else 3457132943Sgshapiro { 345894334Sgshapiro syserr("451 4.3.5 %s failed to %s in map %s", 345964562Sgshapiro# if USE_LDAP_INIT 346090792Sgshapiro "ldap_init/ldap_bind", 346164562Sgshapiro# else /* USE_LDAP_INIT */ 346264562Sgshapiro "ldap_open", 346364562Sgshapiro# endif /* USE_LDAP_INIT */ 3464132943Sgshapiro id, map->map_mname); 3465132943Sgshapiro } 346638032Speter } 346790792Sgshapiro return false; 346838032Speter } 346938032Speter 347090792Sgshapiro /* Save connection for reuse */ 347190792Sgshapiro s->s_lmap = map; 347290792Sgshapiro return true; 347338032Speter} 347438032Speter 347538032Speter/* 347664562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 347738032Speter*/ 347838032Speter 347938032Spetervoid 348064562Sgshapiroldapmap_close(map) 348138032Speter MAP *map; 348238032Speter{ 348390792Sgshapiro SM_LDAP_STRUCT *lmap; 348464562Sgshapiro STAB *s; 348543730Speter 348664562Sgshapiro if (tTd(38, 2)) 348790792Sgshapiro sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 348864562Sgshapiro 348990792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 349064562Sgshapiro 349164562Sgshapiro /* Check if already closed */ 349264562Sgshapiro if (lmap->ldap_ld == NULL) 349364562Sgshapiro return; 349464562Sgshapiro 349577349Sgshapiro /* Close the LDAP connection */ 349690792Sgshapiro sm_ldap_close(lmap); 349777349Sgshapiro 349877349Sgshapiro /* Mark all the maps that share the connection as closed */ 349964562Sgshapiro s = ldapmap_findconn(lmap); 350064562Sgshapiro 350177349Sgshapiro while (s->s_lmap != NULL) 350277349Sgshapiro { 350377349Sgshapiro MAP *smap = s->s_lmap; 350464562Sgshapiro 350577349Sgshapiro if (tTd(38, 2) && smap != map) 350690792Sgshapiro sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 350790792Sgshapiro map->map_mname, smap->map_mname); 350877349Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 350990792Sgshapiro lmap = (SM_LDAP_STRUCT *) smap->map_db1; 351064562Sgshapiro lmap->ldap_ld = NULL; 351177349Sgshapiro s->s_lmap = lmap->ldap_next; 351277349Sgshapiro lmap->ldap_next = NULL; 351343730Speter } 351438032Speter} 351538032Speter 351664562Sgshapiro# ifdef SUNET_ID 351743730Speter/* 351890792Sgshapiro** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 351942575Speter** This only makes sense at Stanford University. 352038032Speter*/ 352138032Speter 352290792Sgshapirostatic char * 352338032Spetersunet_id_hash(str) 352438032Speter char *str; 352538032Speter{ 352638032Speter char *p, *p_last; 352738032Speter 352838032Speter p = str; 352938032Speter p_last = p; 353038032Speter while (*p != '\0') 353138032Speter { 3532203004Sgshapiro if (isascii(*p) && (islower(*p) || isdigit(*p))) 353338032Speter { 353438032Speter *p_last = *p; 353538032Speter p_last++; 353638032Speter } 3537203004Sgshapiro else if (isascii(*p) && isupper(*p)) 353838032Speter { 353938032Speter *p_last = tolower(*p); 354038032Speter p_last++; 354138032Speter } 354238032Speter ++p; 354338032Speter } 354438032Speter if (*p_last != '\0') 354538032Speter *p_last = '\0'; 354664562Sgshapiro return str; 354738032Speter} 3548168515Sgshapiro# define SM_CONVERT_ID(str) sunet_id_hash(str) 3549168515Sgshapiro# else /* SUNET_ID */ 3550168515Sgshapiro# define SM_CONVERT_ID(str) makelower(str) 355164562Sgshapiro# endif /* SUNET_ID */ 355238032Speter 355338032Speter/* 355464562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 355538032Speter*/ 355638032Speter 355738032Speterchar * 355864562Sgshapiroldapmap_lookup(map, name, av, statp) 355938032Speter MAP *map; 356038032Speter char *name; 356138032Speter char **av; 356238032Speter int *statp; 356338032Speter{ 3564132943Sgshapiro int flags; 3565168515Sgshapiro int i; 356694334Sgshapiro int plen = 0; 356794334Sgshapiro int psize = 0; 356864562Sgshapiro int msgid; 356990792Sgshapiro int save_errno; 357090792Sgshapiro char *vp, *p; 357164562Sgshapiro char *result = NULL; 3572132943Sgshapiro SM_RPOOL_T *rpool; 357390792Sgshapiro SM_LDAP_STRUCT *lmap = NULL; 3574168515Sgshapiro char *argv[SM_LDAP_ARGS]; 3575157001Sgshapiro char keybuf[MAXKEY]; 3576168515Sgshapiro#if SM_LDAP_ARGS != MAX_MAP_ARGS 3577168515Sgshapiro# ERROR _SM_LDAP_ARGS must be the same as _MAX_MAP_ARGS 3578168515Sgshapiro#endif /* SM_LDAP_ARGS != MAX_MAP_ARGS */ 357938032Speter 3580168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3581168515Sgshapiro HASLDAPGETALIASBYNAME 3582168515Sgshapiro if (VendorCode == VENDOR_SUN && 3583168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3584168515Sgshapiro { 3585168515Sgshapiro int rc; 3586173340Sgshapiro#if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2) 3587173340Sgshapiro extern char *__getldapaliasbyname(); 3588173340Sgshapiro char *answer; 358938032Speter 3590173340Sgshapiro answer = __getldapaliasbyname(name, &rc); 3591173340Sgshapiro#else 3592173340Sgshapiro char answer[MAXNAME + 1]; 3593173340Sgshapiro 3594168515Sgshapiro rc = __getldapaliasbyname(name, answer, sizeof(answer)); 3595173340Sgshapiro#endif 3596168515Sgshapiro if (rc != 0) 3597168515Sgshapiro { 3598168515Sgshapiro if (tTd(38, 20)) 3599168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n", 3600168515Sgshapiro name, errno); 3601168515Sgshapiro *statp = EX_NOTFOUND; 3602168515Sgshapiro return NULL; 3603168515Sgshapiro } 3604168515Sgshapiro *statp = EX_OK; 3605168515Sgshapiro if (tTd(38, 20)) 3606168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name, 3607168515Sgshapiro answer); 3608168515Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3609168515Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 3610168515Sgshapiro else 3611168515Sgshapiro result = map_rewrite(map, answer, strlen(answer), av); 3612173340Sgshapiro#if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2) 3613173340Sgshapiro free(answer); 3614173340Sgshapiro#endif 3615168515Sgshapiro return result; 3616168515Sgshapiro } 3617168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3618168515Sgshapiro 361938032Speter /* Get ldap struct pointer from map */ 362090792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 362190792Sgshapiro sm_ldap_setopts(lmap->ldap_ld, lmap); 362238032Speter 3623168515Sgshapiro if (lmap->ldap_multi_args) 3624168515Sgshapiro { 3625168515Sgshapiro SM_REQUIRE(av != NULL); 3626168515Sgshapiro memset(argv, '\0', sizeof(argv)); 3627168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && av[i] != NULL; i++) 3628168515Sgshapiro { 3629168515Sgshapiro argv[i] = sm_strdup(av[i]); 3630168515Sgshapiro if (argv[i] == NULL) 3631168515Sgshapiro { 3632168515Sgshapiro int save_errno, j; 363338032Speter 3634168515Sgshapiro save_errno = errno; 3635168515Sgshapiro for (j = 0; j < i && argv[j] != NULL; j++) 3636168515Sgshapiro SM_FREE(argv[j]); 3637168515Sgshapiro *statp = EX_TEMPFAIL; 3638168515Sgshapiro errno = save_errno; 3639168515Sgshapiro return NULL; 3640168515Sgshapiro } 3641168515Sgshapiro 3642168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 3643168515Sgshapiro SM_CONVERT_ID(av[i]); 3644168515Sgshapiro } 3645168515Sgshapiro } 3646168515Sgshapiro else 364764562Sgshapiro { 3648168515Sgshapiro (void) sm_strlcpy(keybuf, name, sizeof(keybuf)); 3649168515Sgshapiro 3650168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 3651168515Sgshapiro SM_CONVERT_ID(keybuf); 365264562Sgshapiro } 365338032Speter 3654168515Sgshapiro if (tTd(38, 20)) 365538032Speter { 3656168515Sgshapiro if (lmap->ldap_multi_args) 3657168515Sgshapiro { 3658168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, argv)\n", 3659168515Sgshapiro map->map_mname); 3660168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS; i++) 3661168515Sgshapiro { 3662168515Sgshapiro sm_dprintf(" argv[%d] = %s\n", i, 3663168515Sgshapiro argv[i] == NULL ? "NULL" : argv[i]); 3664168515Sgshapiro } 3665168515Sgshapiro } 3666168515Sgshapiro else 3667168515Sgshapiro { 3668168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, %s)\n", 3669168515Sgshapiro map->map_mname, name); 3670168515Sgshapiro } 3671168515Sgshapiro } 3672168515Sgshapiro 3673168515Sgshapiro if (lmap->ldap_multi_args) 3674168515Sgshapiro { 3675168515Sgshapiro msgid = sm_ldap_search_m(lmap, argv); 3676168515Sgshapiro 3677168515Sgshapiro /* free the argv array and its content, no longer needed */ 3678168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && argv[i] != NULL; i++) 3679168515Sgshapiro SM_FREE(argv[i]); 3680168515Sgshapiro } 3681168515Sgshapiro else 3682168515Sgshapiro msgid = sm_ldap_search(lmap, keybuf); 3683168515Sgshapiro if (msgid == SM_LDAP_ERR) 3684168515Sgshapiro { 368590792Sgshapiro errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 368677349Sgshapiro save_errno = errno; 368764562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 368838032Speter { 3689168515Sgshapiro /* 3690168515Sgshapiro ** Do not include keybuf as this error may be shown 3691168515Sgshapiro ** to outsiders. 3692168515Sgshapiro */ 3693168515Sgshapiro 369464562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3695168515Sgshapiro syserr("Error in ldap_search in map %s", 3696168515Sgshapiro map->map_mname); 369764562Sgshapiro else 3698168515Sgshapiro syserr("451 4.3.5 Error in ldap_search in map %s", 3699168515Sgshapiro map->map_mname); 370038032Speter } 370164562Sgshapiro *statp = EX_TEMPFAIL; 370290792Sgshapiro switch (save_errno - E_LDAPBASE) 370390792Sgshapiro { 370494334Sgshapiro# ifdef LDAP_SERVER_DOWN 370590792Sgshapiro case LDAP_SERVER_DOWN: 370694334Sgshapiro# endif /* LDAP_SERVER_DOWN */ 370790792Sgshapiro case LDAP_TIMEOUT: 370890792Sgshapiro case LDAP_UNAVAILABLE: 370966494Sgshapiro /* server disappeared, try reopen on next search */ 371077349Sgshapiro ldapmap_close(map); 371190792Sgshapiro break; 371266494Sgshapiro } 371377349Sgshapiro errno = save_errno; 371464562Sgshapiro return NULL; 371564562Sgshapiro } 3716168515Sgshapiro#if SM_LDAP_ERROR_ON_MISSING_ARGS 3717168515Sgshapiro else if (msgid == SM_LDAP_ERR_ARG_MISS) 3718168515Sgshapiro { 3719168515Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3720168515Sgshapiro syserr("Error in ldap_search in map %s, too few arguments", 3721168515Sgshapiro map->map_mname); 3722168515Sgshapiro else 3723168515Sgshapiro syserr("554 5.3.5 Error in ldap_search in map %s, too few arguments", 3724168515Sgshapiro map->map_mname); 3725168515Sgshapiro *statp = EX_CONFIG; 3726168515Sgshapiro return NULL; 3727168515Sgshapiro } 3728168515Sgshapiro#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 372964562Sgshapiro 373064562Sgshapiro *statp = EX_NOTFOUND; 373164562Sgshapiro vp = NULL; 373264562Sgshapiro 3733132943Sgshapiro flags = 0; 3734132943Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 3735132943Sgshapiro flags |= SM_LDAP_SINGLEMATCH; 3736132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3737132943Sgshapiro flags |= SM_LDAP_MATCHONLY; 3738157001Sgshapiro# if _FFR_LDAP_SINGLEDN 3739157001Sgshapiro if (bitset(MF_SINGLEDN, map->map_mflags)) 3740157001Sgshapiro flags |= SM_LDAP_SINGLEDN; 3741157001Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 374290792Sgshapiro 3743132943Sgshapiro /* Create an rpool for search related memory usage */ 3744132943Sgshapiro rpool = sm_rpool_new_x(NULL); 374590792Sgshapiro 3746132943Sgshapiro p = NULL; 3747132943Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 3748132943Sgshapiro rpool, &p, &plen, &psize, NULL); 3749132943Sgshapiro save_errno = errno; 375090792Sgshapiro 3751132943Sgshapiro /* Copy result so rpool can be freed */ 3752132943Sgshapiro if (*statp == EX_OK && p != NULL) 3753132943Sgshapiro vp = newstr(p); 3754132943Sgshapiro sm_rpool_free(rpool); 375590792Sgshapiro 3756132943Sgshapiro /* need to restart LDAP connection? */ 3757132943Sgshapiro if (*statp == EX_RESTART) 375864562Sgshapiro { 3759132943Sgshapiro *statp = EX_TEMPFAIL; 3760132943Sgshapiro ldapmap_close(map); 376138032Speter } 376238032Speter 3763132943Sgshapiro errno = save_errno; 3764132943Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 376538032Speter { 376664562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 376764562Sgshapiro { 376864562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3769244833Sgshapiro syserr("Error getting LDAP results, map=%s, name=%s", 3770244833Sgshapiro map->map_mname, name); 377164562Sgshapiro else 3772244833Sgshapiro syserr("451 4.3.5 Error getting LDAP results, map=%s, name=%s", 3773244833Sgshapiro map->map_mname, name); 377464562Sgshapiro } 377577349Sgshapiro errno = save_errno; 377664562Sgshapiro return NULL; 377738032Speter } 377890792Sgshapiro 377964562Sgshapiro /* Did we match anything? */ 378071345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 378164562Sgshapiro return NULL; 378238032Speter 378364562Sgshapiro if (*statp == EX_OK) 378464562Sgshapiro { 378564562Sgshapiro if (LogLevel > 9) 378664562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 3787244833Sgshapiro "ldap=%s, %.100s=>%s", map->map_mname, name, 378871345Sgshapiro vp == NULL ? "<NULL>" : vp); 378964562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 379064562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 379164562Sgshapiro else 379271345Sgshapiro { 379371345Sgshapiro /* vp != NULL according to test above */ 379464562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 379571345Sgshapiro } 379671345Sgshapiro if (vp != NULL) 379790792Sgshapiro sm_free(vp); /* XXX */ 379864562Sgshapiro } 379964562Sgshapiro return result; 380038032Speter} 380138032Speter 380238032Speter/* 380364562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 380464562Sgshapiro** 380564562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 380666494Sgshapiro** secret, and PID so we don't have multiple connections open to 380766494Sgshapiro** the same server for different maps. Need a separate connection 380866494Sgshapiro** per PID since a parent process may close the map before the 380966494Sgshapiro** child is done with it. 381064562Sgshapiro** 381164562Sgshapiro** Parameters: 381264562Sgshapiro** lmap -- LDAP map information 381364562Sgshapiro** 381464562Sgshapiro** Returns: 381564562Sgshapiro** Symbol table entry for the LDAP connection. 381638032Speter*/ 381738032Speter 381864562Sgshapirostatic STAB * 381964562Sgshapiroldapmap_findconn(lmap) 382090792Sgshapiro SM_LDAP_STRUCT *lmap; 382138032Speter{ 382294334Sgshapiro char *format; 382364562Sgshapiro char *nbuf; 3824132943Sgshapiro char *id; 382590792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 382638032Speter 3827132943Sgshapiro if (lmap->ldap_host != NULL) 3828132943Sgshapiro id = lmap->ldap_host; 3829132943Sgshapiro else if (lmap->ldap_uri != NULL) 3830132943Sgshapiro id = lmap->ldap_uri; 3831132943Sgshapiro else 3832132943Sgshapiro id = "localhost"; 3833132943Sgshapiro 383494334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 383594334Sgshapiro nbuf = sm_stringf_x(format, 3836132943Sgshapiro id, 383790792Sgshapiro CONDELSE, 383890792Sgshapiro lmap->ldap_port, 383990792Sgshapiro CONDELSE, 384094334Sgshapiro lmap->ldap_version, 384194334Sgshapiro CONDELSE, 384290792Sgshapiro (lmap->ldap_binddn == NULL ? "" 384390792Sgshapiro : lmap->ldap_binddn), 384490792Sgshapiro CONDELSE, 384590792Sgshapiro (lmap->ldap_secret == NULL ? "" 384690792Sgshapiro : lmap->ldap_secret), 384790792Sgshapiro (int) CurrentPid); 384890792Sgshapiro SM_TRY 384990792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 385090792Sgshapiro SM_FINALLY 385190792Sgshapiro sm_free(nbuf); 385290792Sgshapiro SM_END_TRY 385364562Sgshapiro return s; 385464562Sgshapiro} 385538032Speter/* 385664562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 385764562Sgshapiro*/ 385838032Speter 385990792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 386064562Sgshapiro{ 386164562Sgshapiro { "none", LDAP_AUTH_NONE }, 386264562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 386364562Sgshapiro# ifdef LDAP_AUTH_KRBV4 386464562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 386564562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 386664562Sgshapiro { NULL, 0 } 386764562Sgshapiro}; 386838032Speter 386990792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 387064562Sgshapiro{ 387164562Sgshapiro { "never", LDAP_DEREF_NEVER }, 387264562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 387364562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 387464562Sgshapiro { "find", LDAP_DEREF_FINDING }, 387564562Sgshapiro { NULL, 0 } 387664562Sgshapiro}; 387738032Speter 387890792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 387964562Sgshapiro{ 388064562Sgshapiro { "base", LDAP_SCOPE_BASE }, 388164562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 388264562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 388364562Sgshapiro { NULL, 0 } 388464562Sgshapiro}; 388538032Speter 388664562Sgshapirobool 388764562Sgshapiroldapmap_parseargs(map, args) 388864562Sgshapiro MAP *map; 388964562Sgshapiro char *args; 389064562Sgshapiro{ 389190792Sgshapiro bool secretread = true; 3892132943Sgshapiro bool attrssetup = false; 389364562Sgshapiro int i; 389464562Sgshapiro register char *p = args; 389590792Sgshapiro SM_LDAP_STRUCT *lmap; 389664562Sgshapiro struct lamvalues *lam; 389764562Sgshapiro struct ladvalues *lad; 389864562Sgshapiro struct lssvalues *lss; 389990792Sgshapiro char ldapfilt[MAXLINE]; 390064562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 390164562Sgshapiro 390264562Sgshapiro /* Get ldap struct pointer from map */ 390390792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 390464562Sgshapiro 390564562Sgshapiro /* Check if setting the initial LDAP defaults */ 390664562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 390764562Sgshapiro { 390890792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 3909168515Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof(*lmap)); 391064562Sgshapiro if (LDAPDefaults == NULL) 391190792Sgshapiro sm_ldap_clear(lmap); 391264562Sgshapiro else 391364562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 391464562Sgshapiro } 391564562Sgshapiro 391664562Sgshapiro /* there is no check whether there is really an argument */ 391764562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 391864562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 391990792Sgshapiro 392090792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 392190792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 392290792Sgshapiro { 392390792Sgshapiro /* Comma separate if used as an alias file */ 392490792Sgshapiro map->map_coldelim = ','; 392590792Sgshapiro if (*args == '\0') 392690792Sgshapiro { 392790792Sgshapiro int n; 392890792Sgshapiro char *lc; 392990792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 393090792Sgshapiro char lcbuf[MAXLINE]; 393190792Sgshapiro 393290792Sgshapiro /* Get $j */ 3933168515Sgshapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope); 393490792Sgshapiro if (jbuf[0] == '\0') 393590792Sgshapiro { 393690792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 3937168515Sgshapiro sizeof(jbuf)); 393890792Sgshapiro } 393990792Sgshapiro 394090792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 394190792Sgshapiro if (lc == NULL) 394290792Sgshapiro lc = ""; 394390792Sgshapiro else 394490792Sgshapiro { 3945168515Sgshapiro expand(lc, lcbuf, sizeof(lcbuf), CurEnv); 394690792Sgshapiro lc = lcbuf; 394790792Sgshapiro } 394890792Sgshapiro 3949168515Sgshapiro n = sm_snprintf(ldapfilt, sizeof(ldapfilt), 395090792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 395190792Sgshapiro lc, jbuf); 3952168515Sgshapiro if (n >= sizeof(ldapfilt)) 395390792Sgshapiro { 395490792Sgshapiro syserr("%s: Default LDAP string too long", 395590792Sgshapiro map->map_mname); 395690792Sgshapiro return false; 395790792Sgshapiro } 395890792Sgshapiro 395990792Sgshapiro /* default args for an alias LDAP entry */ 396090792Sgshapiro lmap->ldap_filter = ldapfilt; 3961132943Sgshapiro lmap->ldap_attr[0] = "objectClass"; 3962132943Sgshapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 3963132943Sgshapiro lmap->ldap_attr_needobjclass[0] = NULL; 3964132943Sgshapiro lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 3965132943Sgshapiro lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 3966132943Sgshapiro lmap->ldap_attr_needobjclass[1] = NULL; 3967132943Sgshapiro lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 3968132943Sgshapiro lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 3969132943Sgshapiro lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 3970132943Sgshapiro lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 3971132943Sgshapiro lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 3972132943Sgshapiro lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 3973132943Sgshapiro lmap->ldap_attr[4] = NULL; 3974132943Sgshapiro lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 3975132943Sgshapiro lmap->ldap_attr_needobjclass[4] = NULL; 3976132943Sgshapiro attrssetup = true; 397790792Sgshapiro } 397890792Sgshapiro } 397990792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 398090792Sgshapiro { 398190792Sgshapiro /* Space separate if used as a file class file */ 398290792Sgshapiro map->map_coldelim = ' '; 398390792Sgshapiro } 398490792Sgshapiro 3985203004Sgshapiro# if _FFR_LDAP_NETWORK_TIMEOUT 3986203004Sgshapiro lmap->ldap_networktmo = 120; 3987203004Sgshapiro# endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 3988203004Sgshapiro 398938032Speter for (;;) 399038032Speter { 399138032Speter while (isascii(*p) && isspace(*p)) 399238032Speter p++; 399338032Speter if (*p != '-') 399438032Speter break; 399538032Speter switch (*++p) 399638032Speter { 3997173340Sgshapiro case 'A': 3998173340Sgshapiro map->map_mflags |= MF_APPEND; 399938032Speter break; 400038032Speter 4001173340Sgshapiro case 'a': 4002173340Sgshapiro map->map_app = ++p; 400338032Speter break; 400438032Speter 4005173340Sgshapiro case 'D': 4006173340Sgshapiro map->map_mflags |= MF_DEFER; 400738032Speter break; 400838032Speter 400938032Speter case 'f': 401038032Speter map->map_mflags |= MF_NOFOLDCASE; 401138032Speter break; 401238032Speter 401338032Speter case 'm': 401438032Speter map->map_mflags |= MF_MATCHONLY; 401538032Speter break; 401638032Speter 4017173340Sgshapiro case 'N': 4018173340Sgshapiro map->map_mflags |= MF_INCLNULL; 4019173340Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 402038032Speter break; 402138032Speter 4022173340Sgshapiro case 'O': 4023173340Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 4024173340Sgshapiro break; 4025173340Sgshapiro 4026173340Sgshapiro case 'o': 4027173340Sgshapiro map->map_mflags |= MF_OPTIONAL; 4028173340Sgshapiro break; 4029173340Sgshapiro 403038032Speter case 'q': 403138032Speter map->map_mflags |= MF_KEEPQUOTES; 403238032Speter break; 403338032Speter 4034173340Sgshapiro case 'S': 4035173340Sgshapiro map->map_spacesub = *++p; 403638032Speter break; 403738032Speter 403838032Speter case 'T': 403938032Speter map->map_tapp = ++p; 404038032Speter break; 404138032Speter 404264562Sgshapiro case 't': 404364562Sgshapiro map->map_mflags |= MF_NODEFER; 404464562Sgshapiro break; 404564562Sgshapiro 404664562Sgshapiro case 'z': 404764562Sgshapiro if (*++p != '\\') 404864562Sgshapiro map->map_coldelim = *p; 404964562Sgshapiro else 405064562Sgshapiro { 405164562Sgshapiro switch (*++p) 405264562Sgshapiro { 405364562Sgshapiro case 'n': 405464562Sgshapiro map->map_coldelim = '\n'; 405564562Sgshapiro break; 405664562Sgshapiro 405764562Sgshapiro case 't': 405864562Sgshapiro map->map_coldelim = '\t'; 405964562Sgshapiro break; 406064562Sgshapiro 406164562Sgshapiro default: 406264562Sgshapiro map->map_coldelim = '\\'; 406364562Sgshapiro } 406464562Sgshapiro } 406564562Sgshapiro break; 406664562Sgshapiro 406764562Sgshapiro /* Start of ldapmap specific args */ 4068173340Sgshapiro case '1': 4069173340Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 4070173340Sgshapiro break; 407190792Sgshapiro 4072173340Sgshapiro# if _FFR_LDAP_SINGLEDN 4073173340Sgshapiro case '2': 4074173340Sgshapiro map->map_mflags |= MF_SINGLEDN; 4075173340Sgshapiro break; 4076173340Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 407790792Sgshapiro 4078173340Sgshapiro case 'b': /* search base */ 4079173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4080173340Sgshapiro continue; 4081173340Sgshapiro lmap->ldap_base = p; 4082173340Sgshapiro break; 4083173340Sgshapiro 4084173340Sgshapiro# if _FFR_LDAP_NETWORK_TIMEOUT 4085173340Sgshapiro case 'c': /* network (connect) timeout */ 4086173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4087173340Sgshapiro continue; 4088203004Sgshapiro lmap->ldap_networktmo = atoi(p); 4089173340Sgshapiro break; 4090173340Sgshapiro# endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 4091173340Sgshapiro 4092173340Sgshapiro case 'd': /* Dn to bind to server as */ 4093173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4094173340Sgshapiro continue; 4095173340Sgshapiro lmap->ldap_binddn = p; 4096173340Sgshapiro break; 4097173340Sgshapiro 4098173340Sgshapiro case 'H': /* Use LDAP URI */ 4099173340Sgshapiro# if !USE_LDAP_INIT 4100173340Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 4101173340Sgshapiro map->map_mname); 4102173340Sgshapiro return false; 4103173340Sgshapiro# else /* !USE_LDAP_INIT */ 4104173340Sgshapiro if (lmap->ldap_host != NULL) 4105173340Sgshapiro { 4106173340Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 4107173340Sgshapiro map->map_mname); 4108173340Sgshapiro return false; 410990792Sgshapiro } 4110173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4111173340Sgshapiro continue; 4112173340Sgshapiro lmap->ldap_uri = p; 411390792Sgshapiro break; 4114173340Sgshapiro# endif /* !USE_LDAP_INIT */ 411590792Sgshapiro 4116173340Sgshapiro case 'h': /* ldap host */ 4117173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4118173340Sgshapiro continue; 4119173340Sgshapiro if (lmap->ldap_uri != NULL) 4120173340Sgshapiro { 4121173340Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 4122173340Sgshapiro map->map_mname); 4123173340Sgshapiro return false; 4124173340Sgshapiro } 4125173340Sgshapiro lmap->ldap_host = p; 4126173340Sgshapiro break; 4127173340Sgshapiro 4128173340Sgshapiro case 'K': 4129173340Sgshapiro lmap->ldap_multi_args = true; 4130173340Sgshapiro break; 4131173340Sgshapiro 413238032Speter case 'k': /* search field */ 413338032Speter while (isascii(*++p) && isspace(*p)) 413438032Speter continue; 413564562Sgshapiro lmap->ldap_filter = p; 413638032Speter break; 413738032Speter 4138173340Sgshapiro case 'l': /* time limit */ 413938032Speter while (isascii(*++p) && isspace(*p)) 414038032Speter continue; 4141173340Sgshapiro lmap->ldap_timelimit = atoi(p); 4142173340Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 414338032Speter break; 414438032Speter 4145173340Sgshapiro case 'M': /* Method for binding */ 4146173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4147173340Sgshapiro continue; 4148173340Sgshapiro 4149173340Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 4150173340Sgshapiro p += 10; 4151173340Sgshapiro 4152173340Sgshapiro for (lam = LDAPAuthMethods; 4153173340Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 4154173340Sgshapiro { 4155173340Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 4156173340Sgshapiro strlen(lam->lam_name)) == 0) 4157173340Sgshapiro break; 4158173340Sgshapiro } 4159173340Sgshapiro if (lam->lam_name != NULL) 4160173340Sgshapiro lmap->ldap_method = lam->lam_code; 4161173340Sgshapiro else 4162173340Sgshapiro { 4163173340Sgshapiro /* bad config line */ 4164173340Sgshapiro if (!bitset(MCF_OPTFILE, 4165173340Sgshapiro map->map_class->map_cflags)) 4166173340Sgshapiro { 4167173340Sgshapiro char *ptr; 4168173340Sgshapiro 4169173340Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 4170173340Sgshapiro *ptr = '\0'; 4171173340Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 4172173340Sgshapiro p, map->map_mname); 4173173340Sgshapiro if (ptr != NULL) 4174173340Sgshapiro *ptr = ' '; 4175173340Sgshapiro return false; 4176173340Sgshapiro } 4177173340Sgshapiro } 417864562Sgshapiro break; 417964562Sgshapiro 4180173340Sgshapiro case 'n': /* retrieve attribute names only */ 4181173340Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 4182157001Sgshapiro break; 4183157001Sgshapiro 4184173340Sgshapiro /* 4185173340Sgshapiro ** This is a string that is dependent on the 4186173340Sgshapiro ** method used defined by 'M'. 4187173340Sgshapiro */ 4188173340Sgshapiro 4189173340Sgshapiro case 'P': /* Secret password for binding */ 4190173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4191173340Sgshapiro continue; 4192173340Sgshapiro lmap->ldap_secret = p; 4193173340Sgshapiro secretread = false; 4194173340Sgshapiro break; 4195173340Sgshapiro 4196173340Sgshapiro case 'p': /* ldap port */ 4197173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4198173340Sgshapiro continue; 4199173340Sgshapiro lmap->ldap_port = atoi(p); 4200173340Sgshapiro break; 4201173340Sgshapiro 420238032Speter /* args stolen from ldapsearch.c */ 420338032Speter case 'R': /* don't auto chase referrals */ 420464562Sgshapiro# ifdef LDAP_REFERRALS 420538032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 420664562Sgshapiro# else /* LDAP_REFERRALS */ 420790792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 420864562Sgshapiro# endif /* LDAP_REFERRALS */ 420938032Speter break; 421038032Speter 421164562Sgshapiro case 'r': /* alias dereferencing */ 421264562Sgshapiro while (isascii(*++p) && isspace(*p)) 421364562Sgshapiro continue; 421464562Sgshapiro 421590792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 421664562Sgshapiro p += 11; 421764562Sgshapiro 421864562Sgshapiro for (lad = LDAPAliasDereference; 421964562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 422038032Speter { 422190792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 422290792Sgshapiro strlen(lad->lad_name)) == 0) 422364562Sgshapiro break; 422438032Speter } 422564562Sgshapiro if (lad->lad_name != NULL) 422664562Sgshapiro lmap->ldap_deref = lad->lad_code; 422764562Sgshapiro else 422838032Speter { 422964562Sgshapiro /* bad config line */ 423064562Sgshapiro if (!bitset(MCF_OPTFILE, 423164562Sgshapiro map->map_class->map_cflags)) 423264562Sgshapiro { 423364562Sgshapiro char *ptr; 423464562Sgshapiro 423564562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 423664562Sgshapiro *ptr = '\0'; 423773188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 423864562Sgshapiro p, map->map_mname); 423964562Sgshapiro if (ptr != NULL) 424064562Sgshapiro *ptr = ' '; 424190792Sgshapiro return false; 424264562Sgshapiro } 424338032Speter } 424464562Sgshapiro break; 424564562Sgshapiro 424664562Sgshapiro case 's': /* search scope */ 424764562Sgshapiro while (isascii(*++p) && isspace(*p)) 424864562Sgshapiro continue; 424964562Sgshapiro 425090792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 425164562Sgshapiro p += 11; 425264562Sgshapiro 425364562Sgshapiro for (lss = LDAPSearchScope; 425464562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 425538032Speter { 425690792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 425790792Sgshapiro strlen(lss->lss_name)) == 0) 425864562Sgshapiro break; 425938032Speter } 426064562Sgshapiro if (lss->lss_name != NULL) 426164562Sgshapiro lmap->ldap_scope = lss->lss_code; 426238032Speter else 426364562Sgshapiro { 426464562Sgshapiro /* bad config line */ 426564562Sgshapiro if (!bitset(MCF_OPTFILE, 426664562Sgshapiro map->map_class->map_cflags)) 426738032Speter { 426838032Speter char *ptr; 426938032Speter 427038032Speter if ((ptr = strchr(p, ' ')) != NULL) 427138032Speter *ptr = '\0'; 427273188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 427338032Speter p, map->map_mname); 427438032Speter if (ptr != NULL) 427538032Speter *ptr = ' '; 427690792Sgshapiro return false; 427738032Speter } 427838032Speter } 427938032Speter break; 428038032Speter 4281173340Sgshapiro case 'V': 4282173340Sgshapiro if (*++p != '\\') 4283173340Sgshapiro lmap->ldap_attrsep = *p; 428464562Sgshapiro else 428564562Sgshapiro { 4286173340Sgshapiro switch (*++p) 428764562Sgshapiro { 4288173340Sgshapiro case 'n': 4289173340Sgshapiro lmap->ldap_attrsep = '\n'; 4290173340Sgshapiro break; 429164562Sgshapiro 4292173340Sgshapiro case 't': 4293173340Sgshapiro lmap->ldap_attrsep = '\t'; 4294173340Sgshapiro break; 4295173340Sgshapiro 4296173340Sgshapiro default: 4297173340Sgshapiro lmap->ldap_attrsep = '\\'; 429864562Sgshapiro } 429964562Sgshapiro } 430064562Sgshapiro break; 430164562Sgshapiro 4302173340Sgshapiro case 'v': /* attr to return */ 430394334Sgshapiro while (isascii(*++p) && isspace(*p)) 430494334Sgshapiro continue; 4305173340Sgshapiro lmap->ldap_attr[0] = p; 4306173340Sgshapiro lmap->ldap_attr[1] = NULL; 430794334Sgshapiro break; 430894334Sgshapiro 430994334Sgshapiro case 'w': 431094334Sgshapiro /* -w should be for passwd, -P should be for version */ 431194334Sgshapiro while (isascii(*++p) && isspace(*p)) 431294334Sgshapiro continue; 431394334Sgshapiro lmap->ldap_version = atoi(p); 4314132943Sgshapiro# ifdef LDAP_VERSION_MAX 431594334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 431694334Sgshapiro { 431794334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 431894334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 431994334Sgshapiro map->map_mname); 432094334Sgshapiro return false; 432194334Sgshapiro } 4322132943Sgshapiro# endif /* LDAP_VERSION_MAX */ 4323132943Sgshapiro# ifdef LDAP_VERSION_MIN 432494334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 432594334Sgshapiro { 432694334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 432794334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 432894334Sgshapiro map->map_mname); 432994334Sgshapiro return false; 433094334Sgshapiro } 4331132943Sgshapiro# endif /* LDAP_VERSION_MIN */ 433294334Sgshapiro break; 433394334Sgshapiro 4334173340Sgshapiro case 'Z': 4335173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4336173340Sgshapiro continue; 4337173340Sgshapiro lmap->ldap_sizelimit = atoi(p); 4338168515Sgshapiro break; 4339168515Sgshapiro 434064562Sgshapiro default: 434164562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 434264562Sgshapiro break; 434338032Speter } 434438032Speter 434564562Sgshapiro /* need to account for quoted strings here */ 434664562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 434738032Speter { 434838032Speter if (*p == '"') 434938032Speter { 435038032Speter while (*++p != '"' && *p != '\0') 435138032Speter continue; 435238032Speter if (*p != '\0') 435338032Speter p++; 435438032Speter } 435538032Speter else 435638032Speter p++; 435738032Speter } 435838032Speter 435938032Speter if (*p != '\0') 436038032Speter *p++ = '\0'; 436138032Speter } 436238032Speter 436338032Speter if (map->map_app != NULL) 436464562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 436538032Speter if (map->map_tapp != NULL) 436664562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 436738032Speter 436838032Speter /* 436942575Speter ** We need to swallow up all the stuff into a struct 437042575Speter ** and dump it into map->map_dbptr1 437138032Speter */ 437238032Speter 4373132943Sgshapiro if (lmap->ldap_host != NULL && 437464562Sgshapiro (LDAPDefaults == NULL || 437564562Sgshapiro LDAPDefaults == lmap || 4376132943Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 4377132943Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 4378132943Sgshapiro map->map_domain = lmap->ldap_host; 437964562Sgshapiro 4380132943Sgshapiro if (lmap->ldap_uri != NULL && 4381132943Sgshapiro (LDAPDefaults == NULL || 4382132943Sgshapiro LDAPDefaults == lmap || 4383132943Sgshapiro LDAPDefaults->ldap_uri != lmap->ldap_uri)) 4384132943Sgshapiro lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 4385132943Sgshapiro map->map_domain = lmap->ldap_uri; 4386132943Sgshapiro 438764562Sgshapiro if (lmap->ldap_binddn != NULL && 438864562Sgshapiro (LDAPDefaults == NULL || 438964562Sgshapiro LDAPDefaults == lmap || 439064562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 439164562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 439264562Sgshapiro 439364562Sgshapiro if (lmap->ldap_secret != NULL && 439464562Sgshapiro (LDAPDefaults == NULL || 439564562Sgshapiro LDAPDefaults == lmap || 439664562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 439738032Speter { 439890792Sgshapiro SM_FILE_T *sfd; 439964562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 440038032Speter 440164562Sgshapiro if (DontLockReadFiles) 440264562Sgshapiro sff |= SFF_NOLOCK; 440338032Speter 440464562Sgshapiro /* need to use method to map secret to passwd string */ 440564562Sgshapiro switch (lmap->ldap_method) 440664562Sgshapiro { 440764562Sgshapiro case LDAP_AUTH_NONE: 440864562Sgshapiro /* Do nothing */ 440964562Sgshapiro break; 441038032Speter 441164562Sgshapiro case LDAP_AUTH_SIMPLE: 441238032Speter 441364562Sgshapiro /* 441464562Sgshapiro ** Secret is the name of a file with 441564562Sgshapiro ** the first line as the password. 441664562Sgshapiro */ 441764562Sgshapiro 441864562Sgshapiro /* Already read in the secret? */ 441964562Sgshapiro if (secretread) 442064562Sgshapiro break; 442164562Sgshapiro 442264562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 442364562Sgshapiro O_RDONLY, 0, sff); 442464562Sgshapiro if (sfd == NULL) 442564562Sgshapiro { 442664562Sgshapiro syserr("LDAP map: cannot open secret %s", 442764562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 442890792Sgshapiro return false; 442964562Sgshapiro } 4430168515Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof(m_tmp), 443166494Sgshapiro sfd, TimeOuts.to_fileopen, 443266494Sgshapiro "ldapmap_parseargs"); 443390792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 443498121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 443598121Sgshapiro { 443698121Sgshapiro syserr("LDAP map: secret in %s too long", 443798121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 443898121Sgshapiro return false; 443998121Sgshapiro } 444064562Sgshapiro if (lmap->ldap_secret != NULL && 444164562Sgshapiro strlen(m_tmp) > 0) 444264562Sgshapiro { 444364562Sgshapiro /* chomp newline */ 444464562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 444564562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 444664562Sgshapiro 444764562Sgshapiro lmap->ldap_secret = m_tmp; 444864562Sgshapiro } 444964562Sgshapiro break; 445064562Sgshapiro 445164562Sgshapiro# ifdef LDAP_AUTH_KRBV4 445264562Sgshapiro case LDAP_AUTH_KRBV4: 445364562Sgshapiro 445464562Sgshapiro /* 445564562Sgshapiro ** Secret is where the ticket file is 445664562Sgshapiro ** stashed 445764562Sgshapiro */ 445864562Sgshapiro 4459168515Sgshapiro (void) sm_snprintf(m_tmp, sizeof(m_tmp), 446090792Sgshapiro "KRBTKFILE=%s", 446190792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 446264562Sgshapiro lmap->ldap_secret = m_tmp; 446364562Sgshapiro break; 446464562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 446564562Sgshapiro 446664562Sgshapiro default: /* Should NEVER get here */ 446764562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 446890792Sgshapiro return false; 446990792Sgshapiro /* NOTREACHED */ 447064562Sgshapiro break; 447164562Sgshapiro } 447238032Speter } 447338032Speter 447464562Sgshapiro if (lmap->ldap_secret != NULL && 447564562Sgshapiro (LDAPDefaults == NULL || 447664562Sgshapiro LDAPDefaults == lmap || 447764562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 447864562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 447938032Speter 448064562Sgshapiro if (lmap->ldap_base != NULL && 448164562Sgshapiro (LDAPDefaults == NULL || 448264562Sgshapiro LDAPDefaults == lmap || 448364562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 448464562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 448564562Sgshapiro 448664562Sgshapiro /* 448764562Sgshapiro ** Save the server from extra work. If request is for a single 448864562Sgshapiro ** match, tell the server to only return enough records to 448964562Sgshapiro ** determine if there is a single match or not. This can not 449064562Sgshapiro ** be one since the server would only return one and we wouldn't 449164562Sgshapiro ** know if there were others available. 449264562Sgshapiro */ 449364562Sgshapiro 449464562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 449564562Sgshapiro lmap->ldap_sizelimit = 2; 449664562Sgshapiro 449764562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 449864562Sgshapiro if (lmap == LDAPDefaults) 449990792Sgshapiro return true; 450064562Sgshapiro 450164562Sgshapiro if (lmap->ldap_filter != NULL) 450264562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 450338032Speter else 450438032Speter { 450538032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 450638032Speter { 450738032Speter syserr("No filter given in map %s", map->map_mname); 450890792Sgshapiro return false; 450938032Speter } 451038032Speter } 451164562Sgshapiro 4512132943Sgshapiro if (!attrssetup && lmap->ldap_attr[0] != NULL) 451338032Speter { 451490792Sgshapiro bool recurse = false; 451594334Sgshapiro bool normalseen = false; 451690792Sgshapiro 451764562Sgshapiro i = 0; 451864562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 451964562Sgshapiro lmap->ldap_attr[0] = NULL; 452064562Sgshapiro 452194334Sgshapiro /* Prime the attr list with the objectClass attribute */ 452294334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 452394334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 452494334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 452594334Sgshapiro i++; 452694334Sgshapiro 452764562Sgshapiro while (p != NULL) 452838032Speter { 452964562Sgshapiro char *v; 453064562Sgshapiro 453164562Sgshapiro while (isascii(*p) && isspace(*p)) 453264562Sgshapiro p++; 453364562Sgshapiro if (*p == '\0') 453464562Sgshapiro break; 453564562Sgshapiro v = p; 453664562Sgshapiro p = strchr(v, ','); 453764562Sgshapiro if (p != NULL) 453864562Sgshapiro *p++ = '\0'; 453964562Sgshapiro 454071345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 454164562Sgshapiro { 454264562Sgshapiro syserr("Too many return attributes in %s (max %d)", 454364562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 454490792Sgshapiro return false; 454564562Sgshapiro } 454664562Sgshapiro if (*v != '\0') 454790792Sgshapiro { 454894334Sgshapiro int j; 454994334Sgshapiro int use; 455090792Sgshapiro char *type; 455194334Sgshapiro char *needobjclass; 455290792Sgshapiro 455390792Sgshapiro type = strchr(v, ':'); 455490792Sgshapiro if (type != NULL) 455594334Sgshapiro { 455690792Sgshapiro *type++ = '\0'; 455794334Sgshapiro needobjclass = strchr(type, ':'); 455894334Sgshapiro if (needobjclass != NULL) 455994334Sgshapiro *needobjclass++ = '\0'; 456094334Sgshapiro } 456194334Sgshapiro else 456294334Sgshapiro { 456394334Sgshapiro needobjclass = NULL; 456494334Sgshapiro } 456590792Sgshapiro 456694334Sgshapiro use = i; 456790792Sgshapiro 456894334Sgshapiro /* allow override on "objectClass" type */ 456994334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 457094334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 457190792Sgshapiro { 457294334Sgshapiro use = 0; 457394334Sgshapiro } 457494334Sgshapiro else 457594334Sgshapiro { 457694334Sgshapiro /* 457794334Sgshapiro ** Don't add something to attribute 457894334Sgshapiro ** list twice. 457994334Sgshapiro */ 458094334Sgshapiro 458194334Sgshapiro for (j = 1; j < i; j++) 458290792Sgshapiro { 458394334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 458494334Sgshapiro { 458594334Sgshapiro syserr("Duplicate attribute (%s) in %s", 458694334Sgshapiro v, map->map_mname); 458794334Sgshapiro return false; 458894334Sgshapiro } 458990792Sgshapiro } 459094334Sgshapiro 459194334Sgshapiro lmap->ldap_attr[use] = newstr(v); 459294334Sgshapiro if (needobjclass != NULL && 459394334Sgshapiro *needobjclass != '\0' && 459494334Sgshapiro *needobjclass != '*') 459590792Sgshapiro { 459694334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 459794334Sgshapiro } 459894334Sgshapiro else 459994334Sgshapiro { 460094334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 460194334Sgshapiro } 460294334Sgshapiro 460394334Sgshapiro } 460494334Sgshapiro 460594334Sgshapiro if (type != NULL && *type != '\0') 460694334Sgshapiro { 460794334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 460894334Sgshapiro { 460990792Sgshapiro recurse = true; 461094334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 461190792Sgshapiro } 461290792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 461390792Sgshapiro { 461490792Sgshapiro recurse = true; 461594334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 461690792Sgshapiro } 461790792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 461890792Sgshapiro { 461990792Sgshapiro recurse = true; 462094334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 462190792Sgshapiro } 462294334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 462390792Sgshapiro { 462494334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 462594334Sgshapiro normalseen = true; 462690792Sgshapiro } 462790792Sgshapiro else 462890792Sgshapiro { 462990792Sgshapiro syserr("Unknown attribute type (%s) in %s", 463090792Sgshapiro type, map->map_mname); 463190792Sgshapiro return false; 463290792Sgshapiro } 463390792Sgshapiro } 463490792Sgshapiro else 463594334Sgshapiro { 463694334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 463794334Sgshapiro normalseen = true; 463894334Sgshapiro } 463990792Sgshapiro i++; 464090792Sgshapiro } 464138032Speter } 464264562Sgshapiro lmap->ldap_attr[i] = NULL; 4643141858Sgshapiro 4644141858Sgshapiro /* Set in case needed in future code */ 4645132943Sgshapiro attrssetup = true; 4646141858Sgshapiro 464794334Sgshapiro if (recurse && !normalseen) 464890792Sgshapiro { 464994334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 465090792Sgshapiro map->map_mname); 465190792Sgshapiro return false; 465290792Sgshapiro } 465390792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 465490792Sgshapiro { 465590792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 465690792Sgshapiro map->map_mname); 465790792Sgshapiro return false; 465890792Sgshapiro } 465938032Speter } 466038032Speter map->map_db1 = (ARBPTR_T) lmap; 466190792Sgshapiro return true; 466238032Speter} 466338032Speter 466464562Sgshapiro/* 466564562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 466664562Sgshapiro** 466764562Sgshapiro** Parameters: 466864562Sgshapiro** spec -- map argument string from LDAPDefaults option 466964562Sgshapiro** 467064562Sgshapiro** Returns: 467164562Sgshapiro** None. 467264562Sgshapiro*/ 467364562Sgshapiro 467464562Sgshapirovoid 467564562Sgshapiroldapmap_set_defaults(spec) 467664562Sgshapiro char *spec; 467764562Sgshapiro{ 467873188Sgshapiro STAB *class; 467964562Sgshapiro MAP map; 468064562Sgshapiro 468164562Sgshapiro /* Allocate and set the default values */ 468264562Sgshapiro if (LDAPDefaults == NULL) 4683168515Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof(*LDAPDefaults)); 468490792Sgshapiro sm_ldap_clear(LDAPDefaults); 468564562Sgshapiro 4686168515Sgshapiro memset(&map, '\0', sizeof(map)); 468773188Sgshapiro 468873188Sgshapiro /* look up the class */ 468973188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 469073188Sgshapiro if (class == NULL) 469173188Sgshapiro { 469273188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 469373188Sgshapiro return; 469473188Sgshapiro } 469573188Sgshapiro map.map_class = &class->s_mapclass; 469664562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 469773188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 469864562Sgshapiro 469964562Sgshapiro (void) ldapmap_parseargs(&map, spec); 470064562Sgshapiro 470164562Sgshapiro /* These should never be set in LDAPDefaults */ 470264562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 470364562Sgshapiro map.map_spacesub != SpaceSub || 470464562Sgshapiro map.map_app != NULL || 470564562Sgshapiro map.map_tapp != NULL) 470664562Sgshapiro { 470764562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 470890792Sgshapiro SM_FREE_CLR(map.map_app); 470990792Sgshapiro SM_FREE_CLR(map.map_tapp); 471064562Sgshapiro } 471164562Sgshapiro 471264562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 471364562Sgshapiro { 471464562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 471594334Sgshapiro 471664562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 471764562Sgshapiro LDAPDefaults->ldap_filter = NULL; 471864562Sgshapiro } 471964562Sgshapiro 472064562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 472164562Sgshapiro { 472264562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 472364562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 472464562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 472564562Sgshapiro } 472664562Sgshapiro} 472764562Sgshapiro#endif /* LDAPMAP */ 472890792Sgshapiro/* 472964562Sgshapiro** PH map 473064562Sgshapiro*/ 473164562Sgshapiro 473290792Sgshapiro#if PH_MAP 473364562Sgshapiro 473464562Sgshapiro/* 473564562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 473664562Sgshapiro** This code is intended to replace the so-called "ph mailer". 4737168515Sgshapiro** Contributed by Mark D. Roth. Contact him for support. 473864562Sgshapiro*/ 473964562Sgshapiro 474090792Sgshapiro/* what version of the ph map code we're running */ 4741110560Sgshapirostatic char phmap_id[128]; 474264562Sgshapiro 474390792Sgshapiro/* sendmail version for phmap id string */ 474490792Sgshapiroextern const char Version[]; 474590792Sgshapiro 4746132943Sgshapiro/* assume we're using nph-1.2.x if not specified */ 4747110560Sgshapiro# ifndef NPH_VERSION 4748132943Sgshapiro# define NPH_VERSION 10200 4749110560Sgshapiro# endif 4750110560Sgshapiro 4751110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 4752110560Sgshapiro# if NPH_VERSION < 10200 4753110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 4754110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 4755110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 4756110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 4757110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 4758110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 4759110560Sgshapiro 476064562Sgshapiro/* 476164562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 476264562Sgshapiro*/ 476364562Sgshapiro 476464562Sgshapirobool 476564562Sgshapiroph_map_parseargs(map, args) 476664562Sgshapiro MAP *map; 476764562Sgshapiro char *args; 476864562Sgshapiro{ 476990792Sgshapiro register bool done; 477090792Sgshapiro register char *p = args; 477164562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 477264562Sgshapiro 477390792Sgshapiro /* initialize version string */ 4774168515Sgshapiro (void) sm_snprintf(phmap_id, sizeof(phmap_id), 477590792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 477690792Sgshapiro Version, libphclient_version); 477790792Sgshapiro 4778168515Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof(*pmap)); 477964562Sgshapiro 478064562Sgshapiro /* defaults */ 478164562Sgshapiro pmap->ph_servers = NULL; 478264562Sgshapiro pmap->ph_field_list = NULL; 478390792Sgshapiro pmap->ph = NULL; 478464562Sgshapiro pmap->ph_timeout = 0; 478590792Sgshapiro pmap->ph_fastclose = 0; 478664562Sgshapiro 478764562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 478864562Sgshapiro for (;;) 478964562Sgshapiro { 479064562Sgshapiro while (isascii(*p) && isspace(*p)) 479164562Sgshapiro p++; 479264562Sgshapiro if (*p != '-') 479364562Sgshapiro break; 479464562Sgshapiro switch (*++p) 479564562Sgshapiro { 479664562Sgshapiro case 'N': 479764562Sgshapiro map->map_mflags |= MF_INCLNULL; 479864562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 479964562Sgshapiro break; 480064562Sgshapiro 480164562Sgshapiro case 'O': 480264562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 480364562Sgshapiro break; 480464562Sgshapiro 480564562Sgshapiro case 'o': 480664562Sgshapiro map->map_mflags |= MF_OPTIONAL; 480764562Sgshapiro break; 480864562Sgshapiro 480964562Sgshapiro case 'f': 481064562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 481164562Sgshapiro break; 481264562Sgshapiro 481364562Sgshapiro case 'm': 481464562Sgshapiro map->map_mflags |= MF_MATCHONLY; 481564562Sgshapiro break; 481664562Sgshapiro 481764562Sgshapiro case 'A': 481864562Sgshapiro map->map_mflags |= MF_APPEND; 481964562Sgshapiro break; 482064562Sgshapiro 482164562Sgshapiro case 'q': 482264562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 482364562Sgshapiro break; 482464562Sgshapiro 482564562Sgshapiro case 't': 482664562Sgshapiro map->map_mflags |= MF_NODEFER; 482764562Sgshapiro break; 482864562Sgshapiro 482964562Sgshapiro case 'a': 483064562Sgshapiro map->map_app = ++p; 483164562Sgshapiro break; 483264562Sgshapiro 483364562Sgshapiro case 'T': 483464562Sgshapiro map->map_tapp = ++p; 483564562Sgshapiro break; 483664562Sgshapiro 483764562Sgshapiro case 'l': 483864562Sgshapiro while (isascii(*++p) && isspace(*p)) 483964562Sgshapiro continue; 484064562Sgshapiro pmap->ph_timeout = atoi(p); 484164562Sgshapiro break; 484264562Sgshapiro 484364562Sgshapiro case 'S': 484464562Sgshapiro map->map_spacesub = *++p; 484564562Sgshapiro break; 484664562Sgshapiro 484764562Sgshapiro case 'D': 484864562Sgshapiro map->map_mflags |= MF_DEFER; 484964562Sgshapiro break; 485064562Sgshapiro 485164562Sgshapiro case 'h': /* PH server list */ 485264562Sgshapiro while (isascii(*++p) && isspace(*p)) 485364562Sgshapiro continue; 485464562Sgshapiro pmap->ph_servers = p; 485564562Sgshapiro break; 485664562Sgshapiro 485790792Sgshapiro case 'k': /* fields to search for */ 485864562Sgshapiro while (isascii(*++p) && isspace(*p)) 485964562Sgshapiro continue; 486064562Sgshapiro pmap->ph_field_list = p; 486164562Sgshapiro break; 486264562Sgshapiro 486364562Sgshapiro default: 486490792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 486564562Sgshapiro } 486664562Sgshapiro 486764562Sgshapiro /* try to account for quoted strings */ 486864562Sgshapiro done = isascii(*p) && isspace(*p); 486964562Sgshapiro while (*p != '\0' && !done) 487064562Sgshapiro { 487164562Sgshapiro if (*p == '"') 487264562Sgshapiro { 487364562Sgshapiro while (*++p != '"' && *p != '\0') 487464562Sgshapiro continue; 487564562Sgshapiro if (*p != '\0') 487664562Sgshapiro p++; 487764562Sgshapiro } 487864562Sgshapiro else 487964562Sgshapiro p++; 488064562Sgshapiro done = isascii(*p) && isspace(*p); 488164562Sgshapiro } 488264562Sgshapiro 488364562Sgshapiro if (*p != '\0') 488464562Sgshapiro *p++ = '\0'; 488564562Sgshapiro } 488664562Sgshapiro 488764562Sgshapiro if (map->map_app != NULL) 488864562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 488964562Sgshapiro if (map->map_tapp != NULL) 489064562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 489164562Sgshapiro 489264562Sgshapiro if (pmap->ph_field_list != NULL) 489364562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 489464562Sgshapiro 489564562Sgshapiro if (pmap->ph_servers != NULL) 489664562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 489764562Sgshapiro else 489864562Sgshapiro { 489964562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 490090792Sgshapiro return false; 490164562Sgshapiro } 490264562Sgshapiro 490364562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 490490792Sgshapiro return true; 490564562Sgshapiro} 490664562Sgshapiro 490764562Sgshapiro/* 490864562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 490964562Sgshapiro*/ 491064562Sgshapiro 491190792Sgshapirovoid 491290792Sgshapiroph_map_close(map) 491364562Sgshapiro MAP *map; 491464562Sgshapiro{ 491564562Sgshapiro PH_MAP_STRUCT *pmap; 491664562Sgshapiro 491764562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 491890792Sgshapiro if (tTd(38, 9)) 491994334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 492090792Sgshapiro map->map_mname, pmap->ph_fastclose); 492164562Sgshapiro 492290792Sgshapiro 492390792Sgshapiro if (pmap->ph != NULL) 492464562Sgshapiro { 492590792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 492690792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 492790792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 492864562Sgshapiro } 492990792Sgshapiro 493064562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 493164562Sgshapiro} 493264562Sgshapiro 493364562Sgshapirostatic jmp_buf PHTimeout; 493464562Sgshapiro 493564562Sgshapiro/* ARGSUSED */ 493664562Sgshapirostatic void 493790792Sgshapiroph_timeout(unused) 493890792Sgshapiro int unused; 493964562Sgshapiro{ 494077349Sgshapiro /* 494177349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 494277349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 494377349Sgshapiro ** DOING. 494477349Sgshapiro */ 494577349Sgshapiro 494677349Sgshapiro errno = ETIMEDOUT; 494764562Sgshapiro longjmp(PHTimeout, 1); 494864562Sgshapiro} 494964562Sgshapiro 495090792Sgshapirostatic void 4951110560Sgshapiro#if NPH_VERSION >= 10200 4952110560Sgshapiroph_map_send_debug(appdata, text) 4953110560Sgshapiro void *appdata; 4954110560Sgshapiro#else 495590792Sgshapiroph_map_send_debug(text) 4956110560Sgshapiro#endif 495790792Sgshapiro char *text; 495864562Sgshapiro{ 495990792Sgshapiro if (LogLevel > 9) 496090792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 496190792Sgshapiro "ph_map_send_debug: ==> %s", text); 496290792Sgshapiro if (tTd(38, 20)) 496390792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 496490792Sgshapiro} 496564562Sgshapiro 496690792Sgshapirostatic void 4967110560Sgshapiro#if NPH_VERSION >= 10200 4968110560Sgshapiroph_map_recv_debug(appdata, text) 4969110560Sgshapiro void *appdata; 4970110560Sgshapiro#else 497190792Sgshapiroph_map_recv_debug(text) 4972110560Sgshapiro#endif 497390792Sgshapiro char *text; 497490792Sgshapiro{ 497590792Sgshapiro if (LogLevel > 10) 497690792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 497790792Sgshapiro "ph_map_recv_debug: <== %s", text); 497890792Sgshapiro if (tTd(38, 21)) 497990792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 498064562Sgshapiro} 498164562Sgshapiro 498290792Sgshapiro/* 498364562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 498464562Sgshapiro*/ 498564562Sgshapirobool 498664562Sgshapiroph_map_open(map, mode) 498764562Sgshapiro MAP *map; 498864562Sgshapiro int mode; 498964562Sgshapiro{ 499090792Sgshapiro PH_MAP_STRUCT *pmap; 499190792Sgshapiro register SM_EVENT *ev = NULL; 499264562Sgshapiro int save_errno = 0; 499390792Sgshapiro char *hostlist, *host; 499464562Sgshapiro 499564562Sgshapiro if (tTd(38, 2)) 499690792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 499764562Sgshapiro 499864562Sgshapiro mode &= O_ACCMODE; 499964562Sgshapiro if (mode != O_RDONLY) 500064562Sgshapiro { 500164562Sgshapiro /* issue a pseudo-error message */ 500290792Sgshapiro errno = SM_EMAPCANTWRITE; 500390792Sgshapiro return false; 500464562Sgshapiro } 500564562Sgshapiro 500666494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 500766494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 500866494Sgshapiro { 500966494Sgshapiro if (tTd(9, 1)) 501090792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 501190792Sgshapiro map->map_mname); 501266494Sgshapiro 501366494Sgshapiro /* 501490792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 501590792Sgshapiro ** a temporary failure using the bogus map and 501690792Sgshapiro ** map->map_tapp instead of the default permanent error. 501766494Sgshapiro */ 501866494Sgshapiro 501966494Sgshapiro map->map_mflags &= ~MF_DEFER; 502090792Sgshapiro return false; 502166494Sgshapiro } 502266494Sgshapiro 502364562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 502490792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 502564562Sgshapiro 502690792Sgshapiro /* try each host in the list */ 502764562Sgshapiro hostlist = newstr(pmap->ph_servers); 502890792Sgshapiro for (host = strtok(hostlist, " "); 502990792Sgshapiro host != NULL; 503090792Sgshapiro host = strtok(NULL, " ")) 503164562Sgshapiro { 503290792Sgshapiro /* set timeout */ 503364562Sgshapiro if (pmap->ph_timeout != 0) 503464562Sgshapiro { 503564562Sgshapiro if (setjmp(PHTimeout) != 0) 503664562Sgshapiro { 503764562Sgshapiro ev = NULL; 503864562Sgshapiro if (LogLevel > 1) 503964562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 504064562Sgshapiro "timeout connecting to PH server %.100s", 504190792Sgshapiro host); 504264562Sgshapiro errno = ETIMEDOUT; 504364562Sgshapiro goto ph_map_open_abort; 504464562Sgshapiro } 504590792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 504664562Sgshapiro } 504790792Sgshapiro 504890792Sgshapiro /* open connection to server */ 5049110560Sgshapiro if (ph_open(&(pmap->ph), host, 5050110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 5051110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 5052110560Sgshapiro#if NPH_VERSION >= 10200 5053110560Sgshapiro , NULL 5054110560Sgshapiro#endif 5055110560Sgshapiro ) == 0 5056110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 505764562Sgshapiro { 505864562Sgshapiro if (ev != NULL) 505990792Sgshapiro sm_clrevent(ev); 506090792Sgshapiro sm_free(hostlist); /* XXX */ 506190792Sgshapiro return true; 506264562Sgshapiro } 506390792Sgshapiro 506464562Sgshapiro ph_map_open_abort: 506590792Sgshapiro save_errno = errno; 506664562Sgshapiro if (ev != NULL) 506790792Sgshapiro sm_clrevent(ev); 5068110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 506990792Sgshapiro ph_map_close(map); 507090792Sgshapiro errno = save_errno; 507190792Sgshapiro } 507264562Sgshapiro 507366494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 507464562Sgshapiro { 507566494Sgshapiro if (errno == 0) 507664562Sgshapiro errno = EAGAIN; 507766494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 507866494Sgshapiro map->map_mname); 507964562Sgshapiro } 508066494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 508164562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 508266494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 508366494Sgshapiro map->map_mname); 508490792Sgshapiro sm_free(hostlist); /* XXX */ 508590792Sgshapiro return false; 508664562Sgshapiro} 508764562Sgshapiro 508864562Sgshapiro/* 508964562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 509064562Sgshapiro*/ 509164562Sgshapiro 509264562Sgshapirochar * 509364562Sgshapiroph_map_lookup(map, key, args, pstat) 509464562Sgshapiro MAP *map; 509564562Sgshapiro char *key; 509664562Sgshapiro char **args; 509764562Sgshapiro int *pstat; 509864562Sgshapiro{ 509990792Sgshapiro int i, save_errno = 0; 510090792Sgshapiro register SM_EVENT *ev = NULL; 510164562Sgshapiro PH_MAP_STRUCT *pmap; 510290792Sgshapiro char *value = NULL; 510364562Sgshapiro 510464562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 510564562Sgshapiro 510664562Sgshapiro *pstat = EX_OK; 510764562Sgshapiro 510890792Sgshapiro /* set timeout */ 510964562Sgshapiro if (pmap->ph_timeout != 0) 511064562Sgshapiro { 511164562Sgshapiro if (setjmp(PHTimeout) != 0) 511264562Sgshapiro { 511364562Sgshapiro ev = NULL; 511464562Sgshapiro if (LogLevel > 1) 511564562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 511664562Sgshapiro "timeout during PH lookup of %.100s", 511764562Sgshapiro key); 511864562Sgshapiro errno = ETIMEDOUT; 511964562Sgshapiro *pstat = EX_TEMPFAIL; 512064562Sgshapiro goto ph_map_lookup_abort; 512164562Sgshapiro } 512290792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 512364562Sgshapiro } 512464562Sgshapiro 512590792Sgshapiro /* perform lookup */ 512690792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 512790792Sgshapiro if (i == -1) 512890792Sgshapiro *pstat = EX_TEMPFAIL; 5129110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 513090792Sgshapiro *pstat = EX_UNAVAILABLE; 513164562Sgshapiro 513264562Sgshapiro ph_map_lookup_abort: 513364562Sgshapiro if (ev != NULL) 513490792Sgshapiro sm_clrevent(ev); 513564562Sgshapiro 513664562Sgshapiro /* 513790792Sgshapiro ** Close the connection if the timer popped 513864562Sgshapiro ** or we got a temporary PH error 513964562Sgshapiro */ 514064562Sgshapiro 514164562Sgshapiro if (*pstat == EX_TEMPFAIL) 514290792Sgshapiro { 514390792Sgshapiro save_errno = errno; 5144110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 514590792Sgshapiro ph_map_close(map); 514690792Sgshapiro errno = save_errno; 514790792Sgshapiro } 514864562Sgshapiro 514964562Sgshapiro if (*pstat == EX_OK) 515064562Sgshapiro { 515164562Sgshapiro if (tTd(38,20)) 515290792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 515364562Sgshapiro 515464562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 515590792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 515664562Sgshapiro else 515790792Sgshapiro return map_rewrite(map, value, strlen(value), args); 515864562Sgshapiro } 515964562Sgshapiro 516064562Sgshapiro return NULL; 516164562Sgshapiro} 516264562Sgshapiro#endif /* PH_MAP */ 5163168515Sgshapiro 516490792Sgshapiro/* 516542575Speter** syslog map 516638032Speter*/ 516738032Speter 516838032Speter#define map_prio map_lockfd /* overload field */ 516938032Speter 517038032Speter/* 517142575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 517238032Speter*/ 517338032Speter 517438032Speterbool 517538032Spetersyslog_map_parseargs(map, args) 517638032Speter MAP *map; 517738032Speter char *args; 517838032Speter{ 517938032Speter char *p = args; 518038032Speter char *priority = NULL; 518138032Speter 518264562Sgshapiro /* there is no check whether there is really an argument */ 518364562Sgshapiro while (*p != '\0') 518438032Speter { 518538032Speter while (isascii(*p) && isspace(*p)) 518638032Speter p++; 518738032Speter if (*p != '-') 518838032Speter break; 518964562Sgshapiro ++p; 519064562Sgshapiro if (*p == 'D') 519164562Sgshapiro { 519264562Sgshapiro map->map_mflags |= MF_DEFER; 519364562Sgshapiro ++p; 519464562Sgshapiro } 519564562Sgshapiro else if (*p == 'S') 519664562Sgshapiro { 519764562Sgshapiro map->map_spacesub = *++p; 519864562Sgshapiro if (*p != '\0') 519964562Sgshapiro p++; 520064562Sgshapiro } 520164562Sgshapiro else if (*p == 'L') 520264562Sgshapiro { 520364562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 520464562Sgshapiro continue; 520564562Sgshapiro if (*p == '\0') 520664562Sgshapiro break; 520764562Sgshapiro priority = p; 520864562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 520964562Sgshapiro p++; 521064562Sgshapiro if (*p != '\0') 521164562Sgshapiro *p++ = '\0'; 521264562Sgshapiro } 521364562Sgshapiro else 521464562Sgshapiro { 521564562Sgshapiro syserr("Illegal option %c map syslog", *p); 521664562Sgshapiro ++p; 521764562Sgshapiro } 521838032Speter } 521938032Speter 522038032Speter if (priority == NULL) 522138032Speter map->map_prio = LOG_INFO; 522238032Speter else 522338032Speter { 522490792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 522538032Speter priority += 4; 522638032Speter 522738032Speter#ifdef LOG_EMERG 522890792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 522938032Speter map->map_prio = LOG_EMERG; 523038032Speter else 523164562Sgshapiro#endif /* LOG_EMERG */ 523238032Speter#ifdef LOG_ALERT 523390792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 523438032Speter map->map_prio = LOG_ALERT; 523538032Speter else 523664562Sgshapiro#endif /* LOG_ALERT */ 523738032Speter#ifdef LOG_CRIT 523890792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 523938032Speter map->map_prio = LOG_CRIT; 524038032Speter else 524164562Sgshapiro#endif /* LOG_CRIT */ 524238032Speter#ifdef LOG_ERR 524390792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 524438032Speter map->map_prio = LOG_ERR; 524538032Speter else 524664562Sgshapiro#endif /* LOG_ERR */ 524738032Speter#ifdef LOG_WARNING 524890792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 524938032Speter map->map_prio = LOG_WARNING; 525038032Speter else 525164562Sgshapiro#endif /* LOG_WARNING */ 525238032Speter#ifdef LOG_NOTICE 525390792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 525438032Speter map->map_prio = LOG_NOTICE; 525538032Speter else 525664562Sgshapiro#endif /* LOG_NOTICE */ 525738032Speter#ifdef LOG_INFO 525890792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 525938032Speter map->map_prio = LOG_INFO; 526038032Speter else 526164562Sgshapiro#endif /* LOG_INFO */ 526238032Speter#ifdef LOG_DEBUG 526390792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 526438032Speter map->map_prio = LOG_DEBUG; 526538032Speter else 526664562Sgshapiro#endif /* LOG_DEBUG */ 526738032Speter { 526890792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 526938032Speter priority); 527090792Sgshapiro return false; 527138032Speter } 527238032Speter } 527390792Sgshapiro return true; 527438032Speter} 527538032Speter 527638032Speter/* 527742575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 527838032Speter*/ 527938032Speter 528038032Speterchar * 528138032Spetersyslog_map_lookup(map, string, args, statp) 528238032Speter MAP *map; 528338032Speter char *string; 528438032Speter char **args; 528538032Speter int *statp; 528638032Speter{ 528738032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 528838032Speter 528938032Speter if (ptr != NULL) 529038032Speter { 529138032Speter if (tTd(38, 20)) 529290792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 529364562Sgshapiro map->map_mname, map->map_prio, ptr); 529438032Speter 529538032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 529638032Speter } 529738032Speter 529838032Speter *statp = EX_OK; 529938032Speter return ""; 530038032Speter} 530138032Speter 5302168515Sgshapiro#if _FFR_DPRINTF_MAP 530390792Sgshapiro/* 5304168515Sgshapiro** dprintf map 5305168515Sgshapiro*/ 5306168515Sgshapiro 5307168515Sgshapiro#define map_dbg_level map_lockfd /* overload field */ 5308168515Sgshapiro 5309168515Sgshapiro/* 5310168515Sgshapiro** DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages. 5311168515Sgshapiro*/ 5312168515Sgshapiro 5313168515Sgshapirobool 5314168515Sgshapirodprintf_map_parseargs(map, args) 5315168515Sgshapiro MAP *map; 5316168515Sgshapiro char *args; 5317168515Sgshapiro{ 5318168515Sgshapiro char *p = args; 5319168515Sgshapiro char *dbg_level = NULL; 5320168515Sgshapiro 5321168515Sgshapiro /* there is no check whether there is really an argument */ 5322168515Sgshapiro while (*p != '\0') 5323168515Sgshapiro { 5324168515Sgshapiro while (isascii(*p) && isspace(*p)) 5325168515Sgshapiro p++; 5326168515Sgshapiro if (*p != '-') 5327168515Sgshapiro break; 5328168515Sgshapiro ++p; 5329168515Sgshapiro if (*p == 'D') 5330168515Sgshapiro { 5331168515Sgshapiro map->map_mflags |= MF_DEFER; 5332168515Sgshapiro ++p; 5333168515Sgshapiro } 5334168515Sgshapiro else if (*p == 'S') 5335168515Sgshapiro { 5336168515Sgshapiro map->map_spacesub = *++p; 5337168515Sgshapiro if (*p != '\0') 5338168515Sgshapiro p++; 5339168515Sgshapiro } 5340168515Sgshapiro else if (*p == 'd') 5341168515Sgshapiro { 5342168515Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 5343168515Sgshapiro continue; 5344168515Sgshapiro if (*p == '\0') 5345168515Sgshapiro break; 5346168515Sgshapiro dbg_level = p; 5347168515Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 5348168515Sgshapiro p++; 5349168515Sgshapiro if (*p != '\0') 5350168515Sgshapiro *p++ = '\0'; 5351168515Sgshapiro } 5352168515Sgshapiro else 5353168515Sgshapiro { 5354168515Sgshapiro syserr("Illegal option %c map dprintf", *p); 5355168515Sgshapiro ++p; 5356168515Sgshapiro } 5357168515Sgshapiro } 5358168515Sgshapiro 5359168515Sgshapiro if (dbg_level == NULL) 5360168515Sgshapiro map->map_dbg_level = 0; 5361168515Sgshapiro else 5362168515Sgshapiro { 5363168515Sgshapiro if (!(isascii(*dbg_level) && isdigit(*dbg_level))) 5364168515Sgshapiro { 5365168515Sgshapiro syserr("dprintf map \"%s\", file %s: -d should specify a number, not %s", 5366168515Sgshapiro map->map_mname, map->map_file, 5367168515Sgshapiro dbg_level); 5368168515Sgshapiro return false; 5369168515Sgshapiro } 5370168515Sgshapiro map->map_dbg_level = atoi(dbg_level); 5371168515Sgshapiro } 5372168515Sgshapiro return true; 5373168515Sgshapiro} 5374168515Sgshapiro 5375168515Sgshapiro/* 5376168515Sgshapiro** DPRINTF_MAP_LOOKUP -- rewrite and print message. Always return empty string 5377168515Sgshapiro*/ 5378168515Sgshapiro 5379168515Sgshapirochar * 5380168515Sgshapirodprintf_map_lookup(map, string, args, statp) 5381168515Sgshapiro MAP *map; 5382168515Sgshapiro char *string; 5383168515Sgshapiro char **args; 5384168515Sgshapiro int *statp; 5385168515Sgshapiro{ 5386168515Sgshapiro char *ptr = map_rewrite(map, string, strlen(string), args); 5387168515Sgshapiro 5388168515Sgshapiro if (ptr != NULL && tTd(85, map->map_dbg_level)) 5389168515Sgshapiro sm_dprintf("%s\n", ptr); 5390168515Sgshapiro *statp = EX_OK; 5391168515Sgshapiro return ""; 5392168515Sgshapiro} 5393168515Sgshapiro#endif /* _FFR_DPRINTF_MAP */ 5394168515Sgshapiro 5395168515Sgshapiro/* 539638032Speter** HESIOD Modules 539738032Speter*/ 539838032Speter 539990792Sgshapiro#if HESIOD 540038032Speter 540138032Speterbool 540238032Speterhes_map_open(map, mode) 540338032Speter MAP *map; 540438032Speter int mode; 540538032Speter{ 540638032Speter if (tTd(38, 2)) 540790792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 540838032Speter map->map_mname, map->map_file, mode); 540938032Speter 541038032Speter if (mode != O_RDONLY) 541138032Speter { 541238032Speter /* issue a pseudo-error message */ 541390792Sgshapiro errno = SM_EMAPCANTWRITE; 541490792Sgshapiro return false; 541538032Speter } 541638032Speter 541764562Sgshapiro# ifdef HESIOD_INIT 541838032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 541990792Sgshapiro return true; 542038032Speter 542138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 542294334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 542390792Sgshapiro sm_errstring(errno)); 542490792Sgshapiro return false; 542564562Sgshapiro# else /* HESIOD_INIT */ 542638032Speter if (hes_error() == HES_ER_UNINIT) 542738032Speter hes_init(); 542838032Speter switch (hes_error()) 542938032Speter { 543038032Speter case HES_ER_OK: 543138032Speter case HES_ER_NOTFOUND: 543290792Sgshapiro return true; 543338032Speter } 543438032Speter 543538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 543694334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 543738032Speter 543890792Sgshapiro return false; 543964562Sgshapiro# endif /* HESIOD_INIT */ 544038032Speter} 544138032Speter 544238032Speterchar * 544338032Speterhes_map_lookup(map, name, av, statp) 544438032Speter MAP *map; 544538032Speter char *name; 544638032Speter char **av; 544738032Speter int *statp; 544838032Speter{ 544938032Speter char **hp; 545038032Speter 545138032Speter if (tTd(38, 20)) 545290792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 545338032Speter 545438032Speter if (name[0] == '\\') 545538032Speter { 545638032Speter char *np; 545738032Speter int nl; 545877349Sgshapiro int save_errno; 545938032Speter char nbuf[MAXNAME]; 546038032Speter 546138032Speter nl = strlen(name); 5462168515Sgshapiro if (nl < sizeof(nbuf) - 1) 546338032Speter np = nbuf; 546438032Speter else 546538032Speter np = xalloc(strlen(name) + 2); 546638032Speter np[0] = '\\'; 5467168515Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof(nbuf)) - 1); 546864562Sgshapiro# ifdef HESIOD_INIT 546938032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 547064562Sgshapiro# else /* HESIOD_INIT */ 547138032Speter hp = hes_resolve(np, map->map_file); 547264562Sgshapiro# endif /* HESIOD_INIT */ 547377349Sgshapiro save_errno = errno; 547438032Speter if (np != nbuf) 547590792Sgshapiro sm_free(np); /* XXX */ 547677349Sgshapiro errno = save_errno; 547738032Speter } 547838032Speter else 547938032Speter { 548064562Sgshapiro# ifdef HESIOD_INIT 548138032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 548264562Sgshapiro# else /* HESIOD_INIT */ 548338032Speter hp = hes_resolve(name, map->map_file); 548464562Sgshapiro# endif /* HESIOD_INIT */ 548538032Speter } 548664562Sgshapiro# ifdef HESIOD_INIT 548777349Sgshapiro if (hp == NULL || *hp == NULL) 548838032Speter { 548938032Speter switch (errno) 549038032Speter { 549138032Speter case ENOENT: 549238032Speter *statp = EX_NOTFOUND; 549338032Speter break; 549438032Speter case ECONNREFUSED: 549538032Speter *statp = EX_TEMPFAIL; 549638032Speter break; 549790792Sgshapiro case EMSGSIZE: 549838032Speter case ENOMEM: 549938032Speter default: 550038032Speter *statp = EX_UNAVAILABLE; 550138032Speter break; 550238032Speter } 550382017Sgshapiro if (hp != NULL) 550482017Sgshapiro hesiod_free_list(HesiodContext, hp); 550538032Speter return NULL; 550638032Speter } 550764562Sgshapiro# else /* HESIOD_INIT */ 550838032Speter if (hp == NULL || hp[0] == NULL) 550938032Speter { 551038032Speter switch (hes_error()) 551138032Speter { 551238032Speter case HES_ER_OK: 551338032Speter *statp = EX_OK; 551438032Speter break; 551538032Speter 551638032Speter case HES_ER_NOTFOUND: 551738032Speter *statp = EX_NOTFOUND; 551838032Speter break; 551938032Speter 552038032Speter case HES_ER_CONFIG: 552138032Speter *statp = EX_UNAVAILABLE; 552238032Speter break; 552338032Speter 552438032Speter case HES_ER_NET: 552538032Speter *statp = EX_TEMPFAIL; 552638032Speter break; 552738032Speter } 552838032Speter return NULL; 552938032Speter } 553064562Sgshapiro# endif /* HESIOD_INIT */ 553138032Speter 553238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 553338032Speter return map_rewrite(map, name, strlen(name), NULL); 553438032Speter else 553538032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 553638032Speter} 553738032Speter 553890792Sgshapiro/* 553990792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 554090792Sgshapiro*/ 554190792Sgshapiro 554290792Sgshapirovoid 554390792Sgshapirohes_map_close(map) 554490792Sgshapiro MAP *map; 554590792Sgshapiro{ 554690792Sgshapiro if (tTd(38, 20)) 554790792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 554890792Sgshapiro 554990792Sgshapiro# ifdef HESIOD_INIT 555090792Sgshapiro /* Free the hesiod context */ 555190792Sgshapiro if (HesiodContext != NULL) 555290792Sgshapiro { 555390792Sgshapiro hesiod_end(HesiodContext); 555490792Sgshapiro HesiodContext = NULL; 555590792Sgshapiro } 555690792Sgshapiro# endif /* HESIOD_INIT */ 555790792Sgshapiro} 555890792Sgshapiro 555964562Sgshapiro#endif /* HESIOD */ 556090792Sgshapiro/* 556138032Speter** NeXT NETINFO Modules 556238032Speter*/ 556338032Speter 556438032Speter#if NETINFO 556538032Speter 556638032Speter# define NETINFO_DEFAULT_DIR "/aliases" 556738032Speter# define NETINFO_DEFAULT_PROPERTY "members" 556838032Speter 556938032Speter/* 557038032Speter** NI_MAP_OPEN -- open NetInfo Aliases 557138032Speter*/ 557238032Speter 557338032Speterbool 557438032Speterni_map_open(map, mode) 557538032Speter MAP *map; 557638032Speter int mode; 557738032Speter{ 557838032Speter if (tTd(38, 2)) 557990792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 558038032Speter map->map_mname, map->map_file, mode); 558138032Speter mode &= O_ACCMODE; 558238032Speter 558338032Speter if (*map->map_file == '\0') 558438032Speter map->map_file = NETINFO_DEFAULT_DIR; 558538032Speter 558638032Speter if (map->map_valcolnm == NULL) 558738032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 558838032Speter 558990792Sgshapiro if (map->map_coldelim == '\0') 559090792Sgshapiro { 559190792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 559290792Sgshapiro map->map_coldelim = ','; 559390792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 559490792Sgshapiro map->map_coldelim = ' '; 559590792Sgshapiro } 559690792Sgshapiro return true; 559738032Speter} 559838032Speter 559938032Speter 560038032Speter/* 560138032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 560238032Speter*/ 560338032Speter 560438032Speterchar * 560538032Speterni_map_lookup(map, name, av, statp) 560638032Speter MAP *map; 560738032Speter char *name; 560838032Speter char **av; 560938032Speter int *statp; 561038032Speter{ 561138032Speter char *res; 561238032Speter char *propval; 561338032Speter 561438032Speter if (tTd(38, 20)) 561590792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 561638032Speter 561738032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 561838032Speter map->map_valcolnm, map->map_coldelim); 561938032Speter 562038032Speter if (propval == NULL) 562138032Speter return NULL; 562238032Speter 562390792Sgshapiro SM_TRY 562490792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 562590792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 562690792Sgshapiro else 562790792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 562890792Sgshapiro SM_FINALLY 562990792Sgshapiro sm_free(propval); 563090792Sgshapiro SM_END_TRY 563138032Speter return res; 563238032Speter} 563338032Speter 563438032Speter 563564562Sgshapirostatic bool 563638032Speterni_getcanonname(name, hbsize, statp) 563738032Speter char *name; 563838032Speter int hbsize; 563938032Speter int *statp; 564038032Speter{ 564138032Speter char *vptr; 564238032Speter char *ptr; 564338032Speter char nbuf[MAXNAME + 1]; 564438032Speter 564538032Speter if (tTd(38, 20)) 564690792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 564738032Speter 5648168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 564938032Speter { 565038032Speter *statp = EX_UNAVAILABLE; 565190792Sgshapiro return false; 565238032Speter } 565373188Sgshapiro (void) shorten_hostname(nbuf); 565438032Speter 565538032Speter /* we only accept single token search key */ 565638032Speter if (strchr(nbuf, '.')) 565738032Speter { 565838032Speter *statp = EX_NOHOST; 565990792Sgshapiro return false; 566038032Speter } 566138032Speter 566238032Speter /* Do the search */ 566338032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 566438032Speter 566538032Speter if (vptr == NULL) 566638032Speter { 566738032Speter *statp = EX_NOHOST; 566890792Sgshapiro return false; 566938032Speter } 567038032Speter 567138032Speter /* Only want the first machine name */ 567238032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 567338032Speter *ptr = '\0'; 567438032Speter 567590792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 567638032Speter { 567777349Sgshapiro sm_free(vptr); 567890792Sgshapiro *statp = EX_UNAVAILABLE; 567990792Sgshapiro return true; 568038032Speter } 568177349Sgshapiro sm_free(vptr); 568290792Sgshapiro *statp = EX_OK; 568390792Sgshapiro return false; 568438032Speter} 568590792Sgshapiro#endif /* NETINFO */ 568638032Speter/* 568738032Speter** TEXT (unindexed text file) Modules 568838032Speter** 568938032Speter** This code donated by Sun Microsystems. 569038032Speter*/ 569138032Speter 569238032Speter#define map_sff map_lockfd /* overload field */ 569338032Speter 569438032Speter 569538032Speter/* 569638032Speter** TEXT_MAP_OPEN -- open text table 569738032Speter*/ 569838032Speter 569938032Speterbool 570038032Spetertext_map_open(map, mode) 570138032Speter MAP *map; 570238032Speter int mode; 570338032Speter{ 570464562Sgshapiro long sff; 570538032Speter int i; 570638032Speter 570738032Speter if (tTd(38, 2)) 570890792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 570938032Speter map->map_mname, map->map_file, mode); 571038032Speter 571138032Speter mode &= O_ACCMODE; 571238032Speter if (mode != O_RDONLY) 571338032Speter { 571438032Speter errno = EPERM; 571590792Sgshapiro return false; 571638032Speter } 571738032Speter 571838032Speter if (*map->map_file == '\0') 571938032Speter { 572038032Speter syserr("text map \"%s\": file name required", 572138032Speter map->map_mname); 572290792Sgshapiro return false; 572338032Speter } 572438032Speter 572538032Speter if (map->map_file[0] != '/') 572638032Speter { 572738032Speter syserr("text map \"%s\": file name must be fully qualified", 572838032Speter map->map_mname); 572990792Sgshapiro return false; 573038032Speter } 573138032Speter 573238032Speter sff = SFF_ROOTOK|SFF_REGONLY; 573364562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 573438032Speter sff |= SFF_NOWLINK; 573564562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 573638032Speter sff |= SFF_SAFEDIRPATH; 573738032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 573838032Speter sff, S_IRUSR, NULL)) != 0) 573938032Speter { 574064562Sgshapiro int save_errno = errno; 574164562Sgshapiro 574238032Speter /* cannot open this map */ 574338032Speter if (tTd(38, 2)) 574490792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 574564562Sgshapiro errno = save_errno; 574638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 574738032Speter syserr("text map \"%s\": unsafe map file %s", 574838032Speter map->map_mname, map->map_file); 574990792Sgshapiro return false; 575038032Speter } 575138032Speter 575238032Speter if (map->map_keycolnm == NULL) 575338032Speter map->map_keycolno = 0; 575438032Speter else 575538032Speter { 575638032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 575738032Speter { 575838032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 575938032Speter map->map_mname, map->map_file, 576038032Speter map->map_keycolnm); 576190792Sgshapiro return false; 576238032Speter } 576338032Speter map->map_keycolno = atoi(map->map_keycolnm); 576438032Speter } 576538032Speter 576638032Speter if (map->map_valcolnm == NULL) 576738032Speter map->map_valcolno = 0; 576838032Speter else 576938032Speter { 577038032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 577138032Speter { 577238032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 577338032Speter map->map_mname, map->map_file, 577438032Speter map->map_valcolnm); 577590792Sgshapiro return false; 577638032Speter } 577738032Speter map->map_valcolno = atoi(map->map_valcolnm); 577838032Speter } 577938032Speter 578038032Speter if (tTd(38, 2)) 578138032Speter { 578290792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 578338032Speter map->map_mname, map->map_file); 578438032Speter if (map->map_coldelim == '\0') 578590792Sgshapiro sm_dprintf("(white space)\n"); 578638032Speter else 578790792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 578838032Speter } 578938032Speter 579038032Speter map->map_sff = sff; 579190792Sgshapiro return true; 579238032Speter} 579338032Speter 579438032Speter 579538032Speter/* 579638032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 579738032Speter*/ 579838032Speter 579938032Speterchar * 580038032Spetertext_map_lookup(map, name, av, statp) 580138032Speter MAP *map; 580238032Speter char *name; 580338032Speter char **av; 580438032Speter int *statp; 580538032Speter{ 580638032Speter char *vp; 580738032Speter auto int vsize; 580838032Speter int buflen; 580990792Sgshapiro SM_FILE_T *f; 581038032Speter char delim; 581138032Speter int key_idx; 581238032Speter bool found_it; 581364562Sgshapiro long sff = map->map_sff; 581438032Speter char search_key[MAXNAME + 1]; 581538032Speter char linebuf[MAXLINE]; 581638032Speter char buf[MAXNAME + 1]; 581738032Speter 581890792Sgshapiro found_it = false; 581938032Speter if (tTd(38, 20)) 582090792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 582138032Speter 582238032Speter buflen = strlen(name); 5823168515Sgshapiro if (buflen > sizeof(search_key) - 1) 5824168515Sgshapiro buflen = sizeof(search_key) - 1; /* XXX just cut if off? */ 582564562Sgshapiro memmove(search_key, name, buflen); 582638032Speter search_key[buflen] = '\0'; 582738032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 582838032Speter makelower(search_key); 582938032Speter 583038032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 583138032Speter if (f == NULL) 583238032Speter { 583338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 583438032Speter *statp = EX_UNAVAILABLE; 583538032Speter return NULL; 583638032Speter } 583738032Speter key_idx = map->map_keycolno; 583838032Speter delim = map->map_coldelim; 583998121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 5840249729Sgshapiro linebuf, sizeof(linebuf)) >= 0) 584138032Speter { 584238032Speter char *p; 584338032Speter 584438032Speter /* skip comment line */ 584538032Speter if (linebuf[0] == '#') 584638032Speter continue; 584738032Speter p = strchr(linebuf, '\n'); 584838032Speter if (p != NULL) 584938032Speter *p = '\0'; 5850168515Sgshapiro p = get_column(linebuf, key_idx, delim, buf, sizeof(buf)); 585190792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 585238032Speter { 585390792Sgshapiro found_it = true; 585438032Speter break; 585538032Speter } 585638032Speter } 585790792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 585838032Speter if (!found_it) 585938032Speter { 586038032Speter *statp = EX_NOTFOUND; 586138032Speter return NULL; 586238032Speter } 5863168515Sgshapiro vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof(buf)); 586442575Speter if (vp == NULL) 586542575Speter { 586642575Speter *statp = EX_NOTFOUND; 586742575Speter return NULL; 586842575Speter } 586938032Speter vsize = strlen(vp); 587038032Speter *statp = EX_OK; 587138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 587238032Speter return map_rewrite(map, name, strlen(name), NULL); 587338032Speter else 587438032Speter return map_rewrite(map, vp, vsize, av); 587538032Speter} 587638032Speter 587738032Speter/* 587838032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 587938032Speter*/ 588038032Speter 588164562Sgshapirostatic bool 588238032Spetertext_getcanonname(name, hbsize, statp) 588338032Speter char *name; 588438032Speter int hbsize; 588538032Speter int *statp; 588638032Speter{ 588738032Speter bool found; 588873188Sgshapiro char *dot; 588990792Sgshapiro SM_FILE_T *f; 589038032Speter char linebuf[MAXLINE]; 589138032Speter char cbuf[MAXNAME + 1]; 589238032Speter char nbuf[MAXNAME + 1]; 589338032Speter 589438032Speter if (tTd(38, 20)) 589590792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 589638032Speter 5897168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 589838032Speter { 589938032Speter *statp = EX_UNAVAILABLE; 590090792Sgshapiro return false; 590138032Speter } 590273188Sgshapiro dot = shorten_hostname(nbuf); 590338032Speter 590490792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 590590792Sgshapiro NULL); 590638032Speter if (f == NULL) 590738032Speter { 590838032Speter *statp = EX_UNAVAILABLE; 590990792Sgshapiro return false; 591038032Speter } 591190792Sgshapiro found = false; 591290792Sgshapiro while (!found && 591398121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 5914249729Sgshapiro linebuf, sizeof(linebuf)) >= 0) 591538032Speter { 591638032Speter char *p = strpbrk(linebuf, "#\n"); 591738032Speter 591838032Speter if (p != NULL) 591938032Speter *p = '\0'; 592038032Speter if (linebuf[0] != '\0') 592173188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 5922168515Sgshapiro cbuf, sizeof(cbuf)); 592338032Speter } 592490792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 592538032Speter if (!found) 592638032Speter { 592738032Speter *statp = EX_NOHOST; 592890792Sgshapiro return false; 592938032Speter } 593038032Speter 593190792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 593238032Speter { 593390792Sgshapiro *statp = EX_UNAVAILABLE; 593490792Sgshapiro return false; 593538032Speter } 593690792Sgshapiro *statp = EX_OK; 593790792Sgshapiro return true; 593838032Speter} 593990792Sgshapiro/* 594038032Speter** STAB (Symbol Table) Modules 594138032Speter*/ 594238032Speter 594338032Speter 594438032Speter/* 594538032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 594638032Speter*/ 594738032Speter 594838032Speter/* ARGSUSED2 */ 594938032Speterchar * 595038032Speterstab_map_lookup(map, name, av, pstat) 595138032Speter register MAP *map; 595238032Speter char *name; 595338032Speter char **av; 595438032Speter int *pstat; 595538032Speter{ 595638032Speter register STAB *s; 595738032Speter 595838032Speter if (tTd(38, 20)) 595990792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 596038032Speter map->map_mname, name); 596138032Speter 596238032Speter s = stab(name, ST_ALIAS, ST_FIND); 5963147078Sgshapiro if (s == NULL) 5964147078Sgshapiro return NULL; 5965147078Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 5966147078Sgshapiro return map_rewrite(map, name, strlen(name), NULL); 5967147078Sgshapiro else 5968147078Sgshapiro return map_rewrite(map, s->s_alias, strlen(s->s_alias), av); 596938032Speter} 597038032Speter 597138032Speter/* 597238032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 597338032Speter*/ 597438032Speter 597538032Spetervoid 597638032Speterstab_map_store(map, lhs, rhs) 597738032Speter register MAP *map; 597838032Speter char *lhs; 597938032Speter char *rhs; 598038032Speter{ 598138032Speter register STAB *s; 598238032Speter 598338032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 598438032Speter s->s_alias = newstr(rhs); 598538032Speter} 598638032Speter 598738032Speter 598838032Speter/* 598938032Speter** STAB_MAP_OPEN -- initialize (reads data file) 599038032Speter** 5991223067Sgshapiro** This is a weird case -- it is only intended as a fallback for 599238032Speter** aliases. For this reason, opens for write (only during a 599338032Speter** "newaliases") always fails, and opens for read open the 599438032Speter** actual underlying text file instead of the database. 599538032Speter*/ 599638032Speter 599738032Speterbool 599838032Speterstab_map_open(map, mode) 599938032Speter register MAP *map; 600038032Speter int mode; 600138032Speter{ 600290792Sgshapiro SM_FILE_T *af; 600364562Sgshapiro long sff; 600438032Speter struct stat st; 600538032Speter 600638032Speter if (tTd(38, 2)) 600790792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 600838032Speter map->map_mname, map->map_file, mode); 600938032Speter 601038032Speter mode &= O_ACCMODE; 601138032Speter if (mode != O_RDONLY) 601238032Speter { 601338032Speter errno = EPERM; 601490792Sgshapiro return false; 601538032Speter } 601638032Speter 601738032Speter sff = SFF_ROOTOK|SFF_REGONLY; 601864562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 601938032Speter sff |= SFF_NOWLINK; 602064562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 602138032Speter sff |= SFF_SAFEDIRPATH; 602238032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 602338032Speter if (af == NULL) 602490792Sgshapiro return false; 602590792Sgshapiro readaliases(map, af, false, false); 602638032Speter 602790792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 602838032Speter map->map_mtime = st.st_mtime; 602990792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 603038032Speter 603190792Sgshapiro return true; 603238032Speter} 603390792Sgshapiro/* 603438032Speter** Implicit Modules 603538032Speter** 603638032Speter** Tries several types. For back compatibility of aliases. 603738032Speter*/ 603838032Speter 603938032Speter 604038032Speter/* 604138032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 604238032Speter*/ 604338032Speter 604438032Speterchar * 604538032Speterimpl_map_lookup(map, name, av, pstat) 604638032Speter MAP *map; 604738032Speter char *name; 604838032Speter char **av; 604938032Speter int *pstat; 605038032Speter{ 605138032Speter if (tTd(38, 20)) 605290792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 605338032Speter map->map_mname, name); 605438032Speter 605590792Sgshapiro#if NEWDB 605638032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 605738032Speter return db_map_lookup(map, name, av, pstat); 605864562Sgshapiro#endif /* NEWDB */ 605990792Sgshapiro#if NDBM 606038032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 606138032Speter return ndbm_map_lookup(map, name, av, pstat); 606264562Sgshapiro#endif /* NDBM */ 606338032Speter return stab_map_lookup(map, name, av, pstat); 606438032Speter} 606538032Speter 606638032Speter/* 606738032Speter** IMPL_MAP_STORE -- store in open databases 606838032Speter*/ 606938032Speter 607038032Spetervoid 607138032Speterimpl_map_store(map, lhs, rhs) 607238032Speter MAP *map; 607338032Speter char *lhs; 607438032Speter char *rhs; 607538032Speter{ 607638032Speter if (tTd(38, 12)) 607790792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 607838032Speter map->map_mname, lhs, rhs); 607990792Sgshapiro#if NEWDB 608038032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 608138032Speter db_map_store(map, lhs, rhs); 608264562Sgshapiro#endif /* NEWDB */ 608390792Sgshapiro#if NDBM 608438032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 608538032Speter ndbm_map_store(map, lhs, rhs); 608664562Sgshapiro#endif /* NDBM */ 608738032Speter stab_map_store(map, lhs, rhs); 608838032Speter} 608938032Speter 609038032Speter/* 609138032Speter** IMPL_MAP_OPEN -- implicit database open 609238032Speter*/ 609338032Speter 609438032Speterbool 609538032Speterimpl_map_open(map, mode) 609638032Speter MAP *map; 609738032Speter int mode; 609838032Speter{ 609938032Speter if (tTd(38, 2)) 610090792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 610138032Speter map->map_mname, map->map_file, mode); 610238032Speter 610338032Speter mode &= O_ACCMODE; 610490792Sgshapiro#if NEWDB 610538032Speter map->map_mflags |= MF_IMPL_HASH; 610638032Speter if (hash_map_open(map, mode)) 610738032Speter { 610838032Speter# ifdef NDBM_YP_COMPAT 610938032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 611064562Sgshapiro# endif /* NDBM_YP_COMPAT */ 611190792Sgshapiro return true; 611238032Speter } 611338032Speter else 611438032Speter map->map_mflags &= ~MF_IMPL_HASH; 611564562Sgshapiro#endif /* NEWDB */ 611690792Sgshapiro#if NDBM 611738032Speter map->map_mflags |= MF_IMPL_NDBM; 611838032Speter if (ndbm_map_open(map, mode)) 611938032Speter { 612090792Sgshapiro return true; 612138032Speter } 612238032Speter else 612338032Speter map->map_mflags &= ~MF_IMPL_NDBM; 612464562Sgshapiro#endif /* NDBM */ 612538032Speter 612638032Speter#if defined(NEWDB) || defined(NDBM) 612738032Speter if (Verbose) 612838032Speter message("WARNING: cannot open alias database %s%s", 612938032Speter map->map_file, 613038032Speter mode == O_RDONLY ? "; reading text version" : ""); 613164562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 613238032Speter if (mode != O_RDONLY) 613338032Speter usrerr("Cannot rebuild aliases: no database format defined"); 613464562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 613538032Speter 613638032Speter if (mode == O_RDONLY) 613738032Speter return stab_map_open(map, mode); 613838032Speter else 613990792Sgshapiro return false; 614038032Speter} 614138032Speter 614238032Speter 614338032Speter/* 614438032Speter** IMPL_MAP_CLOSE -- close any open database(s) 614538032Speter*/ 614638032Speter 614738032Spetervoid 614838032Speterimpl_map_close(map) 614938032Speter MAP *map; 615038032Speter{ 615138032Speter if (tTd(38, 9)) 615290792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 615338032Speter map->map_mname, map->map_file, map->map_mflags); 615490792Sgshapiro#if NEWDB 615538032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 615638032Speter { 615738032Speter db_map_close(map); 615838032Speter map->map_mflags &= ~MF_IMPL_HASH; 615938032Speter } 616064562Sgshapiro#endif /* NEWDB */ 616138032Speter 616290792Sgshapiro#if NDBM 616338032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 616438032Speter { 616538032Speter ndbm_map_close(map); 616638032Speter map->map_mflags &= ~MF_IMPL_NDBM; 616738032Speter } 616864562Sgshapiro#endif /* NDBM */ 616938032Speter} 617090792Sgshapiro/* 617138032Speter** User map class. 617238032Speter** 617338032Speter** Provides access to the system password file. 617438032Speter*/ 617538032Speter 617638032Speter/* 617738032Speter** USER_MAP_OPEN -- open user map 617838032Speter** 617938032Speter** Really just binds field names to field numbers. 618038032Speter*/ 618138032Speter 618238032Speterbool 618338032Speteruser_map_open(map, mode) 618438032Speter MAP *map; 618538032Speter int mode; 618638032Speter{ 618738032Speter if (tTd(38, 2)) 618890792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 618938032Speter map->map_mname, mode); 619038032Speter 619138032Speter mode &= O_ACCMODE; 619238032Speter if (mode != O_RDONLY) 619338032Speter { 619438032Speter /* issue a pseudo-error message */ 619590792Sgshapiro errno = SM_EMAPCANTWRITE; 619690792Sgshapiro return false; 619738032Speter } 619838032Speter if (map->map_valcolnm == NULL) 619964562Sgshapiro /* EMPTY */ 620038032Speter /* nothing */ ; 620190792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 620238032Speter map->map_valcolno = 1; 620390792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 620438032Speter map->map_valcolno = 2; 620590792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 620638032Speter map->map_valcolno = 3; 620790792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 620838032Speter map->map_valcolno = 4; 620990792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 621038032Speter map->map_valcolno = 5; 621190792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 621238032Speter map->map_valcolno = 6; 621390792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 621438032Speter map->map_valcolno = 7; 621538032Speter else 621638032Speter { 621738032Speter syserr("User map %s: unknown column name %s", 621838032Speter map->map_mname, map->map_valcolnm); 621990792Sgshapiro return false; 622038032Speter } 622190792Sgshapiro return true; 622238032Speter} 622338032Speter 622438032Speter 622538032Speter/* 622638032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 622738032Speter*/ 622838032Speter 622938032Speter/* ARGSUSED3 */ 623038032Speterchar * 623138032Speteruser_map_lookup(map, key, av, statp) 623238032Speter MAP *map; 623338032Speter char *key; 623438032Speter char **av; 623538032Speter int *statp; 623638032Speter{ 623738032Speter auto bool fuzzy; 623890792Sgshapiro SM_MBDB_T user; 623938032Speter 624038032Speter if (tTd(38, 20)) 624190792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 624238032Speter map->map_mname, key); 624338032Speter 624490792Sgshapiro *statp = finduser(key, &fuzzy, &user); 624590792Sgshapiro if (*statp != EX_OK) 624638032Speter return NULL; 624738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 624838032Speter return map_rewrite(map, key, strlen(key), NULL); 624938032Speter else 625038032Speter { 625138032Speter char *rwval = NULL; 625238032Speter char buf[30]; 625338032Speter 625438032Speter switch (map->map_valcolno) 625538032Speter { 625638032Speter case 0: 625738032Speter case 1: 625890792Sgshapiro rwval = user.mbdb_name; 625938032Speter break; 626038032Speter 626138032Speter case 2: 626290792Sgshapiro rwval = "x"; /* passwd no longer supported */ 626338032Speter break; 626438032Speter 626538032Speter case 3: 6266168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 626790792Sgshapiro (int) user.mbdb_uid); 626838032Speter rwval = buf; 626938032Speter break; 627038032Speter 627138032Speter case 4: 6272168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 627390792Sgshapiro (int) user.mbdb_gid); 627438032Speter rwval = buf; 627538032Speter break; 627638032Speter 627738032Speter case 5: 627890792Sgshapiro rwval = user.mbdb_fullname; 627938032Speter break; 628038032Speter 628138032Speter case 6: 628290792Sgshapiro rwval = user.mbdb_homedir; 628338032Speter break; 628438032Speter 628538032Speter case 7: 628690792Sgshapiro rwval = user.mbdb_shell; 628738032Speter break; 6288159609Sgshapiro default: 6289159609Sgshapiro syserr("user_map %s: bogus field %d", 6290159609Sgshapiro map->map_mname, map->map_valcolno); 6291159609Sgshapiro return NULL; 629238032Speter } 629338032Speter return map_rewrite(map, rwval, strlen(rwval), av); 629438032Speter } 629538032Speter} 629690792Sgshapiro/* 629738032Speter** Program map type. 629838032Speter** 629938032Speter** This provides access to arbitrary programs. It should be used 630038032Speter** only very sparingly, since there is no way to bound the cost 630138032Speter** of invoking an arbitrary program. 630238032Speter*/ 630338032Speter 630438032Speterchar * 630538032Speterprog_map_lookup(map, name, av, statp) 630638032Speter MAP *map; 630738032Speter char *name; 630838032Speter char **av; 630938032Speter int *statp; 631038032Speter{ 631138032Speter int i; 631264562Sgshapiro int save_errno; 631338032Speter int fd; 631464562Sgshapiro int status; 631538032Speter auto pid_t pid; 631664562Sgshapiro register char *p; 631738032Speter char *rval; 631838032Speter char *argv[MAXPV + 1]; 631938032Speter char buf[MAXLINE]; 632038032Speter 632138032Speter if (tTd(38, 20)) 632290792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 632338032Speter map->map_mname, name, map->map_file); 632438032Speter 632538032Speter i = 0; 632638032Speter argv[i++] = map->map_file; 632738032Speter if (map->map_rebuild != NULL) 632838032Speter { 6329168515Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof(buf)); 633038032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 633138032Speter { 633238032Speter if (i >= MAXPV - 1) 633338032Speter break; 633438032Speter argv[i++] = p; 633538032Speter } 633638032Speter } 633738032Speter argv[i++] = name; 633838032Speter argv[i] = NULL; 633938032Speter if (tTd(38, 21)) 634038032Speter { 634190792Sgshapiro sm_dprintf("prog_open:"); 634238032Speter for (i = 0; argv[i] != NULL; i++) 634390792Sgshapiro sm_dprintf(" %s", argv[i]); 634490792Sgshapiro sm_dprintf("\n"); 634538032Speter } 634690792Sgshapiro (void) sm_blocksignal(SIGCHLD); 634738032Speter pid = prog_open(argv, &fd, CurEnv); 634838032Speter if (pid < 0) 634938032Speter { 635038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 635138032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 635290792Sgshapiro map->map_mname, sm_errstring(errno)); 635338032Speter else if (tTd(38, 9)) 635490792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 635590792Sgshapiro map->map_mname, sm_errstring(errno)); 635638032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 635738032Speter *statp = EX_OSFILE; 635838032Speter return NULL; 635938032Speter } 6360168515Sgshapiro i = read(fd, buf, sizeof(buf) - 1); 636138032Speter if (i < 0) 636238032Speter { 636390792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 636490792Sgshapiro map->map_mname, sm_errstring(errno)); 636538032Speter rval = NULL; 636638032Speter } 636738032Speter else if (i == 0) 636838032Speter { 636938032Speter if (tTd(38, 20)) 637090792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 637190792Sgshapiro map->map_mname); 637238032Speter rval = NULL; 637338032Speter } 637438032Speter else 637538032Speter { 637638032Speter buf[i] = '\0'; 637738032Speter p = strchr(buf, '\n'); 637838032Speter if (p != NULL) 637938032Speter *p = '\0'; 638038032Speter 638138032Speter /* collect the return value */ 638238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 638338032Speter rval = map_rewrite(map, name, strlen(name), NULL); 638438032Speter else 638577349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 638638032Speter 638738032Speter /* now flush any additional output */ 6388168515Sgshapiro while ((i = read(fd, buf, sizeof(buf))) > 0) 638938032Speter continue; 639038032Speter } 639138032Speter 639238032Speter /* wait for the process to terminate */ 639364562Sgshapiro (void) close(fd); 639464562Sgshapiro status = waitfor(pid); 639564562Sgshapiro save_errno = errno; 639690792Sgshapiro (void) sm_releasesignal(SIGCHLD); 639764562Sgshapiro errno = save_errno; 639838032Speter 639964562Sgshapiro if (status == -1) 640038032Speter { 640190792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 640290792Sgshapiro map->map_mname, sm_errstring(errno)); 640338032Speter *statp = EX_SOFTWARE; 640438032Speter rval = NULL; 640538032Speter } 640664562Sgshapiro else if (WIFEXITED(status)) 640738032Speter { 640864562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 640938032Speter rval = NULL; 641038032Speter } 641138032Speter else 641238032Speter { 641338032Speter syserr("prog_map_lookup(%s): child died on signal %d", 641490792Sgshapiro map->map_mname, status); 641538032Speter *statp = EX_UNAVAILABLE; 641638032Speter rval = NULL; 641738032Speter } 641838032Speter return rval; 641938032Speter} 642090792Sgshapiro/* 642138032Speter** Sequenced map type. 642238032Speter** 642338032Speter** Tries each map in order until something matches, much like 642438032Speter** implicit. Stores go to the first map in the list that can 642538032Speter** support storing. 642638032Speter** 642738032Speter** This is slightly unusual in that there are two interfaces. 642838032Speter** The "sequence" interface lets you stack maps arbitrarily. 642938032Speter** The "switch" interface builds a sequence map by looking 643038032Speter** at a system-dependent configuration file such as 643138032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 643238032Speter** 643338032Speter** We don't need an explicit open, since all maps are 643490792Sgshapiro** opened on demand. 643538032Speter*/ 643638032Speter 643738032Speter/* 643838032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 643938032Speter*/ 644038032Speter 644138032Speterbool 644238032Speterseq_map_parse(map, ap) 644338032Speter MAP *map; 644438032Speter char *ap; 644538032Speter{ 644638032Speter int maxmap; 644738032Speter 644838032Speter if (tTd(38, 2)) 644990792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 645038032Speter maxmap = 0; 645138032Speter while (*ap != '\0') 645238032Speter { 645338032Speter register char *p; 645438032Speter STAB *s; 645538032Speter 645638032Speter /* find beginning of map name */ 645738032Speter while (isascii(*ap) && isspace(*ap)) 645838032Speter ap++; 645964562Sgshapiro for (p = ap; 646064562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 646164562Sgshapiro p++) 646238032Speter continue; 646338032Speter if (*p != '\0') 646438032Speter *p++ = '\0'; 646538032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 646638032Speter p++; 646738032Speter if (*ap == '\0') 646838032Speter { 646938032Speter ap = p; 647038032Speter continue; 647138032Speter } 647238032Speter s = stab(ap, ST_MAP, ST_FIND); 647338032Speter if (s == NULL) 647438032Speter { 647538032Speter syserr("Sequence map %s: unknown member map %s", 647638032Speter map->map_mname, ap); 647738032Speter } 647890792Sgshapiro else if (maxmap >= MAXMAPSTACK) 647938032Speter { 648038032Speter syserr("Sequence map %s: too many member maps (%d max)", 648138032Speter map->map_mname, MAXMAPSTACK); 648238032Speter maxmap++; 648338032Speter } 648438032Speter else if (maxmap < MAXMAPSTACK) 648538032Speter { 648638032Speter map->map_stack[maxmap++] = &s->s_map; 648738032Speter } 648838032Speter ap = p; 648938032Speter } 649090792Sgshapiro return true; 649138032Speter} 649238032Speter 649338032Speter/* 649438032Speter** SWITCH_MAP_OPEN -- open a switched map 649538032Speter** 649638032Speter** This looks at the system-dependent configuration and builds 649738032Speter** a sequence map that does the same thing. 649838032Speter** 649938032Speter** Every system must define a switch_map_find routine in conf.c 650038032Speter** that will return the list of service types associated with a 650138032Speter** given service class. 650238032Speter*/ 650338032Speter 650438032Speterbool 650538032Speterswitch_map_open(map, mode) 650638032Speter MAP *map; 650738032Speter int mode; 650838032Speter{ 650938032Speter int mapno; 651038032Speter int nmaps; 651138032Speter char *maptype[MAXMAPSTACK]; 651238032Speter 651338032Speter if (tTd(38, 2)) 651490792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 651538032Speter map->map_mname, map->map_file, mode); 651638032Speter 651738032Speter mode &= O_ACCMODE; 651838032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 651938032Speter if (tTd(38, 19)) 652038032Speter { 652190792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 652238032Speter for (mapno = 0; mapno < nmaps; mapno++) 652390792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 652438032Speter } 652538032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 652690792Sgshapiro return false; 652738032Speter 652838032Speter for (mapno = 0; mapno < nmaps; mapno++) 652938032Speter { 653038032Speter register STAB *s; 653138032Speter char nbuf[MAXNAME + 1]; 653238032Speter 653338032Speter if (maptype[mapno] == NULL) 653438032Speter continue; 6535168515Sgshapiro (void) sm_strlcpyn(nbuf, sizeof(nbuf), 3, 653690792Sgshapiro map->map_mname, ".", maptype[mapno]); 653738032Speter s = stab(nbuf, ST_MAP, ST_FIND); 653838032Speter if (s == NULL) 653938032Speter { 654038032Speter syserr("Switch map %s: unknown member map %s", 654138032Speter map->map_mname, nbuf); 654238032Speter } 654338032Speter else 654438032Speter { 654538032Speter map->map_stack[mapno] = &s->s_map; 654638032Speter if (tTd(38, 4)) 654790792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 654890792Sgshapiro mapno, 654990792Sgshapiro s->s_map.map_class->map_cname, 655090792Sgshapiro nbuf); 655138032Speter } 655238032Speter } 655390792Sgshapiro return true; 655438032Speter} 655538032Speter 655690792Sgshapiro#if 0 655738032Speter/* 655838032Speter** SEQ_MAP_CLOSE -- close all underlying maps 655938032Speter*/ 656038032Speter 656138032Spetervoid 656238032Speterseq_map_close(map) 656338032Speter MAP *map; 656438032Speter{ 656538032Speter int mapno; 656638032Speter 656738032Speter if (tTd(38, 9)) 656890792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 656938032Speter 657038032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 657138032Speter { 657238032Speter MAP *mm = map->map_stack[mapno]; 657338032Speter 657438032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 657538032Speter continue; 657677349Sgshapiro mm->map_mflags |= MF_CLOSING; 657738032Speter mm->map_class->map_close(mm); 657877349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 657938032Speter } 658038032Speter} 658190792Sgshapiro#endif /* 0 */ 658238032Speter 658338032Speter/* 658438032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 658538032Speter*/ 658638032Speter 658738032Speterchar * 658838032Speterseq_map_lookup(map, key, args, pstat) 658938032Speter MAP *map; 659038032Speter char *key; 659138032Speter char **args; 659238032Speter int *pstat; 659338032Speter{ 659438032Speter int mapno; 659538032Speter int mapbit = 0x01; 659690792Sgshapiro bool tempfail = false; 659738032Speter 659838032Speter if (tTd(38, 20)) 659990792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 660038032Speter 660138032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 660238032Speter { 660338032Speter MAP *mm = map->map_stack[mapno]; 660438032Speter char *rv; 660538032Speter 660638032Speter if (mm == NULL) 660738032Speter continue; 660864562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 660964562Sgshapiro !openmap(mm)) 661038032Speter { 661138032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 661238032Speter { 661338032Speter *pstat = EX_UNAVAILABLE; 661438032Speter return NULL; 661538032Speter } 661638032Speter continue; 661738032Speter } 661838032Speter *pstat = EX_OK; 661938032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 662038032Speter if (rv != NULL) 662138032Speter return rv; 662238032Speter if (*pstat == EX_TEMPFAIL) 662338032Speter { 662438032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 662538032Speter return NULL; 662690792Sgshapiro tempfail = true; 662738032Speter } 662838032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 662938032Speter break; 663038032Speter } 663138032Speter if (tempfail) 663238032Speter *pstat = EX_TEMPFAIL; 663338032Speter else if (*pstat == EX_OK) 663438032Speter *pstat = EX_NOTFOUND; 663538032Speter return NULL; 663638032Speter} 663738032Speter 663838032Speter/* 663938032Speter** SEQ_MAP_STORE -- sequenced map store 664038032Speter*/ 664138032Speter 664238032Spetervoid 664338032Speterseq_map_store(map, key, val) 664438032Speter MAP *map; 664538032Speter char *key; 664638032Speter char *val; 664738032Speter{ 664838032Speter int mapno; 664938032Speter 665038032Speter if (tTd(38, 12)) 665190792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 665238032Speter map->map_mname, key, val); 665338032Speter 665438032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 665538032Speter { 665638032Speter MAP *mm = map->map_stack[mapno]; 665738032Speter 665838032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 665938032Speter continue; 666038032Speter 666138032Speter mm->map_class->map_store(mm, key, val); 666238032Speter return; 666338032Speter } 666438032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 666538032Speter map->map_mname, key, val); 666638032Speter} 666790792Sgshapiro/* 666838032Speter** NULL stubs 666938032Speter*/ 667038032Speter 667138032Speter/* ARGSUSED */ 667238032Speterbool 667338032Speternull_map_open(map, mode) 667438032Speter MAP *map; 667538032Speter int mode; 667638032Speter{ 667790792Sgshapiro return true; 667838032Speter} 667938032Speter 668038032Speter/* ARGSUSED */ 668138032Spetervoid 668238032Speternull_map_close(map) 668338032Speter MAP *map; 668438032Speter{ 668538032Speter return; 668638032Speter} 668738032Speter 668838032Speterchar * 668938032Speternull_map_lookup(map, key, args, pstat) 669038032Speter MAP *map; 669138032Speter char *key; 669238032Speter char **args; 669338032Speter int *pstat; 669438032Speter{ 669538032Speter *pstat = EX_NOTFOUND; 669638032Speter return NULL; 669738032Speter} 669838032Speter 669938032Speter/* ARGSUSED */ 670038032Spetervoid 670138032Speternull_map_store(map, key, val) 670238032Speter MAP *map; 670338032Speter char *key; 670438032Speter char *val; 670538032Speter{ 670638032Speter return; 670738032Speter} 670838032Speter 6709203004SgshapiroMAPCLASS NullMapClass = 6710203004Sgshapiro{ 6711203004Sgshapiro "null-map", NULL, 0, 6712203004Sgshapiro NULL, null_map_lookup, null_map_store, 6713203004Sgshapiro null_map_open, null_map_close, 6714203004Sgshapiro}; 6715203004Sgshapiro 671638032Speter/* 671738032Speter** BOGUS stubs 671838032Speter*/ 671938032Speter 672038032Speterchar * 672138032Speterbogus_map_lookup(map, key, args, pstat) 672238032Speter MAP *map; 672338032Speter char *key; 672438032Speter char **args; 672538032Speter int *pstat; 672638032Speter{ 672738032Speter *pstat = EX_TEMPFAIL; 672838032Speter return NULL; 672938032Speter} 673038032Speter 673138032SpeterMAPCLASS BogusMapClass = 673238032Speter{ 673390792Sgshapiro "bogus-map", NULL, 0, 673490792Sgshapiro NULL, bogus_map_lookup, null_map_store, 673590792Sgshapiro null_map_open, null_map_close, 673638032Speter}; 673790792Sgshapiro/* 673864562Sgshapiro** MACRO modules 673964562Sgshapiro*/ 674064562Sgshapiro 674164562Sgshapirochar * 674264562Sgshapiromacro_map_lookup(map, name, av, statp) 674364562Sgshapiro MAP *map; 674464562Sgshapiro char *name; 674564562Sgshapiro char **av; 674664562Sgshapiro int *statp; 674764562Sgshapiro{ 674864562Sgshapiro int mid; 674964562Sgshapiro 675064562Sgshapiro if (tTd(38, 20)) 675190792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 675264562Sgshapiro name == NULL ? "NULL" : name); 675364562Sgshapiro 675464562Sgshapiro if (name == NULL || 675564562Sgshapiro *name == '\0' || 675690792Sgshapiro (mid = macid(name)) == 0) 675764562Sgshapiro { 675864562Sgshapiro *statp = EX_CONFIG; 675964562Sgshapiro return NULL; 676064562Sgshapiro } 676164562Sgshapiro 676264562Sgshapiro if (av[1] == NULL) 676390792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 676464562Sgshapiro else 676590792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 676664562Sgshapiro 676764562Sgshapiro *statp = EX_OK; 676864562Sgshapiro return ""; 676964562Sgshapiro} 677090792Sgshapiro/* 677138032Speter** REGEX modules 677238032Speter*/ 677338032Speter 677490792Sgshapiro#if MAP_REGEX 677538032Speter 677638032Speter# include <regex.h> 677738032Speter 677838032Speter# define DEFAULT_DELIM CONDELSE 677938032Speter# define END_OF_FIELDS -1 678038032Speter# define ERRBUF_SIZE 80 678138032Speter# define MAX_MATCH 32 678238032Speter 678364562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 678438032Speter 678538032Speterstruct regex_map 678638032Speter{ 678771345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 678838032Speter int *regex_subfields; /* move to type MAP */ 678964562Sgshapiro char *regex_delim; /* move to type MAP */ 679038032Speter}; 679138032Speter 6792141858Sgshapirostatic int parse_fields __P((char *, int *, int, int)); 6793141858Sgshapirostatic char *regex_map_rewrite __P((MAP *, const char*, size_t, char **)); 6794141858Sgshapiro 679538032Speterstatic int 679638032Speterparse_fields(s, ibuf, blen, nr_substrings) 679738032Speter char *s; 679838032Speter int *ibuf; /* array */ 679938032Speter int blen; /* number of elements in ibuf */ 680038032Speter int nr_substrings; /* number of substrings in the pattern */ 680138032Speter{ 680238032Speter register char *cp; 680338032Speter int i = 0; 680490792Sgshapiro bool lastone = false; 680538032Speter 680638032Speter blen--; /* for terminating END_OF_FIELDS */ 680738032Speter cp = s; 680838032Speter do 680938032Speter { 681038032Speter for (;; cp++) 681138032Speter { 681238032Speter if (*cp == ',') 681338032Speter { 681438032Speter *cp = '\0'; 681538032Speter break; 681638032Speter } 681738032Speter if (*cp == '\0') 681838032Speter { 681990792Sgshapiro lastone = true; 682038032Speter break; 682138032Speter } 682238032Speter } 682338032Speter if (i < blen) 682438032Speter { 682538032Speter int val = atoi(s); 682638032Speter 682738032Speter if (val < 0 || val >= nr_substrings) 682838032Speter { 682938032Speter syserr("field (%d) out of range, only %d substrings in pattern", 683038032Speter val, nr_substrings); 683138032Speter return -1; 683238032Speter } 683338032Speter ibuf[i++] = val; 683438032Speter } 683538032Speter else 683638032Speter { 683790792Sgshapiro syserr("too many fields, %d max", blen); 683838032Speter return -1; 683938032Speter } 684038032Speter s = ++cp; 684138032Speter } while (!lastone); 684238032Speter ibuf[i] = END_OF_FIELDS; 684338032Speter return i; 684438032Speter} 684538032Speter 684638032Speterbool 684738032Speterregex_map_init(map, ap) 684838032Speter MAP *map; 684938032Speter char *ap; 685038032Speter{ 685138032Speter int regerr; 685238032Speter struct regex_map *map_p; 685338032Speter register char *p; 685438032Speter char *sub_param = NULL; 685538032Speter int pflags; 685690792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 685738032Speter 685838032Speter if (tTd(38, 2)) 685990792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 686064562Sgshapiro map->map_mname, ap); 686138032Speter 686238032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 686338032Speter p = ap; 6864168515Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof(*map_p)); 686571345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 686638032Speter 686738032Speter for (;;) 686864562Sgshapiro { 686938032Speter while (isascii(*p) && isspace(*p)) 687038032Speter p++; 687138032Speter if (*p != '-') 687238032Speter break; 687338032Speter switch (*++p) 687438032Speter { 687538032Speter case 'n': /* not */ 687638032Speter map->map_mflags |= MF_REGEX_NOT; 687738032Speter break; 687838032Speter 687938032Speter case 'f': /* case sensitive */ 688038032Speter map->map_mflags |= MF_NOFOLDCASE; 688138032Speter pflags &= ~REG_ICASE; 688238032Speter break; 688338032Speter 688438032Speter case 'b': /* basic regular expressions */ 688538032Speter pflags &= ~REG_EXTENDED; 688638032Speter break; 688738032Speter 688838032Speter case 's': /* substring match () syntax */ 688938032Speter sub_param = ++p; 689038032Speter pflags &= ~REG_NOSUB; 689138032Speter break; 689238032Speter 689338032Speter case 'd': /* delimiter */ 689464562Sgshapiro map_p->regex_delim = ++p; 689538032Speter break; 689638032Speter 689738032Speter case 'a': /* map append */ 689838032Speter map->map_app = ++p; 689938032Speter break; 690038032Speter 690138032Speter case 'm': /* matchonly */ 690238032Speter map->map_mflags |= MF_MATCHONLY; 690338032Speter break; 690438032Speter 6905120256Sgshapiro case 'q': 6906120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 6907120256Sgshapiro break; 6908120256Sgshapiro 690964562Sgshapiro case 'S': 691064562Sgshapiro map->map_spacesub = *++p; 691164562Sgshapiro break; 691264562Sgshapiro 691364562Sgshapiro case 'D': 691464562Sgshapiro map->map_mflags |= MF_DEFER; 691564562Sgshapiro break; 691664562Sgshapiro 691738032Speter } 691864562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 691964562Sgshapiro p++; 692064562Sgshapiro if (*p != '\0') 692164562Sgshapiro *p++ = '\0'; 692238032Speter } 692338032Speter if (tTd(38, 3)) 692490792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 692538032Speter 692671345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 692738032Speter { 692838032Speter /* Errorhandling */ 692938032Speter char errbuf[ERRBUF_SIZE]; 693038032Speter 693171345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 6932168515Sgshapiro errbuf, sizeof(errbuf)); 693390792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 693490792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 693590792Sgshapiro sm_free(map_p); /* XXX */ 693690792Sgshapiro return false; 693738032Speter } 693838032Speter 693938032Speter if (map->map_app != NULL) 694038032Speter map->map_app = newstr(map->map_app); 694164562Sgshapiro if (map_p->regex_delim != NULL) 694264562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 694338032Speter else 694464562Sgshapiro map_p->regex_delim = defdstr; 694538032Speter 694638032Speter if (!bitset(REG_NOSUB, pflags)) 694738032Speter { 694838032Speter /* substring matching */ 694938032Speter int substrings; 695064562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 695138032Speter 695271345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 695338032Speter 695438032Speter if (tTd(38, 3)) 695590792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 695664562Sgshapiro substrings); 695738032Speter 695838032Speter if (substrings >= MAX_MATCH) 695938032Speter { 696090792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 696190792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 696290792Sgshapiro sm_free(map_p); /* XXX */ 696390792Sgshapiro return false; 696438032Speter } 696538032Speter if (sub_param != NULL && sub_param[0] != '\0') 696638032Speter { 696738032Speter /* optional parameter -sfields */ 696838032Speter if (parse_fields(sub_param, fields, 696938032Speter MAX_MATCH + 1, substrings) == -1) 697090792Sgshapiro return false; 697138032Speter } 697238032Speter else 697338032Speter { 697438032Speter int i; 697538032Speter 697690792Sgshapiro /* set default fields */ 697738032Speter for (i = 0; i < substrings; i++) 697838032Speter fields[i] = i; 697938032Speter fields[i] = END_OF_FIELDS; 698038032Speter } 698138032Speter map_p->regex_subfields = fields; 698238032Speter if (tTd(38, 3)) 698338032Speter { 698438032Speter int *ip; 698538032Speter 698690792Sgshapiro sm_dprintf("regex_map_init: subfields"); 698738032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 698890792Sgshapiro sm_dprintf(" %d", *ip); 698990792Sgshapiro sm_dprintf("\n"); 699038032Speter } 699138032Speter } 699290792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 699390792Sgshapiro return true; 699438032Speter} 699538032Speter 699638032Speterstatic char * 699738032Speterregex_map_rewrite(map, s, slen, av) 699838032Speter MAP *map; 699938032Speter const char *s; 700038032Speter size_t slen; 700138032Speter char **av; 700238032Speter{ 700338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 700438032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 700538032Speter else 700677349Sgshapiro return map_rewrite(map, s, slen, av); 700738032Speter} 700838032Speter 700938032Speterchar * 701038032Speterregex_map_lookup(map, name, av, statp) 701138032Speter MAP *map; 701238032Speter char *name; 701338032Speter char **av; 701438032Speter int *statp; 701538032Speter{ 701638032Speter int reg_res; 701738032Speter struct regex_map *map_p; 701838032Speter regmatch_t pmatch[MAX_MATCH]; 701938032Speter 702038032Speter if (tTd(38, 20)) 702138032Speter { 702238032Speter char **cpp; 702338032Speter 702490792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 702564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 702690792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 702738032Speter } 702838032Speter 702938032Speter map_p = (struct regex_map *)(map->map_db1); 703071345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 703164562Sgshapiro name, MAX_MATCH, pmatch, 0); 703238032Speter 703338032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 703438032Speter { 703538032Speter /* option -n */ 703638032Speter if (reg_res == REG_NOMATCH) 703790792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 703838032Speter else 703938032Speter return NULL; 704038032Speter } 704138032Speter if (reg_res == REG_NOMATCH) 704238032Speter return NULL; 704338032Speter 704438032Speter if (map_p->regex_subfields != NULL) 704538032Speter { 704638032Speter /* option -s */ 704738032Speter static char retbuf[MAXNAME]; 704838032Speter int fields[MAX_MATCH + 1]; 704990792Sgshapiro bool first = true; 705038032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 705190792Sgshapiro bool quotemode = false, bslashmode = false; 705238032Speter register char *dp, *sp; 705338032Speter char *endp, *ldp; 705438032Speter int *ip; 705538032Speter 705638032Speter dp = retbuf; 705738032Speter ldp = retbuf + sizeof(retbuf) - 1; 705838032Speter 705938032Speter if (av[1] != NULL) 706038032Speter { 706138032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 706271345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 706338032Speter { 706438032Speter *statp = EX_CONFIG; 706538032Speter return NULL; 706638032Speter } 706738032Speter ip = fields; 706838032Speter } 706938032Speter else 707038032Speter ip = map_p->regex_subfields; 707138032Speter 707238032Speter for ( ; *ip != END_OF_FIELDS; ip++) 707338032Speter { 707438032Speter if (!first) 707538032Speter { 707664562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 707738032Speter { 707838032Speter if (dp < ldp) 707938032Speter *dp++ = *sp; 708038032Speter } 708138032Speter } 708238032Speter else 708390792Sgshapiro first = false; 708438032Speter 708571345Sgshapiro if (*ip >= MAX_MATCH || 708671345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 708738032Speter continue; 708838032Speter 708938032Speter sp = name + pmatch[*ip].rm_so; 709038032Speter endp = name + pmatch[*ip].rm_eo; 709138032Speter for (; endp > sp; sp++) 709238032Speter { 709338032Speter if (dp < ldp) 709438032Speter { 709564562Sgshapiro if (bslashmode) 709664562Sgshapiro { 709738032Speter *dp++ = *sp; 709890792Sgshapiro bslashmode = false; 709938032Speter } 710064562Sgshapiro else if (quotemode && *sp != '"' && 710138032Speter *sp != '\\') 710238032Speter { 710338032Speter *dp++ = *sp; 710438032Speter } 710590792Sgshapiro else switch (*dp++ = *sp) 710638032Speter { 710790792Sgshapiro case '\\': 710890792Sgshapiro bslashmode = true; 710938032Speter break; 711038032Speter 711190792Sgshapiro case '(': 711238032Speter cmntcnt++; 711338032Speter break; 711438032Speter 711590792Sgshapiro case ')': 711638032Speter cmntcnt--; 711738032Speter break; 711838032Speter 711990792Sgshapiro case '<': 712038032Speter anglecnt++; 712138032Speter break; 712238032Speter 712390792Sgshapiro case '>': 712438032Speter anglecnt--; 712538032Speter break; 712638032Speter 712790792Sgshapiro case ' ': 712838032Speter spacecnt++; 712938032Speter break; 713038032Speter 713190792Sgshapiro case '"': 713238032Speter quotemode = !quotemode; 713338032Speter break; 713438032Speter } 713538032Speter } 713638032Speter } 713738032Speter } 713838032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 713938032Speter bslashmode || spacecnt != 0) 714038032Speter { 714164562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 714264562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 714364562Sgshapiro map->map_mname, name); 714438032Speter return NULL; 714538032Speter } 714638032Speter 714738032Speter *dp = '\0'; 714838032Speter 714938032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 715038032Speter } 715138032Speter return regex_map_rewrite(map, "", (size_t)0, av); 715238032Speter} 715338032Speter#endif /* MAP_REGEX */ 715490792Sgshapiro/* 715564562Sgshapiro** NSD modules 715664562Sgshapiro*/ 715790792Sgshapiro#if MAP_NSD 715864562Sgshapiro 715964562Sgshapiro# include <ndbm.h> 716064562Sgshapiro# define _DATUM_DEFINED 716164562Sgshapiro# include <ns_api.h> 716264562Sgshapiro 716364562Sgshapirotypedef struct ns_map_list 716464562Sgshapiro{ 716590792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 716690792Sgshapiro char *mapname; 716790792Sgshapiro struct ns_map_list *next; 716864562Sgshapiro} ns_map_list_t; 716964562Sgshapiro 717064562Sgshapirostatic ns_map_t * 717164562Sgshapirons_map_t_find(mapname) 717264562Sgshapiro char *mapname; 717364562Sgshapiro{ 717464562Sgshapiro static ns_map_list_t *ns_maps = NULL; 717564562Sgshapiro ns_map_list_t *ns_map; 717664562Sgshapiro 717764562Sgshapiro /* walk the list of maps looking for the correctly named map */ 717864562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 717964562Sgshapiro { 718064562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 718164562Sgshapiro break; 718264562Sgshapiro } 718364562Sgshapiro 718464562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 718564562Sgshapiro if (ns_map == NULL) 718664562Sgshapiro { 7187168515Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof(*ns_map)); 718864562Sgshapiro ns_map->mapname = newstr(mapname); 7189168515Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof(*ns_map->map)); 7190168515Sgshapiro memset(ns_map->map, '\0', sizeof(*ns_map->map)); 719164562Sgshapiro ns_map->next = ns_maps; 719264562Sgshapiro ns_maps = ns_map; 719364562Sgshapiro } 719464562Sgshapiro return ns_map->map; 719564562Sgshapiro} 719664562Sgshapiro 719764562Sgshapirochar * 719864562Sgshapironsd_map_lookup(map, name, av, statp) 719964562Sgshapiro MAP *map; 720064562Sgshapiro char *name; 720164562Sgshapiro char **av; 720264562Sgshapiro int *statp; 720364562Sgshapiro{ 720471345Sgshapiro int buflen, r; 720564562Sgshapiro char *p; 720664562Sgshapiro ns_map_t *ns_map; 720764562Sgshapiro char keybuf[MAXNAME + 1]; 720864562Sgshapiro char buf[MAXLINE]; 720964562Sgshapiro 721064562Sgshapiro if (tTd(38, 20)) 721190792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 721264562Sgshapiro 721364562Sgshapiro buflen = strlen(name); 7214168515Sgshapiro if (buflen > sizeof(keybuf) - 1) 7215168515Sgshapiro buflen = sizeof(keybuf) - 1; /* XXX simply cut off? */ 721664562Sgshapiro memmove(keybuf, name, buflen); 721764562Sgshapiro keybuf[buflen] = '\0'; 721864562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 721964562Sgshapiro makelower(keybuf); 722064562Sgshapiro 722164562Sgshapiro ns_map = ns_map_t_find(map->map_file); 722264562Sgshapiro if (ns_map == NULL) 722364562Sgshapiro { 722464562Sgshapiro if (tTd(38, 20)) 722590792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 722671345Sgshapiro *statp = EX_UNAVAILABLE; 722764562Sgshapiro return NULL; 722864562Sgshapiro } 722998121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 7230168515Sgshapiro buf, sizeof(buf)); 723171345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 723271345Sgshapiro { 723371345Sgshapiro *statp = EX_TEMPFAIL; 723464562Sgshapiro return NULL; 723571345Sgshapiro } 723677349Sgshapiro if (r == NS_BADREQ 723777349Sgshapiro# ifdef NS_NOPERM 723877349Sgshapiro || r == NS_NOPERM 723977349Sgshapiro# endif /* NS_NOPERM */ 724077349Sgshapiro ) 724171345Sgshapiro { 724271345Sgshapiro *statp = EX_CONFIG; 724371345Sgshapiro return NULL; 724471345Sgshapiro } 724571345Sgshapiro if (r != NS_SUCCESS) 724671345Sgshapiro { 724771345Sgshapiro *statp = EX_NOTFOUND; 724871345Sgshapiro return NULL; 724971345Sgshapiro } 725064562Sgshapiro 725171345Sgshapiro *statp = EX_OK; 725271345Sgshapiro 725364562Sgshapiro /* Null out trailing \n */ 725464562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 725564562Sgshapiro *p = '\0'; 725664562Sgshapiro 725764562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 725864562Sgshapiro} 725964562Sgshapiro#endif /* MAP_NSD */ 726064562Sgshapiro 726164562Sgshapirochar * 726264562Sgshapiroarith_map_lookup(map, name, av, statp) 726364562Sgshapiro MAP *map; 726464562Sgshapiro char *name; 726564562Sgshapiro char **av; 726664562Sgshapiro int *statp; 726764562Sgshapiro{ 726864562Sgshapiro long r; 726964562Sgshapiro long v[2]; 727090792Sgshapiro bool res = false; 727164562Sgshapiro bool boolres; 727264562Sgshapiro static char result[16]; 727364562Sgshapiro char **cpp; 727464562Sgshapiro 727564562Sgshapiro if (tTd(38, 2)) 727664562Sgshapiro { 727790792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 727864562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 727990792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 728064562Sgshapiro } 728164562Sgshapiro r = 0; 728290792Sgshapiro boolres = false; 728364562Sgshapiro cpp = av; 728464562Sgshapiro *statp = EX_OK; 728564562Sgshapiro 728664562Sgshapiro /* 728764562Sgshapiro ** read arguments for arith map 728864562Sgshapiro ** - no check is made whether they are really numbers 728964562Sgshapiro ** - just ignores args after the second 729064562Sgshapiro */ 729190792Sgshapiro 729264562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 729364562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 729464562Sgshapiro 729564562Sgshapiro /* operator and (at least) two operands given? */ 729664562Sgshapiro if (name != NULL && r == 2) 729764562Sgshapiro { 729890792Sgshapiro switch (*name) 729964562Sgshapiro { 730064562Sgshapiro case '|': 730164562Sgshapiro r = v[0] | v[1]; 730264562Sgshapiro break; 730364562Sgshapiro 730464562Sgshapiro case '&': 730564562Sgshapiro r = v[0] & v[1]; 730664562Sgshapiro break; 730764562Sgshapiro 730864562Sgshapiro case '%': 730964562Sgshapiro if (v[1] == 0) 731064562Sgshapiro return NULL; 731164562Sgshapiro r = v[0] % v[1]; 731264562Sgshapiro break; 731364562Sgshapiro case '+': 731464562Sgshapiro r = v[0] + v[1]; 731564562Sgshapiro break; 731664562Sgshapiro 731764562Sgshapiro case '-': 731864562Sgshapiro r = v[0] - v[1]; 731964562Sgshapiro break; 732064562Sgshapiro 732164562Sgshapiro case '*': 732264562Sgshapiro r = v[0] * v[1]; 732364562Sgshapiro break; 732464562Sgshapiro 732564562Sgshapiro case '/': 732664562Sgshapiro if (v[1] == 0) 732764562Sgshapiro return NULL; 732864562Sgshapiro r = v[0] / v[1]; 732964562Sgshapiro break; 733064562Sgshapiro 733164562Sgshapiro case 'l': 733264562Sgshapiro res = v[0] < v[1]; 733390792Sgshapiro boolres = true; 733464562Sgshapiro break; 733564562Sgshapiro 733664562Sgshapiro case '=': 733764562Sgshapiro res = v[0] == v[1]; 733890792Sgshapiro boolres = true; 733964562Sgshapiro break; 734064562Sgshapiro 7341168515Sgshapiro case 'r': 7342168515Sgshapiro r = v[1] - v[0] + 1; 7343168515Sgshapiro if (r <= 0) 7344168515Sgshapiro return NULL; 7345168515Sgshapiro r = get_random() % r + v[0]; 7346168515Sgshapiro break; 7347168515Sgshapiro 734864562Sgshapiro default: 734964562Sgshapiro /* XXX */ 735064562Sgshapiro *statp = EX_CONFIG; 735164562Sgshapiro if (LogLevel > 10) 735264562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 735364562Sgshapiro "arith_map: unknown operator %c", 7354203004Sgshapiro (isascii(*name) && isprint(*name)) ? 7355203004Sgshapiro *name : '?'); 735664562Sgshapiro return NULL; 735764562Sgshapiro } 735864562Sgshapiro if (boolres) 7359168515Sgshapiro (void) sm_snprintf(result, sizeof(result), 736090792Sgshapiro res ? "TRUE" : "FALSE"); 736164562Sgshapiro else 7362168515Sgshapiro (void) sm_snprintf(result, sizeof(result), "%ld", r); 736364562Sgshapiro return result; 736464562Sgshapiro } 736564562Sgshapiro *statp = EX_CONFIG; 736664562Sgshapiro return NULL; 736764562Sgshapiro} 7368132943Sgshapiro 7369132943Sgshapiro#if SOCKETMAP 7370132943Sgshapiro 7371132943Sgshapiro# if NETINET || NETINET6 7372132943Sgshapiro# include <arpa/inet.h> 7373132943Sgshapiro# endif /* NETINET || NETINET6 */ 7374132943Sgshapiro 7375132943Sgshapiro# define socket_map_next map_stack[0] 7376132943Sgshapiro 7377132943Sgshapiro/* 7378132943Sgshapiro** SOCKET_MAP_OPEN -- open socket table 7379132943Sgshapiro*/ 7380132943Sgshapiro 7381132943Sgshapirobool 7382132943Sgshapirosocket_map_open(map, mode) 7383132943Sgshapiro MAP *map; 7384132943Sgshapiro int mode; 7385132943Sgshapiro{ 7386132943Sgshapiro STAB *s; 7387132943Sgshapiro int sock = 0; 7388132943Sgshapiro SOCKADDR_LEN_T addrlen = 0; 7389132943Sgshapiro int addrno = 0; 7390132943Sgshapiro int save_errno; 7391132943Sgshapiro char *p; 7392132943Sgshapiro char *colon; 7393132943Sgshapiro char *at; 7394132943Sgshapiro struct hostent *hp = NULL; 7395132943Sgshapiro SOCKADDR addr; 7396132943Sgshapiro 7397132943Sgshapiro if (tTd(38, 2)) 7398132943Sgshapiro sm_dprintf("socket_map_open(%s, %s, %d)\n", 7399132943Sgshapiro map->map_mname, map->map_file, mode); 7400132943Sgshapiro 7401132943Sgshapiro mode &= O_ACCMODE; 7402132943Sgshapiro 7403132943Sgshapiro /* sendmail doesn't have the ability to write to SOCKET (yet) */ 7404132943Sgshapiro if (mode != O_RDONLY) 7405132943Sgshapiro { 7406132943Sgshapiro /* issue a pseudo-error message */ 7407132943Sgshapiro errno = SM_EMAPCANTWRITE; 7408132943Sgshapiro return false; 7409132943Sgshapiro } 7410132943Sgshapiro 7411132943Sgshapiro if (*map->map_file == '\0') 7412132943Sgshapiro { 7413132943Sgshapiro syserr("socket map \"%s\": empty or missing socket information", 7414132943Sgshapiro map->map_mname); 7415132943Sgshapiro return false; 7416132943Sgshapiro } 7417132943Sgshapiro 7418132943Sgshapiro s = socket_map_findconn(map->map_file); 7419132943Sgshapiro if (s->s_socketmap != NULL) 7420132943Sgshapiro { 7421132943Sgshapiro /* Copy open connection */ 7422132943Sgshapiro map->map_db1 = s->s_socketmap->map_db1; 7423132943Sgshapiro 7424132943Sgshapiro /* Add this map as head of linked list */ 7425132943Sgshapiro map->socket_map_next = s->s_socketmap; 7426132943Sgshapiro s->s_socketmap = map; 7427132943Sgshapiro 7428132943Sgshapiro if (tTd(38, 2)) 7429132943Sgshapiro sm_dprintf("using cached connection\n"); 7430132943Sgshapiro return true; 7431132943Sgshapiro } 7432132943Sgshapiro 7433132943Sgshapiro if (tTd(38, 2)) 7434132943Sgshapiro sm_dprintf("opening new connection\n"); 7435132943Sgshapiro 7436132943Sgshapiro /* following code is ripped from milter.c */ 7437132943Sgshapiro /* XXX It should be put in a library... */ 7438132943Sgshapiro 7439132943Sgshapiro /* protocol:filename or protocol:port@host */ 7440168515Sgshapiro memset(&addr, '\0', sizeof(addr)); 7441132943Sgshapiro p = map->map_file; 7442132943Sgshapiro colon = strchr(p, ':'); 7443132943Sgshapiro if (colon != NULL) 7444132943Sgshapiro { 7445132943Sgshapiro *colon = '\0'; 7446132943Sgshapiro 7447132943Sgshapiro if (*p == '\0') 7448132943Sgshapiro { 7449132943Sgshapiro# if NETUNIX 7450132943Sgshapiro /* default to AF_UNIX */ 7451132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7452132943Sgshapiro# else /* NETUNIX */ 7453132943Sgshapiro# if NETINET 7454132943Sgshapiro /* default to AF_INET */ 7455132943Sgshapiro addr.sa.sa_family = AF_INET; 7456132943Sgshapiro# else /* NETINET */ 7457132943Sgshapiro# if NETINET6 7458132943Sgshapiro /* default to AF_INET6 */ 7459132943Sgshapiro addr.sa.sa_family = AF_INET6; 7460132943Sgshapiro# else /* NETINET6 */ 7461132943Sgshapiro /* no protocols available */ 7462132943Sgshapiro syserr("socket map \"%s\": no valid socket protocols available", 7463132943Sgshapiro map->map_mname); 7464132943Sgshapiro return false; 7465132943Sgshapiro# endif /* NETINET6 */ 7466132943Sgshapiro# endif /* NETINET */ 7467132943Sgshapiro# endif /* NETUNIX */ 7468132943Sgshapiro } 7469132943Sgshapiro# if NETUNIX 7470132943Sgshapiro else if (sm_strcasecmp(p, "unix") == 0 || 7471132943Sgshapiro sm_strcasecmp(p, "local") == 0) 7472132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7473132943Sgshapiro# endif /* NETUNIX */ 7474132943Sgshapiro# if NETINET 7475132943Sgshapiro else if (sm_strcasecmp(p, "inet") == 0) 7476132943Sgshapiro addr.sa.sa_family = AF_INET; 7477132943Sgshapiro# endif /* NETINET */ 7478132943Sgshapiro# if NETINET6 7479132943Sgshapiro else if (sm_strcasecmp(p, "inet6") == 0) 7480132943Sgshapiro addr.sa.sa_family = AF_INET6; 7481132943Sgshapiro# endif /* NETINET6 */ 7482132943Sgshapiro else 7483132943Sgshapiro { 7484132943Sgshapiro# ifdef EPROTONOSUPPORT 7485132943Sgshapiro errno = EPROTONOSUPPORT; 7486132943Sgshapiro# else /* EPROTONOSUPPORT */ 7487132943Sgshapiro errno = EINVAL; 7488132943Sgshapiro# endif /* EPROTONOSUPPORT */ 7489132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7490132943Sgshapiro map->map_mname, p); 7491132943Sgshapiro return false; 7492132943Sgshapiro } 7493132943Sgshapiro *colon++ = ':'; 7494132943Sgshapiro } 7495132943Sgshapiro else 7496132943Sgshapiro { 7497132943Sgshapiro colon = p; 7498132943Sgshapiro#if NETUNIX 7499132943Sgshapiro /* default to AF_UNIX */ 7500132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7501132943Sgshapiro#else /* NETUNIX */ 7502132943Sgshapiro# if NETINET 7503132943Sgshapiro /* default to AF_INET */ 7504132943Sgshapiro addr.sa.sa_family = AF_INET; 7505132943Sgshapiro# else /* NETINET */ 7506132943Sgshapiro# if NETINET6 7507132943Sgshapiro /* default to AF_INET6 */ 7508132943Sgshapiro addr.sa.sa_family = AF_INET6; 7509132943Sgshapiro# else /* NETINET6 */ 7510132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7511132943Sgshapiro map->map_mname, p); 7512132943Sgshapiro return false; 7513132943Sgshapiro# endif /* NETINET6 */ 7514132943Sgshapiro# endif /* NETINET */ 7515132943Sgshapiro#endif /* NETUNIX */ 7516132943Sgshapiro } 7517132943Sgshapiro 7518132943Sgshapiro# if NETUNIX 7519132943Sgshapiro if (addr.sa.sa_family == AF_UNIX) 7520132943Sgshapiro { 7521132943Sgshapiro long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 7522132943Sgshapiro 7523132943Sgshapiro at = colon; 7524168515Sgshapiro if (strlen(colon) >= sizeof(addr.sunix.sun_path)) 7525132943Sgshapiro { 7526132943Sgshapiro syserr("socket map \"%s\": local socket name %s too long", 7527132943Sgshapiro map->map_mname, colon); 7528132943Sgshapiro return false; 7529132943Sgshapiro } 7530132943Sgshapiro errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 7531132943Sgshapiro S_IRUSR|S_IWUSR, NULL); 7532132943Sgshapiro 7533132943Sgshapiro if (errno != 0) 7534132943Sgshapiro { 7535132943Sgshapiro /* if not safe, don't create */ 7536132943Sgshapiro syserr("socket map \"%s\": local socket name %s unsafe", 7537132943Sgshapiro map->map_mname, colon); 7538132943Sgshapiro return false; 7539132943Sgshapiro } 7540132943Sgshapiro 7541132943Sgshapiro (void) sm_strlcpy(addr.sunix.sun_path, colon, 7542168515Sgshapiro sizeof(addr.sunix.sun_path)); 7543168515Sgshapiro addrlen = sizeof(struct sockaddr_un); 7544132943Sgshapiro } 7545132943Sgshapiro else 7546132943Sgshapiro# endif /* NETUNIX */ 7547132943Sgshapiro# if NETINET || NETINET6 7548132943Sgshapiro if (false 7549132943Sgshapiro# if NETINET 7550132943Sgshapiro || addr.sa.sa_family == AF_INET 7551132943Sgshapiro# endif /* NETINET */ 7552132943Sgshapiro# if NETINET6 7553132943Sgshapiro || addr.sa.sa_family == AF_INET6 7554132943Sgshapiro# endif /* NETINET6 */ 7555132943Sgshapiro ) 7556132943Sgshapiro { 7557132943Sgshapiro unsigned short port; 7558132943Sgshapiro 7559132943Sgshapiro /* Parse port@host */ 7560132943Sgshapiro at = strchr(colon, '@'); 7561132943Sgshapiro if (at == NULL) 7562132943Sgshapiro { 7563132943Sgshapiro syserr("socket map \"%s\": bad address %s (expected port@host)", 7564132943Sgshapiro map->map_mname, colon); 7565132943Sgshapiro return false; 7566132943Sgshapiro } 7567132943Sgshapiro *at = '\0'; 7568132943Sgshapiro if (isascii(*colon) && isdigit(*colon)) 7569132943Sgshapiro port = htons((unsigned short) atoi(colon)); 7570132943Sgshapiro else 7571132943Sgshapiro { 7572132943Sgshapiro# ifdef NO_GETSERVBYNAME 7573132943Sgshapiro syserr("socket map \"%s\": invalid port number %s", 7574132943Sgshapiro map->map_mname, colon); 7575132943Sgshapiro return false; 7576132943Sgshapiro# else /* NO_GETSERVBYNAME */ 7577132943Sgshapiro register struct servent *sp; 7578132943Sgshapiro 7579132943Sgshapiro sp = getservbyname(colon, "tcp"); 7580132943Sgshapiro if (sp == NULL) 7581132943Sgshapiro { 7582132943Sgshapiro syserr("socket map \"%s\": unknown port name %s", 7583132943Sgshapiro map->map_mname, colon); 7584132943Sgshapiro return false; 7585132943Sgshapiro } 7586132943Sgshapiro port = sp->s_port; 7587132943Sgshapiro# endif /* NO_GETSERVBYNAME */ 7588132943Sgshapiro } 7589132943Sgshapiro *at++ = '@'; 7590132943Sgshapiro if (*at == '[') 7591132943Sgshapiro { 7592132943Sgshapiro char *end; 7593132943Sgshapiro 7594132943Sgshapiro end = strchr(at, ']'); 7595132943Sgshapiro if (end != NULL) 7596132943Sgshapiro { 7597132943Sgshapiro bool found = false; 7598132943Sgshapiro# if NETINET 7599132943Sgshapiro unsigned long hid = INADDR_NONE; 7600132943Sgshapiro# endif /* NETINET */ 7601132943Sgshapiro# if NETINET6 7602132943Sgshapiro struct sockaddr_in6 hid6; 7603132943Sgshapiro# endif /* NETINET6 */ 7604132943Sgshapiro 7605132943Sgshapiro *end = '\0'; 7606132943Sgshapiro# if NETINET 7607132943Sgshapiro if (addr.sa.sa_family == AF_INET && 7608132943Sgshapiro (hid = inet_addr(&at[1])) != INADDR_NONE) 7609132943Sgshapiro { 7610132943Sgshapiro addr.sin.sin_addr.s_addr = hid; 7611132943Sgshapiro addr.sin.sin_port = port; 7612132943Sgshapiro found = true; 7613132943Sgshapiro } 7614132943Sgshapiro# endif /* NETINET */ 7615132943Sgshapiro# if NETINET6 7616168515Sgshapiro (void) memset(&hid6, '\0', sizeof(hid6)); 7617132943Sgshapiro if (addr.sa.sa_family == AF_INET6 && 7618132943Sgshapiro anynet_pton(AF_INET6, &at[1], 7619132943Sgshapiro &hid6.sin6_addr) == 1) 7620132943Sgshapiro { 7621132943Sgshapiro addr.sin6.sin6_addr = hid6.sin6_addr; 7622132943Sgshapiro addr.sin6.sin6_port = port; 7623132943Sgshapiro found = true; 7624132943Sgshapiro } 7625132943Sgshapiro# endif /* NETINET6 */ 7626132943Sgshapiro *end = ']'; 7627132943Sgshapiro if (!found) 7628132943Sgshapiro { 7629132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7630132943Sgshapiro map->map_mname, at); 7631132943Sgshapiro return false; 7632132943Sgshapiro } 7633132943Sgshapiro } 7634132943Sgshapiro else 7635132943Sgshapiro { 7636132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7637132943Sgshapiro map->map_mname, at); 7638132943Sgshapiro return false; 7639132943Sgshapiro } 7640132943Sgshapiro } 7641132943Sgshapiro else 7642132943Sgshapiro { 7643132943Sgshapiro hp = sm_gethostbyname(at, addr.sa.sa_family); 7644132943Sgshapiro if (hp == NULL) 7645132943Sgshapiro { 7646132943Sgshapiro syserr("socket map \"%s\": Unknown host name %s", 7647132943Sgshapiro map->map_mname, at); 7648132943Sgshapiro return false; 7649132943Sgshapiro } 7650132943Sgshapiro addr.sa.sa_family = hp->h_addrtype; 7651132943Sgshapiro switch (hp->h_addrtype) 7652132943Sgshapiro { 7653132943Sgshapiro# if NETINET 7654132943Sgshapiro case AF_INET: 7655132943Sgshapiro memmove(&addr.sin.sin_addr, 7656132943Sgshapiro hp->h_addr, INADDRSZ); 7657132943Sgshapiro addr.sin.sin_port = port; 7658168515Sgshapiro addrlen = sizeof(struct sockaddr_in); 7659132943Sgshapiro addrno = 1; 7660132943Sgshapiro break; 7661132943Sgshapiro# endif /* NETINET */ 7662132943Sgshapiro 7663132943Sgshapiro# if NETINET6 7664132943Sgshapiro case AF_INET6: 7665132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7666132943Sgshapiro hp->h_addr, IN6ADDRSZ); 7667132943Sgshapiro addr.sin6.sin6_port = port; 7668168515Sgshapiro addrlen = sizeof(struct sockaddr_in6); 7669132943Sgshapiro addrno = 1; 7670132943Sgshapiro break; 7671132943Sgshapiro# endif /* NETINET6 */ 7672132943Sgshapiro 7673132943Sgshapiro default: 7674132943Sgshapiro syserr("socket map \"%s\": Unknown protocol for %s (%d)", 7675132943Sgshapiro map->map_mname, at, hp->h_addrtype); 7676132943Sgshapiro# if NETINET6 7677132943Sgshapiro freehostent(hp); 7678132943Sgshapiro# endif /* NETINET6 */ 7679132943Sgshapiro return false; 7680132943Sgshapiro } 7681132943Sgshapiro } 7682132943Sgshapiro } 7683132943Sgshapiro else 7684132943Sgshapiro# endif /* NETINET || NETINET6 */ 7685132943Sgshapiro { 7686132943Sgshapiro syserr("socket map \"%s\": unknown socket protocol", 7687132943Sgshapiro map->map_mname); 7688132943Sgshapiro return false; 7689132943Sgshapiro } 7690132943Sgshapiro 7691132943Sgshapiro /* nope, actually connecting */ 7692132943Sgshapiro for (;;) 7693132943Sgshapiro { 7694132943Sgshapiro sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 7695132943Sgshapiro if (sock < 0) 7696132943Sgshapiro { 7697132943Sgshapiro save_errno = errno; 7698132943Sgshapiro if (tTd(38, 5)) 7699132943Sgshapiro sm_dprintf("socket map \"%s\": error creating socket: %s\n", 7700132943Sgshapiro map->map_mname, 7701132943Sgshapiro sm_errstring(save_errno)); 7702132943Sgshapiro# if NETINET6 7703132943Sgshapiro if (hp != NULL) 7704132943Sgshapiro freehostent(hp); 7705132943Sgshapiro# endif /* NETINET6 */ 7706132943Sgshapiro return false; 7707132943Sgshapiro } 7708132943Sgshapiro 7709132943Sgshapiro if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 7710132943Sgshapiro break; 7711132943Sgshapiro 7712132943Sgshapiro /* couldn't connect.... try next address */ 7713132943Sgshapiro save_errno = errno; 7714132943Sgshapiro p = CurHostName; 7715132943Sgshapiro CurHostName = at; 7716132943Sgshapiro if (tTd(38, 5)) 7717132943Sgshapiro sm_dprintf("socket_open (%s): open %s failed: %s\n", 7718132943Sgshapiro map->map_mname, at, sm_errstring(save_errno)); 7719132943Sgshapiro CurHostName = p; 7720132943Sgshapiro (void) close(sock); 7721132943Sgshapiro 7722132943Sgshapiro /* try next address */ 7723132943Sgshapiro if (hp != NULL && hp->h_addr_list[addrno] != NULL) 7724132943Sgshapiro { 7725132943Sgshapiro switch (addr.sa.sa_family) 7726132943Sgshapiro { 7727132943Sgshapiro# if NETINET 7728132943Sgshapiro case AF_INET: 7729132943Sgshapiro memmove(&addr.sin.sin_addr, 7730132943Sgshapiro hp->h_addr_list[addrno++], 7731132943Sgshapiro INADDRSZ); 7732132943Sgshapiro break; 7733132943Sgshapiro# endif /* NETINET */ 7734132943Sgshapiro 7735132943Sgshapiro# if NETINET6 7736132943Sgshapiro case AF_INET6: 7737132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7738132943Sgshapiro hp->h_addr_list[addrno++], 7739132943Sgshapiro IN6ADDRSZ); 7740132943Sgshapiro break; 7741132943Sgshapiro# endif /* NETINET6 */ 7742132943Sgshapiro 7743132943Sgshapiro default: 7744132943Sgshapiro if (tTd(38, 5)) 7745132943Sgshapiro sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 7746132943Sgshapiro map->map_mname, at, 7747132943Sgshapiro hp->h_addrtype); 7748132943Sgshapiro# if NETINET6 7749132943Sgshapiro freehostent(hp); 7750132943Sgshapiro# endif /* NETINET6 */ 7751132943Sgshapiro return false; 7752132943Sgshapiro } 7753132943Sgshapiro continue; 7754132943Sgshapiro } 7755132943Sgshapiro p = CurHostName; 7756132943Sgshapiro CurHostName = at; 7757132943Sgshapiro if (tTd(38, 5)) 7758132943Sgshapiro sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 7759132943Sgshapiro map->map_mname, sm_errstring(save_errno)); 7760132943Sgshapiro CurHostName = p; 7761132943Sgshapiro# if NETINET6 7762132943Sgshapiro if (hp != NULL) 7763132943Sgshapiro freehostent(hp); 7764132943Sgshapiro# endif /* NETINET6 */ 7765132943Sgshapiro return false; 7766132943Sgshapiro } 7767132943Sgshapiro# if NETINET6 7768132943Sgshapiro if (hp != NULL) 7769132943Sgshapiro { 7770132943Sgshapiro freehostent(hp); 7771132943Sgshapiro hp = NULL; 7772132943Sgshapiro } 7773132943Sgshapiro# endif /* NETINET6 */ 7774132943Sgshapiro if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 7775132943Sgshapiro SM_TIME_DEFAULT, 7776132943Sgshapiro (void *) &sock, 7777132943Sgshapiro SM_IO_RDWR, 7778132943Sgshapiro NULL)) == NULL) 7779132943Sgshapiro { 7780132943Sgshapiro close(sock); 7781132943Sgshapiro if (tTd(38, 2)) 7782132943Sgshapiro sm_dprintf("socket_open (%s): failed to create stream: %s\n", 7783132943Sgshapiro map->map_mname, sm_errstring(errno)); 7784132943Sgshapiro return false; 7785132943Sgshapiro } 7786132943Sgshapiro 7787132943Sgshapiro /* Save connection for reuse */ 7788132943Sgshapiro s->s_socketmap = map; 7789132943Sgshapiro return true; 7790132943Sgshapiro} 7791132943Sgshapiro 7792132943Sgshapiro/* 7793132943Sgshapiro** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 7794132943Sgshapiro** 7795132943Sgshapiro** Cache SOCKET connections based on the connection specifier 7796132943Sgshapiro** and PID so we don't have multiple connections open to 7797132943Sgshapiro** the same server for different maps. Need a separate connection 7798132943Sgshapiro** per PID since a parent process may close the map before the 7799132943Sgshapiro** child is done with it. 7800132943Sgshapiro** 7801132943Sgshapiro** Parameters: 7802132943Sgshapiro** conn -- SOCKET map connection specifier 7803132943Sgshapiro** 7804132943Sgshapiro** Returns: 7805132943Sgshapiro** Symbol table entry for the SOCKET connection. 7806132943Sgshapiro*/ 7807132943Sgshapiro 7808132943Sgshapirostatic STAB * 7809132943Sgshapirosocket_map_findconn(conn) 7810132943Sgshapiro const char *conn; 7811132943Sgshapiro{ 7812132943Sgshapiro char *nbuf; 7813132943Sgshapiro STAB *SM_NONVOLATILE s = NULL; 7814132943Sgshapiro 7815132943Sgshapiro nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 7816132943Sgshapiro SM_TRY 7817132943Sgshapiro s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 7818132943Sgshapiro SM_FINALLY 7819132943Sgshapiro sm_free(nbuf); 7820132943Sgshapiro SM_END_TRY 7821132943Sgshapiro return s; 7822132943Sgshapiro} 7823132943Sgshapiro 7824132943Sgshapiro/* 7825132943Sgshapiro** SOCKET_MAP_CLOSE -- close the socket 7826132943Sgshapiro*/ 7827132943Sgshapiro 7828132943Sgshapirovoid 7829132943Sgshapirosocket_map_close(map) 7830132943Sgshapiro MAP *map; 7831132943Sgshapiro{ 7832132943Sgshapiro STAB *s; 7833132943Sgshapiro MAP *smap; 7834132943Sgshapiro 7835132943Sgshapiro if (tTd(38, 20)) 7836132943Sgshapiro sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 7837132943Sgshapiro (long) CurrentPid); 7838132943Sgshapiro 7839132943Sgshapiro /* Check if already closed */ 7840132943Sgshapiro if (map->map_db1 == NULL) 7841132943Sgshapiro { 7842132943Sgshapiro if (tTd(38, 20)) 7843132943Sgshapiro sm_dprintf("socket_map_close(%s) already closed\n", 7844132943Sgshapiro map->map_file); 7845132943Sgshapiro return; 7846132943Sgshapiro } 7847132943Sgshapiro sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 7848132943Sgshapiro 7849132943Sgshapiro /* Mark all the maps that share the connection as closed */ 7850132943Sgshapiro s = socket_map_findconn(map->map_file); 7851132943Sgshapiro smap = s->s_socketmap; 7852132943Sgshapiro while (smap != NULL) 7853132943Sgshapiro { 7854132943Sgshapiro MAP *next; 7855132943Sgshapiro 7856132943Sgshapiro if (tTd(38, 2) && smap != map) 7857132943Sgshapiro sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 7858132943Sgshapiro map->map_mname, smap->map_mname); 7859132943Sgshapiro 7860132943Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 7861132943Sgshapiro smap->map_db1 = NULL; 7862132943Sgshapiro next = smap->socket_map_next; 7863132943Sgshapiro smap->socket_map_next = NULL; 7864132943Sgshapiro smap = next; 7865132943Sgshapiro } 7866132943Sgshapiro s->s_socketmap = NULL; 7867132943Sgshapiro} 7868132943Sgshapiro 7869132943Sgshapiro/* 7870132943Sgshapiro** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 7871132943Sgshapiro*/ 7872132943Sgshapiro 7873132943Sgshapirochar * 7874132943Sgshapirosocket_map_lookup(map, name, av, statp) 7875132943Sgshapiro MAP *map; 7876132943Sgshapiro char *name; 7877132943Sgshapiro char **av; 7878132943Sgshapiro int *statp; 7879132943Sgshapiro{ 7880132943Sgshapiro unsigned int nettolen, replylen, recvlen; 7881147078Sgshapiro char *replybuf, *rval, *value, *status, *key; 7882132943Sgshapiro SM_FILE_T *f; 7883147078Sgshapiro char keybuf[MAXNAME + 1]; 7884132943Sgshapiro 7885132943Sgshapiro replybuf = NULL; 7886132943Sgshapiro rval = NULL; 7887132943Sgshapiro f = (SM_FILE_T *)map->map_db1; 7888132943Sgshapiro if (tTd(38, 20)) 7889132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s) %s\n", 7890132943Sgshapiro map->map_mname, name, map->map_file); 7891132943Sgshapiro 7892147078Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 7893147078Sgshapiro { 7894147078Sgshapiro nettolen = strlen(name); 7895168515Sgshapiro if (nettolen > sizeof(keybuf) - 1) 7896168515Sgshapiro nettolen = sizeof(keybuf) - 1; 7897147078Sgshapiro memmove(keybuf, name, nettolen); 7898147078Sgshapiro keybuf[nettolen] = '\0'; 7899147078Sgshapiro makelower(keybuf); 7900147078Sgshapiro key = keybuf; 7901147078Sgshapiro } 7902147078Sgshapiro else 7903147078Sgshapiro key = name; 7904147078Sgshapiro 7905147078Sgshapiro nettolen = strlen(map->map_mname) + 1 + strlen(key); 7906132943Sgshapiro SM_ASSERT(nettolen > strlen(map->map_mname)); 7907147078Sgshapiro SM_ASSERT(nettolen > strlen(key)); 7908132943Sgshapiro if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 7909147078Sgshapiro nettolen, map->map_mname, key) == SM_IO_EOF) || 7910132943Sgshapiro (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 7911132943Sgshapiro (sm_io_error(f))) 7912132943Sgshapiro { 7913132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 7914132943Sgshapiro map->map_mname); 7915132943Sgshapiro *statp = EX_TEMPFAIL; 7916132943Sgshapiro goto errcl; 7917132943Sgshapiro } 7918132943Sgshapiro 7919132943Sgshapiro if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) 7920132943Sgshapiro { 7921132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", 7922132943Sgshapiro map->map_mname); 7923132943Sgshapiro *statp = EX_TEMPFAIL; 7924132943Sgshapiro goto errcl; 7925132943Sgshapiro } 7926132943Sgshapiro if (replylen > SOCKETMAP_MAXL) 7927132943Sgshapiro { 7928132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 7929132943Sgshapiro map->map_mname, replylen); 7930132943Sgshapiro *statp = EX_TEMPFAIL; 7931132943Sgshapiro goto errcl; 7932132943Sgshapiro } 7933132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 7934132943Sgshapiro { 7935132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 7936132943Sgshapiro map->map_mname); 7937132943Sgshapiro *statp = EX_TEMPFAIL; 7938132943Sgshapiro goto error; 7939132943Sgshapiro } 7940132943Sgshapiro 7941132943Sgshapiro replybuf = (char *) sm_malloc(replylen + 1); 7942132943Sgshapiro if (replybuf == NULL) 7943132943Sgshapiro { 7944132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 7945132943Sgshapiro map->map_mname, replylen + 1); 7946132943Sgshapiro *statp = EX_OSERR; 7947132943Sgshapiro goto error; 7948132943Sgshapiro } 7949132943Sgshapiro 7950132943Sgshapiro recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 7951132943Sgshapiro if (recvlen < replylen) 7952132943Sgshapiro { 7953132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 7954132943Sgshapiro map->map_mname, recvlen, replylen); 7955132943Sgshapiro *statp = EX_TEMPFAIL; 7956132943Sgshapiro goto errcl; 7957132943Sgshapiro } 7958132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 7959132943Sgshapiro { 7960132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 7961132943Sgshapiro map->map_mname); 7962132943Sgshapiro *statp = EX_TEMPFAIL; 7963132943Sgshapiro goto errcl; 7964132943Sgshapiro } 7965132943Sgshapiro status = replybuf; 7966132943Sgshapiro replybuf[recvlen] = '\0'; 7967132943Sgshapiro value = strchr(replybuf, ' '); 7968132943Sgshapiro if (value != NULL) 7969132943Sgshapiro { 7970132943Sgshapiro *value = '\0'; 7971132943Sgshapiro value++; 7972132943Sgshapiro } 7973132943Sgshapiro if (strcmp(status, "OK") == 0) 7974132943Sgshapiro { 7975132943Sgshapiro *statp = EX_OK; 7976132943Sgshapiro 7977132943Sgshapiro /* collect the return value */ 7978132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 7979147078Sgshapiro rval = map_rewrite(map, key, strlen(key), NULL); 7980132943Sgshapiro else 7981132943Sgshapiro rval = map_rewrite(map, value, strlen(value), av); 7982132943Sgshapiro } 7983132943Sgshapiro else if (strcmp(status, "NOTFOUND") == 0) 7984132943Sgshapiro { 7985132943Sgshapiro *statp = EX_NOTFOUND; 7986132943Sgshapiro if (tTd(38, 20)) 7987132943Sgshapiro sm_dprintf("socket_map_lookup(%s): %s not found\n", 7988147078Sgshapiro map->map_mname, key); 7989132943Sgshapiro } 7990132943Sgshapiro else 7991132943Sgshapiro { 7992132943Sgshapiro if (tTd(38, 5)) 7993132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 7994147078Sgshapiro map->map_mname, key, status, 7995132943Sgshapiro value ? value : ""); 7996132943Sgshapiro if ((strcmp(status, "TEMP") == 0) || 7997132943Sgshapiro (strcmp(status, "TIMEOUT") == 0)) 7998132943Sgshapiro *statp = EX_TEMPFAIL; 7999132943Sgshapiro else if(strcmp(status, "PERM") == 0) 8000132943Sgshapiro *statp = EX_UNAVAILABLE; 8001132943Sgshapiro else 8002132943Sgshapiro *statp = EX_PROTOCOL; 8003132943Sgshapiro } 8004132943Sgshapiro 8005132943Sgshapiro if (replybuf != NULL) 8006132943Sgshapiro sm_free(replybuf); 8007132943Sgshapiro return rval; 8008132943Sgshapiro 8009132943Sgshapiro errcl: 8010132943Sgshapiro socket_map_close(map); 8011132943Sgshapiro error: 8012132943Sgshapiro if (replybuf != NULL) 8013132943Sgshapiro sm_free(replybuf); 8014132943Sgshapiro return rval; 8015132943Sgshapiro} 8016132943Sgshapiro#endif /* SOCKETMAP */ 8017