map.c revision 244833
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 16244833SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.709 2012/04/20 18:47:09 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> 288638032Speter 288764562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 288864562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 288964562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 289064562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 289138032Speter 289238032Speter/* 289338032Speter** NISPLUS_MAP_OPEN -- open nisplus table 289438032Speter*/ 289538032Speter 289638032Speterbool 289738032Speternisplus_map_open(map, mode) 289838032Speter MAP *map; 289938032Speter int mode; 290038032Speter{ 290138032Speter nis_result *res = NULL; 290238032Speter int retry_cnt, max_col, i; 290338032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 290438032Speter 290538032Speter if (tTd(38, 2)) 290690792Sgshapiro sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 290738032Speter map->map_mname, map->map_file, mode); 290838032Speter 290938032Speter mode &= O_ACCMODE; 291038032Speter if (mode != O_RDONLY) 291138032Speter { 291238032Speter errno = EPERM; 291390792Sgshapiro return false; 291438032Speter } 291538032Speter 291638032Speter if (*map->map_file == '\0') 291738032Speter map->map_file = "mail_aliases.org_dir"; 291838032Speter 291938032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 292038032Speter { 292138032Speter /* set default NISPLUS Domain to $m */ 292238032Speter map->map_domain = newstr(nisplus_default_domain()); 292338032Speter if (tTd(38, 2)) 292490792Sgshapiro sm_dprintf("nisplus_map_open(%s): using domain %s\n", 292564562Sgshapiro map->map_file, map->map_domain); 292638032Speter } 292738032Speter if (!PARTIAL_NAME(map->map_file)) 292838032Speter { 292938032Speter map->map_domain = newstr(""); 2930168515Sgshapiro (void) sm_strlcpy(qbuf, map->map_file, sizeof(qbuf)); 293138032Speter } 293238032Speter else 293338032Speter { 293438032Speter /* check to see if this map actually exists */ 2935168515Sgshapiro (void) sm_strlcpyn(qbuf, sizeof(qbuf), 3, 293690792Sgshapiro map->map_file, ".", map->map_domain); 293738032Speter } 293838032Speter 293938032Speter retry_cnt = 0; 294038032Speter while (res == NULL || res->status != NIS_SUCCESS) 294138032Speter { 294238032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 294338032Speter switch (res->status) 294438032Speter { 294538032Speter case NIS_SUCCESS: 294638032Speter break; 294738032Speter 294838032Speter case NIS_TRYAGAIN: 294938032Speter case NIS_RPCERROR: 295038032Speter case NIS_NAMEUNREACHABLE: 295138032Speter if (retry_cnt++ > 4) 295238032Speter { 295338032Speter errno = EAGAIN; 295490792Sgshapiro return false; 295538032Speter } 295638032Speter /* try not to overwhelm hosed server */ 295738032Speter sleep(2); 295838032Speter break; 295938032Speter 296038032Speter default: /* all other nisplus errors */ 296164562Sgshapiro# if 0 296238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 296394334Sgshapiro syserr("451 4.3.5 Cannot find table %s.%s: %s", 296438032Speter map->map_file, map->map_domain, 296538032Speter nis_sperrno(res->status)); 296664562Sgshapiro# endif /* 0 */ 296738032Speter errno = EAGAIN; 296890792Sgshapiro return false; 296938032Speter } 297038032Speter } 297138032Speter 297238032Speter if (NIS_RES_NUMOBJ(res) != 1 || 297338032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 297438032Speter { 297538032Speter if (tTd(38, 10)) 297690792Sgshapiro sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 297764562Sgshapiro# if 0 297838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 297994334Sgshapiro syserr("451 4.3.5 %s.%s: %s is not a table", 298038032Speter map->map_file, map->map_domain, 298138032Speter nis_sperrno(res->status)); 298264562Sgshapiro# endif /* 0 */ 298338032Speter errno = EBADF; 298490792Sgshapiro return false; 298538032Speter } 298638032Speter /* default key column is column 0 */ 298738032Speter if (map->map_keycolnm == NULL) 298838032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 298938032Speter 299038032Speter max_col = COL_MAX(res); 299138032Speter 299238032Speter /* verify the key column exist */ 299390792Sgshapiro for (i = 0; i < max_col; i++) 299438032Speter { 299564562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 299638032Speter break; 299738032Speter } 299838032Speter if (i == max_col) 299938032Speter { 300038032Speter if (tTd(38, 2)) 300190792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 300238032Speter map->map_file, map->map_keycolnm); 300338032Speter errno = ENOENT; 300490792Sgshapiro return false; 300538032Speter } 300638032Speter 300738032Speter /* default value column is the last column */ 300838032Speter if (map->map_valcolnm == NULL) 300938032Speter { 301038032Speter map->map_valcolno = max_col - 1; 301190792Sgshapiro return true; 301238032Speter } 301338032Speter 301464562Sgshapiro for (i = 0; i< max_col; i++) 301538032Speter { 301638032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 301738032Speter { 301838032Speter map->map_valcolno = i; 301990792Sgshapiro return true; 302038032Speter } 302138032Speter } 302238032Speter 302338032Speter if (tTd(38, 2)) 302490792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 302564562Sgshapiro map->map_file, map->map_keycolnm); 302638032Speter errno = ENOENT; 302790792Sgshapiro return false; 302838032Speter} 302938032Speter 303038032Speter 303138032Speter/* 303238032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 303338032Speter*/ 303438032Speter 303538032Speterchar * 303638032Speternisplus_map_lookup(map, name, av, statp) 303738032Speter MAP *map; 303838032Speter char *name; 303938032Speter char **av; 304038032Speter int *statp; 304138032Speter{ 304238032Speter char *p; 304338032Speter auto int vsize; 304438032Speter char *skp; 304538032Speter int skleft; 304638032Speter char search_key[MAXNAME + 4]; 304738032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 304838032Speter nis_result *result; 304938032Speter 305038032Speter if (tTd(38, 20)) 305190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s, %s)\n", 305238032Speter map->map_mname, name); 305338032Speter 305438032Speter if (!bitset(MF_OPEN, map->map_mflags)) 305538032Speter { 305638032Speter if (nisplus_map_open(map, O_RDONLY)) 305742575Speter { 305838032Speter map->map_mflags |= MF_OPEN; 305990792Sgshapiro map->map_pid = CurrentPid; 306042575Speter } 306138032Speter else 306238032Speter { 306338032Speter *statp = EX_UNAVAILABLE; 306438032Speter return NULL; 306538032Speter } 306638032Speter } 306738032Speter 306838032Speter /* 306938032Speter ** Copy the name to the key buffer, escaping double quote characters 307038032Speter ** by doubling them and quoting "]" and "," to avoid having the 307138032Speter ** NIS+ parser choke on them. 307238032Speter */ 307338032Speter 3074168515Sgshapiro skleft = sizeof(search_key) - 4; 307538032Speter skp = search_key; 307638032Speter for (p = name; *p != '\0' && skleft > 0; p++) 307738032Speter { 307838032Speter switch (*p) 307938032Speter { 308038032Speter case ']': 308138032Speter case ',': 308238032Speter /* quote the character */ 308338032Speter *skp++ = '"'; 308438032Speter *skp++ = *p; 308538032Speter *skp++ = '"'; 308638032Speter skleft -= 3; 308738032Speter break; 308838032Speter 308938032Speter case '"': 309038032Speter /* double the quote */ 309138032Speter *skp++ = '"'; 309238032Speter skleft--; 309364562Sgshapiro /* FALLTHROUGH */ 309438032Speter 309538032Speter default: 309638032Speter *skp++ = *p; 309738032Speter skleft--; 309838032Speter break; 309938032Speter } 310038032Speter } 310138032Speter *skp = '\0'; 310238032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 310338032Speter makelower(search_key); 310438032Speter 310538032Speter /* construct the query */ 310638032Speter if (PARTIAL_NAME(map->map_file)) 3107168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s.%s", 310838032Speter map->map_keycolnm, search_key, map->map_file, 310938032Speter map->map_domain); 311038032Speter else 3111168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s", 311238032Speter map->map_keycolnm, search_key, map->map_file); 311338032Speter 311438032Speter if (tTd(38, 20)) 311590792Sgshapiro sm_dprintf("qbuf=%s\n", qbuf); 311638032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 311738032Speter if (result->status == NIS_SUCCESS) 311838032Speter { 311938032Speter int count; 312038032Speter char *str; 312138032Speter 312238032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 312338032Speter { 312438032Speter if (LogLevel > 10) 312538032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 312664562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 312764562Sgshapiro map->map_file, count); 312838032Speter 312938032Speter /* ignore second entry */ 313038032Speter if (tTd(38, 20)) 313190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 313238032Speter name, count); 313338032Speter } 313438032Speter 313538032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 313638032Speter /* set the length of the result */ 313738032Speter if (p == NULL) 313838032Speter p = ""; 313938032Speter vsize = strlen(p); 314038032Speter if (tTd(38, 20)) 314190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), found %s\n", 314238032Speter name, p); 314338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 314438032Speter str = map_rewrite(map, name, strlen(name), NULL); 314538032Speter else 314638032Speter str = map_rewrite(map, p, vsize, av); 314738032Speter nis_freeresult(result); 314838032Speter *statp = EX_OK; 314938032Speter return str; 315038032Speter } 315138032Speter else 315238032Speter { 315338032Speter if (result->status == NIS_NOTFOUND) 315438032Speter *statp = EX_NOTFOUND; 315538032Speter else if (result->status == NIS_TRYAGAIN) 315638032Speter *statp = EX_TEMPFAIL; 315738032Speter else 315838032Speter { 315938032Speter *statp = EX_UNAVAILABLE; 316038032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 316138032Speter } 316238032Speter } 316338032Speter if (tTd(38, 20)) 316490792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 316538032Speter nis_freeresult(result); 316638032Speter return NULL; 316738032Speter} 316838032Speter 316938032Speter 317038032Speter 317138032Speter/* 317238032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 317338032Speter*/ 317438032Speter 317564562Sgshapirostatic bool 317638032Speternisplus_getcanonname(name, hbsize, statp) 317738032Speter char *name; 317838032Speter int hbsize; 317938032Speter int *statp; 318038032Speter{ 318138032Speter char *vp; 318238032Speter auto int vsize; 318338032Speter nis_result *result; 318438032Speter char *p; 318538032Speter char nbuf[MAXNAME + 1]; 318638032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 318738032Speter 3188168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 318938032Speter { 319038032Speter *statp = EX_UNAVAILABLE; 319190792Sgshapiro return false; 319238032Speter } 319373188Sgshapiro (void) shorten_hostname(nbuf); 319438032Speter 319538032Speter p = strchr(nbuf, '.'); 319638032Speter if (p == NULL) 319738032Speter { 319838032Speter /* single token */ 3199168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 320090792Sgshapiro "[name=%s],hosts.org_dir", nbuf); 320138032Speter } 320238032Speter else if (p[1] != '\0') 320338032Speter { 320438032Speter /* multi token -- take only first token in nbuf */ 320538032Speter *p = '\0'; 3206168515Sgshapiro (void) sm_snprintf(qbuf, sizeof(qbuf), 320790792Sgshapiro "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 320838032Speter } 320938032Speter else 321038032Speter { 321138032Speter *statp = EX_NOHOST; 321290792Sgshapiro return false; 321338032Speter } 321438032Speter 321538032Speter if (tTd(38, 20)) 321694334Sgshapiro sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 321790792Sgshapiro name, qbuf); 321838032Speter 321938032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 322090792Sgshapiro NULL, NULL); 322138032Speter 322238032Speter if (result->status == NIS_SUCCESS) 322338032Speter { 322438032Speter int count; 322538032Speter char *domain; 322638032Speter 322738032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 322838032Speter { 322938032Speter if (LogLevel > 10) 323038032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 323164562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 323264562Sgshapiro count); 323338032Speter 323438032Speter /* ignore second entry */ 323538032Speter if (tTd(38, 20)) 323694334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 323790792Sgshapiro name, count); 323838032Speter } 323938032Speter 324038032Speter if (tTd(38, 20)) 324194334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 324290792Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 324338032Speter 324438032Speter 324538032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 324638032Speter vsize = strlen(vp); 324738032Speter if (tTd(38, 20)) 324890792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found %s\n", 324990792Sgshapiro name, vp); 325038032Speter if (strchr(vp, '.') != NULL) 325138032Speter { 325238032Speter domain = ""; 325338032Speter } 325438032Speter else 325538032Speter { 325638032Speter domain = macvalue('m', CurEnv); 325738032Speter if (domain == NULL) 325838032Speter domain = ""; 325938032Speter } 326038032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 326138032Speter { 326238032Speter if (domain[0] == '\0') 326390792Sgshapiro (void) sm_strlcpy(name, vp, hbsize); 326438032Speter else 326590792Sgshapiro (void) sm_snprintf(name, hbsize, 326690792Sgshapiro "%s.%s", vp, domain); 326738032Speter *statp = EX_OK; 326838032Speter } 326938032Speter else 327038032Speter *statp = EX_NOHOST; 327138032Speter nis_freeresult(result); 327290792Sgshapiro return true; 327338032Speter } 327438032Speter else 327538032Speter { 327638032Speter if (result->status == NIS_NOTFOUND) 327738032Speter *statp = EX_NOHOST; 327838032Speter else if (result->status == NIS_TRYAGAIN) 327938032Speter *statp = EX_TEMPFAIL; 328038032Speter else 328138032Speter *statp = EX_UNAVAILABLE; 328238032Speter } 328338032Speter if (tTd(38, 20)) 328490792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 328590792Sgshapiro name, result->status, *statp); 328638032Speter nis_freeresult(result); 328790792Sgshapiro return false; 328838032Speter} 328938032Speter 329038032Speterchar * 329138032Speternisplus_default_domain() 329238032Speter{ 329338032Speter static char default_domain[MAXNAME + 1] = ""; 329438032Speter char *p; 329538032Speter 329638032Speter if (default_domain[0] != '\0') 329764562Sgshapiro return default_domain; 329838032Speter 329938032Speter p = nis_local_directory(); 3300168515Sgshapiro (void) sm_strlcpy(default_domain, p, sizeof(default_domain)); 330138032Speter return default_domain; 330238032Speter} 330338032Speter 330438032Speter#endif /* NISPLUS */ 330590792Sgshapiro/* 330638032Speter** LDAP Modules 330738032Speter*/ 330838032Speter 330964562Sgshapiro/* 331064562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 331164562Sgshapiro*/ 331264562Sgshapiro 331364562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 331464562Sgshapiro 331590792Sgshapiro# if PH_MAP 331664562Sgshapiro# define ph_map_dequote ldapmap_dequote 331764562Sgshapiro# endif /* PH_MAP */ 331864562Sgshapiro 331990792Sgshapirostatic char *ldapmap_dequote __P((char *)); 332090792Sgshapiro 332190792Sgshapirostatic char * 332264562Sgshapiroldapmap_dequote(str) 332364562Sgshapiro char *str; 332464562Sgshapiro{ 332564562Sgshapiro char *p; 332664562Sgshapiro char *start; 332764562Sgshapiro 332864562Sgshapiro if (str == NULL) 332964562Sgshapiro return NULL; 333064562Sgshapiro 333164562Sgshapiro p = str; 333264562Sgshapiro if (*p == '"') 333364562Sgshapiro { 333464562Sgshapiro /* Should probably swallow initial whitespace here */ 333564562Sgshapiro start = ++p; 333664562Sgshapiro } 333764562Sgshapiro else 333864562Sgshapiro return str; 333964562Sgshapiro while (*p != '"' && *p != '\0') 334064562Sgshapiro p++; 334164562Sgshapiro if (*p != '\0') 334264562Sgshapiro *p = '\0'; 334364562Sgshapiro return start; 334464562Sgshapiro} 334564562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 334664562Sgshapiro 334790792Sgshapiro#if LDAPMAP 334838032Speter 334990792Sgshapirostatic SM_LDAP_STRUCT *LDAPDefaults = NULL; 335038032Speter 335138032Speter/* 335264562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 335338032Speter** 335464562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 335564562Sgshapiro** single server connection to a host (with the same host, port, 335664562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 335738032Speter*/ 335838032Speter 335938032Speterbool 336064562Sgshapiroldapmap_open(map, mode) 336138032Speter MAP *map; 336238032Speter int mode; 336338032Speter{ 336490792Sgshapiro SM_LDAP_STRUCT *lmap; 336564562Sgshapiro STAB *s; 3366132943Sgshapiro char *id; 336764562Sgshapiro 336838032Speter if (tTd(38, 2)) 336990792Sgshapiro sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 337038032Speter 3371168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3372168515Sgshapiro HASLDAPGETALIASBYNAME 3373168515Sgshapiro if (VendorCode == VENDOR_SUN && 3374168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3375168515Sgshapiro { 3376168515Sgshapiro return true; 3377168515Sgshapiro } 3378168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3379168515Sgshapiro 338038032Speter mode &= O_ACCMODE; 338164562Sgshapiro 338264562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 338338032Speter if (mode != O_RDONLY) 338438032Speter { 338538032Speter /* issue a pseudo-error message */ 338690792Sgshapiro errno = SM_EMAPCANTWRITE; 338790792Sgshapiro return false; 338838032Speter } 338964562Sgshapiro 339090792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 339164562Sgshapiro 339264562Sgshapiro s = ldapmap_findconn(lmap); 339377349Sgshapiro if (s->s_lmap != NULL) 339464562Sgshapiro { 339564562Sgshapiro /* Already have a connection open to this LDAP server */ 339690792Sgshapiro lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 339790792Sgshapiro lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 339877349Sgshapiro 339977349Sgshapiro /* Add this map as head of linked list */ 340077349Sgshapiro lmap->ldap_next = s->s_lmap; 340177349Sgshapiro s->s_lmap = map; 340277349Sgshapiro 340366494Sgshapiro if (tTd(38, 2)) 340490792Sgshapiro sm_dprintf("using cached connection\n"); 340590792Sgshapiro return true; 340664562Sgshapiro } 340764562Sgshapiro 340866494Sgshapiro if (tTd(38, 2)) 340990792Sgshapiro sm_dprintf("opening new connection\n"); 341066494Sgshapiro 3411132943Sgshapiro if (lmap->ldap_host != NULL) 3412132943Sgshapiro id = lmap->ldap_host; 3413132943Sgshapiro else if (lmap->ldap_uri != NULL) 3414132943Sgshapiro id = lmap->ldap_uri; 3415132943Sgshapiro else 3416132943Sgshapiro id = "localhost"; 3417132943Sgshapiro 3418203004Sgshapiro if (tTd(74, 104)) 3419203004Sgshapiro { 3420203004Sgshapiro extern MAPCLASS NullMapClass; 3421203004Sgshapiro 3422203004Sgshapiro /* debug mode: don't actually open an LDAP connection */ 3423203004Sgshapiro map->map_orgclass = map->map_class; 3424203004Sgshapiro map->map_class = &NullMapClass; 3425203004Sgshapiro map->map_mflags |= MF_OPEN; 3426203004Sgshapiro map->map_pid = CurrentPid; 3427203004Sgshapiro return true; 3428203004Sgshapiro } 3429203004Sgshapiro 343064562Sgshapiro /* No connection yet, connect */ 343190792Sgshapiro if (!sm_ldap_start(map->map_mname, lmap)) 343238032Speter { 343390792Sgshapiro if (errno == ETIMEDOUT) 343438032Speter { 343538032Speter if (LogLevel > 1) 343638032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 3437244833Sgshapiro "timeout connecting to LDAP server %.100s", 3438132943Sgshapiro id); 343938032Speter } 344038032Speter 344138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 344238032Speter { 344364562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3444132943Sgshapiro { 344564562Sgshapiro syserr("%s failed to %s in map %s", 344664562Sgshapiro# if USE_LDAP_INIT 344790792Sgshapiro "ldap_init/ldap_bind", 344864562Sgshapiro# else /* USE_LDAP_INIT */ 344964562Sgshapiro "ldap_open", 345064562Sgshapiro# endif /* USE_LDAP_INIT */ 3451132943Sgshapiro id, map->map_mname); 3452132943Sgshapiro } 345364562Sgshapiro else 3454132943Sgshapiro { 345594334Sgshapiro syserr("451 4.3.5 %s failed to %s in map %s", 345664562Sgshapiro# if USE_LDAP_INIT 345790792Sgshapiro "ldap_init/ldap_bind", 345864562Sgshapiro# else /* USE_LDAP_INIT */ 345964562Sgshapiro "ldap_open", 346064562Sgshapiro# endif /* USE_LDAP_INIT */ 3461132943Sgshapiro id, map->map_mname); 3462132943Sgshapiro } 346338032Speter } 346490792Sgshapiro return false; 346538032Speter } 346638032Speter 346790792Sgshapiro /* Save connection for reuse */ 346890792Sgshapiro s->s_lmap = map; 346990792Sgshapiro return true; 347038032Speter} 347138032Speter 347238032Speter/* 347364562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 347438032Speter*/ 347538032Speter 347638032Spetervoid 347764562Sgshapiroldapmap_close(map) 347838032Speter MAP *map; 347938032Speter{ 348090792Sgshapiro SM_LDAP_STRUCT *lmap; 348164562Sgshapiro STAB *s; 348243730Speter 348364562Sgshapiro if (tTd(38, 2)) 348490792Sgshapiro sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 348564562Sgshapiro 348690792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 348764562Sgshapiro 348864562Sgshapiro /* Check if already closed */ 348964562Sgshapiro if (lmap->ldap_ld == NULL) 349064562Sgshapiro return; 349164562Sgshapiro 349277349Sgshapiro /* Close the LDAP connection */ 349390792Sgshapiro sm_ldap_close(lmap); 349477349Sgshapiro 349577349Sgshapiro /* Mark all the maps that share the connection as closed */ 349664562Sgshapiro s = ldapmap_findconn(lmap); 349764562Sgshapiro 349877349Sgshapiro while (s->s_lmap != NULL) 349977349Sgshapiro { 350077349Sgshapiro MAP *smap = s->s_lmap; 350164562Sgshapiro 350277349Sgshapiro if (tTd(38, 2) && smap != map) 350390792Sgshapiro sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 350490792Sgshapiro map->map_mname, smap->map_mname); 350577349Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 350690792Sgshapiro lmap = (SM_LDAP_STRUCT *) smap->map_db1; 350764562Sgshapiro lmap->ldap_ld = NULL; 350877349Sgshapiro s->s_lmap = lmap->ldap_next; 350977349Sgshapiro lmap->ldap_next = NULL; 351043730Speter } 351138032Speter} 351238032Speter 351364562Sgshapiro# ifdef SUNET_ID 351443730Speter/* 351590792Sgshapiro** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 351642575Speter** This only makes sense at Stanford University. 351738032Speter*/ 351838032Speter 351990792Sgshapirostatic char * 352038032Spetersunet_id_hash(str) 352138032Speter char *str; 352238032Speter{ 352338032Speter char *p, *p_last; 352438032Speter 352538032Speter p = str; 352638032Speter p_last = p; 352738032Speter while (*p != '\0') 352838032Speter { 3529203004Sgshapiro if (isascii(*p) && (islower(*p) || isdigit(*p))) 353038032Speter { 353138032Speter *p_last = *p; 353238032Speter p_last++; 353338032Speter } 3534203004Sgshapiro else if (isascii(*p) && isupper(*p)) 353538032Speter { 353638032Speter *p_last = tolower(*p); 353738032Speter p_last++; 353838032Speter } 353938032Speter ++p; 354038032Speter } 354138032Speter if (*p_last != '\0') 354238032Speter *p_last = '\0'; 354364562Sgshapiro return str; 354438032Speter} 3545168515Sgshapiro# define SM_CONVERT_ID(str) sunet_id_hash(str) 3546168515Sgshapiro# else /* SUNET_ID */ 3547168515Sgshapiro# define SM_CONVERT_ID(str) makelower(str) 354864562Sgshapiro# endif /* SUNET_ID */ 354938032Speter 355038032Speter/* 355164562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 355238032Speter*/ 355338032Speter 355438032Speterchar * 355564562Sgshapiroldapmap_lookup(map, name, av, statp) 355638032Speter MAP *map; 355738032Speter char *name; 355838032Speter char **av; 355938032Speter int *statp; 356038032Speter{ 3561132943Sgshapiro int flags; 3562168515Sgshapiro int i; 356394334Sgshapiro int plen = 0; 356494334Sgshapiro int psize = 0; 356564562Sgshapiro int msgid; 356690792Sgshapiro int save_errno; 356790792Sgshapiro char *vp, *p; 356864562Sgshapiro char *result = NULL; 3569132943Sgshapiro SM_RPOOL_T *rpool; 357090792Sgshapiro SM_LDAP_STRUCT *lmap = NULL; 3571168515Sgshapiro char *argv[SM_LDAP_ARGS]; 3572157001Sgshapiro char keybuf[MAXKEY]; 3573168515Sgshapiro#if SM_LDAP_ARGS != MAX_MAP_ARGS 3574168515Sgshapiro# ERROR _SM_LDAP_ARGS must be the same as _MAX_MAP_ARGS 3575168515Sgshapiro#endif /* SM_LDAP_ARGS != MAX_MAP_ARGS */ 357638032Speter 3577168515Sgshapiro#if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 3578168515Sgshapiro HASLDAPGETALIASBYNAME 3579168515Sgshapiro if (VendorCode == VENDOR_SUN && 3580168515Sgshapiro strcmp(map->map_mname, "aliases.ldap") == 0) 3581168515Sgshapiro { 3582168515Sgshapiro int rc; 3583173340Sgshapiro#if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2) 3584173340Sgshapiro extern char *__getldapaliasbyname(); 3585173340Sgshapiro char *answer; 358638032Speter 3587173340Sgshapiro answer = __getldapaliasbyname(name, &rc); 3588173340Sgshapiro#else 3589173340Sgshapiro char answer[MAXNAME + 1]; 3590173340Sgshapiro 3591168515Sgshapiro rc = __getldapaliasbyname(name, answer, sizeof(answer)); 3592173340Sgshapiro#endif 3593168515Sgshapiro if (rc != 0) 3594168515Sgshapiro { 3595168515Sgshapiro if (tTd(38, 20)) 3596168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n", 3597168515Sgshapiro name, errno); 3598168515Sgshapiro *statp = EX_NOTFOUND; 3599168515Sgshapiro return NULL; 3600168515Sgshapiro } 3601168515Sgshapiro *statp = EX_OK; 3602168515Sgshapiro if (tTd(38, 20)) 3603168515Sgshapiro sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name, 3604168515Sgshapiro answer); 3605168515Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3606168515Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 3607168515Sgshapiro else 3608168515Sgshapiro result = map_rewrite(map, answer, strlen(answer), av); 3609173340Sgshapiro#if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2) 3610173340Sgshapiro free(answer); 3611173340Sgshapiro#endif 3612168515Sgshapiro return result; 3613168515Sgshapiro } 3614168515Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 3615168515Sgshapiro 361638032Speter /* Get ldap struct pointer from map */ 361790792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 361890792Sgshapiro sm_ldap_setopts(lmap->ldap_ld, lmap); 361938032Speter 3620168515Sgshapiro if (lmap->ldap_multi_args) 3621168515Sgshapiro { 3622168515Sgshapiro SM_REQUIRE(av != NULL); 3623168515Sgshapiro memset(argv, '\0', sizeof(argv)); 3624168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && av[i] != NULL; i++) 3625168515Sgshapiro { 3626168515Sgshapiro argv[i] = sm_strdup(av[i]); 3627168515Sgshapiro if (argv[i] == NULL) 3628168515Sgshapiro { 3629168515Sgshapiro int save_errno, j; 363038032Speter 3631168515Sgshapiro save_errno = errno; 3632168515Sgshapiro for (j = 0; j < i && argv[j] != NULL; j++) 3633168515Sgshapiro SM_FREE(argv[j]); 3634168515Sgshapiro *statp = EX_TEMPFAIL; 3635168515Sgshapiro errno = save_errno; 3636168515Sgshapiro return NULL; 3637168515Sgshapiro } 3638168515Sgshapiro 3639168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 3640168515Sgshapiro SM_CONVERT_ID(av[i]); 3641168515Sgshapiro } 3642168515Sgshapiro } 3643168515Sgshapiro else 364464562Sgshapiro { 3645168515Sgshapiro (void) sm_strlcpy(keybuf, name, sizeof(keybuf)); 3646168515Sgshapiro 3647168515Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 3648168515Sgshapiro SM_CONVERT_ID(keybuf); 364964562Sgshapiro } 365038032Speter 3651168515Sgshapiro if (tTd(38, 20)) 365238032Speter { 3653168515Sgshapiro if (lmap->ldap_multi_args) 3654168515Sgshapiro { 3655168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, argv)\n", 3656168515Sgshapiro map->map_mname); 3657168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS; i++) 3658168515Sgshapiro { 3659168515Sgshapiro sm_dprintf(" argv[%d] = %s\n", i, 3660168515Sgshapiro argv[i] == NULL ? "NULL" : argv[i]); 3661168515Sgshapiro } 3662168515Sgshapiro } 3663168515Sgshapiro else 3664168515Sgshapiro { 3665168515Sgshapiro sm_dprintf("ldapmap_lookup(%s, %s)\n", 3666168515Sgshapiro map->map_mname, name); 3667168515Sgshapiro } 3668168515Sgshapiro } 3669168515Sgshapiro 3670168515Sgshapiro if (lmap->ldap_multi_args) 3671168515Sgshapiro { 3672168515Sgshapiro msgid = sm_ldap_search_m(lmap, argv); 3673168515Sgshapiro 3674168515Sgshapiro /* free the argv array and its content, no longer needed */ 3675168515Sgshapiro for (i = 0; i < SM_LDAP_ARGS && argv[i] != NULL; i++) 3676168515Sgshapiro SM_FREE(argv[i]); 3677168515Sgshapiro } 3678168515Sgshapiro else 3679168515Sgshapiro msgid = sm_ldap_search(lmap, keybuf); 3680168515Sgshapiro if (msgid == SM_LDAP_ERR) 3681168515Sgshapiro { 368290792Sgshapiro errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 368377349Sgshapiro save_errno = errno; 368464562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 368538032Speter { 3686168515Sgshapiro /* 3687168515Sgshapiro ** Do not include keybuf as this error may be shown 3688168515Sgshapiro ** to outsiders. 3689168515Sgshapiro */ 3690168515Sgshapiro 369164562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3692168515Sgshapiro syserr("Error in ldap_search in map %s", 3693168515Sgshapiro map->map_mname); 369464562Sgshapiro else 3695168515Sgshapiro syserr("451 4.3.5 Error in ldap_search in map %s", 3696168515Sgshapiro map->map_mname); 369738032Speter } 369864562Sgshapiro *statp = EX_TEMPFAIL; 369990792Sgshapiro switch (save_errno - E_LDAPBASE) 370090792Sgshapiro { 370194334Sgshapiro# ifdef LDAP_SERVER_DOWN 370290792Sgshapiro case LDAP_SERVER_DOWN: 370394334Sgshapiro# endif /* LDAP_SERVER_DOWN */ 370490792Sgshapiro case LDAP_TIMEOUT: 370590792Sgshapiro case LDAP_UNAVAILABLE: 370666494Sgshapiro /* server disappeared, try reopen on next search */ 370777349Sgshapiro ldapmap_close(map); 370890792Sgshapiro break; 370966494Sgshapiro } 371077349Sgshapiro errno = save_errno; 371164562Sgshapiro return NULL; 371264562Sgshapiro } 3713168515Sgshapiro#if SM_LDAP_ERROR_ON_MISSING_ARGS 3714168515Sgshapiro else if (msgid == SM_LDAP_ERR_ARG_MISS) 3715168515Sgshapiro { 3716168515Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3717168515Sgshapiro syserr("Error in ldap_search in map %s, too few arguments", 3718168515Sgshapiro map->map_mname); 3719168515Sgshapiro else 3720168515Sgshapiro syserr("554 5.3.5 Error in ldap_search in map %s, too few arguments", 3721168515Sgshapiro map->map_mname); 3722168515Sgshapiro *statp = EX_CONFIG; 3723168515Sgshapiro return NULL; 3724168515Sgshapiro } 3725168515Sgshapiro#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 372664562Sgshapiro 372764562Sgshapiro *statp = EX_NOTFOUND; 372864562Sgshapiro vp = NULL; 372964562Sgshapiro 3730132943Sgshapiro flags = 0; 3731132943Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 3732132943Sgshapiro flags |= SM_LDAP_SINGLEMATCH; 3733132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3734132943Sgshapiro flags |= SM_LDAP_MATCHONLY; 3735157001Sgshapiro# if _FFR_LDAP_SINGLEDN 3736157001Sgshapiro if (bitset(MF_SINGLEDN, map->map_mflags)) 3737157001Sgshapiro flags |= SM_LDAP_SINGLEDN; 3738157001Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 373990792Sgshapiro 3740132943Sgshapiro /* Create an rpool for search related memory usage */ 3741132943Sgshapiro rpool = sm_rpool_new_x(NULL); 374290792Sgshapiro 3743132943Sgshapiro p = NULL; 3744132943Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 3745132943Sgshapiro rpool, &p, &plen, &psize, NULL); 3746132943Sgshapiro save_errno = errno; 374790792Sgshapiro 3748132943Sgshapiro /* Copy result so rpool can be freed */ 3749132943Sgshapiro if (*statp == EX_OK && p != NULL) 3750132943Sgshapiro vp = newstr(p); 3751132943Sgshapiro sm_rpool_free(rpool); 375290792Sgshapiro 3753132943Sgshapiro /* need to restart LDAP connection? */ 3754132943Sgshapiro if (*statp == EX_RESTART) 375564562Sgshapiro { 3756132943Sgshapiro *statp = EX_TEMPFAIL; 3757132943Sgshapiro ldapmap_close(map); 375838032Speter } 375938032Speter 3760132943Sgshapiro errno = save_errno; 3761132943Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 376238032Speter { 376364562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 376464562Sgshapiro { 376564562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3766244833Sgshapiro syserr("Error getting LDAP results, map=%s, name=%s", 3767244833Sgshapiro map->map_mname, name); 376864562Sgshapiro else 3769244833Sgshapiro syserr("451 4.3.5 Error getting LDAP results, map=%s, name=%s", 3770244833Sgshapiro map->map_mname, name); 377164562Sgshapiro } 377277349Sgshapiro errno = save_errno; 377364562Sgshapiro return NULL; 377438032Speter } 377590792Sgshapiro 377664562Sgshapiro /* Did we match anything? */ 377771345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 377864562Sgshapiro return NULL; 377938032Speter 378064562Sgshapiro if (*statp == EX_OK) 378164562Sgshapiro { 378264562Sgshapiro if (LogLevel > 9) 378364562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 3784244833Sgshapiro "ldap=%s, %.100s=>%s", map->map_mname, name, 378571345Sgshapiro vp == NULL ? "<NULL>" : vp); 378664562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 378764562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 378864562Sgshapiro else 378971345Sgshapiro { 379071345Sgshapiro /* vp != NULL according to test above */ 379164562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 379271345Sgshapiro } 379371345Sgshapiro if (vp != NULL) 379490792Sgshapiro sm_free(vp); /* XXX */ 379564562Sgshapiro } 379664562Sgshapiro return result; 379738032Speter} 379838032Speter 379938032Speter/* 380064562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 380164562Sgshapiro** 380264562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 380366494Sgshapiro** secret, and PID so we don't have multiple connections open to 380466494Sgshapiro** the same server for different maps. Need a separate connection 380566494Sgshapiro** per PID since a parent process may close the map before the 380666494Sgshapiro** child is done with it. 380764562Sgshapiro** 380864562Sgshapiro** Parameters: 380964562Sgshapiro** lmap -- LDAP map information 381064562Sgshapiro** 381164562Sgshapiro** Returns: 381264562Sgshapiro** Symbol table entry for the LDAP connection. 381338032Speter*/ 381438032Speter 381564562Sgshapirostatic STAB * 381664562Sgshapiroldapmap_findconn(lmap) 381790792Sgshapiro SM_LDAP_STRUCT *lmap; 381838032Speter{ 381994334Sgshapiro char *format; 382064562Sgshapiro char *nbuf; 3821132943Sgshapiro char *id; 382290792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 382338032Speter 3824132943Sgshapiro if (lmap->ldap_host != NULL) 3825132943Sgshapiro id = lmap->ldap_host; 3826132943Sgshapiro else if (lmap->ldap_uri != NULL) 3827132943Sgshapiro id = lmap->ldap_uri; 3828132943Sgshapiro else 3829132943Sgshapiro id = "localhost"; 3830132943Sgshapiro 383194334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 383294334Sgshapiro nbuf = sm_stringf_x(format, 3833132943Sgshapiro id, 383490792Sgshapiro CONDELSE, 383590792Sgshapiro lmap->ldap_port, 383690792Sgshapiro CONDELSE, 383794334Sgshapiro lmap->ldap_version, 383894334Sgshapiro CONDELSE, 383990792Sgshapiro (lmap->ldap_binddn == NULL ? "" 384090792Sgshapiro : lmap->ldap_binddn), 384190792Sgshapiro CONDELSE, 384290792Sgshapiro (lmap->ldap_secret == NULL ? "" 384390792Sgshapiro : lmap->ldap_secret), 384490792Sgshapiro (int) CurrentPid); 384590792Sgshapiro SM_TRY 384690792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 384790792Sgshapiro SM_FINALLY 384890792Sgshapiro sm_free(nbuf); 384990792Sgshapiro SM_END_TRY 385064562Sgshapiro return s; 385164562Sgshapiro} 385238032Speter/* 385364562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 385464562Sgshapiro*/ 385538032Speter 385690792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 385764562Sgshapiro{ 385864562Sgshapiro { "none", LDAP_AUTH_NONE }, 385964562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 386064562Sgshapiro# ifdef LDAP_AUTH_KRBV4 386164562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 386264562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 386364562Sgshapiro { NULL, 0 } 386464562Sgshapiro}; 386538032Speter 386690792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 386764562Sgshapiro{ 386864562Sgshapiro { "never", LDAP_DEREF_NEVER }, 386964562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 387064562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 387164562Sgshapiro { "find", LDAP_DEREF_FINDING }, 387264562Sgshapiro { NULL, 0 } 387364562Sgshapiro}; 387438032Speter 387590792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 387664562Sgshapiro{ 387764562Sgshapiro { "base", LDAP_SCOPE_BASE }, 387864562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 387964562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 388064562Sgshapiro { NULL, 0 } 388164562Sgshapiro}; 388238032Speter 388364562Sgshapirobool 388464562Sgshapiroldapmap_parseargs(map, args) 388564562Sgshapiro MAP *map; 388664562Sgshapiro char *args; 388764562Sgshapiro{ 388890792Sgshapiro bool secretread = true; 3889132943Sgshapiro bool attrssetup = false; 389064562Sgshapiro int i; 389164562Sgshapiro register char *p = args; 389290792Sgshapiro SM_LDAP_STRUCT *lmap; 389364562Sgshapiro struct lamvalues *lam; 389464562Sgshapiro struct ladvalues *lad; 389564562Sgshapiro struct lssvalues *lss; 389690792Sgshapiro char ldapfilt[MAXLINE]; 389764562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 389864562Sgshapiro 389964562Sgshapiro /* Get ldap struct pointer from map */ 390090792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 390164562Sgshapiro 390264562Sgshapiro /* Check if setting the initial LDAP defaults */ 390364562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 390464562Sgshapiro { 390590792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 3906168515Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof(*lmap)); 390764562Sgshapiro if (LDAPDefaults == NULL) 390890792Sgshapiro sm_ldap_clear(lmap); 390964562Sgshapiro else 391064562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 391164562Sgshapiro } 391264562Sgshapiro 391364562Sgshapiro /* there is no check whether there is really an argument */ 391464562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 391564562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 391690792Sgshapiro 391790792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 391890792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 391990792Sgshapiro { 392090792Sgshapiro /* Comma separate if used as an alias file */ 392190792Sgshapiro map->map_coldelim = ','; 392290792Sgshapiro if (*args == '\0') 392390792Sgshapiro { 392490792Sgshapiro int n; 392590792Sgshapiro char *lc; 392690792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 392790792Sgshapiro char lcbuf[MAXLINE]; 392890792Sgshapiro 392990792Sgshapiro /* Get $j */ 3930168515Sgshapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope); 393190792Sgshapiro if (jbuf[0] == '\0') 393290792Sgshapiro { 393390792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 3934168515Sgshapiro sizeof(jbuf)); 393590792Sgshapiro } 393690792Sgshapiro 393790792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 393890792Sgshapiro if (lc == NULL) 393990792Sgshapiro lc = ""; 394090792Sgshapiro else 394190792Sgshapiro { 3942168515Sgshapiro expand(lc, lcbuf, sizeof(lcbuf), CurEnv); 394390792Sgshapiro lc = lcbuf; 394490792Sgshapiro } 394590792Sgshapiro 3946168515Sgshapiro n = sm_snprintf(ldapfilt, sizeof(ldapfilt), 394790792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 394890792Sgshapiro lc, jbuf); 3949168515Sgshapiro if (n >= sizeof(ldapfilt)) 395090792Sgshapiro { 395190792Sgshapiro syserr("%s: Default LDAP string too long", 395290792Sgshapiro map->map_mname); 395390792Sgshapiro return false; 395490792Sgshapiro } 395590792Sgshapiro 395690792Sgshapiro /* default args for an alias LDAP entry */ 395790792Sgshapiro lmap->ldap_filter = ldapfilt; 3958132943Sgshapiro lmap->ldap_attr[0] = "objectClass"; 3959132943Sgshapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 3960132943Sgshapiro lmap->ldap_attr_needobjclass[0] = NULL; 3961132943Sgshapiro lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 3962132943Sgshapiro lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 3963132943Sgshapiro lmap->ldap_attr_needobjclass[1] = NULL; 3964132943Sgshapiro lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 3965132943Sgshapiro lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 3966132943Sgshapiro lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 3967132943Sgshapiro lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 3968132943Sgshapiro lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 3969132943Sgshapiro lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 3970132943Sgshapiro lmap->ldap_attr[4] = NULL; 3971132943Sgshapiro lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 3972132943Sgshapiro lmap->ldap_attr_needobjclass[4] = NULL; 3973132943Sgshapiro attrssetup = true; 397490792Sgshapiro } 397590792Sgshapiro } 397690792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 397790792Sgshapiro { 397890792Sgshapiro /* Space separate if used as a file class file */ 397990792Sgshapiro map->map_coldelim = ' '; 398090792Sgshapiro } 398190792Sgshapiro 3982203004Sgshapiro# if _FFR_LDAP_NETWORK_TIMEOUT 3983203004Sgshapiro lmap->ldap_networktmo = 120; 3984203004Sgshapiro# endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 3985203004Sgshapiro 398638032Speter for (;;) 398738032Speter { 398838032Speter while (isascii(*p) && isspace(*p)) 398938032Speter p++; 399038032Speter if (*p != '-') 399138032Speter break; 399238032Speter switch (*++p) 399338032Speter { 3994173340Sgshapiro case 'A': 3995173340Sgshapiro map->map_mflags |= MF_APPEND; 399638032Speter break; 399738032Speter 3998173340Sgshapiro case 'a': 3999173340Sgshapiro map->map_app = ++p; 400038032Speter break; 400138032Speter 4002173340Sgshapiro case 'D': 4003173340Sgshapiro map->map_mflags |= MF_DEFER; 400438032Speter break; 400538032Speter 400638032Speter case 'f': 400738032Speter map->map_mflags |= MF_NOFOLDCASE; 400838032Speter break; 400938032Speter 401038032Speter case 'm': 401138032Speter map->map_mflags |= MF_MATCHONLY; 401238032Speter break; 401338032Speter 4014173340Sgshapiro case 'N': 4015173340Sgshapiro map->map_mflags |= MF_INCLNULL; 4016173340Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 401738032Speter break; 401838032Speter 4019173340Sgshapiro case 'O': 4020173340Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 4021173340Sgshapiro break; 4022173340Sgshapiro 4023173340Sgshapiro case 'o': 4024173340Sgshapiro map->map_mflags |= MF_OPTIONAL; 4025173340Sgshapiro break; 4026173340Sgshapiro 402738032Speter case 'q': 402838032Speter map->map_mflags |= MF_KEEPQUOTES; 402938032Speter break; 403038032Speter 4031173340Sgshapiro case 'S': 4032173340Sgshapiro map->map_spacesub = *++p; 403338032Speter break; 403438032Speter 403538032Speter case 'T': 403638032Speter map->map_tapp = ++p; 403738032Speter break; 403838032Speter 403964562Sgshapiro case 't': 404064562Sgshapiro map->map_mflags |= MF_NODEFER; 404164562Sgshapiro break; 404264562Sgshapiro 404364562Sgshapiro case 'z': 404464562Sgshapiro if (*++p != '\\') 404564562Sgshapiro map->map_coldelim = *p; 404664562Sgshapiro else 404764562Sgshapiro { 404864562Sgshapiro switch (*++p) 404964562Sgshapiro { 405064562Sgshapiro case 'n': 405164562Sgshapiro map->map_coldelim = '\n'; 405264562Sgshapiro break; 405364562Sgshapiro 405464562Sgshapiro case 't': 405564562Sgshapiro map->map_coldelim = '\t'; 405664562Sgshapiro break; 405764562Sgshapiro 405864562Sgshapiro default: 405964562Sgshapiro map->map_coldelim = '\\'; 406064562Sgshapiro } 406164562Sgshapiro } 406264562Sgshapiro break; 406364562Sgshapiro 406464562Sgshapiro /* Start of ldapmap specific args */ 4065173340Sgshapiro case '1': 4066173340Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 4067173340Sgshapiro break; 406890792Sgshapiro 4069173340Sgshapiro# if _FFR_LDAP_SINGLEDN 4070173340Sgshapiro case '2': 4071173340Sgshapiro map->map_mflags |= MF_SINGLEDN; 4072173340Sgshapiro break; 4073173340Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 407490792Sgshapiro 4075173340Sgshapiro case 'b': /* search base */ 4076173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4077173340Sgshapiro continue; 4078173340Sgshapiro lmap->ldap_base = p; 4079173340Sgshapiro break; 4080173340Sgshapiro 4081173340Sgshapiro# if _FFR_LDAP_NETWORK_TIMEOUT 4082173340Sgshapiro case 'c': /* network (connect) timeout */ 4083173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4084173340Sgshapiro continue; 4085203004Sgshapiro lmap->ldap_networktmo = atoi(p); 4086173340Sgshapiro break; 4087173340Sgshapiro# endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 4088173340Sgshapiro 4089173340Sgshapiro case 'd': /* Dn to bind to server as */ 4090173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4091173340Sgshapiro continue; 4092173340Sgshapiro lmap->ldap_binddn = p; 4093173340Sgshapiro break; 4094173340Sgshapiro 4095173340Sgshapiro case 'H': /* Use LDAP URI */ 4096173340Sgshapiro# if !USE_LDAP_INIT 4097173340Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 4098173340Sgshapiro map->map_mname); 4099173340Sgshapiro return false; 4100173340Sgshapiro# else /* !USE_LDAP_INIT */ 4101173340Sgshapiro if (lmap->ldap_host != NULL) 4102173340Sgshapiro { 4103173340Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 4104173340Sgshapiro map->map_mname); 4105173340Sgshapiro return false; 410690792Sgshapiro } 4107173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4108173340Sgshapiro continue; 4109173340Sgshapiro lmap->ldap_uri = p; 411090792Sgshapiro break; 4111173340Sgshapiro# endif /* !USE_LDAP_INIT */ 411290792Sgshapiro 4113173340Sgshapiro case 'h': /* ldap host */ 4114173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4115173340Sgshapiro continue; 4116173340Sgshapiro if (lmap->ldap_uri != NULL) 4117173340Sgshapiro { 4118173340Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 4119173340Sgshapiro map->map_mname); 4120173340Sgshapiro return false; 4121173340Sgshapiro } 4122173340Sgshapiro lmap->ldap_host = p; 4123173340Sgshapiro break; 4124173340Sgshapiro 4125173340Sgshapiro case 'K': 4126173340Sgshapiro lmap->ldap_multi_args = true; 4127173340Sgshapiro break; 4128173340Sgshapiro 412938032Speter case 'k': /* search field */ 413038032Speter while (isascii(*++p) && isspace(*p)) 413138032Speter continue; 413264562Sgshapiro lmap->ldap_filter = p; 413338032Speter break; 413438032Speter 4135173340Sgshapiro case 'l': /* time limit */ 413638032Speter while (isascii(*++p) && isspace(*p)) 413738032Speter continue; 4138173340Sgshapiro lmap->ldap_timelimit = atoi(p); 4139173340Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 414038032Speter break; 414138032Speter 4142173340Sgshapiro case 'M': /* Method for binding */ 4143173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4144173340Sgshapiro continue; 4145173340Sgshapiro 4146173340Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 4147173340Sgshapiro p += 10; 4148173340Sgshapiro 4149173340Sgshapiro for (lam = LDAPAuthMethods; 4150173340Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 4151173340Sgshapiro { 4152173340Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 4153173340Sgshapiro strlen(lam->lam_name)) == 0) 4154173340Sgshapiro break; 4155173340Sgshapiro } 4156173340Sgshapiro if (lam->lam_name != NULL) 4157173340Sgshapiro lmap->ldap_method = lam->lam_code; 4158173340Sgshapiro else 4159173340Sgshapiro { 4160173340Sgshapiro /* bad config line */ 4161173340Sgshapiro if (!bitset(MCF_OPTFILE, 4162173340Sgshapiro map->map_class->map_cflags)) 4163173340Sgshapiro { 4164173340Sgshapiro char *ptr; 4165173340Sgshapiro 4166173340Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 4167173340Sgshapiro *ptr = '\0'; 4168173340Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 4169173340Sgshapiro p, map->map_mname); 4170173340Sgshapiro if (ptr != NULL) 4171173340Sgshapiro *ptr = ' '; 4172173340Sgshapiro return false; 4173173340Sgshapiro } 4174173340Sgshapiro } 417564562Sgshapiro break; 417664562Sgshapiro 4177173340Sgshapiro case 'n': /* retrieve attribute names only */ 4178173340Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 4179157001Sgshapiro break; 4180157001Sgshapiro 4181173340Sgshapiro /* 4182173340Sgshapiro ** This is a string that is dependent on the 4183173340Sgshapiro ** method used defined by 'M'. 4184173340Sgshapiro */ 4185173340Sgshapiro 4186173340Sgshapiro case 'P': /* Secret password for binding */ 4187173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4188173340Sgshapiro continue; 4189173340Sgshapiro lmap->ldap_secret = p; 4190173340Sgshapiro secretread = false; 4191173340Sgshapiro break; 4192173340Sgshapiro 4193173340Sgshapiro case 'p': /* ldap port */ 4194173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4195173340Sgshapiro continue; 4196173340Sgshapiro lmap->ldap_port = atoi(p); 4197173340Sgshapiro break; 4198173340Sgshapiro 419938032Speter /* args stolen from ldapsearch.c */ 420038032Speter case 'R': /* don't auto chase referrals */ 420164562Sgshapiro# ifdef LDAP_REFERRALS 420238032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 420364562Sgshapiro# else /* LDAP_REFERRALS */ 420490792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 420564562Sgshapiro# endif /* LDAP_REFERRALS */ 420638032Speter break; 420738032Speter 420864562Sgshapiro case 'r': /* alias dereferencing */ 420964562Sgshapiro while (isascii(*++p) && isspace(*p)) 421064562Sgshapiro continue; 421164562Sgshapiro 421290792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 421364562Sgshapiro p += 11; 421464562Sgshapiro 421564562Sgshapiro for (lad = LDAPAliasDereference; 421664562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 421738032Speter { 421890792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 421990792Sgshapiro strlen(lad->lad_name)) == 0) 422064562Sgshapiro break; 422138032Speter } 422264562Sgshapiro if (lad->lad_name != NULL) 422364562Sgshapiro lmap->ldap_deref = lad->lad_code; 422464562Sgshapiro else 422538032Speter { 422664562Sgshapiro /* bad config line */ 422764562Sgshapiro if (!bitset(MCF_OPTFILE, 422864562Sgshapiro map->map_class->map_cflags)) 422964562Sgshapiro { 423064562Sgshapiro char *ptr; 423164562Sgshapiro 423264562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 423364562Sgshapiro *ptr = '\0'; 423473188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 423564562Sgshapiro p, map->map_mname); 423664562Sgshapiro if (ptr != NULL) 423764562Sgshapiro *ptr = ' '; 423890792Sgshapiro return false; 423964562Sgshapiro } 424038032Speter } 424164562Sgshapiro break; 424264562Sgshapiro 424364562Sgshapiro case 's': /* search scope */ 424464562Sgshapiro while (isascii(*++p) && isspace(*p)) 424564562Sgshapiro continue; 424664562Sgshapiro 424790792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 424864562Sgshapiro p += 11; 424964562Sgshapiro 425064562Sgshapiro for (lss = LDAPSearchScope; 425164562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 425238032Speter { 425390792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 425490792Sgshapiro strlen(lss->lss_name)) == 0) 425564562Sgshapiro break; 425638032Speter } 425764562Sgshapiro if (lss->lss_name != NULL) 425864562Sgshapiro lmap->ldap_scope = lss->lss_code; 425938032Speter else 426064562Sgshapiro { 426164562Sgshapiro /* bad config line */ 426264562Sgshapiro if (!bitset(MCF_OPTFILE, 426364562Sgshapiro map->map_class->map_cflags)) 426438032Speter { 426538032Speter char *ptr; 426638032Speter 426738032Speter if ((ptr = strchr(p, ' ')) != NULL) 426838032Speter *ptr = '\0'; 426973188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 427038032Speter p, map->map_mname); 427138032Speter if (ptr != NULL) 427238032Speter *ptr = ' '; 427390792Sgshapiro return false; 427438032Speter } 427538032Speter } 427638032Speter break; 427738032Speter 4278173340Sgshapiro case 'V': 4279173340Sgshapiro if (*++p != '\\') 4280173340Sgshapiro lmap->ldap_attrsep = *p; 428164562Sgshapiro else 428264562Sgshapiro { 4283173340Sgshapiro switch (*++p) 428464562Sgshapiro { 4285173340Sgshapiro case 'n': 4286173340Sgshapiro lmap->ldap_attrsep = '\n'; 4287173340Sgshapiro break; 428864562Sgshapiro 4289173340Sgshapiro case 't': 4290173340Sgshapiro lmap->ldap_attrsep = '\t'; 4291173340Sgshapiro break; 4292173340Sgshapiro 4293173340Sgshapiro default: 4294173340Sgshapiro lmap->ldap_attrsep = '\\'; 429564562Sgshapiro } 429664562Sgshapiro } 429764562Sgshapiro break; 429864562Sgshapiro 4299173340Sgshapiro case 'v': /* attr to return */ 430094334Sgshapiro while (isascii(*++p) && isspace(*p)) 430194334Sgshapiro continue; 4302173340Sgshapiro lmap->ldap_attr[0] = p; 4303173340Sgshapiro lmap->ldap_attr[1] = NULL; 430494334Sgshapiro break; 430594334Sgshapiro 430694334Sgshapiro case 'w': 430794334Sgshapiro /* -w should be for passwd, -P should be for version */ 430894334Sgshapiro while (isascii(*++p) && isspace(*p)) 430994334Sgshapiro continue; 431094334Sgshapiro lmap->ldap_version = atoi(p); 4311132943Sgshapiro# ifdef LDAP_VERSION_MAX 431294334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 431394334Sgshapiro { 431494334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 431594334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 431694334Sgshapiro map->map_mname); 431794334Sgshapiro return false; 431894334Sgshapiro } 4319132943Sgshapiro# endif /* LDAP_VERSION_MAX */ 4320132943Sgshapiro# ifdef LDAP_VERSION_MIN 432194334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 432294334Sgshapiro { 432394334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 432494334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 432594334Sgshapiro map->map_mname); 432694334Sgshapiro return false; 432794334Sgshapiro } 4328132943Sgshapiro# endif /* LDAP_VERSION_MIN */ 432994334Sgshapiro break; 433094334Sgshapiro 4331173340Sgshapiro case 'Z': 4332173340Sgshapiro while (isascii(*++p) && isspace(*p)) 4333173340Sgshapiro continue; 4334173340Sgshapiro lmap->ldap_sizelimit = atoi(p); 4335168515Sgshapiro break; 4336168515Sgshapiro 433764562Sgshapiro default: 433864562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 433964562Sgshapiro break; 434038032Speter } 434138032Speter 434264562Sgshapiro /* need to account for quoted strings here */ 434364562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 434438032Speter { 434538032Speter if (*p == '"') 434638032Speter { 434738032Speter while (*++p != '"' && *p != '\0') 434838032Speter continue; 434938032Speter if (*p != '\0') 435038032Speter p++; 435138032Speter } 435238032Speter else 435338032Speter p++; 435438032Speter } 435538032Speter 435638032Speter if (*p != '\0') 435738032Speter *p++ = '\0'; 435838032Speter } 435938032Speter 436038032Speter if (map->map_app != NULL) 436164562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 436238032Speter if (map->map_tapp != NULL) 436364562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 436438032Speter 436538032Speter /* 436642575Speter ** We need to swallow up all the stuff into a struct 436742575Speter ** and dump it into map->map_dbptr1 436838032Speter */ 436938032Speter 4370132943Sgshapiro if (lmap->ldap_host != NULL && 437164562Sgshapiro (LDAPDefaults == NULL || 437264562Sgshapiro LDAPDefaults == lmap || 4373132943Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 4374132943Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 4375132943Sgshapiro map->map_domain = lmap->ldap_host; 437664562Sgshapiro 4377132943Sgshapiro if (lmap->ldap_uri != NULL && 4378132943Sgshapiro (LDAPDefaults == NULL || 4379132943Sgshapiro LDAPDefaults == lmap || 4380132943Sgshapiro LDAPDefaults->ldap_uri != lmap->ldap_uri)) 4381132943Sgshapiro lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 4382132943Sgshapiro map->map_domain = lmap->ldap_uri; 4383132943Sgshapiro 438464562Sgshapiro if (lmap->ldap_binddn != NULL && 438564562Sgshapiro (LDAPDefaults == NULL || 438664562Sgshapiro LDAPDefaults == lmap || 438764562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 438864562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 438964562Sgshapiro 439064562Sgshapiro if (lmap->ldap_secret != NULL && 439164562Sgshapiro (LDAPDefaults == NULL || 439264562Sgshapiro LDAPDefaults == lmap || 439364562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 439438032Speter { 439590792Sgshapiro SM_FILE_T *sfd; 439664562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 439738032Speter 439864562Sgshapiro if (DontLockReadFiles) 439964562Sgshapiro sff |= SFF_NOLOCK; 440038032Speter 440164562Sgshapiro /* need to use method to map secret to passwd string */ 440264562Sgshapiro switch (lmap->ldap_method) 440364562Sgshapiro { 440464562Sgshapiro case LDAP_AUTH_NONE: 440564562Sgshapiro /* Do nothing */ 440664562Sgshapiro break; 440738032Speter 440864562Sgshapiro case LDAP_AUTH_SIMPLE: 440938032Speter 441064562Sgshapiro /* 441164562Sgshapiro ** Secret is the name of a file with 441264562Sgshapiro ** the first line as the password. 441364562Sgshapiro */ 441464562Sgshapiro 441564562Sgshapiro /* Already read in the secret? */ 441664562Sgshapiro if (secretread) 441764562Sgshapiro break; 441864562Sgshapiro 441964562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 442064562Sgshapiro O_RDONLY, 0, sff); 442164562Sgshapiro if (sfd == NULL) 442264562Sgshapiro { 442364562Sgshapiro syserr("LDAP map: cannot open secret %s", 442464562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 442590792Sgshapiro return false; 442664562Sgshapiro } 4427168515Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof(m_tmp), 442866494Sgshapiro sfd, TimeOuts.to_fileopen, 442966494Sgshapiro "ldapmap_parseargs"); 443090792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 443198121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 443298121Sgshapiro { 443398121Sgshapiro syserr("LDAP map: secret in %s too long", 443498121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 443598121Sgshapiro return false; 443698121Sgshapiro } 443764562Sgshapiro if (lmap->ldap_secret != NULL && 443864562Sgshapiro strlen(m_tmp) > 0) 443964562Sgshapiro { 444064562Sgshapiro /* chomp newline */ 444164562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 444264562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 444364562Sgshapiro 444464562Sgshapiro lmap->ldap_secret = m_tmp; 444564562Sgshapiro } 444664562Sgshapiro break; 444764562Sgshapiro 444864562Sgshapiro# ifdef LDAP_AUTH_KRBV4 444964562Sgshapiro case LDAP_AUTH_KRBV4: 445064562Sgshapiro 445164562Sgshapiro /* 445264562Sgshapiro ** Secret is where the ticket file is 445364562Sgshapiro ** stashed 445464562Sgshapiro */ 445564562Sgshapiro 4456168515Sgshapiro (void) sm_snprintf(m_tmp, sizeof(m_tmp), 445790792Sgshapiro "KRBTKFILE=%s", 445890792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 445964562Sgshapiro lmap->ldap_secret = m_tmp; 446064562Sgshapiro break; 446164562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 446264562Sgshapiro 446364562Sgshapiro default: /* Should NEVER get here */ 446464562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 446590792Sgshapiro return false; 446690792Sgshapiro /* NOTREACHED */ 446764562Sgshapiro break; 446864562Sgshapiro } 446938032Speter } 447038032Speter 447164562Sgshapiro if (lmap->ldap_secret != NULL && 447264562Sgshapiro (LDAPDefaults == NULL || 447364562Sgshapiro LDAPDefaults == lmap || 447464562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 447564562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 447638032Speter 447764562Sgshapiro if (lmap->ldap_base != NULL && 447864562Sgshapiro (LDAPDefaults == NULL || 447964562Sgshapiro LDAPDefaults == lmap || 448064562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 448164562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 448264562Sgshapiro 448364562Sgshapiro /* 448464562Sgshapiro ** Save the server from extra work. If request is for a single 448564562Sgshapiro ** match, tell the server to only return enough records to 448664562Sgshapiro ** determine if there is a single match or not. This can not 448764562Sgshapiro ** be one since the server would only return one and we wouldn't 448864562Sgshapiro ** know if there were others available. 448964562Sgshapiro */ 449064562Sgshapiro 449164562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 449264562Sgshapiro lmap->ldap_sizelimit = 2; 449364562Sgshapiro 449464562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 449564562Sgshapiro if (lmap == LDAPDefaults) 449690792Sgshapiro return true; 449764562Sgshapiro 449864562Sgshapiro if (lmap->ldap_filter != NULL) 449964562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 450038032Speter else 450138032Speter { 450238032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 450338032Speter { 450438032Speter syserr("No filter given in map %s", map->map_mname); 450590792Sgshapiro return false; 450638032Speter } 450738032Speter } 450864562Sgshapiro 4509132943Sgshapiro if (!attrssetup && lmap->ldap_attr[0] != NULL) 451038032Speter { 451190792Sgshapiro bool recurse = false; 451294334Sgshapiro bool normalseen = false; 451390792Sgshapiro 451464562Sgshapiro i = 0; 451564562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 451664562Sgshapiro lmap->ldap_attr[0] = NULL; 451764562Sgshapiro 451894334Sgshapiro /* Prime the attr list with the objectClass attribute */ 451994334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 452094334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 452194334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 452294334Sgshapiro i++; 452394334Sgshapiro 452464562Sgshapiro while (p != NULL) 452538032Speter { 452664562Sgshapiro char *v; 452764562Sgshapiro 452864562Sgshapiro while (isascii(*p) && isspace(*p)) 452964562Sgshapiro p++; 453064562Sgshapiro if (*p == '\0') 453164562Sgshapiro break; 453264562Sgshapiro v = p; 453364562Sgshapiro p = strchr(v, ','); 453464562Sgshapiro if (p != NULL) 453564562Sgshapiro *p++ = '\0'; 453664562Sgshapiro 453771345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 453864562Sgshapiro { 453964562Sgshapiro syserr("Too many return attributes in %s (max %d)", 454064562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 454190792Sgshapiro return false; 454264562Sgshapiro } 454364562Sgshapiro if (*v != '\0') 454490792Sgshapiro { 454594334Sgshapiro int j; 454694334Sgshapiro int use; 454790792Sgshapiro char *type; 454894334Sgshapiro char *needobjclass; 454990792Sgshapiro 455090792Sgshapiro type = strchr(v, ':'); 455190792Sgshapiro if (type != NULL) 455294334Sgshapiro { 455390792Sgshapiro *type++ = '\0'; 455494334Sgshapiro needobjclass = strchr(type, ':'); 455594334Sgshapiro if (needobjclass != NULL) 455694334Sgshapiro *needobjclass++ = '\0'; 455794334Sgshapiro } 455894334Sgshapiro else 455994334Sgshapiro { 456094334Sgshapiro needobjclass = NULL; 456194334Sgshapiro } 456290792Sgshapiro 456394334Sgshapiro use = i; 456490792Sgshapiro 456594334Sgshapiro /* allow override on "objectClass" type */ 456694334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 456794334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 456890792Sgshapiro { 456994334Sgshapiro use = 0; 457094334Sgshapiro } 457194334Sgshapiro else 457294334Sgshapiro { 457394334Sgshapiro /* 457494334Sgshapiro ** Don't add something to attribute 457594334Sgshapiro ** list twice. 457694334Sgshapiro */ 457794334Sgshapiro 457894334Sgshapiro for (j = 1; j < i; j++) 457990792Sgshapiro { 458094334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 458194334Sgshapiro { 458294334Sgshapiro syserr("Duplicate attribute (%s) in %s", 458394334Sgshapiro v, map->map_mname); 458494334Sgshapiro return false; 458594334Sgshapiro } 458690792Sgshapiro } 458794334Sgshapiro 458894334Sgshapiro lmap->ldap_attr[use] = newstr(v); 458994334Sgshapiro if (needobjclass != NULL && 459094334Sgshapiro *needobjclass != '\0' && 459194334Sgshapiro *needobjclass != '*') 459290792Sgshapiro { 459394334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 459494334Sgshapiro } 459594334Sgshapiro else 459694334Sgshapiro { 459794334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 459894334Sgshapiro } 459994334Sgshapiro 460094334Sgshapiro } 460194334Sgshapiro 460294334Sgshapiro if (type != NULL && *type != '\0') 460394334Sgshapiro { 460494334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 460594334Sgshapiro { 460690792Sgshapiro recurse = true; 460794334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 460890792Sgshapiro } 460990792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 461090792Sgshapiro { 461190792Sgshapiro recurse = true; 461294334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 461390792Sgshapiro } 461490792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 461590792Sgshapiro { 461690792Sgshapiro recurse = true; 461794334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 461890792Sgshapiro } 461994334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 462090792Sgshapiro { 462194334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 462294334Sgshapiro normalseen = true; 462390792Sgshapiro } 462490792Sgshapiro else 462590792Sgshapiro { 462690792Sgshapiro syserr("Unknown attribute type (%s) in %s", 462790792Sgshapiro type, map->map_mname); 462890792Sgshapiro return false; 462990792Sgshapiro } 463090792Sgshapiro } 463190792Sgshapiro else 463294334Sgshapiro { 463394334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 463494334Sgshapiro normalseen = true; 463594334Sgshapiro } 463690792Sgshapiro i++; 463790792Sgshapiro } 463838032Speter } 463964562Sgshapiro lmap->ldap_attr[i] = NULL; 4640141858Sgshapiro 4641141858Sgshapiro /* Set in case needed in future code */ 4642132943Sgshapiro attrssetup = true; 4643141858Sgshapiro 464494334Sgshapiro if (recurse && !normalseen) 464590792Sgshapiro { 464694334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 464790792Sgshapiro map->map_mname); 464890792Sgshapiro return false; 464990792Sgshapiro } 465090792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 465190792Sgshapiro { 465290792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 465390792Sgshapiro map->map_mname); 465490792Sgshapiro return false; 465590792Sgshapiro } 465638032Speter } 465738032Speter map->map_db1 = (ARBPTR_T) lmap; 465890792Sgshapiro return true; 465938032Speter} 466038032Speter 466164562Sgshapiro/* 466264562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 466364562Sgshapiro** 466464562Sgshapiro** Parameters: 466564562Sgshapiro** spec -- map argument string from LDAPDefaults option 466664562Sgshapiro** 466764562Sgshapiro** Returns: 466864562Sgshapiro** None. 466964562Sgshapiro*/ 467064562Sgshapiro 467164562Sgshapirovoid 467264562Sgshapiroldapmap_set_defaults(spec) 467364562Sgshapiro char *spec; 467464562Sgshapiro{ 467573188Sgshapiro STAB *class; 467664562Sgshapiro MAP map; 467764562Sgshapiro 467864562Sgshapiro /* Allocate and set the default values */ 467964562Sgshapiro if (LDAPDefaults == NULL) 4680168515Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof(*LDAPDefaults)); 468190792Sgshapiro sm_ldap_clear(LDAPDefaults); 468264562Sgshapiro 4683168515Sgshapiro memset(&map, '\0', sizeof(map)); 468473188Sgshapiro 468573188Sgshapiro /* look up the class */ 468673188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 468773188Sgshapiro if (class == NULL) 468873188Sgshapiro { 468973188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 469073188Sgshapiro return; 469173188Sgshapiro } 469273188Sgshapiro map.map_class = &class->s_mapclass; 469364562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 469473188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 469564562Sgshapiro 469664562Sgshapiro (void) ldapmap_parseargs(&map, spec); 469764562Sgshapiro 469864562Sgshapiro /* These should never be set in LDAPDefaults */ 469964562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 470064562Sgshapiro map.map_spacesub != SpaceSub || 470164562Sgshapiro map.map_app != NULL || 470264562Sgshapiro map.map_tapp != NULL) 470364562Sgshapiro { 470464562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 470590792Sgshapiro SM_FREE_CLR(map.map_app); 470690792Sgshapiro SM_FREE_CLR(map.map_tapp); 470764562Sgshapiro } 470864562Sgshapiro 470964562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 471064562Sgshapiro { 471164562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 471294334Sgshapiro 471364562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 471464562Sgshapiro LDAPDefaults->ldap_filter = NULL; 471564562Sgshapiro } 471664562Sgshapiro 471764562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 471864562Sgshapiro { 471964562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 472064562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 472164562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 472264562Sgshapiro } 472364562Sgshapiro} 472464562Sgshapiro#endif /* LDAPMAP */ 472590792Sgshapiro/* 472664562Sgshapiro** PH map 472764562Sgshapiro*/ 472864562Sgshapiro 472990792Sgshapiro#if PH_MAP 473064562Sgshapiro 473164562Sgshapiro/* 473264562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 473364562Sgshapiro** This code is intended to replace the so-called "ph mailer". 4734168515Sgshapiro** Contributed by Mark D. Roth. Contact him for support. 473564562Sgshapiro*/ 473664562Sgshapiro 473790792Sgshapiro/* what version of the ph map code we're running */ 4738110560Sgshapirostatic char phmap_id[128]; 473964562Sgshapiro 474090792Sgshapiro/* sendmail version for phmap id string */ 474190792Sgshapiroextern const char Version[]; 474290792Sgshapiro 4743132943Sgshapiro/* assume we're using nph-1.2.x if not specified */ 4744110560Sgshapiro# ifndef NPH_VERSION 4745132943Sgshapiro# define NPH_VERSION 10200 4746110560Sgshapiro# endif 4747110560Sgshapiro 4748110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 4749110560Sgshapiro# if NPH_VERSION < 10200 4750110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 4751110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 4752110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 4753110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 4754110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 4755110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 4756110560Sgshapiro 475764562Sgshapiro/* 475864562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 475964562Sgshapiro*/ 476064562Sgshapiro 476164562Sgshapirobool 476264562Sgshapiroph_map_parseargs(map, args) 476364562Sgshapiro MAP *map; 476464562Sgshapiro char *args; 476564562Sgshapiro{ 476690792Sgshapiro register bool done; 476790792Sgshapiro register char *p = args; 476864562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 476964562Sgshapiro 477090792Sgshapiro /* initialize version string */ 4771168515Sgshapiro (void) sm_snprintf(phmap_id, sizeof(phmap_id), 477290792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 477390792Sgshapiro Version, libphclient_version); 477490792Sgshapiro 4775168515Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof(*pmap)); 477664562Sgshapiro 477764562Sgshapiro /* defaults */ 477864562Sgshapiro pmap->ph_servers = NULL; 477964562Sgshapiro pmap->ph_field_list = NULL; 478090792Sgshapiro pmap->ph = NULL; 478164562Sgshapiro pmap->ph_timeout = 0; 478290792Sgshapiro pmap->ph_fastclose = 0; 478364562Sgshapiro 478464562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 478564562Sgshapiro for (;;) 478664562Sgshapiro { 478764562Sgshapiro while (isascii(*p) && isspace(*p)) 478864562Sgshapiro p++; 478964562Sgshapiro if (*p != '-') 479064562Sgshapiro break; 479164562Sgshapiro switch (*++p) 479264562Sgshapiro { 479364562Sgshapiro case 'N': 479464562Sgshapiro map->map_mflags |= MF_INCLNULL; 479564562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 479664562Sgshapiro break; 479764562Sgshapiro 479864562Sgshapiro case 'O': 479964562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 480064562Sgshapiro break; 480164562Sgshapiro 480264562Sgshapiro case 'o': 480364562Sgshapiro map->map_mflags |= MF_OPTIONAL; 480464562Sgshapiro break; 480564562Sgshapiro 480664562Sgshapiro case 'f': 480764562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 480864562Sgshapiro break; 480964562Sgshapiro 481064562Sgshapiro case 'm': 481164562Sgshapiro map->map_mflags |= MF_MATCHONLY; 481264562Sgshapiro break; 481364562Sgshapiro 481464562Sgshapiro case 'A': 481564562Sgshapiro map->map_mflags |= MF_APPEND; 481664562Sgshapiro break; 481764562Sgshapiro 481864562Sgshapiro case 'q': 481964562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 482064562Sgshapiro break; 482164562Sgshapiro 482264562Sgshapiro case 't': 482364562Sgshapiro map->map_mflags |= MF_NODEFER; 482464562Sgshapiro break; 482564562Sgshapiro 482664562Sgshapiro case 'a': 482764562Sgshapiro map->map_app = ++p; 482864562Sgshapiro break; 482964562Sgshapiro 483064562Sgshapiro case 'T': 483164562Sgshapiro map->map_tapp = ++p; 483264562Sgshapiro break; 483364562Sgshapiro 483464562Sgshapiro case 'l': 483564562Sgshapiro while (isascii(*++p) && isspace(*p)) 483664562Sgshapiro continue; 483764562Sgshapiro pmap->ph_timeout = atoi(p); 483864562Sgshapiro break; 483964562Sgshapiro 484064562Sgshapiro case 'S': 484164562Sgshapiro map->map_spacesub = *++p; 484264562Sgshapiro break; 484364562Sgshapiro 484464562Sgshapiro case 'D': 484564562Sgshapiro map->map_mflags |= MF_DEFER; 484664562Sgshapiro break; 484764562Sgshapiro 484864562Sgshapiro case 'h': /* PH server list */ 484964562Sgshapiro while (isascii(*++p) && isspace(*p)) 485064562Sgshapiro continue; 485164562Sgshapiro pmap->ph_servers = p; 485264562Sgshapiro break; 485364562Sgshapiro 485490792Sgshapiro case 'k': /* fields to search for */ 485564562Sgshapiro while (isascii(*++p) && isspace(*p)) 485664562Sgshapiro continue; 485764562Sgshapiro pmap->ph_field_list = p; 485864562Sgshapiro break; 485964562Sgshapiro 486064562Sgshapiro default: 486190792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 486264562Sgshapiro } 486364562Sgshapiro 486464562Sgshapiro /* try to account for quoted strings */ 486564562Sgshapiro done = isascii(*p) && isspace(*p); 486664562Sgshapiro while (*p != '\0' && !done) 486764562Sgshapiro { 486864562Sgshapiro if (*p == '"') 486964562Sgshapiro { 487064562Sgshapiro while (*++p != '"' && *p != '\0') 487164562Sgshapiro continue; 487264562Sgshapiro if (*p != '\0') 487364562Sgshapiro p++; 487464562Sgshapiro } 487564562Sgshapiro else 487664562Sgshapiro p++; 487764562Sgshapiro done = isascii(*p) && isspace(*p); 487864562Sgshapiro } 487964562Sgshapiro 488064562Sgshapiro if (*p != '\0') 488164562Sgshapiro *p++ = '\0'; 488264562Sgshapiro } 488364562Sgshapiro 488464562Sgshapiro if (map->map_app != NULL) 488564562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 488664562Sgshapiro if (map->map_tapp != NULL) 488764562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 488864562Sgshapiro 488964562Sgshapiro if (pmap->ph_field_list != NULL) 489064562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 489164562Sgshapiro 489264562Sgshapiro if (pmap->ph_servers != NULL) 489364562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 489464562Sgshapiro else 489564562Sgshapiro { 489664562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 489790792Sgshapiro return false; 489864562Sgshapiro } 489964562Sgshapiro 490064562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 490190792Sgshapiro return true; 490264562Sgshapiro} 490364562Sgshapiro 490464562Sgshapiro/* 490564562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 490664562Sgshapiro*/ 490764562Sgshapiro 490890792Sgshapirovoid 490990792Sgshapiroph_map_close(map) 491064562Sgshapiro MAP *map; 491164562Sgshapiro{ 491264562Sgshapiro PH_MAP_STRUCT *pmap; 491364562Sgshapiro 491464562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 491590792Sgshapiro if (tTd(38, 9)) 491694334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 491790792Sgshapiro map->map_mname, pmap->ph_fastclose); 491864562Sgshapiro 491990792Sgshapiro 492090792Sgshapiro if (pmap->ph != NULL) 492164562Sgshapiro { 492290792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 492390792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 492490792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 492564562Sgshapiro } 492690792Sgshapiro 492764562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 492864562Sgshapiro} 492964562Sgshapiro 493064562Sgshapirostatic jmp_buf PHTimeout; 493164562Sgshapiro 493264562Sgshapiro/* ARGSUSED */ 493364562Sgshapirostatic void 493490792Sgshapiroph_timeout(unused) 493590792Sgshapiro int unused; 493664562Sgshapiro{ 493777349Sgshapiro /* 493877349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 493977349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 494077349Sgshapiro ** DOING. 494177349Sgshapiro */ 494277349Sgshapiro 494377349Sgshapiro errno = ETIMEDOUT; 494464562Sgshapiro longjmp(PHTimeout, 1); 494564562Sgshapiro} 494664562Sgshapiro 494790792Sgshapirostatic void 4948110560Sgshapiro#if NPH_VERSION >= 10200 4949110560Sgshapiroph_map_send_debug(appdata, text) 4950110560Sgshapiro void *appdata; 4951110560Sgshapiro#else 495290792Sgshapiroph_map_send_debug(text) 4953110560Sgshapiro#endif 495490792Sgshapiro char *text; 495564562Sgshapiro{ 495690792Sgshapiro if (LogLevel > 9) 495790792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 495890792Sgshapiro "ph_map_send_debug: ==> %s", text); 495990792Sgshapiro if (tTd(38, 20)) 496090792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 496190792Sgshapiro} 496264562Sgshapiro 496390792Sgshapirostatic void 4964110560Sgshapiro#if NPH_VERSION >= 10200 4965110560Sgshapiroph_map_recv_debug(appdata, text) 4966110560Sgshapiro void *appdata; 4967110560Sgshapiro#else 496890792Sgshapiroph_map_recv_debug(text) 4969110560Sgshapiro#endif 497090792Sgshapiro char *text; 497190792Sgshapiro{ 497290792Sgshapiro if (LogLevel > 10) 497390792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 497490792Sgshapiro "ph_map_recv_debug: <== %s", text); 497590792Sgshapiro if (tTd(38, 21)) 497690792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 497764562Sgshapiro} 497864562Sgshapiro 497990792Sgshapiro/* 498064562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 498164562Sgshapiro*/ 498264562Sgshapirobool 498364562Sgshapiroph_map_open(map, mode) 498464562Sgshapiro MAP *map; 498564562Sgshapiro int mode; 498664562Sgshapiro{ 498790792Sgshapiro PH_MAP_STRUCT *pmap; 498890792Sgshapiro register SM_EVENT *ev = NULL; 498964562Sgshapiro int save_errno = 0; 499090792Sgshapiro char *hostlist, *host; 499164562Sgshapiro 499264562Sgshapiro if (tTd(38, 2)) 499390792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 499464562Sgshapiro 499564562Sgshapiro mode &= O_ACCMODE; 499664562Sgshapiro if (mode != O_RDONLY) 499764562Sgshapiro { 499864562Sgshapiro /* issue a pseudo-error message */ 499990792Sgshapiro errno = SM_EMAPCANTWRITE; 500090792Sgshapiro return false; 500164562Sgshapiro } 500264562Sgshapiro 500366494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 500466494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 500566494Sgshapiro { 500666494Sgshapiro if (tTd(9, 1)) 500790792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 500890792Sgshapiro map->map_mname); 500966494Sgshapiro 501066494Sgshapiro /* 501190792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 501290792Sgshapiro ** a temporary failure using the bogus map and 501390792Sgshapiro ** map->map_tapp instead of the default permanent error. 501466494Sgshapiro */ 501566494Sgshapiro 501666494Sgshapiro map->map_mflags &= ~MF_DEFER; 501790792Sgshapiro return false; 501866494Sgshapiro } 501966494Sgshapiro 502064562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 502190792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 502264562Sgshapiro 502390792Sgshapiro /* try each host in the list */ 502464562Sgshapiro hostlist = newstr(pmap->ph_servers); 502590792Sgshapiro for (host = strtok(hostlist, " "); 502690792Sgshapiro host != NULL; 502790792Sgshapiro host = strtok(NULL, " ")) 502864562Sgshapiro { 502990792Sgshapiro /* set timeout */ 503064562Sgshapiro if (pmap->ph_timeout != 0) 503164562Sgshapiro { 503264562Sgshapiro if (setjmp(PHTimeout) != 0) 503364562Sgshapiro { 503464562Sgshapiro ev = NULL; 503564562Sgshapiro if (LogLevel > 1) 503664562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 503764562Sgshapiro "timeout connecting to PH server %.100s", 503890792Sgshapiro host); 503964562Sgshapiro errno = ETIMEDOUT; 504064562Sgshapiro goto ph_map_open_abort; 504164562Sgshapiro } 504290792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 504364562Sgshapiro } 504490792Sgshapiro 504590792Sgshapiro /* open connection to server */ 5046110560Sgshapiro if (ph_open(&(pmap->ph), host, 5047110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 5048110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 5049110560Sgshapiro#if NPH_VERSION >= 10200 5050110560Sgshapiro , NULL 5051110560Sgshapiro#endif 5052110560Sgshapiro ) == 0 5053110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 505464562Sgshapiro { 505564562Sgshapiro if (ev != NULL) 505690792Sgshapiro sm_clrevent(ev); 505790792Sgshapiro sm_free(hostlist); /* XXX */ 505890792Sgshapiro return true; 505964562Sgshapiro } 506090792Sgshapiro 506164562Sgshapiro ph_map_open_abort: 506290792Sgshapiro save_errno = errno; 506364562Sgshapiro if (ev != NULL) 506490792Sgshapiro sm_clrevent(ev); 5065110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 506690792Sgshapiro ph_map_close(map); 506790792Sgshapiro errno = save_errno; 506890792Sgshapiro } 506964562Sgshapiro 507066494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 507164562Sgshapiro { 507266494Sgshapiro if (errno == 0) 507364562Sgshapiro errno = EAGAIN; 507466494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 507566494Sgshapiro map->map_mname); 507664562Sgshapiro } 507766494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 507864562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 507966494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 508066494Sgshapiro map->map_mname); 508190792Sgshapiro sm_free(hostlist); /* XXX */ 508290792Sgshapiro return false; 508364562Sgshapiro} 508464562Sgshapiro 508564562Sgshapiro/* 508664562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 508764562Sgshapiro*/ 508864562Sgshapiro 508964562Sgshapirochar * 509064562Sgshapiroph_map_lookup(map, key, args, pstat) 509164562Sgshapiro MAP *map; 509264562Sgshapiro char *key; 509364562Sgshapiro char **args; 509464562Sgshapiro int *pstat; 509564562Sgshapiro{ 509690792Sgshapiro int i, save_errno = 0; 509790792Sgshapiro register SM_EVENT *ev = NULL; 509864562Sgshapiro PH_MAP_STRUCT *pmap; 509990792Sgshapiro char *value = NULL; 510064562Sgshapiro 510164562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 510264562Sgshapiro 510364562Sgshapiro *pstat = EX_OK; 510464562Sgshapiro 510590792Sgshapiro /* set timeout */ 510664562Sgshapiro if (pmap->ph_timeout != 0) 510764562Sgshapiro { 510864562Sgshapiro if (setjmp(PHTimeout) != 0) 510964562Sgshapiro { 511064562Sgshapiro ev = NULL; 511164562Sgshapiro if (LogLevel > 1) 511264562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 511364562Sgshapiro "timeout during PH lookup of %.100s", 511464562Sgshapiro key); 511564562Sgshapiro errno = ETIMEDOUT; 511664562Sgshapiro *pstat = EX_TEMPFAIL; 511764562Sgshapiro goto ph_map_lookup_abort; 511864562Sgshapiro } 511990792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 512064562Sgshapiro } 512164562Sgshapiro 512290792Sgshapiro /* perform lookup */ 512390792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 512490792Sgshapiro if (i == -1) 512590792Sgshapiro *pstat = EX_TEMPFAIL; 5126110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 512790792Sgshapiro *pstat = EX_UNAVAILABLE; 512864562Sgshapiro 512964562Sgshapiro ph_map_lookup_abort: 513064562Sgshapiro if (ev != NULL) 513190792Sgshapiro sm_clrevent(ev); 513264562Sgshapiro 513364562Sgshapiro /* 513490792Sgshapiro ** Close the connection if the timer popped 513564562Sgshapiro ** or we got a temporary PH error 513664562Sgshapiro */ 513764562Sgshapiro 513864562Sgshapiro if (*pstat == EX_TEMPFAIL) 513990792Sgshapiro { 514090792Sgshapiro save_errno = errno; 5141110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 514290792Sgshapiro ph_map_close(map); 514390792Sgshapiro errno = save_errno; 514490792Sgshapiro } 514564562Sgshapiro 514664562Sgshapiro if (*pstat == EX_OK) 514764562Sgshapiro { 514864562Sgshapiro if (tTd(38,20)) 514990792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 515064562Sgshapiro 515164562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 515290792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 515364562Sgshapiro else 515490792Sgshapiro return map_rewrite(map, value, strlen(value), args); 515564562Sgshapiro } 515664562Sgshapiro 515764562Sgshapiro return NULL; 515864562Sgshapiro} 515964562Sgshapiro#endif /* PH_MAP */ 5160168515Sgshapiro 516190792Sgshapiro/* 516242575Speter** syslog map 516338032Speter*/ 516438032Speter 516538032Speter#define map_prio map_lockfd /* overload field */ 516638032Speter 516738032Speter/* 516842575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 516938032Speter*/ 517038032Speter 517138032Speterbool 517238032Spetersyslog_map_parseargs(map, args) 517338032Speter MAP *map; 517438032Speter char *args; 517538032Speter{ 517638032Speter char *p = args; 517738032Speter char *priority = NULL; 517838032Speter 517964562Sgshapiro /* there is no check whether there is really an argument */ 518064562Sgshapiro while (*p != '\0') 518138032Speter { 518238032Speter while (isascii(*p) && isspace(*p)) 518338032Speter p++; 518438032Speter if (*p != '-') 518538032Speter break; 518664562Sgshapiro ++p; 518764562Sgshapiro if (*p == 'D') 518864562Sgshapiro { 518964562Sgshapiro map->map_mflags |= MF_DEFER; 519064562Sgshapiro ++p; 519164562Sgshapiro } 519264562Sgshapiro else if (*p == 'S') 519364562Sgshapiro { 519464562Sgshapiro map->map_spacesub = *++p; 519564562Sgshapiro if (*p != '\0') 519664562Sgshapiro p++; 519764562Sgshapiro } 519864562Sgshapiro else if (*p == 'L') 519964562Sgshapiro { 520064562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 520164562Sgshapiro continue; 520264562Sgshapiro if (*p == '\0') 520364562Sgshapiro break; 520464562Sgshapiro priority = p; 520564562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 520664562Sgshapiro p++; 520764562Sgshapiro if (*p != '\0') 520864562Sgshapiro *p++ = '\0'; 520964562Sgshapiro } 521064562Sgshapiro else 521164562Sgshapiro { 521264562Sgshapiro syserr("Illegal option %c map syslog", *p); 521364562Sgshapiro ++p; 521464562Sgshapiro } 521538032Speter } 521638032Speter 521738032Speter if (priority == NULL) 521838032Speter map->map_prio = LOG_INFO; 521938032Speter else 522038032Speter { 522190792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 522238032Speter priority += 4; 522338032Speter 522438032Speter#ifdef LOG_EMERG 522590792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 522638032Speter map->map_prio = LOG_EMERG; 522738032Speter else 522864562Sgshapiro#endif /* LOG_EMERG */ 522938032Speter#ifdef LOG_ALERT 523090792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 523138032Speter map->map_prio = LOG_ALERT; 523238032Speter else 523364562Sgshapiro#endif /* LOG_ALERT */ 523438032Speter#ifdef LOG_CRIT 523590792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 523638032Speter map->map_prio = LOG_CRIT; 523738032Speter else 523864562Sgshapiro#endif /* LOG_CRIT */ 523938032Speter#ifdef LOG_ERR 524090792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 524138032Speter map->map_prio = LOG_ERR; 524238032Speter else 524364562Sgshapiro#endif /* LOG_ERR */ 524438032Speter#ifdef LOG_WARNING 524590792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 524638032Speter map->map_prio = LOG_WARNING; 524738032Speter else 524864562Sgshapiro#endif /* LOG_WARNING */ 524938032Speter#ifdef LOG_NOTICE 525090792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 525138032Speter map->map_prio = LOG_NOTICE; 525238032Speter else 525364562Sgshapiro#endif /* LOG_NOTICE */ 525438032Speter#ifdef LOG_INFO 525590792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 525638032Speter map->map_prio = LOG_INFO; 525738032Speter else 525864562Sgshapiro#endif /* LOG_INFO */ 525938032Speter#ifdef LOG_DEBUG 526090792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 526138032Speter map->map_prio = LOG_DEBUG; 526238032Speter else 526364562Sgshapiro#endif /* LOG_DEBUG */ 526438032Speter { 526590792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 526638032Speter priority); 526790792Sgshapiro return false; 526838032Speter } 526938032Speter } 527090792Sgshapiro return true; 527138032Speter} 527238032Speter 527338032Speter/* 527442575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 527538032Speter*/ 527638032Speter 527738032Speterchar * 527838032Spetersyslog_map_lookup(map, string, args, statp) 527938032Speter MAP *map; 528038032Speter char *string; 528138032Speter char **args; 528238032Speter int *statp; 528338032Speter{ 528438032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 528538032Speter 528638032Speter if (ptr != NULL) 528738032Speter { 528838032Speter if (tTd(38, 20)) 528990792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 529064562Sgshapiro map->map_mname, map->map_prio, ptr); 529138032Speter 529238032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 529338032Speter } 529438032Speter 529538032Speter *statp = EX_OK; 529638032Speter return ""; 529738032Speter} 529838032Speter 5299168515Sgshapiro#if _FFR_DPRINTF_MAP 530090792Sgshapiro/* 5301168515Sgshapiro** dprintf map 5302168515Sgshapiro*/ 5303168515Sgshapiro 5304168515Sgshapiro#define map_dbg_level map_lockfd /* overload field */ 5305168515Sgshapiro 5306168515Sgshapiro/* 5307168515Sgshapiro** DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages. 5308168515Sgshapiro*/ 5309168515Sgshapiro 5310168515Sgshapirobool 5311168515Sgshapirodprintf_map_parseargs(map, args) 5312168515Sgshapiro MAP *map; 5313168515Sgshapiro char *args; 5314168515Sgshapiro{ 5315168515Sgshapiro char *p = args; 5316168515Sgshapiro char *dbg_level = NULL; 5317168515Sgshapiro 5318168515Sgshapiro /* there is no check whether there is really an argument */ 5319168515Sgshapiro while (*p != '\0') 5320168515Sgshapiro { 5321168515Sgshapiro while (isascii(*p) && isspace(*p)) 5322168515Sgshapiro p++; 5323168515Sgshapiro if (*p != '-') 5324168515Sgshapiro break; 5325168515Sgshapiro ++p; 5326168515Sgshapiro if (*p == 'D') 5327168515Sgshapiro { 5328168515Sgshapiro map->map_mflags |= MF_DEFER; 5329168515Sgshapiro ++p; 5330168515Sgshapiro } 5331168515Sgshapiro else if (*p == 'S') 5332168515Sgshapiro { 5333168515Sgshapiro map->map_spacesub = *++p; 5334168515Sgshapiro if (*p != '\0') 5335168515Sgshapiro p++; 5336168515Sgshapiro } 5337168515Sgshapiro else if (*p == 'd') 5338168515Sgshapiro { 5339168515Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 5340168515Sgshapiro continue; 5341168515Sgshapiro if (*p == '\0') 5342168515Sgshapiro break; 5343168515Sgshapiro dbg_level = p; 5344168515Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 5345168515Sgshapiro p++; 5346168515Sgshapiro if (*p != '\0') 5347168515Sgshapiro *p++ = '\0'; 5348168515Sgshapiro } 5349168515Sgshapiro else 5350168515Sgshapiro { 5351168515Sgshapiro syserr("Illegal option %c map dprintf", *p); 5352168515Sgshapiro ++p; 5353168515Sgshapiro } 5354168515Sgshapiro } 5355168515Sgshapiro 5356168515Sgshapiro if (dbg_level == NULL) 5357168515Sgshapiro map->map_dbg_level = 0; 5358168515Sgshapiro else 5359168515Sgshapiro { 5360168515Sgshapiro if (!(isascii(*dbg_level) && isdigit(*dbg_level))) 5361168515Sgshapiro { 5362168515Sgshapiro syserr("dprintf map \"%s\", file %s: -d should specify a number, not %s", 5363168515Sgshapiro map->map_mname, map->map_file, 5364168515Sgshapiro dbg_level); 5365168515Sgshapiro return false; 5366168515Sgshapiro } 5367168515Sgshapiro map->map_dbg_level = atoi(dbg_level); 5368168515Sgshapiro } 5369168515Sgshapiro return true; 5370168515Sgshapiro} 5371168515Sgshapiro 5372168515Sgshapiro/* 5373168515Sgshapiro** DPRINTF_MAP_LOOKUP -- rewrite and print message. Always return empty string 5374168515Sgshapiro*/ 5375168515Sgshapiro 5376168515Sgshapirochar * 5377168515Sgshapirodprintf_map_lookup(map, string, args, statp) 5378168515Sgshapiro MAP *map; 5379168515Sgshapiro char *string; 5380168515Sgshapiro char **args; 5381168515Sgshapiro int *statp; 5382168515Sgshapiro{ 5383168515Sgshapiro char *ptr = map_rewrite(map, string, strlen(string), args); 5384168515Sgshapiro 5385168515Sgshapiro if (ptr != NULL && tTd(85, map->map_dbg_level)) 5386168515Sgshapiro sm_dprintf("%s\n", ptr); 5387168515Sgshapiro *statp = EX_OK; 5388168515Sgshapiro return ""; 5389168515Sgshapiro} 5390168515Sgshapiro#endif /* _FFR_DPRINTF_MAP */ 5391168515Sgshapiro 5392168515Sgshapiro/* 539338032Speter** HESIOD Modules 539438032Speter*/ 539538032Speter 539690792Sgshapiro#if HESIOD 539738032Speter 539838032Speterbool 539938032Speterhes_map_open(map, mode) 540038032Speter MAP *map; 540138032Speter int mode; 540238032Speter{ 540338032Speter if (tTd(38, 2)) 540490792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 540538032Speter map->map_mname, map->map_file, mode); 540638032Speter 540738032Speter if (mode != O_RDONLY) 540838032Speter { 540938032Speter /* issue a pseudo-error message */ 541090792Sgshapiro errno = SM_EMAPCANTWRITE; 541190792Sgshapiro return false; 541238032Speter } 541338032Speter 541464562Sgshapiro# ifdef HESIOD_INIT 541538032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 541690792Sgshapiro return true; 541738032Speter 541838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 541994334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 542090792Sgshapiro sm_errstring(errno)); 542190792Sgshapiro return false; 542264562Sgshapiro# else /* HESIOD_INIT */ 542338032Speter if (hes_error() == HES_ER_UNINIT) 542438032Speter hes_init(); 542538032Speter switch (hes_error()) 542638032Speter { 542738032Speter case HES_ER_OK: 542838032Speter case HES_ER_NOTFOUND: 542990792Sgshapiro return true; 543038032Speter } 543138032Speter 543238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 543394334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 543438032Speter 543590792Sgshapiro return false; 543664562Sgshapiro# endif /* HESIOD_INIT */ 543738032Speter} 543838032Speter 543938032Speterchar * 544038032Speterhes_map_lookup(map, name, av, statp) 544138032Speter MAP *map; 544238032Speter char *name; 544338032Speter char **av; 544438032Speter int *statp; 544538032Speter{ 544638032Speter char **hp; 544738032Speter 544838032Speter if (tTd(38, 20)) 544990792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 545038032Speter 545138032Speter if (name[0] == '\\') 545238032Speter { 545338032Speter char *np; 545438032Speter int nl; 545577349Sgshapiro int save_errno; 545638032Speter char nbuf[MAXNAME]; 545738032Speter 545838032Speter nl = strlen(name); 5459168515Sgshapiro if (nl < sizeof(nbuf) - 1) 546038032Speter np = nbuf; 546138032Speter else 546238032Speter np = xalloc(strlen(name) + 2); 546338032Speter np[0] = '\\'; 5464168515Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof(nbuf)) - 1); 546564562Sgshapiro# ifdef HESIOD_INIT 546638032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 546764562Sgshapiro# else /* HESIOD_INIT */ 546838032Speter hp = hes_resolve(np, map->map_file); 546964562Sgshapiro# endif /* HESIOD_INIT */ 547077349Sgshapiro save_errno = errno; 547138032Speter if (np != nbuf) 547290792Sgshapiro sm_free(np); /* XXX */ 547377349Sgshapiro errno = save_errno; 547438032Speter } 547538032Speter else 547638032Speter { 547764562Sgshapiro# ifdef HESIOD_INIT 547838032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 547964562Sgshapiro# else /* HESIOD_INIT */ 548038032Speter hp = hes_resolve(name, map->map_file); 548164562Sgshapiro# endif /* HESIOD_INIT */ 548238032Speter } 548364562Sgshapiro# ifdef HESIOD_INIT 548477349Sgshapiro if (hp == NULL || *hp == NULL) 548538032Speter { 548638032Speter switch (errno) 548738032Speter { 548838032Speter case ENOENT: 548938032Speter *statp = EX_NOTFOUND; 549038032Speter break; 549138032Speter case ECONNREFUSED: 549238032Speter *statp = EX_TEMPFAIL; 549338032Speter break; 549490792Sgshapiro case EMSGSIZE: 549538032Speter case ENOMEM: 549638032Speter default: 549738032Speter *statp = EX_UNAVAILABLE; 549838032Speter break; 549938032Speter } 550082017Sgshapiro if (hp != NULL) 550182017Sgshapiro hesiod_free_list(HesiodContext, hp); 550238032Speter return NULL; 550338032Speter } 550464562Sgshapiro# else /* HESIOD_INIT */ 550538032Speter if (hp == NULL || hp[0] == NULL) 550638032Speter { 550738032Speter switch (hes_error()) 550838032Speter { 550938032Speter case HES_ER_OK: 551038032Speter *statp = EX_OK; 551138032Speter break; 551238032Speter 551338032Speter case HES_ER_NOTFOUND: 551438032Speter *statp = EX_NOTFOUND; 551538032Speter break; 551638032Speter 551738032Speter case HES_ER_CONFIG: 551838032Speter *statp = EX_UNAVAILABLE; 551938032Speter break; 552038032Speter 552138032Speter case HES_ER_NET: 552238032Speter *statp = EX_TEMPFAIL; 552338032Speter break; 552438032Speter } 552538032Speter return NULL; 552638032Speter } 552764562Sgshapiro# endif /* HESIOD_INIT */ 552838032Speter 552938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 553038032Speter return map_rewrite(map, name, strlen(name), NULL); 553138032Speter else 553238032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 553338032Speter} 553438032Speter 553590792Sgshapiro/* 553690792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 553790792Sgshapiro*/ 553890792Sgshapiro 553990792Sgshapirovoid 554090792Sgshapirohes_map_close(map) 554190792Sgshapiro MAP *map; 554290792Sgshapiro{ 554390792Sgshapiro if (tTd(38, 20)) 554490792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 554590792Sgshapiro 554690792Sgshapiro# ifdef HESIOD_INIT 554790792Sgshapiro /* Free the hesiod context */ 554890792Sgshapiro if (HesiodContext != NULL) 554990792Sgshapiro { 555090792Sgshapiro hesiod_end(HesiodContext); 555190792Sgshapiro HesiodContext = NULL; 555290792Sgshapiro } 555390792Sgshapiro# endif /* HESIOD_INIT */ 555490792Sgshapiro} 555590792Sgshapiro 555664562Sgshapiro#endif /* HESIOD */ 555790792Sgshapiro/* 555838032Speter** NeXT NETINFO Modules 555938032Speter*/ 556038032Speter 556138032Speter#if NETINFO 556238032Speter 556338032Speter# define NETINFO_DEFAULT_DIR "/aliases" 556438032Speter# define NETINFO_DEFAULT_PROPERTY "members" 556538032Speter 556638032Speter/* 556738032Speter** NI_MAP_OPEN -- open NetInfo Aliases 556838032Speter*/ 556938032Speter 557038032Speterbool 557138032Speterni_map_open(map, mode) 557238032Speter MAP *map; 557338032Speter int mode; 557438032Speter{ 557538032Speter if (tTd(38, 2)) 557690792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 557738032Speter map->map_mname, map->map_file, mode); 557838032Speter mode &= O_ACCMODE; 557938032Speter 558038032Speter if (*map->map_file == '\0') 558138032Speter map->map_file = NETINFO_DEFAULT_DIR; 558238032Speter 558338032Speter if (map->map_valcolnm == NULL) 558438032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 558538032Speter 558690792Sgshapiro if (map->map_coldelim == '\0') 558790792Sgshapiro { 558890792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 558990792Sgshapiro map->map_coldelim = ','; 559090792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 559190792Sgshapiro map->map_coldelim = ' '; 559290792Sgshapiro } 559390792Sgshapiro return true; 559438032Speter} 559538032Speter 559638032Speter 559738032Speter/* 559838032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 559938032Speter*/ 560038032Speter 560138032Speterchar * 560238032Speterni_map_lookup(map, name, av, statp) 560338032Speter MAP *map; 560438032Speter char *name; 560538032Speter char **av; 560638032Speter int *statp; 560738032Speter{ 560838032Speter char *res; 560938032Speter char *propval; 561038032Speter 561138032Speter if (tTd(38, 20)) 561290792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 561338032Speter 561438032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 561538032Speter map->map_valcolnm, map->map_coldelim); 561638032Speter 561738032Speter if (propval == NULL) 561838032Speter return NULL; 561938032Speter 562090792Sgshapiro SM_TRY 562190792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 562290792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 562390792Sgshapiro else 562490792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 562590792Sgshapiro SM_FINALLY 562690792Sgshapiro sm_free(propval); 562790792Sgshapiro SM_END_TRY 562838032Speter return res; 562938032Speter} 563038032Speter 563138032Speter 563264562Sgshapirostatic bool 563338032Speterni_getcanonname(name, hbsize, statp) 563438032Speter char *name; 563538032Speter int hbsize; 563638032Speter int *statp; 563738032Speter{ 563838032Speter char *vptr; 563938032Speter char *ptr; 564038032Speter char nbuf[MAXNAME + 1]; 564138032Speter 564238032Speter if (tTd(38, 20)) 564390792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 564438032Speter 5645168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 564638032Speter { 564738032Speter *statp = EX_UNAVAILABLE; 564890792Sgshapiro return false; 564938032Speter } 565073188Sgshapiro (void) shorten_hostname(nbuf); 565138032Speter 565238032Speter /* we only accept single token search key */ 565338032Speter if (strchr(nbuf, '.')) 565438032Speter { 565538032Speter *statp = EX_NOHOST; 565690792Sgshapiro return false; 565738032Speter } 565838032Speter 565938032Speter /* Do the search */ 566038032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 566138032Speter 566238032Speter if (vptr == NULL) 566338032Speter { 566438032Speter *statp = EX_NOHOST; 566590792Sgshapiro return false; 566638032Speter } 566738032Speter 566838032Speter /* Only want the first machine name */ 566938032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 567038032Speter *ptr = '\0'; 567138032Speter 567290792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 567338032Speter { 567477349Sgshapiro sm_free(vptr); 567590792Sgshapiro *statp = EX_UNAVAILABLE; 567690792Sgshapiro return true; 567738032Speter } 567877349Sgshapiro sm_free(vptr); 567990792Sgshapiro *statp = EX_OK; 568090792Sgshapiro return false; 568138032Speter} 568290792Sgshapiro#endif /* NETINFO */ 568338032Speter/* 568438032Speter** TEXT (unindexed text file) Modules 568538032Speter** 568638032Speter** This code donated by Sun Microsystems. 568738032Speter*/ 568838032Speter 568938032Speter#define map_sff map_lockfd /* overload field */ 569038032Speter 569138032Speter 569238032Speter/* 569338032Speter** TEXT_MAP_OPEN -- open text table 569438032Speter*/ 569538032Speter 569638032Speterbool 569738032Spetertext_map_open(map, mode) 569838032Speter MAP *map; 569938032Speter int mode; 570038032Speter{ 570164562Sgshapiro long sff; 570238032Speter int i; 570338032Speter 570438032Speter if (tTd(38, 2)) 570590792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 570638032Speter map->map_mname, map->map_file, mode); 570738032Speter 570838032Speter mode &= O_ACCMODE; 570938032Speter if (mode != O_RDONLY) 571038032Speter { 571138032Speter errno = EPERM; 571290792Sgshapiro return false; 571338032Speter } 571438032Speter 571538032Speter if (*map->map_file == '\0') 571638032Speter { 571738032Speter syserr("text map \"%s\": file name required", 571838032Speter map->map_mname); 571990792Sgshapiro return false; 572038032Speter } 572138032Speter 572238032Speter if (map->map_file[0] != '/') 572338032Speter { 572438032Speter syserr("text map \"%s\": file name must be fully qualified", 572538032Speter map->map_mname); 572690792Sgshapiro return false; 572738032Speter } 572838032Speter 572938032Speter sff = SFF_ROOTOK|SFF_REGONLY; 573064562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 573138032Speter sff |= SFF_NOWLINK; 573264562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 573338032Speter sff |= SFF_SAFEDIRPATH; 573438032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 573538032Speter sff, S_IRUSR, NULL)) != 0) 573638032Speter { 573764562Sgshapiro int save_errno = errno; 573864562Sgshapiro 573938032Speter /* cannot open this map */ 574038032Speter if (tTd(38, 2)) 574190792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 574264562Sgshapiro errno = save_errno; 574338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 574438032Speter syserr("text map \"%s\": unsafe map file %s", 574538032Speter map->map_mname, map->map_file); 574690792Sgshapiro return false; 574738032Speter } 574838032Speter 574938032Speter if (map->map_keycolnm == NULL) 575038032Speter map->map_keycolno = 0; 575138032Speter else 575238032Speter { 575338032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 575438032Speter { 575538032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 575638032Speter map->map_mname, map->map_file, 575738032Speter map->map_keycolnm); 575890792Sgshapiro return false; 575938032Speter } 576038032Speter map->map_keycolno = atoi(map->map_keycolnm); 576138032Speter } 576238032Speter 576338032Speter if (map->map_valcolnm == NULL) 576438032Speter map->map_valcolno = 0; 576538032Speter else 576638032Speter { 576738032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 576838032Speter { 576938032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 577038032Speter map->map_mname, map->map_file, 577138032Speter map->map_valcolnm); 577290792Sgshapiro return false; 577338032Speter } 577438032Speter map->map_valcolno = atoi(map->map_valcolnm); 577538032Speter } 577638032Speter 577738032Speter if (tTd(38, 2)) 577838032Speter { 577990792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 578038032Speter map->map_mname, map->map_file); 578138032Speter if (map->map_coldelim == '\0') 578290792Sgshapiro sm_dprintf("(white space)\n"); 578338032Speter else 578490792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 578538032Speter } 578638032Speter 578738032Speter map->map_sff = sff; 578890792Sgshapiro return true; 578938032Speter} 579038032Speter 579138032Speter 579238032Speter/* 579338032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 579438032Speter*/ 579538032Speter 579638032Speterchar * 579738032Spetertext_map_lookup(map, name, av, statp) 579838032Speter MAP *map; 579938032Speter char *name; 580038032Speter char **av; 580138032Speter int *statp; 580238032Speter{ 580338032Speter char *vp; 580438032Speter auto int vsize; 580538032Speter int buflen; 580690792Sgshapiro SM_FILE_T *f; 580738032Speter char delim; 580838032Speter int key_idx; 580938032Speter bool found_it; 581064562Sgshapiro long sff = map->map_sff; 581138032Speter char search_key[MAXNAME + 1]; 581238032Speter char linebuf[MAXLINE]; 581338032Speter char buf[MAXNAME + 1]; 581438032Speter 581590792Sgshapiro found_it = false; 581638032Speter if (tTd(38, 20)) 581790792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 581838032Speter 581938032Speter buflen = strlen(name); 5820168515Sgshapiro if (buflen > sizeof(search_key) - 1) 5821168515Sgshapiro buflen = sizeof(search_key) - 1; /* XXX just cut if off? */ 582264562Sgshapiro memmove(search_key, name, buflen); 582338032Speter search_key[buflen] = '\0'; 582438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 582538032Speter makelower(search_key); 582638032Speter 582738032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 582838032Speter if (f == NULL) 582938032Speter { 583038032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 583138032Speter *statp = EX_UNAVAILABLE; 583238032Speter return NULL; 583338032Speter } 583438032Speter key_idx = map->map_keycolno; 583538032Speter delim = map->map_coldelim; 583698121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 5837168515Sgshapiro linebuf, sizeof(linebuf)) != NULL) 583838032Speter { 583938032Speter char *p; 584038032Speter 584138032Speter /* skip comment line */ 584238032Speter if (linebuf[0] == '#') 584338032Speter continue; 584438032Speter p = strchr(linebuf, '\n'); 584538032Speter if (p != NULL) 584638032Speter *p = '\0'; 5847168515Sgshapiro p = get_column(linebuf, key_idx, delim, buf, sizeof(buf)); 584890792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 584938032Speter { 585090792Sgshapiro found_it = true; 585138032Speter break; 585238032Speter } 585338032Speter } 585490792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 585538032Speter if (!found_it) 585638032Speter { 585738032Speter *statp = EX_NOTFOUND; 585838032Speter return NULL; 585938032Speter } 5860168515Sgshapiro vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof(buf)); 586142575Speter if (vp == NULL) 586242575Speter { 586342575Speter *statp = EX_NOTFOUND; 586442575Speter return NULL; 586542575Speter } 586638032Speter vsize = strlen(vp); 586738032Speter *statp = EX_OK; 586838032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 586938032Speter return map_rewrite(map, name, strlen(name), NULL); 587038032Speter else 587138032Speter return map_rewrite(map, vp, vsize, av); 587238032Speter} 587338032Speter 587438032Speter/* 587538032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 587638032Speter*/ 587738032Speter 587864562Sgshapirostatic bool 587938032Spetertext_getcanonname(name, hbsize, statp) 588038032Speter char *name; 588138032Speter int hbsize; 588238032Speter int *statp; 588338032Speter{ 588438032Speter bool found; 588573188Sgshapiro char *dot; 588690792Sgshapiro SM_FILE_T *f; 588738032Speter char linebuf[MAXLINE]; 588838032Speter char cbuf[MAXNAME + 1]; 588938032Speter char nbuf[MAXNAME + 1]; 589038032Speter 589138032Speter if (tTd(38, 20)) 589290792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 589338032Speter 5894168515Sgshapiro if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf)) 589538032Speter { 589638032Speter *statp = EX_UNAVAILABLE; 589790792Sgshapiro return false; 589838032Speter } 589973188Sgshapiro dot = shorten_hostname(nbuf); 590038032Speter 590190792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 590290792Sgshapiro NULL); 590338032Speter if (f == NULL) 590438032Speter { 590538032Speter *statp = EX_UNAVAILABLE; 590690792Sgshapiro return false; 590738032Speter } 590890792Sgshapiro found = false; 590990792Sgshapiro while (!found && 591098121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 5911168515Sgshapiro linebuf, sizeof(linebuf)) != NULL) 591238032Speter { 591338032Speter char *p = strpbrk(linebuf, "#\n"); 591438032Speter 591538032Speter if (p != NULL) 591638032Speter *p = '\0'; 591738032Speter if (linebuf[0] != '\0') 591873188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 5919168515Sgshapiro cbuf, sizeof(cbuf)); 592038032Speter } 592190792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 592238032Speter if (!found) 592338032Speter { 592438032Speter *statp = EX_NOHOST; 592590792Sgshapiro return false; 592638032Speter } 592738032Speter 592890792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 592938032Speter { 593090792Sgshapiro *statp = EX_UNAVAILABLE; 593190792Sgshapiro return false; 593238032Speter } 593390792Sgshapiro *statp = EX_OK; 593490792Sgshapiro return true; 593538032Speter} 593690792Sgshapiro/* 593738032Speter** STAB (Symbol Table) Modules 593838032Speter*/ 593938032Speter 594038032Speter 594138032Speter/* 594238032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 594338032Speter*/ 594438032Speter 594538032Speter/* ARGSUSED2 */ 594638032Speterchar * 594738032Speterstab_map_lookup(map, name, av, pstat) 594838032Speter register MAP *map; 594938032Speter char *name; 595038032Speter char **av; 595138032Speter int *pstat; 595238032Speter{ 595338032Speter register STAB *s; 595438032Speter 595538032Speter if (tTd(38, 20)) 595690792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 595738032Speter map->map_mname, name); 595838032Speter 595938032Speter s = stab(name, ST_ALIAS, ST_FIND); 5960147078Sgshapiro if (s == NULL) 5961147078Sgshapiro return NULL; 5962147078Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 5963147078Sgshapiro return map_rewrite(map, name, strlen(name), NULL); 5964147078Sgshapiro else 5965147078Sgshapiro return map_rewrite(map, s->s_alias, strlen(s->s_alias), av); 596638032Speter} 596738032Speter 596838032Speter/* 596938032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 597038032Speter*/ 597138032Speter 597238032Spetervoid 597338032Speterstab_map_store(map, lhs, rhs) 597438032Speter register MAP *map; 597538032Speter char *lhs; 597638032Speter char *rhs; 597738032Speter{ 597838032Speter register STAB *s; 597938032Speter 598038032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 598138032Speter s->s_alias = newstr(rhs); 598238032Speter} 598338032Speter 598438032Speter 598538032Speter/* 598638032Speter** STAB_MAP_OPEN -- initialize (reads data file) 598738032Speter** 5988223067Sgshapiro** This is a weird case -- it is only intended as a fallback for 598938032Speter** aliases. For this reason, opens for write (only during a 599038032Speter** "newaliases") always fails, and opens for read open the 599138032Speter** actual underlying text file instead of the database. 599238032Speter*/ 599338032Speter 599438032Speterbool 599538032Speterstab_map_open(map, mode) 599638032Speter register MAP *map; 599738032Speter int mode; 599838032Speter{ 599990792Sgshapiro SM_FILE_T *af; 600064562Sgshapiro long sff; 600138032Speter struct stat st; 600238032Speter 600338032Speter if (tTd(38, 2)) 600490792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 600538032Speter map->map_mname, map->map_file, mode); 600638032Speter 600738032Speter mode &= O_ACCMODE; 600838032Speter if (mode != O_RDONLY) 600938032Speter { 601038032Speter errno = EPERM; 601190792Sgshapiro return false; 601238032Speter } 601338032Speter 601438032Speter sff = SFF_ROOTOK|SFF_REGONLY; 601564562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 601638032Speter sff |= SFF_NOWLINK; 601764562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 601838032Speter sff |= SFF_SAFEDIRPATH; 601938032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 602038032Speter if (af == NULL) 602190792Sgshapiro return false; 602290792Sgshapiro readaliases(map, af, false, false); 602338032Speter 602490792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 602538032Speter map->map_mtime = st.st_mtime; 602690792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 602738032Speter 602890792Sgshapiro return true; 602938032Speter} 603090792Sgshapiro/* 603138032Speter** Implicit Modules 603238032Speter** 603338032Speter** Tries several types. For back compatibility of aliases. 603438032Speter*/ 603538032Speter 603638032Speter 603738032Speter/* 603838032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 603938032Speter*/ 604038032Speter 604138032Speterchar * 604238032Speterimpl_map_lookup(map, name, av, pstat) 604338032Speter MAP *map; 604438032Speter char *name; 604538032Speter char **av; 604638032Speter int *pstat; 604738032Speter{ 604838032Speter if (tTd(38, 20)) 604990792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 605038032Speter map->map_mname, name); 605138032Speter 605290792Sgshapiro#if NEWDB 605338032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 605438032Speter return db_map_lookup(map, name, av, pstat); 605564562Sgshapiro#endif /* NEWDB */ 605690792Sgshapiro#if NDBM 605738032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 605838032Speter return ndbm_map_lookup(map, name, av, pstat); 605964562Sgshapiro#endif /* NDBM */ 606038032Speter return stab_map_lookup(map, name, av, pstat); 606138032Speter} 606238032Speter 606338032Speter/* 606438032Speter** IMPL_MAP_STORE -- store in open databases 606538032Speter*/ 606638032Speter 606738032Spetervoid 606838032Speterimpl_map_store(map, lhs, rhs) 606938032Speter MAP *map; 607038032Speter char *lhs; 607138032Speter char *rhs; 607238032Speter{ 607338032Speter if (tTd(38, 12)) 607490792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 607538032Speter map->map_mname, lhs, rhs); 607690792Sgshapiro#if NEWDB 607738032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 607838032Speter db_map_store(map, lhs, rhs); 607964562Sgshapiro#endif /* NEWDB */ 608090792Sgshapiro#if NDBM 608138032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 608238032Speter ndbm_map_store(map, lhs, rhs); 608364562Sgshapiro#endif /* NDBM */ 608438032Speter stab_map_store(map, lhs, rhs); 608538032Speter} 608638032Speter 608738032Speter/* 608838032Speter** IMPL_MAP_OPEN -- implicit database open 608938032Speter*/ 609038032Speter 609138032Speterbool 609238032Speterimpl_map_open(map, mode) 609338032Speter MAP *map; 609438032Speter int mode; 609538032Speter{ 609638032Speter if (tTd(38, 2)) 609790792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 609838032Speter map->map_mname, map->map_file, mode); 609938032Speter 610038032Speter mode &= O_ACCMODE; 610190792Sgshapiro#if NEWDB 610238032Speter map->map_mflags |= MF_IMPL_HASH; 610338032Speter if (hash_map_open(map, mode)) 610438032Speter { 610538032Speter# ifdef NDBM_YP_COMPAT 610638032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 610764562Sgshapiro# endif /* NDBM_YP_COMPAT */ 610890792Sgshapiro return true; 610938032Speter } 611038032Speter else 611138032Speter map->map_mflags &= ~MF_IMPL_HASH; 611264562Sgshapiro#endif /* NEWDB */ 611390792Sgshapiro#if NDBM 611438032Speter map->map_mflags |= MF_IMPL_NDBM; 611538032Speter if (ndbm_map_open(map, mode)) 611638032Speter { 611790792Sgshapiro return true; 611838032Speter } 611938032Speter else 612038032Speter map->map_mflags &= ~MF_IMPL_NDBM; 612164562Sgshapiro#endif /* NDBM */ 612238032Speter 612338032Speter#if defined(NEWDB) || defined(NDBM) 612438032Speter if (Verbose) 612538032Speter message("WARNING: cannot open alias database %s%s", 612638032Speter map->map_file, 612738032Speter mode == O_RDONLY ? "; reading text version" : ""); 612864562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 612938032Speter if (mode != O_RDONLY) 613038032Speter usrerr("Cannot rebuild aliases: no database format defined"); 613164562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 613238032Speter 613338032Speter if (mode == O_RDONLY) 613438032Speter return stab_map_open(map, mode); 613538032Speter else 613690792Sgshapiro return false; 613738032Speter} 613838032Speter 613938032Speter 614038032Speter/* 614138032Speter** IMPL_MAP_CLOSE -- close any open database(s) 614238032Speter*/ 614338032Speter 614438032Spetervoid 614538032Speterimpl_map_close(map) 614638032Speter MAP *map; 614738032Speter{ 614838032Speter if (tTd(38, 9)) 614990792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 615038032Speter map->map_mname, map->map_file, map->map_mflags); 615190792Sgshapiro#if NEWDB 615238032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 615338032Speter { 615438032Speter db_map_close(map); 615538032Speter map->map_mflags &= ~MF_IMPL_HASH; 615638032Speter } 615764562Sgshapiro#endif /* NEWDB */ 615838032Speter 615990792Sgshapiro#if NDBM 616038032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 616138032Speter { 616238032Speter ndbm_map_close(map); 616338032Speter map->map_mflags &= ~MF_IMPL_NDBM; 616438032Speter } 616564562Sgshapiro#endif /* NDBM */ 616638032Speter} 616790792Sgshapiro/* 616838032Speter** User map class. 616938032Speter** 617038032Speter** Provides access to the system password file. 617138032Speter*/ 617238032Speter 617338032Speter/* 617438032Speter** USER_MAP_OPEN -- open user map 617538032Speter** 617638032Speter** Really just binds field names to field numbers. 617738032Speter*/ 617838032Speter 617938032Speterbool 618038032Speteruser_map_open(map, mode) 618138032Speter MAP *map; 618238032Speter int mode; 618338032Speter{ 618438032Speter if (tTd(38, 2)) 618590792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 618638032Speter map->map_mname, mode); 618738032Speter 618838032Speter mode &= O_ACCMODE; 618938032Speter if (mode != O_RDONLY) 619038032Speter { 619138032Speter /* issue a pseudo-error message */ 619290792Sgshapiro errno = SM_EMAPCANTWRITE; 619390792Sgshapiro return false; 619438032Speter } 619538032Speter if (map->map_valcolnm == NULL) 619664562Sgshapiro /* EMPTY */ 619738032Speter /* nothing */ ; 619890792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 619938032Speter map->map_valcolno = 1; 620090792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 620138032Speter map->map_valcolno = 2; 620290792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 620338032Speter map->map_valcolno = 3; 620490792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 620538032Speter map->map_valcolno = 4; 620690792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 620738032Speter map->map_valcolno = 5; 620890792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 620938032Speter map->map_valcolno = 6; 621090792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 621138032Speter map->map_valcolno = 7; 621238032Speter else 621338032Speter { 621438032Speter syserr("User map %s: unknown column name %s", 621538032Speter map->map_mname, map->map_valcolnm); 621690792Sgshapiro return false; 621738032Speter } 621890792Sgshapiro return true; 621938032Speter} 622038032Speter 622138032Speter 622238032Speter/* 622338032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 622438032Speter*/ 622538032Speter 622638032Speter/* ARGSUSED3 */ 622738032Speterchar * 622838032Speteruser_map_lookup(map, key, av, statp) 622938032Speter MAP *map; 623038032Speter char *key; 623138032Speter char **av; 623238032Speter int *statp; 623338032Speter{ 623438032Speter auto bool fuzzy; 623590792Sgshapiro SM_MBDB_T user; 623638032Speter 623738032Speter if (tTd(38, 20)) 623890792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 623938032Speter map->map_mname, key); 624038032Speter 624190792Sgshapiro *statp = finduser(key, &fuzzy, &user); 624290792Sgshapiro if (*statp != EX_OK) 624338032Speter return NULL; 624438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 624538032Speter return map_rewrite(map, key, strlen(key), NULL); 624638032Speter else 624738032Speter { 624838032Speter char *rwval = NULL; 624938032Speter char buf[30]; 625038032Speter 625138032Speter switch (map->map_valcolno) 625238032Speter { 625338032Speter case 0: 625438032Speter case 1: 625590792Sgshapiro rwval = user.mbdb_name; 625638032Speter break; 625738032Speter 625838032Speter case 2: 625990792Sgshapiro rwval = "x"; /* passwd no longer supported */ 626038032Speter break; 626138032Speter 626238032Speter case 3: 6263168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 626490792Sgshapiro (int) user.mbdb_uid); 626538032Speter rwval = buf; 626638032Speter break; 626738032Speter 626838032Speter case 4: 6269168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", 627090792Sgshapiro (int) user.mbdb_gid); 627138032Speter rwval = buf; 627238032Speter break; 627338032Speter 627438032Speter case 5: 627590792Sgshapiro rwval = user.mbdb_fullname; 627638032Speter break; 627738032Speter 627838032Speter case 6: 627990792Sgshapiro rwval = user.mbdb_homedir; 628038032Speter break; 628138032Speter 628238032Speter case 7: 628390792Sgshapiro rwval = user.mbdb_shell; 628438032Speter break; 6285159609Sgshapiro default: 6286159609Sgshapiro syserr("user_map %s: bogus field %d", 6287159609Sgshapiro map->map_mname, map->map_valcolno); 6288159609Sgshapiro return NULL; 628938032Speter } 629038032Speter return map_rewrite(map, rwval, strlen(rwval), av); 629138032Speter } 629238032Speter} 629390792Sgshapiro/* 629438032Speter** Program map type. 629538032Speter** 629638032Speter** This provides access to arbitrary programs. It should be used 629738032Speter** only very sparingly, since there is no way to bound the cost 629838032Speter** of invoking an arbitrary program. 629938032Speter*/ 630038032Speter 630138032Speterchar * 630238032Speterprog_map_lookup(map, name, av, statp) 630338032Speter MAP *map; 630438032Speter char *name; 630538032Speter char **av; 630638032Speter int *statp; 630738032Speter{ 630838032Speter int i; 630964562Sgshapiro int save_errno; 631038032Speter int fd; 631164562Sgshapiro int status; 631238032Speter auto pid_t pid; 631364562Sgshapiro register char *p; 631438032Speter char *rval; 631538032Speter char *argv[MAXPV + 1]; 631638032Speter char buf[MAXLINE]; 631738032Speter 631838032Speter if (tTd(38, 20)) 631990792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 632038032Speter map->map_mname, name, map->map_file); 632138032Speter 632238032Speter i = 0; 632338032Speter argv[i++] = map->map_file; 632438032Speter if (map->map_rebuild != NULL) 632538032Speter { 6326168515Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof(buf)); 632738032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 632838032Speter { 632938032Speter if (i >= MAXPV - 1) 633038032Speter break; 633138032Speter argv[i++] = p; 633238032Speter } 633338032Speter } 633438032Speter argv[i++] = name; 633538032Speter argv[i] = NULL; 633638032Speter if (tTd(38, 21)) 633738032Speter { 633890792Sgshapiro sm_dprintf("prog_open:"); 633938032Speter for (i = 0; argv[i] != NULL; i++) 634090792Sgshapiro sm_dprintf(" %s", argv[i]); 634190792Sgshapiro sm_dprintf("\n"); 634238032Speter } 634390792Sgshapiro (void) sm_blocksignal(SIGCHLD); 634438032Speter pid = prog_open(argv, &fd, CurEnv); 634538032Speter if (pid < 0) 634638032Speter { 634738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 634838032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 634990792Sgshapiro map->map_mname, sm_errstring(errno)); 635038032Speter else if (tTd(38, 9)) 635190792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 635290792Sgshapiro map->map_mname, sm_errstring(errno)); 635338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 635438032Speter *statp = EX_OSFILE; 635538032Speter return NULL; 635638032Speter } 6357168515Sgshapiro i = read(fd, buf, sizeof(buf) - 1); 635838032Speter if (i < 0) 635938032Speter { 636090792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 636190792Sgshapiro map->map_mname, sm_errstring(errno)); 636238032Speter rval = NULL; 636338032Speter } 636438032Speter else if (i == 0) 636538032Speter { 636638032Speter if (tTd(38, 20)) 636790792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 636890792Sgshapiro map->map_mname); 636938032Speter rval = NULL; 637038032Speter } 637138032Speter else 637238032Speter { 637338032Speter buf[i] = '\0'; 637438032Speter p = strchr(buf, '\n'); 637538032Speter if (p != NULL) 637638032Speter *p = '\0'; 637738032Speter 637838032Speter /* collect the return value */ 637938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 638038032Speter rval = map_rewrite(map, name, strlen(name), NULL); 638138032Speter else 638277349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 638338032Speter 638438032Speter /* now flush any additional output */ 6385168515Sgshapiro while ((i = read(fd, buf, sizeof(buf))) > 0) 638638032Speter continue; 638738032Speter } 638838032Speter 638938032Speter /* wait for the process to terminate */ 639064562Sgshapiro (void) close(fd); 639164562Sgshapiro status = waitfor(pid); 639264562Sgshapiro save_errno = errno; 639390792Sgshapiro (void) sm_releasesignal(SIGCHLD); 639464562Sgshapiro errno = save_errno; 639538032Speter 639664562Sgshapiro if (status == -1) 639738032Speter { 639890792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 639990792Sgshapiro map->map_mname, sm_errstring(errno)); 640038032Speter *statp = EX_SOFTWARE; 640138032Speter rval = NULL; 640238032Speter } 640364562Sgshapiro else if (WIFEXITED(status)) 640438032Speter { 640564562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 640638032Speter rval = NULL; 640738032Speter } 640838032Speter else 640938032Speter { 641038032Speter syserr("prog_map_lookup(%s): child died on signal %d", 641190792Sgshapiro map->map_mname, status); 641238032Speter *statp = EX_UNAVAILABLE; 641338032Speter rval = NULL; 641438032Speter } 641538032Speter return rval; 641638032Speter} 641790792Sgshapiro/* 641838032Speter** Sequenced map type. 641938032Speter** 642038032Speter** Tries each map in order until something matches, much like 642138032Speter** implicit. Stores go to the first map in the list that can 642238032Speter** support storing. 642338032Speter** 642438032Speter** This is slightly unusual in that there are two interfaces. 642538032Speter** The "sequence" interface lets you stack maps arbitrarily. 642638032Speter** The "switch" interface builds a sequence map by looking 642738032Speter** at a system-dependent configuration file such as 642838032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 642938032Speter** 643038032Speter** We don't need an explicit open, since all maps are 643190792Sgshapiro** opened on demand. 643238032Speter*/ 643338032Speter 643438032Speter/* 643538032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 643638032Speter*/ 643738032Speter 643838032Speterbool 643938032Speterseq_map_parse(map, ap) 644038032Speter MAP *map; 644138032Speter char *ap; 644238032Speter{ 644338032Speter int maxmap; 644438032Speter 644538032Speter if (tTd(38, 2)) 644690792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 644738032Speter maxmap = 0; 644838032Speter while (*ap != '\0') 644938032Speter { 645038032Speter register char *p; 645138032Speter STAB *s; 645238032Speter 645338032Speter /* find beginning of map name */ 645438032Speter while (isascii(*ap) && isspace(*ap)) 645538032Speter ap++; 645664562Sgshapiro for (p = ap; 645764562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 645864562Sgshapiro p++) 645938032Speter continue; 646038032Speter if (*p != '\0') 646138032Speter *p++ = '\0'; 646238032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 646338032Speter p++; 646438032Speter if (*ap == '\0') 646538032Speter { 646638032Speter ap = p; 646738032Speter continue; 646838032Speter } 646938032Speter s = stab(ap, ST_MAP, ST_FIND); 647038032Speter if (s == NULL) 647138032Speter { 647238032Speter syserr("Sequence map %s: unknown member map %s", 647338032Speter map->map_mname, ap); 647438032Speter } 647590792Sgshapiro else if (maxmap >= MAXMAPSTACK) 647638032Speter { 647738032Speter syserr("Sequence map %s: too many member maps (%d max)", 647838032Speter map->map_mname, MAXMAPSTACK); 647938032Speter maxmap++; 648038032Speter } 648138032Speter else if (maxmap < MAXMAPSTACK) 648238032Speter { 648338032Speter map->map_stack[maxmap++] = &s->s_map; 648438032Speter } 648538032Speter ap = p; 648638032Speter } 648790792Sgshapiro return true; 648838032Speter} 648938032Speter 649038032Speter/* 649138032Speter** SWITCH_MAP_OPEN -- open a switched map 649238032Speter** 649338032Speter** This looks at the system-dependent configuration and builds 649438032Speter** a sequence map that does the same thing. 649538032Speter** 649638032Speter** Every system must define a switch_map_find routine in conf.c 649738032Speter** that will return the list of service types associated with a 649838032Speter** given service class. 649938032Speter*/ 650038032Speter 650138032Speterbool 650238032Speterswitch_map_open(map, mode) 650338032Speter MAP *map; 650438032Speter int mode; 650538032Speter{ 650638032Speter int mapno; 650738032Speter int nmaps; 650838032Speter char *maptype[MAXMAPSTACK]; 650938032Speter 651038032Speter if (tTd(38, 2)) 651190792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 651238032Speter map->map_mname, map->map_file, mode); 651338032Speter 651438032Speter mode &= O_ACCMODE; 651538032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 651638032Speter if (tTd(38, 19)) 651738032Speter { 651890792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 651938032Speter for (mapno = 0; mapno < nmaps; mapno++) 652090792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 652138032Speter } 652238032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 652390792Sgshapiro return false; 652438032Speter 652538032Speter for (mapno = 0; mapno < nmaps; mapno++) 652638032Speter { 652738032Speter register STAB *s; 652838032Speter char nbuf[MAXNAME + 1]; 652938032Speter 653038032Speter if (maptype[mapno] == NULL) 653138032Speter continue; 6532168515Sgshapiro (void) sm_strlcpyn(nbuf, sizeof(nbuf), 3, 653390792Sgshapiro map->map_mname, ".", maptype[mapno]); 653438032Speter s = stab(nbuf, ST_MAP, ST_FIND); 653538032Speter if (s == NULL) 653638032Speter { 653738032Speter syserr("Switch map %s: unknown member map %s", 653838032Speter map->map_mname, nbuf); 653938032Speter } 654038032Speter else 654138032Speter { 654238032Speter map->map_stack[mapno] = &s->s_map; 654338032Speter if (tTd(38, 4)) 654490792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 654590792Sgshapiro mapno, 654690792Sgshapiro s->s_map.map_class->map_cname, 654790792Sgshapiro nbuf); 654838032Speter } 654938032Speter } 655090792Sgshapiro return true; 655138032Speter} 655238032Speter 655390792Sgshapiro#if 0 655438032Speter/* 655538032Speter** SEQ_MAP_CLOSE -- close all underlying maps 655638032Speter*/ 655738032Speter 655838032Spetervoid 655938032Speterseq_map_close(map) 656038032Speter MAP *map; 656138032Speter{ 656238032Speter int mapno; 656338032Speter 656438032Speter if (tTd(38, 9)) 656590792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 656638032Speter 656738032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 656838032Speter { 656938032Speter MAP *mm = map->map_stack[mapno]; 657038032Speter 657138032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 657238032Speter continue; 657377349Sgshapiro mm->map_mflags |= MF_CLOSING; 657438032Speter mm->map_class->map_close(mm); 657577349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 657638032Speter } 657738032Speter} 657890792Sgshapiro#endif /* 0 */ 657938032Speter 658038032Speter/* 658138032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 658238032Speter*/ 658338032Speter 658438032Speterchar * 658538032Speterseq_map_lookup(map, key, args, pstat) 658638032Speter MAP *map; 658738032Speter char *key; 658838032Speter char **args; 658938032Speter int *pstat; 659038032Speter{ 659138032Speter int mapno; 659238032Speter int mapbit = 0x01; 659390792Sgshapiro bool tempfail = false; 659438032Speter 659538032Speter if (tTd(38, 20)) 659690792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 659738032Speter 659838032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 659938032Speter { 660038032Speter MAP *mm = map->map_stack[mapno]; 660138032Speter char *rv; 660238032Speter 660338032Speter if (mm == NULL) 660438032Speter continue; 660564562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 660664562Sgshapiro !openmap(mm)) 660738032Speter { 660838032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 660938032Speter { 661038032Speter *pstat = EX_UNAVAILABLE; 661138032Speter return NULL; 661238032Speter } 661338032Speter continue; 661438032Speter } 661538032Speter *pstat = EX_OK; 661638032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 661738032Speter if (rv != NULL) 661838032Speter return rv; 661938032Speter if (*pstat == EX_TEMPFAIL) 662038032Speter { 662138032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 662238032Speter return NULL; 662390792Sgshapiro tempfail = true; 662438032Speter } 662538032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 662638032Speter break; 662738032Speter } 662838032Speter if (tempfail) 662938032Speter *pstat = EX_TEMPFAIL; 663038032Speter else if (*pstat == EX_OK) 663138032Speter *pstat = EX_NOTFOUND; 663238032Speter return NULL; 663338032Speter} 663438032Speter 663538032Speter/* 663638032Speter** SEQ_MAP_STORE -- sequenced map store 663738032Speter*/ 663838032Speter 663938032Spetervoid 664038032Speterseq_map_store(map, key, val) 664138032Speter MAP *map; 664238032Speter char *key; 664338032Speter char *val; 664438032Speter{ 664538032Speter int mapno; 664638032Speter 664738032Speter if (tTd(38, 12)) 664890792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 664938032Speter map->map_mname, key, val); 665038032Speter 665138032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 665238032Speter { 665338032Speter MAP *mm = map->map_stack[mapno]; 665438032Speter 665538032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 665638032Speter continue; 665738032Speter 665838032Speter mm->map_class->map_store(mm, key, val); 665938032Speter return; 666038032Speter } 666138032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 666238032Speter map->map_mname, key, val); 666338032Speter} 666490792Sgshapiro/* 666538032Speter** NULL stubs 666638032Speter*/ 666738032Speter 666838032Speter/* ARGSUSED */ 666938032Speterbool 667038032Speternull_map_open(map, mode) 667138032Speter MAP *map; 667238032Speter int mode; 667338032Speter{ 667490792Sgshapiro return true; 667538032Speter} 667638032Speter 667738032Speter/* ARGSUSED */ 667838032Spetervoid 667938032Speternull_map_close(map) 668038032Speter MAP *map; 668138032Speter{ 668238032Speter return; 668338032Speter} 668438032Speter 668538032Speterchar * 668638032Speternull_map_lookup(map, key, args, pstat) 668738032Speter MAP *map; 668838032Speter char *key; 668938032Speter char **args; 669038032Speter int *pstat; 669138032Speter{ 669238032Speter *pstat = EX_NOTFOUND; 669338032Speter return NULL; 669438032Speter} 669538032Speter 669638032Speter/* ARGSUSED */ 669738032Spetervoid 669838032Speternull_map_store(map, key, val) 669938032Speter MAP *map; 670038032Speter char *key; 670138032Speter char *val; 670238032Speter{ 670338032Speter return; 670438032Speter} 670538032Speter 6706203004SgshapiroMAPCLASS NullMapClass = 6707203004Sgshapiro{ 6708203004Sgshapiro "null-map", NULL, 0, 6709203004Sgshapiro NULL, null_map_lookup, null_map_store, 6710203004Sgshapiro null_map_open, null_map_close, 6711203004Sgshapiro}; 6712203004Sgshapiro 671338032Speter/* 671438032Speter** BOGUS stubs 671538032Speter*/ 671638032Speter 671738032Speterchar * 671838032Speterbogus_map_lookup(map, key, args, pstat) 671938032Speter MAP *map; 672038032Speter char *key; 672138032Speter char **args; 672238032Speter int *pstat; 672338032Speter{ 672438032Speter *pstat = EX_TEMPFAIL; 672538032Speter return NULL; 672638032Speter} 672738032Speter 672838032SpeterMAPCLASS BogusMapClass = 672938032Speter{ 673090792Sgshapiro "bogus-map", NULL, 0, 673190792Sgshapiro NULL, bogus_map_lookup, null_map_store, 673290792Sgshapiro null_map_open, null_map_close, 673338032Speter}; 673490792Sgshapiro/* 673564562Sgshapiro** MACRO modules 673664562Sgshapiro*/ 673764562Sgshapiro 673864562Sgshapirochar * 673964562Sgshapiromacro_map_lookup(map, name, av, statp) 674064562Sgshapiro MAP *map; 674164562Sgshapiro char *name; 674264562Sgshapiro char **av; 674364562Sgshapiro int *statp; 674464562Sgshapiro{ 674564562Sgshapiro int mid; 674664562Sgshapiro 674764562Sgshapiro if (tTd(38, 20)) 674890792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 674964562Sgshapiro name == NULL ? "NULL" : name); 675064562Sgshapiro 675164562Sgshapiro if (name == NULL || 675264562Sgshapiro *name == '\0' || 675390792Sgshapiro (mid = macid(name)) == 0) 675464562Sgshapiro { 675564562Sgshapiro *statp = EX_CONFIG; 675664562Sgshapiro return NULL; 675764562Sgshapiro } 675864562Sgshapiro 675964562Sgshapiro if (av[1] == NULL) 676090792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 676164562Sgshapiro else 676290792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 676364562Sgshapiro 676464562Sgshapiro *statp = EX_OK; 676564562Sgshapiro return ""; 676664562Sgshapiro} 676790792Sgshapiro/* 676838032Speter** REGEX modules 676938032Speter*/ 677038032Speter 677190792Sgshapiro#if MAP_REGEX 677238032Speter 677338032Speter# include <regex.h> 677438032Speter 677538032Speter# define DEFAULT_DELIM CONDELSE 677638032Speter# define END_OF_FIELDS -1 677738032Speter# define ERRBUF_SIZE 80 677838032Speter# define MAX_MATCH 32 677938032Speter 678064562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 678138032Speter 678238032Speterstruct regex_map 678338032Speter{ 678471345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 678538032Speter int *regex_subfields; /* move to type MAP */ 678664562Sgshapiro char *regex_delim; /* move to type MAP */ 678738032Speter}; 678838032Speter 6789141858Sgshapirostatic int parse_fields __P((char *, int *, int, int)); 6790141858Sgshapirostatic char *regex_map_rewrite __P((MAP *, const char*, size_t, char **)); 6791141858Sgshapiro 679238032Speterstatic int 679338032Speterparse_fields(s, ibuf, blen, nr_substrings) 679438032Speter char *s; 679538032Speter int *ibuf; /* array */ 679638032Speter int blen; /* number of elements in ibuf */ 679738032Speter int nr_substrings; /* number of substrings in the pattern */ 679838032Speter{ 679938032Speter register char *cp; 680038032Speter int i = 0; 680190792Sgshapiro bool lastone = false; 680238032Speter 680338032Speter blen--; /* for terminating END_OF_FIELDS */ 680438032Speter cp = s; 680538032Speter do 680638032Speter { 680738032Speter for (;; cp++) 680838032Speter { 680938032Speter if (*cp == ',') 681038032Speter { 681138032Speter *cp = '\0'; 681238032Speter break; 681338032Speter } 681438032Speter if (*cp == '\0') 681538032Speter { 681690792Sgshapiro lastone = true; 681738032Speter break; 681838032Speter } 681938032Speter } 682038032Speter if (i < blen) 682138032Speter { 682238032Speter int val = atoi(s); 682338032Speter 682438032Speter if (val < 0 || val >= nr_substrings) 682538032Speter { 682638032Speter syserr("field (%d) out of range, only %d substrings in pattern", 682738032Speter val, nr_substrings); 682838032Speter return -1; 682938032Speter } 683038032Speter ibuf[i++] = val; 683138032Speter } 683238032Speter else 683338032Speter { 683490792Sgshapiro syserr("too many fields, %d max", blen); 683538032Speter return -1; 683638032Speter } 683738032Speter s = ++cp; 683838032Speter } while (!lastone); 683938032Speter ibuf[i] = END_OF_FIELDS; 684038032Speter return i; 684138032Speter} 684238032Speter 684338032Speterbool 684438032Speterregex_map_init(map, ap) 684538032Speter MAP *map; 684638032Speter char *ap; 684738032Speter{ 684838032Speter int regerr; 684938032Speter struct regex_map *map_p; 685038032Speter register char *p; 685138032Speter char *sub_param = NULL; 685238032Speter int pflags; 685390792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 685438032Speter 685538032Speter if (tTd(38, 2)) 685690792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 685764562Sgshapiro map->map_mname, ap); 685838032Speter 685938032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 686038032Speter p = ap; 6861168515Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof(*map_p)); 686271345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 686338032Speter 686438032Speter for (;;) 686564562Sgshapiro { 686638032Speter while (isascii(*p) && isspace(*p)) 686738032Speter p++; 686838032Speter if (*p != '-') 686938032Speter break; 687038032Speter switch (*++p) 687138032Speter { 687238032Speter case 'n': /* not */ 687338032Speter map->map_mflags |= MF_REGEX_NOT; 687438032Speter break; 687538032Speter 687638032Speter case 'f': /* case sensitive */ 687738032Speter map->map_mflags |= MF_NOFOLDCASE; 687838032Speter pflags &= ~REG_ICASE; 687938032Speter break; 688038032Speter 688138032Speter case 'b': /* basic regular expressions */ 688238032Speter pflags &= ~REG_EXTENDED; 688338032Speter break; 688438032Speter 688538032Speter case 's': /* substring match () syntax */ 688638032Speter sub_param = ++p; 688738032Speter pflags &= ~REG_NOSUB; 688838032Speter break; 688938032Speter 689038032Speter case 'd': /* delimiter */ 689164562Sgshapiro map_p->regex_delim = ++p; 689238032Speter break; 689338032Speter 689438032Speter case 'a': /* map append */ 689538032Speter map->map_app = ++p; 689638032Speter break; 689738032Speter 689838032Speter case 'm': /* matchonly */ 689938032Speter map->map_mflags |= MF_MATCHONLY; 690038032Speter break; 690138032Speter 6902120256Sgshapiro case 'q': 6903120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 6904120256Sgshapiro break; 6905120256Sgshapiro 690664562Sgshapiro case 'S': 690764562Sgshapiro map->map_spacesub = *++p; 690864562Sgshapiro break; 690964562Sgshapiro 691064562Sgshapiro case 'D': 691164562Sgshapiro map->map_mflags |= MF_DEFER; 691264562Sgshapiro break; 691364562Sgshapiro 691438032Speter } 691564562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 691664562Sgshapiro p++; 691764562Sgshapiro if (*p != '\0') 691864562Sgshapiro *p++ = '\0'; 691938032Speter } 692038032Speter if (tTd(38, 3)) 692190792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 692238032Speter 692371345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 692438032Speter { 692538032Speter /* Errorhandling */ 692638032Speter char errbuf[ERRBUF_SIZE]; 692738032Speter 692871345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 6929168515Sgshapiro errbuf, sizeof(errbuf)); 693090792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 693190792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 693290792Sgshapiro sm_free(map_p); /* XXX */ 693390792Sgshapiro return false; 693438032Speter } 693538032Speter 693638032Speter if (map->map_app != NULL) 693738032Speter map->map_app = newstr(map->map_app); 693864562Sgshapiro if (map_p->regex_delim != NULL) 693964562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 694038032Speter else 694164562Sgshapiro map_p->regex_delim = defdstr; 694238032Speter 694338032Speter if (!bitset(REG_NOSUB, pflags)) 694438032Speter { 694538032Speter /* substring matching */ 694638032Speter int substrings; 694764562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 694838032Speter 694971345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 695038032Speter 695138032Speter if (tTd(38, 3)) 695290792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 695364562Sgshapiro substrings); 695438032Speter 695538032Speter if (substrings >= MAX_MATCH) 695638032Speter { 695790792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 695890792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 695990792Sgshapiro sm_free(map_p); /* XXX */ 696090792Sgshapiro return false; 696138032Speter } 696238032Speter if (sub_param != NULL && sub_param[0] != '\0') 696338032Speter { 696438032Speter /* optional parameter -sfields */ 696538032Speter if (parse_fields(sub_param, fields, 696638032Speter MAX_MATCH + 1, substrings) == -1) 696790792Sgshapiro return false; 696838032Speter } 696938032Speter else 697038032Speter { 697138032Speter int i; 697238032Speter 697390792Sgshapiro /* set default fields */ 697438032Speter for (i = 0; i < substrings; i++) 697538032Speter fields[i] = i; 697638032Speter fields[i] = END_OF_FIELDS; 697738032Speter } 697838032Speter map_p->regex_subfields = fields; 697938032Speter if (tTd(38, 3)) 698038032Speter { 698138032Speter int *ip; 698238032Speter 698390792Sgshapiro sm_dprintf("regex_map_init: subfields"); 698438032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 698590792Sgshapiro sm_dprintf(" %d", *ip); 698690792Sgshapiro sm_dprintf("\n"); 698738032Speter } 698838032Speter } 698990792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 699090792Sgshapiro return true; 699138032Speter} 699238032Speter 699338032Speterstatic char * 699438032Speterregex_map_rewrite(map, s, slen, av) 699538032Speter MAP *map; 699638032Speter const char *s; 699738032Speter size_t slen; 699838032Speter char **av; 699938032Speter{ 700038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 700138032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 700238032Speter else 700377349Sgshapiro return map_rewrite(map, s, slen, av); 700438032Speter} 700538032Speter 700638032Speterchar * 700738032Speterregex_map_lookup(map, name, av, statp) 700838032Speter MAP *map; 700938032Speter char *name; 701038032Speter char **av; 701138032Speter int *statp; 701238032Speter{ 701338032Speter int reg_res; 701438032Speter struct regex_map *map_p; 701538032Speter regmatch_t pmatch[MAX_MATCH]; 701638032Speter 701738032Speter if (tTd(38, 20)) 701838032Speter { 701938032Speter char **cpp; 702038032Speter 702190792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 702264562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 702390792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 702438032Speter } 702538032Speter 702638032Speter map_p = (struct regex_map *)(map->map_db1); 702771345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 702864562Sgshapiro name, MAX_MATCH, pmatch, 0); 702938032Speter 703038032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 703138032Speter { 703238032Speter /* option -n */ 703338032Speter if (reg_res == REG_NOMATCH) 703490792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 703538032Speter else 703638032Speter return NULL; 703738032Speter } 703838032Speter if (reg_res == REG_NOMATCH) 703938032Speter return NULL; 704038032Speter 704138032Speter if (map_p->regex_subfields != NULL) 704238032Speter { 704338032Speter /* option -s */ 704438032Speter static char retbuf[MAXNAME]; 704538032Speter int fields[MAX_MATCH + 1]; 704690792Sgshapiro bool first = true; 704738032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 704890792Sgshapiro bool quotemode = false, bslashmode = false; 704938032Speter register char *dp, *sp; 705038032Speter char *endp, *ldp; 705138032Speter int *ip; 705238032Speter 705338032Speter dp = retbuf; 705438032Speter ldp = retbuf + sizeof(retbuf) - 1; 705538032Speter 705638032Speter if (av[1] != NULL) 705738032Speter { 705838032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 705971345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 706038032Speter { 706138032Speter *statp = EX_CONFIG; 706238032Speter return NULL; 706338032Speter } 706438032Speter ip = fields; 706538032Speter } 706638032Speter else 706738032Speter ip = map_p->regex_subfields; 706838032Speter 706938032Speter for ( ; *ip != END_OF_FIELDS; ip++) 707038032Speter { 707138032Speter if (!first) 707238032Speter { 707364562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 707438032Speter { 707538032Speter if (dp < ldp) 707638032Speter *dp++ = *sp; 707738032Speter } 707838032Speter } 707938032Speter else 708090792Sgshapiro first = false; 708138032Speter 708271345Sgshapiro if (*ip >= MAX_MATCH || 708371345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 708438032Speter continue; 708538032Speter 708638032Speter sp = name + pmatch[*ip].rm_so; 708738032Speter endp = name + pmatch[*ip].rm_eo; 708838032Speter for (; endp > sp; sp++) 708938032Speter { 709038032Speter if (dp < ldp) 709138032Speter { 709264562Sgshapiro if (bslashmode) 709364562Sgshapiro { 709438032Speter *dp++ = *sp; 709590792Sgshapiro bslashmode = false; 709638032Speter } 709764562Sgshapiro else if (quotemode && *sp != '"' && 709838032Speter *sp != '\\') 709938032Speter { 710038032Speter *dp++ = *sp; 710138032Speter } 710290792Sgshapiro else switch (*dp++ = *sp) 710338032Speter { 710490792Sgshapiro case '\\': 710590792Sgshapiro bslashmode = true; 710638032Speter break; 710738032Speter 710890792Sgshapiro case '(': 710938032Speter cmntcnt++; 711038032Speter break; 711138032Speter 711290792Sgshapiro case ')': 711338032Speter cmntcnt--; 711438032Speter break; 711538032Speter 711690792Sgshapiro case '<': 711738032Speter anglecnt++; 711838032Speter break; 711938032Speter 712090792Sgshapiro case '>': 712138032Speter anglecnt--; 712238032Speter break; 712338032Speter 712490792Sgshapiro case ' ': 712538032Speter spacecnt++; 712638032Speter break; 712738032Speter 712890792Sgshapiro case '"': 712938032Speter quotemode = !quotemode; 713038032Speter break; 713138032Speter } 713238032Speter } 713338032Speter } 713438032Speter } 713538032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 713638032Speter bslashmode || spacecnt != 0) 713738032Speter { 713864562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 713964562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 714064562Sgshapiro map->map_mname, name); 714138032Speter return NULL; 714238032Speter } 714338032Speter 714438032Speter *dp = '\0'; 714538032Speter 714638032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 714738032Speter } 714838032Speter return regex_map_rewrite(map, "", (size_t)0, av); 714938032Speter} 715038032Speter#endif /* MAP_REGEX */ 715190792Sgshapiro/* 715264562Sgshapiro** NSD modules 715364562Sgshapiro*/ 715490792Sgshapiro#if MAP_NSD 715564562Sgshapiro 715664562Sgshapiro# include <ndbm.h> 715764562Sgshapiro# define _DATUM_DEFINED 715864562Sgshapiro# include <ns_api.h> 715964562Sgshapiro 716064562Sgshapirotypedef struct ns_map_list 716164562Sgshapiro{ 716290792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 716390792Sgshapiro char *mapname; 716490792Sgshapiro struct ns_map_list *next; 716564562Sgshapiro} ns_map_list_t; 716664562Sgshapiro 716764562Sgshapirostatic ns_map_t * 716864562Sgshapirons_map_t_find(mapname) 716964562Sgshapiro char *mapname; 717064562Sgshapiro{ 717164562Sgshapiro static ns_map_list_t *ns_maps = NULL; 717264562Sgshapiro ns_map_list_t *ns_map; 717364562Sgshapiro 717464562Sgshapiro /* walk the list of maps looking for the correctly named map */ 717564562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 717664562Sgshapiro { 717764562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 717864562Sgshapiro break; 717964562Sgshapiro } 718064562Sgshapiro 718164562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 718264562Sgshapiro if (ns_map == NULL) 718364562Sgshapiro { 7184168515Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof(*ns_map)); 718564562Sgshapiro ns_map->mapname = newstr(mapname); 7186168515Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof(*ns_map->map)); 7187168515Sgshapiro memset(ns_map->map, '\0', sizeof(*ns_map->map)); 718864562Sgshapiro ns_map->next = ns_maps; 718964562Sgshapiro ns_maps = ns_map; 719064562Sgshapiro } 719164562Sgshapiro return ns_map->map; 719264562Sgshapiro} 719364562Sgshapiro 719464562Sgshapirochar * 719564562Sgshapironsd_map_lookup(map, name, av, statp) 719664562Sgshapiro MAP *map; 719764562Sgshapiro char *name; 719864562Sgshapiro char **av; 719964562Sgshapiro int *statp; 720064562Sgshapiro{ 720171345Sgshapiro int buflen, r; 720264562Sgshapiro char *p; 720364562Sgshapiro ns_map_t *ns_map; 720464562Sgshapiro char keybuf[MAXNAME + 1]; 720564562Sgshapiro char buf[MAXLINE]; 720664562Sgshapiro 720764562Sgshapiro if (tTd(38, 20)) 720890792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 720964562Sgshapiro 721064562Sgshapiro buflen = strlen(name); 7211168515Sgshapiro if (buflen > sizeof(keybuf) - 1) 7212168515Sgshapiro buflen = sizeof(keybuf) - 1; /* XXX simply cut off? */ 721364562Sgshapiro memmove(keybuf, name, buflen); 721464562Sgshapiro keybuf[buflen] = '\0'; 721564562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 721664562Sgshapiro makelower(keybuf); 721764562Sgshapiro 721864562Sgshapiro ns_map = ns_map_t_find(map->map_file); 721964562Sgshapiro if (ns_map == NULL) 722064562Sgshapiro { 722164562Sgshapiro if (tTd(38, 20)) 722290792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 722371345Sgshapiro *statp = EX_UNAVAILABLE; 722464562Sgshapiro return NULL; 722564562Sgshapiro } 722698121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 7227168515Sgshapiro buf, sizeof(buf)); 722871345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 722971345Sgshapiro { 723071345Sgshapiro *statp = EX_TEMPFAIL; 723164562Sgshapiro return NULL; 723271345Sgshapiro } 723377349Sgshapiro if (r == NS_BADREQ 723477349Sgshapiro# ifdef NS_NOPERM 723577349Sgshapiro || r == NS_NOPERM 723677349Sgshapiro# endif /* NS_NOPERM */ 723777349Sgshapiro ) 723871345Sgshapiro { 723971345Sgshapiro *statp = EX_CONFIG; 724071345Sgshapiro return NULL; 724171345Sgshapiro } 724271345Sgshapiro if (r != NS_SUCCESS) 724371345Sgshapiro { 724471345Sgshapiro *statp = EX_NOTFOUND; 724571345Sgshapiro return NULL; 724671345Sgshapiro } 724764562Sgshapiro 724871345Sgshapiro *statp = EX_OK; 724971345Sgshapiro 725064562Sgshapiro /* Null out trailing \n */ 725164562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 725264562Sgshapiro *p = '\0'; 725364562Sgshapiro 725464562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 725564562Sgshapiro} 725664562Sgshapiro#endif /* MAP_NSD */ 725764562Sgshapiro 725864562Sgshapirochar * 725964562Sgshapiroarith_map_lookup(map, name, av, statp) 726064562Sgshapiro MAP *map; 726164562Sgshapiro char *name; 726264562Sgshapiro char **av; 726364562Sgshapiro int *statp; 726464562Sgshapiro{ 726564562Sgshapiro long r; 726664562Sgshapiro long v[2]; 726790792Sgshapiro bool res = false; 726864562Sgshapiro bool boolres; 726964562Sgshapiro static char result[16]; 727064562Sgshapiro char **cpp; 727164562Sgshapiro 727264562Sgshapiro if (tTd(38, 2)) 727364562Sgshapiro { 727490792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 727564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 727690792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 727764562Sgshapiro } 727864562Sgshapiro r = 0; 727990792Sgshapiro boolres = false; 728064562Sgshapiro cpp = av; 728164562Sgshapiro *statp = EX_OK; 728264562Sgshapiro 728364562Sgshapiro /* 728464562Sgshapiro ** read arguments for arith map 728564562Sgshapiro ** - no check is made whether they are really numbers 728664562Sgshapiro ** - just ignores args after the second 728764562Sgshapiro */ 728890792Sgshapiro 728964562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 729064562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 729164562Sgshapiro 729264562Sgshapiro /* operator and (at least) two operands given? */ 729364562Sgshapiro if (name != NULL && r == 2) 729464562Sgshapiro { 729590792Sgshapiro switch (*name) 729664562Sgshapiro { 729764562Sgshapiro case '|': 729864562Sgshapiro r = v[0] | v[1]; 729964562Sgshapiro break; 730064562Sgshapiro 730164562Sgshapiro case '&': 730264562Sgshapiro r = v[0] & v[1]; 730364562Sgshapiro break; 730464562Sgshapiro 730564562Sgshapiro case '%': 730664562Sgshapiro if (v[1] == 0) 730764562Sgshapiro return NULL; 730864562Sgshapiro r = v[0] % v[1]; 730964562Sgshapiro break; 731064562Sgshapiro case '+': 731164562Sgshapiro r = v[0] + v[1]; 731264562Sgshapiro break; 731364562Sgshapiro 731464562Sgshapiro case '-': 731564562Sgshapiro r = v[0] - v[1]; 731664562Sgshapiro break; 731764562Sgshapiro 731864562Sgshapiro case '*': 731964562Sgshapiro r = v[0] * v[1]; 732064562Sgshapiro break; 732164562Sgshapiro 732264562Sgshapiro case '/': 732364562Sgshapiro if (v[1] == 0) 732464562Sgshapiro return NULL; 732564562Sgshapiro r = v[0] / v[1]; 732664562Sgshapiro break; 732764562Sgshapiro 732864562Sgshapiro case 'l': 732964562Sgshapiro res = v[0] < v[1]; 733090792Sgshapiro boolres = true; 733164562Sgshapiro break; 733264562Sgshapiro 733364562Sgshapiro case '=': 733464562Sgshapiro res = v[0] == v[1]; 733590792Sgshapiro boolres = true; 733664562Sgshapiro break; 733764562Sgshapiro 7338168515Sgshapiro case 'r': 7339168515Sgshapiro r = v[1] - v[0] + 1; 7340168515Sgshapiro if (r <= 0) 7341168515Sgshapiro return NULL; 7342168515Sgshapiro r = get_random() % r + v[0]; 7343168515Sgshapiro break; 7344168515Sgshapiro 734564562Sgshapiro default: 734664562Sgshapiro /* XXX */ 734764562Sgshapiro *statp = EX_CONFIG; 734864562Sgshapiro if (LogLevel > 10) 734964562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 735064562Sgshapiro "arith_map: unknown operator %c", 7351203004Sgshapiro (isascii(*name) && isprint(*name)) ? 7352203004Sgshapiro *name : '?'); 735364562Sgshapiro return NULL; 735464562Sgshapiro } 735564562Sgshapiro if (boolres) 7356168515Sgshapiro (void) sm_snprintf(result, sizeof(result), 735790792Sgshapiro res ? "TRUE" : "FALSE"); 735864562Sgshapiro else 7359168515Sgshapiro (void) sm_snprintf(result, sizeof(result), "%ld", r); 736064562Sgshapiro return result; 736164562Sgshapiro } 736264562Sgshapiro *statp = EX_CONFIG; 736364562Sgshapiro return NULL; 736464562Sgshapiro} 7365132943Sgshapiro 7366132943Sgshapiro#if SOCKETMAP 7367132943Sgshapiro 7368132943Sgshapiro# if NETINET || NETINET6 7369132943Sgshapiro# include <arpa/inet.h> 7370132943Sgshapiro# endif /* NETINET || NETINET6 */ 7371132943Sgshapiro 7372132943Sgshapiro# define socket_map_next map_stack[0] 7373132943Sgshapiro 7374132943Sgshapiro/* 7375132943Sgshapiro** SOCKET_MAP_OPEN -- open socket table 7376132943Sgshapiro*/ 7377132943Sgshapiro 7378132943Sgshapirobool 7379132943Sgshapirosocket_map_open(map, mode) 7380132943Sgshapiro MAP *map; 7381132943Sgshapiro int mode; 7382132943Sgshapiro{ 7383132943Sgshapiro STAB *s; 7384132943Sgshapiro int sock = 0; 7385132943Sgshapiro SOCKADDR_LEN_T addrlen = 0; 7386132943Sgshapiro int addrno = 0; 7387132943Sgshapiro int save_errno; 7388132943Sgshapiro char *p; 7389132943Sgshapiro char *colon; 7390132943Sgshapiro char *at; 7391132943Sgshapiro struct hostent *hp = NULL; 7392132943Sgshapiro SOCKADDR addr; 7393132943Sgshapiro 7394132943Sgshapiro if (tTd(38, 2)) 7395132943Sgshapiro sm_dprintf("socket_map_open(%s, %s, %d)\n", 7396132943Sgshapiro map->map_mname, map->map_file, mode); 7397132943Sgshapiro 7398132943Sgshapiro mode &= O_ACCMODE; 7399132943Sgshapiro 7400132943Sgshapiro /* sendmail doesn't have the ability to write to SOCKET (yet) */ 7401132943Sgshapiro if (mode != O_RDONLY) 7402132943Sgshapiro { 7403132943Sgshapiro /* issue a pseudo-error message */ 7404132943Sgshapiro errno = SM_EMAPCANTWRITE; 7405132943Sgshapiro return false; 7406132943Sgshapiro } 7407132943Sgshapiro 7408132943Sgshapiro if (*map->map_file == '\0') 7409132943Sgshapiro { 7410132943Sgshapiro syserr("socket map \"%s\": empty or missing socket information", 7411132943Sgshapiro map->map_mname); 7412132943Sgshapiro return false; 7413132943Sgshapiro } 7414132943Sgshapiro 7415132943Sgshapiro s = socket_map_findconn(map->map_file); 7416132943Sgshapiro if (s->s_socketmap != NULL) 7417132943Sgshapiro { 7418132943Sgshapiro /* Copy open connection */ 7419132943Sgshapiro map->map_db1 = s->s_socketmap->map_db1; 7420132943Sgshapiro 7421132943Sgshapiro /* Add this map as head of linked list */ 7422132943Sgshapiro map->socket_map_next = s->s_socketmap; 7423132943Sgshapiro s->s_socketmap = map; 7424132943Sgshapiro 7425132943Sgshapiro if (tTd(38, 2)) 7426132943Sgshapiro sm_dprintf("using cached connection\n"); 7427132943Sgshapiro return true; 7428132943Sgshapiro } 7429132943Sgshapiro 7430132943Sgshapiro if (tTd(38, 2)) 7431132943Sgshapiro sm_dprintf("opening new connection\n"); 7432132943Sgshapiro 7433132943Sgshapiro /* following code is ripped from milter.c */ 7434132943Sgshapiro /* XXX It should be put in a library... */ 7435132943Sgshapiro 7436132943Sgshapiro /* protocol:filename or protocol:port@host */ 7437168515Sgshapiro memset(&addr, '\0', sizeof(addr)); 7438132943Sgshapiro p = map->map_file; 7439132943Sgshapiro colon = strchr(p, ':'); 7440132943Sgshapiro if (colon != NULL) 7441132943Sgshapiro { 7442132943Sgshapiro *colon = '\0'; 7443132943Sgshapiro 7444132943Sgshapiro if (*p == '\0') 7445132943Sgshapiro { 7446132943Sgshapiro# if NETUNIX 7447132943Sgshapiro /* default to AF_UNIX */ 7448132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7449132943Sgshapiro# else /* NETUNIX */ 7450132943Sgshapiro# if NETINET 7451132943Sgshapiro /* default to AF_INET */ 7452132943Sgshapiro addr.sa.sa_family = AF_INET; 7453132943Sgshapiro# else /* NETINET */ 7454132943Sgshapiro# if NETINET6 7455132943Sgshapiro /* default to AF_INET6 */ 7456132943Sgshapiro addr.sa.sa_family = AF_INET6; 7457132943Sgshapiro# else /* NETINET6 */ 7458132943Sgshapiro /* no protocols available */ 7459132943Sgshapiro syserr("socket map \"%s\": no valid socket protocols available", 7460132943Sgshapiro map->map_mname); 7461132943Sgshapiro return false; 7462132943Sgshapiro# endif /* NETINET6 */ 7463132943Sgshapiro# endif /* NETINET */ 7464132943Sgshapiro# endif /* NETUNIX */ 7465132943Sgshapiro } 7466132943Sgshapiro# if NETUNIX 7467132943Sgshapiro else if (sm_strcasecmp(p, "unix") == 0 || 7468132943Sgshapiro sm_strcasecmp(p, "local") == 0) 7469132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7470132943Sgshapiro# endif /* NETUNIX */ 7471132943Sgshapiro# if NETINET 7472132943Sgshapiro else if (sm_strcasecmp(p, "inet") == 0) 7473132943Sgshapiro addr.sa.sa_family = AF_INET; 7474132943Sgshapiro# endif /* NETINET */ 7475132943Sgshapiro# if NETINET6 7476132943Sgshapiro else if (sm_strcasecmp(p, "inet6") == 0) 7477132943Sgshapiro addr.sa.sa_family = AF_INET6; 7478132943Sgshapiro# endif /* NETINET6 */ 7479132943Sgshapiro else 7480132943Sgshapiro { 7481132943Sgshapiro# ifdef EPROTONOSUPPORT 7482132943Sgshapiro errno = EPROTONOSUPPORT; 7483132943Sgshapiro# else /* EPROTONOSUPPORT */ 7484132943Sgshapiro errno = EINVAL; 7485132943Sgshapiro# endif /* EPROTONOSUPPORT */ 7486132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7487132943Sgshapiro map->map_mname, p); 7488132943Sgshapiro return false; 7489132943Sgshapiro } 7490132943Sgshapiro *colon++ = ':'; 7491132943Sgshapiro } 7492132943Sgshapiro else 7493132943Sgshapiro { 7494132943Sgshapiro colon = p; 7495132943Sgshapiro#if NETUNIX 7496132943Sgshapiro /* default to AF_UNIX */ 7497132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7498132943Sgshapiro#else /* NETUNIX */ 7499132943Sgshapiro# if NETINET 7500132943Sgshapiro /* default to AF_INET */ 7501132943Sgshapiro addr.sa.sa_family = AF_INET; 7502132943Sgshapiro# else /* NETINET */ 7503132943Sgshapiro# if NETINET6 7504132943Sgshapiro /* default to AF_INET6 */ 7505132943Sgshapiro addr.sa.sa_family = AF_INET6; 7506132943Sgshapiro# else /* NETINET6 */ 7507132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7508132943Sgshapiro map->map_mname, p); 7509132943Sgshapiro return false; 7510132943Sgshapiro# endif /* NETINET6 */ 7511132943Sgshapiro# endif /* NETINET */ 7512132943Sgshapiro#endif /* NETUNIX */ 7513132943Sgshapiro } 7514132943Sgshapiro 7515132943Sgshapiro# if NETUNIX 7516132943Sgshapiro if (addr.sa.sa_family == AF_UNIX) 7517132943Sgshapiro { 7518132943Sgshapiro long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 7519132943Sgshapiro 7520132943Sgshapiro at = colon; 7521168515Sgshapiro if (strlen(colon) >= sizeof(addr.sunix.sun_path)) 7522132943Sgshapiro { 7523132943Sgshapiro syserr("socket map \"%s\": local socket name %s too long", 7524132943Sgshapiro map->map_mname, colon); 7525132943Sgshapiro return false; 7526132943Sgshapiro } 7527132943Sgshapiro errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 7528132943Sgshapiro S_IRUSR|S_IWUSR, NULL); 7529132943Sgshapiro 7530132943Sgshapiro if (errno != 0) 7531132943Sgshapiro { 7532132943Sgshapiro /* if not safe, don't create */ 7533132943Sgshapiro syserr("socket map \"%s\": local socket name %s unsafe", 7534132943Sgshapiro map->map_mname, colon); 7535132943Sgshapiro return false; 7536132943Sgshapiro } 7537132943Sgshapiro 7538132943Sgshapiro (void) sm_strlcpy(addr.sunix.sun_path, colon, 7539168515Sgshapiro sizeof(addr.sunix.sun_path)); 7540168515Sgshapiro addrlen = sizeof(struct sockaddr_un); 7541132943Sgshapiro } 7542132943Sgshapiro else 7543132943Sgshapiro# endif /* NETUNIX */ 7544132943Sgshapiro# if NETINET || NETINET6 7545132943Sgshapiro if (false 7546132943Sgshapiro# if NETINET 7547132943Sgshapiro || addr.sa.sa_family == AF_INET 7548132943Sgshapiro# endif /* NETINET */ 7549132943Sgshapiro# if NETINET6 7550132943Sgshapiro || addr.sa.sa_family == AF_INET6 7551132943Sgshapiro# endif /* NETINET6 */ 7552132943Sgshapiro ) 7553132943Sgshapiro { 7554132943Sgshapiro unsigned short port; 7555132943Sgshapiro 7556132943Sgshapiro /* Parse port@host */ 7557132943Sgshapiro at = strchr(colon, '@'); 7558132943Sgshapiro if (at == NULL) 7559132943Sgshapiro { 7560132943Sgshapiro syserr("socket map \"%s\": bad address %s (expected port@host)", 7561132943Sgshapiro map->map_mname, colon); 7562132943Sgshapiro return false; 7563132943Sgshapiro } 7564132943Sgshapiro *at = '\0'; 7565132943Sgshapiro if (isascii(*colon) && isdigit(*colon)) 7566132943Sgshapiro port = htons((unsigned short) atoi(colon)); 7567132943Sgshapiro else 7568132943Sgshapiro { 7569132943Sgshapiro# ifdef NO_GETSERVBYNAME 7570132943Sgshapiro syserr("socket map \"%s\": invalid port number %s", 7571132943Sgshapiro map->map_mname, colon); 7572132943Sgshapiro return false; 7573132943Sgshapiro# else /* NO_GETSERVBYNAME */ 7574132943Sgshapiro register struct servent *sp; 7575132943Sgshapiro 7576132943Sgshapiro sp = getservbyname(colon, "tcp"); 7577132943Sgshapiro if (sp == NULL) 7578132943Sgshapiro { 7579132943Sgshapiro syserr("socket map \"%s\": unknown port name %s", 7580132943Sgshapiro map->map_mname, colon); 7581132943Sgshapiro return false; 7582132943Sgshapiro } 7583132943Sgshapiro port = sp->s_port; 7584132943Sgshapiro# endif /* NO_GETSERVBYNAME */ 7585132943Sgshapiro } 7586132943Sgshapiro *at++ = '@'; 7587132943Sgshapiro if (*at == '[') 7588132943Sgshapiro { 7589132943Sgshapiro char *end; 7590132943Sgshapiro 7591132943Sgshapiro end = strchr(at, ']'); 7592132943Sgshapiro if (end != NULL) 7593132943Sgshapiro { 7594132943Sgshapiro bool found = false; 7595132943Sgshapiro# if NETINET 7596132943Sgshapiro unsigned long hid = INADDR_NONE; 7597132943Sgshapiro# endif /* NETINET */ 7598132943Sgshapiro# if NETINET6 7599132943Sgshapiro struct sockaddr_in6 hid6; 7600132943Sgshapiro# endif /* NETINET6 */ 7601132943Sgshapiro 7602132943Sgshapiro *end = '\0'; 7603132943Sgshapiro# if NETINET 7604132943Sgshapiro if (addr.sa.sa_family == AF_INET && 7605132943Sgshapiro (hid = inet_addr(&at[1])) != INADDR_NONE) 7606132943Sgshapiro { 7607132943Sgshapiro addr.sin.sin_addr.s_addr = hid; 7608132943Sgshapiro addr.sin.sin_port = port; 7609132943Sgshapiro found = true; 7610132943Sgshapiro } 7611132943Sgshapiro# endif /* NETINET */ 7612132943Sgshapiro# if NETINET6 7613168515Sgshapiro (void) memset(&hid6, '\0', sizeof(hid6)); 7614132943Sgshapiro if (addr.sa.sa_family == AF_INET6 && 7615132943Sgshapiro anynet_pton(AF_INET6, &at[1], 7616132943Sgshapiro &hid6.sin6_addr) == 1) 7617132943Sgshapiro { 7618132943Sgshapiro addr.sin6.sin6_addr = hid6.sin6_addr; 7619132943Sgshapiro addr.sin6.sin6_port = port; 7620132943Sgshapiro found = true; 7621132943Sgshapiro } 7622132943Sgshapiro# endif /* NETINET6 */ 7623132943Sgshapiro *end = ']'; 7624132943Sgshapiro if (!found) 7625132943Sgshapiro { 7626132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7627132943Sgshapiro map->map_mname, at); 7628132943Sgshapiro return false; 7629132943Sgshapiro } 7630132943Sgshapiro } 7631132943Sgshapiro else 7632132943Sgshapiro { 7633132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7634132943Sgshapiro map->map_mname, at); 7635132943Sgshapiro return false; 7636132943Sgshapiro } 7637132943Sgshapiro } 7638132943Sgshapiro else 7639132943Sgshapiro { 7640132943Sgshapiro hp = sm_gethostbyname(at, addr.sa.sa_family); 7641132943Sgshapiro if (hp == NULL) 7642132943Sgshapiro { 7643132943Sgshapiro syserr("socket map \"%s\": Unknown host name %s", 7644132943Sgshapiro map->map_mname, at); 7645132943Sgshapiro return false; 7646132943Sgshapiro } 7647132943Sgshapiro addr.sa.sa_family = hp->h_addrtype; 7648132943Sgshapiro switch (hp->h_addrtype) 7649132943Sgshapiro { 7650132943Sgshapiro# if NETINET 7651132943Sgshapiro case AF_INET: 7652132943Sgshapiro memmove(&addr.sin.sin_addr, 7653132943Sgshapiro hp->h_addr, INADDRSZ); 7654132943Sgshapiro addr.sin.sin_port = port; 7655168515Sgshapiro addrlen = sizeof(struct sockaddr_in); 7656132943Sgshapiro addrno = 1; 7657132943Sgshapiro break; 7658132943Sgshapiro# endif /* NETINET */ 7659132943Sgshapiro 7660132943Sgshapiro# if NETINET6 7661132943Sgshapiro case AF_INET6: 7662132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7663132943Sgshapiro hp->h_addr, IN6ADDRSZ); 7664132943Sgshapiro addr.sin6.sin6_port = port; 7665168515Sgshapiro addrlen = sizeof(struct sockaddr_in6); 7666132943Sgshapiro addrno = 1; 7667132943Sgshapiro break; 7668132943Sgshapiro# endif /* NETINET6 */ 7669132943Sgshapiro 7670132943Sgshapiro default: 7671132943Sgshapiro syserr("socket map \"%s\": Unknown protocol for %s (%d)", 7672132943Sgshapiro map->map_mname, at, hp->h_addrtype); 7673132943Sgshapiro# if NETINET6 7674132943Sgshapiro freehostent(hp); 7675132943Sgshapiro# endif /* NETINET6 */ 7676132943Sgshapiro return false; 7677132943Sgshapiro } 7678132943Sgshapiro } 7679132943Sgshapiro } 7680132943Sgshapiro else 7681132943Sgshapiro# endif /* NETINET || NETINET6 */ 7682132943Sgshapiro { 7683132943Sgshapiro syserr("socket map \"%s\": unknown socket protocol", 7684132943Sgshapiro map->map_mname); 7685132943Sgshapiro return false; 7686132943Sgshapiro } 7687132943Sgshapiro 7688132943Sgshapiro /* nope, actually connecting */ 7689132943Sgshapiro for (;;) 7690132943Sgshapiro { 7691132943Sgshapiro sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 7692132943Sgshapiro if (sock < 0) 7693132943Sgshapiro { 7694132943Sgshapiro save_errno = errno; 7695132943Sgshapiro if (tTd(38, 5)) 7696132943Sgshapiro sm_dprintf("socket map \"%s\": error creating socket: %s\n", 7697132943Sgshapiro map->map_mname, 7698132943Sgshapiro sm_errstring(save_errno)); 7699132943Sgshapiro# if NETINET6 7700132943Sgshapiro if (hp != NULL) 7701132943Sgshapiro freehostent(hp); 7702132943Sgshapiro# endif /* NETINET6 */ 7703132943Sgshapiro return false; 7704132943Sgshapiro } 7705132943Sgshapiro 7706132943Sgshapiro if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 7707132943Sgshapiro break; 7708132943Sgshapiro 7709132943Sgshapiro /* couldn't connect.... try next address */ 7710132943Sgshapiro save_errno = errno; 7711132943Sgshapiro p = CurHostName; 7712132943Sgshapiro CurHostName = at; 7713132943Sgshapiro if (tTd(38, 5)) 7714132943Sgshapiro sm_dprintf("socket_open (%s): open %s failed: %s\n", 7715132943Sgshapiro map->map_mname, at, sm_errstring(save_errno)); 7716132943Sgshapiro CurHostName = p; 7717132943Sgshapiro (void) close(sock); 7718132943Sgshapiro 7719132943Sgshapiro /* try next address */ 7720132943Sgshapiro if (hp != NULL && hp->h_addr_list[addrno] != NULL) 7721132943Sgshapiro { 7722132943Sgshapiro switch (addr.sa.sa_family) 7723132943Sgshapiro { 7724132943Sgshapiro# if NETINET 7725132943Sgshapiro case AF_INET: 7726132943Sgshapiro memmove(&addr.sin.sin_addr, 7727132943Sgshapiro hp->h_addr_list[addrno++], 7728132943Sgshapiro INADDRSZ); 7729132943Sgshapiro break; 7730132943Sgshapiro# endif /* NETINET */ 7731132943Sgshapiro 7732132943Sgshapiro# if NETINET6 7733132943Sgshapiro case AF_INET6: 7734132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7735132943Sgshapiro hp->h_addr_list[addrno++], 7736132943Sgshapiro IN6ADDRSZ); 7737132943Sgshapiro break; 7738132943Sgshapiro# endif /* NETINET6 */ 7739132943Sgshapiro 7740132943Sgshapiro default: 7741132943Sgshapiro if (tTd(38, 5)) 7742132943Sgshapiro sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 7743132943Sgshapiro map->map_mname, at, 7744132943Sgshapiro hp->h_addrtype); 7745132943Sgshapiro# if NETINET6 7746132943Sgshapiro freehostent(hp); 7747132943Sgshapiro# endif /* NETINET6 */ 7748132943Sgshapiro return false; 7749132943Sgshapiro } 7750132943Sgshapiro continue; 7751132943Sgshapiro } 7752132943Sgshapiro p = CurHostName; 7753132943Sgshapiro CurHostName = at; 7754132943Sgshapiro if (tTd(38, 5)) 7755132943Sgshapiro sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 7756132943Sgshapiro map->map_mname, sm_errstring(save_errno)); 7757132943Sgshapiro CurHostName = p; 7758132943Sgshapiro# if NETINET6 7759132943Sgshapiro if (hp != NULL) 7760132943Sgshapiro freehostent(hp); 7761132943Sgshapiro# endif /* NETINET6 */ 7762132943Sgshapiro return false; 7763132943Sgshapiro } 7764132943Sgshapiro# if NETINET6 7765132943Sgshapiro if (hp != NULL) 7766132943Sgshapiro { 7767132943Sgshapiro freehostent(hp); 7768132943Sgshapiro hp = NULL; 7769132943Sgshapiro } 7770132943Sgshapiro# endif /* NETINET6 */ 7771132943Sgshapiro if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 7772132943Sgshapiro SM_TIME_DEFAULT, 7773132943Sgshapiro (void *) &sock, 7774132943Sgshapiro SM_IO_RDWR, 7775132943Sgshapiro NULL)) == NULL) 7776132943Sgshapiro { 7777132943Sgshapiro close(sock); 7778132943Sgshapiro if (tTd(38, 2)) 7779132943Sgshapiro sm_dprintf("socket_open (%s): failed to create stream: %s\n", 7780132943Sgshapiro map->map_mname, sm_errstring(errno)); 7781132943Sgshapiro return false; 7782132943Sgshapiro } 7783132943Sgshapiro 7784132943Sgshapiro /* Save connection for reuse */ 7785132943Sgshapiro s->s_socketmap = map; 7786132943Sgshapiro return true; 7787132943Sgshapiro} 7788132943Sgshapiro 7789132943Sgshapiro/* 7790132943Sgshapiro** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 7791132943Sgshapiro** 7792132943Sgshapiro** Cache SOCKET connections based on the connection specifier 7793132943Sgshapiro** and PID so we don't have multiple connections open to 7794132943Sgshapiro** the same server for different maps. Need a separate connection 7795132943Sgshapiro** per PID since a parent process may close the map before the 7796132943Sgshapiro** child is done with it. 7797132943Sgshapiro** 7798132943Sgshapiro** Parameters: 7799132943Sgshapiro** conn -- SOCKET map connection specifier 7800132943Sgshapiro** 7801132943Sgshapiro** Returns: 7802132943Sgshapiro** Symbol table entry for the SOCKET connection. 7803132943Sgshapiro*/ 7804132943Sgshapiro 7805132943Sgshapirostatic STAB * 7806132943Sgshapirosocket_map_findconn(conn) 7807132943Sgshapiro const char *conn; 7808132943Sgshapiro{ 7809132943Sgshapiro char *nbuf; 7810132943Sgshapiro STAB *SM_NONVOLATILE s = NULL; 7811132943Sgshapiro 7812132943Sgshapiro nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 7813132943Sgshapiro SM_TRY 7814132943Sgshapiro s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 7815132943Sgshapiro SM_FINALLY 7816132943Sgshapiro sm_free(nbuf); 7817132943Sgshapiro SM_END_TRY 7818132943Sgshapiro return s; 7819132943Sgshapiro} 7820132943Sgshapiro 7821132943Sgshapiro/* 7822132943Sgshapiro** SOCKET_MAP_CLOSE -- close the socket 7823132943Sgshapiro*/ 7824132943Sgshapiro 7825132943Sgshapirovoid 7826132943Sgshapirosocket_map_close(map) 7827132943Sgshapiro MAP *map; 7828132943Sgshapiro{ 7829132943Sgshapiro STAB *s; 7830132943Sgshapiro MAP *smap; 7831132943Sgshapiro 7832132943Sgshapiro if (tTd(38, 20)) 7833132943Sgshapiro sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 7834132943Sgshapiro (long) CurrentPid); 7835132943Sgshapiro 7836132943Sgshapiro /* Check if already closed */ 7837132943Sgshapiro if (map->map_db1 == NULL) 7838132943Sgshapiro { 7839132943Sgshapiro if (tTd(38, 20)) 7840132943Sgshapiro sm_dprintf("socket_map_close(%s) already closed\n", 7841132943Sgshapiro map->map_file); 7842132943Sgshapiro return; 7843132943Sgshapiro } 7844132943Sgshapiro sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 7845132943Sgshapiro 7846132943Sgshapiro /* Mark all the maps that share the connection as closed */ 7847132943Sgshapiro s = socket_map_findconn(map->map_file); 7848132943Sgshapiro smap = s->s_socketmap; 7849132943Sgshapiro while (smap != NULL) 7850132943Sgshapiro { 7851132943Sgshapiro MAP *next; 7852132943Sgshapiro 7853132943Sgshapiro if (tTd(38, 2) && smap != map) 7854132943Sgshapiro sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 7855132943Sgshapiro map->map_mname, smap->map_mname); 7856132943Sgshapiro 7857132943Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 7858132943Sgshapiro smap->map_db1 = NULL; 7859132943Sgshapiro next = smap->socket_map_next; 7860132943Sgshapiro smap->socket_map_next = NULL; 7861132943Sgshapiro smap = next; 7862132943Sgshapiro } 7863132943Sgshapiro s->s_socketmap = NULL; 7864132943Sgshapiro} 7865132943Sgshapiro 7866132943Sgshapiro/* 7867132943Sgshapiro** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 7868132943Sgshapiro*/ 7869132943Sgshapiro 7870132943Sgshapirochar * 7871132943Sgshapirosocket_map_lookup(map, name, av, statp) 7872132943Sgshapiro MAP *map; 7873132943Sgshapiro char *name; 7874132943Sgshapiro char **av; 7875132943Sgshapiro int *statp; 7876132943Sgshapiro{ 7877132943Sgshapiro unsigned int nettolen, replylen, recvlen; 7878147078Sgshapiro char *replybuf, *rval, *value, *status, *key; 7879132943Sgshapiro SM_FILE_T *f; 7880147078Sgshapiro char keybuf[MAXNAME + 1]; 7881132943Sgshapiro 7882132943Sgshapiro replybuf = NULL; 7883132943Sgshapiro rval = NULL; 7884132943Sgshapiro f = (SM_FILE_T *)map->map_db1; 7885132943Sgshapiro if (tTd(38, 20)) 7886132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s) %s\n", 7887132943Sgshapiro map->map_mname, name, map->map_file); 7888132943Sgshapiro 7889147078Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 7890147078Sgshapiro { 7891147078Sgshapiro nettolen = strlen(name); 7892168515Sgshapiro if (nettolen > sizeof(keybuf) - 1) 7893168515Sgshapiro nettolen = sizeof(keybuf) - 1; 7894147078Sgshapiro memmove(keybuf, name, nettolen); 7895147078Sgshapiro keybuf[nettolen] = '\0'; 7896147078Sgshapiro makelower(keybuf); 7897147078Sgshapiro key = keybuf; 7898147078Sgshapiro } 7899147078Sgshapiro else 7900147078Sgshapiro key = name; 7901147078Sgshapiro 7902147078Sgshapiro nettolen = strlen(map->map_mname) + 1 + strlen(key); 7903132943Sgshapiro SM_ASSERT(nettolen > strlen(map->map_mname)); 7904147078Sgshapiro SM_ASSERT(nettolen > strlen(key)); 7905132943Sgshapiro if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 7906147078Sgshapiro nettolen, map->map_mname, key) == SM_IO_EOF) || 7907132943Sgshapiro (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 7908132943Sgshapiro (sm_io_error(f))) 7909132943Sgshapiro { 7910132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 7911132943Sgshapiro map->map_mname); 7912132943Sgshapiro *statp = EX_TEMPFAIL; 7913132943Sgshapiro goto errcl; 7914132943Sgshapiro } 7915132943Sgshapiro 7916132943Sgshapiro if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) 7917132943Sgshapiro { 7918132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", 7919132943Sgshapiro map->map_mname); 7920132943Sgshapiro *statp = EX_TEMPFAIL; 7921132943Sgshapiro goto errcl; 7922132943Sgshapiro } 7923132943Sgshapiro if (replylen > SOCKETMAP_MAXL) 7924132943Sgshapiro { 7925132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 7926132943Sgshapiro map->map_mname, replylen); 7927132943Sgshapiro *statp = EX_TEMPFAIL; 7928132943Sgshapiro goto errcl; 7929132943Sgshapiro } 7930132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 7931132943Sgshapiro { 7932132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 7933132943Sgshapiro map->map_mname); 7934132943Sgshapiro *statp = EX_TEMPFAIL; 7935132943Sgshapiro goto error; 7936132943Sgshapiro } 7937132943Sgshapiro 7938132943Sgshapiro replybuf = (char *) sm_malloc(replylen + 1); 7939132943Sgshapiro if (replybuf == NULL) 7940132943Sgshapiro { 7941132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 7942132943Sgshapiro map->map_mname, replylen + 1); 7943132943Sgshapiro *statp = EX_OSERR; 7944132943Sgshapiro goto error; 7945132943Sgshapiro } 7946132943Sgshapiro 7947132943Sgshapiro recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 7948132943Sgshapiro if (recvlen < replylen) 7949132943Sgshapiro { 7950132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 7951132943Sgshapiro map->map_mname, recvlen, replylen); 7952132943Sgshapiro *statp = EX_TEMPFAIL; 7953132943Sgshapiro goto errcl; 7954132943Sgshapiro } 7955132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 7956132943Sgshapiro { 7957132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 7958132943Sgshapiro map->map_mname); 7959132943Sgshapiro *statp = EX_TEMPFAIL; 7960132943Sgshapiro goto errcl; 7961132943Sgshapiro } 7962132943Sgshapiro status = replybuf; 7963132943Sgshapiro replybuf[recvlen] = '\0'; 7964132943Sgshapiro value = strchr(replybuf, ' '); 7965132943Sgshapiro if (value != NULL) 7966132943Sgshapiro { 7967132943Sgshapiro *value = '\0'; 7968132943Sgshapiro value++; 7969132943Sgshapiro } 7970132943Sgshapiro if (strcmp(status, "OK") == 0) 7971132943Sgshapiro { 7972132943Sgshapiro *statp = EX_OK; 7973132943Sgshapiro 7974132943Sgshapiro /* collect the return value */ 7975132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 7976147078Sgshapiro rval = map_rewrite(map, key, strlen(key), NULL); 7977132943Sgshapiro else 7978132943Sgshapiro rval = map_rewrite(map, value, strlen(value), av); 7979132943Sgshapiro } 7980132943Sgshapiro else if (strcmp(status, "NOTFOUND") == 0) 7981132943Sgshapiro { 7982132943Sgshapiro *statp = EX_NOTFOUND; 7983132943Sgshapiro if (tTd(38, 20)) 7984132943Sgshapiro sm_dprintf("socket_map_lookup(%s): %s not found\n", 7985147078Sgshapiro map->map_mname, key); 7986132943Sgshapiro } 7987132943Sgshapiro else 7988132943Sgshapiro { 7989132943Sgshapiro if (tTd(38, 5)) 7990132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 7991147078Sgshapiro map->map_mname, key, status, 7992132943Sgshapiro value ? value : ""); 7993132943Sgshapiro if ((strcmp(status, "TEMP") == 0) || 7994132943Sgshapiro (strcmp(status, "TIMEOUT") == 0)) 7995132943Sgshapiro *statp = EX_TEMPFAIL; 7996132943Sgshapiro else if(strcmp(status, "PERM") == 0) 7997132943Sgshapiro *statp = EX_UNAVAILABLE; 7998132943Sgshapiro else 7999132943Sgshapiro *statp = EX_PROTOCOL; 8000132943Sgshapiro } 8001132943Sgshapiro 8002132943Sgshapiro if (replybuf != NULL) 8003132943Sgshapiro sm_free(replybuf); 8004132943Sgshapiro return rval; 8005132943Sgshapiro 8006132943Sgshapiro errcl: 8007132943Sgshapiro socket_map_close(map); 8008132943Sgshapiro error: 8009132943Sgshapiro if (replybuf != NULL) 8010132943Sgshapiro sm_free(replybuf); 8011132943Sgshapiro return rval; 8012132943Sgshapiro} 8013132943Sgshapiro#endif /* SOCKETMAP */ 8014