map.c revision 132943
138032Speter/* 2120256Sgshapiro * Copyright (c) 1998-2003 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 16132943SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.664 2004/06/28 17:46:13 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 4290792Sgshapiro#if NEWDB 4364562Sgshapiro# if DB_VERSION_MAJOR < 2 4464562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); 4564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 4664562Sgshapiro# if DB_VERSION_MAJOR == 2 4764562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); 4864562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 4964562Sgshapiro# if DB_VERSION_MAJOR > 2 5064562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, void **)); 5164562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 5264562Sgshapiro#endif /* NEWDB */ 5373188Sgshapirostatic bool extract_canonname __P((char *, char *, char *, char[], int)); 5490792Sgshapirostatic void map_close __P((STAB *, int)); 5590792Sgshapirostatic void map_init __P((STAB *, int)); 5664562Sgshapiro#ifdef LDAPMAP 5790792Sgshapirostatic STAB * ldapmap_findconn __P((SM_LDAP_STRUCT *)); 5864562Sgshapiro#endif /* LDAPMAP */ 5990792Sgshapiro#if NISPLUS 6064562Sgshapirostatic bool nisplus_getcanonname __P((char *, int, int *)); 6164562Sgshapiro#endif /* NISPLUS */ 6290792Sgshapiro#if NIS 6364562Sgshapirostatic bool nis_getcanonname __P((char *, int, int *)); 6464562Sgshapiro#endif /* NIS */ 6564562Sgshapiro#if NETINFO 6664562Sgshapirostatic bool ni_getcanonname __P((char *, int, int *)); 6764562Sgshapiro#endif /* NETINFO */ 6864562Sgshapirostatic bool text_getcanonname __P((char *, int, int *)); 69132943Sgshapiro#if SOCKETMAP 70132943Sgshapirostatic STAB *socket_map_findconn __P((const char*)); 7164562Sgshapiro 72132943Sgshapiro/* XXX arbitrary limit for sanity */ 73132943Sgshapiro# define SOCKETMAP_MAXL 1000000 74132943Sgshapiro#endif /* SOCKETMAP */ 75132943Sgshapiro 7690792Sgshapiro/* default error message for trying to open a map in write mode */ 7790792Sgshapiro#ifdef ENOSYS 7890792Sgshapiro# define SM_EMAPCANTWRITE ENOSYS 7990792Sgshapiro#else /* ENOSYS */ 8090792Sgshapiro# ifdef EFTYPE 8190792Sgshapiro# define SM_EMAPCANTWRITE EFTYPE 8290792Sgshapiro# else /* EFTYPE */ 8390792Sgshapiro# define SM_EMAPCANTWRITE ENXIO 8490792Sgshapiro# endif /* EFTYPE */ 8590792Sgshapiro#endif /* ENOSYS */ 8690792Sgshapiro 8738032Speter/* 8838032Speter** MAP.C -- implementations for various map classes. 8938032Speter** 9038032Speter** Each map class implements a series of functions: 9138032Speter** 9238032Speter** bool map_parse(MAP *map, char *args) 9390792Sgshapiro** Parse the arguments from the config file. Return true 9490792Sgshapiro** if they were ok, false otherwise. Fill in map with the 9538032Speter** values. 9638032Speter** 9738032Speter** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 9838032Speter** Look up the key in the given map. If found, do any 9938032Speter** rewriting the map wants (including "args" if desired) 10038032Speter** and return the value. Set *pstat to the appropriate status 10138032Speter** on error and return NULL. Args will be NULL if called 10238032Speter** from the alias routines, although this should probably 10338032Speter** not be relied upon. It is suggested you call map_rewrite 10438032Speter** to return the results -- it takes care of null termination 10538032Speter** and uses a dynamically expanded buffer as needed. 10638032Speter** 10738032Speter** void map_store(MAP *map, char *key, char *value) 10838032Speter** Store the key:value pair in the map. 10938032Speter** 11038032Speter** bool map_open(MAP *map, int mode) 11138032Speter** Open the map for the indicated mode. Mode should 11290792Sgshapiro** be either O_RDONLY or O_RDWR. Return true if it 11390792Sgshapiro** was opened successfully, false otherwise. If the open 11490792Sgshapiro** failed and the MF_OPTIONAL flag is not set, it should 11538032Speter** also print an error. If the MF_ALIAS bit is set 11638032Speter** and this map class understands the @:@ convention, it 11738032Speter** should call aliaswait() before returning. 11838032Speter** 11938032Speter** void map_close(MAP *map) 12038032Speter** Close the map. 12138032Speter** 12238032Speter** This file also includes the implementation for getcanonname. 12338032Speter** It is currently implemented in a pretty ad-hoc manner; it ought 12438032Speter** to be more properly integrated into the map structure. 12538032Speter*/ 12638032Speter 12738032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 12838032Speter# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 12964562Sgshapiro#else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 13038032Speter# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 13164562Sgshapiro#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 13238032Speter 13390792Sgshapiro/* 13438032Speter** MAP_PARSEARGS -- parse config line arguments for database lookup 13538032Speter** 13638032Speter** This is a generic version of the map_parse method. 13738032Speter** 13838032Speter** Parameters: 13938032Speter** map -- the map being initialized. 14038032Speter** ap -- a pointer to the args on the config line. 14138032Speter** 14238032Speter** Returns: 14390792Sgshapiro** true -- if everything parsed OK. 14490792Sgshapiro** false -- otherwise. 14538032Speter** 14638032Speter** Side Effects: 14738032Speter** null terminates the filename; stores it in map 14838032Speter*/ 14938032Speter 15038032Speterbool 15138032Spetermap_parseargs(map, ap) 15238032Speter MAP *map; 15338032Speter char *ap; 15438032Speter{ 15538032Speter register char *p = ap; 15638032Speter 15764562Sgshapiro /* 15890792Sgshapiro ** There is no check whether there is really an argument, 15990792Sgshapiro ** but that's not important enough to warrant extra code. 16064562Sgshapiro */ 16190792Sgshapiro 16290792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 16364562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 16438032Speter for (;;) 16538032Speter { 16638032Speter while (isascii(*p) && isspace(*p)) 16738032Speter p++; 16838032Speter if (*p != '-') 16938032Speter break; 17038032Speter switch (*++p) 17138032Speter { 17238032Speter case 'N': 17338032Speter map->map_mflags |= MF_INCLNULL; 17438032Speter map->map_mflags &= ~MF_TRY0NULL; 17538032Speter break; 17638032Speter 17738032Speter case 'O': 17838032Speter map->map_mflags &= ~MF_TRY1NULL; 17938032Speter break; 18038032Speter 18138032Speter case 'o': 18238032Speter map->map_mflags |= MF_OPTIONAL; 18338032Speter break; 18438032Speter 18538032Speter case 'f': 18638032Speter map->map_mflags |= MF_NOFOLDCASE; 18738032Speter break; 18838032Speter 18938032Speter case 'm': 19038032Speter map->map_mflags |= MF_MATCHONLY; 19138032Speter break; 19238032Speter 19338032Speter case 'A': 19438032Speter map->map_mflags |= MF_APPEND; 19538032Speter break; 19638032Speter 19738032Speter case 'q': 19838032Speter map->map_mflags |= MF_KEEPQUOTES; 19938032Speter break; 20038032Speter 20138032Speter case 'a': 20238032Speter map->map_app = ++p; 20338032Speter break; 20438032Speter 20538032Speter case 'T': 20638032Speter map->map_tapp = ++p; 20738032Speter break; 20838032Speter 20938032Speter case 'k': 21038032Speter while (isascii(*++p) && isspace(*p)) 21138032Speter continue; 21238032Speter map->map_keycolnm = p; 21338032Speter break; 21438032Speter 21538032Speter case 'v': 21638032Speter while (isascii(*++p) && isspace(*p)) 21738032Speter continue; 21838032Speter map->map_valcolnm = p; 21938032Speter break; 22038032Speter 22138032Speter case 'z': 22238032Speter if (*++p != '\\') 22338032Speter map->map_coldelim = *p; 22438032Speter else 22538032Speter { 22638032Speter switch (*++p) 22738032Speter { 22838032Speter case 'n': 22938032Speter map->map_coldelim = '\n'; 23038032Speter break; 23138032Speter 23238032Speter case 't': 23338032Speter map->map_coldelim = '\t'; 23438032Speter break; 23538032Speter 23638032Speter default: 23738032Speter map->map_coldelim = '\\'; 23838032Speter } 23938032Speter } 24038032Speter break; 24138032Speter 24238032Speter case 't': 24338032Speter map->map_mflags |= MF_NODEFER; 24438032Speter break; 24538032Speter 24664562Sgshapiro 24764562Sgshapiro case 'S': 24864562Sgshapiro map->map_spacesub = *++p; 24938032Speter break; 25038032Speter 25164562Sgshapiro case 'D': 25264562Sgshapiro map->map_mflags |= MF_DEFER; 25338032Speter break; 25464562Sgshapiro 25564562Sgshapiro default: 25664562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 25764562Sgshapiro break; 25838032Speter } 25938032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 26038032Speter p++; 26138032Speter if (*p != '\0') 26238032Speter *p++ = '\0'; 26338032Speter } 26438032Speter if (map->map_app != NULL) 26538032Speter map->map_app = newstr(map->map_app); 26638032Speter if (map->map_tapp != NULL) 26738032Speter map->map_tapp = newstr(map->map_tapp); 26838032Speter if (map->map_keycolnm != NULL) 26938032Speter map->map_keycolnm = newstr(map->map_keycolnm); 27038032Speter if (map->map_valcolnm != NULL) 27138032Speter map->map_valcolnm = newstr(map->map_valcolnm); 27238032Speter 27338032Speter if (*p != '\0') 27438032Speter { 27538032Speter map->map_file = p; 27638032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 27738032Speter p++; 27838032Speter if (*p != '\0') 27938032Speter *p++ = '\0'; 28038032Speter map->map_file = newstr(map->map_file); 28138032Speter } 28238032Speter 28338032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 28438032Speter p++; 28538032Speter if (*p != '\0') 28638032Speter map->map_rebuild = newstr(p); 28738032Speter 28838032Speter if (map->map_file == NULL && 28938032Speter !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 29038032Speter { 29138032Speter syserr("No file name for %s map %s", 29238032Speter map->map_class->map_cname, map->map_mname); 29390792Sgshapiro return false; 29438032Speter } 29590792Sgshapiro return true; 29638032Speter} 29790792Sgshapiro/* 29838032Speter** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 29938032Speter** 30038032Speter** It also adds the map_app string. It can be used as a utility 30138032Speter** in the map_lookup method. 30238032Speter** 30338032Speter** Parameters: 30438032Speter** map -- the map that causes this. 30538032Speter** s -- the string to rewrite, NOT necessarily null terminated. 30638032Speter** slen -- the length of s. 30738032Speter** av -- arguments to interpolate into buf. 30838032Speter** 30938032Speter** Returns: 31038032Speter** Pointer to rewritten result. This is static data that 31138032Speter** should be copied if it is to be saved! 31238032Speter*/ 31338032Speter 31438032Speterchar * 31538032Spetermap_rewrite(map, s, slen, av) 31638032Speter register MAP *map; 31738032Speter register const char *s; 31838032Speter size_t slen; 31938032Speter char **av; 32038032Speter{ 32138032Speter register char *bp; 32238032Speter register char c; 32338032Speter char **avp; 32438032Speter register char *ap; 32538032Speter size_t l; 32638032Speter size_t len; 32738032Speter static size_t buflen = 0; 32838032Speter static char *buf = NULL; 32938032Speter 33038032Speter if (tTd(39, 1)) 33138032Speter { 33290792Sgshapiro sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s); 33338032Speter if (av == NULL) 33490792Sgshapiro sm_dprintf(" (nullv)"); 33538032Speter else 33638032Speter { 33738032Speter for (avp = av; *avp != NULL; avp++) 33890792Sgshapiro sm_dprintf("\n\t%s", *avp); 33938032Speter } 34090792Sgshapiro sm_dprintf("\n"); 34138032Speter } 34238032Speter 34338032Speter /* count expected size of output (can safely overestimate) */ 34438032Speter l = len = slen; 34538032Speter if (av != NULL) 34638032Speter { 34738032Speter const char *sp = s; 34838032Speter 34938032Speter while (l-- > 0 && (c = *sp++) != '\0') 35038032Speter { 35138032Speter if (c != '%') 35238032Speter continue; 35338032Speter if (l-- <= 0) 35438032Speter break; 35538032Speter c = *sp++; 35638032Speter if (!(isascii(c) && isdigit(c))) 35738032Speter continue; 35838032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 35938032Speter continue; 36038032Speter if (*avp == NULL) 36138032Speter continue; 36238032Speter len += strlen(*avp); 36338032Speter } 36438032Speter } 36538032Speter if (map->map_app != NULL) 36638032Speter len += strlen(map->map_app); 36738032Speter if (buflen < ++len) 36838032Speter { 36938032Speter /* need to malloc additional space */ 37038032Speter buflen = len; 37138032Speter if (buf != NULL) 37277349Sgshapiro sm_free(buf); 37390792Sgshapiro buf = sm_pmalloc_x(buflen); 37438032Speter } 37538032Speter 37638032Speter bp = buf; 37738032Speter if (av == NULL) 37838032Speter { 37964562Sgshapiro memmove(bp, s, slen); 38038032Speter bp += slen; 38164562Sgshapiro 38264562Sgshapiro /* assert(len > slen); */ 38364562Sgshapiro len -= slen; 38438032Speter } 38538032Speter else 38638032Speter { 38738032Speter while (slen-- > 0 && (c = *s++) != '\0') 38838032Speter { 38938032Speter if (c != '%') 39038032Speter { 39138032Speter pushc: 392120256Sgshapiro if (len-- <= 1) 39390792Sgshapiro break; 39438032Speter *bp++ = c; 39538032Speter continue; 39638032Speter } 39738032Speter if (slen-- <= 0 || (c = *s++) == '\0') 39838032Speter c = '%'; 39938032Speter if (c == '%') 40038032Speter goto pushc; 40138032Speter if (!(isascii(c) && isdigit(c))) 40238032Speter { 403120256Sgshapiro if (len-- <= 1) 404120256Sgshapiro break; 40538032Speter *bp++ = '%'; 40638032Speter goto pushc; 40738032Speter } 40838032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 40938032Speter continue; 41038032Speter if (*avp == NULL) 41138032Speter continue; 41238032Speter 41338032Speter /* transliterate argument into output string */ 41464562Sgshapiro for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len) 41538032Speter *bp++ = c; 41638032Speter } 41738032Speter } 41864562Sgshapiro if (map->map_app != NULL && len > 0) 41990792Sgshapiro (void) sm_strlcpy(bp, map->map_app, len); 42038032Speter else 42138032Speter *bp = '\0'; 42238032Speter if (tTd(39, 1)) 42390792Sgshapiro sm_dprintf("map_rewrite => %s\n", buf); 42438032Speter return buf; 42538032Speter} 42690792Sgshapiro/* 42764562Sgshapiro** INITMAPS -- rebuild alias maps 42838032Speter** 42938032Speter** Parameters: 43064562Sgshapiro** none. 43138032Speter** 43238032Speter** Returns: 43338032Speter** none. 43438032Speter*/ 43538032Speter 43638032Spetervoid 43764562Sgshapiroinitmaps() 43838032Speter{ 43938032Speter#if XDEBUG 44038032Speter checkfd012("entering initmaps"); 44164562Sgshapiro#endif /* XDEBUG */ 44238032Speter stabapply(map_init, 0); 44338032Speter#if XDEBUG 44438032Speter checkfd012("exiting initmaps"); 44564562Sgshapiro#endif /* XDEBUG */ 44638032Speter} 44790792Sgshapiro/* 44864562Sgshapiro** MAP_INIT -- rebuild a map 44964562Sgshapiro** 45064562Sgshapiro** Parameters: 45164562Sgshapiro** s -- STAB entry: if map: try to rebuild 45264562Sgshapiro** unused -- unused variable 45364562Sgshapiro** 45464562Sgshapiro** Returns: 45564562Sgshapiro** none. 45664562Sgshapiro** 45764562Sgshapiro** Side Effects: 45864562Sgshapiro** will close already open rebuildable map. 45964562Sgshapiro*/ 46038032Speter 46164562Sgshapiro/* ARGSUSED1 */ 46264562Sgshapirostatic void 46364562Sgshapiromap_init(s, unused) 46438032Speter register STAB *s; 46564562Sgshapiro int unused; 46638032Speter{ 46738032Speter register MAP *map; 46838032Speter 46938032Speter /* has to be a map */ 47090792Sgshapiro if (s->s_symtype != ST_MAP) 47138032Speter return; 47238032Speter 47338032Speter map = &s->s_map; 47438032Speter if (!bitset(MF_VALID, map->map_mflags)) 47538032Speter return; 47638032Speter 47738032Speter if (tTd(38, 2)) 47890792Sgshapiro sm_dprintf("map_init(%s:%s, %s)\n", 47938032Speter map->map_class->map_cname == NULL ? "NULL" : 48038032Speter map->map_class->map_cname, 48138032Speter map->map_mname == NULL ? "NULL" : map->map_mname, 48264562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 48338032Speter 48464562Sgshapiro if (!bitset(MF_ALIAS, map->map_mflags) || 48564562Sgshapiro !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 48638032Speter { 48738032Speter if (tTd(38, 3)) 48890792Sgshapiro sm_dprintf("\tnot rebuildable\n"); 48938032Speter return; 49038032Speter } 49138032Speter 49238032Speter /* if already open, close it (for nested open) */ 49338032Speter if (bitset(MF_OPEN, map->map_mflags)) 49438032Speter { 49577349Sgshapiro map->map_mflags |= MF_CLOSING; 49638032Speter map->map_class->map_close(map); 49777349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 49838032Speter } 49938032Speter 50090792Sgshapiro (void) rebuildaliases(map, false); 50164562Sgshapiro return; 50264562Sgshapiro} 50390792Sgshapiro/* 50464562Sgshapiro** OPENMAP -- open a map 50564562Sgshapiro** 50664562Sgshapiro** Parameters: 50764562Sgshapiro** map -- map to open (it must not be open). 50864562Sgshapiro** 50964562Sgshapiro** Returns: 51064562Sgshapiro** whether open succeeded. 51164562Sgshapiro*/ 51264562Sgshapiro 51364562Sgshapirobool 51464562Sgshapiroopenmap(map) 51564562Sgshapiro MAP *map; 51664562Sgshapiro{ 51790792Sgshapiro bool restore = false; 51864562Sgshapiro bool savehold = HoldErrs; 51964562Sgshapiro bool savequick = QuickAbort; 52064562Sgshapiro int saveerrors = Errors; 52164562Sgshapiro 52264562Sgshapiro if (!bitset(MF_VALID, map->map_mflags)) 52390792Sgshapiro return false; 52464562Sgshapiro 52564562Sgshapiro /* better safe than sorry... */ 52664562Sgshapiro if (bitset(MF_OPEN, map->map_mflags)) 52790792Sgshapiro return true; 52864562Sgshapiro 52964562Sgshapiro /* Don't send a map open error out via SMTP */ 53064562Sgshapiro if ((OnlyOneError || QuickAbort) && 53164562Sgshapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 53238032Speter { 53390792Sgshapiro restore = true; 53490792Sgshapiro HoldErrs = true; 53590792Sgshapiro QuickAbort = false; 53638032Speter } 53738032Speter 53864562Sgshapiro errno = 0; 53938032Speter if (map->map_class->map_open(map, O_RDONLY)) 54038032Speter { 54138032Speter if (tTd(38, 4)) 54290792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: valid\n", 54338032Speter map->map_class->map_cname == NULL ? "NULL" : 54438032Speter map->map_class->map_cname, 54538032Speter map->map_mname == NULL ? "NULL" : 54638032Speter map->map_mname, 54738032Speter map->map_file == NULL ? "NULL" : 54838032Speter map->map_file); 54938032Speter map->map_mflags |= MF_OPEN; 55090792Sgshapiro map->map_pid = CurrentPid; 55138032Speter } 55238032Speter else 55338032Speter { 55438032Speter if (tTd(38, 4)) 55590792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n", 55638032Speter map->map_class->map_cname == NULL ? "NULL" : 55738032Speter map->map_class->map_cname, 55838032Speter map->map_mname == NULL ? "NULL" : 55938032Speter map->map_mname, 56038032Speter map->map_file == NULL ? "NULL" : 56138032Speter map->map_file, 56264562Sgshapiro errno == 0 ? "" : ": ", 56390792Sgshapiro errno == 0 ? "" : sm_errstring(errno)); 56438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 56538032Speter { 56638032Speter extern MAPCLASS BogusMapClass; 56738032Speter 56890792Sgshapiro map->map_orgclass = map->map_class; 56938032Speter map->map_class = &BogusMapClass; 57090792Sgshapiro map->map_mflags |= MF_OPEN|MF_OPENBOGUS; 57190792Sgshapiro map->map_pid = CurrentPid; 57238032Speter } 57364562Sgshapiro else 57464562Sgshapiro { 57564562Sgshapiro /* don't try again */ 57664562Sgshapiro map->map_mflags &= ~MF_VALID; 57764562Sgshapiro } 57838032Speter } 57964562Sgshapiro 58064562Sgshapiro if (restore) 58164562Sgshapiro { 58264562Sgshapiro Errors = saveerrors; 58364562Sgshapiro HoldErrs = savehold; 58464562Sgshapiro QuickAbort = savequick; 58564562Sgshapiro } 58664562Sgshapiro 58764562Sgshapiro return bitset(MF_OPEN, map->map_mflags); 58838032Speter} 58990792Sgshapiro/* 59042575Speter** CLOSEMAPS -- close all open maps opened by the current pid. 59142575Speter** 59242575Speter** Parameters: 59390792Sgshapiro** bogus -- only close bogus maps. 59442575Speter** 59542575Speter** Returns: 59642575Speter** none. 59742575Speter*/ 59842575Speter 59942575Spetervoid 60090792Sgshapiroclosemaps(bogus) 60190792Sgshapiro bool bogus; 60242575Speter{ 60390792Sgshapiro stabapply(map_close, bogus); 60442575Speter} 60590792Sgshapiro/* 60664562Sgshapiro** MAP_CLOSE -- close a map opened by the current pid. 60764562Sgshapiro** 60864562Sgshapiro** Parameters: 60990792Sgshapiro** s -- STAB entry: if map: try to close 61090792Sgshapiro** bogus -- only close bogus maps or MCF_NOTPERSIST maps. 61164562Sgshapiro** 61264562Sgshapiro** Returns: 61364562Sgshapiro** none. 61464562Sgshapiro*/ 61542575Speter 61642575Speter/* ARGSUSED1 */ 61764562Sgshapirostatic void 61890792Sgshapiromap_close(s, bogus) 61942575Speter register STAB *s; 62090792Sgshapiro int bogus; /* int because of stabapply(), used as bool */ 62142575Speter{ 62242575Speter MAP *map; 62390792Sgshapiro extern MAPCLASS BogusMapClass; 62442575Speter 62590792Sgshapiro if (s->s_symtype != ST_MAP) 62642575Speter return; 62764562Sgshapiro 62842575Speter map = &s->s_map; 62942575Speter 63090792Sgshapiro /* 63190792Sgshapiro ** close the map iff: 63290792Sgshapiro ** it is valid and open and opened by this process 63390792Sgshapiro ** and (!bogus or it's a bogus map or it is not persistent) 63490792Sgshapiro ** negate this: return iff 63590792Sgshapiro ** it is not valid or it is not open or not opened by this process 63690792Sgshapiro ** or (bogus and it's not a bogus map and it's not not-persistent) 63790792Sgshapiro */ 63890792Sgshapiro 63942575Speter if (!bitset(MF_VALID, map->map_mflags) || 64042575Speter !bitset(MF_OPEN, map->map_mflags) || 64177349Sgshapiro bitset(MF_CLOSING, map->map_mflags) || 64290792Sgshapiro map->map_pid != CurrentPid || 64390792Sgshapiro (bogus && map->map_class != &BogusMapClass && 64490792Sgshapiro !bitset(MCF_NOTPERSIST, map->map_class->map_cflags))) 64542575Speter return; 64664562Sgshapiro 64790792Sgshapiro if (map->map_class == &BogusMapClass && map->map_orgclass != NULL && 64890792Sgshapiro map->map_orgclass != &BogusMapClass) 64990792Sgshapiro map->map_class = map->map_orgclass; 65042575Speter if (tTd(38, 5)) 65190792Sgshapiro sm_dprintf("closemaps: closing %s (%s)\n", 65264562Sgshapiro map->map_mname == NULL ? "NULL" : map->map_mname, 65364562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 65464562Sgshapiro 65590792Sgshapiro if (!bitset(MF_OPENBOGUS, map->map_mflags)) 65690792Sgshapiro { 65790792Sgshapiro map->map_mflags |= MF_CLOSING; 65890792Sgshapiro map->map_class->map_close(map); 65990792Sgshapiro } 66090792Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING); 66142575Speter} 66290792Sgshapiro/* 66338032Speter** GETCANONNAME -- look up name using service switch 66438032Speter** 66538032Speter** Parameters: 66638032Speter** host -- the host name to look up. 66738032Speter** hbsize -- the size of the host buffer. 66838032Speter** trymx -- if set, try MX records. 66990792Sgshapiro** pttl -- pointer to return TTL (can be NULL). 67038032Speter** 67138032Speter** Returns: 67290792Sgshapiro** true -- if the host was found. 67390792Sgshapiro** false -- otherwise. 67438032Speter*/ 67538032Speter 67638032Speterbool 67790792Sgshapirogetcanonname(host, hbsize, trymx, pttl) 67838032Speter char *host; 67938032Speter int hbsize; 68038032Speter bool trymx; 68190792Sgshapiro int *pttl; 68238032Speter{ 68338032Speter int nmaps; 68438032Speter int mapno; 68590792Sgshapiro bool found = false; 68690792Sgshapiro bool got_tempfail = false; 68764562Sgshapiro auto int status; 68838032Speter char *maptype[MAXMAPSTACK]; 68938032Speter short mapreturn[MAXMAPACTIONS]; 69038032Speter 69138032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 69290792Sgshapiro if (pttl != 0) 69390792Sgshapiro *pttl = SM_DEFAULT_TTL; 69438032Speter for (mapno = 0; mapno < nmaps; mapno++) 69538032Speter { 69638032Speter int i; 69738032Speter 69838032Speter if (tTd(38, 20)) 69990792Sgshapiro sm_dprintf("getcanonname(%s), trying %s\n", 70038032Speter host, maptype[mapno]); 70138032Speter if (strcmp("files", maptype[mapno]) == 0) 70238032Speter { 70364562Sgshapiro found = text_getcanonname(host, hbsize, &status); 70438032Speter } 70590792Sgshapiro#if NIS 70638032Speter else if (strcmp("nis", maptype[mapno]) == 0) 70738032Speter { 70864562Sgshapiro found = nis_getcanonname(host, hbsize, &status); 70938032Speter } 71064562Sgshapiro#endif /* NIS */ 71190792Sgshapiro#if NISPLUS 71238032Speter else if (strcmp("nisplus", maptype[mapno]) == 0) 71338032Speter { 71464562Sgshapiro found = nisplus_getcanonname(host, hbsize, &status); 71538032Speter } 71664562Sgshapiro#endif /* NISPLUS */ 71738032Speter#if NAMED_BIND 71838032Speter else if (strcmp("dns", maptype[mapno]) == 0) 71938032Speter { 72090792Sgshapiro found = dns_getcanonname(host, hbsize, trymx, &status, pttl); 72138032Speter } 72264562Sgshapiro#endif /* NAMED_BIND */ 72338032Speter#if NETINFO 72438032Speter else if (strcmp("netinfo", maptype[mapno]) == 0) 72538032Speter { 72664562Sgshapiro found = ni_getcanonname(host, hbsize, &status); 72738032Speter } 72864562Sgshapiro#endif /* NETINFO */ 72938032Speter else 73038032Speter { 73190792Sgshapiro found = false; 73264562Sgshapiro status = EX_UNAVAILABLE; 73338032Speter } 73438032Speter 73538032Speter /* 73638032Speter ** Heuristic: if $m is not set, we are running during system 73738032Speter ** startup. In this case, when a name is apparently found 73838032Speter ** but has no dot, treat is as not found. This avoids 73938032Speter ** problems if /etc/hosts has no FQDN but is listed first 74038032Speter ** in the service switch. 74138032Speter */ 74238032Speter 74338032Speter if (found && 74438032Speter (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 74538032Speter break; 74638032Speter 74738032Speter /* see if we should continue */ 74864562Sgshapiro if (status == EX_TEMPFAIL) 74938032Speter { 75038032Speter i = MA_TRYAGAIN; 75190792Sgshapiro got_tempfail = true; 75238032Speter } 75364562Sgshapiro else if (status == EX_NOTFOUND) 75438032Speter i = MA_NOTFOUND; 75538032Speter else 75638032Speter i = MA_UNAVAIL; 75738032Speter if (bitset(1 << mapno, mapreturn[i])) 75838032Speter break; 75938032Speter } 76038032Speter 76138032Speter if (found) 76238032Speter { 76338032Speter char *d; 76438032Speter 76538032Speter if (tTd(38, 20)) 76690792Sgshapiro sm_dprintf("getcanonname(%s), found\n", host); 76738032Speter 76838032Speter /* 76938032Speter ** If returned name is still single token, compensate 77038032Speter ** by tagging on $m. This is because some sites set 77138032Speter ** up their DNS or NIS databases wrong. 77238032Speter */ 77338032Speter 77438032Speter if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 77538032Speter { 77638032Speter d = macvalue('m', CurEnv); 77738032Speter if (d != NULL && 77838032Speter hbsize > (int) (strlen(host) + strlen(d) + 1)) 77938032Speter { 78038032Speter if (host[strlen(host) - 1] != '.') 78190792Sgshapiro (void) sm_strlcat2(host, ".", d, 78290792Sgshapiro hbsize); 78390792Sgshapiro else 78490792Sgshapiro (void) sm_strlcat(host, d, hbsize); 78538032Speter } 78638032Speter else 78790792Sgshapiro return false; 78838032Speter } 78990792Sgshapiro return true; 79038032Speter } 79138032Speter 79238032Speter if (tTd(38, 20)) 79390792Sgshapiro sm_dprintf("getcanonname(%s), failed, status=%d\n", host, 79490792Sgshapiro status); 79538032Speter 79638032Speter if (got_tempfail) 79773188Sgshapiro SM_SET_H_ERRNO(TRY_AGAIN); 79838032Speter else 79973188Sgshapiro SM_SET_H_ERRNO(HOST_NOT_FOUND); 80090792Sgshapiro 80190792Sgshapiro return false; 80238032Speter} 80390792Sgshapiro/* 80438032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 80538032Speter** 80638032Speter** Parameters: 80738032Speter** name -- the name against which to match. 80873188Sgshapiro** dot -- where to reinsert '.' to get FQDN 80938032Speter** line -- the /etc/hosts line. 81038032Speter** cbuf -- the location to store the result. 81138032Speter** cbuflen -- the size of cbuf. 81238032Speter** 81338032Speter** Returns: 81490792Sgshapiro** true -- if the line matched the desired name. 81590792Sgshapiro** false -- otherwise. 81638032Speter*/ 81738032Speter 81864562Sgshapirostatic bool 81973188Sgshapiroextract_canonname(name, dot, line, cbuf, cbuflen) 82038032Speter char *name; 82173188Sgshapiro char *dot; 82238032Speter char *line; 82338032Speter char cbuf[]; 82438032Speter int cbuflen; 82538032Speter{ 82638032Speter int i; 82738032Speter char *p; 82890792Sgshapiro bool found = false; 82938032Speter 83038032Speter cbuf[0] = '\0'; 83138032Speter if (line[0] == '#') 83290792Sgshapiro return false; 83338032Speter 83438032Speter for (i = 1; ; i++) 83538032Speter { 83638032Speter char nbuf[MAXNAME + 1]; 83738032Speter 83838032Speter p = get_column(line, i, '\0', nbuf, sizeof nbuf); 83938032Speter if (p == NULL) 84038032Speter break; 84138032Speter if (*p == '\0') 84238032Speter continue; 84338032Speter if (cbuf[0] == '\0' || 84438032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 84538032Speter { 84690792Sgshapiro (void) sm_strlcpy(cbuf, p, cbuflen); 84738032Speter } 84890792Sgshapiro if (sm_strcasecmp(name, p) == 0) 84990792Sgshapiro found = true; 85073188Sgshapiro else if (dot != NULL) 85173188Sgshapiro { 85273188Sgshapiro /* try looking for the FQDN as well */ 85373188Sgshapiro *dot = '.'; 85490792Sgshapiro if (sm_strcasecmp(name, p) == 0) 85590792Sgshapiro found = true; 85673188Sgshapiro *dot = '\0'; 85773188Sgshapiro } 85838032Speter } 85938032Speter if (found && strchr(cbuf, '.') == NULL) 86038032Speter { 86138032Speter /* try to add a domain on the end of the name */ 86238032Speter char *domain = macvalue('m', CurEnv); 86338032Speter 86438032Speter if (domain != NULL && 86564562Sgshapiro strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 86638032Speter { 86764562Sgshapiro p = &cbuf[i]; 86838032Speter *p++ = '.'; 86990792Sgshapiro (void) sm_strlcpy(p, domain, cbuflen - i - 1); 87038032Speter } 87138032Speter } 87238032Speter return found; 87338032Speter} 87490792Sgshapiro 87590792Sgshapiro/* 87690792Sgshapiro** DNS modules 87790792Sgshapiro*/ 87890792Sgshapiro 87990792Sgshapiro#if NAMED_BIND 88090792Sgshapiro# if DNSMAP 88190792Sgshapiro 88290792Sgshapiro# include "sm_resolve.h" 88390792Sgshapiro# if NETINET || NETINET6 88490792Sgshapiro# include <arpa/inet.h> 88590792Sgshapiro# endif /* NETINET || NETINET6 */ 88690792Sgshapiro 88790792Sgshapiro/* 88890792Sgshapiro** DNS_MAP_OPEN -- stub to check proper value for dns map type 88990792Sgshapiro*/ 89090792Sgshapiro 89190792Sgshapirobool 89290792Sgshapirodns_map_open(map, mode) 89390792Sgshapiro MAP *map; 89490792Sgshapiro int mode; 89590792Sgshapiro{ 89690792Sgshapiro if (tTd(38,2)) 89790792Sgshapiro sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode); 89890792Sgshapiro 89990792Sgshapiro mode &= O_ACCMODE; 90090792Sgshapiro if (mode != O_RDONLY) 90190792Sgshapiro { 90290792Sgshapiro /* issue a pseudo-error message */ 90390792Sgshapiro errno = SM_EMAPCANTWRITE; 90490792Sgshapiro return false; 90590792Sgshapiro } 90690792Sgshapiro return true; 90790792Sgshapiro} 90890792Sgshapiro 90990792Sgshapiro/* 91090792Sgshapiro** DNS_MAP_PARSEARGS -- parse dns map definition args. 91190792Sgshapiro** 91290792Sgshapiro** Parameters: 91390792Sgshapiro** map -- pointer to MAP 91490792Sgshapiro** args -- pointer to the args on the config line. 91590792Sgshapiro** 91690792Sgshapiro** Returns: 91790792Sgshapiro** true -- if everything parsed OK. 91890792Sgshapiro** false -- otherwise. 91990792Sgshapiro*/ 92090792Sgshapiro 92190792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 92290792Sgshapiro# if !_FFR_DNSMAP_MULTI 92390792Sgshapiro ERROR README: You must define _FFR_DNSMAP_MULTI to use _FFR_DNSMAP_MULTILIMIT 92490792Sgshapiro# endif /* ! _FFR_DNSMAP_MULTI */ 92590792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 92690792Sgshapiro 92790792Sgshapiro# if _FFR_DNSMAP_MULTI 92890792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 92990792Sgshapiro# define map_sizelimit map_lockfd /* overload field */ 93090792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 93190792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 93290792Sgshapiro 93390792Sgshapirostruct dns_map 93490792Sgshapiro{ 93590792Sgshapiro int dns_m_type; 93690792Sgshapiro}; 93790792Sgshapiro 93890792Sgshapirobool 93990792Sgshapirodns_map_parseargs(map,args) 94090792Sgshapiro MAP *map; 94190792Sgshapiro char *args; 94290792Sgshapiro{ 94390792Sgshapiro register char *p = args; 94490792Sgshapiro struct dns_map *map_p; 94590792Sgshapiro 94690792Sgshapiro map_p = (struct dns_map *) xalloc(sizeof *map_p); 94790792Sgshapiro map_p->dns_m_type = -1; 94890792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 94990792Sgshapiro 95090792Sgshapiro for (;;) 95190792Sgshapiro { 95290792Sgshapiro while (isascii(*p) && isspace(*p)) 95390792Sgshapiro p++; 95490792Sgshapiro if (*p != '-') 95590792Sgshapiro break; 95690792Sgshapiro switch (*++p) 95790792Sgshapiro { 95890792Sgshapiro case 'N': 95990792Sgshapiro map->map_mflags |= MF_INCLNULL; 96090792Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 96190792Sgshapiro break; 96290792Sgshapiro 96390792Sgshapiro case 'O': 96490792Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 96590792Sgshapiro break; 96690792Sgshapiro 96790792Sgshapiro case 'o': 96890792Sgshapiro map->map_mflags |= MF_OPTIONAL; 96990792Sgshapiro break; 97090792Sgshapiro 97190792Sgshapiro case 'f': 97290792Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 97390792Sgshapiro break; 97490792Sgshapiro 97590792Sgshapiro case 'm': 97690792Sgshapiro map->map_mflags |= MF_MATCHONLY; 97790792Sgshapiro break; 97890792Sgshapiro 97990792Sgshapiro case 'A': 98090792Sgshapiro map->map_mflags |= MF_APPEND; 98190792Sgshapiro break; 98290792Sgshapiro 98390792Sgshapiro case 'q': 98490792Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 98590792Sgshapiro break; 98690792Sgshapiro 98790792Sgshapiro case 't': 98890792Sgshapiro map->map_mflags |= MF_NODEFER; 98990792Sgshapiro break; 99090792Sgshapiro 99190792Sgshapiro case 'a': 99290792Sgshapiro map->map_app = ++p; 99390792Sgshapiro break; 99490792Sgshapiro 99590792Sgshapiro case 'T': 99690792Sgshapiro map->map_tapp = ++p; 99790792Sgshapiro break; 99890792Sgshapiro 99990792Sgshapiro case 'd': 100090792Sgshapiro { 100190792Sgshapiro char *h; 100290792Sgshapiro 100390792Sgshapiro ++p; 100490792Sgshapiro h = strchr(p, ' '); 100590792Sgshapiro if (h != NULL) 100690792Sgshapiro *h = '\0'; 100790792Sgshapiro map->map_timeout = convtime(p, 's'); 100890792Sgshapiro if (h != NULL) 100990792Sgshapiro *h = ' '; 101090792Sgshapiro } 101190792Sgshapiro break; 101290792Sgshapiro 101390792Sgshapiro case 'r': 101490792Sgshapiro while (isascii(*++p) && isspace(*p)) 101590792Sgshapiro continue; 101690792Sgshapiro map->map_retry = atoi(p); 101790792Sgshapiro break; 101890792Sgshapiro 101990792Sgshapiro# if _FFR_DNSMAP_MULTI 102090792Sgshapiro case 'z': 102190792Sgshapiro if (*++p != '\\') 102290792Sgshapiro map->map_coldelim = *p; 102390792Sgshapiro else 102490792Sgshapiro { 102590792Sgshapiro switch (*++p) 102690792Sgshapiro { 102790792Sgshapiro case 'n': 102890792Sgshapiro map->map_coldelim = '\n'; 102990792Sgshapiro break; 103090792Sgshapiro 103190792Sgshapiro case 't': 103290792Sgshapiro map->map_coldelim = '\t'; 103390792Sgshapiro break; 103490792Sgshapiro 103590792Sgshapiro default: 103690792Sgshapiro map->map_coldelim = '\\'; 103790792Sgshapiro } 103890792Sgshapiro } 103990792Sgshapiro break; 104090792Sgshapiro 104190792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 104290792Sgshapiro case 'Z': 104390792Sgshapiro while (isascii(*++p) && isspace(*p)) 104490792Sgshapiro continue; 104590792Sgshapiro map->map_sizelimit = atoi(p); 104690792Sgshapiro break; 104790792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 104890792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 104990792Sgshapiro 105090792Sgshapiro /* Start of dns_map specific args */ 105190792Sgshapiro case 'R': /* search field */ 105290792Sgshapiro { 105390792Sgshapiro char *h; 105490792Sgshapiro 105590792Sgshapiro while (isascii(*++p) && isspace(*p)) 105690792Sgshapiro continue; 105790792Sgshapiro h = strchr(p, ' '); 105890792Sgshapiro if (h != NULL) 105990792Sgshapiro *h = '\0'; 106090792Sgshapiro map_p->dns_m_type = dns_string_to_type(p); 106190792Sgshapiro if (h != NULL) 106290792Sgshapiro *h = ' '; 106390792Sgshapiro if (map_p->dns_m_type < 0) 106490792Sgshapiro syserr("dns map %s: wrong type %s", 106590792Sgshapiro map->map_mname, p); 106690792Sgshapiro } 106790792Sgshapiro break; 106890792Sgshapiro 106990792Sgshapiro# if _FFR_DNSMAP_BASE 107090792Sgshapiro case 'B': /* base domain */ 107190792Sgshapiro { 107290792Sgshapiro char *h; 107390792Sgshapiro 107490792Sgshapiro while (isascii(*++p) && isspace(*p)) 107590792Sgshapiro continue; 107690792Sgshapiro h = strchr(p, ' '); 107790792Sgshapiro if (h != NULL) 107890792Sgshapiro *h = '\0'; 107990792Sgshapiro 108090792Sgshapiro /* 108190792Sgshapiro ** slight abuse of map->map_file; it isn't 108290792Sgshapiro ** used otherwise in this map type. 108390792Sgshapiro */ 108490792Sgshapiro 108590792Sgshapiro map->map_file = newstr(p); 108690792Sgshapiro if (h != NULL) 108790792Sgshapiro *h = ' '; 108890792Sgshapiro } 108990792Sgshapiro break; 109090792Sgshapiro# endif /* _FFR_DNSMAP_BASE */ 109190792Sgshapiro 109290792Sgshapiro } 109390792Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 109490792Sgshapiro p++; 109590792Sgshapiro if (*p != '\0') 109690792Sgshapiro *p++ = '\0'; 109790792Sgshapiro } 109890792Sgshapiro if (map_p->dns_m_type < 0) 109990792Sgshapiro syserr("dns map %s: missing -R type", map->map_mname); 110090792Sgshapiro if (map->map_app != NULL) 110190792Sgshapiro map->map_app = newstr(map->map_app); 110290792Sgshapiro if (map->map_tapp != NULL) 110390792Sgshapiro map->map_tapp = newstr(map->map_tapp); 110490792Sgshapiro 110590792Sgshapiro /* 110690792Sgshapiro ** Assumption: assert(sizeof int <= sizeof(ARBPTR_T)); 110790792Sgshapiro ** Even if this assumption is wrong, we use only one byte, 110890792Sgshapiro ** so it doesn't really matter. 110990792Sgshapiro */ 111090792Sgshapiro 111190792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; 111290792Sgshapiro return true; 111390792Sgshapiro} 111490792Sgshapiro 111590792Sgshapiro/* 111690792Sgshapiro** DNS_MAP_LOOKUP -- perform dns map lookup. 111790792Sgshapiro** 111890792Sgshapiro** Parameters: 111990792Sgshapiro** map -- pointer to MAP 112090792Sgshapiro** name -- name to lookup 112190792Sgshapiro** av -- arguments to interpolate into buf. 112290792Sgshapiro** statp -- pointer to status (EX_) 112390792Sgshapiro** 112490792Sgshapiro** Returns: 112590792Sgshapiro** result of lookup if succeeded. 112690792Sgshapiro** NULL -- otherwise. 112790792Sgshapiro*/ 112890792Sgshapiro 112990792Sgshapirochar * 113090792Sgshapirodns_map_lookup(map, name, av, statp) 113190792Sgshapiro MAP *map; 113290792Sgshapiro char *name; 113390792Sgshapiro char **av; 113490792Sgshapiro int *statp; 113590792Sgshapiro{ 113690792Sgshapiro# if _FFR_DNSMAP_MULTI 113790792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 113890792Sgshapiro int resnum = 0; 113990792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 114090792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 114190792Sgshapiro char *vp = NULL, *result = NULL; 114290792Sgshapiro size_t vsize; 114390792Sgshapiro struct dns_map *map_p; 114490792Sgshapiro RESOURCE_RECORD_T *rr = NULL; 114590792Sgshapiro DNS_REPLY_T *r = NULL; 114690792Sgshapiro# if NETINET6 114790792Sgshapiro static char buf6[INET6_ADDRSTRLEN]; 114890792Sgshapiro# endif /* NETINET6 */ 114990792Sgshapiro 115090792Sgshapiro if (tTd(38, 20)) 115190792Sgshapiro sm_dprintf("dns_map_lookup(%s, %s)\n", 115290792Sgshapiro map->map_mname, name); 115390792Sgshapiro 115490792Sgshapiro map_p = (struct dns_map *)(map->map_db1); 115590792Sgshapiro# if _FFR_DNSMAP_BASE 115690792Sgshapiro if (map->map_file != NULL && *map->map_file != '\0') 115790792Sgshapiro { 115890792Sgshapiro size_t len; 115990792Sgshapiro char *appdomain; 116090792Sgshapiro 116190792Sgshapiro len = strlen(map->map_file) + strlen(name) + 2; 116290792Sgshapiro appdomain = (char *) sm_malloc(len); 116390792Sgshapiro if (appdomain == NULL) 116490792Sgshapiro { 116590792Sgshapiro *statp = EX_UNAVAILABLE; 116690792Sgshapiro return NULL; 116790792Sgshapiro } 116890792Sgshapiro (void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file); 116990792Sgshapiro r = dns_lookup_int(appdomain, C_IN, map_p->dns_m_type, 117090792Sgshapiro map->map_timeout, map->map_retry); 117190792Sgshapiro sm_free(appdomain); 117290792Sgshapiro } 117390792Sgshapiro else 117490792Sgshapiro# endif /* _FFR_DNSMAP_BASE */ 117590792Sgshapiro { 117690792Sgshapiro r = dns_lookup_int(name, C_IN, map_p->dns_m_type, 117790792Sgshapiro map->map_timeout, map->map_retry); 117890792Sgshapiro } 117990792Sgshapiro 118090792Sgshapiro if (r == NULL) 118190792Sgshapiro { 118290792Sgshapiro result = NULL; 1183120256Sgshapiro if (h_errno == TRY_AGAIN || transienterror(errno)) 118490792Sgshapiro *statp = EX_TEMPFAIL; 118590792Sgshapiro else 118690792Sgshapiro *statp = EX_NOTFOUND; 118790792Sgshapiro goto cleanup; 118890792Sgshapiro } 118990792Sgshapiro *statp = EX_OK; 119090792Sgshapiro for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next) 119190792Sgshapiro { 119290792Sgshapiro char *type = NULL; 119390792Sgshapiro char *value = NULL; 119490792Sgshapiro 119590792Sgshapiro switch (rr->rr_type) 119690792Sgshapiro { 119790792Sgshapiro case T_NS: 119890792Sgshapiro type = "T_NS"; 119990792Sgshapiro value = rr->rr_u.rr_txt; 120090792Sgshapiro break; 120190792Sgshapiro case T_CNAME: 120290792Sgshapiro type = "T_CNAME"; 120390792Sgshapiro value = rr->rr_u.rr_txt; 120490792Sgshapiro break; 120590792Sgshapiro case T_AFSDB: 120690792Sgshapiro type = "T_AFSDB"; 120790792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 120890792Sgshapiro break; 120990792Sgshapiro case T_SRV: 121090792Sgshapiro type = "T_SRV"; 121190792Sgshapiro value = rr->rr_u.rr_srv->srv_r_target; 121290792Sgshapiro break; 121390792Sgshapiro case T_PTR: 121490792Sgshapiro type = "T_PTR"; 121590792Sgshapiro value = rr->rr_u.rr_txt; 121690792Sgshapiro break; 121790792Sgshapiro case T_TXT: 121890792Sgshapiro type = "T_TXT"; 121990792Sgshapiro value = rr->rr_u.rr_txt; 122090792Sgshapiro break; 122190792Sgshapiro case T_MX: 122290792Sgshapiro type = "T_MX"; 122390792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 122490792Sgshapiro break; 122590792Sgshapiro# if NETINET 122690792Sgshapiro case T_A: 122790792Sgshapiro type = "T_A"; 122890792Sgshapiro value = inet_ntoa(*(rr->rr_u.rr_a)); 122990792Sgshapiro break; 123090792Sgshapiro# endif /* NETINET */ 123190792Sgshapiro# if NETINET6 123290792Sgshapiro case T_AAAA: 123390792Sgshapiro type = "T_AAAA"; 123490792Sgshapiro value = anynet_ntop(rr->rr_u.rr_aaaa, buf6, 123590792Sgshapiro sizeof buf6); 123690792Sgshapiro break; 123790792Sgshapiro# endif /* NETINET6 */ 123890792Sgshapiro } 123990792Sgshapiro 124098841Sgshapiro (void) strreplnonprt(value, 'X'); 124190792Sgshapiro if (map_p->dns_m_type != rr->rr_type) 124290792Sgshapiro { 124390792Sgshapiro if (tTd(38, 40)) 124490792Sgshapiro sm_dprintf("\tskipping type %s (%d) value %s\n", 124590792Sgshapiro type != NULL ? type : "<UNKNOWN>", 124690792Sgshapiro rr->rr_type, 124790792Sgshapiro value != NULL ? value : "<NO VALUE>"); 124890792Sgshapiro continue; 124990792Sgshapiro } 125090792Sgshapiro 125190792Sgshapiro# if NETINET6 125290792Sgshapiro if (rr->rr_type == T_AAAA && value == NULL) 125390792Sgshapiro { 125490792Sgshapiro result = NULL; 125590792Sgshapiro *statp = EX_DATAERR; 125690792Sgshapiro if (tTd(38, 40)) 125790792Sgshapiro sm_dprintf("\tbad T_AAAA conversion\n"); 125890792Sgshapiro goto cleanup; 125990792Sgshapiro } 126090792Sgshapiro# endif /* NETINET6 */ 126190792Sgshapiro if (tTd(38, 40)) 126290792Sgshapiro sm_dprintf("\tfound type %s (%d) value %s\n", 126390792Sgshapiro type != NULL ? type : "<UNKNOWN>", 126490792Sgshapiro rr->rr_type, 126590792Sgshapiro value != NULL ? value : "<NO VALUE>"); 126690792Sgshapiro# if _FFR_DNSMAP_MULTI 126790792Sgshapiro if (value != NULL && 126890792Sgshapiro (map->map_coldelim == '\0' || 126990792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 127090792Sgshapiro map->map_sizelimit == 1 || 127190792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 127290792Sgshapiro bitset(MF_MATCHONLY, map->map_mflags))) 127390792Sgshapiro { 127490792Sgshapiro /* Only care about the first match */ 127590792Sgshapiro vp = newstr(value); 127690792Sgshapiro break; 127790792Sgshapiro } 127890792Sgshapiro else if (vp == NULL) 127990792Sgshapiro { 128090792Sgshapiro /* First result */ 128190792Sgshapiro vp = newstr(value); 128290792Sgshapiro } 128390792Sgshapiro else 128490792Sgshapiro { 128590792Sgshapiro /* concatenate the results */ 128690792Sgshapiro int sz; 128790792Sgshapiro char *new; 128890792Sgshapiro 128990792Sgshapiro sz = strlen(vp) + strlen(value) + 2; 129090792Sgshapiro new = xalloc(sz); 129190792Sgshapiro (void) sm_snprintf(new, sz, "%s%c%s", 129290792Sgshapiro vp, map->map_coldelim, value); 129390792Sgshapiro sm_free(vp); 129490792Sgshapiro vp = new; 129590792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 129690792Sgshapiro if (map->map_sizelimit > 0 && 129790792Sgshapiro ++resnum >= map->map_sizelimit) 129890792Sgshapiro break; 129990792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 130090792Sgshapiro } 130190792Sgshapiro# else /* _FFR_DNSMAP_MULTI */ 130290792Sgshapiro vp = value; 130390792Sgshapiro break; 130490792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 130590792Sgshapiro } 130690792Sgshapiro if (vp == NULL) 130790792Sgshapiro { 130890792Sgshapiro result = NULL; 130990792Sgshapiro *statp = EX_NOTFOUND; 131090792Sgshapiro if (tTd(38, 40)) 131190792Sgshapiro sm_dprintf("\tno match found\n"); 131290792Sgshapiro goto cleanup; 131390792Sgshapiro } 131490792Sgshapiro 131590792Sgshapiro# if _FFR_DNSMAP_MULTI 131690792Sgshapiro /* Cleanly truncate for rulesets */ 131790792Sgshapiro truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim); 131890792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 131990792Sgshapiro 132090792Sgshapiro vsize = strlen(vp); 132190792Sgshapiro 132290792Sgshapiro if (LogLevel > 9) 132390792Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s", 132490792Sgshapiro name, vp); 132590792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 132690792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 132790792Sgshapiro else 132890792Sgshapiro result = map_rewrite(map, vp, vsize, av); 132990792Sgshapiro 133090792Sgshapiro cleanup: 133190792Sgshapiro# if _FFR_DNSMAP_MULTI 133290792Sgshapiro if (vp != NULL) 133390792Sgshapiro sm_free(vp); 133490792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 133590792Sgshapiro if (r != NULL) 133690792Sgshapiro dns_free_data(r); 133790792Sgshapiro return result; 133890792Sgshapiro} 133990792Sgshapiro# endif /* DNSMAP */ 134090792Sgshapiro#endif /* NAMED_BIND */ 134190792Sgshapiro 134290792Sgshapiro/* 134338032Speter** NDBM modules 134438032Speter*/ 134538032Speter 134690792Sgshapiro#if NDBM 134738032Speter 134838032Speter/* 134938032Speter** NDBM_MAP_OPEN -- DBM-style map open 135038032Speter*/ 135138032Speter 135238032Speterbool 135338032Speterndbm_map_open(map, mode) 135438032Speter MAP *map; 135538032Speter int mode; 135638032Speter{ 135738032Speter register DBM *dbm; 135864562Sgshapiro int save_errno; 135938032Speter int dfd; 136038032Speter int pfd; 136164562Sgshapiro long sff; 136238032Speter int ret; 136338032Speter int smode = S_IREAD; 136498121Sgshapiro char dirfile[MAXPATHLEN]; 136598121Sgshapiro char pagfile[MAXPATHLEN]; 136664562Sgshapiro struct stat st; 136738032Speter struct stat std, stp; 136838032Speter 136938032Speter if (tTd(38, 2)) 137090792Sgshapiro sm_dprintf("ndbm_map_open(%s, %s, %d)\n", 137138032Speter map->map_mname, map->map_file, mode); 137238032Speter map->map_lockfd = -1; 137338032Speter mode &= O_ACCMODE; 137438032Speter 137538032Speter /* do initial file and directory checks */ 137698121Sgshapiro if (sm_strlcpyn(dirfile, sizeof dirfile, 2, 137798121Sgshapiro map->map_file, ".dir") >= sizeof dirfile || 137898121Sgshapiro sm_strlcpyn(pagfile, sizeof pagfile, 2, 137998121Sgshapiro map->map_file, ".pag") >= sizeof pagfile) 138098121Sgshapiro { 138198121Sgshapiro errno = 0; 138298121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 138398121Sgshapiro syserr("dbm map \"%s\": map file %s name too long", 138498121Sgshapiro map->map_mname, map->map_file); 138598121Sgshapiro return false; 138698121Sgshapiro } 138738032Speter sff = SFF_ROOTOK|SFF_REGONLY; 138838032Speter if (mode == O_RDWR) 138938032Speter { 139038032Speter sff |= SFF_CREAT; 139164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 139238032Speter sff |= SFF_NOSLINK; 139364562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 139438032Speter sff |= SFF_NOHLINK; 139538032Speter smode = S_IWRITE; 139638032Speter } 139738032Speter else 139838032Speter { 139964562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 140038032Speter sff |= SFF_NOWLINK; 140138032Speter } 140264562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 140338032Speter sff |= SFF_SAFEDIRPATH; 140438032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 140590792Sgshapiro sff, smode, &std); 140638032Speter if (ret == 0) 140738032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 140838032Speter sff, smode, &stp); 140964562Sgshapiro 141038032Speter if (ret != 0) 141138032Speter { 141238032Speter char *prob = "unsafe"; 141338032Speter 141438032Speter /* cannot open this map */ 141538032Speter if (ret == ENOENT) 141638032Speter prob = "missing"; 141738032Speter if (tTd(38, 2)) 141890792Sgshapiro sm_dprintf("\t%s map file: %d\n", prob, ret); 141938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 142038032Speter syserr("dbm map \"%s\": %s map file %s", 142138032Speter map->map_mname, prob, map->map_file); 142290792Sgshapiro return false; 142338032Speter } 142438032Speter if (std.st_mode == ST_MODE_NOFILE) 142538032Speter mode |= O_CREAT|O_EXCL; 142638032Speter 142764562Sgshapiro# if LOCK_ON_OPEN 142838032Speter if (mode == O_RDONLY) 142938032Speter mode |= O_SHLOCK; 143038032Speter else 143138032Speter mode |= O_TRUNC|O_EXLOCK; 143264562Sgshapiro# else /* LOCK_ON_OPEN */ 143338032Speter if ((mode & O_ACCMODE) == O_RDWR) 143438032Speter { 143564562Sgshapiro# if NOFTRUNCATE 143638032Speter /* 143738032Speter ** Warning: race condition. Try to lock the file as 143838032Speter ** quickly as possible after opening it. 143938032Speter ** This may also have security problems on some systems, 144038032Speter ** but there isn't anything we can do about it. 144138032Speter */ 144238032Speter 144338032Speter mode |= O_TRUNC; 144464562Sgshapiro# else /* NOFTRUNCATE */ 144538032Speter /* 144638032Speter ** This ugly code opens the map without truncating it, 144738032Speter ** locks the file, then truncates it. Necessary to 144838032Speter ** avoid race conditions. 144938032Speter */ 145038032Speter 145138032Speter int dirfd; 145238032Speter int pagfd; 145364562Sgshapiro long sff = SFF_CREAT|SFF_OPENASROOT; 145438032Speter 145564562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 145638032Speter sff |= SFF_NOSLINK; 145764562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 145838032Speter sff |= SFF_NOHLINK; 145938032Speter 146038032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 146138032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 146238032Speter 146338032Speter if (dirfd < 0 || pagfd < 0) 146438032Speter { 146564562Sgshapiro save_errno = errno; 146638032Speter if (dirfd >= 0) 146738032Speter (void) close(dirfd); 146838032Speter if (pagfd >= 0) 146938032Speter (void) close(pagfd); 147038032Speter errno = save_errno; 147138032Speter syserr("ndbm_map_open: cannot create database %s", 147238032Speter map->map_file); 147390792Sgshapiro return false; 147438032Speter } 147538032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 147638032Speter ftruncate(pagfd, (off_t) 0) < 0) 147738032Speter { 147864562Sgshapiro save_errno = errno; 147938032Speter (void) close(dirfd); 148038032Speter (void) close(pagfd); 148138032Speter errno = save_errno; 148238032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 148338032Speter map->map_file); 148490792Sgshapiro return false; 148538032Speter } 148638032Speter 148738032Speter /* if new file, get "before" bits for later filechanged check */ 148838032Speter if (std.st_mode == ST_MODE_NOFILE && 148938032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 149038032Speter { 149164562Sgshapiro save_errno = errno; 149238032Speter (void) close(dirfd); 149338032Speter (void) close(pagfd); 149438032Speter errno = save_errno; 149538032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 149638032Speter map->map_file); 149790792Sgshapiro return false; 149838032Speter } 149938032Speter 150038032Speter /* have to save the lock for the duration (bletch) */ 150138032Speter map->map_lockfd = dirfd; 150264562Sgshapiro (void) close(pagfd); 150338032Speter 150438032Speter /* twiddle bits for dbm_open */ 150538032Speter mode &= ~(O_CREAT|O_EXCL); 150664562Sgshapiro# endif /* NOFTRUNCATE */ 150738032Speter } 150864562Sgshapiro# endif /* LOCK_ON_OPEN */ 150938032Speter 151038032Speter /* open the database */ 151138032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 151238032Speter if (dbm == NULL) 151338032Speter { 151464562Sgshapiro save_errno = errno; 151538032Speter if (bitset(MF_ALIAS, map->map_mflags) && 151690792Sgshapiro aliaswait(map, ".pag", false)) 151790792Sgshapiro return true; 151864562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 151938032Speter if (map->map_lockfd >= 0) 152064562Sgshapiro (void) close(map->map_lockfd); 152164562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 152238032Speter errno = save_errno; 152338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 152438032Speter syserr("Cannot open DBM database %s", map->map_file); 152590792Sgshapiro return false; 152638032Speter } 152738032Speter dfd = dbm_dirfno(dbm); 152838032Speter pfd = dbm_pagfno(dbm); 152938032Speter if (dfd == pfd) 153038032Speter { 153138032Speter /* heuristic: if files are linked, this is actually gdbm */ 153238032Speter dbm_close(dbm); 153364562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 153438032Speter if (map->map_lockfd >= 0) 153564562Sgshapiro (void) close(map->map_lockfd); 153664562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 153738032Speter errno = 0; 153838032Speter syserr("dbm map \"%s\": cannot support GDBM", 153938032Speter map->map_mname); 154090792Sgshapiro return false; 154138032Speter } 154238032Speter 154338032Speter if (filechanged(dirfile, dfd, &std) || 154438032Speter filechanged(pagfile, pfd, &stp)) 154538032Speter { 154664562Sgshapiro save_errno = errno; 154738032Speter dbm_close(dbm); 154864562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 154938032Speter if (map->map_lockfd >= 0) 155064562Sgshapiro (void) close(map->map_lockfd); 155164562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 155238032Speter errno = save_errno; 155338032Speter syserr("ndbm_map_open(%s): file changed after open", 155438032Speter map->map_file); 155590792Sgshapiro return false; 155638032Speter } 155738032Speter 155838032Speter map->map_db1 = (ARBPTR_T) dbm; 155964562Sgshapiro 156064562Sgshapiro /* 156164562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 156264562Sgshapiro ** as aliaswait() will call map_lookup() which requires 156364562Sgshapiro ** map_mtime to be set 156464562Sgshapiro */ 156564562Sgshapiro 156677349Sgshapiro if (fstat(pfd, &st) >= 0) 156764562Sgshapiro map->map_mtime = st.st_mtime; 156864562Sgshapiro 156938032Speter if (mode == O_RDONLY) 157038032Speter { 157164562Sgshapiro# if LOCK_ON_OPEN 157238032Speter if (dfd >= 0) 157338032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 157438032Speter if (pfd >= 0) 157538032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 157664562Sgshapiro# endif /* LOCK_ON_OPEN */ 157738032Speter if (bitset(MF_ALIAS, map->map_mflags) && 157890792Sgshapiro !aliaswait(map, ".pag", true)) 157990792Sgshapiro return false; 158038032Speter } 158138032Speter else 158238032Speter { 158338032Speter map->map_mflags |= MF_LOCKED; 158442575Speter if (geteuid() == 0 && TrustedUid != 0) 158538032Speter { 158664562Sgshapiro# if HASFCHOWN 158742575Speter if (fchown(dfd, TrustedUid, -1) < 0 || 158842575Speter fchown(pfd, TrustedUid, -1) < 0) 158938032Speter { 159038032Speter int err = errno; 159138032Speter 159238032Speter sm_syslog(LOG_ALERT, NOQID, 159338032Speter "ownership change on %s failed: %s", 159490792Sgshapiro map->map_file, sm_errstring(err)); 159538032Speter message("050 ownership change on %s failed: %s", 159690792Sgshapiro map->map_file, sm_errstring(err)); 159738032Speter } 159890792Sgshapiro# else /* HASFCHOWN */ 159990792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 160090792Sgshapiro "no fchown(): cannot change ownership on %s", 160190792Sgshapiro map->map_file); 160290792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 160390792Sgshapiro map->map_file); 160464562Sgshapiro# endif /* HASFCHOWN */ 160538032Speter } 160638032Speter } 160790792Sgshapiro return true; 160838032Speter} 160938032Speter 161038032Speter 161138032Speter/* 161238032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 161338032Speter*/ 161438032Speter 161538032Speterchar * 161638032Speterndbm_map_lookup(map, name, av, statp) 161738032Speter MAP *map; 161838032Speter char *name; 161938032Speter char **av; 162038032Speter int *statp; 162138032Speter{ 162238032Speter datum key, val; 162377349Sgshapiro int dfd, pfd; 162438032Speter char keybuf[MAXNAME + 1]; 162538032Speter struct stat stbuf; 162638032Speter 162738032Speter if (tTd(38, 20)) 162890792Sgshapiro sm_dprintf("ndbm_map_lookup(%s, %s)\n", 162938032Speter map->map_mname, name); 163038032Speter 163138032Speter key.dptr = name; 163238032Speter key.dsize = strlen(name); 163338032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 163438032Speter { 163538032Speter if (key.dsize > sizeof keybuf - 1) 163638032Speter key.dsize = sizeof keybuf - 1; 163764562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 163838032Speter keybuf[key.dsize] = '\0'; 163938032Speter makelower(keybuf); 164038032Speter key.dptr = keybuf; 164138032Speter } 164238032Speterlockdbm: 164377349Sgshapiro dfd = dbm_dirfno((DBM *) map->map_db1); 164477349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 164577349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_SH); 164677349Sgshapiro pfd = dbm_pagfno((DBM *) map->map_db1); 164777349Sgshapiro if (pfd < 0 || fstat(pfd, &stbuf) < 0 || 164877349Sgshapiro stbuf.st_mtime > map->map_mtime) 164938032Speter { 165038032Speter /* Reopen the database to sync the cache */ 165138032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 165238032Speter : O_RDONLY; 165338032Speter 165477349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 165577349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 165677349Sgshapiro map->map_mflags |= MF_CLOSING; 165738032Speter map->map_class->map_close(map); 165877349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 165938032Speter if (map->map_class->map_open(map, omode)) 166038032Speter { 166138032Speter map->map_mflags |= MF_OPEN; 166290792Sgshapiro map->map_pid = CurrentPid; 166338032Speter if ((omode && O_ACCMODE) == O_RDWR) 166438032Speter map->map_mflags |= MF_WRITABLE; 166538032Speter goto lockdbm; 166638032Speter } 166738032Speter else 166838032Speter { 166938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 167038032Speter { 167138032Speter extern MAPCLASS BogusMapClass; 167238032Speter 167338032Speter *statp = EX_TEMPFAIL; 167490792Sgshapiro map->map_orgclass = map->map_class; 167538032Speter map->map_class = &BogusMapClass; 167638032Speter map->map_mflags |= MF_OPEN; 167790792Sgshapiro map->map_pid = CurrentPid; 167838032Speter syserr("Cannot reopen NDBM database %s", 167938032Speter map->map_file); 168038032Speter } 168138032Speter return NULL; 168238032Speter } 168338032Speter } 168438032Speter val.dptr = NULL; 168538032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 168638032Speter { 168738032Speter val = dbm_fetch((DBM *) map->map_db1, key); 168838032Speter if (val.dptr != NULL) 168938032Speter map->map_mflags &= ~MF_TRY1NULL; 169038032Speter } 169138032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 169238032Speter { 169338032Speter key.dsize++; 169438032Speter val = dbm_fetch((DBM *) map->map_db1, key); 169538032Speter if (val.dptr != NULL) 169638032Speter map->map_mflags &= ~MF_TRY0NULL; 169738032Speter } 169877349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 169977349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 170038032Speter if (val.dptr == NULL) 170138032Speter return NULL; 170238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 170338032Speter return map_rewrite(map, name, strlen(name), NULL); 170438032Speter else 170538032Speter return map_rewrite(map, val.dptr, val.dsize, av); 170638032Speter} 170738032Speter 170838032Speter 170938032Speter/* 171038032Speter** NDBM_MAP_STORE -- store a datum in the database 171138032Speter*/ 171238032Speter 171338032Spetervoid 171438032Speterndbm_map_store(map, lhs, rhs) 171538032Speter register MAP *map; 171638032Speter char *lhs; 171738032Speter char *rhs; 171838032Speter{ 171938032Speter datum key; 172038032Speter datum data; 172164562Sgshapiro int status; 172238032Speter char keybuf[MAXNAME + 1]; 172338032Speter 172438032Speter if (tTd(38, 12)) 172590792Sgshapiro sm_dprintf("ndbm_map_store(%s, %s, %s)\n", 172638032Speter map->map_mname, lhs, rhs); 172738032Speter 172838032Speter key.dsize = strlen(lhs); 172938032Speter key.dptr = lhs; 173038032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 173138032Speter { 173238032Speter if (key.dsize > sizeof keybuf - 1) 173338032Speter key.dsize = sizeof keybuf - 1; 173464562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 173538032Speter keybuf[key.dsize] = '\0'; 173638032Speter makelower(keybuf); 173738032Speter key.dptr = keybuf; 173838032Speter } 173938032Speter 174038032Speter data.dsize = strlen(rhs); 174138032Speter data.dptr = rhs; 174238032Speter 174338032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 174438032Speter { 174538032Speter key.dsize++; 174638032Speter data.dsize++; 174738032Speter } 174838032Speter 174964562Sgshapiro status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 175064562Sgshapiro if (status > 0) 175138032Speter { 175238032Speter if (!bitset(MF_APPEND, map->map_mflags)) 175338032Speter message("050 Warning: duplicate alias name %s", lhs); 175438032Speter else 175538032Speter { 175638032Speter static char *buf = NULL; 175738032Speter static int bufsiz = 0; 175838032Speter auto int xstat; 175938032Speter datum old; 176038032Speter 176138032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 176290792Sgshapiro (char **) NULL, &xstat); 176338032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 176438032Speter { 176538032Speter old.dsize = strlen(old.dptr); 176638032Speter if (data.dsize + old.dsize + 2 > bufsiz) 176738032Speter { 176838032Speter if (buf != NULL) 176990792Sgshapiro (void) sm_free(buf); 177038032Speter bufsiz = data.dsize + old.dsize + 2; 177190792Sgshapiro buf = sm_pmalloc_x(bufsiz); 177238032Speter } 177390792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 177490792Sgshapiro data.dptr, ",", old.dptr); 177538032Speter data.dsize = data.dsize + old.dsize + 1; 177638032Speter data.dptr = buf; 177738032Speter if (tTd(38, 9)) 177890792Sgshapiro sm_dprintf("ndbm_map_store append=%s\n", 177964562Sgshapiro data.dptr); 178038032Speter } 178138032Speter } 178264562Sgshapiro status = dbm_store((DBM *) map->map_db1, 178364562Sgshapiro key, data, DBM_REPLACE); 178438032Speter } 178564562Sgshapiro if (status != 0) 178664562Sgshapiro syserr("readaliases: dbm put (%s): %d", lhs, status); 178738032Speter} 178838032Speter 178938032Speter 179038032Speter/* 179138032Speter** NDBM_MAP_CLOSE -- close the database 179238032Speter*/ 179338032Speter 179438032Spetervoid 179538032Speterndbm_map_close(map) 179638032Speter register MAP *map; 179738032Speter{ 179838032Speter if (tTd(38, 9)) 179990792Sgshapiro sm_dprintf("ndbm_map_close(%s, %s, %lx)\n", 180038032Speter map->map_mname, map->map_file, map->map_mflags); 180138032Speter 180238032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 180338032Speter { 180464562Sgshapiro# ifdef NDBM_YP_COMPAT 180538032Speter bool inclnull; 180642575Speter char buf[MAXHOSTNAMELEN]; 180738032Speter 180838032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 180938032Speter map->map_mflags &= ~MF_INCLNULL; 181038032Speter 181138032Speter if (strstr(map->map_file, "/yp/") != NULL) 181238032Speter { 181338032Speter long save_mflags = map->map_mflags; 181438032Speter 181538032Speter map->map_mflags |= MF_NOFOLDCASE; 181638032Speter 181790792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%010ld", curtime()); 181838032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 181938032Speter 182038032Speter (void) gethostname(buf, sizeof buf); 182138032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 182238032Speter 182338032Speter map->map_mflags = save_mflags; 182438032Speter } 182538032Speter 182638032Speter if (inclnull) 182738032Speter map->map_mflags |= MF_INCLNULL; 182864562Sgshapiro# endif /* NDBM_YP_COMPAT */ 182938032Speter 183038032Speter /* write out the distinguished alias */ 183138032Speter ndbm_map_store(map, "@", "@"); 183238032Speter } 183338032Speter dbm_close((DBM *) map->map_db1); 183438032Speter 183538032Speter /* release lock (if needed) */ 183664562Sgshapiro# if !LOCK_ON_OPEN 183738032Speter if (map->map_lockfd >= 0) 183838032Speter (void) close(map->map_lockfd); 183964562Sgshapiro# endif /* !LOCK_ON_OPEN */ 184038032Speter} 184138032Speter 184264562Sgshapiro#endif /* NDBM */ 184390792Sgshapiro/* 184438032Speter** NEWDB (Hash and BTree) Modules 184538032Speter*/ 184638032Speter 184790792Sgshapiro#if NEWDB 184838032Speter 184938032Speter/* 185038032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 185138032Speter** 185238032Speter** These do rather bizarre locking. If you can lock on open, 185338032Speter** do that to avoid the condition of opening a database that 185438032Speter** is being rebuilt. If you don't, we'll try to fake it, but 185538032Speter** there will be a race condition. If opening for read-only, 185638032Speter** we immediately release the lock to avoid freezing things up. 185738032Speter** We really ought to hold the lock, but guarantee that we won't 185838032Speter** be pokey about it. That's hard to do. 185938032Speter*/ 186038032Speter 186138032Speter/* these should be K line arguments */ 186264562Sgshapiro# if DB_VERSION_MAJOR < 2 186364562Sgshapiro# define db_cachesize cachesize 186464562Sgshapiro# define h_nelem nelem 186564562Sgshapiro# ifndef DB_CACHE_SIZE 186664562Sgshapiro# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 186764562Sgshapiro# endif /* ! DB_CACHE_SIZE */ 186864562Sgshapiro# ifndef DB_HASH_NELEM 186964562Sgshapiro# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 187064562Sgshapiro# endif /* ! DB_HASH_NELEM */ 187164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 187238032Speter 187338032Speterbool 187438032Speterbt_map_open(map, mode) 187538032Speter MAP *map; 187638032Speter int mode; 187738032Speter{ 187864562Sgshapiro# if DB_VERSION_MAJOR < 2 187938032Speter BTREEINFO btinfo; 188064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 188164562Sgshapiro# if DB_VERSION_MAJOR == 2 188238032Speter DB_INFO btinfo; 188364562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 188464562Sgshapiro# if DB_VERSION_MAJOR > 2 188564562Sgshapiro void *btinfo = NULL; 188664562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 188738032Speter 188838032Speter if (tTd(38, 2)) 188990792Sgshapiro sm_dprintf("bt_map_open(%s, %s, %d)\n", 189038032Speter map->map_mname, map->map_file, mode); 189138032Speter 189264562Sgshapiro# if DB_VERSION_MAJOR < 3 189364562Sgshapiro memset(&btinfo, '\0', sizeof btinfo); 189464562Sgshapiro# ifdef DB_CACHE_SIZE 189538032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 189664562Sgshapiro# endif /* DB_CACHE_SIZE */ 189764562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 189864562Sgshapiro 189938032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 190038032Speter} 190138032Speter 190238032Speterbool 190338032Speterhash_map_open(map, mode) 190438032Speter MAP *map; 190538032Speter int mode; 190638032Speter{ 190764562Sgshapiro# if DB_VERSION_MAJOR < 2 190838032Speter HASHINFO hinfo; 190964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 191064562Sgshapiro# if DB_VERSION_MAJOR == 2 191138032Speter DB_INFO hinfo; 191264562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 191364562Sgshapiro# if DB_VERSION_MAJOR > 2 191464562Sgshapiro void *hinfo = NULL; 191564562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 191638032Speter 191738032Speter if (tTd(38, 2)) 191890792Sgshapiro sm_dprintf("hash_map_open(%s, %s, %d)\n", 191938032Speter map->map_mname, map->map_file, mode); 192038032Speter 192164562Sgshapiro# if DB_VERSION_MAJOR < 3 192264562Sgshapiro memset(&hinfo, '\0', sizeof hinfo); 192364562Sgshapiro# ifdef DB_HASH_NELEM 192438032Speter hinfo.h_nelem = DB_HASH_NELEM; 192564562Sgshapiro# endif /* DB_HASH_NELEM */ 192664562Sgshapiro# ifdef DB_CACHE_SIZE 192738032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 192864562Sgshapiro# endif /* DB_CACHE_SIZE */ 192964562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 193064562Sgshapiro 193138032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 193238032Speter} 193338032Speter 193464562Sgshapirostatic bool 193538032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 193638032Speter MAP *map; 193738032Speter int mode; 193838032Speter char *mapclassname; 193938032Speter DBTYPE dbtype; 194064562Sgshapiro# if DB_VERSION_MAJOR < 2 194138032Speter const void *openinfo; 194264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 194364562Sgshapiro# if DB_VERSION_MAJOR == 2 194438032Speter DB_INFO *openinfo; 194564562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 194664562Sgshapiro# if DB_VERSION_MAJOR > 2 194764562Sgshapiro void **openinfo; 194864562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 194938032Speter{ 195038032Speter DB *db = NULL; 195138032Speter int i; 195238032Speter int omode; 195338032Speter int smode = S_IREAD; 195438032Speter int fd; 195564562Sgshapiro long sff; 195664562Sgshapiro int save_errno; 195738032Speter struct stat st; 195898121Sgshapiro char buf[MAXPATHLEN]; 195938032Speter 196038032Speter /* do initial file and directory checks */ 196198121Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf) 196298121Sgshapiro { 196398121Sgshapiro errno = 0; 196498121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 196598121Sgshapiro syserr("map \"%s\": map file %s name too long", 196698121Sgshapiro map->map_mname, map->map_file); 196798121Sgshapiro return false; 196898121Sgshapiro } 196938032Speter i = strlen(buf); 197038032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 197198121Sgshapiro { 197298121Sgshapiro if (sm_strlcat(buf, ".db", sizeof buf) >= sizeof buf) 197398121Sgshapiro { 197498121Sgshapiro errno = 0; 197598121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 197698121Sgshapiro syserr("map \"%s\": map file %s name too long", 197798121Sgshapiro map->map_mname, map->map_file); 197898121Sgshapiro return false; 197998121Sgshapiro } 198098121Sgshapiro } 198138032Speter 198238032Speter mode &= O_ACCMODE; 198338032Speter omode = mode; 198438032Speter 198538032Speter sff = SFF_ROOTOK|SFF_REGONLY; 198638032Speter if (mode == O_RDWR) 198738032Speter { 198838032Speter sff |= SFF_CREAT; 198964562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 199038032Speter sff |= SFF_NOSLINK; 199164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 199238032Speter sff |= SFF_NOHLINK; 199338032Speter smode = S_IWRITE; 199438032Speter } 199538032Speter else 199638032Speter { 199764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 199838032Speter sff |= SFF_NOWLINK; 199938032Speter } 200064562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 200138032Speter sff |= SFF_SAFEDIRPATH; 200238032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 200364562Sgshapiro 200438032Speter if (i != 0) 200538032Speter { 200638032Speter char *prob = "unsafe"; 200738032Speter 200838032Speter /* cannot open this map */ 200938032Speter if (i == ENOENT) 201038032Speter prob = "missing"; 201138032Speter if (tTd(38, 2)) 201290792Sgshapiro sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i)); 201338032Speter errno = i; 201438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 201538032Speter syserr("%s map \"%s\": %s map file %s", 201638032Speter mapclassname, map->map_mname, prob, buf); 201790792Sgshapiro return false; 201838032Speter } 201938032Speter if (st.st_mode == ST_MODE_NOFILE) 202038032Speter omode |= O_CREAT|O_EXCL; 202138032Speter 202238032Speter map->map_lockfd = -1; 202338032Speter 202464562Sgshapiro# if LOCK_ON_OPEN 202538032Speter if (mode == O_RDWR) 202638032Speter omode |= O_TRUNC|O_EXLOCK; 202738032Speter else 202838032Speter omode |= O_SHLOCK; 202964562Sgshapiro# else /* LOCK_ON_OPEN */ 203038032Speter /* 203138032Speter ** Pre-lock the file to avoid race conditions. In particular, 203238032Speter ** since dbopen returns NULL if the file is zero length, we 203338032Speter ** must have a locked instance around the dbopen. 203438032Speter */ 203538032Speter 203638032Speter fd = open(buf, omode, DBMMODE); 203738032Speter if (fd < 0) 203838032Speter { 203938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 204038032Speter syserr("db_map_open: cannot pre-open database %s", buf); 204190792Sgshapiro return false; 204238032Speter } 204338032Speter 204438032Speter /* make sure no baddies slipped in just before the open... */ 204538032Speter if (filechanged(buf, fd, &st)) 204638032Speter { 204764562Sgshapiro save_errno = errno; 204838032Speter (void) close(fd); 204938032Speter errno = save_errno; 205038032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 205190792Sgshapiro return false; 205238032Speter } 205338032Speter 205438032Speter /* if new file, get the "before" bits for later filechanged check */ 205538032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 205638032Speter { 205764562Sgshapiro save_errno = errno; 205838032Speter (void) close(fd); 205938032Speter errno = save_errno; 206038032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 206138032Speter buf); 206290792Sgshapiro return false; 206338032Speter } 206438032Speter 206538032Speter /* actually lock the pre-opened file */ 206638032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 206738032Speter syserr("db_map_open: cannot lock %s", buf); 206838032Speter 206938032Speter /* set up mode bits for dbopen */ 207038032Speter if (mode == O_RDWR) 207138032Speter omode |= O_TRUNC; 207238032Speter omode &= ~(O_EXCL|O_CREAT); 207364562Sgshapiro# endif /* LOCK_ON_OPEN */ 207438032Speter 207564562Sgshapiro# if DB_VERSION_MAJOR < 2 207638032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 207764562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 207838032Speter { 207938032Speter int flags = 0; 208064562Sgshapiro# if DB_VERSION_MAJOR > 2 208164562Sgshapiro int ret; 208264562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 208338032Speter 208438032Speter if (mode == O_RDONLY) 208538032Speter flags |= DB_RDONLY; 208638032Speter if (bitset(O_CREAT, omode)) 208738032Speter flags |= DB_CREATE; 208838032Speter if (bitset(O_TRUNC, omode)) 208938032Speter flags |= DB_TRUNCATE; 2090110560Sgshapiro SM_DB_FLAG_ADD(flags); 209138032Speter 209264562Sgshapiro# if DB_VERSION_MAJOR > 2 209364562Sgshapiro ret = db_create(&db, NULL, 0); 209464562Sgshapiro# ifdef DB_CACHE_SIZE 209564562Sgshapiro if (ret == 0 && db != NULL) 209664562Sgshapiro { 209764562Sgshapiro ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 209864562Sgshapiro if (ret != 0) 209964562Sgshapiro { 210064562Sgshapiro (void) db->close(db, 0); 210164562Sgshapiro db = NULL; 210264562Sgshapiro } 210364562Sgshapiro } 210464562Sgshapiro# endif /* DB_CACHE_SIZE */ 210564562Sgshapiro# ifdef DB_HASH_NELEM 210664562Sgshapiro if (dbtype == DB_HASH && ret == 0 && db != NULL) 210764562Sgshapiro { 210864562Sgshapiro ret = db->set_h_nelem(db, DB_HASH_NELEM); 210964562Sgshapiro if (ret != 0) 211064562Sgshapiro { 211164562Sgshapiro (void) db->close(db, 0); 211264562Sgshapiro db = NULL; 211364562Sgshapiro } 211464562Sgshapiro } 211564562Sgshapiro# endif /* DB_HASH_NELEM */ 211664562Sgshapiro if (ret == 0 && db != NULL) 211764562Sgshapiro { 2118110560Sgshapiro ret = db->open(db, 2119110560Sgshapiro DBTXN /* transaction for DB 4.1 */ 2120110560Sgshapiro buf, NULL, dbtype, flags, DBMMODE); 212164562Sgshapiro if (ret != 0) 212264562Sgshapiro { 212373188Sgshapiro#ifdef DB_OLD_VERSION 212473188Sgshapiro if (ret == DB_OLD_VERSION) 212573188Sgshapiro ret = EINVAL; 212673188Sgshapiro#endif /* DB_OLD_VERSION */ 212764562Sgshapiro (void) db->close(db, 0); 212864562Sgshapiro db = NULL; 212964562Sgshapiro } 213064562Sgshapiro } 213164562Sgshapiro errno = ret; 213264562Sgshapiro# else /* DB_VERSION_MAJOR > 2 */ 213338032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 213438032Speter NULL, openinfo, &db); 213564562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 213638032Speter } 213764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 213864562Sgshapiro save_errno = errno; 213938032Speter 214064562Sgshapiro# if !LOCK_ON_OPEN 214138032Speter if (mode == O_RDWR) 214238032Speter map->map_lockfd = fd; 214338032Speter else 214438032Speter (void) close(fd); 214564562Sgshapiro# endif /* !LOCK_ON_OPEN */ 214638032Speter 214738032Speter if (db == NULL) 214838032Speter { 214938032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 215090792Sgshapiro aliaswait(map, ".db", false)) 215190792Sgshapiro return true; 215264562Sgshapiro# if !LOCK_ON_OPEN 215338032Speter if (map->map_lockfd >= 0) 215438032Speter (void) close(map->map_lockfd); 215564562Sgshapiro# endif /* !LOCK_ON_OPEN */ 215664562Sgshapiro errno = save_errno; 215738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 215838032Speter syserr("Cannot open %s database %s", 215938032Speter mapclassname, buf); 216090792Sgshapiro return false; 216138032Speter } 216238032Speter 216364562Sgshapiro# if DB_VERSION_MAJOR < 2 216438032Speter fd = db->fd(db); 216564562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 216638032Speter fd = -1; 216738032Speter errno = db->fd(db, &fd); 216864562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 216938032Speter if (filechanged(buf, fd, &st)) 217038032Speter { 217164562Sgshapiro save_errno = errno; 217264562Sgshapiro# if DB_VERSION_MAJOR < 2 217364562Sgshapiro (void) db->close(db); 217464562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 217538032Speter errno = db->close(db, 0); 217664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 217764562Sgshapiro# if !LOCK_ON_OPEN 217838032Speter if (map->map_lockfd >= 0) 217964562Sgshapiro (void) close(map->map_lockfd); 218064562Sgshapiro# endif /* !LOCK_ON_OPEN */ 218138032Speter errno = save_errno; 218238032Speter syserr("db_map_open(%s): file changed after open", buf); 218390792Sgshapiro return false; 218438032Speter } 218538032Speter 218638032Speter if (mode == O_RDWR) 218738032Speter map->map_mflags |= MF_LOCKED; 218864562Sgshapiro# if LOCK_ON_OPEN 218938032Speter if (fd >= 0 && mode == O_RDONLY) 219038032Speter { 219138032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 219238032Speter } 219364562Sgshapiro# endif /* LOCK_ON_OPEN */ 219438032Speter 219538032Speter /* try to make sure that at least the database header is on disk */ 219638032Speter if (mode == O_RDWR) 219738032Speter { 219838032Speter (void) db->sync(db, 0); 219942575Speter if (geteuid() == 0 && TrustedUid != 0) 220038032Speter { 220164562Sgshapiro# if HASFCHOWN 220242575Speter if (fchown(fd, TrustedUid, -1) < 0) 220338032Speter { 220438032Speter int err = errno; 220538032Speter 220638032Speter sm_syslog(LOG_ALERT, NOQID, 220738032Speter "ownership change on %s failed: %s", 220890792Sgshapiro buf, sm_errstring(err)); 220938032Speter message("050 ownership change on %s failed: %s", 221090792Sgshapiro buf, sm_errstring(err)); 221138032Speter } 221290792Sgshapiro# else /* HASFCHOWN */ 221390792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 221490792Sgshapiro "no fchown(): cannot change ownership on %s", 221590792Sgshapiro map->map_file); 221690792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 221790792Sgshapiro map->map_file); 221864562Sgshapiro# endif /* HASFCHOWN */ 221938032Speter } 222038032Speter } 222138032Speter 222264562Sgshapiro map->map_db2 = (ARBPTR_T) db; 222364562Sgshapiro 222464562Sgshapiro /* 222564562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 222664562Sgshapiro ** as aliaswait() will call map_lookup() which requires 222764562Sgshapiro ** map_mtime to be set 222864562Sgshapiro */ 222964562Sgshapiro 223038032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 223138032Speter map->map_mtime = st.st_mtime; 223238032Speter 223338032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 223490792Sgshapiro !aliaswait(map, ".db", true)) 223590792Sgshapiro return false; 223690792Sgshapiro return true; 223738032Speter} 223838032Speter 223938032Speter 224038032Speter/* 224138032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 224238032Speter*/ 224338032Speter 224438032Speterchar * 224538032Speterdb_map_lookup(map, name, av, statp) 224638032Speter MAP *map; 224738032Speter char *name; 224838032Speter char **av; 224938032Speter int *statp; 225038032Speter{ 225138032Speter DBT key, val; 225238032Speter register DB *db = (DB *) map->map_db2; 225338032Speter int i; 225438032Speter int st; 225564562Sgshapiro int save_errno; 225638032Speter int fd; 225738032Speter struct stat stbuf; 225838032Speter char keybuf[MAXNAME + 1]; 225998121Sgshapiro char buf[MAXPATHLEN]; 226038032Speter 226164562Sgshapiro memset(&key, '\0', sizeof key); 226264562Sgshapiro memset(&val, '\0', sizeof val); 226338032Speter 226438032Speter if (tTd(38, 20)) 226590792Sgshapiro sm_dprintf("db_map_lookup(%s, %s)\n", 226638032Speter map->map_mname, name); 226738032Speter 226898121Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf) 226998121Sgshapiro { 227098121Sgshapiro errno = 0; 227198121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 227298121Sgshapiro syserr("map \"%s\": map file %s name too long", 227398121Sgshapiro map->map_mname, map->map_file); 227498121Sgshapiro return NULL; 227598121Sgshapiro } 227698121Sgshapiro i = strlen(buf); 227738032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 227838032Speter buf[i - 3] = '\0'; 227938032Speter 228038032Speter key.size = strlen(name); 228138032Speter if (key.size > sizeof keybuf - 1) 228238032Speter key.size = sizeof keybuf - 1; 228338032Speter key.data = keybuf; 228464562Sgshapiro memmove(keybuf, name, key.size); 228538032Speter keybuf[key.size] = '\0'; 228638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 228738032Speter makelower(keybuf); 228838032Speter lockdb: 228964562Sgshapiro# if DB_VERSION_MAJOR < 2 229038032Speter fd = db->fd(db); 229164562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 229238032Speter fd = -1; 229338032Speter errno = db->fd(db, &fd); 229464562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 229538032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 229638032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 229738032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 229838032Speter { 229938032Speter /* Reopen the database to sync the cache */ 230038032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 230138032Speter : O_RDONLY; 230238032Speter 230364562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 230464562Sgshapiro (void) lockfile(fd, buf, ".db", LOCK_UN); 230577349Sgshapiro map->map_mflags |= MF_CLOSING; 230638032Speter map->map_class->map_close(map); 230777349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 230838032Speter if (map->map_class->map_open(map, omode)) 230938032Speter { 231038032Speter map->map_mflags |= MF_OPEN; 231190792Sgshapiro map->map_pid = CurrentPid; 231238032Speter if ((omode && O_ACCMODE) == O_RDWR) 231338032Speter map->map_mflags |= MF_WRITABLE; 231438032Speter db = (DB *) map->map_db2; 231538032Speter goto lockdb; 231638032Speter } 231738032Speter else 231838032Speter { 231938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 232038032Speter { 232138032Speter extern MAPCLASS BogusMapClass; 232238032Speter 232338032Speter *statp = EX_TEMPFAIL; 232490792Sgshapiro map->map_orgclass = map->map_class; 232538032Speter map->map_class = &BogusMapClass; 232638032Speter map->map_mflags |= MF_OPEN; 232790792Sgshapiro map->map_pid = CurrentPid; 232838032Speter syserr("Cannot reopen DB database %s", 232938032Speter map->map_file); 233038032Speter } 233138032Speter return NULL; 233238032Speter } 233338032Speter } 233438032Speter 233538032Speter st = 1; 233638032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 233738032Speter { 233864562Sgshapiro# if DB_VERSION_MAJOR < 2 233938032Speter st = db->get(db, &key, &val, 0); 234064562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 234138032Speter errno = db->get(db, NULL, &key, &val, 0); 234238032Speter switch (errno) 234338032Speter { 234438032Speter case DB_NOTFOUND: 234538032Speter case DB_KEYEMPTY: 234638032Speter st = 1; 234738032Speter break; 234838032Speter 234938032Speter case 0: 235038032Speter st = 0; 235138032Speter break; 235238032Speter 235338032Speter default: 235438032Speter st = -1; 235538032Speter break; 235638032Speter } 235764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 235838032Speter if (st == 0) 235938032Speter map->map_mflags &= ~MF_TRY1NULL; 236038032Speter } 236138032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 236238032Speter { 236338032Speter key.size++; 236464562Sgshapiro# if DB_VERSION_MAJOR < 2 236538032Speter st = db->get(db, &key, &val, 0); 236664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 236738032Speter errno = db->get(db, NULL, &key, &val, 0); 236838032Speter switch (errno) 236938032Speter { 237038032Speter case DB_NOTFOUND: 237138032Speter case DB_KEYEMPTY: 237238032Speter st = 1; 237338032Speter break; 237438032Speter 237538032Speter case 0: 237638032Speter st = 0; 237738032Speter break; 237838032Speter 237938032Speter default: 238038032Speter st = -1; 238138032Speter break; 238238032Speter } 238364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 238438032Speter if (st == 0) 238538032Speter map->map_mflags &= ~MF_TRY0NULL; 238638032Speter } 238764562Sgshapiro save_errno = errno; 238838032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 238938032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 239038032Speter if (st != 0) 239138032Speter { 239264562Sgshapiro errno = save_errno; 239338032Speter if (st < 0) 239438032Speter syserr("db_map_lookup: get (%s)", name); 239538032Speter return NULL; 239638032Speter } 239738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 239838032Speter return map_rewrite(map, name, strlen(name), NULL); 239938032Speter else 240038032Speter return map_rewrite(map, val.data, val.size, av); 240138032Speter} 240238032Speter 240338032Speter 240438032Speter/* 240538032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 240638032Speter*/ 240738032Speter 240838032Spetervoid 240938032Speterdb_map_store(map, lhs, rhs) 241038032Speter register MAP *map; 241138032Speter char *lhs; 241238032Speter char *rhs; 241338032Speter{ 241464562Sgshapiro int status; 241538032Speter DBT key; 241638032Speter DBT data; 241738032Speter register DB *db = map->map_db2; 241838032Speter char keybuf[MAXNAME + 1]; 241938032Speter 242064562Sgshapiro memset(&key, '\0', sizeof key); 242164562Sgshapiro memset(&data, '\0', sizeof data); 242238032Speter 242338032Speter if (tTd(38, 12)) 242490792Sgshapiro sm_dprintf("db_map_store(%s, %s, %s)\n", 242538032Speter map->map_mname, lhs, rhs); 242638032Speter 242738032Speter key.size = strlen(lhs); 242838032Speter key.data = lhs; 242938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 243038032Speter { 243138032Speter if (key.size > sizeof keybuf - 1) 243238032Speter key.size = sizeof keybuf - 1; 243364562Sgshapiro memmove(keybuf, key.data, key.size); 243438032Speter keybuf[key.size] = '\0'; 243538032Speter makelower(keybuf); 243638032Speter key.data = keybuf; 243738032Speter } 243838032Speter 243938032Speter data.size = strlen(rhs); 244038032Speter data.data = rhs; 244138032Speter 244238032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 244338032Speter { 244438032Speter key.size++; 244538032Speter data.size++; 244638032Speter } 244738032Speter 244864562Sgshapiro# if DB_VERSION_MAJOR < 2 244964562Sgshapiro status = db->put(db, &key, &data, R_NOOVERWRITE); 245064562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 245138032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 245238032Speter switch (errno) 245338032Speter { 245438032Speter case DB_KEYEXIST: 245564562Sgshapiro status = 1; 245638032Speter break; 245738032Speter 245838032Speter case 0: 245964562Sgshapiro status = 0; 246038032Speter break; 246138032Speter 246238032Speter default: 246364562Sgshapiro status = -1; 246438032Speter break; 246538032Speter } 246664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 246764562Sgshapiro if (status > 0) 246838032Speter { 246938032Speter if (!bitset(MF_APPEND, map->map_mflags)) 247038032Speter message("050 Warning: duplicate alias name %s", lhs); 247138032Speter else 247238032Speter { 247338032Speter static char *buf = NULL; 247438032Speter static int bufsiz = 0; 247538032Speter DBT old; 247638032Speter 247764562Sgshapiro memset(&old, '\0', sizeof old); 247838032Speter 247964562Sgshapiro old.data = db_map_lookup(map, key.data, 248090792Sgshapiro (char **) NULL, &status); 248138032Speter if (old.data != NULL) 248238032Speter { 248338032Speter old.size = strlen(old.data); 248490792Sgshapiro if (data.size + old.size + 2 > (size_t) bufsiz) 248538032Speter { 248638032Speter if (buf != NULL) 248777349Sgshapiro sm_free(buf); 248838032Speter bufsiz = data.size + old.size + 2; 248990792Sgshapiro buf = sm_pmalloc_x(bufsiz); 249038032Speter } 249190792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 249290792Sgshapiro (char *) data.data, ",", 249390792Sgshapiro (char *) old.data); 249438032Speter data.size = data.size + old.size + 1; 249538032Speter data.data = buf; 249638032Speter if (tTd(38, 9)) 249790792Sgshapiro sm_dprintf("db_map_store append=%s\n", 249864562Sgshapiro (char *) data.data); 249938032Speter } 250038032Speter } 250164562Sgshapiro# if DB_VERSION_MAJOR < 2 250264562Sgshapiro status = db->put(db, &key, &data, 0); 250364562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 250464562Sgshapiro status = errno = db->put(db, NULL, &key, &data, 0); 250564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 250638032Speter } 250764562Sgshapiro if (status != 0) 250838032Speter syserr("readaliases: db put (%s)", lhs); 250938032Speter} 251038032Speter 251138032Speter 251238032Speter/* 251338032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 251438032Speter*/ 251538032Speter 251638032Spetervoid 251738032Speterdb_map_close(map) 251838032Speter MAP *map; 251938032Speter{ 252038032Speter register DB *db = map->map_db2; 252138032Speter 252238032Speter if (tTd(38, 9)) 252390792Sgshapiro sm_dprintf("db_map_close(%s, %s, %lx)\n", 252438032Speter map->map_mname, map->map_file, map->map_mflags); 252538032Speter 252638032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 252738032Speter { 252838032Speter /* write out the distinguished alias */ 252938032Speter db_map_store(map, "@", "@"); 253038032Speter } 253138032Speter 253238032Speter (void) db->sync(db, 0); 253338032Speter 253464562Sgshapiro# if !LOCK_ON_OPEN 253538032Speter if (map->map_lockfd >= 0) 253638032Speter (void) close(map->map_lockfd); 253764562Sgshapiro# endif /* !LOCK_ON_OPEN */ 253838032Speter 253964562Sgshapiro# if DB_VERSION_MAJOR < 2 254038032Speter if (db->close(db) != 0) 254164562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 254242575Speter /* 254342575Speter ** Berkeley DB can use internal shared memory 254442575Speter ** locking for its memory pool. Closing a map 254542575Speter ** opened by another process will interfere 254642575Speter ** with the shared memory and locks of the parent 254742575Speter ** process leaving things in a bad state. 254843730Speter */ 254943730Speter 255043730Speter /* 255142575Speter ** If this map was not opened by the current 255243730Speter ** process, do not close the map but recover 255342575Speter ** the file descriptor. 255442575Speter */ 255590792Sgshapiro 255690792Sgshapiro if (map->map_pid != CurrentPid) 255742575Speter { 255842575Speter int fd = -1; 255942575Speter 256042575Speter errno = db->fd(db, &fd); 256142575Speter if (fd >= 0) 256242575Speter (void) close(fd); 256342575Speter return; 256442575Speter } 256542575Speter 256638032Speter if ((errno = db->close(db, 0)) != 0) 256764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 256842575Speter syserr("db_map_close(%s, %s, %lx): db close failure", 256942575Speter map->map_mname, map->map_file, map->map_mflags); 257038032Speter} 257164562Sgshapiro#endif /* NEWDB */ 257290792Sgshapiro/* 257338032Speter** NIS Modules 257438032Speter*/ 257538032Speter 257690792Sgshapiro#if NIS 257738032Speter 257838032Speter# ifndef YPERR_BUSY 257938032Speter# define YPERR_BUSY 16 258064562Sgshapiro# endif /* ! YPERR_BUSY */ 258138032Speter 258238032Speter/* 258338032Speter** NIS_MAP_OPEN -- open DBM map 258438032Speter*/ 258538032Speter 258638032Speterbool 258738032Speternis_map_open(map, mode) 258838032Speter MAP *map; 258938032Speter int mode; 259038032Speter{ 259138032Speter int yperr; 259238032Speter register char *p; 259338032Speter auto char *vp; 259438032Speter auto int vsize; 259538032Speter 259638032Speter if (tTd(38, 2)) 259790792Sgshapiro sm_dprintf("nis_map_open(%s, %s, %d)\n", 259838032Speter map->map_mname, map->map_file, mode); 259938032Speter 260038032Speter mode &= O_ACCMODE; 260138032Speter if (mode != O_RDONLY) 260238032Speter { 260338032Speter /* issue a pseudo-error message */ 260490792Sgshapiro errno = SM_EMAPCANTWRITE; 260590792Sgshapiro return false; 260638032Speter } 260738032Speter 260838032Speter p = strchr(map->map_file, '@'); 260938032Speter if (p != NULL) 261038032Speter { 261138032Speter *p++ = '\0'; 261238032Speter if (*p != '\0') 261338032Speter map->map_domain = p; 261438032Speter } 261538032Speter 261638032Speter if (*map->map_file == '\0') 261738032Speter map->map_file = "mail.aliases"; 261838032Speter 261938032Speter if (map->map_domain == NULL) 262038032Speter { 262138032Speter yperr = yp_get_default_domain(&map->map_domain); 262238032Speter if (yperr != 0) 262338032Speter { 262438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 262594334Sgshapiro syserr("451 4.3.5 NIS map %s specified, but NIS not running", 262664562Sgshapiro map->map_file); 262790792Sgshapiro return false; 262838032Speter } 262938032Speter } 263038032Speter 263138032Speter /* check to see if this map actually exists */ 263264562Sgshapiro vp = NULL; 263338032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 263438032Speter &vp, &vsize); 263538032Speter if (tTd(38, 10)) 263690792Sgshapiro sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 263738032Speter map->map_domain, map->map_file, yperr_string(yperr)); 263864562Sgshapiro if (vp != NULL) 263977349Sgshapiro sm_free(vp); 264064562Sgshapiro 264138032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 264238032Speter { 264338032Speter /* 264438032Speter ** We ought to be calling aliaswait() here if this is an 264538032Speter ** alias file, but powerful HP-UX NIS servers apparently 264638032Speter ** don't insert the @:@ token into the alias map when it 264738032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 264838032Speter */ 264938032Speter 265064562Sgshapiro# if 0 265138032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 265290792Sgshapiro aliaswait(map, NULL, true)) 265364562Sgshapiro# endif /* 0 */ 265490792Sgshapiro return true; 265538032Speter } 265638032Speter 265738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 265838032Speter { 265994334Sgshapiro syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s", 266038032Speter map->map_file, map->map_domain, yperr_string(yperr)); 266138032Speter } 266238032Speter 266390792Sgshapiro return false; 266438032Speter} 266538032Speter 266638032Speter 266738032Speter/* 266838032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 266938032Speter*/ 267038032Speter 267138032Speter/* ARGSUSED3 */ 267238032Speterchar * 267338032Speternis_map_lookup(map, name, av, statp) 267438032Speter MAP *map; 267538032Speter char *name; 267638032Speter char **av; 267738032Speter int *statp; 267838032Speter{ 267938032Speter char *vp; 268038032Speter auto int vsize; 268138032Speter int buflen; 268238032Speter int yperr; 268338032Speter char keybuf[MAXNAME + 1]; 268490792Sgshapiro char *SM_NONVOLATILE result = NULL; 268538032Speter 268638032Speter if (tTd(38, 20)) 268790792Sgshapiro sm_dprintf("nis_map_lookup(%s, %s)\n", 268838032Speter map->map_mname, name); 268938032Speter 269038032Speter buflen = strlen(name); 269138032Speter if (buflen > sizeof keybuf - 1) 269238032Speter buflen = sizeof keybuf - 1; 269364562Sgshapiro memmove(keybuf, name, buflen); 269438032Speter keybuf[buflen] = '\0'; 269538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 269638032Speter makelower(keybuf); 269738032Speter yperr = YPERR_KEY; 269864562Sgshapiro vp = NULL; 269938032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 270038032Speter { 270138032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 270238032Speter &vp, &vsize); 270338032Speter if (yperr == 0) 270438032Speter map->map_mflags &= ~MF_TRY1NULL; 270538032Speter } 270638032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 270738032Speter { 270890792Sgshapiro SM_FREE_CLR(vp); 270938032Speter buflen++; 271038032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 271138032Speter &vp, &vsize); 271238032Speter if (yperr == 0) 271338032Speter map->map_mflags &= ~MF_TRY0NULL; 271438032Speter } 271538032Speter if (yperr != 0) 271638032Speter { 271738032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 271838032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 271964562Sgshapiro if (vp != NULL) 272077349Sgshapiro sm_free(vp); 272138032Speter return NULL; 272238032Speter } 272390792Sgshapiro SM_TRY 272490792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 272590792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 272690792Sgshapiro else 272790792Sgshapiro result = map_rewrite(map, vp, vsize, av); 272890792Sgshapiro SM_FINALLY 272964562Sgshapiro if (vp != NULL) 273077349Sgshapiro sm_free(vp); 273190792Sgshapiro SM_END_TRY 273290792Sgshapiro return result; 273338032Speter} 273438032Speter 273538032Speter 273638032Speter/* 273738032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 273838032Speter*/ 273938032Speter 274064562Sgshapirostatic bool 274138032Speternis_getcanonname(name, hbsize, statp) 274238032Speter char *name; 274338032Speter int hbsize; 274438032Speter int *statp; 274538032Speter{ 274638032Speter char *vp; 274738032Speter auto int vsize; 274838032Speter int keylen; 274938032Speter int yperr; 275090792Sgshapiro static bool try0null = true; 275190792Sgshapiro static bool try1null = true; 275238032Speter static char *yp_domain = NULL; 275338032Speter char host_record[MAXLINE]; 275438032Speter char cbuf[MAXNAME]; 275538032Speter char nbuf[MAXNAME + 1]; 275638032Speter 275738032Speter if (tTd(38, 20)) 275890792Sgshapiro sm_dprintf("nis_getcanonname(%s)\n", name); 275938032Speter 276090792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 276138032Speter { 276238032Speter *statp = EX_UNAVAILABLE; 276390792Sgshapiro return false; 276438032Speter } 276573188Sgshapiro (void) shorten_hostname(nbuf); 276638032Speter keylen = strlen(nbuf); 276738032Speter 276838032Speter if (yp_domain == NULL) 276964562Sgshapiro (void) yp_get_default_domain(&yp_domain); 277038032Speter makelower(nbuf); 277138032Speter yperr = YPERR_KEY; 277264562Sgshapiro vp = NULL; 277338032Speter if (try0null) 277438032Speter { 277538032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 277638032Speter &vp, &vsize); 277738032Speter if (yperr == 0) 277890792Sgshapiro try1null = false; 277938032Speter } 278038032Speter if (yperr == YPERR_KEY && try1null) 278138032Speter { 278290792Sgshapiro SM_FREE_CLR(vp); 278338032Speter keylen++; 278438032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 278538032Speter &vp, &vsize); 278638032Speter if (yperr == 0) 278790792Sgshapiro try0null = false; 278838032Speter } 278938032Speter if (yperr != 0) 279038032Speter { 279138032Speter if (yperr == YPERR_KEY) 279238032Speter *statp = EX_NOHOST; 279338032Speter else if (yperr == YPERR_BUSY) 279438032Speter *statp = EX_TEMPFAIL; 279538032Speter else 279638032Speter *statp = EX_UNAVAILABLE; 279764562Sgshapiro if (vp != NULL) 279877349Sgshapiro sm_free(vp); 279990792Sgshapiro return false; 280038032Speter } 280190792Sgshapiro (void) sm_strlcpy(host_record, vp, sizeof host_record); 280277349Sgshapiro sm_free(vp); 280338032Speter if (tTd(38, 44)) 280490792Sgshapiro sm_dprintf("got record `%s'\n", host_record); 280590792Sgshapiro vp = strpbrk(host_record, "#\n"); 280690792Sgshapiro if (vp != NULL) 280790792Sgshapiro *vp = '\0'; 280873188Sgshapiro if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf)) 280938032Speter { 281038032Speter /* this should not happen, but.... */ 281138032Speter *statp = EX_NOHOST; 281290792Sgshapiro return false; 281338032Speter } 281490792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 281538032Speter { 281638032Speter *statp = EX_UNAVAILABLE; 281790792Sgshapiro return false; 281838032Speter } 281938032Speter *statp = EX_OK; 282090792Sgshapiro return true; 282138032Speter} 282238032Speter 282364562Sgshapiro#endif /* NIS */ 282490792Sgshapiro/* 282538032Speter** NISPLUS Modules 282638032Speter** 282738032Speter** This code donated by Sun Microsystems. 282838032Speter*/ 282938032Speter 283090792Sgshapiro#if NISPLUS 283138032Speter 283264562Sgshapiro# undef NIS /* symbol conflict in nis.h */ 283364562Sgshapiro# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 283464562Sgshapiro# include <rpcsvc/nis.h> 283564562Sgshapiro# include <rpcsvc/nislib.h> 283638032Speter 283764562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 283864562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 283964562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 284064562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 284138032Speter 284238032Speter/* 284338032Speter** NISPLUS_MAP_OPEN -- open nisplus table 284438032Speter*/ 284538032Speter 284638032Speterbool 284738032Speternisplus_map_open(map, mode) 284838032Speter MAP *map; 284938032Speter int mode; 285038032Speter{ 285138032Speter nis_result *res = NULL; 285238032Speter int retry_cnt, max_col, i; 285338032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 285438032Speter 285538032Speter if (tTd(38, 2)) 285690792Sgshapiro sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 285738032Speter map->map_mname, map->map_file, mode); 285838032Speter 285938032Speter mode &= O_ACCMODE; 286038032Speter if (mode != O_RDONLY) 286138032Speter { 286238032Speter errno = EPERM; 286390792Sgshapiro return false; 286438032Speter } 286538032Speter 286638032Speter if (*map->map_file == '\0') 286738032Speter map->map_file = "mail_aliases.org_dir"; 286838032Speter 286938032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 287038032Speter { 287138032Speter /* set default NISPLUS Domain to $m */ 287238032Speter map->map_domain = newstr(nisplus_default_domain()); 287338032Speter if (tTd(38, 2)) 287490792Sgshapiro sm_dprintf("nisplus_map_open(%s): using domain %s\n", 287564562Sgshapiro map->map_file, map->map_domain); 287638032Speter } 287738032Speter if (!PARTIAL_NAME(map->map_file)) 287838032Speter { 287938032Speter map->map_domain = newstr(""); 288090792Sgshapiro (void) sm_strlcpy(qbuf, map->map_file, sizeof qbuf); 288138032Speter } 288238032Speter else 288338032Speter { 288438032Speter /* check to see if this map actually exists */ 288590792Sgshapiro (void) sm_strlcpyn(qbuf, sizeof qbuf, 3, 288690792Sgshapiro map->map_file, ".", map->map_domain); 288738032Speter } 288838032Speter 288938032Speter retry_cnt = 0; 289038032Speter while (res == NULL || res->status != NIS_SUCCESS) 289138032Speter { 289238032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 289338032Speter switch (res->status) 289438032Speter { 289538032Speter case NIS_SUCCESS: 289638032Speter break; 289738032Speter 289838032Speter case NIS_TRYAGAIN: 289938032Speter case NIS_RPCERROR: 290038032Speter case NIS_NAMEUNREACHABLE: 290138032Speter if (retry_cnt++ > 4) 290238032Speter { 290338032Speter errno = EAGAIN; 290490792Sgshapiro return false; 290538032Speter } 290638032Speter /* try not to overwhelm hosed server */ 290738032Speter sleep(2); 290838032Speter break; 290938032Speter 291038032Speter default: /* all other nisplus errors */ 291164562Sgshapiro# if 0 291238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 291394334Sgshapiro syserr("451 4.3.5 Cannot find table %s.%s: %s", 291438032Speter map->map_file, map->map_domain, 291538032Speter nis_sperrno(res->status)); 291664562Sgshapiro# endif /* 0 */ 291738032Speter errno = EAGAIN; 291890792Sgshapiro return false; 291938032Speter } 292038032Speter } 292138032Speter 292238032Speter if (NIS_RES_NUMOBJ(res) != 1 || 292338032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 292438032Speter { 292538032Speter if (tTd(38, 10)) 292690792Sgshapiro sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 292764562Sgshapiro# if 0 292838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 292994334Sgshapiro syserr("451 4.3.5 %s.%s: %s is not a table", 293038032Speter map->map_file, map->map_domain, 293138032Speter nis_sperrno(res->status)); 293264562Sgshapiro# endif /* 0 */ 293338032Speter errno = EBADF; 293490792Sgshapiro return false; 293538032Speter } 293638032Speter /* default key column is column 0 */ 293738032Speter if (map->map_keycolnm == NULL) 293838032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 293938032Speter 294038032Speter max_col = COL_MAX(res); 294138032Speter 294238032Speter /* verify the key column exist */ 294390792Sgshapiro for (i = 0; i < max_col; i++) 294438032Speter { 294564562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 294638032Speter break; 294738032Speter } 294838032Speter if (i == max_col) 294938032Speter { 295038032Speter if (tTd(38, 2)) 295190792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 295238032Speter map->map_file, map->map_keycolnm); 295338032Speter errno = ENOENT; 295490792Sgshapiro return false; 295538032Speter } 295638032Speter 295738032Speter /* default value column is the last column */ 295838032Speter if (map->map_valcolnm == NULL) 295938032Speter { 296038032Speter map->map_valcolno = max_col - 1; 296190792Sgshapiro return true; 296238032Speter } 296338032Speter 296464562Sgshapiro for (i = 0; i< max_col; i++) 296538032Speter { 296638032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 296738032Speter { 296838032Speter map->map_valcolno = i; 296990792Sgshapiro return true; 297038032Speter } 297138032Speter } 297238032Speter 297338032Speter if (tTd(38, 2)) 297490792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 297564562Sgshapiro map->map_file, map->map_keycolnm); 297638032Speter errno = ENOENT; 297790792Sgshapiro return false; 297838032Speter} 297938032Speter 298038032Speter 298138032Speter/* 298238032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 298338032Speter*/ 298438032Speter 298538032Speterchar * 298638032Speternisplus_map_lookup(map, name, av, statp) 298738032Speter MAP *map; 298838032Speter char *name; 298938032Speter char **av; 299038032Speter int *statp; 299138032Speter{ 299238032Speter char *p; 299338032Speter auto int vsize; 299438032Speter char *skp; 299538032Speter int skleft; 299638032Speter char search_key[MAXNAME + 4]; 299738032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 299838032Speter nis_result *result; 299938032Speter 300038032Speter if (tTd(38, 20)) 300190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s, %s)\n", 300238032Speter map->map_mname, name); 300338032Speter 300438032Speter if (!bitset(MF_OPEN, map->map_mflags)) 300538032Speter { 300638032Speter if (nisplus_map_open(map, O_RDONLY)) 300742575Speter { 300838032Speter map->map_mflags |= MF_OPEN; 300990792Sgshapiro map->map_pid = CurrentPid; 301042575Speter } 301138032Speter else 301238032Speter { 301338032Speter *statp = EX_UNAVAILABLE; 301438032Speter return NULL; 301538032Speter } 301638032Speter } 301738032Speter 301838032Speter /* 301938032Speter ** Copy the name to the key buffer, escaping double quote characters 302038032Speter ** by doubling them and quoting "]" and "," to avoid having the 302138032Speter ** NIS+ parser choke on them. 302238032Speter */ 302338032Speter 302438032Speter skleft = sizeof search_key - 4; 302538032Speter skp = search_key; 302638032Speter for (p = name; *p != '\0' && skleft > 0; p++) 302738032Speter { 302838032Speter switch (*p) 302938032Speter { 303038032Speter case ']': 303138032Speter case ',': 303238032Speter /* quote the character */ 303338032Speter *skp++ = '"'; 303438032Speter *skp++ = *p; 303538032Speter *skp++ = '"'; 303638032Speter skleft -= 3; 303738032Speter break; 303838032Speter 303938032Speter case '"': 304038032Speter /* double the quote */ 304138032Speter *skp++ = '"'; 304238032Speter skleft--; 304364562Sgshapiro /* FALLTHROUGH */ 304438032Speter 304538032Speter default: 304638032Speter *skp++ = *p; 304738032Speter skleft--; 304838032Speter break; 304938032Speter } 305038032Speter } 305138032Speter *skp = '\0'; 305238032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 305338032Speter makelower(search_key); 305438032Speter 305538032Speter /* construct the query */ 305638032Speter if (PARTIAL_NAME(map->map_file)) 305790792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", 305838032Speter map->map_keycolnm, search_key, map->map_file, 305938032Speter map->map_domain); 306038032Speter else 306190792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", 306238032Speter map->map_keycolnm, search_key, map->map_file); 306338032Speter 306438032Speter if (tTd(38, 20)) 306590792Sgshapiro sm_dprintf("qbuf=%s\n", qbuf); 306638032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 306738032Speter if (result->status == NIS_SUCCESS) 306838032Speter { 306938032Speter int count; 307038032Speter char *str; 307138032Speter 307238032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 307338032Speter { 307438032Speter if (LogLevel > 10) 307538032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 307664562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 307764562Sgshapiro map->map_file, count); 307838032Speter 307938032Speter /* ignore second entry */ 308038032Speter if (tTd(38, 20)) 308190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 308238032Speter name, count); 308338032Speter } 308438032Speter 308538032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 308638032Speter /* set the length of the result */ 308738032Speter if (p == NULL) 308838032Speter p = ""; 308938032Speter vsize = strlen(p); 309038032Speter if (tTd(38, 20)) 309190792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), found %s\n", 309238032Speter name, p); 309338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 309438032Speter str = map_rewrite(map, name, strlen(name), NULL); 309538032Speter else 309638032Speter str = map_rewrite(map, p, vsize, av); 309738032Speter nis_freeresult(result); 309838032Speter *statp = EX_OK; 309938032Speter return str; 310038032Speter } 310138032Speter else 310238032Speter { 310338032Speter if (result->status == NIS_NOTFOUND) 310438032Speter *statp = EX_NOTFOUND; 310538032Speter else if (result->status == NIS_TRYAGAIN) 310638032Speter *statp = EX_TEMPFAIL; 310738032Speter else 310838032Speter { 310938032Speter *statp = EX_UNAVAILABLE; 311038032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 311138032Speter } 311238032Speter } 311338032Speter if (tTd(38, 20)) 311490792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 311538032Speter nis_freeresult(result); 311638032Speter return NULL; 311738032Speter} 311838032Speter 311938032Speter 312038032Speter 312138032Speter/* 312238032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 312338032Speter*/ 312438032Speter 312564562Sgshapirostatic bool 312638032Speternisplus_getcanonname(name, hbsize, statp) 312738032Speter char *name; 312838032Speter int hbsize; 312938032Speter int *statp; 313038032Speter{ 313138032Speter char *vp; 313238032Speter auto int vsize; 313338032Speter nis_result *result; 313438032Speter char *p; 313538032Speter char nbuf[MAXNAME + 1]; 313638032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 313738032Speter 313890792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 313938032Speter { 314038032Speter *statp = EX_UNAVAILABLE; 314190792Sgshapiro return false; 314238032Speter } 314373188Sgshapiro (void) shorten_hostname(nbuf); 314438032Speter 314538032Speter p = strchr(nbuf, '.'); 314638032Speter if (p == NULL) 314738032Speter { 314838032Speter /* single token */ 314990792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, 315090792Sgshapiro "[name=%s],hosts.org_dir", nbuf); 315138032Speter } 315238032Speter else if (p[1] != '\0') 315338032Speter { 315438032Speter /* multi token -- take only first token in nbuf */ 315538032Speter *p = '\0'; 315690792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, 315790792Sgshapiro "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 315838032Speter } 315938032Speter else 316038032Speter { 316138032Speter *statp = EX_NOHOST; 316290792Sgshapiro return false; 316338032Speter } 316438032Speter 316538032Speter if (tTd(38, 20)) 316694334Sgshapiro sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 316790792Sgshapiro name, qbuf); 316838032Speter 316938032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 317090792Sgshapiro NULL, NULL); 317138032Speter 317238032Speter if (result->status == NIS_SUCCESS) 317338032Speter { 317438032Speter int count; 317538032Speter char *domain; 317638032Speter 317738032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 317838032Speter { 317938032Speter if (LogLevel > 10) 318038032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 318164562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 318264562Sgshapiro count); 318338032Speter 318438032Speter /* ignore second entry */ 318538032Speter if (tTd(38, 20)) 318694334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 318790792Sgshapiro name, count); 318838032Speter } 318938032Speter 319038032Speter if (tTd(38, 20)) 319194334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 319290792Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 319338032Speter 319438032Speter 319538032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 319638032Speter vsize = strlen(vp); 319738032Speter if (tTd(38, 20)) 319890792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found %s\n", 319990792Sgshapiro name, vp); 320038032Speter if (strchr(vp, '.') != NULL) 320138032Speter { 320238032Speter domain = ""; 320338032Speter } 320438032Speter else 320538032Speter { 320638032Speter domain = macvalue('m', CurEnv); 320738032Speter if (domain == NULL) 320838032Speter domain = ""; 320938032Speter } 321038032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 321138032Speter { 321238032Speter if (domain[0] == '\0') 321390792Sgshapiro (void) sm_strlcpy(name, vp, hbsize); 321438032Speter else 321590792Sgshapiro (void) sm_snprintf(name, hbsize, 321690792Sgshapiro "%s.%s", vp, domain); 321738032Speter *statp = EX_OK; 321838032Speter } 321938032Speter else 322038032Speter *statp = EX_NOHOST; 322138032Speter nis_freeresult(result); 322290792Sgshapiro return true; 322338032Speter } 322438032Speter else 322538032Speter { 322638032Speter if (result->status == NIS_NOTFOUND) 322738032Speter *statp = EX_NOHOST; 322838032Speter else if (result->status == NIS_TRYAGAIN) 322938032Speter *statp = EX_TEMPFAIL; 323038032Speter else 323138032Speter *statp = EX_UNAVAILABLE; 323238032Speter } 323338032Speter if (tTd(38, 20)) 323490792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 323590792Sgshapiro name, result->status, *statp); 323638032Speter nis_freeresult(result); 323790792Sgshapiro return false; 323838032Speter} 323938032Speter 324038032Speterchar * 324138032Speternisplus_default_domain() 324238032Speter{ 324338032Speter static char default_domain[MAXNAME + 1] = ""; 324438032Speter char *p; 324538032Speter 324638032Speter if (default_domain[0] != '\0') 324764562Sgshapiro return default_domain; 324838032Speter 324938032Speter p = nis_local_directory(); 325090792Sgshapiro (void) sm_strlcpy(default_domain, p, sizeof default_domain); 325138032Speter return default_domain; 325238032Speter} 325338032Speter 325438032Speter#endif /* NISPLUS */ 325590792Sgshapiro/* 325638032Speter** LDAP Modules 325738032Speter*/ 325838032Speter 325964562Sgshapiro/* 326064562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 326164562Sgshapiro*/ 326264562Sgshapiro 326364562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 326464562Sgshapiro 326590792Sgshapiro# if PH_MAP 326664562Sgshapiro# define ph_map_dequote ldapmap_dequote 326764562Sgshapiro# endif /* PH_MAP */ 326864562Sgshapiro 326990792Sgshapirostatic char *ldapmap_dequote __P((char *)); 327090792Sgshapiro 327190792Sgshapirostatic char * 327264562Sgshapiroldapmap_dequote(str) 327364562Sgshapiro char *str; 327464562Sgshapiro{ 327564562Sgshapiro char *p; 327664562Sgshapiro char *start; 327764562Sgshapiro 327864562Sgshapiro if (str == NULL) 327964562Sgshapiro return NULL; 328064562Sgshapiro 328164562Sgshapiro p = str; 328264562Sgshapiro if (*p == '"') 328364562Sgshapiro { 328464562Sgshapiro /* Should probably swallow initial whitespace here */ 328564562Sgshapiro start = ++p; 328664562Sgshapiro } 328764562Sgshapiro else 328864562Sgshapiro return str; 328964562Sgshapiro while (*p != '"' && *p != '\0') 329064562Sgshapiro p++; 329164562Sgshapiro if (*p != '\0') 329264562Sgshapiro *p = '\0'; 329364562Sgshapiro return start; 329464562Sgshapiro} 329564562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 329664562Sgshapiro 329790792Sgshapiro#if LDAPMAP 329838032Speter 329990792Sgshapirostatic SM_LDAP_STRUCT *LDAPDefaults = NULL; 330038032Speter 330138032Speter/* 330264562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 330338032Speter** 330464562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 330564562Sgshapiro** single server connection to a host (with the same host, port, 330664562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 330738032Speter*/ 330838032Speter 330938032Speterbool 331064562Sgshapiroldapmap_open(map, mode) 331138032Speter MAP *map; 331238032Speter int mode; 331338032Speter{ 331490792Sgshapiro SM_LDAP_STRUCT *lmap; 331564562Sgshapiro STAB *s; 3316132943Sgshapiro char *id; 331764562Sgshapiro 331838032Speter if (tTd(38, 2)) 331990792Sgshapiro sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 332038032Speter 332138032Speter mode &= O_ACCMODE; 332264562Sgshapiro 332364562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 332438032Speter if (mode != O_RDONLY) 332538032Speter { 332638032Speter /* issue a pseudo-error message */ 332790792Sgshapiro errno = SM_EMAPCANTWRITE; 332890792Sgshapiro return false; 332938032Speter } 333064562Sgshapiro 333190792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 333264562Sgshapiro 333364562Sgshapiro s = ldapmap_findconn(lmap); 333477349Sgshapiro if (s->s_lmap != NULL) 333564562Sgshapiro { 333664562Sgshapiro /* Already have a connection open to this LDAP server */ 333790792Sgshapiro lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 333890792Sgshapiro lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 333977349Sgshapiro 334077349Sgshapiro /* Add this map as head of linked list */ 334177349Sgshapiro lmap->ldap_next = s->s_lmap; 334277349Sgshapiro s->s_lmap = map; 334377349Sgshapiro 334466494Sgshapiro if (tTd(38, 2)) 334590792Sgshapiro sm_dprintf("using cached connection\n"); 334690792Sgshapiro return true; 334764562Sgshapiro } 334864562Sgshapiro 334966494Sgshapiro if (tTd(38, 2)) 335090792Sgshapiro sm_dprintf("opening new connection\n"); 335166494Sgshapiro 3352132943Sgshapiro if (lmap->ldap_host != NULL) 3353132943Sgshapiro id = lmap->ldap_host; 3354132943Sgshapiro else if (lmap->ldap_uri != NULL) 3355132943Sgshapiro id = lmap->ldap_uri; 3356132943Sgshapiro else 3357132943Sgshapiro id = "localhost"; 3358132943Sgshapiro 335964562Sgshapiro /* No connection yet, connect */ 336090792Sgshapiro if (!sm_ldap_start(map->map_mname, lmap)) 336138032Speter { 336290792Sgshapiro if (errno == ETIMEDOUT) 336338032Speter { 336438032Speter if (LogLevel > 1) 336538032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 336664562Sgshapiro "timeout conning to LDAP server %.100s", 3367132943Sgshapiro id); 336838032Speter } 336938032Speter 337038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 337138032Speter { 337264562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 3373132943Sgshapiro { 337464562Sgshapiro syserr("%s failed to %s in map %s", 337564562Sgshapiro# if USE_LDAP_INIT 337690792Sgshapiro "ldap_init/ldap_bind", 337764562Sgshapiro# else /* USE_LDAP_INIT */ 337864562Sgshapiro "ldap_open", 337964562Sgshapiro# endif /* USE_LDAP_INIT */ 3380132943Sgshapiro id, map->map_mname); 3381132943Sgshapiro } 338264562Sgshapiro else 3383132943Sgshapiro { 338494334Sgshapiro syserr("451 4.3.5 %s failed to %s in map %s", 338564562Sgshapiro# if USE_LDAP_INIT 338690792Sgshapiro "ldap_init/ldap_bind", 338764562Sgshapiro# else /* USE_LDAP_INIT */ 338864562Sgshapiro "ldap_open", 338964562Sgshapiro# endif /* USE_LDAP_INIT */ 3390132943Sgshapiro id, map->map_mname); 3391132943Sgshapiro } 339238032Speter } 339390792Sgshapiro return false; 339438032Speter } 339538032Speter 339690792Sgshapiro /* Save connection for reuse */ 339790792Sgshapiro s->s_lmap = map; 339890792Sgshapiro return true; 339938032Speter} 340038032Speter 340138032Speter/* 340264562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 340338032Speter*/ 340438032Speter 340538032Spetervoid 340664562Sgshapiroldapmap_close(map) 340738032Speter MAP *map; 340838032Speter{ 340990792Sgshapiro SM_LDAP_STRUCT *lmap; 341064562Sgshapiro STAB *s; 341143730Speter 341264562Sgshapiro if (tTd(38, 2)) 341390792Sgshapiro sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 341464562Sgshapiro 341590792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 341664562Sgshapiro 341764562Sgshapiro /* Check if already closed */ 341864562Sgshapiro if (lmap->ldap_ld == NULL) 341964562Sgshapiro return; 342064562Sgshapiro 342177349Sgshapiro /* Close the LDAP connection */ 342290792Sgshapiro sm_ldap_close(lmap); 342377349Sgshapiro 342477349Sgshapiro /* Mark all the maps that share the connection as closed */ 342564562Sgshapiro s = ldapmap_findconn(lmap); 342664562Sgshapiro 342777349Sgshapiro while (s->s_lmap != NULL) 342877349Sgshapiro { 342977349Sgshapiro MAP *smap = s->s_lmap; 343064562Sgshapiro 343177349Sgshapiro if (tTd(38, 2) && smap != map) 343290792Sgshapiro sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 343390792Sgshapiro map->map_mname, smap->map_mname); 343477349Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 343590792Sgshapiro lmap = (SM_LDAP_STRUCT *) smap->map_db1; 343664562Sgshapiro lmap->ldap_ld = NULL; 343777349Sgshapiro s->s_lmap = lmap->ldap_next; 343877349Sgshapiro lmap->ldap_next = NULL; 343943730Speter } 344038032Speter} 344138032Speter 344264562Sgshapiro# ifdef SUNET_ID 344343730Speter/* 344490792Sgshapiro** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 344542575Speter** This only makes sense at Stanford University. 344638032Speter*/ 344738032Speter 344890792Sgshapirostatic char * 344938032Spetersunet_id_hash(str) 345038032Speter char *str; 345138032Speter{ 345238032Speter char *p, *p_last; 345338032Speter 345438032Speter p = str; 345538032Speter p_last = p; 345638032Speter while (*p != '\0') 345738032Speter { 345838032Speter if (islower(*p) || isdigit(*p)) 345938032Speter { 346038032Speter *p_last = *p; 346138032Speter p_last++; 346238032Speter } 346338032Speter else if (isupper(*p)) 346438032Speter { 346538032Speter *p_last = tolower(*p); 346638032Speter p_last++; 346738032Speter } 346838032Speter ++p; 346938032Speter } 347038032Speter if (*p_last != '\0') 347138032Speter *p_last = '\0'; 347264562Sgshapiro return str; 347338032Speter} 347464562Sgshapiro# endif /* SUNET_ID */ 347538032Speter 347638032Speter/* 347764562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 347838032Speter*/ 347938032Speter 348038032Speterchar * 348164562Sgshapiroldapmap_lookup(map, name, av, statp) 348238032Speter MAP *map; 348338032Speter char *name; 348438032Speter char **av; 348538032Speter int *statp; 348638032Speter{ 3487132943Sgshapiro int flags; 348894334Sgshapiro int plen = 0; 348994334Sgshapiro int psize = 0; 349064562Sgshapiro int msgid; 349190792Sgshapiro int save_errno; 349290792Sgshapiro char *vp, *p; 349364562Sgshapiro char *result = NULL; 3494132943Sgshapiro SM_RPOOL_T *rpool; 349590792Sgshapiro SM_LDAP_STRUCT *lmap = NULL; 349638032Speter char keybuf[MAXNAME + 1]; 349738032Speter 349838032Speter if (tTd(38, 20)) 349990792Sgshapiro sm_dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); 350038032Speter 350138032Speter /* Get ldap struct pointer from map */ 350290792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 350390792Sgshapiro sm_ldap_setopts(lmap->ldap_ld, lmap); 350438032Speter 350590792Sgshapiro (void) sm_strlcpy(keybuf, name, sizeof keybuf); 350638032Speter 350738032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 350864562Sgshapiro { 350964562Sgshapiro# ifdef SUNET_ID 351038032Speter sunet_id_hash(keybuf); 351164562Sgshapiro# else /* SUNET_ID */ 351238032Speter makelower(keybuf); 351364562Sgshapiro# endif /* SUNET_ID */ 351464562Sgshapiro } 351538032Speter 351690792Sgshapiro msgid = sm_ldap_search(lmap, keybuf); 351764562Sgshapiro if (msgid == -1) 351838032Speter { 351990792Sgshapiro errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 352077349Sgshapiro save_errno = errno; 352164562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 352238032Speter { 352364562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 352466494Sgshapiro syserr("Error in ldap_search using %s in map %s", 352590792Sgshapiro keybuf, map->map_mname); 352664562Sgshapiro else 352794334Sgshapiro syserr("451 4.3.5 Error in ldap_search using %s in map %s", 352890792Sgshapiro keybuf, map->map_mname); 352938032Speter } 353064562Sgshapiro *statp = EX_TEMPFAIL; 353190792Sgshapiro switch (save_errno - E_LDAPBASE) 353290792Sgshapiro { 353394334Sgshapiro# ifdef LDAP_SERVER_DOWN 353490792Sgshapiro case LDAP_SERVER_DOWN: 353594334Sgshapiro# endif /* LDAP_SERVER_DOWN */ 353690792Sgshapiro case LDAP_TIMEOUT: 353790792Sgshapiro case LDAP_UNAVAILABLE: 353866494Sgshapiro /* server disappeared, try reopen on next search */ 353977349Sgshapiro ldapmap_close(map); 354090792Sgshapiro break; 354166494Sgshapiro } 354277349Sgshapiro errno = save_errno; 354364562Sgshapiro return NULL; 354464562Sgshapiro } 354564562Sgshapiro 354664562Sgshapiro *statp = EX_NOTFOUND; 354764562Sgshapiro vp = NULL; 354864562Sgshapiro 3549132943Sgshapiro flags = 0; 3550132943Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 3551132943Sgshapiro flags |= SM_LDAP_SINGLEMATCH; 3552132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 3553132943Sgshapiro flags |= SM_LDAP_MATCHONLY; 355490792Sgshapiro 3555132943Sgshapiro /* Create an rpool for search related memory usage */ 3556132943Sgshapiro rpool = sm_rpool_new_x(NULL); 355790792Sgshapiro 3558132943Sgshapiro p = NULL; 3559132943Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 3560132943Sgshapiro rpool, &p, &plen, &psize, NULL); 3561132943Sgshapiro save_errno = errno; 356290792Sgshapiro 3563132943Sgshapiro /* Copy result so rpool can be freed */ 3564132943Sgshapiro if (*statp == EX_OK && p != NULL) 3565132943Sgshapiro vp = newstr(p); 3566132943Sgshapiro sm_rpool_free(rpool); 356790792Sgshapiro 3568132943Sgshapiro /* need to restart LDAP connection? */ 3569132943Sgshapiro if (*statp == EX_RESTART) 357064562Sgshapiro { 3571132943Sgshapiro *statp = EX_TEMPFAIL; 3572132943Sgshapiro ldapmap_close(map); 357338032Speter } 357438032Speter 3575132943Sgshapiro errno = save_errno; 3576132943Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 357738032Speter { 357864562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 357964562Sgshapiro { 358064562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 358164562Sgshapiro syserr("Error getting LDAP results in map %s", 358264562Sgshapiro map->map_mname); 358364562Sgshapiro else 358494334Sgshapiro syserr("451 4.3.5 Error getting LDAP results in map %s", 358564562Sgshapiro map->map_mname); 358664562Sgshapiro } 358777349Sgshapiro errno = save_errno; 358864562Sgshapiro return NULL; 358938032Speter } 359090792Sgshapiro 359164562Sgshapiro /* Did we match anything? */ 359271345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 359364562Sgshapiro return NULL; 359438032Speter 359564562Sgshapiro if (*statp == EX_OK) 359664562Sgshapiro { 359764562Sgshapiro if (LogLevel > 9) 359864562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 359971345Sgshapiro "ldap %.100s => %s", name, 360071345Sgshapiro vp == NULL ? "<NULL>" : vp); 360164562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 360264562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 360364562Sgshapiro else 360471345Sgshapiro { 360571345Sgshapiro /* vp != NULL according to test above */ 360664562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 360771345Sgshapiro } 360871345Sgshapiro if (vp != NULL) 360990792Sgshapiro sm_free(vp); /* XXX */ 361064562Sgshapiro } 361164562Sgshapiro return result; 361238032Speter} 361338032Speter 361438032Speter/* 361564562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 361664562Sgshapiro** 361764562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 361866494Sgshapiro** secret, and PID so we don't have multiple connections open to 361966494Sgshapiro** the same server for different maps. Need a separate connection 362066494Sgshapiro** per PID since a parent process may close the map before the 362166494Sgshapiro** child is done with it. 362264562Sgshapiro** 362364562Sgshapiro** Parameters: 362464562Sgshapiro** lmap -- LDAP map information 362564562Sgshapiro** 362664562Sgshapiro** Returns: 362764562Sgshapiro** Symbol table entry for the LDAP connection. 362838032Speter*/ 362938032Speter 363064562Sgshapirostatic STAB * 363164562Sgshapiroldapmap_findconn(lmap) 363290792Sgshapiro SM_LDAP_STRUCT *lmap; 363338032Speter{ 363494334Sgshapiro char *format; 363564562Sgshapiro char *nbuf; 3636132943Sgshapiro char *id; 363790792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 363838032Speter 3639132943Sgshapiro if (lmap->ldap_host != NULL) 3640132943Sgshapiro id = lmap->ldap_host; 3641132943Sgshapiro else if (lmap->ldap_uri != NULL) 3642132943Sgshapiro id = lmap->ldap_uri; 3643132943Sgshapiro else 3644132943Sgshapiro id = "localhost"; 3645132943Sgshapiro 364694334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 364794334Sgshapiro nbuf = sm_stringf_x(format, 3648132943Sgshapiro id, 364990792Sgshapiro CONDELSE, 365090792Sgshapiro lmap->ldap_port, 365190792Sgshapiro CONDELSE, 365294334Sgshapiro lmap->ldap_version, 365394334Sgshapiro CONDELSE, 365490792Sgshapiro (lmap->ldap_binddn == NULL ? "" 365590792Sgshapiro : lmap->ldap_binddn), 365690792Sgshapiro CONDELSE, 365790792Sgshapiro (lmap->ldap_secret == NULL ? "" 365890792Sgshapiro : lmap->ldap_secret), 365990792Sgshapiro (int) CurrentPid); 366090792Sgshapiro SM_TRY 366190792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 366290792Sgshapiro SM_FINALLY 366390792Sgshapiro sm_free(nbuf); 366490792Sgshapiro SM_END_TRY 366564562Sgshapiro return s; 366664562Sgshapiro} 366738032Speter/* 366864562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 366964562Sgshapiro*/ 367038032Speter 367190792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 367264562Sgshapiro{ 367364562Sgshapiro { "none", LDAP_AUTH_NONE }, 367464562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 367564562Sgshapiro# ifdef LDAP_AUTH_KRBV4 367664562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 367764562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 367864562Sgshapiro { NULL, 0 } 367964562Sgshapiro}; 368038032Speter 368190792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 368264562Sgshapiro{ 368364562Sgshapiro { "never", LDAP_DEREF_NEVER }, 368464562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 368564562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 368664562Sgshapiro { "find", LDAP_DEREF_FINDING }, 368764562Sgshapiro { NULL, 0 } 368864562Sgshapiro}; 368938032Speter 369090792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 369164562Sgshapiro{ 369264562Sgshapiro { "base", LDAP_SCOPE_BASE }, 369364562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 369464562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 369564562Sgshapiro { NULL, 0 } 369664562Sgshapiro}; 369738032Speter 369864562Sgshapirobool 369964562Sgshapiroldapmap_parseargs(map, args) 370064562Sgshapiro MAP *map; 370164562Sgshapiro char *args; 370264562Sgshapiro{ 370390792Sgshapiro bool secretread = true; 3704132943Sgshapiro bool attrssetup = false; 370564562Sgshapiro int i; 370664562Sgshapiro register char *p = args; 370790792Sgshapiro SM_LDAP_STRUCT *lmap; 370864562Sgshapiro struct lamvalues *lam; 370964562Sgshapiro struct ladvalues *lad; 371064562Sgshapiro struct lssvalues *lss; 371190792Sgshapiro char ldapfilt[MAXLINE]; 371264562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 371364562Sgshapiro 371464562Sgshapiro /* Get ldap struct pointer from map */ 371590792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 371664562Sgshapiro 371764562Sgshapiro /* Check if setting the initial LDAP defaults */ 371864562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 371964562Sgshapiro { 372090792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 372190792Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof *lmap); 372264562Sgshapiro if (LDAPDefaults == NULL) 372390792Sgshapiro sm_ldap_clear(lmap); 372464562Sgshapiro else 372564562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 372664562Sgshapiro } 372764562Sgshapiro 372864562Sgshapiro /* there is no check whether there is really an argument */ 372964562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 373064562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 373190792Sgshapiro 373290792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 373390792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 373490792Sgshapiro { 373590792Sgshapiro /* Comma separate if used as an alias file */ 373690792Sgshapiro map->map_coldelim = ','; 373790792Sgshapiro if (*args == '\0') 373890792Sgshapiro { 373990792Sgshapiro int n; 374090792Sgshapiro char *lc; 374190792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 374290792Sgshapiro char lcbuf[MAXLINE]; 374390792Sgshapiro 374490792Sgshapiro /* Get $j */ 374590792Sgshapiro expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 374690792Sgshapiro if (jbuf[0] == '\0') 374790792Sgshapiro { 374890792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 374990792Sgshapiro sizeof jbuf); 375090792Sgshapiro } 375190792Sgshapiro 375290792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 375390792Sgshapiro if (lc == NULL) 375490792Sgshapiro lc = ""; 375590792Sgshapiro else 375690792Sgshapiro { 375790792Sgshapiro expand(lc, lcbuf, sizeof lcbuf, CurEnv); 375890792Sgshapiro lc = lcbuf; 375990792Sgshapiro } 376090792Sgshapiro 376190792Sgshapiro n = sm_snprintf(ldapfilt, sizeof ldapfilt, 376290792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 376390792Sgshapiro lc, jbuf); 376490792Sgshapiro if (n >= sizeof ldapfilt) 376590792Sgshapiro { 376690792Sgshapiro syserr("%s: Default LDAP string too long", 376790792Sgshapiro map->map_mname); 376890792Sgshapiro return false; 376990792Sgshapiro } 377090792Sgshapiro 377190792Sgshapiro /* default args for an alias LDAP entry */ 377290792Sgshapiro lmap->ldap_filter = ldapfilt; 3773132943Sgshapiro lmap->ldap_attr[0] = "objectClass"; 3774132943Sgshapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 3775132943Sgshapiro lmap->ldap_attr_needobjclass[0] = NULL; 3776132943Sgshapiro lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 3777132943Sgshapiro lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 3778132943Sgshapiro lmap->ldap_attr_needobjclass[1] = NULL; 3779132943Sgshapiro lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 3780132943Sgshapiro lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 3781132943Sgshapiro lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 3782132943Sgshapiro lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 3783132943Sgshapiro lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 3784132943Sgshapiro lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 3785132943Sgshapiro lmap->ldap_attr[4] = NULL; 3786132943Sgshapiro lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 3787132943Sgshapiro lmap->ldap_attr_needobjclass[4] = NULL; 3788132943Sgshapiro attrssetup = true; 378990792Sgshapiro } 379090792Sgshapiro } 379190792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 379290792Sgshapiro { 379390792Sgshapiro /* Space separate if used as a file class file */ 379490792Sgshapiro map->map_coldelim = ' '; 379590792Sgshapiro } 379690792Sgshapiro 379738032Speter for (;;) 379838032Speter { 379938032Speter while (isascii(*p) && isspace(*p)) 380038032Speter p++; 380138032Speter if (*p != '-') 380238032Speter break; 380338032Speter switch (*++p) 380438032Speter { 380538032Speter case 'N': 380638032Speter map->map_mflags |= MF_INCLNULL; 380738032Speter map->map_mflags &= ~MF_TRY0NULL; 380838032Speter break; 380938032Speter 381038032Speter case 'O': 381138032Speter map->map_mflags &= ~MF_TRY1NULL; 381238032Speter break; 381338032Speter 381438032Speter case 'o': 381538032Speter map->map_mflags |= MF_OPTIONAL; 381638032Speter break; 381738032Speter 381838032Speter case 'f': 381938032Speter map->map_mflags |= MF_NOFOLDCASE; 382038032Speter break; 382138032Speter 382238032Speter case 'm': 382338032Speter map->map_mflags |= MF_MATCHONLY; 382438032Speter break; 382538032Speter 382638032Speter case 'A': 382738032Speter map->map_mflags |= MF_APPEND; 382838032Speter break; 382938032Speter 383038032Speter case 'q': 383138032Speter map->map_mflags |= MF_KEEPQUOTES; 383238032Speter break; 383338032Speter 383438032Speter case 'a': 383538032Speter map->map_app = ++p; 383638032Speter break; 383738032Speter 383838032Speter case 'T': 383938032Speter map->map_tapp = ++p; 384038032Speter break; 384138032Speter 384264562Sgshapiro case 't': 384364562Sgshapiro map->map_mflags |= MF_NODEFER; 384464562Sgshapiro break; 384564562Sgshapiro 384664562Sgshapiro case 'S': 384764562Sgshapiro map->map_spacesub = *++p; 384864562Sgshapiro break; 384964562Sgshapiro 385064562Sgshapiro case 'D': 385164562Sgshapiro map->map_mflags |= MF_DEFER; 385264562Sgshapiro break; 385364562Sgshapiro 385464562Sgshapiro case 'z': 385564562Sgshapiro if (*++p != '\\') 385664562Sgshapiro map->map_coldelim = *p; 385764562Sgshapiro else 385864562Sgshapiro { 385964562Sgshapiro switch (*++p) 386064562Sgshapiro { 386164562Sgshapiro case 'n': 386264562Sgshapiro map->map_coldelim = '\n'; 386364562Sgshapiro break; 386464562Sgshapiro 386564562Sgshapiro case 't': 386664562Sgshapiro map->map_coldelim = '\t'; 386764562Sgshapiro break; 386864562Sgshapiro 386964562Sgshapiro default: 387064562Sgshapiro map->map_coldelim = '\\'; 387164562Sgshapiro } 387264562Sgshapiro } 387364562Sgshapiro break; 387464562Sgshapiro 387564562Sgshapiro /* Start of ldapmap specific args */ 387690792Sgshapiro case 'V': 387790792Sgshapiro if (*++p != '\\') 387890792Sgshapiro lmap->ldap_attrsep = *p; 387990792Sgshapiro else 388090792Sgshapiro { 388190792Sgshapiro switch (*++p) 388290792Sgshapiro { 388390792Sgshapiro case 'n': 388490792Sgshapiro lmap->ldap_attrsep = '\n'; 388590792Sgshapiro break; 388690792Sgshapiro 388790792Sgshapiro case 't': 388890792Sgshapiro lmap->ldap_attrsep = '\t'; 388990792Sgshapiro break; 389090792Sgshapiro 389190792Sgshapiro default: 389290792Sgshapiro lmap->ldap_attrsep = '\\'; 389390792Sgshapiro } 389490792Sgshapiro } 389590792Sgshapiro break; 389690792Sgshapiro 389738032Speter case 'k': /* search field */ 389838032Speter while (isascii(*++p) && isspace(*p)) 389938032Speter continue; 390064562Sgshapiro lmap->ldap_filter = p; 390138032Speter break; 390238032Speter 390338032Speter case 'v': /* attr to return */ 390438032Speter while (isascii(*++p) && isspace(*p)) 390538032Speter continue; 390664562Sgshapiro lmap->ldap_attr[0] = p; 390764562Sgshapiro lmap->ldap_attr[1] = NULL; 390838032Speter break; 390938032Speter 391064562Sgshapiro case '1': 391164562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 391264562Sgshapiro break; 391364562Sgshapiro 391438032Speter /* args stolen from ldapsearch.c */ 391538032Speter case 'R': /* don't auto chase referrals */ 391664562Sgshapiro# ifdef LDAP_REFERRALS 391738032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 391864562Sgshapiro# else /* LDAP_REFERRALS */ 391990792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 392064562Sgshapiro# endif /* LDAP_REFERRALS */ 392138032Speter break; 392238032Speter 392364562Sgshapiro case 'n': /* retrieve attribute names only */ 392464562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 392538032Speter break; 392638032Speter 392764562Sgshapiro case 'r': /* alias dereferencing */ 392864562Sgshapiro while (isascii(*++p) && isspace(*p)) 392964562Sgshapiro continue; 393064562Sgshapiro 393190792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 393264562Sgshapiro p += 11; 393364562Sgshapiro 393464562Sgshapiro for (lad = LDAPAliasDereference; 393564562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 393638032Speter { 393790792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 393890792Sgshapiro strlen(lad->lad_name)) == 0) 393964562Sgshapiro break; 394038032Speter } 394164562Sgshapiro if (lad->lad_name != NULL) 394264562Sgshapiro lmap->ldap_deref = lad->lad_code; 394364562Sgshapiro else 394438032Speter { 394564562Sgshapiro /* bad config line */ 394664562Sgshapiro if (!bitset(MCF_OPTFILE, 394764562Sgshapiro map->map_class->map_cflags)) 394864562Sgshapiro { 394964562Sgshapiro char *ptr; 395064562Sgshapiro 395164562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 395264562Sgshapiro *ptr = '\0'; 395373188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 395464562Sgshapiro p, map->map_mname); 395564562Sgshapiro if (ptr != NULL) 395664562Sgshapiro *ptr = ' '; 395790792Sgshapiro return false; 395864562Sgshapiro } 395938032Speter } 396064562Sgshapiro break; 396164562Sgshapiro 396264562Sgshapiro case 's': /* search scope */ 396364562Sgshapiro while (isascii(*++p) && isspace(*p)) 396464562Sgshapiro continue; 396564562Sgshapiro 396690792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 396764562Sgshapiro p += 11; 396864562Sgshapiro 396964562Sgshapiro for (lss = LDAPSearchScope; 397064562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 397138032Speter { 397290792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 397390792Sgshapiro strlen(lss->lss_name)) == 0) 397464562Sgshapiro break; 397538032Speter } 397664562Sgshapiro if (lss->lss_name != NULL) 397764562Sgshapiro lmap->ldap_scope = lss->lss_code; 397838032Speter else 397964562Sgshapiro { 398064562Sgshapiro /* bad config line */ 398164562Sgshapiro if (!bitset(MCF_OPTFILE, 398264562Sgshapiro map->map_class->map_cflags)) 398338032Speter { 398438032Speter char *ptr; 398538032Speter 398638032Speter if ((ptr = strchr(p, ' ')) != NULL) 398738032Speter *ptr = '\0'; 398873188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 398938032Speter p, map->map_mname); 399038032Speter if (ptr != NULL) 399138032Speter *ptr = ' '; 399290792Sgshapiro return false; 399338032Speter } 399438032Speter } 399538032Speter break; 399638032Speter 399738032Speter case 'h': /* ldap host */ 399838032Speter while (isascii(*++p) && isspace(*p)) 399938032Speter continue; 4000132943Sgshapiro if (lmap->ldap_uri != NULL) 400194334Sgshapiro { 400294334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 400394334Sgshapiro map->map_mname); 400494334Sgshapiro return false; 400594334Sgshapiro } 4006132943Sgshapiro lmap->ldap_host = p; 400738032Speter break; 400838032Speter 400938032Speter case 'b': /* search base */ 401038032Speter while (isascii(*++p) && isspace(*p)) 401138032Speter continue; 401264562Sgshapiro lmap->ldap_base = p; 401338032Speter break; 401438032Speter 401538032Speter case 'p': /* ldap port */ 401638032Speter while (isascii(*++p) && isspace(*p)) 401738032Speter continue; 401864562Sgshapiro lmap->ldap_port = atoi(p); 401938032Speter break; 402038032Speter 402138032Speter case 'l': /* time limit */ 402238032Speter while (isascii(*++p) && isspace(*p)) 402338032Speter continue; 402464562Sgshapiro lmap->ldap_timelimit = atoi(p); 402564562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 402638032Speter break; 402738032Speter 402864562Sgshapiro case 'Z': 402964562Sgshapiro while (isascii(*++p) && isspace(*p)) 403064562Sgshapiro continue; 403164562Sgshapiro lmap->ldap_sizelimit = atoi(p); 403264562Sgshapiro break; 403364562Sgshapiro 403464562Sgshapiro case 'd': /* Dn to bind to server as */ 403564562Sgshapiro while (isascii(*++p) && isspace(*p)) 403664562Sgshapiro continue; 403764562Sgshapiro lmap->ldap_binddn = p; 403864562Sgshapiro break; 403964562Sgshapiro 404064562Sgshapiro case 'M': /* Method for binding */ 404164562Sgshapiro while (isascii(*++p) && isspace(*p)) 404264562Sgshapiro continue; 404364562Sgshapiro 404490792Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 404564562Sgshapiro p += 10; 404664562Sgshapiro 404764562Sgshapiro for (lam = LDAPAuthMethods; 404864562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 404964562Sgshapiro { 405090792Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 405190792Sgshapiro strlen(lam->lam_name)) == 0) 405264562Sgshapiro break; 405364562Sgshapiro } 405464562Sgshapiro if (lam->lam_name != NULL) 405564562Sgshapiro lmap->ldap_method = lam->lam_code; 405664562Sgshapiro else 405764562Sgshapiro { 405864562Sgshapiro /* bad config line */ 405964562Sgshapiro if (!bitset(MCF_OPTFILE, 406064562Sgshapiro map->map_class->map_cflags)) 406164562Sgshapiro { 406264562Sgshapiro char *ptr; 406364562Sgshapiro 406464562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 406564562Sgshapiro *ptr = '\0'; 406673188Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 406764562Sgshapiro p, map->map_mname); 406864562Sgshapiro if (ptr != NULL) 406964562Sgshapiro *ptr = ' '; 407090792Sgshapiro return false; 407164562Sgshapiro } 407264562Sgshapiro } 407364562Sgshapiro 407464562Sgshapiro break; 407564562Sgshapiro 407664562Sgshapiro /* 407764562Sgshapiro ** This is a string that is dependent on the 407864562Sgshapiro ** method used defined above. 407964562Sgshapiro */ 408064562Sgshapiro 408164562Sgshapiro case 'P': /* Secret password for binding */ 408264562Sgshapiro while (isascii(*++p) && isspace(*p)) 408364562Sgshapiro continue; 408464562Sgshapiro lmap->ldap_secret = p; 408590792Sgshapiro secretread = false; 408664562Sgshapiro break; 408764562Sgshapiro 408894334Sgshapiro case 'H': /* Use LDAP URI */ 408994334Sgshapiro# if !USE_LDAP_INIT 409094334Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 409194334Sgshapiro map->map_mname); 409294334Sgshapiro return false; 4093132943Sgshapiro# else /* !USE_LDAP_INIT */ 4094132943Sgshapiro if (lmap->ldap_host != NULL) 409594334Sgshapiro { 409694334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 409794334Sgshapiro map->map_mname); 409894334Sgshapiro return false; 409994334Sgshapiro } 410094334Sgshapiro while (isascii(*++p) && isspace(*p)) 410194334Sgshapiro continue; 4102132943Sgshapiro lmap->ldap_uri = p; 410394334Sgshapiro break; 410494334Sgshapiro# endif /* !USE_LDAP_INIT */ 410594334Sgshapiro 410694334Sgshapiro case 'w': 410794334Sgshapiro /* -w should be for passwd, -P should be for version */ 410894334Sgshapiro while (isascii(*++p) && isspace(*p)) 410994334Sgshapiro continue; 411094334Sgshapiro lmap->ldap_version = atoi(p); 4111132943Sgshapiro# ifdef LDAP_VERSION_MAX 411294334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 411394334Sgshapiro { 411494334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 411594334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 411694334Sgshapiro map->map_mname); 411794334Sgshapiro return false; 411894334Sgshapiro } 4119132943Sgshapiro# endif /* LDAP_VERSION_MAX */ 4120132943Sgshapiro# ifdef LDAP_VERSION_MIN 412194334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 412294334Sgshapiro { 412394334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 412494334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 412594334Sgshapiro map->map_mname); 412694334Sgshapiro return false; 412794334Sgshapiro } 4128132943Sgshapiro# endif /* LDAP_VERSION_MIN */ 412994334Sgshapiro break; 413094334Sgshapiro 413164562Sgshapiro default: 413264562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 413364562Sgshapiro break; 413438032Speter } 413538032Speter 413664562Sgshapiro /* need to account for quoted strings here */ 413764562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 413838032Speter { 413938032Speter if (*p == '"') 414038032Speter { 414138032Speter while (*++p != '"' && *p != '\0') 414238032Speter continue; 414338032Speter if (*p != '\0') 414438032Speter p++; 414538032Speter } 414638032Speter else 414738032Speter p++; 414838032Speter } 414938032Speter 415038032Speter if (*p != '\0') 415138032Speter *p++ = '\0'; 415238032Speter } 415338032Speter 415438032Speter if (map->map_app != NULL) 415564562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 415638032Speter if (map->map_tapp != NULL) 415764562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 415838032Speter 415938032Speter /* 416042575Speter ** We need to swallow up all the stuff into a struct 416142575Speter ** and dump it into map->map_dbptr1 416238032Speter */ 416338032Speter 4164132943Sgshapiro if (lmap->ldap_host != NULL && 416564562Sgshapiro (LDAPDefaults == NULL || 416664562Sgshapiro LDAPDefaults == lmap || 4167132943Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 4168132943Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 4169132943Sgshapiro map->map_domain = lmap->ldap_host; 417064562Sgshapiro 4171132943Sgshapiro if (lmap->ldap_uri != NULL && 4172132943Sgshapiro (LDAPDefaults == NULL || 4173132943Sgshapiro LDAPDefaults == lmap || 4174132943Sgshapiro LDAPDefaults->ldap_uri != lmap->ldap_uri)) 4175132943Sgshapiro lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 4176132943Sgshapiro map->map_domain = lmap->ldap_uri; 4177132943Sgshapiro 417864562Sgshapiro if (lmap->ldap_binddn != NULL && 417964562Sgshapiro (LDAPDefaults == NULL || 418064562Sgshapiro LDAPDefaults == lmap || 418164562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 418264562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 418364562Sgshapiro 418464562Sgshapiro if (lmap->ldap_secret != NULL && 418564562Sgshapiro (LDAPDefaults == NULL || 418664562Sgshapiro LDAPDefaults == lmap || 418764562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 418838032Speter { 418990792Sgshapiro SM_FILE_T *sfd; 419064562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 419138032Speter 419264562Sgshapiro if (DontLockReadFiles) 419364562Sgshapiro sff |= SFF_NOLOCK; 419438032Speter 419564562Sgshapiro /* need to use method to map secret to passwd string */ 419664562Sgshapiro switch (lmap->ldap_method) 419764562Sgshapiro { 419864562Sgshapiro case LDAP_AUTH_NONE: 419964562Sgshapiro /* Do nothing */ 420064562Sgshapiro break; 420138032Speter 420264562Sgshapiro case LDAP_AUTH_SIMPLE: 420338032Speter 420464562Sgshapiro /* 420564562Sgshapiro ** Secret is the name of a file with 420664562Sgshapiro ** the first line as the password. 420764562Sgshapiro */ 420864562Sgshapiro 420964562Sgshapiro /* Already read in the secret? */ 421064562Sgshapiro if (secretread) 421164562Sgshapiro break; 421264562Sgshapiro 421364562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 421464562Sgshapiro O_RDONLY, 0, sff); 421564562Sgshapiro if (sfd == NULL) 421664562Sgshapiro { 421764562Sgshapiro syserr("LDAP map: cannot open secret %s", 421864562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 421990792Sgshapiro return false; 422064562Sgshapiro } 422198121Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof m_tmp, 422266494Sgshapiro sfd, TimeOuts.to_fileopen, 422366494Sgshapiro "ldapmap_parseargs"); 422490792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 422598121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 422698121Sgshapiro { 422798121Sgshapiro syserr("LDAP map: secret in %s too long", 422898121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 422998121Sgshapiro return false; 423098121Sgshapiro } 423164562Sgshapiro if (lmap->ldap_secret != NULL && 423264562Sgshapiro strlen(m_tmp) > 0) 423364562Sgshapiro { 423464562Sgshapiro /* chomp newline */ 423564562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 423664562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 423764562Sgshapiro 423864562Sgshapiro lmap->ldap_secret = m_tmp; 423964562Sgshapiro } 424064562Sgshapiro break; 424164562Sgshapiro 424264562Sgshapiro# ifdef LDAP_AUTH_KRBV4 424364562Sgshapiro case LDAP_AUTH_KRBV4: 424464562Sgshapiro 424564562Sgshapiro /* 424664562Sgshapiro ** Secret is where the ticket file is 424764562Sgshapiro ** stashed 424864562Sgshapiro */ 424964562Sgshapiro 425098121Sgshapiro (void) sm_snprintf(m_tmp, sizeof m_tmp, 425190792Sgshapiro "KRBTKFILE=%s", 425290792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 425364562Sgshapiro lmap->ldap_secret = m_tmp; 425464562Sgshapiro break; 425564562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 425664562Sgshapiro 425764562Sgshapiro default: /* Should NEVER get here */ 425864562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 425990792Sgshapiro return false; 426090792Sgshapiro /* NOTREACHED */ 426164562Sgshapiro break; 426264562Sgshapiro } 426338032Speter } 426438032Speter 426564562Sgshapiro if (lmap->ldap_secret != NULL && 426664562Sgshapiro (LDAPDefaults == NULL || 426764562Sgshapiro LDAPDefaults == lmap || 426864562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 426964562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 427038032Speter 427164562Sgshapiro if (lmap->ldap_base != NULL && 427264562Sgshapiro (LDAPDefaults == NULL || 427364562Sgshapiro LDAPDefaults == lmap || 427464562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 427564562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 427664562Sgshapiro 427764562Sgshapiro /* 427864562Sgshapiro ** Save the server from extra work. If request is for a single 427964562Sgshapiro ** match, tell the server to only return enough records to 428064562Sgshapiro ** determine if there is a single match or not. This can not 428164562Sgshapiro ** be one since the server would only return one and we wouldn't 428264562Sgshapiro ** know if there were others available. 428364562Sgshapiro */ 428464562Sgshapiro 428564562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 428664562Sgshapiro lmap->ldap_sizelimit = 2; 428764562Sgshapiro 428864562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 428964562Sgshapiro if (lmap == LDAPDefaults) 429090792Sgshapiro return true; 429164562Sgshapiro 429264562Sgshapiro if (lmap->ldap_filter != NULL) 429364562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 429438032Speter else 429538032Speter { 429638032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 429738032Speter { 429838032Speter syserr("No filter given in map %s", map->map_mname); 429990792Sgshapiro return false; 430038032Speter } 430138032Speter } 430264562Sgshapiro 4303132943Sgshapiro if (!attrssetup && lmap->ldap_attr[0] != NULL) 430438032Speter { 430590792Sgshapiro bool recurse = false; 430694334Sgshapiro bool normalseen = false; 430790792Sgshapiro 430864562Sgshapiro i = 0; 430964562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 431064562Sgshapiro lmap->ldap_attr[0] = NULL; 431164562Sgshapiro 431294334Sgshapiro /* Prime the attr list with the objectClass attribute */ 431394334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 431494334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 431594334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 431694334Sgshapiro i++; 431794334Sgshapiro 431864562Sgshapiro while (p != NULL) 431938032Speter { 432064562Sgshapiro char *v; 432164562Sgshapiro 432264562Sgshapiro while (isascii(*p) && isspace(*p)) 432364562Sgshapiro p++; 432464562Sgshapiro if (*p == '\0') 432564562Sgshapiro break; 432664562Sgshapiro v = p; 432764562Sgshapiro p = strchr(v, ','); 432864562Sgshapiro if (p != NULL) 432964562Sgshapiro *p++ = '\0'; 433064562Sgshapiro 433171345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 433264562Sgshapiro { 433364562Sgshapiro syserr("Too many return attributes in %s (max %d)", 433464562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 433590792Sgshapiro return false; 433664562Sgshapiro } 433764562Sgshapiro if (*v != '\0') 433890792Sgshapiro { 433994334Sgshapiro int j; 434094334Sgshapiro int use; 434190792Sgshapiro char *type; 434294334Sgshapiro char *needobjclass; 434390792Sgshapiro 434490792Sgshapiro type = strchr(v, ':'); 434590792Sgshapiro if (type != NULL) 434694334Sgshapiro { 434790792Sgshapiro *type++ = '\0'; 434894334Sgshapiro needobjclass = strchr(type, ':'); 434994334Sgshapiro if (needobjclass != NULL) 435094334Sgshapiro *needobjclass++ = '\0'; 435194334Sgshapiro } 435294334Sgshapiro else 435394334Sgshapiro { 435494334Sgshapiro needobjclass = NULL; 435594334Sgshapiro } 435690792Sgshapiro 435794334Sgshapiro use = i; 435890792Sgshapiro 435994334Sgshapiro /* allow override on "objectClass" type */ 436094334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 436194334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 436290792Sgshapiro { 436394334Sgshapiro use = 0; 436494334Sgshapiro } 436594334Sgshapiro else 436694334Sgshapiro { 436794334Sgshapiro /* 436894334Sgshapiro ** Don't add something to attribute 436994334Sgshapiro ** list twice. 437094334Sgshapiro */ 437194334Sgshapiro 437294334Sgshapiro for (j = 1; j < i; j++) 437390792Sgshapiro { 437494334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 437594334Sgshapiro { 437694334Sgshapiro syserr("Duplicate attribute (%s) in %s", 437794334Sgshapiro v, map->map_mname); 437894334Sgshapiro return false; 437994334Sgshapiro } 438090792Sgshapiro } 438194334Sgshapiro 438294334Sgshapiro lmap->ldap_attr[use] = newstr(v); 438394334Sgshapiro if (needobjclass != NULL && 438494334Sgshapiro *needobjclass != '\0' && 438594334Sgshapiro *needobjclass != '*') 438690792Sgshapiro { 438794334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 438894334Sgshapiro } 438994334Sgshapiro else 439094334Sgshapiro { 439194334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 439294334Sgshapiro } 439394334Sgshapiro 439494334Sgshapiro } 439594334Sgshapiro 439694334Sgshapiro if (type != NULL && *type != '\0') 439794334Sgshapiro { 439894334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 439994334Sgshapiro { 440090792Sgshapiro recurse = true; 440194334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 440290792Sgshapiro } 440390792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 440490792Sgshapiro { 440590792Sgshapiro recurse = true; 440694334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 440790792Sgshapiro } 440890792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 440990792Sgshapiro { 441090792Sgshapiro recurse = true; 441194334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 441290792Sgshapiro } 441394334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 441490792Sgshapiro { 441594334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 441694334Sgshapiro normalseen = true; 441790792Sgshapiro } 441890792Sgshapiro else 441990792Sgshapiro { 442090792Sgshapiro syserr("Unknown attribute type (%s) in %s", 442190792Sgshapiro type, map->map_mname); 442290792Sgshapiro return false; 442390792Sgshapiro } 442490792Sgshapiro } 442590792Sgshapiro else 442694334Sgshapiro { 442794334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 442894334Sgshapiro normalseen = true; 442994334Sgshapiro } 443090792Sgshapiro i++; 443190792Sgshapiro } 443238032Speter } 443364562Sgshapiro lmap->ldap_attr[i] = NULL; 4434132943Sgshapiro attrssetup = true; 443594334Sgshapiro if (recurse && !normalseen) 443690792Sgshapiro { 443794334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 443890792Sgshapiro map->map_mname); 443990792Sgshapiro return false; 444090792Sgshapiro } 444190792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 444290792Sgshapiro { 444390792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 444490792Sgshapiro map->map_mname); 444590792Sgshapiro return false; 444690792Sgshapiro } 444738032Speter } 444838032Speter map->map_db1 = (ARBPTR_T) lmap; 444990792Sgshapiro return true; 445038032Speter} 445138032Speter 445264562Sgshapiro/* 445364562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 445464562Sgshapiro** 445564562Sgshapiro** Parameters: 445664562Sgshapiro** spec -- map argument string from LDAPDefaults option 445764562Sgshapiro** 445864562Sgshapiro** Returns: 445964562Sgshapiro** None. 446064562Sgshapiro*/ 446164562Sgshapiro 446264562Sgshapirovoid 446364562Sgshapiroldapmap_set_defaults(spec) 446464562Sgshapiro char *spec; 446564562Sgshapiro{ 446673188Sgshapiro STAB *class; 446764562Sgshapiro MAP map; 446864562Sgshapiro 446964562Sgshapiro /* Allocate and set the default values */ 447064562Sgshapiro if (LDAPDefaults == NULL) 447190792Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 447290792Sgshapiro sm_ldap_clear(LDAPDefaults); 447364562Sgshapiro 447464562Sgshapiro memset(&map, '\0', sizeof map); 447573188Sgshapiro 447673188Sgshapiro /* look up the class */ 447773188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 447873188Sgshapiro if (class == NULL) 447973188Sgshapiro { 448073188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 448173188Sgshapiro return; 448273188Sgshapiro } 448373188Sgshapiro map.map_class = &class->s_mapclass; 448464562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 448573188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 448664562Sgshapiro 448764562Sgshapiro (void) ldapmap_parseargs(&map, spec); 448864562Sgshapiro 448964562Sgshapiro /* These should never be set in LDAPDefaults */ 449064562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 449164562Sgshapiro map.map_spacesub != SpaceSub || 449264562Sgshapiro map.map_app != NULL || 449364562Sgshapiro map.map_tapp != NULL) 449464562Sgshapiro { 449564562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 449690792Sgshapiro SM_FREE_CLR(map.map_app); 449790792Sgshapiro SM_FREE_CLR(map.map_tapp); 449864562Sgshapiro } 449964562Sgshapiro 450064562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 450164562Sgshapiro { 450264562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 450394334Sgshapiro 450464562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 450564562Sgshapiro LDAPDefaults->ldap_filter = NULL; 450664562Sgshapiro } 450764562Sgshapiro 450864562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 450964562Sgshapiro { 451064562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 451164562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 451264562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 451364562Sgshapiro } 451464562Sgshapiro} 451564562Sgshapiro#endif /* LDAPMAP */ 451690792Sgshapiro/* 451764562Sgshapiro** PH map 451864562Sgshapiro*/ 451964562Sgshapiro 452090792Sgshapiro#if PH_MAP 452164562Sgshapiro 452264562Sgshapiro/* 452364562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 452464562Sgshapiro** This code is intended to replace the so-called "ph mailer". 452564562Sgshapiro** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 452664562Sgshapiro*/ 452764562Sgshapiro 452890792Sgshapiro/* what version of the ph map code we're running */ 4529110560Sgshapirostatic char phmap_id[128]; 453064562Sgshapiro 453190792Sgshapiro/* sendmail version for phmap id string */ 453290792Sgshapiroextern const char Version[]; 453390792Sgshapiro 4534132943Sgshapiro/* assume we're using nph-1.2.x if not specified */ 4535110560Sgshapiro# ifndef NPH_VERSION 4536132943Sgshapiro# define NPH_VERSION 10200 4537110560Sgshapiro# endif 4538110560Sgshapiro 4539110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 4540110560Sgshapiro# if NPH_VERSION < 10200 4541110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 4542110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 4543110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 4544110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 4545110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 4546110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 4547110560Sgshapiro 454864562Sgshapiro/* 454964562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 455064562Sgshapiro*/ 455164562Sgshapiro 455264562Sgshapirobool 455364562Sgshapiroph_map_parseargs(map, args) 455464562Sgshapiro MAP *map; 455564562Sgshapiro char *args; 455664562Sgshapiro{ 455790792Sgshapiro register bool done; 455890792Sgshapiro register char *p = args; 455964562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 456064562Sgshapiro 456190792Sgshapiro /* initialize version string */ 456290792Sgshapiro (void) sm_snprintf(phmap_id, sizeof phmap_id, 456390792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 456490792Sgshapiro Version, libphclient_version); 456590792Sgshapiro 456664562Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 456764562Sgshapiro 456864562Sgshapiro /* defaults */ 456964562Sgshapiro pmap->ph_servers = NULL; 457064562Sgshapiro pmap->ph_field_list = NULL; 457190792Sgshapiro pmap->ph = NULL; 457264562Sgshapiro pmap->ph_timeout = 0; 457390792Sgshapiro pmap->ph_fastclose = 0; 457464562Sgshapiro 457564562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 457664562Sgshapiro for (;;) 457764562Sgshapiro { 457864562Sgshapiro while (isascii(*p) && isspace(*p)) 457964562Sgshapiro p++; 458064562Sgshapiro if (*p != '-') 458164562Sgshapiro break; 458264562Sgshapiro switch (*++p) 458364562Sgshapiro { 458464562Sgshapiro case 'N': 458564562Sgshapiro map->map_mflags |= MF_INCLNULL; 458664562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 458764562Sgshapiro break; 458864562Sgshapiro 458964562Sgshapiro case 'O': 459064562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 459164562Sgshapiro break; 459264562Sgshapiro 459364562Sgshapiro case 'o': 459464562Sgshapiro map->map_mflags |= MF_OPTIONAL; 459564562Sgshapiro break; 459664562Sgshapiro 459764562Sgshapiro case 'f': 459864562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 459964562Sgshapiro break; 460064562Sgshapiro 460164562Sgshapiro case 'm': 460264562Sgshapiro map->map_mflags |= MF_MATCHONLY; 460364562Sgshapiro break; 460464562Sgshapiro 460564562Sgshapiro case 'A': 460664562Sgshapiro map->map_mflags |= MF_APPEND; 460764562Sgshapiro break; 460864562Sgshapiro 460964562Sgshapiro case 'q': 461064562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 461164562Sgshapiro break; 461264562Sgshapiro 461364562Sgshapiro case 't': 461464562Sgshapiro map->map_mflags |= MF_NODEFER; 461564562Sgshapiro break; 461664562Sgshapiro 461764562Sgshapiro case 'a': 461864562Sgshapiro map->map_app = ++p; 461964562Sgshapiro break; 462064562Sgshapiro 462164562Sgshapiro case 'T': 462264562Sgshapiro map->map_tapp = ++p; 462364562Sgshapiro break; 462464562Sgshapiro 462564562Sgshapiro case 'l': 462664562Sgshapiro while (isascii(*++p) && isspace(*p)) 462764562Sgshapiro continue; 462864562Sgshapiro pmap->ph_timeout = atoi(p); 462964562Sgshapiro break; 463064562Sgshapiro 463164562Sgshapiro case 'S': 463264562Sgshapiro map->map_spacesub = *++p; 463364562Sgshapiro break; 463464562Sgshapiro 463564562Sgshapiro case 'D': 463664562Sgshapiro map->map_mflags |= MF_DEFER; 463764562Sgshapiro break; 463864562Sgshapiro 463964562Sgshapiro case 'h': /* PH server list */ 464064562Sgshapiro while (isascii(*++p) && isspace(*p)) 464164562Sgshapiro continue; 464264562Sgshapiro pmap->ph_servers = p; 464364562Sgshapiro break; 464464562Sgshapiro 464590792Sgshapiro case 'k': /* fields to search for */ 464664562Sgshapiro while (isascii(*++p) && isspace(*p)) 464764562Sgshapiro continue; 464864562Sgshapiro pmap->ph_field_list = p; 464964562Sgshapiro break; 465064562Sgshapiro 465164562Sgshapiro default: 465290792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 465364562Sgshapiro } 465464562Sgshapiro 465564562Sgshapiro /* try to account for quoted strings */ 465664562Sgshapiro done = isascii(*p) && isspace(*p); 465764562Sgshapiro while (*p != '\0' && !done) 465864562Sgshapiro { 465964562Sgshapiro if (*p == '"') 466064562Sgshapiro { 466164562Sgshapiro while (*++p != '"' && *p != '\0') 466264562Sgshapiro continue; 466364562Sgshapiro if (*p != '\0') 466464562Sgshapiro p++; 466564562Sgshapiro } 466664562Sgshapiro else 466764562Sgshapiro p++; 466864562Sgshapiro done = isascii(*p) && isspace(*p); 466964562Sgshapiro } 467064562Sgshapiro 467164562Sgshapiro if (*p != '\0') 467264562Sgshapiro *p++ = '\0'; 467364562Sgshapiro } 467464562Sgshapiro 467564562Sgshapiro if (map->map_app != NULL) 467664562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 467764562Sgshapiro if (map->map_tapp != NULL) 467864562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 467964562Sgshapiro 468064562Sgshapiro if (pmap->ph_field_list != NULL) 468164562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 468264562Sgshapiro 468364562Sgshapiro if (pmap->ph_servers != NULL) 468464562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 468564562Sgshapiro else 468664562Sgshapiro { 468764562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 468890792Sgshapiro return false; 468964562Sgshapiro } 469064562Sgshapiro 469164562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 469290792Sgshapiro return true; 469364562Sgshapiro} 469464562Sgshapiro 469564562Sgshapiro/* 469664562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 469764562Sgshapiro*/ 469864562Sgshapiro 469990792Sgshapirovoid 470090792Sgshapiroph_map_close(map) 470164562Sgshapiro MAP *map; 470264562Sgshapiro{ 470364562Sgshapiro PH_MAP_STRUCT *pmap; 470464562Sgshapiro 470564562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 470690792Sgshapiro if (tTd(38, 9)) 470794334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 470890792Sgshapiro map->map_mname, pmap->ph_fastclose); 470964562Sgshapiro 471090792Sgshapiro 471190792Sgshapiro if (pmap->ph != NULL) 471264562Sgshapiro { 471390792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 471490792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 471590792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 471664562Sgshapiro } 471790792Sgshapiro 471864562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 471964562Sgshapiro} 472064562Sgshapiro 472164562Sgshapirostatic jmp_buf PHTimeout; 472264562Sgshapiro 472364562Sgshapiro/* ARGSUSED */ 472464562Sgshapirostatic void 472590792Sgshapiroph_timeout(unused) 472690792Sgshapiro int unused; 472764562Sgshapiro{ 472877349Sgshapiro /* 472977349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 473077349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 473177349Sgshapiro ** DOING. 473277349Sgshapiro */ 473377349Sgshapiro 473477349Sgshapiro errno = ETIMEDOUT; 473564562Sgshapiro longjmp(PHTimeout, 1); 473664562Sgshapiro} 473764562Sgshapiro 473890792Sgshapirostatic void 4739110560Sgshapiro#if NPH_VERSION >= 10200 4740110560Sgshapiroph_map_send_debug(appdata, text) 4741110560Sgshapiro void *appdata; 4742110560Sgshapiro#else 474390792Sgshapiroph_map_send_debug(text) 4744110560Sgshapiro#endif 474590792Sgshapiro char *text; 474664562Sgshapiro{ 474790792Sgshapiro if (LogLevel > 9) 474890792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 474990792Sgshapiro "ph_map_send_debug: ==> %s", text); 475090792Sgshapiro if (tTd(38, 20)) 475190792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 475290792Sgshapiro} 475364562Sgshapiro 475490792Sgshapirostatic void 4755110560Sgshapiro#if NPH_VERSION >= 10200 4756110560Sgshapiroph_map_recv_debug(appdata, text) 4757110560Sgshapiro void *appdata; 4758110560Sgshapiro#else 475990792Sgshapiroph_map_recv_debug(text) 4760110560Sgshapiro#endif 476190792Sgshapiro char *text; 476290792Sgshapiro{ 476390792Sgshapiro if (LogLevel > 10) 476490792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 476590792Sgshapiro "ph_map_recv_debug: <== %s", text); 476690792Sgshapiro if (tTd(38, 21)) 476790792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 476864562Sgshapiro} 476964562Sgshapiro 477090792Sgshapiro/* 477164562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 477264562Sgshapiro*/ 477364562Sgshapirobool 477464562Sgshapiroph_map_open(map, mode) 477564562Sgshapiro MAP *map; 477664562Sgshapiro int mode; 477764562Sgshapiro{ 477890792Sgshapiro PH_MAP_STRUCT *pmap; 477990792Sgshapiro register SM_EVENT *ev = NULL; 478064562Sgshapiro int save_errno = 0; 478190792Sgshapiro char *hostlist, *host; 478264562Sgshapiro 478364562Sgshapiro if (tTd(38, 2)) 478490792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 478564562Sgshapiro 478664562Sgshapiro mode &= O_ACCMODE; 478764562Sgshapiro if (mode != O_RDONLY) 478864562Sgshapiro { 478964562Sgshapiro /* issue a pseudo-error message */ 479090792Sgshapiro errno = SM_EMAPCANTWRITE; 479190792Sgshapiro return false; 479264562Sgshapiro } 479364562Sgshapiro 479466494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 479566494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 479666494Sgshapiro { 479766494Sgshapiro if (tTd(9, 1)) 479890792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 479990792Sgshapiro map->map_mname); 480066494Sgshapiro 480166494Sgshapiro /* 480290792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 480390792Sgshapiro ** a temporary failure using the bogus map and 480490792Sgshapiro ** map->map_tapp instead of the default permanent error. 480566494Sgshapiro */ 480666494Sgshapiro 480766494Sgshapiro map->map_mflags &= ~MF_DEFER; 480890792Sgshapiro return false; 480966494Sgshapiro } 481066494Sgshapiro 481164562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 481290792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 481364562Sgshapiro 481490792Sgshapiro /* try each host in the list */ 481564562Sgshapiro hostlist = newstr(pmap->ph_servers); 481690792Sgshapiro for (host = strtok(hostlist, " "); 481790792Sgshapiro host != NULL; 481890792Sgshapiro host = strtok(NULL, " ")) 481964562Sgshapiro { 482090792Sgshapiro /* set timeout */ 482164562Sgshapiro if (pmap->ph_timeout != 0) 482264562Sgshapiro { 482364562Sgshapiro if (setjmp(PHTimeout) != 0) 482464562Sgshapiro { 482564562Sgshapiro ev = NULL; 482664562Sgshapiro if (LogLevel > 1) 482764562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 482864562Sgshapiro "timeout connecting to PH server %.100s", 482990792Sgshapiro host); 483064562Sgshapiro errno = ETIMEDOUT; 483164562Sgshapiro goto ph_map_open_abort; 483264562Sgshapiro } 483390792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 483464562Sgshapiro } 483590792Sgshapiro 483690792Sgshapiro /* open connection to server */ 4837110560Sgshapiro if (ph_open(&(pmap->ph), host, 4838110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 4839110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 4840110560Sgshapiro#if NPH_VERSION >= 10200 4841110560Sgshapiro , NULL 4842110560Sgshapiro#endif 4843110560Sgshapiro ) == 0 4844110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 484564562Sgshapiro { 484664562Sgshapiro if (ev != NULL) 484790792Sgshapiro sm_clrevent(ev); 484890792Sgshapiro sm_free(hostlist); /* XXX */ 484990792Sgshapiro return true; 485064562Sgshapiro } 485190792Sgshapiro 485264562Sgshapiro ph_map_open_abort: 485390792Sgshapiro save_errno = errno; 485464562Sgshapiro if (ev != NULL) 485590792Sgshapiro sm_clrevent(ev); 4856110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 485790792Sgshapiro ph_map_close(map); 485890792Sgshapiro errno = save_errno; 485990792Sgshapiro } 486064562Sgshapiro 486166494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 486264562Sgshapiro { 486366494Sgshapiro if (errno == 0) 486464562Sgshapiro errno = EAGAIN; 486566494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 486666494Sgshapiro map->map_mname); 486764562Sgshapiro } 486866494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 486964562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 487066494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 487166494Sgshapiro map->map_mname); 487290792Sgshapiro sm_free(hostlist); /* XXX */ 487390792Sgshapiro return false; 487464562Sgshapiro} 487564562Sgshapiro 487664562Sgshapiro/* 487764562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 487864562Sgshapiro*/ 487964562Sgshapiro 488064562Sgshapirochar * 488164562Sgshapiroph_map_lookup(map, key, args, pstat) 488264562Sgshapiro MAP *map; 488364562Sgshapiro char *key; 488464562Sgshapiro char **args; 488564562Sgshapiro int *pstat; 488664562Sgshapiro{ 488790792Sgshapiro int i, save_errno = 0; 488890792Sgshapiro register SM_EVENT *ev = NULL; 488964562Sgshapiro PH_MAP_STRUCT *pmap; 489090792Sgshapiro char *value = NULL; 489164562Sgshapiro 489264562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 489364562Sgshapiro 489464562Sgshapiro *pstat = EX_OK; 489564562Sgshapiro 489690792Sgshapiro /* set timeout */ 489764562Sgshapiro if (pmap->ph_timeout != 0) 489864562Sgshapiro { 489964562Sgshapiro if (setjmp(PHTimeout) != 0) 490064562Sgshapiro { 490164562Sgshapiro ev = NULL; 490264562Sgshapiro if (LogLevel > 1) 490364562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 490464562Sgshapiro "timeout during PH lookup of %.100s", 490564562Sgshapiro key); 490664562Sgshapiro errno = ETIMEDOUT; 490764562Sgshapiro *pstat = EX_TEMPFAIL; 490864562Sgshapiro goto ph_map_lookup_abort; 490964562Sgshapiro } 491090792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 491164562Sgshapiro } 491264562Sgshapiro 491390792Sgshapiro /* perform lookup */ 491490792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 491590792Sgshapiro if (i == -1) 491690792Sgshapiro *pstat = EX_TEMPFAIL; 4917110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 491890792Sgshapiro *pstat = EX_UNAVAILABLE; 491964562Sgshapiro 492064562Sgshapiro ph_map_lookup_abort: 492164562Sgshapiro if (ev != NULL) 492290792Sgshapiro sm_clrevent(ev); 492364562Sgshapiro 492464562Sgshapiro /* 492590792Sgshapiro ** Close the connection if the timer popped 492664562Sgshapiro ** or we got a temporary PH error 492764562Sgshapiro */ 492864562Sgshapiro 492964562Sgshapiro if (*pstat == EX_TEMPFAIL) 493090792Sgshapiro { 493190792Sgshapiro save_errno = errno; 4932110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 493390792Sgshapiro ph_map_close(map); 493490792Sgshapiro errno = save_errno; 493590792Sgshapiro } 493664562Sgshapiro 493764562Sgshapiro if (*pstat == EX_OK) 493864562Sgshapiro { 493964562Sgshapiro if (tTd(38,20)) 494090792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 494164562Sgshapiro 494264562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 494390792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 494464562Sgshapiro else 494590792Sgshapiro return map_rewrite(map, value, strlen(value), args); 494664562Sgshapiro } 494764562Sgshapiro 494864562Sgshapiro return NULL; 494964562Sgshapiro} 495064562Sgshapiro#endif /* PH_MAP */ 495190792Sgshapiro/* 495242575Speter** syslog map 495338032Speter*/ 495438032Speter 495538032Speter#define map_prio map_lockfd /* overload field */ 495638032Speter 495738032Speter/* 495842575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 495938032Speter*/ 496038032Speter 496138032Speterbool 496238032Spetersyslog_map_parseargs(map, args) 496338032Speter MAP *map; 496438032Speter char *args; 496538032Speter{ 496638032Speter char *p = args; 496738032Speter char *priority = NULL; 496838032Speter 496964562Sgshapiro /* there is no check whether there is really an argument */ 497064562Sgshapiro while (*p != '\0') 497138032Speter { 497238032Speter while (isascii(*p) && isspace(*p)) 497338032Speter p++; 497438032Speter if (*p != '-') 497538032Speter break; 497664562Sgshapiro ++p; 497764562Sgshapiro if (*p == 'D') 497864562Sgshapiro { 497964562Sgshapiro map->map_mflags |= MF_DEFER; 498064562Sgshapiro ++p; 498164562Sgshapiro } 498264562Sgshapiro else if (*p == 'S') 498364562Sgshapiro { 498464562Sgshapiro map->map_spacesub = *++p; 498564562Sgshapiro if (*p != '\0') 498664562Sgshapiro p++; 498764562Sgshapiro } 498864562Sgshapiro else if (*p == 'L') 498964562Sgshapiro { 499064562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 499164562Sgshapiro continue; 499264562Sgshapiro if (*p == '\0') 499364562Sgshapiro break; 499464562Sgshapiro priority = p; 499564562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 499664562Sgshapiro p++; 499764562Sgshapiro if (*p != '\0') 499864562Sgshapiro *p++ = '\0'; 499964562Sgshapiro } 500064562Sgshapiro else 500164562Sgshapiro { 500264562Sgshapiro syserr("Illegal option %c map syslog", *p); 500364562Sgshapiro ++p; 500464562Sgshapiro } 500538032Speter } 500638032Speter 500738032Speter if (priority == NULL) 500838032Speter map->map_prio = LOG_INFO; 500938032Speter else 501038032Speter { 501190792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 501238032Speter priority += 4; 501338032Speter 501438032Speter#ifdef LOG_EMERG 501590792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 501638032Speter map->map_prio = LOG_EMERG; 501738032Speter else 501864562Sgshapiro#endif /* LOG_EMERG */ 501938032Speter#ifdef LOG_ALERT 502090792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 502138032Speter map->map_prio = LOG_ALERT; 502238032Speter else 502364562Sgshapiro#endif /* LOG_ALERT */ 502438032Speter#ifdef LOG_CRIT 502590792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 502638032Speter map->map_prio = LOG_CRIT; 502738032Speter else 502864562Sgshapiro#endif /* LOG_CRIT */ 502938032Speter#ifdef LOG_ERR 503090792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 503138032Speter map->map_prio = LOG_ERR; 503238032Speter else 503364562Sgshapiro#endif /* LOG_ERR */ 503438032Speter#ifdef LOG_WARNING 503590792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 503638032Speter map->map_prio = LOG_WARNING; 503738032Speter else 503864562Sgshapiro#endif /* LOG_WARNING */ 503938032Speter#ifdef LOG_NOTICE 504090792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 504138032Speter map->map_prio = LOG_NOTICE; 504238032Speter else 504364562Sgshapiro#endif /* LOG_NOTICE */ 504438032Speter#ifdef LOG_INFO 504590792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 504638032Speter map->map_prio = LOG_INFO; 504738032Speter else 504864562Sgshapiro#endif /* LOG_INFO */ 504938032Speter#ifdef LOG_DEBUG 505090792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 505138032Speter map->map_prio = LOG_DEBUG; 505238032Speter else 505364562Sgshapiro#endif /* LOG_DEBUG */ 505438032Speter { 505590792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 505638032Speter priority); 505790792Sgshapiro return false; 505838032Speter } 505938032Speter } 506090792Sgshapiro return true; 506138032Speter} 506238032Speter 506338032Speter/* 506442575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 506538032Speter*/ 506638032Speter 506738032Speterchar * 506838032Spetersyslog_map_lookup(map, string, args, statp) 506938032Speter MAP *map; 507038032Speter char *string; 507138032Speter char **args; 507238032Speter int *statp; 507338032Speter{ 507438032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 507538032Speter 507638032Speter if (ptr != NULL) 507738032Speter { 507838032Speter if (tTd(38, 20)) 507990792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 508064562Sgshapiro map->map_mname, map->map_prio, ptr); 508138032Speter 508238032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 508338032Speter } 508438032Speter 508538032Speter *statp = EX_OK; 508638032Speter return ""; 508738032Speter} 508838032Speter 508990792Sgshapiro/* 509038032Speter** HESIOD Modules 509138032Speter*/ 509238032Speter 509390792Sgshapiro#if HESIOD 509438032Speter 509538032Speterbool 509638032Speterhes_map_open(map, mode) 509738032Speter MAP *map; 509838032Speter int mode; 509938032Speter{ 510038032Speter if (tTd(38, 2)) 510190792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 510238032Speter map->map_mname, map->map_file, mode); 510338032Speter 510438032Speter if (mode != O_RDONLY) 510538032Speter { 510638032Speter /* issue a pseudo-error message */ 510790792Sgshapiro errno = SM_EMAPCANTWRITE; 510890792Sgshapiro return false; 510938032Speter } 511038032Speter 511164562Sgshapiro# ifdef HESIOD_INIT 511238032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 511390792Sgshapiro return true; 511438032Speter 511538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 511694334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 511790792Sgshapiro sm_errstring(errno)); 511890792Sgshapiro return false; 511964562Sgshapiro# else /* HESIOD_INIT */ 512038032Speter if (hes_error() == HES_ER_UNINIT) 512138032Speter hes_init(); 512238032Speter switch (hes_error()) 512338032Speter { 512438032Speter case HES_ER_OK: 512538032Speter case HES_ER_NOTFOUND: 512690792Sgshapiro return true; 512738032Speter } 512838032Speter 512938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 513094334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 513138032Speter 513290792Sgshapiro return false; 513364562Sgshapiro# endif /* HESIOD_INIT */ 513438032Speter} 513538032Speter 513638032Speterchar * 513738032Speterhes_map_lookup(map, name, av, statp) 513838032Speter MAP *map; 513938032Speter char *name; 514038032Speter char **av; 514138032Speter int *statp; 514238032Speter{ 514338032Speter char **hp; 514438032Speter 514538032Speter if (tTd(38, 20)) 514690792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 514738032Speter 514838032Speter if (name[0] == '\\') 514938032Speter { 515038032Speter char *np; 515138032Speter int nl; 515277349Sgshapiro int save_errno; 515338032Speter char nbuf[MAXNAME]; 515438032Speter 515538032Speter nl = strlen(name); 515638032Speter if (nl < sizeof nbuf - 1) 515738032Speter np = nbuf; 515838032Speter else 515938032Speter np = xalloc(strlen(name) + 2); 516038032Speter np[0] = '\\'; 516190792Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof nbuf) - 1); 516264562Sgshapiro# ifdef HESIOD_INIT 516338032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 516464562Sgshapiro# else /* HESIOD_INIT */ 516538032Speter hp = hes_resolve(np, map->map_file); 516664562Sgshapiro# endif /* HESIOD_INIT */ 516777349Sgshapiro save_errno = errno; 516838032Speter if (np != nbuf) 516990792Sgshapiro sm_free(np); /* XXX */ 517077349Sgshapiro errno = save_errno; 517138032Speter } 517238032Speter else 517338032Speter { 517464562Sgshapiro# ifdef HESIOD_INIT 517538032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 517664562Sgshapiro# else /* HESIOD_INIT */ 517738032Speter hp = hes_resolve(name, map->map_file); 517864562Sgshapiro# endif /* HESIOD_INIT */ 517938032Speter } 518064562Sgshapiro# ifdef HESIOD_INIT 518177349Sgshapiro if (hp == NULL || *hp == NULL) 518238032Speter { 518338032Speter switch (errno) 518438032Speter { 518538032Speter case ENOENT: 518638032Speter *statp = EX_NOTFOUND; 518738032Speter break; 518838032Speter case ECONNREFUSED: 518938032Speter *statp = EX_TEMPFAIL; 519038032Speter break; 519190792Sgshapiro case EMSGSIZE: 519238032Speter case ENOMEM: 519338032Speter default: 519438032Speter *statp = EX_UNAVAILABLE; 519538032Speter break; 519638032Speter } 519782017Sgshapiro if (hp != NULL) 519882017Sgshapiro hesiod_free_list(HesiodContext, hp); 519938032Speter return NULL; 520038032Speter } 520164562Sgshapiro# else /* HESIOD_INIT */ 520238032Speter if (hp == NULL || hp[0] == NULL) 520338032Speter { 520438032Speter switch (hes_error()) 520538032Speter { 520638032Speter case HES_ER_OK: 520738032Speter *statp = EX_OK; 520838032Speter break; 520938032Speter 521038032Speter case HES_ER_NOTFOUND: 521138032Speter *statp = EX_NOTFOUND; 521238032Speter break; 521338032Speter 521438032Speter case HES_ER_CONFIG: 521538032Speter *statp = EX_UNAVAILABLE; 521638032Speter break; 521738032Speter 521838032Speter case HES_ER_NET: 521938032Speter *statp = EX_TEMPFAIL; 522038032Speter break; 522138032Speter } 522238032Speter return NULL; 522338032Speter } 522464562Sgshapiro# endif /* HESIOD_INIT */ 522538032Speter 522638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 522738032Speter return map_rewrite(map, name, strlen(name), NULL); 522838032Speter else 522938032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 523038032Speter} 523138032Speter 523290792Sgshapiro/* 523390792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 523490792Sgshapiro*/ 523590792Sgshapiro 523690792Sgshapirovoid 523790792Sgshapirohes_map_close(map) 523890792Sgshapiro MAP *map; 523990792Sgshapiro{ 524090792Sgshapiro if (tTd(38, 20)) 524190792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 524290792Sgshapiro 524390792Sgshapiro# ifdef HESIOD_INIT 524490792Sgshapiro /* Free the hesiod context */ 524590792Sgshapiro if (HesiodContext != NULL) 524690792Sgshapiro { 524790792Sgshapiro hesiod_end(HesiodContext); 524890792Sgshapiro HesiodContext = NULL; 524990792Sgshapiro } 525090792Sgshapiro# endif /* HESIOD_INIT */ 525190792Sgshapiro} 525290792Sgshapiro 525364562Sgshapiro#endif /* HESIOD */ 525490792Sgshapiro/* 525538032Speter** NeXT NETINFO Modules 525638032Speter*/ 525738032Speter 525838032Speter#if NETINFO 525938032Speter 526038032Speter# define NETINFO_DEFAULT_DIR "/aliases" 526138032Speter# define NETINFO_DEFAULT_PROPERTY "members" 526238032Speter 526338032Speter/* 526438032Speter** NI_MAP_OPEN -- open NetInfo Aliases 526538032Speter*/ 526638032Speter 526738032Speterbool 526838032Speterni_map_open(map, mode) 526938032Speter MAP *map; 527038032Speter int mode; 527138032Speter{ 527238032Speter if (tTd(38, 2)) 527390792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 527438032Speter map->map_mname, map->map_file, mode); 527538032Speter mode &= O_ACCMODE; 527638032Speter 527738032Speter if (*map->map_file == '\0') 527838032Speter map->map_file = NETINFO_DEFAULT_DIR; 527938032Speter 528038032Speter if (map->map_valcolnm == NULL) 528138032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 528238032Speter 528390792Sgshapiro if (map->map_coldelim == '\0') 528490792Sgshapiro { 528590792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 528690792Sgshapiro map->map_coldelim = ','; 528790792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 528890792Sgshapiro map->map_coldelim = ' '; 528990792Sgshapiro } 529090792Sgshapiro return true; 529138032Speter} 529238032Speter 529338032Speter 529438032Speter/* 529538032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 529638032Speter*/ 529738032Speter 529838032Speterchar * 529938032Speterni_map_lookup(map, name, av, statp) 530038032Speter MAP *map; 530138032Speter char *name; 530238032Speter char **av; 530338032Speter int *statp; 530438032Speter{ 530538032Speter char *res; 530638032Speter char *propval; 530738032Speter 530838032Speter if (tTd(38, 20)) 530990792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 531038032Speter 531138032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 531238032Speter map->map_valcolnm, map->map_coldelim); 531338032Speter 531438032Speter if (propval == NULL) 531538032Speter return NULL; 531638032Speter 531790792Sgshapiro SM_TRY 531890792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 531990792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 532090792Sgshapiro else 532190792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 532290792Sgshapiro SM_FINALLY 532390792Sgshapiro sm_free(propval); 532490792Sgshapiro SM_END_TRY 532538032Speter return res; 532638032Speter} 532738032Speter 532838032Speter 532964562Sgshapirostatic bool 533038032Speterni_getcanonname(name, hbsize, statp) 533138032Speter char *name; 533238032Speter int hbsize; 533338032Speter int *statp; 533438032Speter{ 533538032Speter char *vptr; 533638032Speter char *ptr; 533738032Speter char nbuf[MAXNAME + 1]; 533838032Speter 533938032Speter if (tTd(38, 20)) 534090792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 534138032Speter 534290792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 534338032Speter { 534438032Speter *statp = EX_UNAVAILABLE; 534590792Sgshapiro return false; 534638032Speter } 534773188Sgshapiro (void) shorten_hostname(nbuf); 534838032Speter 534938032Speter /* we only accept single token search key */ 535038032Speter if (strchr(nbuf, '.')) 535138032Speter { 535238032Speter *statp = EX_NOHOST; 535390792Sgshapiro return false; 535438032Speter } 535538032Speter 535638032Speter /* Do the search */ 535738032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 535838032Speter 535938032Speter if (vptr == NULL) 536038032Speter { 536138032Speter *statp = EX_NOHOST; 536290792Sgshapiro return false; 536338032Speter } 536438032Speter 536538032Speter /* Only want the first machine name */ 536638032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 536738032Speter *ptr = '\0'; 536838032Speter 536990792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 537038032Speter { 537177349Sgshapiro sm_free(vptr); 537290792Sgshapiro *statp = EX_UNAVAILABLE; 537390792Sgshapiro return true; 537438032Speter } 537577349Sgshapiro sm_free(vptr); 537690792Sgshapiro *statp = EX_OK; 537790792Sgshapiro return false; 537838032Speter} 537990792Sgshapiro#endif /* NETINFO */ 538038032Speter/* 538138032Speter** TEXT (unindexed text file) Modules 538238032Speter** 538338032Speter** This code donated by Sun Microsystems. 538438032Speter*/ 538538032Speter 538638032Speter#define map_sff map_lockfd /* overload field */ 538738032Speter 538838032Speter 538938032Speter/* 539038032Speter** TEXT_MAP_OPEN -- open text table 539138032Speter*/ 539238032Speter 539338032Speterbool 539438032Spetertext_map_open(map, mode) 539538032Speter MAP *map; 539638032Speter int mode; 539738032Speter{ 539864562Sgshapiro long sff; 539938032Speter int i; 540038032Speter 540138032Speter if (tTd(38, 2)) 540290792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 540338032Speter map->map_mname, map->map_file, mode); 540438032Speter 540538032Speter mode &= O_ACCMODE; 540638032Speter if (mode != O_RDONLY) 540738032Speter { 540838032Speter errno = EPERM; 540990792Sgshapiro return false; 541038032Speter } 541138032Speter 541238032Speter if (*map->map_file == '\0') 541338032Speter { 541438032Speter syserr("text map \"%s\": file name required", 541538032Speter map->map_mname); 541690792Sgshapiro return false; 541738032Speter } 541838032Speter 541938032Speter if (map->map_file[0] != '/') 542038032Speter { 542138032Speter syserr("text map \"%s\": file name must be fully qualified", 542238032Speter map->map_mname); 542390792Sgshapiro return false; 542438032Speter } 542538032Speter 542638032Speter sff = SFF_ROOTOK|SFF_REGONLY; 542764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 542838032Speter sff |= SFF_NOWLINK; 542964562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 543038032Speter sff |= SFF_SAFEDIRPATH; 543138032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 543238032Speter sff, S_IRUSR, NULL)) != 0) 543338032Speter { 543464562Sgshapiro int save_errno = errno; 543564562Sgshapiro 543638032Speter /* cannot open this map */ 543738032Speter if (tTd(38, 2)) 543890792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 543964562Sgshapiro errno = save_errno; 544038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 544138032Speter syserr("text map \"%s\": unsafe map file %s", 544238032Speter map->map_mname, map->map_file); 544390792Sgshapiro return false; 544438032Speter } 544538032Speter 544638032Speter if (map->map_keycolnm == NULL) 544738032Speter map->map_keycolno = 0; 544838032Speter else 544938032Speter { 545038032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 545138032Speter { 545238032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 545338032Speter map->map_mname, map->map_file, 545438032Speter map->map_keycolnm); 545590792Sgshapiro return false; 545638032Speter } 545738032Speter map->map_keycolno = atoi(map->map_keycolnm); 545838032Speter } 545938032Speter 546038032Speter if (map->map_valcolnm == NULL) 546138032Speter map->map_valcolno = 0; 546238032Speter else 546338032Speter { 546438032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 546538032Speter { 546638032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 546738032Speter map->map_mname, map->map_file, 546838032Speter map->map_valcolnm); 546990792Sgshapiro return false; 547038032Speter } 547138032Speter map->map_valcolno = atoi(map->map_valcolnm); 547238032Speter } 547338032Speter 547438032Speter if (tTd(38, 2)) 547538032Speter { 547690792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 547738032Speter map->map_mname, map->map_file); 547838032Speter if (map->map_coldelim == '\0') 547990792Sgshapiro sm_dprintf("(white space)\n"); 548038032Speter else 548190792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 548238032Speter } 548338032Speter 548438032Speter map->map_sff = sff; 548590792Sgshapiro return true; 548638032Speter} 548738032Speter 548838032Speter 548938032Speter/* 549038032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 549138032Speter*/ 549238032Speter 549338032Speterchar * 549438032Spetertext_map_lookup(map, name, av, statp) 549538032Speter MAP *map; 549638032Speter char *name; 549738032Speter char **av; 549838032Speter int *statp; 549938032Speter{ 550038032Speter char *vp; 550138032Speter auto int vsize; 550238032Speter int buflen; 550390792Sgshapiro SM_FILE_T *f; 550438032Speter char delim; 550538032Speter int key_idx; 550638032Speter bool found_it; 550764562Sgshapiro long sff = map->map_sff; 550838032Speter char search_key[MAXNAME + 1]; 550938032Speter char linebuf[MAXLINE]; 551038032Speter char buf[MAXNAME + 1]; 551138032Speter 551290792Sgshapiro found_it = false; 551338032Speter if (tTd(38, 20)) 551490792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 551538032Speter 551638032Speter buflen = strlen(name); 551738032Speter if (buflen > sizeof search_key - 1) 551890792Sgshapiro buflen = sizeof search_key - 1; /* XXX just cut if off? */ 551964562Sgshapiro memmove(search_key, name, buflen); 552038032Speter search_key[buflen] = '\0'; 552138032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 552238032Speter makelower(search_key); 552338032Speter 552438032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 552538032Speter if (f == NULL) 552638032Speter { 552738032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 552838032Speter *statp = EX_UNAVAILABLE; 552938032Speter return NULL; 553038032Speter } 553138032Speter key_idx = map->map_keycolno; 553238032Speter delim = map->map_coldelim; 553398121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 553498121Sgshapiro linebuf, sizeof linebuf) != NULL) 553538032Speter { 553638032Speter char *p; 553738032Speter 553838032Speter /* skip comment line */ 553938032Speter if (linebuf[0] == '#') 554038032Speter continue; 554138032Speter p = strchr(linebuf, '\n'); 554238032Speter if (p != NULL) 554338032Speter *p = '\0'; 554438032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 554590792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 554638032Speter { 554790792Sgshapiro found_it = true; 554838032Speter break; 554938032Speter } 555038032Speter } 555190792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 555238032Speter if (!found_it) 555338032Speter { 555438032Speter *statp = EX_NOTFOUND; 555538032Speter return NULL; 555638032Speter } 555738032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 555842575Speter if (vp == NULL) 555942575Speter { 556042575Speter *statp = EX_NOTFOUND; 556142575Speter return NULL; 556242575Speter } 556338032Speter vsize = strlen(vp); 556438032Speter *statp = EX_OK; 556538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 556638032Speter return map_rewrite(map, name, strlen(name), NULL); 556738032Speter else 556838032Speter return map_rewrite(map, vp, vsize, av); 556938032Speter} 557038032Speter 557138032Speter/* 557238032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 557338032Speter*/ 557438032Speter 557564562Sgshapirostatic bool 557638032Spetertext_getcanonname(name, hbsize, statp) 557738032Speter char *name; 557838032Speter int hbsize; 557938032Speter int *statp; 558038032Speter{ 558138032Speter bool found; 558273188Sgshapiro char *dot; 558390792Sgshapiro SM_FILE_T *f; 558438032Speter char linebuf[MAXLINE]; 558538032Speter char cbuf[MAXNAME + 1]; 558638032Speter char nbuf[MAXNAME + 1]; 558738032Speter 558838032Speter if (tTd(38, 20)) 558990792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 559038032Speter 559190792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 559238032Speter { 559338032Speter *statp = EX_UNAVAILABLE; 559490792Sgshapiro return false; 559538032Speter } 559673188Sgshapiro dot = shorten_hostname(nbuf); 559738032Speter 559890792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 559990792Sgshapiro NULL); 560038032Speter if (f == NULL) 560138032Speter { 560238032Speter *statp = EX_UNAVAILABLE; 560390792Sgshapiro return false; 560438032Speter } 560590792Sgshapiro found = false; 560690792Sgshapiro while (!found && 560798121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 560898121Sgshapiro linebuf, sizeof linebuf) != NULL) 560938032Speter { 561038032Speter char *p = strpbrk(linebuf, "#\n"); 561138032Speter 561238032Speter if (p != NULL) 561338032Speter *p = '\0'; 561438032Speter if (linebuf[0] != '\0') 561573188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 561673188Sgshapiro cbuf, sizeof cbuf); 561738032Speter } 561890792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 561938032Speter if (!found) 562038032Speter { 562138032Speter *statp = EX_NOHOST; 562290792Sgshapiro return false; 562338032Speter } 562438032Speter 562590792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 562638032Speter { 562790792Sgshapiro *statp = EX_UNAVAILABLE; 562890792Sgshapiro return false; 562938032Speter } 563090792Sgshapiro *statp = EX_OK; 563190792Sgshapiro return true; 563238032Speter} 563390792Sgshapiro/* 563438032Speter** STAB (Symbol Table) Modules 563538032Speter*/ 563638032Speter 563738032Speter 563838032Speter/* 563938032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 564038032Speter*/ 564138032Speter 564238032Speter/* ARGSUSED2 */ 564338032Speterchar * 564438032Speterstab_map_lookup(map, name, av, pstat) 564538032Speter register MAP *map; 564638032Speter char *name; 564738032Speter char **av; 564838032Speter int *pstat; 564938032Speter{ 565038032Speter register STAB *s; 565138032Speter 565238032Speter if (tTd(38, 20)) 565390792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 565438032Speter map->map_mname, name); 565538032Speter 565638032Speter s = stab(name, ST_ALIAS, ST_FIND); 565738032Speter if (s != NULL) 565864562Sgshapiro return s->s_alias; 565964562Sgshapiro return NULL; 566038032Speter} 566138032Speter 566238032Speter 566338032Speter/* 566438032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 566538032Speter*/ 566638032Speter 566738032Spetervoid 566838032Speterstab_map_store(map, lhs, rhs) 566938032Speter register MAP *map; 567038032Speter char *lhs; 567138032Speter char *rhs; 567238032Speter{ 567338032Speter register STAB *s; 567438032Speter 567538032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 567638032Speter s->s_alias = newstr(rhs); 567738032Speter} 567838032Speter 567938032Speter 568038032Speter/* 568138032Speter** STAB_MAP_OPEN -- initialize (reads data file) 568238032Speter** 568338032Speter** This is a wierd case -- it is only intended as a fallback for 568438032Speter** aliases. For this reason, opens for write (only during a 568538032Speter** "newaliases") always fails, and opens for read open the 568638032Speter** actual underlying text file instead of the database. 568738032Speter*/ 568838032Speter 568938032Speterbool 569038032Speterstab_map_open(map, mode) 569138032Speter register MAP *map; 569238032Speter int mode; 569338032Speter{ 569490792Sgshapiro SM_FILE_T *af; 569564562Sgshapiro long sff; 569638032Speter struct stat st; 569738032Speter 569838032Speter if (tTd(38, 2)) 569990792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 570038032Speter map->map_mname, map->map_file, mode); 570138032Speter 570238032Speter mode &= O_ACCMODE; 570338032Speter if (mode != O_RDONLY) 570438032Speter { 570538032Speter errno = EPERM; 570690792Sgshapiro return false; 570738032Speter } 570838032Speter 570938032Speter sff = SFF_ROOTOK|SFF_REGONLY; 571064562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 571138032Speter sff |= SFF_NOWLINK; 571264562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 571338032Speter sff |= SFF_SAFEDIRPATH; 571438032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 571538032Speter if (af == NULL) 571690792Sgshapiro return false; 571790792Sgshapiro readaliases(map, af, false, false); 571838032Speter 571990792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 572038032Speter map->map_mtime = st.st_mtime; 572190792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 572238032Speter 572390792Sgshapiro return true; 572438032Speter} 572590792Sgshapiro/* 572638032Speter** Implicit Modules 572738032Speter** 572838032Speter** Tries several types. For back compatibility of aliases. 572938032Speter*/ 573038032Speter 573138032Speter 573238032Speter/* 573338032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 573438032Speter*/ 573538032Speter 573638032Speterchar * 573738032Speterimpl_map_lookup(map, name, av, pstat) 573838032Speter MAP *map; 573938032Speter char *name; 574038032Speter char **av; 574138032Speter int *pstat; 574238032Speter{ 574338032Speter if (tTd(38, 20)) 574490792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 574538032Speter map->map_mname, name); 574638032Speter 574790792Sgshapiro#if NEWDB 574838032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 574938032Speter return db_map_lookup(map, name, av, pstat); 575064562Sgshapiro#endif /* NEWDB */ 575190792Sgshapiro#if NDBM 575238032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 575338032Speter return ndbm_map_lookup(map, name, av, pstat); 575464562Sgshapiro#endif /* NDBM */ 575538032Speter return stab_map_lookup(map, name, av, pstat); 575638032Speter} 575738032Speter 575838032Speter/* 575938032Speter** IMPL_MAP_STORE -- store in open databases 576038032Speter*/ 576138032Speter 576238032Spetervoid 576338032Speterimpl_map_store(map, lhs, rhs) 576438032Speter MAP *map; 576538032Speter char *lhs; 576638032Speter char *rhs; 576738032Speter{ 576838032Speter if (tTd(38, 12)) 576990792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 577038032Speter map->map_mname, lhs, rhs); 577190792Sgshapiro#if NEWDB 577238032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 577338032Speter db_map_store(map, lhs, rhs); 577464562Sgshapiro#endif /* NEWDB */ 577590792Sgshapiro#if NDBM 577638032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 577738032Speter ndbm_map_store(map, lhs, rhs); 577864562Sgshapiro#endif /* NDBM */ 577938032Speter stab_map_store(map, lhs, rhs); 578038032Speter} 578138032Speter 578238032Speter/* 578338032Speter** IMPL_MAP_OPEN -- implicit database open 578438032Speter*/ 578538032Speter 578638032Speterbool 578738032Speterimpl_map_open(map, mode) 578838032Speter MAP *map; 578938032Speter int mode; 579038032Speter{ 579138032Speter if (tTd(38, 2)) 579290792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 579338032Speter map->map_mname, map->map_file, mode); 579438032Speter 579538032Speter mode &= O_ACCMODE; 579690792Sgshapiro#if NEWDB 579738032Speter map->map_mflags |= MF_IMPL_HASH; 579838032Speter if (hash_map_open(map, mode)) 579938032Speter { 580038032Speter# ifdef NDBM_YP_COMPAT 580138032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 580264562Sgshapiro# endif /* NDBM_YP_COMPAT */ 580390792Sgshapiro return true; 580438032Speter } 580538032Speter else 580638032Speter map->map_mflags &= ~MF_IMPL_HASH; 580764562Sgshapiro#endif /* NEWDB */ 580890792Sgshapiro#if NDBM 580938032Speter map->map_mflags |= MF_IMPL_NDBM; 581038032Speter if (ndbm_map_open(map, mode)) 581138032Speter { 581290792Sgshapiro return true; 581338032Speter } 581438032Speter else 581538032Speter map->map_mflags &= ~MF_IMPL_NDBM; 581664562Sgshapiro#endif /* NDBM */ 581738032Speter 581838032Speter#if defined(NEWDB) || defined(NDBM) 581938032Speter if (Verbose) 582038032Speter message("WARNING: cannot open alias database %s%s", 582138032Speter map->map_file, 582238032Speter mode == O_RDONLY ? "; reading text version" : ""); 582364562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 582438032Speter if (mode != O_RDONLY) 582538032Speter usrerr("Cannot rebuild aliases: no database format defined"); 582664562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 582738032Speter 582838032Speter if (mode == O_RDONLY) 582938032Speter return stab_map_open(map, mode); 583038032Speter else 583190792Sgshapiro return false; 583238032Speter} 583338032Speter 583438032Speter 583538032Speter/* 583638032Speter** IMPL_MAP_CLOSE -- close any open database(s) 583738032Speter*/ 583838032Speter 583938032Spetervoid 584038032Speterimpl_map_close(map) 584138032Speter MAP *map; 584238032Speter{ 584338032Speter if (tTd(38, 9)) 584490792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 584538032Speter map->map_mname, map->map_file, map->map_mflags); 584690792Sgshapiro#if NEWDB 584738032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 584838032Speter { 584938032Speter db_map_close(map); 585038032Speter map->map_mflags &= ~MF_IMPL_HASH; 585138032Speter } 585264562Sgshapiro#endif /* NEWDB */ 585338032Speter 585490792Sgshapiro#if NDBM 585538032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 585638032Speter { 585738032Speter ndbm_map_close(map); 585838032Speter map->map_mflags &= ~MF_IMPL_NDBM; 585938032Speter } 586064562Sgshapiro#endif /* NDBM */ 586138032Speter} 586290792Sgshapiro/* 586338032Speter** User map class. 586438032Speter** 586538032Speter** Provides access to the system password file. 586638032Speter*/ 586738032Speter 586838032Speter/* 586938032Speter** USER_MAP_OPEN -- open user map 587038032Speter** 587138032Speter** Really just binds field names to field numbers. 587238032Speter*/ 587338032Speter 587438032Speterbool 587538032Speteruser_map_open(map, mode) 587638032Speter MAP *map; 587738032Speter int mode; 587838032Speter{ 587938032Speter if (tTd(38, 2)) 588090792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 588138032Speter map->map_mname, mode); 588238032Speter 588338032Speter mode &= O_ACCMODE; 588438032Speter if (mode != O_RDONLY) 588538032Speter { 588638032Speter /* issue a pseudo-error message */ 588790792Sgshapiro errno = SM_EMAPCANTWRITE; 588890792Sgshapiro return false; 588938032Speter } 589038032Speter if (map->map_valcolnm == NULL) 589164562Sgshapiro /* EMPTY */ 589238032Speter /* nothing */ ; 589390792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 589438032Speter map->map_valcolno = 1; 589590792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 589638032Speter map->map_valcolno = 2; 589790792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 589838032Speter map->map_valcolno = 3; 589990792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 590038032Speter map->map_valcolno = 4; 590190792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 590238032Speter map->map_valcolno = 5; 590390792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 590438032Speter map->map_valcolno = 6; 590590792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 590638032Speter map->map_valcolno = 7; 590738032Speter else 590838032Speter { 590938032Speter syserr("User map %s: unknown column name %s", 591038032Speter map->map_mname, map->map_valcolnm); 591190792Sgshapiro return false; 591238032Speter } 591390792Sgshapiro return true; 591438032Speter} 591538032Speter 591638032Speter 591738032Speter/* 591838032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 591938032Speter*/ 592038032Speter 592138032Speter/* ARGSUSED3 */ 592238032Speterchar * 592338032Speteruser_map_lookup(map, key, av, statp) 592438032Speter MAP *map; 592538032Speter char *key; 592638032Speter char **av; 592738032Speter int *statp; 592838032Speter{ 592938032Speter auto bool fuzzy; 593090792Sgshapiro SM_MBDB_T user; 593138032Speter 593238032Speter if (tTd(38, 20)) 593390792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 593438032Speter map->map_mname, key); 593538032Speter 593690792Sgshapiro *statp = finduser(key, &fuzzy, &user); 593790792Sgshapiro if (*statp != EX_OK) 593838032Speter return NULL; 593938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 594038032Speter return map_rewrite(map, key, strlen(key), NULL); 594138032Speter else 594238032Speter { 594338032Speter char *rwval = NULL; 594438032Speter char buf[30]; 594538032Speter 594638032Speter switch (map->map_valcolno) 594738032Speter { 594838032Speter case 0: 594938032Speter case 1: 595090792Sgshapiro rwval = user.mbdb_name; 595138032Speter break; 595238032Speter 595338032Speter case 2: 595490792Sgshapiro rwval = "x"; /* passwd no longer supported */ 595538032Speter break; 595638032Speter 595738032Speter case 3: 595890792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%d", 595990792Sgshapiro (int) user.mbdb_uid); 596038032Speter rwval = buf; 596138032Speter break; 596238032Speter 596338032Speter case 4: 596490792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%d", 596590792Sgshapiro (int) user.mbdb_gid); 596638032Speter rwval = buf; 596738032Speter break; 596838032Speter 596938032Speter case 5: 597090792Sgshapiro rwval = user.mbdb_fullname; 597138032Speter break; 597238032Speter 597338032Speter case 6: 597490792Sgshapiro rwval = user.mbdb_homedir; 597538032Speter break; 597638032Speter 597738032Speter case 7: 597890792Sgshapiro rwval = user.mbdb_shell; 597938032Speter break; 598038032Speter } 598138032Speter return map_rewrite(map, rwval, strlen(rwval), av); 598238032Speter } 598338032Speter} 598490792Sgshapiro/* 598538032Speter** Program map type. 598638032Speter** 598738032Speter** This provides access to arbitrary programs. It should be used 598838032Speter** only very sparingly, since there is no way to bound the cost 598938032Speter** of invoking an arbitrary program. 599038032Speter*/ 599138032Speter 599238032Speterchar * 599338032Speterprog_map_lookup(map, name, av, statp) 599438032Speter MAP *map; 599538032Speter char *name; 599638032Speter char **av; 599738032Speter int *statp; 599838032Speter{ 599938032Speter int i; 600064562Sgshapiro int save_errno; 600138032Speter int fd; 600264562Sgshapiro int status; 600338032Speter auto pid_t pid; 600464562Sgshapiro register char *p; 600538032Speter char *rval; 600638032Speter char *argv[MAXPV + 1]; 600738032Speter char buf[MAXLINE]; 600838032Speter 600938032Speter if (tTd(38, 20)) 601090792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 601138032Speter map->map_mname, name, map->map_file); 601238032Speter 601338032Speter i = 0; 601438032Speter argv[i++] = map->map_file; 601538032Speter if (map->map_rebuild != NULL) 601638032Speter { 601790792Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof buf); 601838032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 601938032Speter { 602038032Speter if (i >= MAXPV - 1) 602138032Speter break; 602238032Speter argv[i++] = p; 602338032Speter } 602438032Speter } 602538032Speter argv[i++] = name; 602638032Speter argv[i] = NULL; 602738032Speter if (tTd(38, 21)) 602838032Speter { 602990792Sgshapiro sm_dprintf("prog_open:"); 603038032Speter for (i = 0; argv[i] != NULL; i++) 603190792Sgshapiro sm_dprintf(" %s", argv[i]); 603290792Sgshapiro sm_dprintf("\n"); 603338032Speter } 603490792Sgshapiro (void) sm_blocksignal(SIGCHLD); 603538032Speter pid = prog_open(argv, &fd, CurEnv); 603638032Speter if (pid < 0) 603738032Speter { 603838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 603938032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 604090792Sgshapiro map->map_mname, sm_errstring(errno)); 604138032Speter else if (tTd(38, 9)) 604290792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 604390792Sgshapiro map->map_mname, sm_errstring(errno)); 604438032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 604538032Speter *statp = EX_OSFILE; 604638032Speter return NULL; 604738032Speter } 604838032Speter i = read(fd, buf, sizeof buf - 1); 604938032Speter if (i < 0) 605038032Speter { 605190792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 605290792Sgshapiro map->map_mname, sm_errstring(errno)); 605338032Speter rval = NULL; 605438032Speter } 605538032Speter else if (i == 0) 605638032Speter { 605738032Speter if (tTd(38, 20)) 605890792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 605990792Sgshapiro map->map_mname); 606038032Speter rval = NULL; 606138032Speter } 606238032Speter else 606338032Speter { 606438032Speter buf[i] = '\0'; 606538032Speter p = strchr(buf, '\n'); 606638032Speter if (p != NULL) 606738032Speter *p = '\0'; 606838032Speter 606938032Speter /* collect the return value */ 607038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 607138032Speter rval = map_rewrite(map, name, strlen(name), NULL); 607238032Speter else 607377349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 607438032Speter 607538032Speter /* now flush any additional output */ 607638032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 607738032Speter continue; 607838032Speter } 607938032Speter 608038032Speter /* wait for the process to terminate */ 608164562Sgshapiro (void) close(fd); 608264562Sgshapiro status = waitfor(pid); 608364562Sgshapiro save_errno = errno; 608490792Sgshapiro (void) sm_releasesignal(SIGCHLD); 608564562Sgshapiro errno = save_errno; 608638032Speter 608764562Sgshapiro if (status == -1) 608838032Speter { 608990792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 609090792Sgshapiro map->map_mname, sm_errstring(errno)); 609138032Speter *statp = EX_SOFTWARE; 609238032Speter rval = NULL; 609338032Speter } 609464562Sgshapiro else if (WIFEXITED(status)) 609538032Speter { 609664562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 609738032Speter rval = NULL; 609838032Speter } 609938032Speter else 610038032Speter { 610138032Speter syserr("prog_map_lookup(%s): child died on signal %d", 610290792Sgshapiro map->map_mname, status); 610338032Speter *statp = EX_UNAVAILABLE; 610438032Speter rval = NULL; 610538032Speter } 610638032Speter return rval; 610738032Speter} 610890792Sgshapiro/* 610938032Speter** Sequenced map type. 611038032Speter** 611138032Speter** Tries each map in order until something matches, much like 611238032Speter** implicit. Stores go to the first map in the list that can 611338032Speter** support storing. 611438032Speter** 611538032Speter** This is slightly unusual in that there are two interfaces. 611638032Speter** The "sequence" interface lets you stack maps arbitrarily. 611738032Speter** The "switch" interface builds a sequence map by looking 611838032Speter** at a system-dependent configuration file such as 611938032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 612038032Speter** 612138032Speter** We don't need an explicit open, since all maps are 612290792Sgshapiro** opened on demand. 612338032Speter*/ 612438032Speter 612538032Speter/* 612638032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 612738032Speter*/ 612838032Speter 612938032Speterbool 613038032Speterseq_map_parse(map, ap) 613138032Speter MAP *map; 613238032Speter char *ap; 613338032Speter{ 613438032Speter int maxmap; 613538032Speter 613638032Speter if (tTd(38, 2)) 613790792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 613838032Speter maxmap = 0; 613938032Speter while (*ap != '\0') 614038032Speter { 614138032Speter register char *p; 614238032Speter STAB *s; 614338032Speter 614438032Speter /* find beginning of map name */ 614538032Speter while (isascii(*ap) && isspace(*ap)) 614638032Speter ap++; 614764562Sgshapiro for (p = ap; 614864562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 614964562Sgshapiro p++) 615038032Speter continue; 615138032Speter if (*p != '\0') 615238032Speter *p++ = '\0'; 615338032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 615438032Speter p++; 615538032Speter if (*ap == '\0') 615638032Speter { 615738032Speter ap = p; 615838032Speter continue; 615938032Speter } 616038032Speter s = stab(ap, ST_MAP, ST_FIND); 616138032Speter if (s == NULL) 616238032Speter { 616338032Speter syserr("Sequence map %s: unknown member map %s", 616438032Speter map->map_mname, ap); 616538032Speter } 616690792Sgshapiro else if (maxmap >= MAXMAPSTACK) 616738032Speter { 616838032Speter syserr("Sequence map %s: too many member maps (%d max)", 616938032Speter map->map_mname, MAXMAPSTACK); 617038032Speter maxmap++; 617138032Speter } 617238032Speter else if (maxmap < MAXMAPSTACK) 617338032Speter { 617438032Speter map->map_stack[maxmap++] = &s->s_map; 617538032Speter } 617638032Speter ap = p; 617738032Speter } 617890792Sgshapiro return true; 617938032Speter} 618038032Speter 618138032Speter/* 618238032Speter** SWITCH_MAP_OPEN -- open a switched map 618338032Speter** 618438032Speter** This looks at the system-dependent configuration and builds 618538032Speter** a sequence map that does the same thing. 618638032Speter** 618738032Speter** Every system must define a switch_map_find routine in conf.c 618838032Speter** that will return the list of service types associated with a 618938032Speter** given service class. 619038032Speter*/ 619138032Speter 619238032Speterbool 619338032Speterswitch_map_open(map, mode) 619438032Speter MAP *map; 619538032Speter int mode; 619638032Speter{ 619738032Speter int mapno; 619838032Speter int nmaps; 619938032Speter char *maptype[MAXMAPSTACK]; 620038032Speter 620138032Speter if (tTd(38, 2)) 620290792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 620338032Speter map->map_mname, map->map_file, mode); 620438032Speter 620538032Speter mode &= O_ACCMODE; 620638032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 620738032Speter if (tTd(38, 19)) 620838032Speter { 620990792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 621038032Speter for (mapno = 0; mapno < nmaps; mapno++) 621190792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 621238032Speter } 621338032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 621490792Sgshapiro return false; 621538032Speter 621638032Speter for (mapno = 0; mapno < nmaps; mapno++) 621738032Speter { 621838032Speter register STAB *s; 621938032Speter char nbuf[MAXNAME + 1]; 622038032Speter 622138032Speter if (maptype[mapno] == NULL) 622238032Speter continue; 622390792Sgshapiro (void) sm_strlcpyn(nbuf, sizeof nbuf, 3, 622490792Sgshapiro map->map_mname, ".", maptype[mapno]); 622538032Speter s = stab(nbuf, ST_MAP, ST_FIND); 622638032Speter if (s == NULL) 622738032Speter { 622838032Speter syserr("Switch map %s: unknown member map %s", 622938032Speter map->map_mname, nbuf); 623038032Speter } 623138032Speter else 623238032Speter { 623338032Speter map->map_stack[mapno] = &s->s_map; 623438032Speter if (tTd(38, 4)) 623590792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 623690792Sgshapiro mapno, 623790792Sgshapiro s->s_map.map_class->map_cname, 623890792Sgshapiro nbuf); 623938032Speter } 624038032Speter } 624190792Sgshapiro return true; 624238032Speter} 624338032Speter 624490792Sgshapiro#if 0 624538032Speter/* 624638032Speter** SEQ_MAP_CLOSE -- close all underlying maps 624738032Speter*/ 624838032Speter 624938032Spetervoid 625038032Speterseq_map_close(map) 625138032Speter MAP *map; 625238032Speter{ 625338032Speter int mapno; 625438032Speter 625538032Speter if (tTd(38, 9)) 625690792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 625738032Speter 625838032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 625938032Speter { 626038032Speter MAP *mm = map->map_stack[mapno]; 626138032Speter 626238032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 626338032Speter continue; 626477349Sgshapiro mm->map_mflags |= MF_CLOSING; 626538032Speter mm->map_class->map_close(mm); 626677349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 626738032Speter } 626838032Speter} 626990792Sgshapiro#endif /* 0 */ 627038032Speter 627138032Speter/* 627238032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 627338032Speter*/ 627438032Speter 627538032Speterchar * 627638032Speterseq_map_lookup(map, key, args, pstat) 627738032Speter MAP *map; 627838032Speter char *key; 627938032Speter char **args; 628038032Speter int *pstat; 628138032Speter{ 628238032Speter int mapno; 628338032Speter int mapbit = 0x01; 628490792Sgshapiro bool tempfail = false; 628538032Speter 628638032Speter if (tTd(38, 20)) 628790792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 628838032Speter 628938032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 629038032Speter { 629138032Speter MAP *mm = map->map_stack[mapno]; 629238032Speter char *rv; 629338032Speter 629438032Speter if (mm == NULL) 629538032Speter continue; 629664562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 629764562Sgshapiro !openmap(mm)) 629838032Speter { 629938032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 630038032Speter { 630138032Speter *pstat = EX_UNAVAILABLE; 630238032Speter return NULL; 630338032Speter } 630438032Speter continue; 630538032Speter } 630638032Speter *pstat = EX_OK; 630738032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 630838032Speter if (rv != NULL) 630938032Speter return rv; 631038032Speter if (*pstat == EX_TEMPFAIL) 631138032Speter { 631238032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 631338032Speter return NULL; 631490792Sgshapiro tempfail = true; 631538032Speter } 631638032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 631738032Speter break; 631838032Speter } 631938032Speter if (tempfail) 632038032Speter *pstat = EX_TEMPFAIL; 632138032Speter else if (*pstat == EX_OK) 632238032Speter *pstat = EX_NOTFOUND; 632338032Speter return NULL; 632438032Speter} 632538032Speter 632638032Speter/* 632738032Speter** SEQ_MAP_STORE -- sequenced map store 632838032Speter*/ 632938032Speter 633038032Spetervoid 633138032Speterseq_map_store(map, key, val) 633238032Speter MAP *map; 633338032Speter char *key; 633438032Speter char *val; 633538032Speter{ 633638032Speter int mapno; 633738032Speter 633838032Speter if (tTd(38, 12)) 633990792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 634038032Speter map->map_mname, key, val); 634138032Speter 634238032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 634338032Speter { 634438032Speter MAP *mm = map->map_stack[mapno]; 634538032Speter 634638032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 634738032Speter continue; 634838032Speter 634938032Speter mm->map_class->map_store(mm, key, val); 635038032Speter return; 635138032Speter } 635238032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 635338032Speter map->map_mname, key, val); 635438032Speter} 635590792Sgshapiro/* 635638032Speter** NULL stubs 635738032Speter*/ 635838032Speter 635938032Speter/* ARGSUSED */ 636038032Speterbool 636138032Speternull_map_open(map, mode) 636238032Speter MAP *map; 636338032Speter int mode; 636438032Speter{ 636590792Sgshapiro return true; 636638032Speter} 636738032Speter 636838032Speter/* ARGSUSED */ 636938032Spetervoid 637038032Speternull_map_close(map) 637138032Speter MAP *map; 637238032Speter{ 637338032Speter return; 637438032Speter} 637538032Speter 637638032Speterchar * 637738032Speternull_map_lookup(map, key, args, pstat) 637838032Speter MAP *map; 637938032Speter char *key; 638038032Speter char **args; 638138032Speter int *pstat; 638238032Speter{ 638338032Speter *pstat = EX_NOTFOUND; 638438032Speter return NULL; 638538032Speter} 638638032Speter 638738032Speter/* ARGSUSED */ 638838032Spetervoid 638938032Speternull_map_store(map, key, val) 639038032Speter MAP *map; 639138032Speter char *key; 639238032Speter char *val; 639338032Speter{ 639438032Speter return; 639538032Speter} 639638032Speter 639738032Speter/* 639838032Speter** BOGUS stubs 639938032Speter*/ 640038032Speter 640138032Speterchar * 640238032Speterbogus_map_lookup(map, key, args, pstat) 640338032Speter MAP *map; 640438032Speter char *key; 640538032Speter char **args; 640638032Speter int *pstat; 640738032Speter{ 640838032Speter *pstat = EX_TEMPFAIL; 640938032Speter return NULL; 641038032Speter} 641138032Speter 641238032SpeterMAPCLASS BogusMapClass = 641338032Speter{ 641490792Sgshapiro "bogus-map", NULL, 0, 641590792Sgshapiro NULL, bogus_map_lookup, null_map_store, 641690792Sgshapiro null_map_open, null_map_close, 641738032Speter}; 641890792Sgshapiro/* 641964562Sgshapiro** MACRO modules 642064562Sgshapiro*/ 642164562Sgshapiro 642264562Sgshapirochar * 642364562Sgshapiromacro_map_lookup(map, name, av, statp) 642464562Sgshapiro MAP *map; 642564562Sgshapiro char *name; 642664562Sgshapiro char **av; 642764562Sgshapiro int *statp; 642864562Sgshapiro{ 642964562Sgshapiro int mid; 643064562Sgshapiro 643164562Sgshapiro if (tTd(38, 20)) 643290792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 643364562Sgshapiro name == NULL ? "NULL" : name); 643464562Sgshapiro 643564562Sgshapiro if (name == NULL || 643664562Sgshapiro *name == '\0' || 643790792Sgshapiro (mid = macid(name)) == 0) 643864562Sgshapiro { 643964562Sgshapiro *statp = EX_CONFIG; 644064562Sgshapiro return NULL; 644164562Sgshapiro } 644264562Sgshapiro 644364562Sgshapiro if (av[1] == NULL) 644490792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 644564562Sgshapiro else 644690792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 644764562Sgshapiro 644864562Sgshapiro *statp = EX_OK; 644964562Sgshapiro return ""; 645064562Sgshapiro} 645190792Sgshapiro/* 645238032Speter** REGEX modules 645338032Speter*/ 645438032Speter 645590792Sgshapiro#if MAP_REGEX 645638032Speter 645738032Speter# include <regex.h> 645838032Speter 645938032Speter# define DEFAULT_DELIM CONDELSE 646038032Speter# define END_OF_FIELDS -1 646138032Speter# define ERRBUF_SIZE 80 646238032Speter# define MAX_MATCH 32 646338032Speter 646464562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 646538032Speter 646638032Speterstruct regex_map 646738032Speter{ 646871345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 646938032Speter int *regex_subfields; /* move to type MAP */ 647064562Sgshapiro char *regex_delim; /* move to type MAP */ 647138032Speter}; 647238032Speter 647338032Speterstatic int 647438032Speterparse_fields(s, ibuf, blen, nr_substrings) 647538032Speter char *s; 647638032Speter int *ibuf; /* array */ 647738032Speter int blen; /* number of elements in ibuf */ 647838032Speter int nr_substrings; /* number of substrings in the pattern */ 647938032Speter{ 648038032Speter register char *cp; 648138032Speter int i = 0; 648290792Sgshapiro bool lastone = false; 648338032Speter 648438032Speter blen--; /* for terminating END_OF_FIELDS */ 648538032Speter cp = s; 648638032Speter do 648738032Speter { 648838032Speter for (;; cp++) 648938032Speter { 649038032Speter if (*cp == ',') 649138032Speter { 649238032Speter *cp = '\0'; 649338032Speter break; 649438032Speter } 649538032Speter if (*cp == '\0') 649638032Speter { 649790792Sgshapiro lastone = true; 649838032Speter break; 649938032Speter } 650038032Speter } 650138032Speter if (i < blen) 650238032Speter { 650338032Speter int val = atoi(s); 650438032Speter 650538032Speter if (val < 0 || val >= nr_substrings) 650638032Speter { 650738032Speter syserr("field (%d) out of range, only %d substrings in pattern", 650838032Speter val, nr_substrings); 650938032Speter return -1; 651038032Speter } 651138032Speter ibuf[i++] = val; 651238032Speter } 651338032Speter else 651438032Speter { 651590792Sgshapiro syserr("too many fields, %d max", blen); 651638032Speter return -1; 651738032Speter } 651838032Speter s = ++cp; 651938032Speter } while (!lastone); 652038032Speter ibuf[i] = END_OF_FIELDS; 652138032Speter return i; 652238032Speter} 652338032Speter 652438032Speterbool 652538032Speterregex_map_init(map, ap) 652638032Speter MAP *map; 652738032Speter char *ap; 652838032Speter{ 652938032Speter int regerr; 653038032Speter struct regex_map *map_p; 653138032Speter register char *p; 653238032Speter char *sub_param = NULL; 653338032Speter int pflags; 653490792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 653538032Speter 653638032Speter if (tTd(38, 2)) 653790792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 653864562Sgshapiro map->map_mname, ap); 653938032Speter 654038032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 654138032Speter p = ap; 654264562Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof *map_p); 654371345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 654438032Speter 654538032Speter for (;;) 654664562Sgshapiro { 654738032Speter while (isascii(*p) && isspace(*p)) 654838032Speter p++; 654938032Speter if (*p != '-') 655038032Speter break; 655138032Speter switch (*++p) 655238032Speter { 655338032Speter case 'n': /* not */ 655438032Speter map->map_mflags |= MF_REGEX_NOT; 655538032Speter break; 655638032Speter 655738032Speter case 'f': /* case sensitive */ 655838032Speter map->map_mflags |= MF_NOFOLDCASE; 655938032Speter pflags &= ~REG_ICASE; 656038032Speter break; 656138032Speter 656238032Speter case 'b': /* basic regular expressions */ 656338032Speter pflags &= ~REG_EXTENDED; 656438032Speter break; 656538032Speter 656638032Speter case 's': /* substring match () syntax */ 656738032Speter sub_param = ++p; 656838032Speter pflags &= ~REG_NOSUB; 656938032Speter break; 657038032Speter 657138032Speter case 'd': /* delimiter */ 657264562Sgshapiro map_p->regex_delim = ++p; 657338032Speter break; 657438032Speter 657538032Speter case 'a': /* map append */ 657638032Speter map->map_app = ++p; 657738032Speter break; 657838032Speter 657938032Speter case 'm': /* matchonly */ 658038032Speter map->map_mflags |= MF_MATCHONLY; 658138032Speter break; 658238032Speter 6583120256Sgshapiro case 'q': 6584120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 6585120256Sgshapiro break; 6586120256Sgshapiro 658764562Sgshapiro case 'S': 658864562Sgshapiro map->map_spacesub = *++p; 658964562Sgshapiro break; 659064562Sgshapiro 659164562Sgshapiro case 'D': 659264562Sgshapiro map->map_mflags |= MF_DEFER; 659364562Sgshapiro break; 659464562Sgshapiro 659538032Speter } 659664562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 659764562Sgshapiro p++; 659864562Sgshapiro if (*p != '\0') 659964562Sgshapiro *p++ = '\0'; 660038032Speter } 660138032Speter if (tTd(38, 3)) 660290792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 660338032Speter 660471345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 660538032Speter { 660638032Speter /* Errorhandling */ 660738032Speter char errbuf[ERRBUF_SIZE]; 660838032Speter 660971345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 661090792Sgshapiro errbuf, sizeof errbuf); 661190792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 661290792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 661390792Sgshapiro sm_free(map_p); /* XXX */ 661490792Sgshapiro return false; 661538032Speter } 661638032Speter 661738032Speter if (map->map_app != NULL) 661838032Speter map->map_app = newstr(map->map_app); 661964562Sgshapiro if (map_p->regex_delim != NULL) 662064562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 662138032Speter else 662264562Sgshapiro map_p->regex_delim = defdstr; 662338032Speter 662438032Speter if (!bitset(REG_NOSUB, pflags)) 662538032Speter { 662638032Speter /* substring matching */ 662738032Speter int substrings; 662864562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 662938032Speter 663071345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 663138032Speter 663238032Speter if (tTd(38, 3)) 663390792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 663464562Sgshapiro substrings); 663538032Speter 663638032Speter if (substrings >= MAX_MATCH) 663738032Speter { 663890792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 663990792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 664090792Sgshapiro sm_free(map_p); /* XXX */ 664190792Sgshapiro return false; 664238032Speter } 664338032Speter if (sub_param != NULL && sub_param[0] != '\0') 664438032Speter { 664538032Speter /* optional parameter -sfields */ 664638032Speter if (parse_fields(sub_param, fields, 664738032Speter MAX_MATCH + 1, substrings) == -1) 664890792Sgshapiro return false; 664938032Speter } 665038032Speter else 665138032Speter { 665238032Speter int i; 665338032Speter 665490792Sgshapiro /* set default fields */ 665538032Speter for (i = 0; i < substrings; i++) 665638032Speter fields[i] = i; 665738032Speter fields[i] = END_OF_FIELDS; 665838032Speter } 665938032Speter map_p->regex_subfields = fields; 666038032Speter if (tTd(38, 3)) 666138032Speter { 666238032Speter int *ip; 666338032Speter 666490792Sgshapiro sm_dprintf("regex_map_init: subfields"); 666538032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 666690792Sgshapiro sm_dprintf(" %d", *ip); 666790792Sgshapiro sm_dprintf("\n"); 666838032Speter } 666938032Speter } 667090792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 667190792Sgshapiro return true; 667238032Speter} 667338032Speter 667438032Speterstatic char * 667538032Speterregex_map_rewrite(map, s, slen, av) 667638032Speter MAP *map; 667738032Speter const char *s; 667838032Speter size_t slen; 667938032Speter char **av; 668038032Speter{ 668138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 668238032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 668338032Speter else 668477349Sgshapiro return map_rewrite(map, s, slen, av); 668538032Speter} 668638032Speter 668738032Speterchar * 668838032Speterregex_map_lookup(map, name, av, statp) 668938032Speter MAP *map; 669038032Speter char *name; 669138032Speter char **av; 669238032Speter int *statp; 669338032Speter{ 669438032Speter int reg_res; 669538032Speter struct regex_map *map_p; 669638032Speter regmatch_t pmatch[MAX_MATCH]; 669738032Speter 669838032Speter if (tTd(38, 20)) 669938032Speter { 670038032Speter char **cpp; 670138032Speter 670290792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 670364562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 670490792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 670538032Speter } 670638032Speter 670738032Speter map_p = (struct regex_map *)(map->map_db1); 670871345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 670964562Sgshapiro name, MAX_MATCH, pmatch, 0); 671038032Speter 671138032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 671238032Speter { 671338032Speter /* option -n */ 671438032Speter if (reg_res == REG_NOMATCH) 671590792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 671638032Speter else 671738032Speter return NULL; 671838032Speter } 671938032Speter if (reg_res == REG_NOMATCH) 672038032Speter return NULL; 672138032Speter 672238032Speter if (map_p->regex_subfields != NULL) 672338032Speter { 672438032Speter /* option -s */ 672538032Speter static char retbuf[MAXNAME]; 672638032Speter int fields[MAX_MATCH + 1]; 672790792Sgshapiro bool first = true; 672838032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 672990792Sgshapiro bool quotemode = false, bslashmode = false; 673038032Speter register char *dp, *sp; 673138032Speter char *endp, *ldp; 673238032Speter int *ip; 673338032Speter 673438032Speter dp = retbuf; 673538032Speter ldp = retbuf + sizeof(retbuf) - 1; 673638032Speter 673738032Speter if (av[1] != NULL) 673838032Speter { 673938032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 674071345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 674138032Speter { 674238032Speter *statp = EX_CONFIG; 674338032Speter return NULL; 674438032Speter } 674538032Speter ip = fields; 674638032Speter } 674738032Speter else 674838032Speter ip = map_p->regex_subfields; 674938032Speter 675038032Speter for ( ; *ip != END_OF_FIELDS; ip++) 675138032Speter { 675238032Speter if (!first) 675338032Speter { 675464562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 675538032Speter { 675638032Speter if (dp < ldp) 675738032Speter *dp++ = *sp; 675838032Speter } 675938032Speter } 676038032Speter else 676190792Sgshapiro first = false; 676238032Speter 676371345Sgshapiro if (*ip >= MAX_MATCH || 676471345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 676538032Speter continue; 676638032Speter 676738032Speter sp = name + pmatch[*ip].rm_so; 676838032Speter endp = name + pmatch[*ip].rm_eo; 676938032Speter for (; endp > sp; sp++) 677038032Speter { 677138032Speter if (dp < ldp) 677238032Speter { 677364562Sgshapiro if (bslashmode) 677464562Sgshapiro { 677538032Speter *dp++ = *sp; 677690792Sgshapiro bslashmode = false; 677738032Speter } 677864562Sgshapiro else if (quotemode && *sp != '"' && 677938032Speter *sp != '\\') 678038032Speter { 678138032Speter *dp++ = *sp; 678238032Speter } 678390792Sgshapiro else switch (*dp++ = *sp) 678438032Speter { 678590792Sgshapiro case '\\': 678690792Sgshapiro bslashmode = true; 678738032Speter break; 678838032Speter 678990792Sgshapiro case '(': 679038032Speter cmntcnt++; 679138032Speter break; 679238032Speter 679390792Sgshapiro case ')': 679438032Speter cmntcnt--; 679538032Speter break; 679638032Speter 679790792Sgshapiro case '<': 679838032Speter anglecnt++; 679938032Speter break; 680038032Speter 680190792Sgshapiro case '>': 680238032Speter anglecnt--; 680338032Speter break; 680438032Speter 680590792Sgshapiro case ' ': 680638032Speter spacecnt++; 680738032Speter break; 680838032Speter 680990792Sgshapiro case '"': 681038032Speter quotemode = !quotemode; 681138032Speter break; 681238032Speter } 681338032Speter } 681438032Speter } 681538032Speter } 681638032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 681738032Speter bslashmode || spacecnt != 0) 681838032Speter { 681964562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 682064562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 682164562Sgshapiro map->map_mname, name); 682238032Speter return NULL; 682338032Speter } 682438032Speter 682538032Speter *dp = '\0'; 682638032Speter 682738032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 682838032Speter } 682938032Speter return regex_map_rewrite(map, "", (size_t)0, av); 683038032Speter} 683138032Speter#endif /* MAP_REGEX */ 683290792Sgshapiro/* 683364562Sgshapiro** NSD modules 683464562Sgshapiro*/ 683590792Sgshapiro#if MAP_NSD 683664562Sgshapiro 683764562Sgshapiro# include <ndbm.h> 683864562Sgshapiro# define _DATUM_DEFINED 683964562Sgshapiro# include <ns_api.h> 684064562Sgshapiro 684164562Sgshapirotypedef struct ns_map_list 684264562Sgshapiro{ 684390792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 684490792Sgshapiro char *mapname; 684590792Sgshapiro struct ns_map_list *next; 684664562Sgshapiro} ns_map_list_t; 684764562Sgshapiro 684864562Sgshapirostatic ns_map_t * 684964562Sgshapirons_map_t_find(mapname) 685064562Sgshapiro char *mapname; 685164562Sgshapiro{ 685264562Sgshapiro static ns_map_list_t *ns_maps = NULL; 685364562Sgshapiro ns_map_list_t *ns_map; 685464562Sgshapiro 685564562Sgshapiro /* walk the list of maps looking for the correctly named map */ 685664562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 685764562Sgshapiro { 685864562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 685964562Sgshapiro break; 686064562Sgshapiro } 686164562Sgshapiro 686264562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 686364562Sgshapiro if (ns_map == NULL) 686464562Sgshapiro { 686564562Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 686664562Sgshapiro ns_map->mapname = newstr(mapname); 686764562Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 6868102528Sgshapiro memset(ns_map->map, '\0', sizeof *ns_map->map); 686964562Sgshapiro ns_map->next = ns_maps; 687064562Sgshapiro ns_maps = ns_map; 687164562Sgshapiro } 687264562Sgshapiro return ns_map->map; 687364562Sgshapiro} 687464562Sgshapiro 687564562Sgshapirochar * 687664562Sgshapironsd_map_lookup(map, name, av, statp) 687764562Sgshapiro MAP *map; 687864562Sgshapiro char *name; 687964562Sgshapiro char **av; 688064562Sgshapiro int *statp; 688164562Sgshapiro{ 688271345Sgshapiro int buflen, r; 688364562Sgshapiro char *p; 688464562Sgshapiro ns_map_t *ns_map; 688564562Sgshapiro char keybuf[MAXNAME + 1]; 688664562Sgshapiro char buf[MAXLINE]; 688764562Sgshapiro 688864562Sgshapiro if (tTd(38, 20)) 688990792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 689064562Sgshapiro 689164562Sgshapiro buflen = strlen(name); 689264562Sgshapiro if (buflen > sizeof keybuf - 1) 689390792Sgshapiro buflen = sizeof keybuf - 1; /* XXX simply cut off? */ 689464562Sgshapiro memmove(keybuf, name, buflen); 689564562Sgshapiro keybuf[buflen] = '\0'; 689664562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 689764562Sgshapiro makelower(keybuf); 689864562Sgshapiro 689964562Sgshapiro ns_map = ns_map_t_find(map->map_file); 690064562Sgshapiro if (ns_map == NULL) 690164562Sgshapiro { 690264562Sgshapiro if (tTd(38, 20)) 690390792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 690471345Sgshapiro *statp = EX_UNAVAILABLE; 690564562Sgshapiro return NULL; 690664562Sgshapiro } 690798121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 690898121Sgshapiro buf, sizeof buf); 690971345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 691071345Sgshapiro { 691171345Sgshapiro *statp = EX_TEMPFAIL; 691264562Sgshapiro return NULL; 691371345Sgshapiro } 691477349Sgshapiro if (r == NS_BADREQ 691577349Sgshapiro# ifdef NS_NOPERM 691677349Sgshapiro || r == NS_NOPERM 691777349Sgshapiro# endif /* NS_NOPERM */ 691877349Sgshapiro ) 691971345Sgshapiro { 692071345Sgshapiro *statp = EX_CONFIG; 692171345Sgshapiro return NULL; 692271345Sgshapiro } 692371345Sgshapiro if (r != NS_SUCCESS) 692471345Sgshapiro { 692571345Sgshapiro *statp = EX_NOTFOUND; 692671345Sgshapiro return NULL; 692771345Sgshapiro } 692864562Sgshapiro 692971345Sgshapiro *statp = EX_OK; 693071345Sgshapiro 693164562Sgshapiro /* Null out trailing \n */ 693264562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 693364562Sgshapiro *p = '\0'; 693464562Sgshapiro 693564562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 693664562Sgshapiro} 693764562Sgshapiro#endif /* MAP_NSD */ 693864562Sgshapiro 693964562Sgshapirochar * 694064562Sgshapiroarith_map_lookup(map, name, av, statp) 694164562Sgshapiro MAP *map; 694264562Sgshapiro char *name; 694364562Sgshapiro char **av; 694464562Sgshapiro int *statp; 694564562Sgshapiro{ 694664562Sgshapiro long r; 694764562Sgshapiro long v[2]; 694890792Sgshapiro bool res = false; 694964562Sgshapiro bool boolres; 695064562Sgshapiro static char result[16]; 695164562Sgshapiro char **cpp; 695264562Sgshapiro 695364562Sgshapiro if (tTd(38, 2)) 695464562Sgshapiro { 695590792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 695664562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 695790792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 695864562Sgshapiro } 695964562Sgshapiro r = 0; 696090792Sgshapiro boolres = false; 696164562Sgshapiro cpp = av; 696264562Sgshapiro *statp = EX_OK; 696364562Sgshapiro 696464562Sgshapiro /* 696564562Sgshapiro ** read arguments for arith map 696664562Sgshapiro ** - no check is made whether they are really numbers 696764562Sgshapiro ** - just ignores args after the second 696864562Sgshapiro */ 696990792Sgshapiro 697064562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 697164562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 697264562Sgshapiro 697364562Sgshapiro /* operator and (at least) two operands given? */ 697464562Sgshapiro if (name != NULL && r == 2) 697564562Sgshapiro { 697690792Sgshapiro switch (*name) 697764562Sgshapiro { 697864562Sgshapiro case '|': 697964562Sgshapiro r = v[0] | v[1]; 698064562Sgshapiro break; 698164562Sgshapiro 698264562Sgshapiro case '&': 698364562Sgshapiro r = v[0] & v[1]; 698464562Sgshapiro break; 698564562Sgshapiro 698664562Sgshapiro case '%': 698764562Sgshapiro if (v[1] == 0) 698864562Sgshapiro return NULL; 698964562Sgshapiro r = v[0] % v[1]; 699064562Sgshapiro break; 699164562Sgshapiro case '+': 699264562Sgshapiro r = v[0] + v[1]; 699364562Sgshapiro break; 699464562Sgshapiro 699564562Sgshapiro case '-': 699664562Sgshapiro r = v[0] - v[1]; 699764562Sgshapiro break; 699864562Sgshapiro 699964562Sgshapiro case '*': 700064562Sgshapiro r = v[0] * v[1]; 700164562Sgshapiro break; 700264562Sgshapiro 700364562Sgshapiro case '/': 700464562Sgshapiro if (v[1] == 0) 700564562Sgshapiro return NULL; 700664562Sgshapiro r = v[0] / v[1]; 700764562Sgshapiro break; 700864562Sgshapiro 700964562Sgshapiro case 'l': 701064562Sgshapiro res = v[0] < v[1]; 701190792Sgshapiro boolres = true; 701264562Sgshapiro break; 701364562Sgshapiro 701464562Sgshapiro case '=': 701564562Sgshapiro res = v[0] == v[1]; 701690792Sgshapiro boolres = true; 701764562Sgshapiro break; 701864562Sgshapiro 701964562Sgshapiro default: 702064562Sgshapiro /* XXX */ 702164562Sgshapiro *statp = EX_CONFIG; 702264562Sgshapiro if (LogLevel > 10) 702364562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 702464562Sgshapiro "arith_map: unknown operator %c", 702564562Sgshapiro isprint(*name) ? *name : '?'); 702664562Sgshapiro return NULL; 702764562Sgshapiro } 702864562Sgshapiro if (boolres) 702990792Sgshapiro (void) sm_snprintf(result, sizeof result, 703090792Sgshapiro res ? "TRUE" : "FALSE"); 703164562Sgshapiro else 703290792Sgshapiro (void) sm_snprintf(result, sizeof result, "%ld", r); 703364562Sgshapiro return result; 703464562Sgshapiro } 703564562Sgshapiro *statp = EX_CONFIG; 703664562Sgshapiro return NULL; 703764562Sgshapiro} 7038132943Sgshapiro 7039132943Sgshapiro#if SOCKETMAP 7040132943Sgshapiro 7041132943Sgshapiro# if NETINET || NETINET6 7042132943Sgshapiro# include <arpa/inet.h> 7043132943Sgshapiro# endif /* NETINET || NETINET6 */ 7044132943Sgshapiro 7045132943Sgshapiro# define socket_map_next map_stack[0] 7046132943Sgshapiro 7047132943Sgshapiro/* 7048132943Sgshapiro** SOCKET_MAP_OPEN -- open socket table 7049132943Sgshapiro*/ 7050132943Sgshapiro 7051132943Sgshapirobool 7052132943Sgshapirosocket_map_open(map, mode) 7053132943Sgshapiro MAP *map; 7054132943Sgshapiro int mode; 7055132943Sgshapiro{ 7056132943Sgshapiro STAB *s; 7057132943Sgshapiro int sock = 0; 7058132943Sgshapiro SOCKADDR_LEN_T addrlen = 0; 7059132943Sgshapiro int addrno = 0; 7060132943Sgshapiro int save_errno; 7061132943Sgshapiro char *p; 7062132943Sgshapiro char *colon; 7063132943Sgshapiro char *at; 7064132943Sgshapiro struct hostent *hp = NULL; 7065132943Sgshapiro SOCKADDR addr; 7066132943Sgshapiro 7067132943Sgshapiro if (tTd(38, 2)) 7068132943Sgshapiro sm_dprintf("socket_map_open(%s, %s, %d)\n", 7069132943Sgshapiro map->map_mname, map->map_file, mode); 7070132943Sgshapiro 7071132943Sgshapiro mode &= O_ACCMODE; 7072132943Sgshapiro 7073132943Sgshapiro /* sendmail doesn't have the ability to write to SOCKET (yet) */ 7074132943Sgshapiro if (mode != O_RDONLY) 7075132943Sgshapiro { 7076132943Sgshapiro /* issue a pseudo-error message */ 7077132943Sgshapiro errno = SM_EMAPCANTWRITE; 7078132943Sgshapiro return false; 7079132943Sgshapiro } 7080132943Sgshapiro 7081132943Sgshapiro if (*map->map_file == '\0') 7082132943Sgshapiro { 7083132943Sgshapiro syserr("socket map \"%s\": empty or missing socket information", 7084132943Sgshapiro map->map_mname); 7085132943Sgshapiro return false; 7086132943Sgshapiro } 7087132943Sgshapiro 7088132943Sgshapiro s = socket_map_findconn(map->map_file); 7089132943Sgshapiro if (s->s_socketmap != NULL) 7090132943Sgshapiro { 7091132943Sgshapiro /* Copy open connection */ 7092132943Sgshapiro map->map_db1 = s->s_socketmap->map_db1; 7093132943Sgshapiro 7094132943Sgshapiro /* Add this map as head of linked list */ 7095132943Sgshapiro map->socket_map_next = s->s_socketmap; 7096132943Sgshapiro s->s_socketmap = map; 7097132943Sgshapiro 7098132943Sgshapiro if (tTd(38, 2)) 7099132943Sgshapiro sm_dprintf("using cached connection\n"); 7100132943Sgshapiro return true; 7101132943Sgshapiro } 7102132943Sgshapiro 7103132943Sgshapiro if (tTd(38, 2)) 7104132943Sgshapiro sm_dprintf("opening new connection\n"); 7105132943Sgshapiro 7106132943Sgshapiro /* following code is ripped from milter.c */ 7107132943Sgshapiro /* XXX It should be put in a library... */ 7108132943Sgshapiro 7109132943Sgshapiro /* protocol:filename or protocol:port@host */ 7110132943Sgshapiro memset(&addr, '\0', sizeof addr); 7111132943Sgshapiro p = map->map_file; 7112132943Sgshapiro colon = strchr(p, ':'); 7113132943Sgshapiro if (colon != NULL) 7114132943Sgshapiro { 7115132943Sgshapiro *colon = '\0'; 7116132943Sgshapiro 7117132943Sgshapiro if (*p == '\0') 7118132943Sgshapiro { 7119132943Sgshapiro# if NETUNIX 7120132943Sgshapiro /* default to AF_UNIX */ 7121132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7122132943Sgshapiro# else /* NETUNIX */ 7123132943Sgshapiro# if NETINET 7124132943Sgshapiro /* default to AF_INET */ 7125132943Sgshapiro addr.sa.sa_family = AF_INET; 7126132943Sgshapiro# else /* NETINET */ 7127132943Sgshapiro# if NETINET6 7128132943Sgshapiro /* default to AF_INET6 */ 7129132943Sgshapiro addr.sa.sa_family = AF_INET6; 7130132943Sgshapiro# else /* NETINET6 */ 7131132943Sgshapiro /* no protocols available */ 7132132943Sgshapiro syserr("socket map \"%s\": no valid socket protocols available", 7133132943Sgshapiro map->map_mname); 7134132943Sgshapiro return false; 7135132943Sgshapiro# endif /* NETINET6 */ 7136132943Sgshapiro# endif /* NETINET */ 7137132943Sgshapiro# endif /* NETUNIX */ 7138132943Sgshapiro } 7139132943Sgshapiro# if NETUNIX 7140132943Sgshapiro else if (sm_strcasecmp(p, "unix") == 0 || 7141132943Sgshapiro sm_strcasecmp(p, "local") == 0) 7142132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7143132943Sgshapiro# endif /* NETUNIX */ 7144132943Sgshapiro# if NETINET 7145132943Sgshapiro else if (sm_strcasecmp(p, "inet") == 0) 7146132943Sgshapiro addr.sa.sa_family = AF_INET; 7147132943Sgshapiro# endif /* NETINET */ 7148132943Sgshapiro# if NETINET6 7149132943Sgshapiro else if (sm_strcasecmp(p, "inet6") == 0) 7150132943Sgshapiro addr.sa.sa_family = AF_INET6; 7151132943Sgshapiro# endif /* NETINET6 */ 7152132943Sgshapiro else 7153132943Sgshapiro { 7154132943Sgshapiro# ifdef EPROTONOSUPPORT 7155132943Sgshapiro errno = EPROTONOSUPPORT; 7156132943Sgshapiro# else /* EPROTONOSUPPORT */ 7157132943Sgshapiro errno = EINVAL; 7158132943Sgshapiro# endif /* EPROTONOSUPPORT */ 7159132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7160132943Sgshapiro map->map_mname, p); 7161132943Sgshapiro return false; 7162132943Sgshapiro } 7163132943Sgshapiro *colon++ = ':'; 7164132943Sgshapiro } 7165132943Sgshapiro else 7166132943Sgshapiro { 7167132943Sgshapiro colon = p; 7168132943Sgshapiro#if NETUNIX 7169132943Sgshapiro /* default to AF_UNIX */ 7170132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7171132943Sgshapiro#else /* NETUNIX */ 7172132943Sgshapiro# if NETINET 7173132943Sgshapiro /* default to AF_INET */ 7174132943Sgshapiro addr.sa.sa_family = AF_INET; 7175132943Sgshapiro# else /* NETINET */ 7176132943Sgshapiro# if NETINET6 7177132943Sgshapiro /* default to AF_INET6 */ 7178132943Sgshapiro addr.sa.sa_family = AF_INET6; 7179132943Sgshapiro# else /* NETINET6 */ 7180132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7181132943Sgshapiro map->map_mname, p); 7182132943Sgshapiro return false; 7183132943Sgshapiro# endif /* NETINET6 */ 7184132943Sgshapiro# endif /* NETINET */ 7185132943Sgshapiro#endif /* NETUNIX */ 7186132943Sgshapiro } 7187132943Sgshapiro 7188132943Sgshapiro# if NETUNIX 7189132943Sgshapiro if (addr.sa.sa_family == AF_UNIX) 7190132943Sgshapiro { 7191132943Sgshapiro long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 7192132943Sgshapiro 7193132943Sgshapiro at = colon; 7194132943Sgshapiro if (strlen(colon) >= sizeof addr.sunix.sun_path) 7195132943Sgshapiro { 7196132943Sgshapiro syserr("socket map \"%s\": local socket name %s too long", 7197132943Sgshapiro map->map_mname, colon); 7198132943Sgshapiro return false; 7199132943Sgshapiro } 7200132943Sgshapiro errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 7201132943Sgshapiro S_IRUSR|S_IWUSR, NULL); 7202132943Sgshapiro 7203132943Sgshapiro if (errno != 0) 7204132943Sgshapiro { 7205132943Sgshapiro /* if not safe, don't create */ 7206132943Sgshapiro syserr("socket map \"%s\": local socket name %s unsafe", 7207132943Sgshapiro map->map_mname, colon); 7208132943Sgshapiro return false; 7209132943Sgshapiro } 7210132943Sgshapiro 7211132943Sgshapiro (void) sm_strlcpy(addr.sunix.sun_path, colon, 7212132943Sgshapiro sizeof addr.sunix.sun_path); 7213132943Sgshapiro addrlen = sizeof (struct sockaddr_un); 7214132943Sgshapiro } 7215132943Sgshapiro else 7216132943Sgshapiro# endif /* NETUNIX */ 7217132943Sgshapiro# if NETINET || NETINET6 7218132943Sgshapiro if (false 7219132943Sgshapiro# if NETINET 7220132943Sgshapiro || addr.sa.sa_family == AF_INET 7221132943Sgshapiro# endif /* NETINET */ 7222132943Sgshapiro# if NETINET6 7223132943Sgshapiro || addr.sa.sa_family == AF_INET6 7224132943Sgshapiro# endif /* NETINET6 */ 7225132943Sgshapiro ) 7226132943Sgshapiro { 7227132943Sgshapiro unsigned short port; 7228132943Sgshapiro 7229132943Sgshapiro /* Parse port@host */ 7230132943Sgshapiro at = strchr(colon, '@'); 7231132943Sgshapiro if (at == NULL) 7232132943Sgshapiro { 7233132943Sgshapiro syserr("socket map \"%s\": bad address %s (expected port@host)", 7234132943Sgshapiro map->map_mname, colon); 7235132943Sgshapiro return false; 7236132943Sgshapiro } 7237132943Sgshapiro *at = '\0'; 7238132943Sgshapiro if (isascii(*colon) && isdigit(*colon)) 7239132943Sgshapiro port = htons((unsigned short) atoi(colon)); 7240132943Sgshapiro else 7241132943Sgshapiro { 7242132943Sgshapiro# ifdef NO_GETSERVBYNAME 7243132943Sgshapiro syserr("socket map \"%s\": invalid port number %s", 7244132943Sgshapiro map->map_mname, colon); 7245132943Sgshapiro return false; 7246132943Sgshapiro# else /* NO_GETSERVBYNAME */ 7247132943Sgshapiro register struct servent *sp; 7248132943Sgshapiro 7249132943Sgshapiro sp = getservbyname(colon, "tcp"); 7250132943Sgshapiro if (sp == NULL) 7251132943Sgshapiro { 7252132943Sgshapiro syserr("socket map \"%s\": unknown port name %s", 7253132943Sgshapiro map->map_mname, colon); 7254132943Sgshapiro return false; 7255132943Sgshapiro } 7256132943Sgshapiro port = sp->s_port; 7257132943Sgshapiro# endif /* NO_GETSERVBYNAME */ 7258132943Sgshapiro } 7259132943Sgshapiro *at++ = '@'; 7260132943Sgshapiro if (*at == '[') 7261132943Sgshapiro { 7262132943Sgshapiro char *end; 7263132943Sgshapiro 7264132943Sgshapiro end = strchr(at, ']'); 7265132943Sgshapiro if (end != NULL) 7266132943Sgshapiro { 7267132943Sgshapiro bool found = false; 7268132943Sgshapiro# if NETINET 7269132943Sgshapiro unsigned long hid = INADDR_NONE; 7270132943Sgshapiro# endif /* NETINET */ 7271132943Sgshapiro# if NETINET6 7272132943Sgshapiro struct sockaddr_in6 hid6; 7273132943Sgshapiro# endif /* NETINET6 */ 7274132943Sgshapiro 7275132943Sgshapiro *end = '\0'; 7276132943Sgshapiro# if NETINET 7277132943Sgshapiro if (addr.sa.sa_family == AF_INET && 7278132943Sgshapiro (hid = inet_addr(&at[1])) != INADDR_NONE) 7279132943Sgshapiro { 7280132943Sgshapiro addr.sin.sin_addr.s_addr = hid; 7281132943Sgshapiro addr.sin.sin_port = port; 7282132943Sgshapiro found = true; 7283132943Sgshapiro } 7284132943Sgshapiro# endif /* NETINET */ 7285132943Sgshapiro# if NETINET6 7286132943Sgshapiro (void) memset(&hid6, '\0', sizeof hid6); 7287132943Sgshapiro if (addr.sa.sa_family == AF_INET6 && 7288132943Sgshapiro anynet_pton(AF_INET6, &at[1], 7289132943Sgshapiro &hid6.sin6_addr) == 1) 7290132943Sgshapiro { 7291132943Sgshapiro addr.sin6.sin6_addr = hid6.sin6_addr; 7292132943Sgshapiro addr.sin6.sin6_port = port; 7293132943Sgshapiro found = true; 7294132943Sgshapiro } 7295132943Sgshapiro# endif /* NETINET6 */ 7296132943Sgshapiro *end = ']'; 7297132943Sgshapiro if (!found) 7298132943Sgshapiro { 7299132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7300132943Sgshapiro map->map_mname, at); 7301132943Sgshapiro return false; 7302132943Sgshapiro } 7303132943Sgshapiro } 7304132943Sgshapiro else 7305132943Sgshapiro { 7306132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7307132943Sgshapiro map->map_mname, at); 7308132943Sgshapiro return false; 7309132943Sgshapiro } 7310132943Sgshapiro } 7311132943Sgshapiro else 7312132943Sgshapiro { 7313132943Sgshapiro hp = sm_gethostbyname(at, addr.sa.sa_family); 7314132943Sgshapiro if (hp == NULL) 7315132943Sgshapiro { 7316132943Sgshapiro syserr("socket map \"%s\": Unknown host name %s", 7317132943Sgshapiro map->map_mname, at); 7318132943Sgshapiro return false; 7319132943Sgshapiro } 7320132943Sgshapiro addr.sa.sa_family = hp->h_addrtype; 7321132943Sgshapiro switch (hp->h_addrtype) 7322132943Sgshapiro { 7323132943Sgshapiro# if NETINET 7324132943Sgshapiro case AF_INET: 7325132943Sgshapiro memmove(&addr.sin.sin_addr, 7326132943Sgshapiro hp->h_addr, INADDRSZ); 7327132943Sgshapiro addr.sin.sin_port = port; 7328132943Sgshapiro addrlen = sizeof (struct sockaddr_in); 7329132943Sgshapiro addrno = 1; 7330132943Sgshapiro break; 7331132943Sgshapiro# endif /* NETINET */ 7332132943Sgshapiro 7333132943Sgshapiro# if NETINET6 7334132943Sgshapiro case AF_INET6: 7335132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7336132943Sgshapiro hp->h_addr, IN6ADDRSZ); 7337132943Sgshapiro addr.sin6.sin6_port = port; 7338132943Sgshapiro addrlen = sizeof (struct sockaddr_in6); 7339132943Sgshapiro addrno = 1; 7340132943Sgshapiro break; 7341132943Sgshapiro# endif /* NETINET6 */ 7342132943Sgshapiro 7343132943Sgshapiro default: 7344132943Sgshapiro syserr("socket map \"%s\": Unknown protocol for %s (%d)", 7345132943Sgshapiro map->map_mname, at, hp->h_addrtype); 7346132943Sgshapiro# if NETINET6 7347132943Sgshapiro freehostent(hp); 7348132943Sgshapiro# endif /* NETINET6 */ 7349132943Sgshapiro return false; 7350132943Sgshapiro } 7351132943Sgshapiro } 7352132943Sgshapiro } 7353132943Sgshapiro else 7354132943Sgshapiro# endif /* NETINET || NETINET6 */ 7355132943Sgshapiro { 7356132943Sgshapiro syserr("socket map \"%s\": unknown socket protocol", 7357132943Sgshapiro map->map_mname); 7358132943Sgshapiro return false; 7359132943Sgshapiro } 7360132943Sgshapiro 7361132943Sgshapiro /* nope, actually connecting */ 7362132943Sgshapiro for (;;) 7363132943Sgshapiro { 7364132943Sgshapiro sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 7365132943Sgshapiro if (sock < 0) 7366132943Sgshapiro { 7367132943Sgshapiro save_errno = errno; 7368132943Sgshapiro if (tTd(38, 5)) 7369132943Sgshapiro sm_dprintf("socket map \"%s\": error creating socket: %s\n", 7370132943Sgshapiro map->map_mname, 7371132943Sgshapiro sm_errstring(save_errno)); 7372132943Sgshapiro# if NETINET6 7373132943Sgshapiro if (hp != NULL) 7374132943Sgshapiro freehostent(hp); 7375132943Sgshapiro# endif /* NETINET6 */ 7376132943Sgshapiro return false; 7377132943Sgshapiro } 7378132943Sgshapiro 7379132943Sgshapiro if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 7380132943Sgshapiro break; 7381132943Sgshapiro 7382132943Sgshapiro /* couldn't connect.... try next address */ 7383132943Sgshapiro save_errno = errno; 7384132943Sgshapiro p = CurHostName; 7385132943Sgshapiro CurHostName = at; 7386132943Sgshapiro if (tTd(38, 5)) 7387132943Sgshapiro sm_dprintf("socket_open (%s): open %s failed: %s\n", 7388132943Sgshapiro map->map_mname, at, sm_errstring(save_errno)); 7389132943Sgshapiro CurHostName = p; 7390132943Sgshapiro (void) close(sock); 7391132943Sgshapiro 7392132943Sgshapiro /* try next address */ 7393132943Sgshapiro if (hp != NULL && hp->h_addr_list[addrno] != NULL) 7394132943Sgshapiro { 7395132943Sgshapiro switch (addr.sa.sa_family) 7396132943Sgshapiro { 7397132943Sgshapiro# if NETINET 7398132943Sgshapiro case AF_INET: 7399132943Sgshapiro memmove(&addr.sin.sin_addr, 7400132943Sgshapiro hp->h_addr_list[addrno++], 7401132943Sgshapiro INADDRSZ); 7402132943Sgshapiro break; 7403132943Sgshapiro# endif /* NETINET */ 7404132943Sgshapiro 7405132943Sgshapiro# if NETINET6 7406132943Sgshapiro case AF_INET6: 7407132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7408132943Sgshapiro hp->h_addr_list[addrno++], 7409132943Sgshapiro IN6ADDRSZ); 7410132943Sgshapiro break; 7411132943Sgshapiro# endif /* NETINET6 */ 7412132943Sgshapiro 7413132943Sgshapiro default: 7414132943Sgshapiro if (tTd(38, 5)) 7415132943Sgshapiro sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 7416132943Sgshapiro map->map_mname, at, 7417132943Sgshapiro hp->h_addrtype); 7418132943Sgshapiro# if NETINET6 7419132943Sgshapiro freehostent(hp); 7420132943Sgshapiro# endif /* NETINET6 */ 7421132943Sgshapiro return false; 7422132943Sgshapiro } 7423132943Sgshapiro continue; 7424132943Sgshapiro } 7425132943Sgshapiro p = CurHostName; 7426132943Sgshapiro CurHostName = at; 7427132943Sgshapiro if (tTd(38, 5)) 7428132943Sgshapiro sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 7429132943Sgshapiro map->map_mname, sm_errstring(save_errno)); 7430132943Sgshapiro CurHostName = p; 7431132943Sgshapiro# if NETINET6 7432132943Sgshapiro if (hp != NULL) 7433132943Sgshapiro freehostent(hp); 7434132943Sgshapiro# endif /* NETINET6 */ 7435132943Sgshapiro return false; 7436132943Sgshapiro } 7437132943Sgshapiro# if NETINET6 7438132943Sgshapiro if (hp != NULL) 7439132943Sgshapiro { 7440132943Sgshapiro freehostent(hp); 7441132943Sgshapiro hp = NULL; 7442132943Sgshapiro } 7443132943Sgshapiro# endif /* NETINET6 */ 7444132943Sgshapiro if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 7445132943Sgshapiro SM_TIME_DEFAULT, 7446132943Sgshapiro (void *) &sock, 7447132943Sgshapiro SM_IO_RDWR, 7448132943Sgshapiro NULL)) == NULL) 7449132943Sgshapiro { 7450132943Sgshapiro close(sock); 7451132943Sgshapiro if (tTd(38, 2)) 7452132943Sgshapiro sm_dprintf("socket_open (%s): failed to create stream: %s\n", 7453132943Sgshapiro map->map_mname, sm_errstring(errno)); 7454132943Sgshapiro return false; 7455132943Sgshapiro } 7456132943Sgshapiro 7457132943Sgshapiro /* Save connection for reuse */ 7458132943Sgshapiro s->s_socketmap = map; 7459132943Sgshapiro return true; 7460132943Sgshapiro} 7461132943Sgshapiro 7462132943Sgshapiro/* 7463132943Sgshapiro** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 7464132943Sgshapiro** 7465132943Sgshapiro** Cache SOCKET connections based on the connection specifier 7466132943Sgshapiro** and PID so we don't have multiple connections open to 7467132943Sgshapiro** the same server for different maps. Need a separate connection 7468132943Sgshapiro** per PID since a parent process may close the map before the 7469132943Sgshapiro** child is done with it. 7470132943Sgshapiro** 7471132943Sgshapiro** Parameters: 7472132943Sgshapiro** conn -- SOCKET map connection specifier 7473132943Sgshapiro** 7474132943Sgshapiro** Returns: 7475132943Sgshapiro** Symbol table entry for the SOCKET connection. 7476132943Sgshapiro*/ 7477132943Sgshapiro 7478132943Sgshapirostatic STAB * 7479132943Sgshapirosocket_map_findconn(conn) 7480132943Sgshapiro const char *conn; 7481132943Sgshapiro{ 7482132943Sgshapiro char *nbuf; 7483132943Sgshapiro STAB *SM_NONVOLATILE s = NULL; 7484132943Sgshapiro 7485132943Sgshapiro nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 7486132943Sgshapiro SM_TRY 7487132943Sgshapiro s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 7488132943Sgshapiro SM_FINALLY 7489132943Sgshapiro sm_free(nbuf); 7490132943Sgshapiro SM_END_TRY 7491132943Sgshapiro return s; 7492132943Sgshapiro} 7493132943Sgshapiro 7494132943Sgshapiro/* 7495132943Sgshapiro** SOCKET_MAP_CLOSE -- close the socket 7496132943Sgshapiro*/ 7497132943Sgshapiro 7498132943Sgshapirovoid 7499132943Sgshapirosocket_map_close(map) 7500132943Sgshapiro MAP *map; 7501132943Sgshapiro{ 7502132943Sgshapiro STAB *s; 7503132943Sgshapiro MAP *smap; 7504132943Sgshapiro 7505132943Sgshapiro if (tTd(38, 20)) 7506132943Sgshapiro sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 7507132943Sgshapiro (long) CurrentPid); 7508132943Sgshapiro 7509132943Sgshapiro /* Check if already closed */ 7510132943Sgshapiro if (map->map_db1 == NULL) 7511132943Sgshapiro { 7512132943Sgshapiro if (tTd(38, 20)) 7513132943Sgshapiro sm_dprintf("socket_map_close(%s) already closed\n", 7514132943Sgshapiro map->map_file); 7515132943Sgshapiro return; 7516132943Sgshapiro } 7517132943Sgshapiro sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 7518132943Sgshapiro 7519132943Sgshapiro /* Mark all the maps that share the connection as closed */ 7520132943Sgshapiro s = socket_map_findconn(map->map_file); 7521132943Sgshapiro smap = s->s_socketmap; 7522132943Sgshapiro while (smap != NULL) 7523132943Sgshapiro { 7524132943Sgshapiro MAP *next; 7525132943Sgshapiro 7526132943Sgshapiro if (tTd(38, 2) && smap != map) 7527132943Sgshapiro sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 7528132943Sgshapiro map->map_mname, smap->map_mname); 7529132943Sgshapiro 7530132943Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 7531132943Sgshapiro smap->map_db1 = NULL; 7532132943Sgshapiro next = smap->socket_map_next; 7533132943Sgshapiro smap->socket_map_next = NULL; 7534132943Sgshapiro smap = next; 7535132943Sgshapiro } 7536132943Sgshapiro s->s_socketmap = NULL; 7537132943Sgshapiro} 7538132943Sgshapiro 7539132943Sgshapiro/* 7540132943Sgshapiro** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 7541132943Sgshapiro*/ 7542132943Sgshapiro 7543132943Sgshapirochar * 7544132943Sgshapirosocket_map_lookup(map, name, av, statp) 7545132943Sgshapiro MAP *map; 7546132943Sgshapiro char *name; 7547132943Sgshapiro char **av; 7548132943Sgshapiro int *statp; 7549132943Sgshapiro{ 7550132943Sgshapiro unsigned int nettolen, replylen, recvlen; 7551132943Sgshapiro char *replybuf, *rval, *value, *status; 7552132943Sgshapiro SM_FILE_T *f; 7553132943Sgshapiro 7554132943Sgshapiro replybuf = NULL; 7555132943Sgshapiro rval = NULL; 7556132943Sgshapiro f = (SM_FILE_T *)map->map_db1; 7557132943Sgshapiro if (tTd(38, 20)) 7558132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s) %s\n", 7559132943Sgshapiro map->map_mname, name, map->map_file); 7560132943Sgshapiro 7561132943Sgshapiro nettolen = strlen(map->map_mname) + 1 + strlen(name); 7562132943Sgshapiro SM_ASSERT(nettolen > strlen(map->map_mname)); 7563132943Sgshapiro SM_ASSERT(nettolen > strlen(name)); 7564132943Sgshapiro if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 7565132943Sgshapiro nettolen, map->map_mname, name) == SM_IO_EOF) || 7566132943Sgshapiro (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 7567132943Sgshapiro (sm_io_error(f))) 7568132943Sgshapiro { 7569132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 7570132943Sgshapiro map->map_mname); 7571132943Sgshapiro *statp = EX_TEMPFAIL; 7572132943Sgshapiro goto errcl; 7573132943Sgshapiro } 7574132943Sgshapiro 7575132943Sgshapiro if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) 7576132943Sgshapiro { 7577132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", 7578132943Sgshapiro map->map_mname); 7579132943Sgshapiro *statp = EX_TEMPFAIL; 7580132943Sgshapiro goto errcl; 7581132943Sgshapiro } 7582132943Sgshapiro if (replylen > SOCKETMAP_MAXL) 7583132943Sgshapiro { 7584132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 7585132943Sgshapiro map->map_mname, replylen); 7586132943Sgshapiro *statp = EX_TEMPFAIL; 7587132943Sgshapiro goto errcl; 7588132943Sgshapiro } 7589132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 7590132943Sgshapiro { 7591132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 7592132943Sgshapiro map->map_mname); 7593132943Sgshapiro *statp = EX_TEMPFAIL; 7594132943Sgshapiro goto error; 7595132943Sgshapiro } 7596132943Sgshapiro 7597132943Sgshapiro replybuf = (char *) sm_malloc(replylen + 1); 7598132943Sgshapiro if (replybuf == NULL) 7599132943Sgshapiro { 7600132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 7601132943Sgshapiro map->map_mname, replylen + 1); 7602132943Sgshapiro *statp = EX_OSERR; 7603132943Sgshapiro goto error; 7604132943Sgshapiro } 7605132943Sgshapiro 7606132943Sgshapiro recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 7607132943Sgshapiro if (recvlen < replylen) 7608132943Sgshapiro { 7609132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 7610132943Sgshapiro map->map_mname, recvlen, replylen); 7611132943Sgshapiro *statp = EX_TEMPFAIL; 7612132943Sgshapiro goto errcl; 7613132943Sgshapiro } 7614132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 7615132943Sgshapiro { 7616132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 7617132943Sgshapiro map->map_mname); 7618132943Sgshapiro *statp = EX_TEMPFAIL; 7619132943Sgshapiro goto errcl; 7620132943Sgshapiro } 7621132943Sgshapiro status = replybuf; 7622132943Sgshapiro replybuf[recvlen] = '\0'; 7623132943Sgshapiro value = strchr(replybuf, ' '); 7624132943Sgshapiro if (value != NULL) 7625132943Sgshapiro { 7626132943Sgshapiro *value = '\0'; 7627132943Sgshapiro value++; 7628132943Sgshapiro } 7629132943Sgshapiro if (strcmp(status, "OK") == 0) 7630132943Sgshapiro { 7631132943Sgshapiro *statp = EX_OK; 7632132943Sgshapiro 7633132943Sgshapiro /* collect the return value */ 7634132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 7635132943Sgshapiro rval = map_rewrite(map, name, strlen(name), NULL); 7636132943Sgshapiro else 7637132943Sgshapiro rval = map_rewrite(map, value, strlen(value), av); 7638132943Sgshapiro } 7639132943Sgshapiro else if (strcmp(status, "NOTFOUND") == 0) 7640132943Sgshapiro { 7641132943Sgshapiro *statp = EX_NOTFOUND; 7642132943Sgshapiro if (tTd(38, 20)) 7643132943Sgshapiro sm_dprintf("socket_map_lookup(%s): %s not found\n", 7644132943Sgshapiro map->map_mname, name); 7645132943Sgshapiro } 7646132943Sgshapiro else 7647132943Sgshapiro { 7648132943Sgshapiro if (tTd(38, 5)) 7649132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 7650132943Sgshapiro map->map_mname, name, status, 7651132943Sgshapiro value ? value : ""); 7652132943Sgshapiro if ((strcmp(status, "TEMP") == 0) || 7653132943Sgshapiro (strcmp(status, "TIMEOUT") == 0)) 7654132943Sgshapiro *statp = EX_TEMPFAIL; 7655132943Sgshapiro else if(strcmp(status, "PERM") == 0) 7656132943Sgshapiro *statp = EX_UNAVAILABLE; 7657132943Sgshapiro else 7658132943Sgshapiro *statp = EX_PROTOCOL; 7659132943Sgshapiro } 7660132943Sgshapiro 7661132943Sgshapiro if (replybuf != NULL) 7662132943Sgshapiro sm_free(replybuf); 7663132943Sgshapiro return rval; 7664132943Sgshapiro 7665132943Sgshapiro errcl: 7666132943Sgshapiro socket_map_close(map); 7667132943Sgshapiro error: 7668132943Sgshapiro if (replybuf != NULL) 7669132943Sgshapiro sm_free(replybuf); 7670132943Sgshapiro return rval; 7671132943Sgshapiro} 7672132943Sgshapiro#endif /* SOCKETMAP */ 7673