map.c revision 157001
138032Speter/* 2147078Sgshapiro * Copyright (c) 1998-2005 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 16157001SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.671 2005/10/25 17:55:50 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; 3496157001Sgshapiro char keybuf[MAXKEY]; 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; 3554157001Sgshapiro# if _FFR_LDAP_SINGLEDN 3555157001Sgshapiro if (bitset(MF_SINGLEDN, map->map_mflags)) 3556157001Sgshapiro flags |= SM_LDAP_SINGLEDN; 3557157001Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 355890792Sgshapiro 3559132943Sgshapiro /* Create an rpool for search related memory usage */ 3560132943Sgshapiro rpool = sm_rpool_new_x(NULL); 356190792Sgshapiro 3562132943Sgshapiro p = NULL; 3563132943Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 3564132943Sgshapiro rpool, &p, &plen, &psize, NULL); 3565132943Sgshapiro save_errno = errno; 356690792Sgshapiro 3567132943Sgshapiro /* Copy result so rpool can be freed */ 3568132943Sgshapiro if (*statp == EX_OK && p != NULL) 3569132943Sgshapiro vp = newstr(p); 3570132943Sgshapiro sm_rpool_free(rpool); 357190792Sgshapiro 3572132943Sgshapiro /* need to restart LDAP connection? */ 3573132943Sgshapiro if (*statp == EX_RESTART) 357464562Sgshapiro { 3575132943Sgshapiro *statp = EX_TEMPFAIL; 3576132943Sgshapiro ldapmap_close(map); 357738032Speter } 357838032Speter 3579132943Sgshapiro errno = save_errno; 3580132943Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 358138032Speter { 358264562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 358364562Sgshapiro { 358464562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 358564562Sgshapiro syserr("Error getting LDAP results in map %s", 358664562Sgshapiro map->map_mname); 358764562Sgshapiro else 358894334Sgshapiro syserr("451 4.3.5 Error getting LDAP results in map %s", 358964562Sgshapiro map->map_mname); 359064562Sgshapiro } 359177349Sgshapiro errno = save_errno; 359264562Sgshapiro return NULL; 359338032Speter } 359490792Sgshapiro 359564562Sgshapiro /* Did we match anything? */ 359671345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 359764562Sgshapiro return NULL; 359838032Speter 359964562Sgshapiro if (*statp == EX_OK) 360064562Sgshapiro { 360164562Sgshapiro if (LogLevel > 9) 360264562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 360371345Sgshapiro "ldap %.100s => %s", name, 360471345Sgshapiro vp == NULL ? "<NULL>" : vp); 360564562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 360664562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 360764562Sgshapiro else 360871345Sgshapiro { 360971345Sgshapiro /* vp != NULL according to test above */ 361064562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 361171345Sgshapiro } 361271345Sgshapiro if (vp != NULL) 361390792Sgshapiro sm_free(vp); /* XXX */ 361464562Sgshapiro } 361564562Sgshapiro return result; 361638032Speter} 361738032Speter 361838032Speter/* 361964562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 362064562Sgshapiro** 362164562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 362266494Sgshapiro** secret, and PID so we don't have multiple connections open to 362366494Sgshapiro** the same server for different maps. Need a separate connection 362466494Sgshapiro** per PID since a parent process may close the map before the 362566494Sgshapiro** child is done with it. 362664562Sgshapiro** 362764562Sgshapiro** Parameters: 362864562Sgshapiro** lmap -- LDAP map information 362964562Sgshapiro** 363064562Sgshapiro** Returns: 363164562Sgshapiro** Symbol table entry for the LDAP connection. 363238032Speter*/ 363338032Speter 363464562Sgshapirostatic STAB * 363564562Sgshapiroldapmap_findconn(lmap) 363690792Sgshapiro SM_LDAP_STRUCT *lmap; 363738032Speter{ 363894334Sgshapiro char *format; 363964562Sgshapiro char *nbuf; 3640132943Sgshapiro char *id; 364190792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 364238032Speter 3643132943Sgshapiro if (lmap->ldap_host != NULL) 3644132943Sgshapiro id = lmap->ldap_host; 3645132943Sgshapiro else if (lmap->ldap_uri != NULL) 3646132943Sgshapiro id = lmap->ldap_uri; 3647132943Sgshapiro else 3648132943Sgshapiro id = "localhost"; 3649132943Sgshapiro 365094334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 365194334Sgshapiro nbuf = sm_stringf_x(format, 3652132943Sgshapiro id, 365390792Sgshapiro CONDELSE, 365490792Sgshapiro lmap->ldap_port, 365590792Sgshapiro CONDELSE, 365694334Sgshapiro lmap->ldap_version, 365794334Sgshapiro CONDELSE, 365890792Sgshapiro (lmap->ldap_binddn == NULL ? "" 365990792Sgshapiro : lmap->ldap_binddn), 366090792Sgshapiro CONDELSE, 366190792Sgshapiro (lmap->ldap_secret == NULL ? "" 366290792Sgshapiro : lmap->ldap_secret), 366390792Sgshapiro (int) CurrentPid); 366490792Sgshapiro SM_TRY 366590792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 366690792Sgshapiro SM_FINALLY 366790792Sgshapiro sm_free(nbuf); 366890792Sgshapiro SM_END_TRY 366964562Sgshapiro return s; 367064562Sgshapiro} 367138032Speter/* 367264562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 367364562Sgshapiro*/ 367438032Speter 367590792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 367664562Sgshapiro{ 367764562Sgshapiro { "none", LDAP_AUTH_NONE }, 367864562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 367964562Sgshapiro# ifdef LDAP_AUTH_KRBV4 368064562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 368164562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 368264562Sgshapiro { NULL, 0 } 368364562Sgshapiro}; 368438032Speter 368590792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 368664562Sgshapiro{ 368764562Sgshapiro { "never", LDAP_DEREF_NEVER }, 368864562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 368964562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 369064562Sgshapiro { "find", LDAP_DEREF_FINDING }, 369164562Sgshapiro { NULL, 0 } 369264562Sgshapiro}; 369338032Speter 369490792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 369564562Sgshapiro{ 369664562Sgshapiro { "base", LDAP_SCOPE_BASE }, 369764562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 369864562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 369964562Sgshapiro { NULL, 0 } 370064562Sgshapiro}; 370138032Speter 370264562Sgshapirobool 370364562Sgshapiroldapmap_parseargs(map, args) 370464562Sgshapiro MAP *map; 370564562Sgshapiro char *args; 370664562Sgshapiro{ 370790792Sgshapiro bool secretread = true; 3708132943Sgshapiro bool attrssetup = false; 370964562Sgshapiro int i; 371064562Sgshapiro register char *p = args; 371190792Sgshapiro SM_LDAP_STRUCT *lmap; 371264562Sgshapiro struct lamvalues *lam; 371364562Sgshapiro struct ladvalues *lad; 371464562Sgshapiro struct lssvalues *lss; 371590792Sgshapiro char ldapfilt[MAXLINE]; 371664562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 371764562Sgshapiro 371864562Sgshapiro /* Get ldap struct pointer from map */ 371990792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 372064562Sgshapiro 372164562Sgshapiro /* Check if setting the initial LDAP defaults */ 372264562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 372364562Sgshapiro { 372490792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 372590792Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof *lmap); 372664562Sgshapiro if (LDAPDefaults == NULL) 372790792Sgshapiro sm_ldap_clear(lmap); 372864562Sgshapiro else 372964562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 373064562Sgshapiro } 373164562Sgshapiro 373264562Sgshapiro /* there is no check whether there is really an argument */ 373364562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 373464562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 373590792Sgshapiro 373690792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 373790792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 373890792Sgshapiro { 373990792Sgshapiro /* Comma separate if used as an alias file */ 374090792Sgshapiro map->map_coldelim = ','; 374190792Sgshapiro if (*args == '\0') 374290792Sgshapiro { 374390792Sgshapiro int n; 374490792Sgshapiro char *lc; 374590792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 374690792Sgshapiro char lcbuf[MAXLINE]; 374790792Sgshapiro 374890792Sgshapiro /* Get $j */ 374990792Sgshapiro expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 375090792Sgshapiro if (jbuf[0] == '\0') 375190792Sgshapiro { 375290792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 375390792Sgshapiro sizeof jbuf); 375490792Sgshapiro } 375590792Sgshapiro 375690792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 375790792Sgshapiro if (lc == NULL) 375890792Sgshapiro lc = ""; 375990792Sgshapiro else 376090792Sgshapiro { 376190792Sgshapiro expand(lc, lcbuf, sizeof lcbuf, CurEnv); 376290792Sgshapiro lc = lcbuf; 376390792Sgshapiro } 376490792Sgshapiro 376590792Sgshapiro n = sm_snprintf(ldapfilt, sizeof ldapfilt, 376690792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 376790792Sgshapiro lc, jbuf); 376890792Sgshapiro if (n >= sizeof ldapfilt) 376990792Sgshapiro { 377090792Sgshapiro syserr("%s: Default LDAP string too long", 377190792Sgshapiro map->map_mname); 377290792Sgshapiro return false; 377390792Sgshapiro } 377490792Sgshapiro 377590792Sgshapiro /* default args for an alias LDAP entry */ 377690792Sgshapiro lmap->ldap_filter = ldapfilt; 3777132943Sgshapiro lmap->ldap_attr[0] = "objectClass"; 3778132943Sgshapiro lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 3779132943Sgshapiro lmap->ldap_attr_needobjclass[0] = NULL; 3780132943Sgshapiro lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 3781132943Sgshapiro lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 3782132943Sgshapiro lmap->ldap_attr_needobjclass[1] = NULL; 3783132943Sgshapiro lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 3784132943Sgshapiro lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 3785132943Sgshapiro lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 3786132943Sgshapiro lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 3787132943Sgshapiro lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 3788132943Sgshapiro lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 3789132943Sgshapiro lmap->ldap_attr[4] = NULL; 3790132943Sgshapiro lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 3791132943Sgshapiro lmap->ldap_attr_needobjclass[4] = NULL; 3792132943Sgshapiro attrssetup = true; 379390792Sgshapiro } 379490792Sgshapiro } 379590792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 379690792Sgshapiro { 379790792Sgshapiro /* Space separate if used as a file class file */ 379890792Sgshapiro map->map_coldelim = ' '; 379990792Sgshapiro } 380090792Sgshapiro 380138032Speter for (;;) 380238032Speter { 380338032Speter while (isascii(*p) && isspace(*p)) 380438032Speter p++; 380538032Speter if (*p != '-') 380638032Speter break; 380738032Speter switch (*++p) 380838032Speter { 380938032Speter case 'N': 381038032Speter map->map_mflags |= MF_INCLNULL; 381138032Speter map->map_mflags &= ~MF_TRY0NULL; 381238032Speter break; 381338032Speter 381438032Speter case 'O': 381538032Speter map->map_mflags &= ~MF_TRY1NULL; 381638032Speter break; 381738032Speter 381838032Speter case 'o': 381938032Speter map->map_mflags |= MF_OPTIONAL; 382038032Speter break; 382138032Speter 382238032Speter case 'f': 382338032Speter map->map_mflags |= MF_NOFOLDCASE; 382438032Speter break; 382538032Speter 382638032Speter case 'm': 382738032Speter map->map_mflags |= MF_MATCHONLY; 382838032Speter break; 382938032Speter 383038032Speter case 'A': 383138032Speter map->map_mflags |= MF_APPEND; 383238032Speter break; 383338032Speter 383438032Speter case 'q': 383538032Speter map->map_mflags |= MF_KEEPQUOTES; 383638032Speter break; 383738032Speter 383838032Speter case 'a': 383938032Speter map->map_app = ++p; 384038032Speter break; 384138032Speter 384238032Speter case 'T': 384338032Speter map->map_tapp = ++p; 384438032Speter break; 384538032Speter 384664562Sgshapiro case 't': 384764562Sgshapiro map->map_mflags |= MF_NODEFER; 384864562Sgshapiro break; 384964562Sgshapiro 385064562Sgshapiro case 'S': 385164562Sgshapiro map->map_spacesub = *++p; 385264562Sgshapiro break; 385364562Sgshapiro 385464562Sgshapiro case 'D': 385564562Sgshapiro map->map_mflags |= MF_DEFER; 385664562Sgshapiro break; 385764562Sgshapiro 385864562Sgshapiro case 'z': 385964562Sgshapiro if (*++p != '\\') 386064562Sgshapiro map->map_coldelim = *p; 386164562Sgshapiro else 386264562Sgshapiro { 386364562Sgshapiro switch (*++p) 386464562Sgshapiro { 386564562Sgshapiro case 'n': 386664562Sgshapiro map->map_coldelim = '\n'; 386764562Sgshapiro break; 386864562Sgshapiro 386964562Sgshapiro case 't': 387064562Sgshapiro map->map_coldelim = '\t'; 387164562Sgshapiro break; 387264562Sgshapiro 387364562Sgshapiro default: 387464562Sgshapiro map->map_coldelim = '\\'; 387564562Sgshapiro } 387664562Sgshapiro } 387764562Sgshapiro break; 387864562Sgshapiro 387964562Sgshapiro /* Start of ldapmap specific args */ 388090792Sgshapiro case 'V': 388190792Sgshapiro if (*++p != '\\') 388290792Sgshapiro lmap->ldap_attrsep = *p; 388390792Sgshapiro else 388490792Sgshapiro { 388590792Sgshapiro switch (*++p) 388690792Sgshapiro { 388790792Sgshapiro case 'n': 388890792Sgshapiro lmap->ldap_attrsep = '\n'; 388990792Sgshapiro break; 389090792Sgshapiro 389190792Sgshapiro case 't': 389290792Sgshapiro lmap->ldap_attrsep = '\t'; 389390792Sgshapiro break; 389490792Sgshapiro 389590792Sgshapiro default: 389690792Sgshapiro lmap->ldap_attrsep = '\\'; 389790792Sgshapiro } 389890792Sgshapiro } 389990792Sgshapiro break; 390090792Sgshapiro 390138032Speter case 'k': /* search field */ 390238032Speter while (isascii(*++p) && isspace(*p)) 390338032Speter continue; 390464562Sgshapiro lmap->ldap_filter = p; 390538032Speter break; 390638032Speter 390738032Speter case 'v': /* attr to return */ 390838032Speter while (isascii(*++p) && isspace(*p)) 390938032Speter continue; 391064562Sgshapiro lmap->ldap_attr[0] = p; 391164562Sgshapiro lmap->ldap_attr[1] = NULL; 391238032Speter break; 391338032Speter 391464562Sgshapiro case '1': 391564562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 391664562Sgshapiro break; 391764562Sgshapiro 3918157001Sgshapiro# if _FFR_LDAP_SINGLEDN 3919157001Sgshapiro case '2': 3920157001Sgshapiro map->map_mflags |= MF_SINGLEDN; 3921157001Sgshapiro break; 3922157001Sgshapiro# endif /* _FFR_LDAP_SINGLEDN */ 3923157001Sgshapiro 392438032Speter /* args stolen from ldapsearch.c */ 392538032Speter case 'R': /* don't auto chase referrals */ 392664562Sgshapiro# ifdef LDAP_REFERRALS 392738032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 392864562Sgshapiro# else /* LDAP_REFERRALS */ 392990792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 393064562Sgshapiro# endif /* LDAP_REFERRALS */ 393138032Speter break; 393238032Speter 393364562Sgshapiro case 'n': /* retrieve attribute names only */ 393464562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 393538032Speter break; 393638032Speter 393764562Sgshapiro case 'r': /* alias dereferencing */ 393864562Sgshapiro while (isascii(*++p) && isspace(*p)) 393964562Sgshapiro continue; 394064562Sgshapiro 394190792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 394264562Sgshapiro p += 11; 394364562Sgshapiro 394464562Sgshapiro for (lad = LDAPAliasDereference; 394564562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 394638032Speter { 394790792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 394890792Sgshapiro strlen(lad->lad_name)) == 0) 394964562Sgshapiro break; 395038032Speter } 395164562Sgshapiro if (lad->lad_name != NULL) 395264562Sgshapiro lmap->ldap_deref = lad->lad_code; 395364562Sgshapiro else 395438032Speter { 395564562Sgshapiro /* bad config line */ 395664562Sgshapiro if (!bitset(MCF_OPTFILE, 395764562Sgshapiro map->map_class->map_cflags)) 395864562Sgshapiro { 395964562Sgshapiro char *ptr; 396064562Sgshapiro 396164562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 396264562Sgshapiro *ptr = '\0'; 396373188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 396464562Sgshapiro p, map->map_mname); 396564562Sgshapiro if (ptr != NULL) 396664562Sgshapiro *ptr = ' '; 396790792Sgshapiro return false; 396864562Sgshapiro } 396938032Speter } 397064562Sgshapiro break; 397164562Sgshapiro 397264562Sgshapiro case 's': /* search scope */ 397364562Sgshapiro while (isascii(*++p) && isspace(*p)) 397464562Sgshapiro continue; 397564562Sgshapiro 397690792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 397764562Sgshapiro p += 11; 397864562Sgshapiro 397964562Sgshapiro for (lss = LDAPSearchScope; 398064562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 398138032Speter { 398290792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 398390792Sgshapiro strlen(lss->lss_name)) == 0) 398464562Sgshapiro break; 398538032Speter } 398664562Sgshapiro if (lss->lss_name != NULL) 398764562Sgshapiro lmap->ldap_scope = lss->lss_code; 398838032Speter else 398964562Sgshapiro { 399064562Sgshapiro /* bad config line */ 399164562Sgshapiro if (!bitset(MCF_OPTFILE, 399264562Sgshapiro map->map_class->map_cflags)) 399338032Speter { 399438032Speter char *ptr; 399538032Speter 399638032Speter if ((ptr = strchr(p, ' ')) != NULL) 399738032Speter *ptr = '\0'; 399873188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 399938032Speter p, map->map_mname); 400038032Speter if (ptr != NULL) 400138032Speter *ptr = ' '; 400290792Sgshapiro return false; 400338032Speter } 400438032Speter } 400538032Speter break; 400638032Speter 400738032Speter case 'h': /* ldap host */ 400838032Speter while (isascii(*++p) && isspace(*p)) 400938032Speter continue; 4010132943Sgshapiro if (lmap->ldap_uri != NULL) 401194334Sgshapiro { 401294334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 401394334Sgshapiro map->map_mname); 401494334Sgshapiro return false; 401594334Sgshapiro } 4016132943Sgshapiro lmap->ldap_host = p; 401738032Speter break; 401838032Speter 401938032Speter case 'b': /* search base */ 402038032Speter while (isascii(*++p) && isspace(*p)) 402138032Speter continue; 402264562Sgshapiro lmap->ldap_base = p; 402338032Speter break; 402438032Speter 402538032Speter case 'p': /* ldap port */ 402638032Speter while (isascii(*++p) && isspace(*p)) 402738032Speter continue; 402864562Sgshapiro lmap->ldap_port = atoi(p); 402938032Speter break; 403038032Speter 403138032Speter case 'l': /* time limit */ 403238032Speter while (isascii(*++p) && isspace(*p)) 403338032Speter continue; 403464562Sgshapiro lmap->ldap_timelimit = atoi(p); 403564562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 403638032Speter break; 403738032Speter 403864562Sgshapiro case 'Z': 403964562Sgshapiro while (isascii(*++p) && isspace(*p)) 404064562Sgshapiro continue; 404164562Sgshapiro lmap->ldap_sizelimit = atoi(p); 404264562Sgshapiro break; 404364562Sgshapiro 404464562Sgshapiro case 'd': /* Dn to bind to server as */ 404564562Sgshapiro while (isascii(*++p) && isspace(*p)) 404664562Sgshapiro continue; 404764562Sgshapiro lmap->ldap_binddn = p; 404864562Sgshapiro break; 404964562Sgshapiro 405064562Sgshapiro case 'M': /* Method for binding */ 405164562Sgshapiro while (isascii(*++p) && isspace(*p)) 405264562Sgshapiro continue; 405364562Sgshapiro 405490792Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 405564562Sgshapiro p += 10; 405664562Sgshapiro 405764562Sgshapiro for (lam = LDAPAuthMethods; 405864562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 405964562Sgshapiro { 406090792Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 406190792Sgshapiro strlen(lam->lam_name)) == 0) 406264562Sgshapiro break; 406364562Sgshapiro } 406464562Sgshapiro if (lam->lam_name != NULL) 406564562Sgshapiro lmap->ldap_method = lam->lam_code; 406664562Sgshapiro else 406764562Sgshapiro { 406864562Sgshapiro /* bad config line */ 406964562Sgshapiro if (!bitset(MCF_OPTFILE, 407064562Sgshapiro map->map_class->map_cflags)) 407164562Sgshapiro { 407264562Sgshapiro char *ptr; 407364562Sgshapiro 407464562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 407564562Sgshapiro *ptr = '\0'; 407673188Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 407764562Sgshapiro p, map->map_mname); 407864562Sgshapiro if (ptr != NULL) 407964562Sgshapiro *ptr = ' '; 408090792Sgshapiro return false; 408164562Sgshapiro } 408264562Sgshapiro } 408364562Sgshapiro 408464562Sgshapiro break; 408564562Sgshapiro 408664562Sgshapiro /* 408764562Sgshapiro ** This is a string that is dependent on the 408864562Sgshapiro ** method used defined above. 408964562Sgshapiro */ 409064562Sgshapiro 409164562Sgshapiro case 'P': /* Secret password for binding */ 409264562Sgshapiro while (isascii(*++p) && isspace(*p)) 409364562Sgshapiro continue; 409464562Sgshapiro lmap->ldap_secret = p; 409590792Sgshapiro secretread = false; 409664562Sgshapiro break; 409764562Sgshapiro 409894334Sgshapiro case 'H': /* Use LDAP URI */ 409994334Sgshapiro# if !USE_LDAP_INIT 410094334Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 410194334Sgshapiro map->map_mname); 410294334Sgshapiro return false; 4103132943Sgshapiro# else /* !USE_LDAP_INIT */ 4104132943Sgshapiro if (lmap->ldap_host != NULL) 410594334Sgshapiro { 410694334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 410794334Sgshapiro map->map_mname); 410894334Sgshapiro return false; 410994334Sgshapiro } 411094334Sgshapiro while (isascii(*++p) && isspace(*p)) 411194334Sgshapiro continue; 4112132943Sgshapiro lmap->ldap_uri = p; 411394334Sgshapiro break; 411494334Sgshapiro# endif /* !USE_LDAP_INIT */ 411594334Sgshapiro 411694334Sgshapiro case 'w': 411794334Sgshapiro /* -w should be for passwd, -P should be for version */ 411894334Sgshapiro while (isascii(*++p) && isspace(*p)) 411994334Sgshapiro continue; 412094334Sgshapiro lmap->ldap_version = atoi(p); 4121132943Sgshapiro# ifdef LDAP_VERSION_MAX 412294334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 412394334Sgshapiro { 412494334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 412594334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 412694334Sgshapiro map->map_mname); 412794334Sgshapiro return false; 412894334Sgshapiro } 4129132943Sgshapiro# endif /* LDAP_VERSION_MAX */ 4130132943Sgshapiro# ifdef LDAP_VERSION_MIN 413194334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 413294334Sgshapiro { 413394334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 413494334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 413594334Sgshapiro map->map_mname); 413694334Sgshapiro return false; 413794334Sgshapiro } 4138132943Sgshapiro# endif /* LDAP_VERSION_MIN */ 413994334Sgshapiro break; 414094334Sgshapiro 414164562Sgshapiro default: 414264562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 414364562Sgshapiro break; 414438032Speter } 414538032Speter 414664562Sgshapiro /* need to account for quoted strings here */ 414764562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 414838032Speter { 414938032Speter if (*p == '"') 415038032Speter { 415138032Speter while (*++p != '"' && *p != '\0') 415238032Speter continue; 415338032Speter if (*p != '\0') 415438032Speter p++; 415538032Speter } 415638032Speter else 415738032Speter p++; 415838032Speter } 415938032Speter 416038032Speter if (*p != '\0') 416138032Speter *p++ = '\0'; 416238032Speter } 416338032Speter 416438032Speter if (map->map_app != NULL) 416564562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 416638032Speter if (map->map_tapp != NULL) 416764562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 416838032Speter 416938032Speter /* 417042575Speter ** We need to swallow up all the stuff into a struct 417142575Speter ** and dump it into map->map_dbptr1 417238032Speter */ 417338032Speter 4174132943Sgshapiro if (lmap->ldap_host != NULL && 417564562Sgshapiro (LDAPDefaults == NULL || 417664562Sgshapiro LDAPDefaults == lmap || 4177132943Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 4178132943Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 4179132943Sgshapiro map->map_domain = lmap->ldap_host; 418064562Sgshapiro 4181132943Sgshapiro if (lmap->ldap_uri != NULL && 4182132943Sgshapiro (LDAPDefaults == NULL || 4183132943Sgshapiro LDAPDefaults == lmap || 4184132943Sgshapiro LDAPDefaults->ldap_uri != lmap->ldap_uri)) 4185132943Sgshapiro lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 4186132943Sgshapiro map->map_domain = lmap->ldap_uri; 4187132943Sgshapiro 418864562Sgshapiro if (lmap->ldap_binddn != NULL && 418964562Sgshapiro (LDAPDefaults == NULL || 419064562Sgshapiro LDAPDefaults == lmap || 419164562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 419264562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 419364562Sgshapiro 419464562Sgshapiro if (lmap->ldap_secret != NULL && 419564562Sgshapiro (LDAPDefaults == NULL || 419664562Sgshapiro LDAPDefaults == lmap || 419764562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 419838032Speter { 419990792Sgshapiro SM_FILE_T *sfd; 420064562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 420138032Speter 420264562Sgshapiro if (DontLockReadFiles) 420364562Sgshapiro sff |= SFF_NOLOCK; 420438032Speter 420564562Sgshapiro /* need to use method to map secret to passwd string */ 420664562Sgshapiro switch (lmap->ldap_method) 420764562Sgshapiro { 420864562Sgshapiro case LDAP_AUTH_NONE: 420964562Sgshapiro /* Do nothing */ 421064562Sgshapiro break; 421138032Speter 421264562Sgshapiro case LDAP_AUTH_SIMPLE: 421338032Speter 421464562Sgshapiro /* 421564562Sgshapiro ** Secret is the name of a file with 421664562Sgshapiro ** the first line as the password. 421764562Sgshapiro */ 421864562Sgshapiro 421964562Sgshapiro /* Already read in the secret? */ 422064562Sgshapiro if (secretread) 422164562Sgshapiro break; 422264562Sgshapiro 422364562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 422464562Sgshapiro O_RDONLY, 0, sff); 422564562Sgshapiro if (sfd == NULL) 422664562Sgshapiro { 422764562Sgshapiro syserr("LDAP map: cannot open secret %s", 422864562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 422990792Sgshapiro return false; 423064562Sgshapiro } 423198121Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof m_tmp, 423266494Sgshapiro sfd, TimeOuts.to_fileopen, 423366494Sgshapiro "ldapmap_parseargs"); 423490792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 423598121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 423698121Sgshapiro { 423798121Sgshapiro syserr("LDAP map: secret in %s too long", 423898121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 423998121Sgshapiro return false; 424098121Sgshapiro } 424164562Sgshapiro if (lmap->ldap_secret != NULL && 424264562Sgshapiro strlen(m_tmp) > 0) 424364562Sgshapiro { 424464562Sgshapiro /* chomp newline */ 424564562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 424664562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 424764562Sgshapiro 424864562Sgshapiro lmap->ldap_secret = m_tmp; 424964562Sgshapiro } 425064562Sgshapiro break; 425164562Sgshapiro 425264562Sgshapiro# ifdef LDAP_AUTH_KRBV4 425364562Sgshapiro case LDAP_AUTH_KRBV4: 425464562Sgshapiro 425564562Sgshapiro /* 425664562Sgshapiro ** Secret is where the ticket file is 425764562Sgshapiro ** stashed 425864562Sgshapiro */ 425964562Sgshapiro 426098121Sgshapiro (void) sm_snprintf(m_tmp, sizeof m_tmp, 426190792Sgshapiro "KRBTKFILE=%s", 426290792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 426364562Sgshapiro lmap->ldap_secret = m_tmp; 426464562Sgshapiro break; 426564562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 426664562Sgshapiro 426764562Sgshapiro default: /* Should NEVER get here */ 426864562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 426990792Sgshapiro return false; 427090792Sgshapiro /* NOTREACHED */ 427164562Sgshapiro break; 427264562Sgshapiro } 427338032Speter } 427438032Speter 427564562Sgshapiro if (lmap->ldap_secret != NULL && 427664562Sgshapiro (LDAPDefaults == NULL || 427764562Sgshapiro LDAPDefaults == lmap || 427864562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 427964562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 428038032Speter 428164562Sgshapiro if (lmap->ldap_base != NULL && 428264562Sgshapiro (LDAPDefaults == NULL || 428364562Sgshapiro LDAPDefaults == lmap || 428464562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 428564562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 428664562Sgshapiro 428764562Sgshapiro /* 428864562Sgshapiro ** Save the server from extra work. If request is for a single 428964562Sgshapiro ** match, tell the server to only return enough records to 429064562Sgshapiro ** determine if there is a single match or not. This can not 429164562Sgshapiro ** be one since the server would only return one and we wouldn't 429264562Sgshapiro ** know if there were others available. 429364562Sgshapiro */ 429464562Sgshapiro 429564562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 429664562Sgshapiro lmap->ldap_sizelimit = 2; 429764562Sgshapiro 429864562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 429964562Sgshapiro if (lmap == LDAPDefaults) 430090792Sgshapiro return true; 430164562Sgshapiro 430264562Sgshapiro if (lmap->ldap_filter != NULL) 430364562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 430438032Speter else 430538032Speter { 430638032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 430738032Speter { 430838032Speter syserr("No filter given in map %s", map->map_mname); 430990792Sgshapiro return false; 431038032Speter } 431138032Speter } 431264562Sgshapiro 4313132943Sgshapiro if (!attrssetup && lmap->ldap_attr[0] != NULL) 431438032Speter { 431590792Sgshapiro bool recurse = false; 431694334Sgshapiro bool normalseen = false; 431790792Sgshapiro 431864562Sgshapiro i = 0; 431964562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 432064562Sgshapiro lmap->ldap_attr[0] = NULL; 432164562Sgshapiro 432294334Sgshapiro /* Prime the attr list with the objectClass attribute */ 432394334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 432494334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 432594334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 432694334Sgshapiro i++; 432794334Sgshapiro 432864562Sgshapiro while (p != NULL) 432938032Speter { 433064562Sgshapiro char *v; 433164562Sgshapiro 433264562Sgshapiro while (isascii(*p) && isspace(*p)) 433364562Sgshapiro p++; 433464562Sgshapiro if (*p == '\0') 433564562Sgshapiro break; 433664562Sgshapiro v = p; 433764562Sgshapiro p = strchr(v, ','); 433864562Sgshapiro if (p != NULL) 433964562Sgshapiro *p++ = '\0'; 434064562Sgshapiro 434171345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 434264562Sgshapiro { 434364562Sgshapiro syserr("Too many return attributes in %s (max %d)", 434464562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 434590792Sgshapiro return false; 434664562Sgshapiro } 434764562Sgshapiro if (*v != '\0') 434890792Sgshapiro { 434994334Sgshapiro int j; 435094334Sgshapiro int use; 435190792Sgshapiro char *type; 435294334Sgshapiro char *needobjclass; 435390792Sgshapiro 435490792Sgshapiro type = strchr(v, ':'); 435590792Sgshapiro if (type != NULL) 435694334Sgshapiro { 435790792Sgshapiro *type++ = '\0'; 435894334Sgshapiro needobjclass = strchr(type, ':'); 435994334Sgshapiro if (needobjclass != NULL) 436094334Sgshapiro *needobjclass++ = '\0'; 436194334Sgshapiro } 436294334Sgshapiro else 436394334Sgshapiro { 436494334Sgshapiro needobjclass = NULL; 436594334Sgshapiro } 436690792Sgshapiro 436794334Sgshapiro use = i; 436890792Sgshapiro 436994334Sgshapiro /* allow override on "objectClass" type */ 437094334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 437194334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 437290792Sgshapiro { 437394334Sgshapiro use = 0; 437494334Sgshapiro } 437594334Sgshapiro else 437694334Sgshapiro { 437794334Sgshapiro /* 437894334Sgshapiro ** Don't add something to attribute 437994334Sgshapiro ** list twice. 438094334Sgshapiro */ 438194334Sgshapiro 438294334Sgshapiro for (j = 1; j < i; j++) 438390792Sgshapiro { 438494334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 438594334Sgshapiro { 438694334Sgshapiro syserr("Duplicate attribute (%s) in %s", 438794334Sgshapiro v, map->map_mname); 438894334Sgshapiro return false; 438994334Sgshapiro } 439090792Sgshapiro } 439194334Sgshapiro 439294334Sgshapiro lmap->ldap_attr[use] = newstr(v); 439394334Sgshapiro if (needobjclass != NULL && 439494334Sgshapiro *needobjclass != '\0' && 439594334Sgshapiro *needobjclass != '*') 439690792Sgshapiro { 439794334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 439894334Sgshapiro } 439994334Sgshapiro else 440094334Sgshapiro { 440194334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 440294334Sgshapiro } 440394334Sgshapiro 440494334Sgshapiro } 440594334Sgshapiro 440694334Sgshapiro if (type != NULL && *type != '\0') 440794334Sgshapiro { 440894334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 440994334Sgshapiro { 441090792Sgshapiro recurse = true; 441194334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 441290792Sgshapiro } 441390792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 441490792Sgshapiro { 441590792Sgshapiro recurse = true; 441694334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 441790792Sgshapiro } 441890792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 441990792Sgshapiro { 442090792Sgshapiro recurse = true; 442194334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 442290792Sgshapiro } 442394334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 442490792Sgshapiro { 442594334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 442694334Sgshapiro normalseen = true; 442790792Sgshapiro } 442890792Sgshapiro else 442990792Sgshapiro { 443090792Sgshapiro syserr("Unknown attribute type (%s) in %s", 443190792Sgshapiro type, map->map_mname); 443290792Sgshapiro return false; 443390792Sgshapiro } 443490792Sgshapiro } 443590792Sgshapiro else 443694334Sgshapiro { 443794334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 443894334Sgshapiro normalseen = true; 443994334Sgshapiro } 444090792Sgshapiro i++; 444190792Sgshapiro } 444238032Speter } 444364562Sgshapiro lmap->ldap_attr[i] = NULL; 4444141858Sgshapiro 4445141858Sgshapiro /* Set in case needed in future code */ 4446132943Sgshapiro attrssetup = true; 4447141858Sgshapiro 444894334Sgshapiro if (recurse && !normalseen) 444990792Sgshapiro { 445094334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 445190792Sgshapiro map->map_mname); 445290792Sgshapiro return false; 445390792Sgshapiro } 445490792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 445590792Sgshapiro { 445690792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 445790792Sgshapiro map->map_mname); 445890792Sgshapiro return false; 445990792Sgshapiro } 446038032Speter } 446138032Speter map->map_db1 = (ARBPTR_T) lmap; 446290792Sgshapiro return true; 446338032Speter} 446438032Speter 446564562Sgshapiro/* 446664562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 446764562Sgshapiro** 446864562Sgshapiro** Parameters: 446964562Sgshapiro** spec -- map argument string from LDAPDefaults option 447064562Sgshapiro** 447164562Sgshapiro** Returns: 447264562Sgshapiro** None. 447364562Sgshapiro*/ 447464562Sgshapiro 447564562Sgshapirovoid 447664562Sgshapiroldapmap_set_defaults(spec) 447764562Sgshapiro char *spec; 447864562Sgshapiro{ 447973188Sgshapiro STAB *class; 448064562Sgshapiro MAP map; 448164562Sgshapiro 448264562Sgshapiro /* Allocate and set the default values */ 448364562Sgshapiro if (LDAPDefaults == NULL) 448490792Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 448590792Sgshapiro sm_ldap_clear(LDAPDefaults); 448664562Sgshapiro 448764562Sgshapiro memset(&map, '\0', sizeof map); 448873188Sgshapiro 448973188Sgshapiro /* look up the class */ 449073188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 449173188Sgshapiro if (class == NULL) 449273188Sgshapiro { 449373188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 449473188Sgshapiro return; 449573188Sgshapiro } 449673188Sgshapiro map.map_class = &class->s_mapclass; 449764562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 449873188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 449964562Sgshapiro 450064562Sgshapiro (void) ldapmap_parseargs(&map, spec); 450164562Sgshapiro 450264562Sgshapiro /* These should never be set in LDAPDefaults */ 450364562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 450464562Sgshapiro map.map_spacesub != SpaceSub || 450564562Sgshapiro map.map_app != NULL || 450664562Sgshapiro map.map_tapp != NULL) 450764562Sgshapiro { 450864562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 450990792Sgshapiro SM_FREE_CLR(map.map_app); 451090792Sgshapiro SM_FREE_CLR(map.map_tapp); 451164562Sgshapiro } 451264562Sgshapiro 451364562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 451464562Sgshapiro { 451564562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 451694334Sgshapiro 451764562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 451864562Sgshapiro LDAPDefaults->ldap_filter = NULL; 451964562Sgshapiro } 452064562Sgshapiro 452164562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 452264562Sgshapiro { 452364562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 452464562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 452564562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 452664562Sgshapiro } 452764562Sgshapiro} 452864562Sgshapiro#endif /* LDAPMAP */ 452990792Sgshapiro/* 453064562Sgshapiro** PH map 453164562Sgshapiro*/ 453264562Sgshapiro 453390792Sgshapiro#if PH_MAP 453464562Sgshapiro 453564562Sgshapiro/* 453664562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 453764562Sgshapiro** This code is intended to replace the so-called "ph mailer". 453864562Sgshapiro** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 453964562Sgshapiro*/ 454064562Sgshapiro 454190792Sgshapiro/* what version of the ph map code we're running */ 4542110560Sgshapirostatic char phmap_id[128]; 454364562Sgshapiro 454490792Sgshapiro/* sendmail version for phmap id string */ 454590792Sgshapiroextern const char Version[]; 454690792Sgshapiro 4547132943Sgshapiro/* assume we're using nph-1.2.x if not specified */ 4548110560Sgshapiro# ifndef NPH_VERSION 4549132943Sgshapiro# define NPH_VERSION 10200 4550110560Sgshapiro# endif 4551110560Sgshapiro 4552110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 4553110560Sgshapiro# if NPH_VERSION < 10200 4554110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 4555110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 4556110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 4557110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 4558110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 4559110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 4560110560Sgshapiro 456164562Sgshapiro/* 456264562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 456364562Sgshapiro*/ 456464562Sgshapiro 456564562Sgshapirobool 456664562Sgshapiroph_map_parseargs(map, args) 456764562Sgshapiro MAP *map; 456864562Sgshapiro char *args; 456964562Sgshapiro{ 457090792Sgshapiro register bool done; 457190792Sgshapiro register char *p = args; 457264562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 457364562Sgshapiro 457490792Sgshapiro /* initialize version string */ 457590792Sgshapiro (void) sm_snprintf(phmap_id, sizeof phmap_id, 457690792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 457790792Sgshapiro Version, libphclient_version); 457890792Sgshapiro 457964562Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 458064562Sgshapiro 458164562Sgshapiro /* defaults */ 458264562Sgshapiro pmap->ph_servers = NULL; 458364562Sgshapiro pmap->ph_field_list = NULL; 458490792Sgshapiro pmap->ph = NULL; 458564562Sgshapiro pmap->ph_timeout = 0; 458690792Sgshapiro pmap->ph_fastclose = 0; 458764562Sgshapiro 458864562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 458964562Sgshapiro for (;;) 459064562Sgshapiro { 459164562Sgshapiro while (isascii(*p) && isspace(*p)) 459264562Sgshapiro p++; 459364562Sgshapiro if (*p != '-') 459464562Sgshapiro break; 459564562Sgshapiro switch (*++p) 459664562Sgshapiro { 459764562Sgshapiro case 'N': 459864562Sgshapiro map->map_mflags |= MF_INCLNULL; 459964562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 460064562Sgshapiro break; 460164562Sgshapiro 460264562Sgshapiro case 'O': 460364562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 460464562Sgshapiro break; 460564562Sgshapiro 460664562Sgshapiro case 'o': 460764562Sgshapiro map->map_mflags |= MF_OPTIONAL; 460864562Sgshapiro break; 460964562Sgshapiro 461064562Sgshapiro case 'f': 461164562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 461264562Sgshapiro break; 461364562Sgshapiro 461464562Sgshapiro case 'm': 461564562Sgshapiro map->map_mflags |= MF_MATCHONLY; 461664562Sgshapiro break; 461764562Sgshapiro 461864562Sgshapiro case 'A': 461964562Sgshapiro map->map_mflags |= MF_APPEND; 462064562Sgshapiro break; 462164562Sgshapiro 462264562Sgshapiro case 'q': 462364562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 462464562Sgshapiro break; 462564562Sgshapiro 462664562Sgshapiro case 't': 462764562Sgshapiro map->map_mflags |= MF_NODEFER; 462864562Sgshapiro break; 462964562Sgshapiro 463064562Sgshapiro case 'a': 463164562Sgshapiro map->map_app = ++p; 463264562Sgshapiro break; 463364562Sgshapiro 463464562Sgshapiro case 'T': 463564562Sgshapiro map->map_tapp = ++p; 463664562Sgshapiro break; 463764562Sgshapiro 463864562Sgshapiro case 'l': 463964562Sgshapiro while (isascii(*++p) && isspace(*p)) 464064562Sgshapiro continue; 464164562Sgshapiro pmap->ph_timeout = atoi(p); 464264562Sgshapiro break; 464364562Sgshapiro 464464562Sgshapiro case 'S': 464564562Sgshapiro map->map_spacesub = *++p; 464664562Sgshapiro break; 464764562Sgshapiro 464864562Sgshapiro case 'D': 464964562Sgshapiro map->map_mflags |= MF_DEFER; 465064562Sgshapiro break; 465164562Sgshapiro 465264562Sgshapiro case 'h': /* PH server list */ 465364562Sgshapiro while (isascii(*++p) && isspace(*p)) 465464562Sgshapiro continue; 465564562Sgshapiro pmap->ph_servers = p; 465664562Sgshapiro break; 465764562Sgshapiro 465890792Sgshapiro case 'k': /* fields to search for */ 465964562Sgshapiro while (isascii(*++p) && isspace(*p)) 466064562Sgshapiro continue; 466164562Sgshapiro pmap->ph_field_list = p; 466264562Sgshapiro break; 466364562Sgshapiro 466464562Sgshapiro default: 466590792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 466664562Sgshapiro } 466764562Sgshapiro 466864562Sgshapiro /* try to account for quoted strings */ 466964562Sgshapiro done = isascii(*p) && isspace(*p); 467064562Sgshapiro while (*p != '\0' && !done) 467164562Sgshapiro { 467264562Sgshapiro if (*p == '"') 467364562Sgshapiro { 467464562Sgshapiro while (*++p != '"' && *p != '\0') 467564562Sgshapiro continue; 467664562Sgshapiro if (*p != '\0') 467764562Sgshapiro p++; 467864562Sgshapiro } 467964562Sgshapiro else 468064562Sgshapiro p++; 468164562Sgshapiro done = isascii(*p) && isspace(*p); 468264562Sgshapiro } 468364562Sgshapiro 468464562Sgshapiro if (*p != '\0') 468564562Sgshapiro *p++ = '\0'; 468664562Sgshapiro } 468764562Sgshapiro 468864562Sgshapiro if (map->map_app != NULL) 468964562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 469064562Sgshapiro if (map->map_tapp != NULL) 469164562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 469264562Sgshapiro 469364562Sgshapiro if (pmap->ph_field_list != NULL) 469464562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 469564562Sgshapiro 469664562Sgshapiro if (pmap->ph_servers != NULL) 469764562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 469864562Sgshapiro else 469964562Sgshapiro { 470064562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 470190792Sgshapiro return false; 470264562Sgshapiro } 470364562Sgshapiro 470464562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 470590792Sgshapiro return true; 470664562Sgshapiro} 470764562Sgshapiro 470864562Sgshapiro/* 470964562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 471064562Sgshapiro*/ 471164562Sgshapiro 471290792Sgshapirovoid 471390792Sgshapiroph_map_close(map) 471464562Sgshapiro MAP *map; 471564562Sgshapiro{ 471664562Sgshapiro PH_MAP_STRUCT *pmap; 471764562Sgshapiro 471864562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 471990792Sgshapiro if (tTd(38, 9)) 472094334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 472190792Sgshapiro map->map_mname, pmap->ph_fastclose); 472264562Sgshapiro 472390792Sgshapiro 472490792Sgshapiro if (pmap->ph != NULL) 472564562Sgshapiro { 472690792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 472790792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 472890792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 472964562Sgshapiro } 473090792Sgshapiro 473164562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 473264562Sgshapiro} 473364562Sgshapiro 473464562Sgshapirostatic jmp_buf PHTimeout; 473564562Sgshapiro 473664562Sgshapiro/* ARGSUSED */ 473764562Sgshapirostatic void 473890792Sgshapiroph_timeout(unused) 473990792Sgshapiro int unused; 474064562Sgshapiro{ 474177349Sgshapiro /* 474277349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 474377349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 474477349Sgshapiro ** DOING. 474577349Sgshapiro */ 474677349Sgshapiro 474777349Sgshapiro errno = ETIMEDOUT; 474864562Sgshapiro longjmp(PHTimeout, 1); 474964562Sgshapiro} 475064562Sgshapiro 475190792Sgshapirostatic void 4752110560Sgshapiro#if NPH_VERSION >= 10200 4753110560Sgshapiroph_map_send_debug(appdata, text) 4754110560Sgshapiro void *appdata; 4755110560Sgshapiro#else 475690792Sgshapiroph_map_send_debug(text) 4757110560Sgshapiro#endif 475890792Sgshapiro char *text; 475964562Sgshapiro{ 476090792Sgshapiro if (LogLevel > 9) 476190792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 476290792Sgshapiro "ph_map_send_debug: ==> %s", text); 476390792Sgshapiro if (tTd(38, 20)) 476490792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 476590792Sgshapiro} 476664562Sgshapiro 476790792Sgshapirostatic void 4768110560Sgshapiro#if NPH_VERSION >= 10200 4769110560Sgshapiroph_map_recv_debug(appdata, text) 4770110560Sgshapiro void *appdata; 4771110560Sgshapiro#else 477290792Sgshapiroph_map_recv_debug(text) 4773110560Sgshapiro#endif 477490792Sgshapiro char *text; 477590792Sgshapiro{ 477690792Sgshapiro if (LogLevel > 10) 477790792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 477890792Sgshapiro "ph_map_recv_debug: <== %s", text); 477990792Sgshapiro if (tTd(38, 21)) 478090792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 478164562Sgshapiro} 478264562Sgshapiro 478390792Sgshapiro/* 478464562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 478564562Sgshapiro*/ 478664562Sgshapirobool 478764562Sgshapiroph_map_open(map, mode) 478864562Sgshapiro MAP *map; 478964562Sgshapiro int mode; 479064562Sgshapiro{ 479190792Sgshapiro PH_MAP_STRUCT *pmap; 479290792Sgshapiro register SM_EVENT *ev = NULL; 479364562Sgshapiro int save_errno = 0; 479490792Sgshapiro char *hostlist, *host; 479564562Sgshapiro 479664562Sgshapiro if (tTd(38, 2)) 479790792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 479864562Sgshapiro 479964562Sgshapiro mode &= O_ACCMODE; 480064562Sgshapiro if (mode != O_RDONLY) 480164562Sgshapiro { 480264562Sgshapiro /* issue a pseudo-error message */ 480390792Sgshapiro errno = SM_EMAPCANTWRITE; 480490792Sgshapiro return false; 480564562Sgshapiro } 480664562Sgshapiro 480766494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 480866494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 480966494Sgshapiro { 481066494Sgshapiro if (tTd(9, 1)) 481190792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 481290792Sgshapiro map->map_mname); 481366494Sgshapiro 481466494Sgshapiro /* 481590792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 481690792Sgshapiro ** a temporary failure using the bogus map and 481790792Sgshapiro ** map->map_tapp instead of the default permanent error. 481866494Sgshapiro */ 481966494Sgshapiro 482066494Sgshapiro map->map_mflags &= ~MF_DEFER; 482190792Sgshapiro return false; 482266494Sgshapiro } 482366494Sgshapiro 482464562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 482590792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 482664562Sgshapiro 482790792Sgshapiro /* try each host in the list */ 482864562Sgshapiro hostlist = newstr(pmap->ph_servers); 482990792Sgshapiro for (host = strtok(hostlist, " "); 483090792Sgshapiro host != NULL; 483190792Sgshapiro host = strtok(NULL, " ")) 483264562Sgshapiro { 483390792Sgshapiro /* set timeout */ 483464562Sgshapiro if (pmap->ph_timeout != 0) 483564562Sgshapiro { 483664562Sgshapiro if (setjmp(PHTimeout) != 0) 483764562Sgshapiro { 483864562Sgshapiro ev = NULL; 483964562Sgshapiro if (LogLevel > 1) 484064562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 484164562Sgshapiro "timeout connecting to PH server %.100s", 484290792Sgshapiro host); 484364562Sgshapiro errno = ETIMEDOUT; 484464562Sgshapiro goto ph_map_open_abort; 484564562Sgshapiro } 484690792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 484764562Sgshapiro } 484890792Sgshapiro 484990792Sgshapiro /* open connection to server */ 4850110560Sgshapiro if (ph_open(&(pmap->ph), host, 4851110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 4852110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 4853110560Sgshapiro#if NPH_VERSION >= 10200 4854110560Sgshapiro , NULL 4855110560Sgshapiro#endif 4856110560Sgshapiro ) == 0 4857110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 485864562Sgshapiro { 485964562Sgshapiro if (ev != NULL) 486090792Sgshapiro sm_clrevent(ev); 486190792Sgshapiro sm_free(hostlist); /* XXX */ 486290792Sgshapiro return true; 486364562Sgshapiro } 486490792Sgshapiro 486564562Sgshapiro ph_map_open_abort: 486690792Sgshapiro save_errno = errno; 486764562Sgshapiro if (ev != NULL) 486890792Sgshapiro sm_clrevent(ev); 4869110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 487090792Sgshapiro ph_map_close(map); 487190792Sgshapiro errno = save_errno; 487290792Sgshapiro } 487364562Sgshapiro 487466494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 487564562Sgshapiro { 487666494Sgshapiro if (errno == 0) 487764562Sgshapiro errno = EAGAIN; 487866494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 487966494Sgshapiro map->map_mname); 488064562Sgshapiro } 488166494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 488264562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 488366494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 488466494Sgshapiro map->map_mname); 488590792Sgshapiro sm_free(hostlist); /* XXX */ 488690792Sgshapiro return false; 488764562Sgshapiro} 488864562Sgshapiro 488964562Sgshapiro/* 489064562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 489164562Sgshapiro*/ 489264562Sgshapiro 489364562Sgshapirochar * 489464562Sgshapiroph_map_lookup(map, key, args, pstat) 489564562Sgshapiro MAP *map; 489664562Sgshapiro char *key; 489764562Sgshapiro char **args; 489864562Sgshapiro int *pstat; 489964562Sgshapiro{ 490090792Sgshapiro int i, save_errno = 0; 490190792Sgshapiro register SM_EVENT *ev = NULL; 490264562Sgshapiro PH_MAP_STRUCT *pmap; 490390792Sgshapiro char *value = NULL; 490464562Sgshapiro 490564562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 490664562Sgshapiro 490764562Sgshapiro *pstat = EX_OK; 490864562Sgshapiro 490990792Sgshapiro /* set timeout */ 491064562Sgshapiro if (pmap->ph_timeout != 0) 491164562Sgshapiro { 491264562Sgshapiro if (setjmp(PHTimeout) != 0) 491364562Sgshapiro { 491464562Sgshapiro ev = NULL; 491564562Sgshapiro if (LogLevel > 1) 491664562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 491764562Sgshapiro "timeout during PH lookup of %.100s", 491864562Sgshapiro key); 491964562Sgshapiro errno = ETIMEDOUT; 492064562Sgshapiro *pstat = EX_TEMPFAIL; 492164562Sgshapiro goto ph_map_lookup_abort; 492264562Sgshapiro } 492390792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 492464562Sgshapiro } 492564562Sgshapiro 492690792Sgshapiro /* perform lookup */ 492790792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 492890792Sgshapiro if (i == -1) 492990792Sgshapiro *pstat = EX_TEMPFAIL; 4930110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 493190792Sgshapiro *pstat = EX_UNAVAILABLE; 493264562Sgshapiro 493364562Sgshapiro ph_map_lookup_abort: 493464562Sgshapiro if (ev != NULL) 493590792Sgshapiro sm_clrevent(ev); 493664562Sgshapiro 493764562Sgshapiro /* 493890792Sgshapiro ** Close the connection if the timer popped 493964562Sgshapiro ** or we got a temporary PH error 494064562Sgshapiro */ 494164562Sgshapiro 494264562Sgshapiro if (*pstat == EX_TEMPFAIL) 494390792Sgshapiro { 494490792Sgshapiro save_errno = errno; 4945110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 494690792Sgshapiro ph_map_close(map); 494790792Sgshapiro errno = save_errno; 494890792Sgshapiro } 494964562Sgshapiro 495064562Sgshapiro if (*pstat == EX_OK) 495164562Sgshapiro { 495264562Sgshapiro if (tTd(38,20)) 495390792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 495464562Sgshapiro 495564562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 495690792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 495764562Sgshapiro else 495890792Sgshapiro return map_rewrite(map, value, strlen(value), args); 495964562Sgshapiro } 496064562Sgshapiro 496164562Sgshapiro return NULL; 496264562Sgshapiro} 496364562Sgshapiro#endif /* PH_MAP */ 496490792Sgshapiro/* 496542575Speter** syslog map 496638032Speter*/ 496738032Speter 496838032Speter#define map_prio map_lockfd /* overload field */ 496938032Speter 497038032Speter/* 497142575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 497238032Speter*/ 497338032Speter 497438032Speterbool 497538032Spetersyslog_map_parseargs(map, args) 497638032Speter MAP *map; 497738032Speter char *args; 497838032Speter{ 497938032Speter char *p = args; 498038032Speter char *priority = NULL; 498138032Speter 498264562Sgshapiro /* there is no check whether there is really an argument */ 498364562Sgshapiro while (*p != '\0') 498438032Speter { 498538032Speter while (isascii(*p) && isspace(*p)) 498638032Speter p++; 498738032Speter if (*p != '-') 498838032Speter break; 498964562Sgshapiro ++p; 499064562Sgshapiro if (*p == 'D') 499164562Sgshapiro { 499264562Sgshapiro map->map_mflags |= MF_DEFER; 499364562Sgshapiro ++p; 499464562Sgshapiro } 499564562Sgshapiro else if (*p == 'S') 499664562Sgshapiro { 499764562Sgshapiro map->map_spacesub = *++p; 499864562Sgshapiro if (*p != '\0') 499964562Sgshapiro p++; 500064562Sgshapiro } 500164562Sgshapiro else if (*p == 'L') 500264562Sgshapiro { 500364562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 500464562Sgshapiro continue; 500564562Sgshapiro if (*p == '\0') 500664562Sgshapiro break; 500764562Sgshapiro priority = p; 500864562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 500964562Sgshapiro p++; 501064562Sgshapiro if (*p != '\0') 501164562Sgshapiro *p++ = '\0'; 501264562Sgshapiro } 501364562Sgshapiro else 501464562Sgshapiro { 501564562Sgshapiro syserr("Illegal option %c map syslog", *p); 501664562Sgshapiro ++p; 501764562Sgshapiro } 501838032Speter } 501938032Speter 502038032Speter if (priority == NULL) 502138032Speter map->map_prio = LOG_INFO; 502238032Speter else 502338032Speter { 502490792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 502538032Speter priority += 4; 502638032Speter 502738032Speter#ifdef LOG_EMERG 502890792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 502938032Speter map->map_prio = LOG_EMERG; 503038032Speter else 503164562Sgshapiro#endif /* LOG_EMERG */ 503238032Speter#ifdef LOG_ALERT 503390792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 503438032Speter map->map_prio = LOG_ALERT; 503538032Speter else 503664562Sgshapiro#endif /* LOG_ALERT */ 503738032Speter#ifdef LOG_CRIT 503890792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 503938032Speter map->map_prio = LOG_CRIT; 504038032Speter else 504164562Sgshapiro#endif /* LOG_CRIT */ 504238032Speter#ifdef LOG_ERR 504390792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 504438032Speter map->map_prio = LOG_ERR; 504538032Speter else 504664562Sgshapiro#endif /* LOG_ERR */ 504738032Speter#ifdef LOG_WARNING 504890792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 504938032Speter map->map_prio = LOG_WARNING; 505038032Speter else 505164562Sgshapiro#endif /* LOG_WARNING */ 505238032Speter#ifdef LOG_NOTICE 505390792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 505438032Speter map->map_prio = LOG_NOTICE; 505538032Speter else 505664562Sgshapiro#endif /* LOG_NOTICE */ 505738032Speter#ifdef LOG_INFO 505890792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 505938032Speter map->map_prio = LOG_INFO; 506038032Speter else 506164562Sgshapiro#endif /* LOG_INFO */ 506238032Speter#ifdef LOG_DEBUG 506390792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 506438032Speter map->map_prio = LOG_DEBUG; 506538032Speter else 506664562Sgshapiro#endif /* LOG_DEBUG */ 506738032Speter { 506890792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 506938032Speter priority); 507090792Sgshapiro return false; 507138032Speter } 507238032Speter } 507390792Sgshapiro return true; 507438032Speter} 507538032Speter 507638032Speter/* 507742575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 507838032Speter*/ 507938032Speter 508038032Speterchar * 508138032Spetersyslog_map_lookup(map, string, args, statp) 508238032Speter MAP *map; 508338032Speter char *string; 508438032Speter char **args; 508538032Speter int *statp; 508638032Speter{ 508738032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 508838032Speter 508938032Speter if (ptr != NULL) 509038032Speter { 509138032Speter if (tTd(38, 20)) 509290792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 509364562Sgshapiro map->map_mname, map->map_prio, ptr); 509438032Speter 509538032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 509638032Speter } 509738032Speter 509838032Speter *statp = EX_OK; 509938032Speter return ""; 510038032Speter} 510138032Speter 510290792Sgshapiro/* 510338032Speter** HESIOD Modules 510438032Speter*/ 510538032Speter 510690792Sgshapiro#if HESIOD 510738032Speter 510838032Speterbool 510938032Speterhes_map_open(map, mode) 511038032Speter MAP *map; 511138032Speter int mode; 511238032Speter{ 511338032Speter if (tTd(38, 2)) 511490792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 511538032Speter map->map_mname, map->map_file, mode); 511638032Speter 511738032Speter if (mode != O_RDONLY) 511838032Speter { 511938032Speter /* issue a pseudo-error message */ 512090792Sgshapiro errno = SM_EMAPCANTWRITE; 512190792Sgshapiro return false; 512238032Speter } 512338032Speter 512464562Sgshapiro# ifdef HESIOD_INIT 512538032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 512690792Sgshapiro return true; 512738032Speter 512838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 512994334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 513090792Sgshapiro sm_errstring(errno)); 513190792Sgshapiro return false; 513264562Sgshapiro# else /* HESIOD_INIT */ 513338032Speter if (hes_error() == HES_ER_UNINIT) 513438032Speter hes_init(); 513538032Speter switch (hes_error()) 513638032Speter { 513738032Speter case HES_ER_OK: 513838032Speter case HES_ER_NOTFOUND: 513990792Sgshapiro return true; 514038032Speter } 514138032Speter 514238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 514394334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 514438032Speter 514590792Sgshapiro return false; 514664562Sgshapiro# endif /* HESIOD_INIT */ 514738032Speter} 514838032Speter 514938032Speterchar * 515038032Speterhes_map_lookup(map, name, av, statp) 515138032Speter MAP *map; 515238032Speter char *name; 515338032Speter char **av; 515438032Speter int *statp; 515538032Speter{ 515638032Speter char **hp; 515738032Speter 515838032Speter if (tTd(38, 20)) 515990792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 516038032Speter 516138032Speter if (name[0] == '\\') 516238032Speter { 516338032Speter char *np; 516438032Speter int nl; 516577349Sgshapiro int save_errno; 516638032Speter char nbuf[MAXNAME]; 516738032Speter 516838032Speter nl = strlen(name); 516938032Speter if (nl < sizeof nbuf - 1) 517038032Speter np = nbuf; 517138032Speter else 517238032Speter np = xalloc(strlen(name) + 2); 517338032Speter np[0] = '\\'; 517490792Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof nbuf) - 1); 517564562Sgshapiro# ifdef HESIOD_INIT 517638032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 517764562Sgshapiro# else /* HESIOD_INIT */ 517838032Speter hp = hes_resolve(np, map->map_file); 517964562Sgshapiro# endif /* HESIOD_INIT */ 518077349Sgshapiro save_errno = errno; 518138032Speter if (np != nbuf) 518290792Sgshapiro sm_free(np); /* XXX */ 518377349Sgshapiro errno = save_errno; 518438032Speter } 518538032Speter else 518638032Speter { 518764562Sgshapiro# ifdef HESIOD_INIT 518838032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 518964562Sgshapiro# else /* HESIOD_INIT */ 519038032Speter hp = hes_resolve(name, map->map_file); 519164562Sgshapiro# endif /* HESIOD_INIT */ 519238032Speter } 519364562Sgshapiro# ifdef HESIOD_INIT 519477349Sgshapiro if (hp == NULL || *hp == NULL) 519538032Speter { 519638032Speter switch (errno) 519738032Speter { 519838032Speter case ENOENT: 519938032Speter *statp = EX_NOTFOUND; 520038032Speter break; 520138032Speter case ECONNREFUSED: 520238032Speter *statp = EX_TEMPFAIL; 520338032Speter break; 520490792Sgshapiro case EMSGSIZE: 520538032Speter case ENOMEM: 520638032Speter default: 520738032Speter *statp = EX_UNAVAILABLE; 520838032Speter break; 520938032Speter } 521082017Sgshapiro if (hp != NULL) 521182017Sgshapiro hesiod_free_list(HesiodContext, hp); 521238032Speter return NULL; 521338032Speter } 521464562Sgshapiro# else /* HESIOD_INIT */ 521538032Speter if (hp == NULL || hp[0] == NULL) 521638032Speter { 521738032Speter switch (hes_error()) 521838032Speter { 521938032Speter case HES_ER_OK: 522038032Speter *statp = EX_OK; 522138032Speter break; 522238032Speter 522338032Speter case HES_ER_NOTFOUND: 522438032Speter *statp = EX_NOTFOUND; 522538032Speter break; 522638032Speter 522738032Speter case HES_ER_CONFIG: 522838032Speter *statp = EX_UNAVAILABLE; 522938032Speter break; 523038032Speter 523138032Speter case HES_ER_NET: 523238032Speter *statp = EX_TEMPFAIL; 523338032Speter break; 523438032Speter } 523538032Speter return NULL; 523638032Speter } 523764562Sgshapiro# endif /* HESIOD_INIT */ 523838032Speter 523938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 524038032Speter return map_rewrite(map, name, strlen(name), NULL); 524138032Speter else 524238032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 524338032Speter} 524438032Speter 524590792Sgshapiro/* 524690792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 524790792Sgshapiro*/ 524890792Sgshapiro 524990792Sgshapirovoid 525090792Sgshapirohes_map_close(map) 525190792Sgshapiro MAP *map; 525290792Sgshapiro{ 525390792Sgshapiro if (tTd(38, 20)) 525490792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 525590792Sgshapiro 525690792Sgshapiro# ifdef HESIOD_INIT 525790792Sgshapiro /* Free the hesiod context */ 525890792Sgshapiro if (HesiodContext != NULL) 525990792Sgshapiro { 526090792Sgshapiro hesiod_end(HesiodContext); 526190792Sgshapiro HesiodContext = NULL; 526290792Sgshapiro } 526390792Sgshapiro# endif /* HESIOD_INIT */ 526490792Sgshapiro} 526590792Sgshapiro 526664562Sgshapiro#endif /* HESIOD */ 526790792Sgshapiro/* 526838032Speter** NeXT NETINFO Modules 526938032Speter*/ 527038032Speter 527138032Speter#if NETINFO 527238032Speter 527338032Speter# define NETINFO_DEFAULT_DIR "/aliases" 527438032Speter# define NETINFO_DEFAULT_PROPERTY "members" 527538032Speter 527638032Speter/* 527738032Speter** NI_MAP_OPEN -- open NetInfo Aliases 527838032Speter*/ 527938032Speter 528038032Speterbool 528138032Speterni_map_open(map, mode) 528238032Speter MAP *map; 528338032Speter int mode; 528438032Speter{ 528538032Speter if (tTd(38, 2)) 528690792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 528738032Speter map->map_mname, map->map_file, mode); 528838032Speter mode &= O_ACCMODE; 528938032Speter 529038032Speter if (*map->map_file == '\0') 529138032Speter map->map_file = NETINFO_DEFAULT_DIR; 529238032Speter 529338032Speter if (map->map_valcolnm == NULL) 529438032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 529538032Speter 529690792Sgshapiro if (map->map_coldelim == '\0') 529790792Sgshapiro { 529890792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 529990792Sgshapiro map->map_coldelim = ','; 530090792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 530190792Sgshapiro map->map_coldelim = ' '; 530290792Sgshapiro } 530390792Sgshapiro return true; 530438032Speter} 530538032Speter 530638032Speter 530738032Speter/* 530838032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 530938032Speter*/ 531038032Speter 531138032Speterchar * 531238032Speterni_map_lookup(map, name, av, statp) 531338032Speter MAP *map; 531438032Speter char *name; 531538032Speter char **av; 531638032Speter int *statp; 531738032Speter{ 531838032Speter char *res; 531938032Speter char *propval; 532038032Speter 532138032Speter if (tTd(38, 20)) 532290792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 532338032Speter 532438032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 532538032Speter map->map_valcolnm, map->map_coldelim); 532638032Speter 532738032Speter if (propval == NULL) 532838032Speter return NULL; 532938032Speter 533090792Sgshapiro SM_TRY 533190792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 533290792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 533390792Sgshapiro else 533490792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 533590792Sgshapiro SM_FINALLY 533690792Sgshapiro sm_free(propval); 533790792Sgshapiro SM_END_TRY 533838032Speter return res; 533938032Speter} 534038032Speter 534138032Speter 534264562Sgshapirostatic bool 534338032Speterni_getcanonname(name, hbsize, statp) 534438032Speter char *name; 534538032Speter int hbsize; 534638032Speter int *statp; 534738032Speter{ 534838032Speter char *vptr; 534938032Speter char *ptr; 535038032Speter char nbuf[MAXNAME + 1]; 535138032Speter 535238032Speter if (tTd(38, 20)) 535390792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 535438032Speter 535590792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 535638032Speter { 535738032Speter *statp = EX_UNAVAILABLE; 535890792Sgshapiro return false; 535938032Speter } 536073188Sgshapiro (void) shorten_hostname(nbuf); 536138032Speter 536238032Speter /* we only accept single token search key */ 536338032Speter if (strchr(nbuf, '.')) 536438032Speter { 536538032Speter *statp = EX_NOHOST; 536690792Sgshapiro return false; 536738032Speter } 536838032Speter 536938032Speter /* Do the search */ 537038032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 537138032Speter 537238032Speter if (vptr == NULL) 537338032Speter { 537438032Speter *statp = EX_NOHOST; 537590792Sgshapiro return false; 537638032Speter } 537738032Speter 537838032Speter /* Only want the first machine name */ 537938032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 538038032Speter *ptr = '\0'; 538138032Speter 538290792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 538338032Speter { 538477349Sgshapiro sm_free(vptr); 538590792Sgshapiro *statp = EX_UNAVAILABLE; 538690792Sgshapiro return true; 538738032Speter } 538877349Sgshapiro sm_free(vptr); 538990792Sgshapiro *statp = EX_OK; 539090792Sgshapiro return false; 539138032Speter} 539290792Sgshapiro#endif /* NETINFO */ 539338032Speter/* 539438032Speter** TEXT (unindexed text file) Modules 539538032Speter** 539638032Speter** This code donated by Sun Microsystems. 539738032Speter*/ 539838032Speter 539938032Speter#define map_sff map_lockfd /* overload field */ 540038032Speter 540138032Speter 540238032Speter/* 540338032Speter** TEXT_MAP_OPEN -- open text table 540438032Speter*/ 540538032Speter 540638032Speterbool 540738032Spetertext_map_open(map, mode) 540838032Speter MAP *map; 540938032Speter int mode; 541038032Speter{ 541164562Sgshapiro long sff; 541238032Speter int i; 541338032Speter 541438032Speter if (tTd(38, 2)) 541590792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 541638032Speter map->map_mname, map->map_file, mode); 541738032Speter 541838032Speter mode &= O_ACCMODE; 541938032Speter if (mode != O_RDONLY) 542038032Speter { 542138032Speter errno = EPERM; 542290792Sgshapiro return false; 542338032Speter } 542438032Speter 542538032Speter if (*map->map_file == '\0') 542638032Speter { 542738032Speter syserr("text map \"%s\": file name required", 542838032Speter map->map_mname); 542990792Sgshapiro return false; 543038032Speter } 543138032Speter 543238032Speter if (map->map_file[0] != '/') 543338032Speter { 543438032Speter syserr("text map \"%s\": file name must be fully qualified", 543538032Speter map->map_mname); 543690792Sgshapiro return false; 543738032Speter } 543838032Speter 543938032Speter sff = SFF_ROOTOK|SFF_REGONLY; 544064562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 544138032Speter sff |= SFF_NOWLINK; 544264562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 544338032Speter sff |= SFF_SAFEDIRPATH; 544438032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 544538032Speter sff, S_IRUSR, NULL)) != 0) 544638032Speter { 544764562Sgshapiro int save_errno = errno; 544864562Sgshapiro 544938032Speter /* cannot open this map */ 545038032Speter if (tTd(38, 2)) 545190792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 545264562Sgshapiro errno = save_errno; 545338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 545438032Speter syserr("text map \"%s\": unsafe map file %s", 545538032Speter map->map_mname, map->map_file); 545690792Sgshapiro return false; 545738032Speter } 545838032Speter 545938032Speter if (map->map_keycolnm == NULL) 546038032Speter map->map_keycolno = 0; 546138032Speter else 546238032Speter { 546338032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 546438032Speter { 546538032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 546638032Speter map->map_mname, map->map_file, 546738032Speter map->map_keycolnm); 546890792Sgshapiro return false; 546938032Speter } 547038032Speter map->map_keycolno = atoi(map->map_keycolnm); 547138032Speter } 547238032Speter 547338032Speter if (map->map_valcolnm == NULL) 547438032Speter map->map_valcolno = 0; 547538032Speter else 547638032Speter { 547738032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 547838032Speter { 547938032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 548038032Speter map->map_mname, map->map_file, 548138032Speter map->map_valcolnm); 548290792Sgshapiro return false; 548338032Speter } 548438032Speter map->map_valcolno = atoi(map->map_valcolnm); 548538032Speter } 548638032Speter 548738032Speter if (tTd(38, 2)) 548838032Speter { 548990792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 549038032Speter map->map_mname, map->map_file); 549138032Speter if (map->map_coldelim == '\0') 549290792Sgshapiro sm_dprintf("(white space)\n"); 549338032Speter else 549490792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 549538032Speter } 549638032Speter 549738032Speter map->map_sff = sff; 549890792Sgshapiro return true; 549938032Speter} 550038032Speter 550138032Speter 550238032Speter/* 550338032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 550438032Speter*/ 550538032Speter 550638032Speterchar * 550738032Spetertext_map_lookup(map, name, av, statp) 550838032Speter MAP *map; 550938032Speter char *name; 551038032Speter char **av; 551138032Speter int *statp; 551238032Speter{ 551338032Speter char *vp; 551438032Speter auto int vsize; 551538032Speter int buflen; 551690792Sgshapiro SM_FILE_T *f; 551738032Speter char delim; 551838032Speter int key_idx; 551938032Speter bool found_it; 552064562Sgshapiro long sff = map->map_sff; 552138032Speter char search_key[MAXNAME + 1]; 552238032Speter char linebuf[MAXLINE]; 552338032Speter char buf[MAXNAME + 1]; 552438032Speter 552590792Sgshapiro found_it = false; 552638032Speter if (tTd(38, 20)) 552790792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 552838032Speter 552938032Speter buflen = strlen(name); 553038032Speter if (buflen > sizeof search_key - 1) 553190792Sgshapiro buflen = sizeof search_key - 1; /* XXX just cut if off? */ 553264562Sgshapiro memmove(search_key, name, buflen); 553338032Speter search_key[buflen] = '\0'; 553438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 553538032Speter makelower(search_key); 553638032Speter 553738032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 553838032Speter if (f == NULL) 553938032Speter { 554038032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 554138032Speter *statp = EX_UNAVAILABLE; 554238032Speter return NULL; 554338032Speter } 554438032Speter key_idx = map->map_keycolno; 554538032Speter delim = map->map_coldelim; 554698121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 554798121Sgshapiro linebuf, sizeof linebuf) != NULL) 554838032Speter { 554938032Speter char *p; 555038032Speter 555138032Speter /* skip comment line */ 555238032Speter if (linebuf[0] == '#') 555338032Speter continue; 555438032Speter p = strchr(linebuf, '\n'); 555538032Speter if (p != NULL) 555638032Speter *p = '\0'; 555738032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 555890792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 555938032Speter { 556090792Sgshapiro found_it = true; 556138032Speter break; 556238032Speter } 556338032Speter } 556490792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 556538032Speter if (!found_it) 556638032Speter { 556738032Speter *statp = EX_NOTFOUND; 556838032Speter return NULL; 556938032Speter } 557038032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 557142575Speter if (vp == NULL) 557242575Speter { 557342575Speter *statp = EX_NOTFOUND; 557442575Speter return NULL; 557542575Speter } 557638032Speter vsize = strlen(vp); 557738032Speter *statp = EX_OK; 557838032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 557938032Speter return map_rewrite(map, name, strlen(name), NULL); 558038032Speter else 558138032Speter return map_rewrite(map, vp, vsize, av); 558238032Speter} 558338032Speter 558438032Speter/* 558538032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 558638032Speter*/ 558738032Speter 558864562Sgshapirostatic bool 558938032Spetertext_getcanonname(name, hbsize, statp) 559038032Speter char *name; 559138032Speter int hbsize; 559238032Speter int *statp; 559338032Speter{ 559438032Speter bool found; 559573188Sgshapiro char *dot; 559690792Sgshapiro SM_FILE_T *f; 559738032Speter char linebuf[MAXLINE]; 559838032Speter char cbuf[MAXNAME + 1]; 559938032Speter char nbuf[MAXNAME + 1]; 560038032Speter 560138032Speter if (tTd(38, 20)) 560290792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 560338032Speter 560490792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 560538032Speter { 560638032Speter *statp = EX_UNAVAILABLE; 560790792Sgshapiro return false; 560838032Speter } 560973188Sgshapiro dot = shorten_hostname(nbuf); 561038032Speter 561190792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 561290792Sgshapiro NULL); 561338032Speter if (f == NULL) 561438032Speter { 561538032Speter *statp = EX_UNAVAILABLE; 561690792Sgshapiro return false; 561738032Speter } 561890792Sgshapiro found = false; 561990792Sgshapiro while (!found && 562098121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 562198121Sgshapiro linebuf, sizeof linebuf) != NULL) 562238032Speter { 562338032Speter char *p = strpbrk(linebuf, "#\n"); 562438032Speter 562538032Speter if (p != NULL) 562638032Speter *p = '\0'; 562738032Speter if (linebuf[0] != '\0') 562873188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 562973188Sgshapiro cbuf, sizeof cbuf); 563038032Speter } 563190792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 563238032Speter if (!found) 563338032Speter { 563438032Speter *statp = EX_NOHOST; 563590792Sgshapiro return false; 563638032Speter } 563738032Speter 563890792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 563938032Speter { 564090792Sgshapiro *statp = EX_UNAVAILABLE; 564190792Sgshapiro return false; 564238032Speter } 564390792Sgshapiro *statp = EX_OK; 564490792Sgshapiro return true; 564538032Speter} 564690792Sgshapiro/* 564738032Speter** STAB (Symbol Table) Modules 564838032Speter*/ 564938032Speter 565038032Speter 565138032Speter/* 565238032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 565338032Speter*/ 565438032Speter 565538032Speter/* ARGSUSED2 */ 565638032Speterchar * 565738032Speterstab_map_lookup(map, name, av, pstat) 565838032Speter register MAP *map; 565938032Speter char *name; 566038032Speter char **av; 566138032Speter int *pstat; 566238032Speter{ 566338032Speter register STAB *s; 566438032Speter 566538032Speter if (tTd(38, 20)) 566690792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 566738032Speter map->map_mname, name); 566838032Speter 566938032Speter s = stab(name, ST_ALIAS, ST_FIND); 5670147078Sgshapiro if (s == NULL) 5671147078Sgshapiro return NULL; 5672147078Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 5673147078Sgshapiro return map_rewrite(map, name, strlen(name), NULL); 5674147078Sgshapiro else 5675147078Sgshapiro return map_rewrite(map, s->s_alias, strlen(s->s_alias), av); 567638032Speter} 567738032Speter 567838032Speter/* 567938032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 568038032Speter*/ 568138032Speter 568238032Spetervoid 568338032Speterstab_map_store(map, lhs, rhs) 568438032Speter register MAP *map; 568538032Speter char *lhs; 568638032Speter char *rhs; 568738032Speter{ 568838032Speter register STAB *s; 568938032Speter 569038032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 569138032Speter s->s_alias = newstr(rhs); 569238032Speter} 569338032Speter 569438032Speter 569538032Speter/* 569638032Speter** STAB_MAP_OPEN -- initialize (reads data file) 569738032Speter** 569838032Speter** This is a wierd case -- it is only intended as a fallback for 569938032Speter** aliases. For this reason, opens for write (only during a 570038032Speter** "newaliases") always fails, and opens for read open the 570138032Speter** actual underlying text file instead of the database. 570238032Speter*/ 570338032Speter 570438032Speterbool 570538032Speterstab_map_open(map, mode) 570638032Speter register MAP *map; 570738032Speter int mode; 570838032Speter{ 570990792Sgshapiro SM_FILE_T *af; 571064562Sgshapiro long sff; 571138032Speter struct stat st; 571238032Speter 571338032Speter if (tTd(38, 2)) 571490792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 571538032Speter map->map_mname, map->map_file, mode); 571638032Speter 571738032Speter mode &= O_ACCMODE; 571838032Speter if (mode != O_RDONLY) 571938032Speter { 572038032Speter errno = EPERM; 572190792Sgshapiro return false; 572238032Speter } 572338032Speter 572438032Speter sff = SFF_ROOTOK|SFF_REGONLY; 572564562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 572638032Speter sff |= SFF_NOWLINK; 572764562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 572838032Speter sff |= SFF_SAFEDIRPATH; 572938032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 573038032Speter if (af == NULL) 573190792Sgshapiro return false; 573290792Sgshapiro readaliases(map, af, false, false); 573338032Speter 573490792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 573538032Speter map->map_mtime = st.st_mtime; 573690792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 573738032Speter 573890792Sgshapiro return true; 573938032Speter} 574090792Sgshapiro/* 574138032Speter** Implicit Modules 574238032Speter** 574338032Speter** Tries several types. For back compatibility of aliases. 574438032Speter*/ 574538032Speter 574638032Speter 574738032Speter/* 574838032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 574938032Speter*/ 575038032Speter 575138032Speterchar * 575238032Speterimpl_map_lookup(map, name, av, pstat) 575338032Speter MAP *map; 575438032Speter char *name; 575538032Speter char **av; 575638032Speter int *pstat; 575738032Speter{ 575838032Speter if (tTd(38, 20)) 575990792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 576038032Speter map->map_mname, name); 576138032Speter 576290792Sgshapiro#if NEWDB 576338032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 576438032Speter return db_map_lookup(map, name, av, pstat); 576564562Sgshapiro#endif /* NEWDB */ 576690792Sgshapiro#if NDBM 576738032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 576838032Speter return ndbm_map_lookup(map, name, av, pstat); 576964562Sgshapiro#endif /* NDBM */ 577038032Speter return stab_map_lookup(map, name, av, pstat); 577138032Speter} 577238032Speter 577338032Speter/* 577438032Speter** IMPL_MAP_STORE -- store in open databases 577538032Speter*/ 577638032Speter 577738032Spetervoid 577838032Speterimpl_map_store(map, lhs, rhs) 577938032Speter MAP *map; 578038032Speter char *lhs; 578138032Speter char *rhs; 578238032Speter{ 578338032Speter if (tTd(38, 12)) 578490792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 578538032Speter map->map_mname, lhs, rhs); 578690792Sgshapiro#if NEWDB 578738032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 578838032Speter db_map_store(map, lhs, rhs); 578964562Sgshapiro#endif /* NEWDB */ 579090792Sgshapiro#if NDBM 579138032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 579238032Speter ndbm_map_store(map, lhs, rhs); 579364562Sgshapiro#endif /* NDBM */ 579438032Speter stab_map_store(map, lhs, rhs); 579538032Speter} 579638032Speter 579738032Speter/* 579838032Speter** IMPL_MAP_OPEN -- implicit database open 579938032Speter*/ 580038032Speter 580138032Speterbool 580238032Speterimpl_map_open(map, mode) 580338032Speter MAP *map; 580438032Speter int mode; 580538032Speter{ 580638032Speter if (tTd(38, 2)) 580790792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 580838032Speter map->map_mname, map->map_file, mode); 580938032Speter 581038032Speter mode &= O_ACCMODE; 581190792Sgshapiro#if NEWDB 581238032Speter map->map_mflags |= MF_IMPL_HASH; 581338032Speter if (hash_map_open(map, mode)) 581438032Speter { 581538032Speter# ifdef NDBM_YP_COMPAT 581638032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 581764562Sgshapiro# endif /* NDBM_YP_COMPAT */ 581890792Sgshapiro return true; 581938032Speter } 582038032Speter else 582138032Speter map->map_mflags &= ~MF_IMPL_HASH; 582264562Sgshapiro#endif /* NEWDB */ 582390792Sgshapiro#if NDBM 582438032Speter map->map_mflags |= MF_IMPL_NDBM; 582538032Speter if (ndbm_map_open(map, mode)) 582638032Speter { 582790792Sgshapiro return true; 582838032Speter } 582938032Speter else 583038032Speter map->map_mflags &= ~MF_IMPL_NDBM; 583164562Sgshapiro#endif /* NDBM */ 583238032Speter 583338032Speter#if defined(NEWDB) || defined(NDBM) 583438032Speter if (Verbose) 583538032Speter message("WARNING: cannot open alias database %s%s", 583638032Speter map->map_file, 583738032Speter mode == O_RDONLY ? "; reading text version" : ""); 583864562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 583938032Speter if (mode != O_RDONLY) 584038032Speter usrerr("Cannot rebuild aliases: no database format defined"); 584164562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 584238032Speter 584338032Speter if (mode == O_RDONLY) 584438032Speter return stab_map_open(map, mode); 584538032Speter else 584690792Sgshapiro return false; 584738032Speter} 584838032Speter 584938032Speter 585038032Speter/* 585138032Speter** IMPL_MAP_CLOSE -- close any open database(s) 585238032Speter*/ 585338032Speter 585438032Spetervoid 585538032Speterimpl_map_close(map) 585638032Speter MAP *map; 585738032Speter{ 585838032Speter if (tTd(38, 9)) 585990792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 586038032Speter map->map_mname, map->map_file, map->map_mflags); 586190792Sgshapiro#if NEWDB 586238032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 586338032Speter { 586438032Speter db_map_close(map); 586538032Speter map->map_mflags &= ~MF_IMPL_HASH; 586638032Speter } 586764562Sgshapiro#endif /* NEWDB */ 586838032Speter 586990792Sgshapiro#if NDBM 587038032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 587138032Speter { 587238032Speter ndbm_map_close(map); 587338032Speter map->map_mflags &= ~MF_IMPL_NDBM; 587438032Speter } 587564562Sgshapiro#endif /* NDBM */ 587638032Speter} 587790792Sgshapiro/* 587838032Speter** User map class. 587938032Speter** 588038032Speter** Provides access to the system password file. 588138032Speter*/ 588238032Speter 588338032Speter/* 588438032Speter** USER_MAP_OPEN -- open user map 588538032Speter** 588638032Speter** Really just binds field names to field numbers. 588738032Speter*/ 588838032Speter 588938032Speterbool 589038032Speteruser_map_open(map, mode) 589138032Speter MAP *map; 589238032Speter int mode; 589338032Speter{ 589438032Speter if (tTd(38, 2)) 589590792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 589638032Speter map->map_mname, mode); 589738032Speter 589838032Speter mode &= O_ACCMODE; 589938032Speter if (mode != O_RDONLY) 590038032Speter { 590138032Speter /* issue a pseudo-error message */ 590290792Sgshapiro errno = SM_EMAPCANTWRITE; 590390792Sgshapiro return false; 590438032Speter } 590538032Speter if (map->map_valcolnm == NULL) 590664562Sgshapiro /* EMPTY */ 590738032Speter /* nothing */ ; 590890792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 590938032Speter map->map_valcolno = 1; 591090792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 591138032Speter map->map_valcolno = 2; 591290792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 591338032Speter map->map_valcolno = 3; 591490792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 591538032Speter map->map_valcolno = 4; 591690792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 591738032Speter map->map_valcolno = 5; 591890792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 591938032Speter map->map_valcolno = 6; 592090792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 592138032Speter map->map_valcolno = 7; 592238032Speter else 592338032Speter { 592438032Speter syserr("User map %s: unknown column name %s", 592538032Speter map->map_mname, map->map_valcolnm); 592690792Sgshapiro return false; 592738032Speter } 592890792Sgshapiro return true; 592938032Speter} 593038032Speter 593138032Speter 593238032Speter/* 593338032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 593438032Speter*/ 593538032Speter 593638032Speter/* ARGSUSED3 */ 593738032Speterchar * 593838032Speteruser_map_lookup(map, key, av, statp) 593938032Speter MAP *map; 594038032Speter char *key; 594138032Speter char **av; 594238032Speter int *statp; 594338032Speter{ 594438032Speter auto bool fuzzy; 594590792Sgshapiro SM_MBDB_T user; 594638032Speter 594738032Speter if (tTd(38, 20)) 594890792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 594938032Speter map->map_mname, key); 595038032Speter 595190792Sgshapiro *statp = finduser(key, &fuzzy, &user); 595290792Sgshapiro if (*statp != EX_OK) 595338032Speter return NULL; 595438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 595538032Speter return map_rewrite(map, key, strlen(key), NULL); 595638032Speter else 595738032Speter { 595838032Speter char *rwval = NULL; 595938032Speter char buf[30]; 596038032Speter 596138032Speter switch (map->map_valcolno) 596238032Speter { 596338032Speter case 0: 596438032Speter case 1: 596590792Sgshapiro rwval = user.mbdb_name; 596638032Speter break; 596738032Speter 596838032Speter case 2: 596990792Sgshapiro rwval = "x"; /* passwd no longer supported */ 597038032Speter break; 597138032Speter 597238032Speter case 3: 597390792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%d", 597490792Sgshapiro (int) user.mbdb_uid); 597538032Speter rwval = buf; 597638032Speter break; 597738032Speter 597838032Speter case 4: 597990792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%d", 598090792Sgshapiro (int) user.mbdb_gid); 598138032Speter rwval = buf; 598238032Speter break; 598338032Speter 598438032Speter case 5: 598590792Sgshapiro rwval = user.mbdb_fullname; 598638032Speter break; 598738032Speter 598838032Speter case 6: 598990792Sgshapiro rwval = user.mbdb_homedir; 599038032Speter break; 599138032Speter 599238032Speter case 7: 599390792Sgshapiro rwval = user.mbdb_shell; 599438032Speter break; 599538032Speter } 599638032Speter return map_rewrite(map, rwval, strlen(rwval), av); 599738032Speter } 599838032Speter} 599990792Sgshapiro/* 600038032Speter** Program map type. 600138032Speter** 600238032Speter** This provides access to arbitrary programs. It should be used 600338032Speter** only very sparingly, since there is no way to bound the cost 600438032Speter** of invoking an arbitrary program. 600538032Speter*/ 600638032Speter 600738032Speterchar * 600838032Speterprog_map_lookup(map, name, av, statp) 600938032Speter MAP *map; 601038032Speter char *name; 601138032Speter char **av; 601238032Speter int *statp; 601338032Speter{ 601438032Speter int i; 601564562Sgshapiro int save_errno; 601638032Speter int fd; 601764562Sgshapiro int status; 601838032Speter auto pid_t pid; 601964562Sgshapiro register char *p; 602038032Speter char *rval; 602138032Speter char *argv[MAXPV + 1]; 602238032Speter char buf[MAXLINE]; 602338032Speter 602438032Speter if (tTd(38, 20)) 602590792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 602638032Speter map->map_mname, name, map->map_file); 602738032Speter 602838032Speter i = 0; 602938032Speter argv[i++] = map->map_file; 603038032Speter if (map->map_rebuild != NULL) 603138032Speter { 603290792Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof buf); 603338032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 603438032Speter { 603538032Speter if (i >= MAXPV - 1) 603638032Speter break; 603738032Speter argv[i++] = p; 603838032Speter } 603938032Speter } 604038032Speter argv[i++] = name; 604138032Speter argv[i] = NULL; 604238032Speter if (tTd(38, 21)) 604338032Speter { 604490792Sgshapiro sm_dprintf("prog_open:"); 604538032Speter for (i = 0; argv[i] != NULL; i++) 604690792Sgshapiro sm_dprintf(" %s", argv[i]); 604790792Sgshapiro sm_dprintf("\n"); 604838032Speter } 604990792Sgshapiro (void) sm_blocksignal(SIGCHLD); 605038032Speter pid = prog_open(argv, &fd, CurEnv); 605138032Speter if (pid < 0) 605238032Speter { 605338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 605438032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 605590792Sgshapiro map->map_mname, sm_errstring(errno)); 605638032Speter else if (tTd(38, 9)) 605790792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 605890792Sgshapiro map->map_mname, sm_errstring(errno)); 605938032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 606038032Speter *statp = EX_OSFILE; 606138032Speter return NULL; 606238032Speter } 606338032Speter i = read(fd, buf, sizeof buf - 1); 606438032Speter if (i < 0) 606538032Speter { 606690792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 606790792Sgshapiro map->map_mname, sm_errstring(errno)); 606838032Speter rval = NULL; 606938032Speter } 607038032Speter else if (i == 0) 607138032Speter { 607238032Speter if (tTd(38, 20)) 607390792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 607490792Sgshapiro map->map_mname); 607538032Speter rval = NULL; 607638032Speter } 607738032Speter else 607838032Speter { 607938032Speter buf[i] = '\0'; 608038032Speter p = strchr(buf, '\n'); 608138032Speter if (p != NULL) 608238032Speter *p = '\0'; 608338032Speter 608438032Speter /* collect the return value */ 608538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 608638032Speter rval = map_rewrite(map, name, strlen(name), NULL); 608738032Speter else 608877349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 608938032Speter 609038032Speter /* now flush any additional output */ 609138032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 609238032Speter continue; 609338032Speter } 609438032Speter 609538032Speter /* wait for the process to terminate */ 609664562Sgshapiro (void) close(fd); 609764562Sgshapiro status = waitfor(pid); 609864562Sgshapiro save_errno = errno; 609990792Sgshapiro (void) sm_releasesignal(SIGCHLD); 610064562Sgshapiro errno = save_errno; 610138032Speter 610264562Sgshapiro if (status == -1) 610338032Speter { 610490792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 610590792Sgshapiro map->map_mname, sm_errstring(errno)); 610638032Speter *statp = EX_SOFTWARE; 610738032Speter rval = NULL; 610838032Speter } 610964562Sgshapiro else if (WIFEXITED(status)) 611038032Speter { 611164562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 611238032Speter rval = NULL; 611338032Speter } 611438032Speter else 611538032Speter { 611638032Speter syserr("prog_map_lookup(%s): child died on signal %d", 611790792Sgshapiro map->map_mname, status); 611838032Speter *statp = EX_UNAVAILABLE; 611938032Speter rval = NULL; 612038032Speter } 612138032Speter return rval; 612238032Speter} 612390792Sgshapiro/* 612438032Speter** Sequenced map type. 612538032Speter** 612638032Speter** Tries each map in order until something matches, much like 612738032Speter** implicit. Stores go to the first map in the list that can 612838032Speter** support storing. 612938032Speter** 613038032Speter** This is slightly unusual in that there are two interfaces. 613138032Speter** The "sequence" interface lets you stack maps arbitrarily. 613238032Speter** The "switch" interface builds a sequence map by looking 613338032Speter** at a system-dependent configuration file such as 613438032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 613538032Speter** 613638032Speter** We don't need an explicit open, since all maps are 613790792Sgshapiro** opened on demand. 613838032Speter*/ 613938032Speter 614038032Speter/* 614138032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 614238032Speter*/ 614338032Speter 614438032Speterbool 614538032Speterseq_map_parse(map, ap) 614638032Speter MAP *map; 614738032Speter char *ap; 614838032Speter{ 614938032Speter int maxmap; 615038032Speter 615138032Speter if (tTd(38, 2)) 615290792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 615338032Speter maxmap = 0; 615438032Speter while (*ap != '\0') 615538032Speter { 615638032Speter register char *p; 615738032Speter STAB *s; 615838032Speter 615938032Speter /* find beginning of map name */ 616038032Speter while (isascii(*ap) && isspace(*ap)) 616138032Speter ap++; 616264562Sgshapiro for (p = ap; 616364562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 616464562Sgshapiro p++) 616538032Speter continue; 616638032Speter if (*p != '\0') 616738032Speter *p++ = '\0'; 616838032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 616938032Speter p++; 617038032Speter if (*ap == '\0') 617138032Speter { 617238032Speter ap = p; 617338032Speter continue; 617438032Speter } 617538032Speter s = stab(ap, ST_MAP, ST_FIND); 617638032Speter if (s == NULL) 617738032Speter { 617838032Speter syserr("Sequence map %s: unknown member map %s", 617938032Speter map->map_mname, ap); 618038032Speter } 618190792Sgshapiro else if (maxmap >= MAXMAPSTACK) 618238032Speter { 618338032Speter syserr("Sequence map %s: too many member maps (%d max)", 618438032Speter map->map_mname, MAXMAPSTACK); 618538032Speter maxmap++; 618638032Speter } 618738032Speter else if (maxmap < MAXMAPSTACK) 618838032Speter { 618938032Speter map->map_stack[maxmap++] = &s->s_map; 619038032Speter } 619138032Speter ap = p; 619238032Speter } 619390792Sgshapiro return true; 619438032Speter} 619538032Speter 619638032Speter/* 619738032Speter** SWITCH_MAP_OPEN -- open a switched map 619838032Speter** 619938032Speter** This looks at the system-dependent configuration and builds 620038032Speter** a sequence map that does the same thing. 620138032Speter** 620238032Speter** Every system must define a switch_map_find routine in conf.c 620338032Speter** that will return the list of service types associated with a 620438032Speter** given service class. 620538032Speter*/ 620638032Speter 620738032Speterbool 620838032Speterswitch_map_open(map, mode) 620938032Speter MAP *map; 621038032Speter int mode; 621138032Speter{ 621238032Speter int mapno; 621338032Speter int nmaps; 621438032Speter char *maptype[MAXMAPSTACK]; 621538032Speter 621638032Speter if (tTd(38, 2)) 621790792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 621838032Speter map->map_mname, map->map_file, mode); 621938032Speter 622038032Speter mode &= O_ACCMODE; 622138032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 622238032Speter if (tTd(38, 19)) 622338032Speter { 622490792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 622538032Speter for (mapno = 0; mapno < nmaps; mapno++) 622690792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 622738032Speter } 622838032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 622990792Sgshapiro return false; 623038032Speter 623138032Speter for (mapno = 0; mapno < nmaps; mapno++) 623238032Speter { 623338032Speter register STAB *s; 623438032Speter char nbuf[MAXNAME + 1]; 623538032Speter 623638032Speter if (maptype[mapno] == NULL) 623738032Speter continue; 623890792Sgshapiro (void) sm_strlcpyn(nbuf, sizeof nbuf, 3, 623990792Sgshapiro map->map_mname, ".", maptype[mapno]); 624038032Speter s = stab(nbuf, ST_MAP, ST_FIND); 624138032Speter if (s == NULL) 624238032Speter { 624338032Speter syserr("Switch map %s: unknown member map %s", 624438032Speter map->map_mname, nbuf); 624538032Speter } 624638032Speter else 624738032Speter { 624838032Speter map->map_stack[mapno] = &s->s_map; 624938032Speter if (tTd(38, 4)) 625090792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 625190792Sgshapiro mapno, 625290792Sgshapiro s->s_map.map_class->map_cname, 625390792Sgshapiro nbuf); 625438032Speter } 625538032Speter } 625690792Sgshapiro return true; 625738032Speter} 625838032Speter 625990792Sgshapiro#if 0 626038032Speter/* 626138032Speter** SEQ_MAP_CLOSE -- close all underlying maps 626238032Speter*/ 626338032Speter 626438032Spetervoid 626538032Speterseq_map_close(map) 626638032Speter MAP *map; 626738032Speter{ 626838032Speter int mapno; 626938032Speter 627038032Speter if (tTd(38, 9)) 627190792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 627238032Speter 627338032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 627438032Speter { 627538032Speter MAP *mm = map->map_stack[mapno]; 627638032Speter 627738032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 627838032Speter continue; 627977349Sgshapiro mm->map_mflags |= MF_CLOSING; 628038032Speter mm->map_class->map_close(mm); 628177349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 628238032Speter } 628338032Speter} 628490792Sgshapiro#endif /* 0 */ 628538032Speter 628638032Speter/* 628738032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 628838032Speter*/ 628938032Speter 629038032Speterchar * 629138032Speterseq_map_lookup(map, key, args, pstat) 629238032Speter MAP *map; 629338032Speter char *key; 629438032Speter char **args; 629538032Speter int *pstat; 629638032Speter{ 629738032Speter int mapno; 629838032Speter int mapbit = 0x01; 629990792Sgshapiro bool tempfail = false; 630038032Speter 630138032Speter if (tTd(38, 20)) 630290792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 630338032Speter 630438032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 630538032Speter { 630638032Speter MAP *mm = map->map_stack[mapno]; 630738032Speter char *rv; 630838032Speter 630938032Speter if (mm == NULL) 631038032Speter continue; 631164562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 631264562Sgshapiro !openmap(mm)) 631338032Speter { 631438032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 631538032Speter { 631638032Speter *pstat = EX_UNAVAILABLE; 631738032Speter return NULL; 631838032Speter } 631938032Speter continue; 632038032Speter } 632138032Speter *pstat = EX_OK; 632238032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 632338032Speter if (rv != NULL) 632438032Speter return rv; 632538032Speter if (*pstat == EX_TEMPFAIL) 632638032Speter { 632738032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 632838032Speter return NULL; 632990792Sgshapiro tempfail = true; 633038032Speter } 633138032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 633238032Speter break; 633338032Speter } 633438032Speter if (tempfail) 633538032Speter *pstat = EX_TEMPFAIL; 633638032Speter else if (*pstat == EX_OK) 633738032Speter *pstat = EX_NOTFOUND; 633838032Speter return NULL; 633938032Speter} 634038032Speter 634138032Speter/* 634238032Speter** SEQ_MAP_STORE -- sequenced map store 634338032Speter*/ 634438032Speter 634538032Spetervoid 634638032Speterseq_map_store(map, key, val) 634738032Speter MAP *map; 634838032Speter char *key; 634938032Speter char *val; 635038032Speter{ 635138032Speter int mapno; 635238032Speter 635338032Speter if (tTd(38, 12)) 635490792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 635538032Speter map->map_mname, key, val); 635638032Speter 635738032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 635838032Speter { 635938032Speter MAP *mm = map->map_stack[mapno]; 636038032Speter 636138032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 636238032Speter continue; 636338032Speter 636438032Speter mm->map_class->map_store(mm, key, val); 636538032Speter return; 636638032Speter } 636738032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 636838032Speter map->map_mname, key, val); 636938032Speter} 637090792Sgshapiro/* 637138032Speter** NULL stubs 637238032Speter*/ 637338032Speter 637438032Speter/* ARGSUSED */ 637538032Speterbool 637638032Speternull_map_open(map, mode) 637738032Speter MAP *map; 637838032Speter int mode; 637938032Speter{ 638090792Sgshapiro return true; 638138032Speter} 638238032Speter 638338032Speter/* ARGSUSED */ 638438032Spetervoid 638538032Speternull_map_close(map) 638638032Speter MAP *map; 638738032Speter{ 638838032Speter return; 638938032Speter} 639038032Speter 639138032Speterchar * 639238032Speternull_map_lookup(map, key, args, pstat) 639338032Speter MAP *map; 639438032Speter char *key; 639538032Speter char **args; 639638032Speter int *pstat; 639738032Speter{ 639838032Speter *pstat = EX_NOTFOUND; 639938032Speter return NULL; 640038032Speter} 640138032Speter 640238032Speter/* ARGSUSED */ 640338032Spetervoid 640438032Speternull_map_store(map, key, val) 640538032Speter MAP *map; 640638032Speter char *key; 640738032Speter char *val; 640838032Speter{ 640938032Speter return; 641038032Speter} 641138032Speter 641238032Speter/* 641338032Speter** BOGUS stubs 641438032Speter*/ 641538032Speter 641638032Speterchar * 641738032Speterbogus_map_lookup(map, key, args, pstat) 641838032Speter MAP *map; 641938032Speter char *key; 642038032Speter char **args; 642138032Speter int *pstat; 642238032Speter{ 642338032Speter *pstat = EX_TEMPFAIL; 642438032Speter return NULL; 642538032Speter} 642638032Speter 642738032SpeterMAPCLASS BogusMapClass = 642838032Speter{ 642990792Sgshapiro "bogus-map", NULL, 0, 643090792Sgshapiro NULL, bogus_map_lookup, null_map_store, 643190792Sgshapiro null_map_open, null_map_close, 643238032Speter}; 643390792Sgshapiro/* 643464562Sgshapiro** MACRO modules 643564562Sgshapiro*/ 643664562Sgshapiro 643764562Sgshapirochar * 643864562Sgshapiromacro_map_lookup(map, name, av, statp) 643964562Sgshapiro MAP *map; 644064562Sgshapiro char *name; 644164562Sgshapiro char **av; 644264562Sgshapiro int *statp; 644364562Sgshapiro{ 644464562Sgshapiro int mid; 644564562Sgshapiro 644664562Sgshapiro if (tTd(38, 20)) 644790792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 644864562Sgshapiro name == NULL ? "NULL" : name); 644964562Sgshapiro 645064562Sgshapiro if (name == NULL || 645164562Sgshapiro *name == '\0' || 645290792Sgshapiro (mid = macid(name)) == 0) 645364562Sgshapiro { 645464562Sgshapiro *statp = EX_CONFIG; 645564562Sgshapiro return NULL; 645664562Sgshapiro } 645764562Sgshapiro 645864562Sgshapiro if (av[1] == NULL) 645990792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 646064562Sgshapiro else 646190792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 646264562Sgshapiro 646364562Sgshapiro *statp = EX_OK; 646464562Sgshapiro return ""; 646564562Sgshapiro} 646690792Sgshapiro/* 646738032Speter** REGEX modules 646838032Speter*/ 646938032Speter 647090792Sgshapiro#if MAP_REGEX 647138032Speter 647238032Speter# include <regex.h> 647338032Speter 647438032Speter# define DEFAULT_DELIM CONDELSE 647538032Speter# define END_OF_FIELDS -1 647638032Speter# define ERRBUF_SIZE 80 647738032Speter# define MAX_MATCH 32 647838032Speter 647964562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 648038032Speter 648138032Speterstruct regex_map 648238032Speter{ 648371345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 648438032Speter int *regex_subfields; /* move to type MAP */ 648564562Sgshapiro char *regex_delim; /* move to type MAP */ 648638032Speter}; 648738032Speter 6488141858Sgshapirostatic int parse_fields __P((char *, int *, int, int)); 6489141858Sgshapirostatic char *regex_map_rewrite __P((MAP *, const char*, size_t, char **)); 6490141858Sgshapiro 649138032Speterstatic int 649238032Speterparse_fields(s, ibuf, blen, nr_substrings) 649338032Speter char *s; 649438032Speter int *ibuf; /* array */ 649538032Speter int blen; /* number of elements in ibuf */ 649638032Speter int nr_substrings; /* number of substrings in the pattern */ 649738032Speter{ 649838032Speter register char *cp; 649938032Speter int i = 0; 650090792Sgshapiro bool lastone = false; 650138032Speter 650238032Speter blen--; /* for terminating END_OF_FIELDS */ 650338032Speter cp = s; 650438032Speter do 650538032Speter { 650638032Speter for (;; cp++) 650738032Speter { 650838032Speter if (*cp == ',') 650938032Speter { 651038032Speter *cp = '\0'; 651138032Speter break; 651238032Speter } 651338032Speter if (*cp == '\0') 651438032Speter { 651590792Sgshapiro lastone = true; 651638032Speter break; 651738032Speter } 651838032Speter } 651938032Speter if (i < blen) 652038032Speter { 652138032Speter int val = atoi(s); 652238032Speter 652338032Speter if (val < 0 || val >= nr_substrings) 652438032Speter { 652538032Speter syserr("field (%d) out of range, only %d substrings in pattern", 652638032Speter val, nr_substrings); 652738032Speter return -1; 652838032Speter } 652938032Speter ibuf[i++] = val; 653038032Speter } 653138032Speter else 653238032Speter { 653390792Sgshapiro syserr("too many fields, %d max", blen); 653438032Speter return -1; 653538032Speter } 653638032Speter s = ++cp; 653738032Speter } while (!lastone); 653838032Speter ibuf[i] = END_OF_FIELDS; 653938032Speter return i; 654038032Speter} 654138032Speter 654238032Speterbool 654338032Speterregex_map_init(map, ap) 654438032Speter MAP *map; 654538032Speter char *ap; 654638032Speter{ 654738032Speter int regerr; 654838032Speter struct regex_map *map_p; 654938032Speter register char *p; 655038032Speter char *sub_param = NULL; 655138032Speter int pflags; 655290792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 655338032Speter 655438032Speter if (tTd(38, 2)) 655590792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 655664562Sgshapiro map->map_mname, ap); 655738032Speter 655838032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 655938032Speter p = ap; 656064562Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof *map_p); 656171345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 656238032Speter 656338032Speter for (;;) 656464562Sgshapiro { 656538032Speter while (isascii(*p) && isspace(*p)) 656638032Speter p++; 656738032Speter if (*p != '-') 656838032Speter break; 656938032Speter switch (*++p) 657038032Speter { 657138032Speter case 'n': /* not */ 657238032Speter map->map_mflags |= MF_REGEX_NOT; 657338032Speter break; 657438032Speter 657538032Speter case 'f': /* case sensitive */ 657638032Speter map->map_mflags |= MF_NOFOLDCASE; 657738032Speter pflags &= ~REG_ICASE; 657838032Speter break; 657938032Speter 658038032Speter case 'b': /* basic regular expressions */ 658138032Speter pflags &= ~REG_EXTENDED; 658238032Speter break; 658338032Speter 658438032Speter case 's': /* substring match () syntax */ 658538032Speter sub_param = ++p; 658638032Speter pflags &= ~REG_NOSUB; 658738032Speter break; 658838032Speter 658938032Speter case 'd': /* delimiter */ 659064562Sgshapiro map_p->regex_delim = ++p; 659138032Speter break; 659238032Speter 659338032Speter case 'a': /* map append */ 659438032Speter map->map_app = ++p; 659538032Speter break; 659638032Speter 659738032Speter case 'm': /* matchonly */ 659838032Speter map->map_mflags |= MF_MATCHONLY; 659938032Speter break; 660038032Speter 6601120256Sgshapiro case 'q': 6602120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 6603120256Sgshapiro break; 6604120256Sgshapiro 660564562Sgshapiro case 'S': 660664562Sgshapiro map->map_spacesub = *++p; 660764562Sgshapiro break; 660864562Sgshapiro 660964562Sgshapiro case 'D': 661064562Sgshapiro map->map_mflags |= MF_DEFER; 661164562Sgshapiro break; 661264562Sgshapiro 661338032Speter } 661464562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 661564562Sgshapiro p++; 661664562Sgshapiro if (*p != '\0') 661764562Sgshapiro *p++ = '\0'; 661838032Speter } 661938032Speter if (tTd(38, 3)) 662090792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 662138032Speter 662271345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 662338032Speter { 662438032Speter /* Errorhandling */ 662538032Speter char errbuf[ERRBUF_SIZE]; 662638032Speter 662771345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 662890792Sgshapiro errbuf, sizeof errbuf); 662990792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 663090792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 663190792Sgshapiro sm_free(map_p); /* XXX */ 663290792Sgshapiro return false; 663338032Speter } 663438032Speter 663538032Speter if (map->map_app != NULL) 663638032Speter map->map_app = newstr(map->map_app); 663764562Sgshapiro if (map_p->regex_delim != NULL) 663864562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 663938032Speter else 664064562Sgshapiro map_p->regex_delim = defdstr; 664138032Speter 664238032Speter if (!bitset(REG_NOSUB, pflags)) 664338032Speter { 664438032Speter /* substring matching */ 664538032Speter int substrings; 664664562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 664738032Speter 664871345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 664938032Speter 665038032Speter if (tTd(38, 3)) 665190792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 665264562Sgshapiro substrings); 665338032Speter 665438032Speter if (substrings >= MAX_MATCH) 665538032Speter { 665690792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 665790792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 665890792Sgshapiro sm_free(map_p); /* XXX */ 665990792Sgshapiro return false; 666038032Speter } 666138032Speter if (sub_param != NULL && sub_param[0] != '\0') 666238032Speter { 666338032Speter /* optional parameter -sfields */ 666438032Speter if (parse_fields(sub_param, fields, 666538032Speter MAX_MATCH + 1, substrings) == -1) 666690792Sgshapiro return false; 666738032Speter } 666838032Speter else 666938032Speter { 667038032Speter int i; 667138032Speter 667290792Sgshapiro /* set default fields */ 667338032Speter for (i = 0; i < substrings; i++) 667438032Speter fields[i] = i; 667538032Speter fields[i] = END_OF_FIELDS; 667638032Speter } 667738032Speter map_p->regex_subfields = fields; 667838032Speter if (tTd(38, 3)) 667938032Speter { 668038032Speter int *ip; 668138032Speter 668290792Sgshapiro sm_dprintf("regex_map_init: subfields"); 668338032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 668490792Sgshapiro sm_dprintf(" %d", *ip); 668590792Sgshapiro sm_dprintf("\n"); 668638032Speter } 668738032Speter } 668890792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 668990792Sgshapiro return true; 669038032Speter} 669138032Speter 669238032Speterstatic char * 669338032Speterregex_map_rewrite(map, s, slen, av) 669438032Speter MAP *map; 669538032Speter const char *s; 669638032Speter size_t slen; 669738032Speter char **av; 669838032Speter{ 669938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 670038032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 670138032Speter else 670277349Sgshapiro return map_rewrite(map, s, slen, av); 670338032Speter} 670438032Speter 670538032Speterchar * 670638032Speterregex_map_lookup(map, name, av, statp) 670738032Speter MAP *map; 670838032Speter char *name; 670938032Speter char **av; 671038032Speter int *statp; 671138032Speter{ 671238032Speter int reg_res; 671338032Speter struct regex_map *map_p; 671438032Speter regmatch_t pmatch[MAX_MATCH]; 671538032Speter 671638032Speter if (tTd(38, 20)) 671738032Speter { 671838032Speter char **cpp; 671938032Speter 672090792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 672164562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 672290792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 672338032Speter } 672438032Speter 672538032Speter map_p = (struct regex_map *)(map->map_db1); 672671345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 672764562Sgshapiro name, MAX_MATCH, pmatch, 0); 672838032Speter 672938032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 673038032Speter { 673138032Speter /* option -n */ 673238032Speter if (reg_res == REG_NOMATCH) 673390792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 673438032Speter else 673538032Speter return NULL; 673638032Speter } 673738032Speter if (reg_res == REG_NOMATCH) 673838032Speter return NULL; 673938032Speter 674038032Speter if (map_p->regex_subfields != NULL) 674138032Speter { 674238032Speter /* option -s */ 674338032Speter static char retbuf[MAXNAME]; 674438032Speter int fields[MAX_MATCH + 1]; 674590792Sgshapiro bool first = true; 674638032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 674790792Sgshapiro bool quotemode = false, bslashmode = false; 674838032Speter register char *dp, *sp; 674938032Speter char *endp, *ldp; 675038032Speter int *ip; 675138032Speter 675238032Speter dp = retbuf; 675338032Speter ldp = retbuf + sizeof(retbuf) - 1; 675438032Speter 675538032Speter if (av[1] != NULL) 675638032Speter { 675738032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 675871345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 675938032Speter { 676038032Speter *statp = EX_CONFIG; 676138032Speter return NULL; 676238032Speter } 676338032Speter ip = fields; 676438032Speter } 676538032Speter else 676638032Speter ip = map_p->regex_subfields; 676738032Speter 676838032Speter for ( ; *ip != END_OF_FIELDS; ip++) 676938032Speter { 677038032Speter if (!first) 677138032Speter { 677264562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 677338032Speter { 677438032Speter if (dp < ldp) 677538032Speter *dp++ = *sp; 677638032Speter } 677738032Speter } 677838032Speter else 677990792Sgshapiro first = false; 678038032Speter 678171345Sgshapiro if (*ip >= MAX_MATCH || 678271345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 678338032Speter continue; 678438032Speter 678538032Speter sp = name + pmatch[*ip].rm_so; 678638032Speter endp = name + pmatch[*ip].rm_eo; 678738032Speter for (; endp > sp; sp++) 678838032Speter { 678938032Speter if (dp < ldp) 679038032Speter { 679164562Sgshapiro if (bslashmode) 679264562Sgshapiro { 679338032Speter *dp++ = *sp; 679490792Sgshapiro bslashmode = false; 679538032Speter } 679664562Sgshapiro else if (quotemode && *sp != '"' && 679738032Speter *sp != '\\') 679838032Speter { 679938032Speter *dp++ = *sp; 680038032Speter } 680190792Sgshapiro else switch (*dp++ = *sp) 680238032Speter { 680390792Sgshapiro case '\\': 680490792Sgshapiro bslashmode = true; 680538032Speter break; 680638032Speter 680790792Sgshapiro case '(': 680838032Speter cmntcnt++; 680938032Speter break; 681038032Speter 681190792Sgshapiro case ')': 681238032Speter cmntcnt--; 681338032Speter break; 681438032Speter 681590792Sgshapiro case '<': 681638032Speter anglecnt++; 681738032Speter break; 681838032Speter 681990792Sgshapiro case '>': 682038032Speter anglecnt--; 682138032Speter break; 682238032Speter 682390792Sgshapiro case ' ': 682438032Speter spacecnt++; 682538032Speter break; 682638032Speter 682790792Sgshapiro case '"': 682838032Speter quotemode = !quotemode; 682938032Speter break; 683038032Speter } 683138032Speter } 683238032Speter } 683338032Speter } 683438032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 683538032Speter bslashmode || spacecnt != 0) 683638032Speter { 683764562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 683864562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 683964562Sgshapiro map->map_mname, name); 684038032Speter return NULL; 684138032Speter } 684238032Speter 684338032Speter *dp = '\0'; 684438032Speter 684538032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 684638032Speter } 684738032Speter return regex_map_rewrite(map, "", (size_t)0, av); 684838032Speter} 684938032Speter#endif /* MAP_REGEX */ 685090792Sgshapiro/* 685164562Sgshapiro** NSD modules 685264562Sgshapiro*/ 685390792Sgshapiro#if MAP_NSD 685464562Sgshapiro 685564562Sgshapiro# include <ndbm.h> 685664562Sgshapiro# define _DATUM_DEFINED 685764562Sgshapiro# include <ns_api.h> 685864562Sgshapiro 685964562Sgshapirotypedef struct ns_map_list 686064562Sgshapiro{ 686190792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 686290792Sgshapiro char *mapname; 686390792Sgshapiro struct ns_map_list *next; 686464562Sgshapiro} ns_map_list_t; 686564562Sgshapiro 686664562Sgshapirostatic ns_map_t * 686764562Sgshapirons_map_t_find(mapname) 686864562Sgshapiro char *mapname; 686964562Sgshapiro{ 687064562Sgshapiro static ns_map_list_t *ns_maps = NULL; 687164562Sgshapiro ns_map_list_t *ns_map; 687264562Sgshapiro 687364562Sgshapiro /* walk the list of maps looking for the correctly named map */ 687464562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 687564562Sgshapiro { 687664562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 687764562Sgshapiro break; 687864562Sgshapiro } 687964562Sgshapiro 688064562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 688164562Sgshapiro if (ns_map == NULL) 688264562Sgshapiro { 688364562Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 688464562Sgshapiro ns_map->mapname = newstr(mapname); 688564562Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 6886102528Sgshapiro memset(ns_map->map, '\0', sizeof *ns_map->map); 688764562Sgshapiro ns_map->next = ns_maps; 688864562Sgshapiro ns_maps = ns_map; 688964562Sgshapiro } 689064562Sgshapiro return ns_map->map; 689164562Sgshapiro} 689264562Sgshapiro 689364562Sgshapirochar * 689464562Sgshapironsd_map_lookup(map, name, av, statp) 689564562Sgshapiro MAP *map; 689664562Sgshapiro char *name; 689764562Sgshapiro char **av; 689864562Sgshapiro int *statp; 689964562Sgshapiro{ 690071345Sgshapiro int buflen, r; 690164562Sgshapiro char *p; 690264562Sgshapiro ns_map_t *ns_map; 690364562Sgshapiro char keybuf[MAXNAME + 1]; 690464562Sgshapiro char buf[MAXLINE]; 690564562Sgshapiro 690664562Sgshapiro if (tTd(38, 20)) 690790792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 690864562Sgshapiro 690964562Sgshapiro buflen = strlen(name); 691064562Sgshapiro if (buflen > sizeof keybuf - 1) 691190792Sgshapiro buflen = sizeof keybuf - 1; /* XXX simply cut off? */ 691264562Sgshapiro memmove(keybuf, name, buflen); 691364562Sgshapiro keybuf[buflen] = '\0'; 691464562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 691564562Sgshapiro makelower(keybuf); 691664562Sgshapiro 691764562Sgshapiro ns_map = ns_map_t_find(map->map_file); 691864562Sgshapiro if (ns_map == NULL) 691964562Sgshapiro { 692064562Sgshapiro if (tTd(38, 20)) 692190792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 692271345Sgshapiro *statp = EX_UNAVAILABLE; 692364562Sgshapiro return NULL; 692464562Sgshapiro } 692598121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 692698121Sgshapiro buf, sizeof buf); 692771345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 692871345Sgshapiro { 692971345Sgshapiro *statp = EX_TEMPFAIL; 693064562Sgshapiro return NULL; 693171345Sgshapiro } 693277349Sgshapiro if (r == NS_BADREQ 693377349Sgshapiro# ifdef NS_NOPERM 693477349Sgshapiro || r == NS_NOPERM 693577349Sgshapiro# endif /* NS_NOPERM */ 693677349Sgshapiro ) 693771345Sgshapiro { 693871345Sgshapiro *statp = EX_CONFIG; 693971345Sgshapiro return NULL; 694071345Sgshapiro } 694171345Sgshapiro if (r != NS_SUCCESS) 694271345Sgshapiro { 694371345Sgshapiro *statp = EX_NOTFOUND; 694471345Sgshapiro return NULL; 694571345Sgshapiro } 694664562Sgshapiro 694771345Sgshapiro *statp = EX_OK; 694871345Sgshapiro 694964562Sgshapiro /* Null out trailing \n */ 695064562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 695164562Sgshapiro *p = '\0'; 695264562Sgshapiro 695364562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 695464562Sgshapiro} 695564562Sgshapiro#endif /* MAP_NSD */ 695664562Sgshapiro 695764562Sgshapirochar * 695864562Sgshapiroarith_map_lookup(map, name, av, statp) 695964562Sgshapiro MAP *map; 696064562Sgshapiro char *name; 696164562Sgshapiro char **av; 696264562Sgshapiro int *statp; 696364562Sgshapiro{ 696464562Sgshapiro long r; 696564562Sgshapiro long v[2]; 696690792Sgshapiro bool res = false; 696764562Sgshapiro bool boolres; 696864562Sgshapiro static char result[16]; 696964562Sgshapiro char **cpp; 697064562Sgshapiro 697164562Sgshapiro if (tTd(38, 2)) 697264562Sgshapiro { 697390792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 697464562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 697590792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 697664562Sgshapiro } 697764562Sgshapiro r = 0; 697890792Sgshapiro boolres = false; 697964562Sgshapiro cpp = av; 698064562Sgshapiro *statp = EX_OK; 698164562Sgshapiro 698264562Sgshapiro /* 698364562Sgshapiro ** read arguments for arith map 698464562Sgshapiro ** - no check is made whether they are really numbers 698564562Sgshapiro ** - just ignores args after the second 698664562Sgshapiro */ 698790792Sgshapiro 698864562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 698964562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 699064562Sgshapiro 699164562Sgshapiro /* operator and (at least) two operands given? */ 699264562Sgshapiro if (name != NULL && r == 2) 699364562Sgshapiro { 699490792Sgshapiro switch (*name) 699564562Sgshapiro { 699664562Sgshapiro case '|': 699764562Sgshapiro r = v[0] | v[1]; 699864562Sgshapiro break; 699964562Sgshapiro 700064562Sgshapiro case '&': 700164562Sgshapiro r = v[0] & v[1]; 700264562Sgshapiro break; 700364562Sgshapiro 700464562Sgshapiro case '%': 700564562Sgshapiro if (v[1] == 0) 700664562Sgshapiro return NULL; 700764562Sgshapiro r = v[0] % v[1]; 700864562Sgshapiro break; 700964562Sgshapiro case '+': 701064562Sgshapiro r = v[0] + v[1]; 701164562Sgshapiro break; 701264562Sgshapiro 701364562Sgshapiro case '-': 701464562Sgshapiro r = v[0] - v[1]; 701564562Sgshapiro break; 701664562Sgshapiro 701764562Sgshapiro case '*': 701864562Sgshapiro r = v[0] * v[1]; 701964562Sgshapiro break; 702064562Sgshapiro 702164562Sgshapiro case '/': 702264562Sgshapiro if (v[1] == 0) 702364562Sgshapiro return NULL; 702464562Sgshapiro r = v[0] / v[1]; 702564562Sgshapiro break; 702664562Sgshapiro 702764562Sgshapiro case 'l': 702864562Sgshapiro res = v[0] < v[1]; 702990792Sgshapiro boolres = true; 703064562Sgshapiro break; 703164562Sgshapiro 703264562Sgshapiro case '=': 703364562Sgshapiro res = v[0] == v[1]; 703490792Sgshapiro boolres = true; 703564562Sgshapiro break; 703664562Sgshapiro 703764562Sgshapiro default: 703864562Sgshapiro /* XXX */ 703964562Sgshapiro *statp = EX_CONFIG; 704064562Sgshapiro if (LogLevel > 10) 704164562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 704264562Sgshapiro "arith_map: unknown operator %c", 704364562Sgshapiro isprint(*name) ? *name : '?'); 704464562Sgshapiro return NULL; 704564562Sgshapiro } 704664562Sgshapiro if (boolres) 704790792Sgshapiro (void) sm_snprintf(result, sizeof result, 704890792Sgshapiro res ? "TRUE" : "FALSE"); 704964562Sgshapiro else 705090792Sgshapiro (void) sm_snprintf(result, sizeof result, "%ld", r); 705164562Sgshapiro return result; 705264562Sgshapiro } 705364562Sgshapiro *statp = EX_CONFIG; 705464562Sgshapiro return NULL; 705564562Sgshapiro} 7056132943Sgshapiro 7057132943Sgshapiro#if SOCKETMAP 7058132943Sgshapiro 7059132943Sgshapiro# if NETINET || NETINET6 7060132943Sgshapiro# include <arpa/inet.h> 7061132943Sgshapiro# endif /* NETINET || NETINET6 */ 7062132943Sgshapiro 7063132943Sgshapiro# define socket_map_next map_stack[0] 7064132943Sgshapiro 7065132943Sgshapiro/* 7066132943Sgshapiro** SOCKET_MAP_OPEN -- open socket table 7067132943Sgshapiro*/ 7068132943Sgshapiro 7069132943Sgshapirobool 7070132943Sgshapirosocket_map_open(map, mode) 7071132943Sgshapiro MAP *map; 7072132943Sgshapiro int mode; 7073132943Sgshapiro{ 7074132943Sgshapiro STAB *s; 7075132943Sgshapiro int sock = 0; 7076132943Sgshapiro SOCKADDR_LEN_T addrlen = 0; 7077132943Sgshapiro int addrno = 0; 7078132943Sgshapiro int save_errno; 7079132943Sgshapiro char *p; 7080132943Sgshapiro char *colon; 7081132943Sgshapiro char *at; 7082132943Sgshapiro struct hostent *hp = NULL; 7083132943Sgshapiro SOCKADDR addr; 7084132943Sgshapiro 7085132943Sgshapiro if (tTd(38, 2)) 7086132943Sgshapiro sm_dprintf("socket_map_open(%s, %s, %d)\n", 7087132943Sgshapiro map->map_mname, map->map_file, mode); 7088132943Sgshapiro 7089132943Sgshapiro mode &= O_ACCMODE; 7090132943Sgshapiro 7091132943Sgshapiro /* sendmail doesn't have the ability to write to SOCKET (yet) */ 7092132943Sgshapiro if (mode != O_RDONLY) 7093132943Sgshapiro { 7094132943Sgshapiro /* issue a pseudo-error message */ 7095132943Sgshapiro errno = SM_EMAPCANTWRITE; 7096132943Sgshapiro return false; 7097132943Sgshapiro } 7098132943Sgshapiro 7099132943Sgshapiro if (*map->map_file == '\0') 7100132943Sgshapiro { 7101132943Sgshapiro syserr("socket map \"%s\": empty or missing socket information", 7102132943Sgshapiro map->map_mname); 7103132943Sgshapiro return false; 7104132943Sgshapiro } 7105132943Sgshapiro 7106132943Sgshapiro s = socket_map_findconn(map->map_file); 7107132943Sgshapiro if (s->s_socketmap != NULL) 7108132943Sgshapiro { 7109132943Sgshapiro /* Copy open connection */ 7110132943Sgshapiro map->map_db1 = s->s_socketmap->map_db1; 7111132943Sgshapiro 7112132943Sgshapiro /* Add this map as head of linked list */ 7113132943Sgshapiro map->socket_map_next = s->s_socketmap; 7114132943Sgshapiro s->s_socketmap = map; 7115132943Sgshapiro 7116132943Sgshapiro if (tTd(38, 2)) 7117132943Sgshapiro sm_dprintf("using cached connection\n"); 7118132943Sgshapiro return true; 7119132943Sgshapiro } 7120132943Sgshapiro 7121132943Sgshapiro if (tTd(38, 2)) 7122132943Sgshapiro sm_dprintf("opening new connection\n"); 7123132943Sgshapiro 7124132943Sgshapiro /* following code is ripped from milter.c */ 7125132943Sgshapiro /* XXX It should be put in a library... */ 7126132943Sgshapiro 7127132943Sgshapiro /* protocol:filename or protocol:port@host */ 7128132943Sgshapiro memset(&addr, '\0', sizeof addr); 7129132943Sgshapiro p = map->map_file; 7130132943Sgshapiro colon = strchr(p, ':'); 7131132943Sgshapiro if (colon != NULL) 7132132943Sgshapiro { 7133132943Sgshapiro *colon = '\0'; 7134132943Sgshapiro 7135132943Sgshapiro if (*p == '\0') 7136132943Sgshapiro { 7137132943Sgshapiro# if NETUNIX 7138132943Sgshapiro /* default to AF_UNIX */ 7139132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7140132943Sgshapiro# else /* NETUNIX */ 7141132943Sgshapiro# if NETINET 7142132943Sgshapiro /* default to AF_INET */ 7143132943Sgshapiro addr.sa.sa_family = AF_INET; 7144132943Sgshapiro# else /* NETINET */ 7145132943Sgshapiro# if NETINET6 7146132943Sgshapiro /* default to AF_INET6 */ 7147132943Sgshapiro addr.sa.sa_family = AF_INET6; 7148132943Sgshapiro# else /* NETINET6 */ 7149132943Sgshapiro /* no protocols available */ 7150132943Sgshapiro syserr("socket map \"%s\": no valid socket protocols available", 7151132943Sgshapiro map->map_mname); 7152132943Sgshapiro return false; 7153132943Sgshapiro# endif /* NETINET6 */ 7154132943Sgshapiro# endif /* NETINET */ 7155132943Sgshapiro# endif /* NETUNIX */ 7156132943Sgshapiro } 7157132943Sgshapiro# if NETUNIX 7158132943Sgshapiro else if (sm_strcasecmp(p, "unix") == 0 || 7159132943Sgshapiro sm_strcasecmp(p, "local") == 0) 7160132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7161132943Sgshapiro# endif /* NETUNIX */ 7162132943Sgshapiro# if NETINET 7163132943Sgshapiro else if (sm_strcasecmp(p, "inet") == 0) 7164132943Sgshapiro addr.sa.sa_family = AF_INET; 7165132943Sgshapiro# endif /* NETINET */ 7166132943Sgshapiro# if NETINET6 7167132943Sgshapiro else if (sm_strcasecmp(p, "inet6") == 0) 7168132943Sgshapiro addr.sa.sa_family = AF_INET6; 7169132943Sgshapiro# endif /* NETINET6 */ 7170132943Sgshapiro else 7171132943Sgshapiro { 7172132943Sgshapiro# ifdef EPROTONOSUPPORT 7173132943Sgshapiro errno = EPROTONOSUPPORT; 7174132943Sgshapiro# else /* EPROTONOSUPPORT */ 7175132943Sgshapiro errno = EINVAL; 7176132943Sgshapiro# endif /* EPROTONOSUPPORT */ 7177132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7178132943Sgshapiro map->map_mname, p); 7179132943Sgshapiro return false; 7180132943Sgshapiro } 7181132943Sgshapiro *colon++ = ':'; 7182132943Sgshapiro } 7183132943Sgshapiro else 7184132943Sgshapiro { 7185132943Sgshapiro colon = p; 7186132943Sgshapiro#if NETUNIX 7187132943Sgshapiro /* default to AF_UNIX */ 7188132943Sgshapiro addr.sa.sa_family = AF_UNIX; 7189132943Sgshapiro#else /* NETUNIX */ 7190132943Sgshapiro# if NETINET 7191132943Sgshapiro /* default to AF_INET */ 7192132943Sgshapiro addr.sa.sa_family = AF_INET; 7193132943Sgshapiro# else /* NETINET */ 7194132943Sgshapiro# if NETINET6 7195132943Sgshapiro /* default to AF_INET6 */ 7196132943Sgshapiro addr.sa.sa_family = AF_INET6; 7197132943Sgshapiro# else /* NETINET6 */ 7198132943Sgshapiro syserr("socket map \"%s\": unknown socket type %s", 7199132943Sgshapiro map->map_mname, p); 7200132943Sgshapiro return false; 7201132943Sgshapiro# endif /* NETINET6 */ 7202132943Sgshapiro# endif /* NETINET */ 7203132943Sgshapiro#endif /* NETUNIX */ 7204132943Sgshapiro } 7205132943Sgshapiro 7206132943Sgshapiro# if NETUNIX 7207132943Sgshapiro if (addr.sa.sa_family == AF_UNIX) 7208132943Sgshapiro { 7209132943Sgshapiro long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 7210132943Sgshapiro 7211132943Sgshapiro at = colon; 7212132943Sgshapiro if (strlen(colon) >= sizeof addr.sunix.sun_path) 7213132943Sgshapiro { 7214132943Sgshapiro syserr("socket map \"%s\": local socket name %s too long", 7215132943Sgshapiro map->map_mname, colon); 7216132943Sgshapiro return false; 7217132943Sgshapiro } 7218132943Sgshapiro errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 7219132943Sgshapiro S_IRUSR|S_IWUSR, NULL); 7220132943Sgshapiro 7221132943Sgshapiro if (errno != 0) 7222132943Sgshapiro { 7223132943Sgshapiro /* if not safe, don't create */ 7224132943Sgshapiro syserr("socket map \"%s\": local socket name %s unsafe", 7225132943Sgshapiro map->map_mname, colon); 7226132943Sgshapiro return false; 7227132943Sgshapiro } 7228132943Sgshapiro 7229132943Sgshapiro (void) sm_strlcpy(addr.sunix.sun_path, colon, 7230132943Sgshapiro sizeof addr.sunix.sun_path); 7231132943Sgshapiro addrlen = sizeof (struct sockaddr_un); 7232132943Sgshapiro } 7233132943Sgshapiro else 7234132943Sgshapiro# endif /* NETUNIX */ 7235132943Sgshapiro# if NETINET || NETINET6 7236132943Sgshapiro if (false 7237132943Sgshapiro# if NETINET 7238132943Sgshapiro || addr.sa.sa_family == AF_INET 7239132943Sgshapiro# endif /* NETINET */ 7240132943Sgshapiro# if NETINET6 7241132943Sgshapiro || addr.sa.sa_family == AF_INET6 7242132943Sgshapiro# endif /* NETINET6 */ 7243132943Sgshapiro ) 7244132943Sgshapiro { 7245132943Sgshapiro unsigned short port; 7246132943Sgshapiro 7247132943Sgshapiro /* Parse port@host */ 7248132943Sgshapiro at = strchr(colon, '@'); 7249132943Sgshapiro if (at == NULL) 7250132943Sgshapiro { 7251132943Sgshapiro syserr("socket map \"%s\": bad address %s (expected port@host)", 7252132943Sgshapiro map->map_mname, colon); 7253132943Sgshapiro return false; 7254132943Sgshapiro } 7255132943Sgshapiro *at = '\0'; 7256132943Sgshapiro if (isascii(*colon) && isdigit(*colon)) 7257132943Sgshapiro port = htons((unsigned short) atoi(colon)); 7258132943Sgshapiro else 7259132943Sgshapiro { 7260132943Sgshapiro# ifdef NO_GETSERVBYNAME 7261132943Sgshapiro syserr("socket map \"%s\": invalid port number %s", 7262132943Sgshapiro map->map_mname, colon); 7263132943Sgshapiro return false; 7264132943Sgshapiro# else /* NO_GETSERVBYNAME */ 7265132943Sgshapiro register struct servent *sp; 7266132943Sgshapiro 7267132943Sgshapiro sp = getservbyname(colon, "tcp"); 7268132943Sgshapiro if (sp == NULL) 7269132943Sgshapiro { 7270132943Sgshapiro syserr("socket map \"%s\": unknown port name %s", 7271132943Sgshapiro map->map_mname, colon); 7272132943Sgshapiro return false; 7273132943Sgshapiro } 7274132943Sgshapiro port = sp->s_port; 7275132943Sgshapiro# endif /* NO_GETSERVBYNAME */ 7276132943Sgshapiro } 7277132943Sgshapiro *at++ = '@'; 7278132943Sgshapiro if (*at == '[') 7279132943Sgshapiro { 7280132943Sgshapiro char *end; 7281132943Sgshapiro 7282132943Sgshapiro end = strchr(at, ']'); 7283132943Sgshapiro if (end != NULL) 7284132943Sgshapiro { 7285132943Sgshapiro bool found = false; 7286132943Sgshapiro# if NETINET 7287132943Sgshapiro unsigned long hid = INADDR_NONE; 7288132943Sgshapiro# endif /* NETINET */ 7289132943Sgshapiro# if NETINET6 7290132943Sgshapiro struct sockaddr_in6 hid6; 7291132943Sgshapiro# endif /* NETINET6 */ 7292132943Sgshapiro 7293132943Sgshapiro *end = '\0'; 7294132943Sgshapiro# if NETINET 7295132943Sgshapiro if (addr.sa.sa_family == AF_INET && 7296132943Sgshapiro (hid = inet_addr(&at[1])) != INADDR_NONE) 7297132943Sgshapiro { 7298132943Sgshapiro addr.sin.sin_addr.s_addr = hid; 7299132943Sgshapiro addr.sin.sin_port = port; 7300132943Sgshapiro found = true; 7301132943Sgshapiro } 7302132943Sgshapiro# endif /* NETINET */ 7303132943Sgshapiro# if NETINET6 7304132943Sgshapiro (void) memset(&hid6, '\0', sizeof hid6); 7305132943Sgshapiro if (addr.sa.sa_family == AF_INET6 && 7306132943Sgshapiro anynet_pton(AF_INET6, &at[1], 7307132943Sgshapiro &hid6.sin6_addr) == 1) 7308132943Sgshapiro { 7309132943Sgshapiro addr.sin6.sin6_addr = hid6.sin6_addr; 7310132943Sgshapiro addr.sin6.sin6_port = port; 7311132943Sgshapiro found = true; 7312132943Sgshapiro } 7313132943Sgshapiro# endif /* NETINET6 */ 7314132943Sgshapiro *end = ']'; 7315132943Sgshapiro if (!found) 7316132943Sgshapiro { 7317132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7318132943Sgshapiro map->map_mname, at); 7319132943Sgshapiro return false; 7320132943Sgshapiro } 7321132943Sgshapiro } 7322132943Sgshapiro else 7323132943Sgshapiro { 7324132943Sgshapiro syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 7325132943Sgshapiro map->map_mname, at); 7326132943Sgshapiro return false; 7327132943Sgshapiro } 7328132943Sgshapiro } 7329132943Sgshapiro else 7330132943Sgshapiro { 7331132943Sgshapiro hp = sm_gethostbyname(at, addr.sa.sa_family); 7332132943Sgshapiro if (hp == NULL) 7333132943Sgshapiro { 7334132943Sgshapiro syserr("socket map \"%s\": Unknown host name %s", 7335132943Sgshapiro map->map_mname, at); 7336132943Sgshapiro return false; 7337132943Sgshapiro } 7338132943Sgshapiro addr.sa.sa_family = hp->h_addrtype; 7339132943Sgshapiro switch (hp->h_addrtype) 7340132943Sgshapiro { 7341132943Sgshapiro# if NETINET 7342132943Sgshapiro case AF_INET: 7343132943Sgshapiro memmove(&addr.sin.sin_addr, 7344132943Sgshapiro hp->h_addr, INADDRSZ); 7345132943Sgshapiro addr.sin.sin_port = port; 7346132943Sgshapiro addrlen = sizeof (struct sockaddr_in); 7347132943Sgshapiro addrno = 1; 7348132943Sgshapiro break; 7349132943Sgshapiro# endif /* NETINET */ 7350132943Sgshapiro 7351132943Sgshapiro# if NETINET6 7352132943Sgshapiro case AF_INET6: 7353132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7354132943Sgshapiro hp->h_addr, IN6ADDRSZ); 7355132943Sgshapiro addr.sin6.sin6_port = port; 7356132943Sgshapiro addrlen = sizeof (struct sockaddr_in6); 7357132943Sgshapiro addrno = 1; 7358132943Sgshapiro break; 7359132943Sgshapiro# endif /* NETINET6 */ 7360132943Sgshapiro 7361132943Sgshapiro default: 7362132943Sgshapiro syserr("socket map \"%s\": Unknown protocol for %s (%d)", 7363132943Sgshapiro map->map_mname, at, hp->h_addrtype); 7364132943Sgshapiro# if NETINET6 7365132943Sgshapiro freehostent(hp); 7366132943Sgshapiro# endif /* NETINET6 */ 7367132943Sgshapiro return false; 7368132943Sgshapiro } 7369132943Sgshapiro } 7370132943Sgshapiro } 7371132943Sgshapiro else 7372132943Sgshapiro# endif /* NETINET || NETINET6 */ 7373132943Sgshapiro { 7374132943Sgshapiro syserr("socket map \"%s\": unknown socket protocol", 7375132943Sgshapiro map->map_mname); 7376132943Sgshapiro return false; 7377132943Sgshapiro } 7378132943Sgshapiro 7379132943Sgshapiro /* nope, actually connecting */ 7380132943Sgshapiro for (;;) 7381132943Sgshapiro { 7382132943Sgshapiro sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 7383132943Sgshapiro if (sock < 0) 7384132943Sgshapiro { 7385132943Sgshapiro save_errno = errno; 7386132943Sgshapiro if (tTd(38, 5)) 7387132943Sgshapiro sm_dprintf("socket map \"%s\": error creating socket: %s\n", 7388132943Sgshapiro map->map_mname, 7389132943Sgshapiro sm_errstring(save_errno)); 7390132943Sgshapiro# if NETINET6 7391132943Sgshapiro if (hp != NULL) 7392132943Sgshapiro freehostent(hp); 7393132943Sgshapiro# endif /* NETINET6 */ 7394132943Sgshapiro return false; 7395132943Sgshapiro } 7396132943Sgshapiro 7397132943Sgshapiro if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 7398132943Sgshapiro break; 7399132943Sgshapiro 7400132943Sgshapiro /* couldn't connect.... try next address */ 7401132943Sgshapiro save_errno = errno; 7402132943Sgshapiro p = CurHostName; 7403132943Sgshapiro CurHostName = at; 7404132943Sgshapiro if (tTd(38, 5)) 7405132943Sgshapiro sm_dprintf("socket_open (%s): open %s failed: %s\n", 7406132943Sgshapiro map->map_mname, at, sm_errstring(save_errno)); 7407132943Sgshapiro CurHostName = p; 7408132943Sgshapiro (void) close(sock); 7409132943Sgshapiro 7410132943Sgshapiro /* try next address */ 7411132943Sgshapiro if (hp != NULL && hp->h_addr_list[addrno] != NULL) 7412132943Sgshapiro { 7413132943Sgshapiro switch (addr.sa.sa_family) 7414132943Sgshapiro { 7415132943Sgshapiro# if NETINET 7416132943Sgshapiro case AF_INET: 7417132943Sgshapiro memmove(&addr.sin.sin_addr, 7418132943Sgshapiro hp->h_addr_list[addrno++], 7419132943Sgshapiro INADDRSZ); 7420132943Sgshapiro break; 7421132943Sgshapiro# endif /* NETINET */ 7422132943Sgshapiro 7423132943Sgshapiro# if NETINET6 7424132943Sgshapiro case AF_INET6: 7425132943Sgshapiro memmove(&addr.sin6.sin6_addr, 7426132943Sgshapiro hp->h_addr_list[addrno++], 7427132943Sgshapiro IN6ADDRSZ); 7428132943Sgshapiro break; 7429132943Sgshapiro# endif /* NETINET6 */ 7430132943Sgshapiro 7431132943Sgshapiro default: 7432132943Sgshapiro if (tTd(38, 5)) 7433132943Sgshapiro sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 7434132943Sgshapiro map->map_mname, at, 7435132943Sgshapiro hp->h_addrtype); 7436132943Sgshapiro# if NETINET6 7437132943Sgshapiro freehostent(hp); 7438132943Sgshapiro# endif /* NETINET6 */ 7439132943Sgshapiro return false; 7440132943Sgshapiro } 7441132943Sgshapiro continue; 7442132943Sgshapiro } 7443132943Sgshapiro p = CurHostName; 7444132943Sgshapiro CurHostName = at; 7445132943Sgshapiro if (tTd(38, 5)) 7446132943Sgshapiro sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 7447132943Sgshapiro map->map_mname, sm_errstring(save_errno)); 7448132943Sgshapiro CurHostName = p; 7449132943Sgshapiro# if NETINET6 7450132943Sgshapiro if (hp != NULL) 7451132943Sgshapiro freehostent(hp); 7452132943Sgshapiro# endif /* NETINET6 */ 7453132943Sgshapiro return false; 7454132943Sgshapiro } 7455132943Sgshapiro# if NETINET6 7456132943Sgshapiro if (hp != NULL) 7457132943Sgshapiro { 7458132943Sgshapiro freehostent(hp); 7459132943Sgshapiro hp = NULL; 7460132943Sgshapiro } 7461132943Sgshapiro# endif /* NETINET6 */ 7462132943Sgshapiro if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 7463132943Sgshapiro SM_TIME_DEFAULT, 7464132943Sgshapiro (void *) &sock, 7465132943Sgshapiro SM_IO_RDWR, 7466132943Sgshapiro NULL)) == NULL) 7467132943Sgshapiro { 7468132943Sgshapiro close(sock); 7469132943Sgshapiro if (tTd(38, 2)) 7470132943Sgshapiro sm_dprintf("socket_open (%s): failed to create stream: %s\n", 7471132943Sgshapiro map->map_mname, sm_errstring(errno)); 7472132943Sgshapiro return false; 7473132943Sgshapiro } 7474132943Sgshapiro 7475132943Sgshapiro /* Save connection for reuse */ 7476132943Sgshapiro s->s_socketmap = map; 7477132943Sgshapiro return true; 7478132943Sgshapiro} 7479132943Sgshapiro 7480132943Sgshapiro/* 7481132943Sgshapiro** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 7482132943Sgshapiro** 7483132943Sgshapiro** Cache SOCKET connections based on the connection specifier 7484132943Sgshapiro** and PID so we don't have multiple connections open to 7485132943Sgshapiro** the same server for different maps. Need a separate connection 7486132943Sgshapiro** per PID since a parent process may close the map before the 7487132943Sgshapiro** child is done with it. 7488132943Sgshapiro** 7489132943Sgshapiro** Parameters: 7490132943Sgshapiro** conn -- SOCKET map connection specifier 7491132943Sgshapiro** 7492132943Sgshapiro** Returns: 7493132943Sgshapiro** Symbol table entry for the SOCKET connection. 7494132943Sgshapiro*/ 7495132943Sgshapiro 7496132943Sgshapirostatic STAB * 7497132943Sgshapirosocket_map_findconn(conn) 7498132943Sgshapiro const char *conn; 7499132943Sgshapiro{ 7500132943Sgshapiro char *nbuf; 7501132943Sgshapiro STAB *SM_NONVOLATILE s = NULL; 7502132943Sgshapiro 7503132943Sgshapiro nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 7504132943Sgshapiro SM_TRY 7505132943Sgshapiro s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 7506132943Sgshapiro SM_FINALLY 7507132943Sgshapiro sm_free(nbuf); 7508132943Sgshapiro SM_END_TRY 7509132943Sgshapiro return s; 7510132943Sgshapiro} 7511132943Sgshapiro 7512132943Sgshapiro/* 7513132943Sgshapiro** SOCKET_MAP_CLOSE -- close the socket 7514132943Sgshapiro*/ 7515132943Sgshapiro 7516132943Sgshapirovoid 7517132943Sgshapirosocket_map_close(map) 7518132943Sgshapiro MAP *map; 7519132943Sgshapiro{ 7520132943Sgshapiro STAB *s; 7521132943Sgshapiro MAP *smap; 7522132943Sgshapiro 7523132943Sgshapiro if (tTd(38, 20)) 7524132943Sgshapiro sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 7525132943Sgshapiro (long) CurrentPid); 7526132943Sgshapiro 7527132943Sgshapiro /* Check if already closed */ 7528132943Sgshapiro if (map->map_db1 == NULL) 7529132943Sgshapiro { 7530132943Sgshapiro if (tTd(38, 20)) 7531132943Sgshapiro sm_dprintf("socket_map_close(%s) already closed\n", 7532132943Sgshapiro map->map_file); 7533132943Sgshapiro return; 7534132943Sgshapiro } 7535132943Sgshapiro sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 7536132943Sgshapiro 7537132943Sgshapiro /* Mark all the maps that share the connection as closed */ 7538132943Sgshapiro s = socket_map_findconn(map->map_file); 7539132943Sgshapiro smap = s->s_socketmap; 7540132943Sgshapiro while (smap != NULL) 7541132943Sgshapiro { 7542132943Sgshapiro MAP *next; 7543132943Sgshapiro 7544132943Sgshapiro if (tTd(38, 2) && smap != map) 7545132943Sgshapiro sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 7546132943Sgshapiro map->map_mname, smap->map_mname); 7547132943Sgshapiro 7548132943Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 7549132943Sgshapiro smap->map_db1 = NULL; 7550132943Sgshapiro next = smap->socket_map_next; 7551132943Sgshapiro smap->socket_map_next = NULL; 7552132943Sgshapiro smap = next; 7553132943Sgshapiro } 7554132943Sgshapiro s->s_socketmap = NULL; 7555132943Sgshapiro} 7556132943Sgshapiro 7557132943Sgshapiro/* 7558132943Sgshapiro** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 7559132943Sgshapiro*/ 7560132943Sgshapiro 7561132943Sgshapirochar * 7562132943Sgshapirosocket_map_lookup(map, name, av, statp) 7563132943Sgshapiro MAP *map; 7564132943Sgshapiro char *name; 7565132943Sgshapiro char **av; 7566132943Sgshapiro int *statp; 7567132943Sgshapiro{ 7568132943Sgshapiro unsigned int nettolen, replylen, recvlen; 7569147078Sgshapiro char *replybuf, *rval, *value, *status, *key; 7570132943Sgshapiro SM_FILE_T *f; 7571147078Sgshapiro char keybuf[MAXNAME + 1]; 7572132943Sgshapiro 7573132943Sgshapiro replybuf = NULL; 7574132943Sgshapiro rval = NULL; 7575132943Sgshapiro f = (SM_FILE_T *)map->map_db1; 7576132943Sgshapiro if (tTd(38, 20)) 7577132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s) %s\n", 7578132943Sgshapiro map->map_mname, name, map->map_file); 7579132943Sgshapiro 7580147078Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 7581147078Sgshapiro { 7582147078Sgshapiro nettolen = strlen(name); 7583147078Sgshapiro if (nettolen > sizeof keybuf - 1) 7584147078Sgshapiro nettolen = sizeof keybuf - 1; 7585147078Sgshapiro memmove(keybuf, name, nettolen); 7586147078Sgshapiro keybuf[nettolen] = '\0'; 7587147078Sgshapiro makelower(keybuf); 7588147078Sgshapiro key = keybuf; 7589147078Sgshapiro } 7590147078Sgshapiro else 7591147078Sgshapiro key = name; 7592147078Sgshapiro 7593147078Sgshapiro nettolen = strlen(map->map_mname) + 1 + strlen(key); 7594132943Sgshapiro SM_ASSERT(nettolen > strlen(map->map_mname)); 7595147078Sgshapiro SM_ASSERT(nettolen > strlen(key)); 7596132943Sgshapiro if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 7597147078Sgshapiro nettolen, map->map_mname, key) == SM_IO_EOF) || 7598132943Sgshapiro (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 7599132943Sgshapiro (sm_io_error(f))) 7600132943Sgshapiro { 7601132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 7602132943Sgshapiro map->map_mname); 7603132943Sgshapiro *statp = EX_TEMPFAIL; 7604132943Sgshapiro goto errcl; 7605132943Sgshapiro } 7606132943Sgshapiro 7607132943Sgshapiro if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) 7608132943Sgshapiro { 7609132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", 7610132943Sgshapiro map->map_mname); 7611132943Sgshapiro *statp = EX_TEMPFAIL; 7612132943Sgshapiro goto errcl; 7613132943Sgshapiro } 7614132943Sgshapiro if (replylen > SOCKETMAP_MAXL) 7615132943Sgshapiro { 7616132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 7617132943Sgshapiro map->map_mname, replylen); 7618132943Sgshapiro *statp = EX_TEMPFAIL; 7619132943Sgshapiro goto errcl; 7620132943Sgshapiro } 7621132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 7622132943Sgshapiro { 7623132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 7624132943Sgshapiro map->map_mname); 7625132943Sgshapiro *statp = EX_TEMPFAIL; 7626132943Sgshapiro goto error; 7627132943Sgshapiro } 7628132943Sgshapiro 7629132943Sgshapiro replybuf = (char *) sm_malloc(replylen + 1); 7630132943Sgshapiro if (replybuf == NULL) 7631132943Sgshapiro { 7632132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 7633132943Sgshapiro map->map_mname, replylen + 1); 7634132943Sgshapiro *statp = EX_OSERR; 7635132943Sgshapiro goto error; 7636132943Sgshapiro } 7637132943Sgshapiro 7638132943Sgshapiro recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 7639132943Sgshapiro if (recvlen < replylen) 7640132943Sgshapiro { 7641132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 7642132943Sgshapiro map->map_mname, recvlen, replylen); 7643132943Sgshapiro *statp = EX_TEMPFAIL; 7644132943Sgshapiro goto errcl; 7645132943Sgshapiro } 7646132943Sgshapiro if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 7647132943Sgshapiro { 7648132943Sgshapiro syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 7649132943Sgshapiro map->map_mname); 7650132943Sgshapiro *statp = EX_TEMPFAIL; 7651132943Sgshapiro goto errcl; 7652132943Sgshapiro } 7653132943Sgshapiro status = replybuf; 7654132943Sgshapiro replybuf[recvlen] = '\0'; 7655132943Sgshapiro value = strchr(replybuf, ' '); 7656132943Sgshapiro if (value != NULL) 7657132943Sgshapiro { 7658132943Sgshapiro *value = '\0'; 7659132943Sgshapiro value++; 7660132943Sgshapiro } 7661132943Sgshapiro if (strcmp(status, "OK") == 0) 7662132943Sgshapiro { 7663132943Sgshapiro *statp = EX_OK; 7664132943Sgshapiro 7665132943Sgshapiro /* collect the return value */ 7666132943Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 7667147078Sgshapiro rval = map_rewrite(map, key, strlen(key), NULL); 7668132943Sgshapiro else 7669132943Sgshapiro rval = map_rewrite(map, value, strlen(value), av); 7670132943Sgshapiro } 7671132943Sgshapiro else if (strcmp(status, "NOTFOUND") == 0) 7672132943Sgshapiro { 7673132943Sgshapiro *statp = EX_NOTFOUND; 7674132943Sgshapiro if (tTd(38, 20)) 7675132943Sgshapiro sm_dprintf("socket_map_lookup(%s): %s not found\n", 7676147078Sgshapiro map->map_mname, key); 7677132943Sgshapiro } 7678132943Sgshapiro else 7679132943Sgshapiro { 7680132943Sgshapiro if (tTd(38, 5)) 7681132943Sgshapiro sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 7682147078Sgshapiro map->map_mname, key, status, 7683132943Sgshapiro value ? value : ""); 7684132943Sgshapiro if ((strcmp(status, "TEMP") == 0) || 7685132943Sgshapiro (strcmp(status, "TIMEOUT") == 0)) 7686132943Sgshapiro *statp = EX_TEMPFAIL; 7687132943Sgshapiro else if(strcmp(status, "PERM") == 0) 7688132943Sgshapiro *statp = EX_UNAVAILABLE; 7689132943Sgshapiro else 7690132943Sgshapiro *statp = EX_PROTOCOL; 7691132943Sgshapiro } 7692132943Sgshapiro 7693132943Sgshapiro if (replybuf != NULL) 7694132943Sgshapiro sm_free(replybuf); 7695132943Sgshapiro return rval; 7696132943Sgshapiro 7697132943Sgshapiro errcl: 7698132943Sgshapiro socket_map_close(map); 7699132943Sgshapiro error: 7700132943Sgshapiro if (replybuf != NULL) 7701132943Sgshapiro sm_free(replybuf); 7702132943Sgshapiro return rval; 7703132943Sgshapiro} 7704132943Sgshapiro#endif /* SOCKETMAP */ 7705