map.c revision 120256
138032Speter/* 2120256Sgshapiro * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1992, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 1538032Speter 16120256SgshapiroSM_RCSID("@(#)$Id: map.c,v 8.645.2.10 2003/07/24 18:24:17 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 *)); 6964562Sgshapiro 7090792Sgshapiro/* default error message for trying to open a map in write mode */ 7190792Sgshapiro#ifdef ENOSYS 7290792Sgshapiro# define SM_EMAPCANTWRITE ENOSYS 7390792Sgshapiro#else /* ENOSYS */ 7490792Sgshapiro# ifdef EFTYPE 7590792Sgshapiro# define SM_EMAPCANTWRITE EFTYPE 7690792Sgshapiro# else /* EFTYPE */ 7790792Sgshapiro# define SM_EMAPCANTWRITE ENXIO 7890792Sgshapiro# endif /* EFTYPE */ 7990792Sgshapiro#endif /* ENOSYS */ 8090792Sgshapiro 8138032Speter/* 8238032Speter** MAP.C -- implementations for various map classes. 8338032Speter** 8438032Speter** Each map class implements a series of functions: 8538032Speter** 8638032Speter** bool map_parse(MAP *map, char *args) 8790792Sgshapiro** Parse the arguments from the config file. Return true 8890792Sgshapiro** if they were ok, false otherwise. Fill in map with the 8938032Speter** values. 9038032Speter** 9138032Speter** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 9238032Speter** Look up the key in the given map. If found, do any 9338032Speter** rewriting the map wants (including "args" if desired) 9438032Speter** and return the value. Set *pstat to the appropriate status 9538032Speter** on error and return NULL. Args will be NULL if called 9638032Speter** from the alias routines, although this should probably 9738032Speter** not be relied upon. It is suggested you call map_rewrite 9838032Speter** to return the results -- it takes care of null termination 9938032Speter** and uses a dynamically expanded buffer as needed. 10038032Speter** 10138032Speter** void map_store(MAP *map, char *key, char *value) 10238032Speter** Store the key:value pair in the map. 10338032Speter** 10438032Speter** bool map_open(MAP *map, int mode) 10538032Speter** Open the map for the indicated mode. Mode should 10690792Sgshapiro** be either O_RDONLY or O_RDWR. Return true if it 10790792Sgshapiro** was opened successfully, false otherwise. If the open 10890792Sgshapiro** failed and the MF_OPTIONAL flag is not set, it should 10938032Speter** also print an error. If the MF_ALIAS bit is set 11038032Speter** and this map class understands the @:@ convention, it 11138032Speter** should call aliaswait() before returning. 11238032Speter** 11338032Speter** void map_close(MAP *map) 11438032Speter** Close the map. 11538032Speter** 11638032Speter** This file also includes the implementation for getcanonname. 11738032Speter** It is currently implemented in a pretty ad-hoc manner; it ought 11838032Speter** to be more properly integrated into the map structure. 11938032Speter*/ 12038032Speter 12138032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 12238032Speter# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 12364562Sgshapiro#else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 12438032Speter# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 12564562Sgshapiro#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 12638032Speter 12790792Sgshapiro/* 12838032Speter** MAP_PARSEARGS -- parse config line arguments for database lookup 12938032Speter** 13038032Speter** This is a generic version of the map_parse method. 13138032Speter** 13238032Speter** Parameters: 13338032Speter** map -- the map being initialized. 13438032Speter** ap -- a pointer to the args on the config line. 13538032Speter** 13638032Speter** Returns: 13790792Sgshapiro** true -- if everything parsed OK. 13890792Sgshapiro** false -- otherwise. 13938032Speter** 14038032Speter** Side Effects: 14138032Speter** null terminates the filename; stores it in map 14238032Speter*/ 14338032Speter 14438032Speterbool 14538032Spetermap_parseargs(map, ap) 14638032Speter MAP *map; 14738032Speter char *ap; 14838032Speter{ 14938032Speter register char *p = ap; 15038032Speter 15164562Sgshapiro /* 15290792Sgshapiro ** There is no check whether there is really an argument, 15390792Sgshapiro ** but that's not important enough to warrant extra code. 15464562Sgshapiro */ 15590792Sgshapiro 15690792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 15764562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 15838032Speter for (;;) 15938032Speter { 16038032Speter while (isascii(*p) && isspace(*p)) 16138032Speter p++; 16238032Speter if (*p != '-') 16338032Speter break; 16438032Speter switch (*++p) 16538032Speter { 16638032Speter case 'N': 16738032Speter map->map_mflags |= MF_INCLNULL; 16838032Speter map->map_mflags &= ~MF_TRY0NULL; 16938032Speter break; 17038032Speter 17138032Speter case 'O': 17238032Speter map->map_mflags &= ~MF_TRY1NULL; 17338032Speter break; 17438032Speter 17538032Speter case 'o': 17638032Speter map->map_mflags |= MF_OPTIONAL; 17738032Speter break; 17838032Speter 17938032Speter case 'f': 18038032Speter map->map_mflags |= MF_NOFOLDCASE; 18138032Speter break; 18238032Speter 18338032Speter case 'm': 18438032Speter map->map_mflags |= MF_MATCHONLY; 18538032Speter break; 18638032Speter 18738032Speter case 'A': 18838032Speter map->map_mflags |= MF_APPEND; 18938032Speter break; 19038032Speter 19138032Speter case 'q': 19238032Speter map->map_mflags |= MF_KEEPQUOTES; 19338032Speter break; 19438032Speter 19538032Speter case 'a': 19638032Speter map->map_app = ++p; 19738032Speter break; 19838032Speter 19938032Speter case 'T': 20038032Speter map->map_tapp = ++p; 20138032Speter break; 20238032Speter 20338032Speter case 'k': 20438032Speter while (isascii(*++p) && isspace(*p)) 20538032Speter continue; 20638032Speter map->map_keycolnm = p; 20738032Speter break; 20838032Speter 20938032Speter case 'v': 21038032Speter while (isascii(*++p) && isspace(*p)) 21138032Speter continue; 21238032Speter map->map_valcolnm = p; 21338032Speter break; 21438032Speter 21538032Speter case 'z': 21638032Speter if (*++p != '\\') 21738032Speter map->map_coldelim = *p; 21838032Speter else 21938032Speter { 22038032Speter switch (*++p) 22138032Speter { 22238032Speter case 'n': 22338032Speter map->map_coldelim = '\n'; 22438032Speter break; 22538032Speter 22638032Speter case 't': 22738032Speter map->map_coldelim = '\t'; 22838032Speter break; 22938032Speter 23038032Speter default: 23138032Speter map->map_coldelim = '\\'; 23238032Speter } 23338032Speter } 23438032Speter break; 23538032Speter 23638032Speter case 't': 23738032Speter map->map_mflags |= MF_NODEFER; 23838032Speter break; 23938032Speter 24064562Sgshapiro 24164562Sgshapiro case 'S': 24264562Sgshapiro map->map_spacesub = *++p; 24338032Speter break; 24438032Speter 24564562Sgshapiro case 'D': 24664562Sgshapiro map->map_mflags |= MF_DEFER; 24738032Speter break; 24864562Sgshapiro 24964562Sgshapiro default: 25064562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 25164562Sgshapiro break; 25238032Speter } 25338032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 25438032Speter p++; 25538032Speter if (*p != '\0') 25638032Speter *p++ = '\0'; 25738032Speter } 25838032Speter if (map->map_app != NULL) 25938032Speter map->map_app = newstr(map->map_app); 26038032Speter if (map->map_tapp != NULL) 26138032Speter map->map_tapp = newstr(map->map_tapp); 26238032Speter if (map->map_keycolnm != NULL) 26338032Speter map->map_keycolnm = newstr(map->map_keycolnm); 26438032Speter if (map->map_valcolnm != NULL) 26538032Speter map->map_valcolnm = newstr(map->map_valcolnm); 26638032Speter 26738032Speter if (*p != '\0') 26838032Speter { 26938032Speter map->map_file = p; 27038032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 27138032Speter p++; 27238032Speter if (*p != '\0') 27338032Speter *p++ = '\0'; 27438032Speter map->map_file = newstr(map->map_file); 27538032Speter } 27638032Speter 27738032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 27838032Speter p++; 27938032Speter if (*p != '\0') 28038032Speter map->map_rebuild = newstr(p); 28138032Speter 28238032Speter if (map->map_file == NULL && 28338032Speter !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 28438032Speter { 28538032Speter syserr("No file name for %s map %s", 28638032Speter map->map_class->map_cname, map->map_mname); 28790792Sgshapiro return false; 28838032Speter } 28990792Sgshapiro return true; 29038032Speter} 29190792Sgshapiro/* 29238032Speter** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 29338032Speter** 29438032Speter** It also adds the map_app string. It can be used as a utility 29538032Speter** in the map_lookup method. 29638032Speter** 29738032Speter** Parameters: 29838032Speter** map -- the map that causes this. 29938032Speter** s -- the string to rewrite, NOT necessarily null terminated. 30038032Speter** slen -- the length of s. 30138032Speter** av -- arguments to interpolate into buf. 30238032Speter** 30338032Speter** Returns: 30438032Speter** Pointer to rewritten result. This is static data that 30538032Speter** should be copied if it is to be saved! 30638032Speter*/ 30738032Speter 30838032Speterchar * 30938032Spetermap_rewrite(map, s, slen, av) 31038032Speter register MAP *map; 31138032Speter register const char *s; 31238032Speter size_t slen; 31338032Speter char **av; 31438032Speter{ 31538032Speter register char *bp; 31638032Speter register char c; 31738032Speter char **avp; 31838032Speter register char *ap; 31938032Speter size_t l; 32038032Speter size_t len; 32138032Speter static size_t buflen = 0; 32238032Speter static char *buf = NULL; 32338032Speter 32438032Speter if (tTd(39, 1)) 32538032Speter { 32690792Sgshapiro sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s); 32738032Speter if (av == NULL) 32890792Sgshapiro sm_dprintf(" (nullv)"); 32938032Speter else 33038032Speter { 33138032Speter for (avp = av; *avp != NULL; avp++) 33290792Sgshapiro sm_dprintf("\n\t%s", *avp); 33338032Speter } 33490792Sgshapiro sm_dprintf("\n"); 33538032Speter } 33638032Speter 33738032Speter /* count expected size of output (can safely overestimate) */ 33838032Speter l = len = slen; 33938032Speter if (av != NULL) 34038032Speter { 34138032Speter const char *sp = s; 34238032Speter 34338032Speter while (l-- > 0 && (c = *sp++) != '\0') 34438032Speter { 34538032Speter if (c != '%') 34638032Speter continue; 34738032Speter if (l-- <= 0) 34838032Speter break; 34938032Speter c = *sp++; 35038032Speter if (!(isascii(c) && isdigit(c))) 35138032Speter continue; 35238032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 35338032Speter continue; 35438032Speter if (*avp == NULL) 35538032Speter continue; 35638032Speter len += strlen(*avp); 35738032Speter } 35838032Speter } 35938032Speter if (map->map_app != NULL) 36038032Speter len += strlen(map->map_app); 36138032Speter if (buflen < ++len) 36238032Speter { 36338032Speter /* need to malloc additional space */ 36438032Speter buflen = len; 36538032Speter if (buf != NULL) 36677349Sgshapiro sm_free(buf); 36790792Sgshapiro buf = sm_pmalloc_x(buflen); 36838032Speter } 36938032Speter 37038032Speter bp = buf; 37138032Speter if (av == NULL) 37238032Speter { 37364562Sgshapiro memmove(bp, s, slen); 37438032Speter bp += slen; 37564562Sgshapiro 37664562Sgshapiro /* assert(len > slen); */ 37764562Sgshapiro len -= slen; 37838032Speter } 37938032Speter else 38038032Speter { 38138032Speter while (slen-- > 0 && (c = *s++) != '\0') 38238032Speter { 38338032Speter if (c != '%') 38438032Speter { 38538032Speter pushc: 386120256Sgshapiro if (len-- <= 1) 38790792Sgshapiro break; 38838032Speter *bp++ = c; 38938032Speter continue; 39038032Speter } 39138032Speter if (slen-- <= 0 || (c = *s++) == '\0') 39238032Speter c = '%'; 39338032Speter if (c == '%') 39438032Speter goto pushc; 39538032Speter if (!(isascii(c) && isdigit(c))) 39638032Speter { 397120256Sgshapiro if (len-- <= 1) 398120256Sgshapiro break; 39938032Speter *bp++ = '%'; 40038032Speter goto pushc; 40138032Speter } 40238032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 40338032Speter continue; 40438032Speter if (*avp == NULL) 40538032Speter continue; 40638032Speter 40738032Speter /* transliterate argument into output string */ 40864562Sgshapiro for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len) 40938032Speter *bp++ = c; 41038032Speter } 41138032Speter } 41264562Sgshapiro if (map->map_app != NULL && len > 0) 41390792Sgshapiro (void) sm_strlcpy(bp, map->map_app, len); 41438032Speter else 41538032Speter *bp = '\0'; 41638032Speter if (tTd(39, 1)) 41790792Sgshapiro sm_dprintf("map_rewrite => %s\n", buf); 41838032Speter return buf; 41938032Speter} 42090792Sgshapiro/* 42164562Sgshapiro** INITMAPS -- rebuild alias maps 42238032Speter** 42338032Speter** Parameters: 42464562Sgshapiro** none. 42538032Speter** 42638032Speter** Returns: 42738032Speter** none. 42838032Speter*/ 42938032Speter 43038032Spetervoid 43164562Sgshapiroinitmaps() 43238032Speter{ 43338032Speter#if XDEBUG 43438032Speter checkfd012("entering initmaps"); 43564562Sgshapiro#endif /* XDEBUG */ 43638032Speter stabapply(map_init, 0); 43738032Speter#if XDEBUG 43838032Speter checkfd012("exiting initmaps"); 43964562Sgshapiro#endif /* XDEBUG */ 44038032Speter} 44190792Sgshapiro/* 44264562Sgshapiro** MAP_INIT -- rebuild a map 44364562Sgshapiro** 44464562Sgshapiro** Parameters: 44564562Sgshapiro** s -- STAB entry: if map: try to rebuild 44664562Sgshapiro** unused -- unused variable 44764562Sgshapiro** 44864562Sgshapiro** Returns: 44964562Sgshapiro** none. 45064562Sgshapiro** 45164562Sgshapiro** Side Effects: 45264562Sgshapiro** will close already open rebuildable map. 45364562Sgshapiro*/ 45438032Speter 45564562Sgshapiro/* ARGSUSED1 */ 45664562Sgshapirostatic void 45764562Sgshapiromap_init(s, unused) 45838032Speter register STAB *s; 45964562Sgshapiro int unused; 46038032Speter{ 46138032Speter register MAP *map; 46238032Speter 46338032Speter /* has to be a map */ 46490792Sgshapiro if (s->s_symtype != ST_MAP) 46538032Speter return; 46638032Speter 46738032Speter map = &s->s_map; 46838032Speter if (!bitset(MF_VALID, map->map_mflags)) 46938032Speter return; 47038032Speter 47138032Speter if (tTd(38, 2)) 47290792Sgshapiro sm_dprintf("map_init(%s:%s, %s)\n", 47338032Speter map->map_class->map_cname == NULL ? "NULL" : 47438032Speter map->map_class->map_cname, 47538032Speter map->map_mname == NULL ? "NULL" : map->map_mname, 47664562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 47738032Speter 47864562Sgshapiro if (!bitset(MF_ALIAS, map->map_mflags) || 47964562Sgshapiro !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 48038032Speter { 48138032Speter if (tTd(38, 3)) 48290792Sgshapiro sm_dprintf("\tnot rebuildable\n"); 48338032Speter return; 48438032Speter } 48538032Speter 48638032Speter /* if already open, close it (for nested open) */ 48738032Speter if (bitset(MF_OPEN, map->map_mflags)) 48838032Speter { 48977349Sgshapiro map->map_mflags |= MF_CLOSING; 49038032Speter map->map_class->map_close(map); 49177349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 49238032Speter } 49338032Speter 49490792Sgshapiro (void) rebuildaliases(map, false); 49564562Sgshapiro return; 49664562Sgshapiro} 49790792Sgshapiro/* 49864562Sgshapiro** OPENMAP -- open a map 49964562Sgshapiro** 50064562Sgshapiro** Parameters: 50164562Sgshapiro** map -- map to open (it must not be open). 50264562Sgshapiro** 50364562Sgshapiro** Returns: 50464562Sgshapiro** whether open succeeded. 50564562Sgshapiro*/ 50664562Sgshapiro 50764562Sgshapirobool 50864562Sgshapiroopenmap(map) 50964562Sgshapiro MAP *map; 51064562Sgshapiro{ 51190792Sgshapiro bool restore = false; 51264562Sgshapiro bool savehold = HoldErrs; 51364562Sgshapiro bool savequick = QuickAbort; 51464562Sgshapiro int saveerrors = Errors; 51564562Sgshapiro 51664562Sgshapiro if (!bitset(MF_VALID, map->map_mflags)) 51790792Sgshapiro return false; 51864562Sgshapiro 51964562Sgshapiro /* better safe than sorry... */ 52064562Sgshapiro if (bitset(MF_OPEN, map->map_mflags)) 52190792Sgshapiro return true; 52264562Sgshapiro 52364562Sgshapiro /* Don't send a map open error out via SMTP */ 52464562Sgshapiro if ((OnlyOneError || QuickAbort) && 52564562Sgshapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 52638032Speter { 52790792Sgshapiro restore = true; 52890792Sgshapiro HoldErrs = true; 52990792Sgshapiro QuickAbort = false; 53038032Speter } 53138032Speter 53264562Sgshapiro errno = 0; 53338032Speter if (map->map_class->map_open(map, O_RDONLY)) 53438032Speter { 53538032Speter if (tTd(38, 4)) 53690792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: valid\n", 53738032Speter map->map_class->map_cname == NULL ? "NULL" : 53838032Speter map->map_class->map_cname, 53938032Speter map->map_mname == NULL ? "NULL" : 54038032Speter map->map_mname, 54138032Speter map->map_file == NULL ? "NULL" : 54238032Speter map->map_file); 54338032Speter map->map_mflags |= MF_OPEN; 54490792Sgshapiro map->map_pid = CurrentPid; 54538032Speter } 54638032Speter else 54738032Speter { 54838032Speter if (tTd(38, 4)) 54990792Sgshapiro sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n", 55038032Speter map->map_class->map_cname == NULL ? "NULL" : 55138032Speter map->map_class->map_cname, 55238032Speter map->map_mname == NULL ? "NULL" : 55338032Speter map->map_mname, 55438032Speter map->map_file == NULL ? "NULL" : 55538032Speter map->map_file, 55664562Sgshapiro errno == 0 ? "" : ": ", 55790792Sgshapiro errno == 0 ? "" : sm_errstring(errno)); 55838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 55938032Speter { 56038032Speter extern MAPCLASS BogusMapClass; 56138032Speter 56290792Sgshapiro map->map_orgclass = map->map_class; 56338032Speter map->map_class = &BogusMapClass; 56490792Sgshapiro map->map_mflags |= MF_OPEN|MF_OPENBOGUS; 56590792Sgshapiro map->map_pid = CurrentPid; 56638032Speter } 56764562Sgshapiro else 56864562Sgshapiro { 56964562Sgshapiro /* don't try again */ 57064562Sgshapiro map->map_mflags &= ~MF_VALID; 57164562Sgshapiro } 57238032Speter } 57364562Sgshapiro 57464562Sgshapiro if (restore) 57564562Sgshapiro { 57664562Sgshapiro Errors = saveerrors; 57764562Sgshapiro HoldErrs = savehold; 57864562Sgshapiro QuickAbort = savequick; 57964562Sgshapiro } 58064562Sgshapiro 58164562Sgshapiro return bitset(MF_OPEN, map->map_mflags); 58238032Speter} 58390792Sgshapiro/* 58442575Speter** CLOSEMAPS -- close all open maps opened by the current pid. 58542575Speter** 58642575Speter** Parameters: 58790792Sgshapiro** bogus -- only close bogus maps. 58842575Speter** 58942575Speter** Returns: 59042575Speter** none. 59142575Speter*/ 59242575Speter 59342575Spetervoid 59490792Sgshapiroclosemaps(bogus) 59590792Sgshapiro bool bogus; 59642575Speter{ 59790792Sgshapiro stabapply(map_close, bogus); 59842575Speter} 59990792Sgshapiro/* 60064562Sgshapiro** MAP_CLOSE -- close a map opened by the current pid. 60164562Sgshapiro** 60264562Sgshapiro** Parameters: 60390792Sgshapiro** s -- STAB entry: if map: try to close 60490792Sgshapiro** bogus -- only close bogus maps or MCF_NOTPERSIST maps. 60564562Sgshapiro** 60664562Sgshapiro** Returns: 60764562Sgshapiro** none. 60864562Sgshapiro*/ 60942575Speter 61042575Speter/* ARGSUSED1 */ 61164562Sgshapirostatic void 61290792Sgshapiromap_close(s, bogus) 61342575Speter register STAB *s; 61490792Sgshapiro int bogus; /* int because of stabapply(), used as bool */ 61542575Speter{ 61642575Speter MAP *map; 61790792Sgshapiro extern MAPCLASS BogusMapClass; 61842575Speter 61990792Sgshapiro if (s->s_symtype != ST_MAP) 62042575Speter return; 62164562Sgshapiro 62242575Speter map = &s->s_map; 62342575Speter 62490792Sgshapiro /* 62590792Sgshapiro ** close the map iff: 62690792Sgshapiro ** it is valid and open and opened by this process 62790792Sgshapiro ** and (!bogus or it's a bogus map or it is not persistent) 62890792Sgshapiro ** negate this: return iff 62990792Sgshapiro ** it is not valid or it is not open or not opened by this process 63090792Sgshapiro ** or (bogus and it's not a bogus map and it's not not-persistent) 63190792Sgshapiro */ 63290792Sgshapiro 63342575Speter if (!bitset(MF_VALID, map->map_mflags) || 63442575Speter !bitset(MF_OPEN, map->map_mflags) || 63577349Sgshapiro bitset(MF_CLOSING, map->map_mflags) || 63690792Sgshapiro map->map_pid != CurrentPid || 63790792Sgshapiro (bogus && map->map_class != &BogusMapClass && 63890792Sgshapiro !bitset(MCF_NOTPERSIST, map->map_class->map_cflags))) 63942575Speter return; 64064562Sgshapiro 64190792Sgshapiro if (map->map_class == &BogusMapClass && map->map_orgclass != NULL && 64290792Sgshapiro map->map_orgclass != &BogusMapClass) 64390792Sgshapiro map->map_class = map->map_orgclass; 64442575Speter if (tTd(38, 5)) 64590792Sgshapiro sm_dprintf("closemaps: closing %s (%s)\n", 64664562Sgshapiro map->map_mname == NULL ? "NULL" : map->map_mname, 64764562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 64864562Sgshapiro 64990792Sgshapiro if (!bitset(MF_OPENBOGUS, map->map_mflags)) 65090792Sgshapiro { 65190792Sgshapiro map->map_mflags |= MF_CLOSING; 65290792Sgshapiro map->map_class->map_close(map); 65390792Sgshapiro } 65490792Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING); 65542575Speter} 65690792Sgshapiro/* 65738032Speter** GETCANONNAME -- look up name using service switch 65838032Speter** 65938032Speter** Parameters: 66038032Speter** host -- the host name to look up. 66138032Speter** hbsize -- the size of the host buffer. 66238032Speter** trymx -- if set, try MX records. 66390792Sgshapiro** pttl -- pointer to return TTL (can be NULL). 66438032Speter** 66538032Speter** Returns: 66690792Sgshapiro** true -- if the host was found. 66790792Sgshapiro** false -- otherwise. 66838032Speter*/ 66938032Speter 67038032Speterbool 67190792Sgshapirogetcanonname(host, hbsize, trymx, pttl) 67238032Speter char *host; 67338032Speter int hbsize; 67438032Speter bool trymx; 67590792Sgshapiro int *pttl; 67638032Speter{ 67738032Speter int nmaps; 67838032Speter int mapno; 67990792Sgshapiro bool found = false; 68090792Sgshapiro bool got_tempfail = false; 68164562Sgshapiro auto int status; 68238032Speter char *maptype[MAXMAPSTACK]; 68338032Speter short mapreturn[MAXMAPACTIONS]; 68438032Speter 68538032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 68690792Sgshapiro if (pttl != 0) 68790792Sgshapiro *pttl = SM_DEFAULT_TTL; 68838032Speter for (mapno = 0; mapno < nmaps; mapno++) 68938032Speter { 69038032Speter int i; 69138032Speter 69238032Speter if (tTd(38, 20)) 69390792Sgshapiro sm_dprintf("getcanonname(%s), trying %s\n", 69438032Speter host, maptype[mapno]); 69538032Speter if (strcmp("files", maptype[mapno]) == 0) 69638032Speter { 69764562Sgshapiro found = text_getcanonname(host, hbsize, &status); 69838032Speter } 69990792Sgshapiro#if NIS 70038032Speter else if (strcmp("nis", maptype[mapno]) == 0) 70138032Speter { 70264562Sgshapiro found = nis_getcanonname(host, hbsize, &status); 70338032Speter } 70464562Sgshapiro#endif /* NIS */ 70590792Sgshapiro#if NISPLUS 70638032Speter else if (strcmp("nisplus", maptype[mapno]) == 0) 70738032Speter { 70864562Sgshapiro found = nisplus_getcanonname(host, hbsize, &status); 70938032Speter } 71064562Sgshapiro#endif /* NISPLUS */ 71138032Speter#if NAMED_BIND 71238032Speter else if (strcmp("dns", maptype[mapno]) == 0) 71338032Speter { 71490792Sgshapiro found = dns_getcanonname(host, hbsize, trymx, &status, pttl); 71538032Speter } 71664562Sgshapiro#endif /* NAMED_BIND */ 71738032Speter#if NETINFO 71838032Speter else if (strcmp("netinfo", maptype[mapno]) == 0) 71938032Speter { 72064562Sgshapiro found = ni_getcanonname(host, hbsize, &status); 72138032Speter } 72264562Sgshapiro#endif /* NETINFO */ 72338032Speter else 72438032Speter { 72590792Sgshapiro found = false; 72664562Sgshapiro status = EX_UNAVAILABLE; 72738032Speter } 72838032Speter 72938032Speter /* 73038032Speter ** Heuristic: if $m is not set, we are running during system 73138032Speter ** startup. In this case, when a name is apparently found 73238032Speter ** but has no dot, treat is as not found. This avoids 73338032Speter ** problems if /etc/hosts has no FQDN but is listed first 73438032Speter ** in the service switch. 73538032Speter */ 73638032Speter 73738032Speter if (found && 73838032Speter (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 73938032Speter break; 74038032Speter 74138032Speter /* see if we should continue */ 74264562Sgshapiro if (status == EX_TEMPFAIL) 74338032Speter { 74438032Speter i = MA_TRYAGAIN; 74590792Sgshapiro got_tempfail = true; 74638032Speter } 74764562Sgshapiro else if (status == EX_NOTFOUND) 74838032Speter i = MA_NOTFOUND; 74938032Speter else 75038032Speter i = MA_UNAVAIL; 75138032Speter if (bitset(1 << mapno, mapreturn[i])) 75238032Speter break; 75338032Speter } 75438032Speter 75538032Speter if (found) 75638032Speter { 75738032Speter char *d; 75838032Speter 75938032Speter if (tTd(38, 20)) 76090792Sgshapiro sm_dprintf("getcanonname(%s), found\n", host); 76138032Speter 76238032Speter /* 76338032Speter ** If returned name is still single token, compensate 76438032Speter ** by tagging on $m. This is because some sites set 76538032Speter ** up their DNS or NIS databases wrong. 76638032Speter */ 76738032Speter 76838032Speter if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 76938032Speter { 77038032Speter d = macvalue('m', CurEnv); 77138032Speter if (d != NULL && 77238032Speter hbsize > (int) (strlen(host) + strlen(d) + 1)) 77338032Speter { 77438032Speter if (host[strlen(host) - 1] != '.') 77590792Sgshapiro (void) sm_strlcat2(host, ".", d, 77690792Sgshapiro hbsize); 77790792Sgshapiro else 77890792Sgshapiro (void) sm_strlcat(host, d, hbsize); 77938032Speter } 78038032Speter else 78190792Sgshapiro return false; 78238032Speter } 78390792Sgshapiro return true; 78438032Speter } 78538032Speter 78638032Speter if (tTd(38, 20)) 78790792Sgshapiro sm_dprintf("getcanonname(%s), failed, status=%d\n", host, 78890792Sgshapiro status); 78938032Speter 79038032Speter if (got_tempfail) 79173188Sgshapiro SM_SET_H_ERRNO(TRY_AGAIN); 79238032Speter else 79373188Sgshapiro SM_SET_H_ERRNO(HOST_NOT_FOUND); 79490792Sgshapiro 79590792Sgshapiro return false; 79638032Speter} 79790792Sgshapiro/* 79838032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 79938032Speter** 80038032Speter** Parameters: 80138032Speter** name -- the name against which to match. 80273188Sgshapiro** dot -- where to reinsert '.' to get FQDN 80338032Speter** line -- the /etc/hosts line. 80438032Speter** cbuf -- the location to store the result. 80538032Speter** cbuflen -- the size of cbuf. 80638032Speter** 80738032Speter** Returns: 80890792Sgshapiro** true -- if the line matched the desired name. 80990792Sgshapiro** false -- otherwise. 81038032Speter*/ 81138032Speter 81264562Sgshapirostatic bool 81373188Sgshapiroextract_canonname(name, dot, line, cbuf, cbuflen) 81438032Speter char *name; 81573188Sgshapiro char *dot; 81638032Speter char *line; 81738032Speter char cbuf[]; 81838032Speter int cbuflen; 81938032Speter{ 82038032Speter int i; 82138032Speter char *p; 82290792Sgshapiro bool found = false; 82338032Speter 82438032Speter cbuf[0] = '\0'; 82538032Speter if (line[0] == '#') 82690792Sgshapiro return false; 82738032Speter 82838032Speter for (i = 1; ; i++) 82938032Speter { 83038032Speter char nbuf[MAXNAME + 1]; 83138032Speter 83238032Speter p = get_column(line, i, '\0', nbuf, sizeof nbuf); 83338032Speter if (p == NULL) 83438032Speter break; 83538032Speter if (*p == '\0') 83638032Speter continue; 83738032Speter if (cbuf[0] == '\0' || 83838032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 83938032Speter { 84090792Sgshapiro (void) sm_strlcpy(cbuf, p, cbuflen); 84138032Speter } 84290792Sgshapiro if (sm_strcasecmp(name, p) == 0) 84390792Sgshapiro found = true; 84473188Sgshapiro else if (dot != NULL) 84573188Sgshapiro { 84673188Sgshapiro /* try looking for the FQDN as well */ 84773188Sgshapiro *dot = '.'; 84890792Sgshapiro if (sm_strcasecmp(name, p) == 0) 84990792Sgshapiro found = true; 85073188Sgshapiro *dot = '\0'; 85173188Sgshapiro } 85238032Speter } 85338032Speter if (found && strchr(cbuf, '.') == NULL) 85438032Speter { 85538032Speter /* try to add a domain on the end of the name */ 85638032Speter char *domain = macvalue('m', CurEnv); 85738032Speter 85838032Speter if (domain != NULL && 85964562Sgshapiro strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 86038032Speter { 86164562Sgshapiro p = &cbuf[i]; 86238032Speter *p++ = '.'; 86390792Sgshapiro (void) sm_strlcpy(p, domain, cbuflen - i - 1); 86438032Speter } 86538032Speter } 86638032Speter return found; 86738032Speter} 86890792Sgshapiro 86990792Sgshapiro/* 87090792Sgshapiro** DNS modules 87190792Sgshapiro*/ 87290792Sgshapiro 87390792Sgshapiro#if NAMED_BIND 87490792Sgshapiro# if DNSMAP 87590792Sgshapiro 87690792Sgshapiro# include "sm_resolve.h" 87790792Sgshapiro# if NETINET || NETINET6 87890792Sgshapiro# include <arpa/inet.h> 87990792Sgshapiro# endif /* NETINET || NETINET6 */ 88090792Sgshapiro 88190792Sgshapiro/* 88290792Sgshapiro** DNS_MAP_OPEN -- stub to check proper value for dns map type 88390792Sgshapiro*/ 88490792Sgshapiro 88590792Sgshapirobool 88690792Sgshapirodns_map_open(map, mode) 88790792Sgshapiro MAP *map; 88890792Sgshapiro int mode; 88990792Sgshapiro{ 89090792Sgshapiro if (tTd(38,2)) 89190792Sgshapiro sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode); 89290792Sgshapiro 89390792Sgshapiro mode &= O_ACCMODE; 89490792Sgshapiro if (mode != O_RDONLY) 89590792Sgshapiro { 89690792Sgshapiro /* issue a pseudo-error message */ 89790792Sgshapiro errno = SM_EMAPCANTWRITE; 89890792Sgshapiro return false; 89990792Sgshapiro } 90090792Sgshapiro return true; 90190792Sgshapiro} 90290792Sgshapiro 90390792Sgshapiro/* 90490792Sgshapiro** DNS_MAP_PARSEARGS -- parse dns map definition args. 90590792Sgshapiro** 90690792Sgshapiro** Parameters: 90790792Sgshapiro** map -- pointer to MAP 90890792Sgshapiro** args -- pointer to the args on the config line. 90990792Sgshapiro** 91090792Sgshapiro** Returns: 91190792Sgshapiro** true -- if everything parsed OK. 91290792Sgshapiro** false -- otherwise. 91390792Sgshapiro*/ 91490792Sgshapiro 91590792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 91690792Sgshapiro# if !_FFR_DNSMAP_MULTI 91790792Sgshapiro ERROR README: You must define _FFR_DNSMAP_MULTI to use _FFR_DNSMAP_MULTILIMIT 91890792Sgshapiro# endif /* ! _FFR_DNSMAP_MULTI */ 91990792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 92090792Sgshapiro 92190792Sgshapiro# if _FFR_DNSMAP_MULTI 92290792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 92390792Sgshapiro# define map_sizelimit map_lockfd /* overload field */ 92490792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 92590792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 92690792Sgshapiro 92790792Sgshapirostruct dns_map 92890792Sgshapiro{ 92990792Sgshapiro int dns_m_type; 93090792Sgshapiro}; 93190792Sgshapiro 93290792Sgshapirobool 93390792Sgshapirodns_map_parseargs(map,args) 93490792Sgshapiro MAP *map; 93590792Sgshapiro char *args; 93690792Sgshapiro{ 93790792Sgshapiro register char *p = args; 93890792Sgshapiro struct dns_map *map_p; 93990792Sgshapiro 94090792Sgshapiro map_p = (struct dns_map *) xalloc(sizeof *map_p); 94190792Sgshapiro map_p->dns_m_type = -1; 94290792Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 94390792Sgshapiro 94490792Sgshapiro for (;;) 94590792Sgshapiro { 94690792Sgshapiro while (isascii(*p) && isspace(*p)) 94790792Sgshapiro p++; 94890792Sgshapiro if (*p != '-') 94990792Sgshapiro break; 95090792Sgshapiro switch (*++p) 95190792Sgshapiro { 95290792Sgshapiro case 'N': 95390792Sgshapiro map->map_mflags |= MF_INCLNULL; 95490792Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 95590792Sgshapiro break; 95690792Sgshapiro 95790792Sgshapiro case 'O': 95890792Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 95990792Sgshapiro break; 96090792Sgshapiro 96190792Sgshapiro case 'o': 96290792Sgshapiro map->map_mflags |= MF_OPTIONAL; 96390792Sgshapiro break; 96490792Sgshapiro 96590792Sgshapiro case 'f': 96690792Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 96790792Sgshapiro break; 96890792Sgshapiro 96990792Sgshapiro case 'm': 97090792Sgshapiro map->map_mflags |= MF_MATCHONLY; 97190792Sgshapiro break; 97290792Sgshapiro 97390792Sgshapiro case 'A': 97490792Sgshapiro map->map_mflags |= MF_APPEND; 97590792Sgshapiro break; 97690792Sgshapiro 97790792Sgshapiro case 'q': 97890792Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 97990792Sgshapiro break; 98090792Sgshapiro 98190792Sgshapiro case 't': 98290792Sgshapiro map->map_mflags |= MF_NODEFER; 98390792Sgshapiro break; 98490792Sgshapiro 98590792Sgshapiro case 'a': 98690792Sgshapiro map->map_app = ++p; 98790792Sgshapiro break; 98890792Sgshapiro 98990792Sgshapiro case 'T': 99090792Sgshapiro map->map_tapp = ++p; 99190792Sgshapiro break; 99290792Sgshapiro 99390792Sgshapiro case 'd': 99490792Sgshapiro { 99590792Sgshapiro char *h; 99690792Sgshapiro 99790792Sgshapiro ++p; 99890792Sgshapiro h = strchr(p, ' '); 99990792Sgshapiro if (h != NULL) 100090792Sgshapiro *h = '\0'; 100190792Sgshapiro map->map_timeout = convtime(p, 's'); 100290792Sgshapiro if (h != NULL) 100390792Sgshapiro *h = ' '; 100490792Sgshapiro } 100590792Sgshapiro break; 100690792Sgshapiro 100790792Sgshapiro case 'r': 100890792Sgshapiro while (isascii(*++p) && isspace(*p)) 100990792Sgshapiro continue; 101090792Sgshapiro map->map_retry = atoi(p); 101190792Sgshapiro break; 101290792Sgshapiro 101390792Sgshapiro# if _FFR_DNSMAP_MULTI 101490792Sgshapiro case 'z': 101590792Sgshapiro if (*++p != '\\') 101690792Sgshapiro map->map_coldelim = *p; 101790792Sgshapiro else 101890792Sgshapiro { 101990792Sgshapiro switch (*++p) 102090792Sgshapiro { 102190792Sgshapiro case 'n': 102290792Sgshapiro map->map_coldelim = '\n'; 102390792Sgshapiro break; 102490792Sgshapiro 102590792Sgshapiro case 't': 102690792Sgshapiro map->map_coldelim = '\t'; 102790792Sgshapiro break; 102890792Sgshapiro 102990792Sgshapiro default: 103090792Sgshapiro map->map_coldelim = '\\'; 103190792Sgshapiro } 103290792Sgshapiro } 103390792Sgshapiro break; 103490792Sgshapiro 103590792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 103690792Sgshapiro case 'Z': 103790792Sgshapiro while (isascii(*++p) && isspace(*p)) 103890792Sgshapiro continue; 103990792Sgshapiro map->map_sizelimit = atoi(p); 104090792Sgshapiro break; 104190792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 104290792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 104390792Sgshapiro 104490792Sgshapiro /* Start of dns_map specific args */ 104590792Sgshapiro case 'R': /* search field */ 104690792Sgshapiro { 104790792Sgshapiro char *h; 104890792Sgshapiro 104990792Sgshapiro while (isascii(*++p) && isspace(*p)) 105090792Sgshapiro continue; 105190792Sgshapiro h = strchr(p, ' '); 105290792Sgshapiro if (h != NULL) 105390792Sgshapiro *h = '\0'; 105490792Sgshapiro map_p->dns_m_type = dns_string_to_type(p); 105590792Sgshapiro if (h != NULL) 105690792Sgshapiro *h = ' '; 105790792Sgshapiro if (map_p->dns_m_type < 0) 105890792Sgshapiro syserr("dns map %s: wrong type %s", 105990792Sgshapiro map->map_mname, p); 106090792Sgshapiro } 106190792Sgshapiro break; 106290792Sgshapiro 106390792Sgshapiro# if _FFR_DNSMAP_BASE 106490792Sgshapiro case 'B': /* base domain */ 106590792Sgshapiro { 106690792Sgshapiro char *h; 106790792Sgshapiro 106890792Sgshapiro while (isascii(*++p) && isspace(*p)) 106990792Sgshapiro continue; 107090792Sgshapiro h = strchr(p, ' '); 107190792Sgshapiro if (h != NULL) 107290792Sgshapiro *h = '\0'; 107390792Sgshapiro 107490792Sgshapiro /* 107590792Sgshapiro ** slight abuse of map->map_file; it isn't 107690792Sgshapiro ** used otherwise in this map type. 107790792Sgshapiro */ 107890792Sgshapiro 107990792Sgshapiro map->map_file = newstr(p); 108090792Sgshapiro if (h != NULL) 108190792Sgshapiro *h = ' '; 108290792Sgshapiro } 108390792Sgshapiro break; 108490792Sgshapiro# endif /* _FFR_DNSMAP_BASE */ 108590792Sgshapiro 108690792Sgshapiro } 108790792Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 108890792Sgshapiro p++; 108990792Sgshapiro if (*p != '\0') 109090792Sgshapiro *p++ = '\0'; 109190792Sgshapiro } 109290792Sgshapiro if (map_p->dns_m_type < 0) 109390792Sgshapiro syserr("dns map %s: missing -R type", map->map_mname); 109490792Sgshapiro if (map->map_app != NULL) 109590792Sgshapiro map->map_app = newstr(map->map_app); 109690792Sgshapiro if (map->map_tapp != NULL) 109790792Sgshapiro map->map_tapp = newstr(map->map_tapp); 109890792Sgshapiro 109990792Sgshapiro /* 110090792Sgshapiro ** Assumption: assert(sizeof int <= sizeof(ARBPTR_T)); 110190792Sgshapiro ** Even if this assumption is wrong, we use only one byte, 110290792Sgshapiro ** so it doesn't really matter. 110390792Sgshapiro */ 110490792Sgshapiro 110590792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; 110690792Sgshapiro return true; 110790792Sgshapiro} 110890792Sgshapiro 110990792Sgshapiro/* 111090792Sgshapiro** DNS_MAP_LOOKUP -- perform dns map lookup. 111190792Sgshapiro** 111290792Sgshapiro** Parameters: 111390792Sgshapiro** map -- pointer to MAP 111490792Sgshapiro** name -- name to lookup 111590792Sgshapiro** av -- arguments to interpolate into buf. 111690792Sgshapiro** statp -- pointer to status (EX_) 111790792Sgshapiro** 111890792Sgshapiro** Returns: 111990792Sgshapiro** result of lookup if succeeded. 112090792Sgshapiro** NULL -- otherwise. 112190792Sgshapiro*/ 112290792Sgshapiro 112390792Sgshapirochar * 112490792Sgshapirodns_map_lookup(map, name, av, statp) 112590792Sgshapiro MAP *map; 112690792Sgshapiro char *name; 112790792Sgshapiro char **av; 112890792Sgshapiro int *statp; 112990792Sgshapiro{ 113090792Sgshapiro# if _FFR_DNSMAP_MULTI 113190792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 113290792Sgshapiro int resnum = 0; 113390792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 113490792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 113590792Sgshapiro char *vp = NULL, *result = NULL; 113690792Sgshapiro size_t vsize; 113790792Sgshapiro struct dns_map *map_p; 113890792Sgshapiro RESOURCE_RECORD_T *rr = NULL; 113990792Sgshapiro DNS_REPLY_T *r = NULL; 114090792Sgshapiro# if NETINET6 114190792Sgshapiro static char buf6[INET6_ADDRSTRLEN]; 114290792Sgshapiro# endif /* NETINET6 */ 114390792Sgshapiro 114490792Sgshapiro if (tTd(38, 20)) 114590792Sgshapiro sm_dprintf("dns_map_lookup(%s, %s)\n", 114690792Sgshapiro map->map_mname, name); 114790792Sgshapiro 114890792Sgshapiro map_p = (struct dns_map *)(map->map_db1); 114990792Sgshapiro# if _FFR_DNSMAP_BASE 115090792Sgshapiro if (map->map_file != NULL && *map->map_file != '\0') 115190792Sgshapiro { 115290792Sgshapiro size_t len; 115390792Sgshapiro char *appdomain; 115490792Sgshapiro 115590792Sgshapiro len = strlen(map->map_file) + strlen(name) + 2; 115690792Sgshapiro appdomain = (char *) sm_malloc(len); 115790792Sgshapiro if (appdomain == NULL) 115890792Sgshapiro { 115990792Sgshapiro *statp = EX_UNAVAILABLE; 116090792Sgshapiro return NULL; 116190792Sgshapiro } 116290792Sgshapiro (void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file); 116390792Sgshapiro r = dns_lookup_int(appdomain, C_IN, map_p->dns_m_type, 116490792Sgshapiro map->map_timeout, map->map_retry); 116590792Sgshapiro sm_free(appdomain); 116690792Sgshapiro } 116790792Sgshapiro else 116890792Sgshapiro# endif /* _FFR_DNSMAP_BASE */ 116990792Sgshapiro { 117090792Sgshapiro r = dns_lookup_int(name, C_IN, map_p->dns_m_type, 117190792Sgshapiro map->map_timeout, map->map_retry); 117290792Sgshapiro } 117390792Sgshapiro 117490792Sgshapiro if (r == NULL) 117590792Sgshapiro { 117690792Sgshapiro result = NULL; 1177120256Sgshapiro if (h_errno == TRY_AGAIN || transienterror(errno)) 117890792Sgshapiro *statp = EX_TEMPFAIL; 117990792Sgshapiro else 118090792Sgshapiro *statp = EX_NOTFOUND; 118190792Sgshapiro goto cleanup; 118290792Sgshapiro } 118390792Sgshapiro *statp = EX_OK; 118490792Sgshapiro for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next) 118590792Sgshapiro { 118690792Sgshapiro char *type = NULL; 118790792Sgshapiro char *value = NULL; 118890792Sgshapiro 118990792Sgshapiro switch (rr->rr_type) 119090792Sgshapiro { 119190792Sgshapiro case T_NS: 119290792Sgshapiro type = "T_NS"; 119390792Sgshapiro value = rr->rr_u.rr_txt; 119490792Sgshapiro break; 119590792Sgshapiro case T_CNAME: 119690792Sgshapiro type = "T_CNAME"; 119790792Sgshapiro value = rr->rr_u.rr_txt; 119890792Sgshapiro break; 119990792Sgshapiro case T_AFSDB: 120090792Sgshapiro type = "T_AFSDB"; 120190792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 120290792Sgshapiro break; 120390792Sgshapiro case T_SRV: 120490792Sgshapiro type = "T_SRV"; 120590792Sgshapiro value = rr->rr_u.rr_srv->srv_r_target; 120690792Sgshapiro break; 120790792Sgshapiro case T_PTR: 120890792Sgshapiro type = "T_PTR"; 120990792Sgshapiro value = rr->rr_u.rr_txt; 121090792Sgshapiro break; 121190792Sgshapiro case T_TXT: 121290792Sgshapiro type = "T_TXT"; 121390792Sgshapiro value = rr->rr_u.rr_txt; 121490792Sgshapiro break; 121590792Sgshapiro case T_MX: 121690792Sgshapiro type = "T_MX"; 121790792Sgshapiro value = rr->rr_u.rr_mx->mx_r_domain; 121890792Sgshapiro break; 121990792Sgshapiro# if NETINET 122090792Sgshapiro case T_A: 122190792Sgshapiro type = "T_A"; 122290792Sgshapiro value = inet_ntoa(*(rr->rr_u.rr_a)); 122390792Sgshapiro break; 122490792Sgshapiro# endif /* NETINET */ 122590792Sgshapiro# if NETINET6 122690792Sgshapiro case T_AAAA: 122790792Sgshapiro type = "T_AAAA"; 122890792Sgshapiro value = anynet_ntop(rr->rr_u.rr_aaaa, buf6, 122990792Sgshapiro sizeof buf6); 123090792Sgshapiro break; 123190792Sgshapiro# endif /* NETINET6 */ 123290792Sgshapiro } 123390792Sgshapiro 123498841Sgshapiro (void) strreplnonprt(value, 'X'); 123590792Sgshapiro if (map_p->dns_m_type != rr->rr_type) 123690792Sgshapiro { 123790792Sgshapiro if (tTd(38, 40)) 123890792Sgshapiro sm_dprintf("\tskipping type %s (%d) value %s\n", 123990792Sgshapiro type != NULL ? type : "<UNKNOWN>", 124090792Sgshapiro rr->rr_type, 124190792Sgshapiro value != NULL ? value : "<NO VALUE>"); 124290792Sgshapiro continue; 124390792Sgshapiro } 124490792Sgshapiro 124590792Sgshapiro# if NETINET6 124690792Sgshapiro if (rr->rr_type == T_AAAA && value == NULL) 124790792Sgshapiro { 124890792Sgshapiro result = NULL; 124990792Sgshapiro *statp = EX_DATAERR; 125090792Sgshapiro if (tTd(38, 40)) 125190792Sgshapiro sm_dprintf("\tbad T_AAAA conversion\n"); 125290792Sgshapiro goto cleanup; 125390792Sgshapiro } 125490792Sgshapiro# endif /* NETINET6 */ 125590792Sgshapiro if (tTd(38, 40)) 125690792Sgshapiro sm_dprintf("\tfound type %s (%d) value %s\n", 125790792Sgshapiro type != NULL ? type : "<UNKNOWN>", 125890792Sgshapiro rr->rr_type, 125990792Sgshapiro value != NULL ? value : "<NO VALUE>"); 126090792Sgshapiro# if _FFR_DNSMAP_MULTI 126190792Sgshapiro if (value != NULL && 126290792Sgshapiro (map->map_coldelim == '\0' || 126390792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 126490792Sgshapiro map->map_sizelimit == 1 || 126590792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 126690792Sgshapiro bitset(MF_MATCHONLY, map->map_mflags))) 126790792Sgshapiro { 126890792Sgshapiro /* Only care about the first match */ 126990792Sgshapiro vp = newstr(value); 127090792Sgshapiro break; 127190792Sgshapiro } 127290792Sgshapiro else if (vp == NULL) 127390792Sgshapiro { 127490792Sgshapiro /* First result */ 127590792Sgshapiro vp = newstr(value); 127690792Sgshapiro } 127790792Sgshapiro else 127890792Sgshapiro { 127990792Sgshapiro /* concatenate the results */ 128090792Sgshapiro int sz; 128190792Sgshapiro char *new; 128290792Sgshapiro 128390792Sgshapiro sz = strlen(vp) + strlen(value) + 2; 128490792Sgshapiro new = xalloc(sz); 128590792Sgshapiro (void) sm_snprintf(new, sz, "%s%c%s", 128690792Sgshapiro vp, map->map_coldelim, value); 128790792Sgshapiro sm_free(vp); 128890792Sgshapiro vp = new; 128990792Sgshapiro# if _FFR_DNSMAP_MULTILIMIT 129090792Sgshapiro if (map->map_sizelimit > 0 && 129190792Sgshapiro ++resnum >= map->map_sizelimit) 129290792Sgshapiro break; 129390792Sgshapiro# endif /* _FFR_DNSMAP_MULTILIMIT */ 129490792Sgshapiro } 129590792Sgshapiro# else /* _FFR_DNSMAP_MULTI */ 129690792Sgshapiro vp = value; 129790792Sgshapiro break; 129890792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 129990792Sgshapiro } 130090792Sgshapiro if (vp == NULL) 130190792Sgshapiro { 130290792Sgshapiro result = NULL; 130390792Sgshapiro *statp = EX_NOTFOUND; 130490792Sgshapiro if (tTd(38, 40)) 130590792Sgshapiro sm_dprintf("\tno match found\n"); 130690792Sgshapiro goto cleanup; 130790792Sgshapiro } 130890792Sgshapiro 130990792Sgshapiro# if _FFR_DNSMAP_MULTI 131090792Sgshapiro /* Cleanly truncate for rulesets */ 131190792Sgshapiro truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim); 131290792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 131390792Sgshapiro 131490792Sgshapiro vsize = strlen(vp); 131590792Sgshapiro 131690792Sgshapiro if (LogLevel > 9) 131790792Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s", 131890792Sgshapiro name, vp); 131990792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 132090792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 132190792Sgshapiro else 132290792Sgshapiro result = map_rewrite(map, vp, vsize, av); 132390792Sgshapiro 132490792Sgshapiro cleanup: 132590792Sgshapiro# if _FFR_DNSMAP_MULTI 132690792Sgshapiro if (vp != NULL) 132790792Sgshapiro sm_free(vp); 132890792Sgshapiro# endif /* _FFR_DNSMAP_MULTI */ 132990792Sgshapiro if (r != NULL) 133090792Sgshapiro dns_free_data(r); 133190792Sgshapiro return result; 133290792Sgshapiro} 133390792Sgshapiro# endif /* DNSMAP */ 133490792Sgshapiro#endif /* NAMED_BIND */ 133590792Sgshapiro 133690792Sgshapiro/* 133738032Speter** NDBM modules 133838032Speter*/ 133938032Speter 134090792Sgshapiro#if NDBM 134138032Speter 134238032Speter/* 134338032Speter** NDBM_MAP_OPEN -- DBM-style map open 134438032Speter*/ 134538032Speter 134638032Speterbool 134738032Speterndbm_map_open(map, mode) 134838032Speter MAP *map; 134938032Speter int mode; 135038032Speter{ 135138032Speter register DBM *dbm; 135264562Sgshapiro int save_errno; 135338032Speter int dfd; 135438032Speter int pfd; 135564562Sgshapiro long sff; 135638032Speter int ret; 135738032Speter int smode = S_IREAD; 135898121Sgshapiro char dirfile[MAXPATHLEN]; 135998121Sgshapiro char pagfile[MAXPATHLEN]; 136064562Sgshapiro struct stat st; 136138032Speter struct stat std, stp; 136238032Speter 136338032Speter if (tTd(38, 2)) 136490792Sgshapiro sm_dprintf("ndbm_map_open(%s, %s, %d)\n", 136538032Speter map->map_mname, map->map_file, mode); 136638032Speter map->map_lockfd = -1; 136738032Speter mode &= O_ACCMODE; 136838032Speter 136938032Speter /* do initial file and directory checks */ 137098121Sgshapiro if (sm_strlcpyn(dirfile, sizeof dirfile, 2, 137198121Sgshapiro map->map_file, ".dir") >= sizeof dirfile || 137298121Sgshapiro sm_strlcpyn(pagfile, sizeof pagfile, 2, 137398121Sgshapiro map->map_file, ".pag") >= sizeof pagfile) 137498121Sgshapiro { 137598121Sgshapiro errno = 0; 137698121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 137798121Sgshapiro syserr("dbm map \"%s\": map file %s name too long", 137898121Sgshapiro map->map_mname, map->map_file); 137998121Sgshapiro return false; 138098121Sgshapiro } 138138032Speter sff = SFF_ROOTOK|SFF_REGONLY; 138238032Speter if (mode == O_RDWR) 138338032Speter { 138438032Speter sff |= SFF_CREAT; 138564562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 138638032Speter sff |= SFF_NOSLINK; 138764562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 138838032Speter sff |= SFF_NOHLINK; 138938032Speter smode = S_IWRITE; 139038032Speter } 139138032Speter else 139238032Speter { 139364562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 139438032Speter sff |= SFF_NOWLINK; 139538032Speter } 139664562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 139738032Speter sff |= SFF_SAFEDIRPATH; 139838032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 139990792Sgshapiro sff, smode, &std); 140038032Speter if (ret == 0) 140138032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 140238032Speter sff, smode, &stp); 140364562Sgshapiro 140438032Speter if (ret != 0) 140538032Speter { 140638032Speter char *prob = "unsafe"; 140738032Speter 140838032Speter /* cannot open this map */ 140938032Speter if (ret == ENOENT) 141038032Speter prob = "missing"; 141138032Speter if (tTd(38, 2)) 141290792Sgshapiro sm_dprintf("\t%s map file: %d\n", prob, ret); 141338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 141438032Speter syserr("dbm map \"%s\": %s map file %s", 141538032Speter map->map_mname, prob, map->map_file); 141690792Sgshapiro return false; 141738032Speter } 141838032Speter if (std.st_mode == ST_MODE_NOFILE) 141938032Speter mode |= O_CREAT|O_EXCL; 142038032Speter 142164562Sgshapiro# if LOCK_ON_OPEN 142238032Speter if (mode == O_RDONLY) 142338032Speter mode |= O_SHLOCK; 142438032Speter else 142538032Speter mode |= O_TRUNC|O_EXLOCK; 142664562Sgshapiro# else /* LOCK_ON_OPEN */ 142738032Speter if ((mode & O_ACCMODE) == O_RDWR) 142838032Speter { 142964562Sgshapiro# if NOFTRUNCATE 143038032Speter /* 143138032Speter ** Warning: race condition. Try to lock the file as 143238032Speter ** quickly as possible after opening it. 143338032Speter ** This may also have security problems on some systems, 143438032Speter ** but there isn't anything we can do about it. 143538032Speter */ 143638032Speter 143738032Speter mode |= O_TRUNC; 143864562Sgshapiro# else /* NOFTRUNCATE */ 143938032Speter /* 144038032Speter ** This ugly code opens the map without truncating it, 144138032Speter ** locks the file, then truncates it. Necessary to 144238032Speter ** avoid race conditions. 144338032Speter */ 144438032Speter 144538032Speter int dirfd; 144638032Speter int pagfd; 144764562Sgshapiro long sff = SFF_CREAT|SFF_OPENASROOT; 144838032Speter 144964562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 145038032Speter sff |= SFF_NOSLINK; 145164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 145238032Speter sff |= SFF_NOHLINK; 145338032Speter 145438032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 145538032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 145638032Speter 145738032Speter if (dirfd < 0 || pagfd < 0) 145838032Speter { 145964562Sgshapiro save_errno = errno; 146038032Speter if (dirfd >= 0) 146138032Speter (void) close(dirfd); 146238032Speter if (pagfd >= 0) 146338032Speter (void) close(pagfd); 146438032Speter errno = save_errno; 146538032Speter syserr("ndbm_map_open: cannot create database %s", 146638032Speter map->map_file); 146790792Sgshapiro return false; 146838032Speter } 146938032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 147038032Speter ftruncate(pagfd, (off_t) 0) < 0) 147138032Speter { 147264562Sgshapiro save_errno = errno; 147338032Speter (void) close(dirfd); 147438032Speter (void) close(pagfd); 147538032Speter errno = save_errno; 147638032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 147738032Speter map->map_file); 147890792Sgshapiro return false; 147938032Speter } 148038032Speter 148138032Speter /* if new file, get "before" bits for later filechanged check */ 148238032Speter if (std.st_mode == ST_MODE_NOFILE && 148338032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 148438032Speter { 148564562Sgshapiro save_errno = errno; 148638032Speter (void) close(dirfd); 148738032Speter (void) close(pagfd); 148838032Speter errno = save_errno; 148938032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 149038032Speter map->map_file); 149190792Sgshapiro return false; 149238032Speter } 149338032Speter 149438032Speter /* have to save the lock for the duration (bletch) */ 149538032Speter map->map_lockfd = dirfd; 149664562Sgshapiro (void) close(pagfd); 149738032Speter 149838032Speter /* twiddle bits for dbm_open */ 149938032Speter mode &= ~(O_CREAT|O_EXCL); 150064562Sgshapiro# endif /* NOFTRUNCATE */ 150138032Speter } 150264562Sgshapiro# endif /* LOCK_ON_OPEN */ 150338032Speter 150438032Speter /* open the database */ 150538032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 150638032Speter if (dbm == NULL) 150738032Speter { 150864562Sgshapiro save_errno = errno; 150938032Speter if (bitset(MF_ALIAS, map->map_mflags) && 151090792Sgshapiro aliaswait(map, ".pag", false)) 151190792Sgshapiro return true; 151264562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 151338032Speter if (map->map_lockfd >= 0) 151464562Sgshapiro (void) close(map->map_lockfd); 151564562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 151638032Speter errno = save_errno; 151738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 151838032Speter syserr("Cannot open DBM database %s", map->map_file); 151990792Sgshapiro return false; 152038032Speter } 152138032Speter dfd = dbm_dirfno(dbm); 152238032Speter pfd = dbm_pagfno(dbm); 152338032Speter if (dfd == pfd) 152438032Speter { 152538032Speter /* heuristic: if files are linked, this is actually gdbm */ 152638032Speter dbm_close(dbm); 152764562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 152838032Speter if (map->map_lockfd >= 0) 152964562Sgshapiro (void) close(map->map_lockfd); 153064562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 153138032Speter errno = 0; 153238032Speter syserr("dbm map \"%s\": cannot support GDBM", 153338032Speter map->map_mname); 153490792Sgshapiro return false; 153538032Speter } 153638032Speter 153738032Speter if (filechanged(dirfile, dfd, &std) || 153838032Speter filechanged(pagfile, pfd, &stp)) 153938032Speter { 154064562Sgshapiro save_errno = errno; 154138032Speter dbm_close(dbm); 154264562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 154338032Speter if (map->map_lockfd >= 0) 154464562Sgshapiro (void) close(map->map_lockfd); 154564562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 154638032Speter errno = save_errno; 154738032Speter syserr("ndbm_map_open(%s): file changed after open", 154838032Speter map->map_file); 154990792Sgshapiro return false; 155038032Speter } 155138032Speter 155238032Speter map->map_db1 = (ARBPTR_T) dbm; 155364562Sgshapiro 155464562Sgshapiro /* 155564562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 155664562Sgshapiro ** as aliaswait() will call map_lookup() which requires 155764562Sgshapiro ** map_mtime to be set 155864562Sgshapiro */ 155964562Sgshapiro 156077349Sgshapiro if (fstat(pfd, &st) >= 0) 156164562Sgshapiro map->map_mtime = st.st_mtime; 156264562Sgshapiro 156338032Speter if (mode == O_RDONLY) 156438032Speter { 156564562Sgshapiro# if LOCK_ON_OPEN 156638032Speter if (dfd >= 0) 156738032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 156838032Speter if (pfd >= 0) 156938032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 157064562Sgshapiro# endif /* LOCK_ON_OPEN */ 157138032Speter if (bitset(MF_ALIAS, map->map_mflags) && 157290792Sgshapiro !aliaswait(map, ".pag", true)) 157390792Sgshapiro return false; 157438032Speter } 157538032Speter else 157638032Speter { 157738032Speter map->map_mflags |= MF_LOCKED; 157842575Speter if (geteuid() == 0 && TrustedUid != 0) 157938032Speter { 158064562Sgshapiro# if HASFCHOWN 158142575Speter if (fchown(dfd, TrustedUid, -1) < 0 || 158242575Speter fchown(pfd, TrustedUid, -1) < 0) 158338032Speter { 158438032Speter int err = errno; 158538032Speter 158638032Speter sm_syslog(LOG_ALERT, NOQID, 158738032Speter "ownership change on %s failed: %s", 158890792Sgshapiro map->map_file, sm_errstring(err)); 158938032Speter message("050 ownership change on %s failed: %s", 159090792Sgshapiro map->map_file, sm_errstring(err)); 159138032Speter } 159290792Sgshapiro# else /* HASFCHOWN */ 159390792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 159490792Sgshapiro "no fchown(): cannot change ownership on %s", 159590792Sgshapiro map->map_file); 159690792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 159790792Sgshapiro map->map_file); 159864562Sgshapiro# endif /* HASFCHOWN */ 159938032Speter } 160038032Speter } 160190792Sgshapiro return true; 160238032Speter} 160338032Speter 160438032Speter 160538032Speter/* 160638032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 160738032Speter*/ 160838032Speter 160938032Speterchar * 161038032Speterndbm_map_lookup(map, name, av, statp) 161138032Speter MAP *map; 161238032Speter char *name; 161338032Speter char **av; 161438032Speter int *statp; 161538032Speter{ 161638032Speter datum key, val; 161777349Sgshapiro int dfd, pfd; 161838032Speter char keybuf[MAXNAME + 1]; 161938032Speter struct stat stbuf; 162038032Speter 162138032Speter if (tTd(38, 20)) 162290792Sgshapiro sm_dprintf("ndbm_map_lookup(%s, %s)\n", 162338032Speter map->map_mname, name); 162438032Speter 162538032Speter key.dptr = name; 162638032Speter key.dsize = strlen(name); 162738032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 162838032Speter { 162938032Speter if (key.dsize > sizeof keybuf - 1) 163038032Speter key.dsize = sizeof keybuf - 1; 163164562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 163238032Speter keybuf[key.dsize] = '\0'; 163338032Speter makelower(keybuf); 163438032Speter key.dptr = keybuf; 163538032Speter } 163638032Speterlockdbm: 163777349Sgshapiro dfd = dbm_dirfno((DBM *) map->map_db1); 163877349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 163977349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_SH); 164077349Sgshapiro pfd = dbm_pagfno((DBM *) map->map_db1); 164177349Sgshapiro if (pfd < 0 || fstat(pfd, &stbuf) < 0 || 164277349Sgshapiro stbuf.st_mtime > map->map_mtime) 164338032Speter { 164438032Speter /* Reopen the database to sync the cache */ 164538032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 164638032Speter : O_RDONLY; 164738032Speter 164877349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 164977349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 165077349Sgshapiro map->map_mflags |= MF_CLOSING; 165138032Speter map->map_class->map_close(map); 165277349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 165338032Speter if (map->map_class->map_open(map, omode)) 165438032Speter { 165538032Speter map->map_mflags |= MF_OPEN; 165690792Sgshapiro map->map_pid = CurrentPid; 165738032Speter if ((omode && O_ACCMODE) == O_RDWR) 165838032Speter map->map_mflags |= MF_WRITABLE; 165938032Speter goto lockdbm; 166038032Speter } 166138032Speter else 166238032Speter { 166338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 166438032Speter { 166538032Speter extern MAPCLASS BogusMapClass; 166638032Speter 166738032Speter *statp = EX_TEMPFAIL; 166890792Sgshapiro map->map_orgclass = map->map_class; 166938032Speter map->map_class = &BogusMapClass; 167038032Speter map->map_mflags |= MF_OPEN; 167190792Sgshapiro map->map_pid = CurrentPid; 167238032Speter syserr("Cannot reopen NDBM database %s", 167338032Speter map->map_file); 167438032Speter } 167538032Speter return NULL; 167638032Speter } 167738032Speter } 167838032Speter val.dptr = NULL; 167938032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 168038032Speter { 168138032Speter val = dbm_fetch((DBM *) map->map_db1, key); 168238032Speter if (val.dptr != NULL) 168338032Speter map->map_mflags &= ~MF_TRY1NULL; 168438032Speter } 168538032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 168638032Speter { 168738032Speter key.dsize++; 168838032Speter val = dbm_fetch((DBM *) map->map_db1, key); 168938032Speter if (val.dptr != NULL) 169038032Speter map->map_mflags &= ~MF_TRY0NULL; 169138032Speter } 169277349Sgshapiro if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 169377349Sgshapiro (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 169438032Speter if (val.dptr == NULL) 169538032Speter return NULL; 169638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 169738032Speter return map_rewrite(map, name, strlen(name), NULL); 169838032Speter else 169938032Speter return map_rewrite(map, val.dptr, val.dsize, av); 170038032Speter} 170138032Speter 170238032Speter 170338032Speter/* 170438032Speter** NDBM_MAP_STORE -- store a datum in the database 170538032Speter*/ 170638032Speter 170738032Spetervoid 170838032Speterndbm_map_store(map, lhs, rhs) 170938032Speter register MAP *map; 171038032Speter char *lhs; 171138032Speter char *rhs; 171238032Speter{ 171338032Speter datum key; 171438032Speter datum data; 171564562Sgshapiro int status; 171638032Speter char keybuf[MAXNAME + 1]; 171738032Speter 171838032Speter if (tTd(38, 12)) 171990792Sgshapiro sm_dprintf("ndbm_map_store(%s, %s, %s)\n", 172038032Speter map->map_mname, lhs, rhs); 172138032Speter 172238032Speter key.dsize = strlen(lhs); 172338032Speter key.dptr = lhs; 172438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 172538032Speter { 172638032Speter if (key.dsize > sizeof keybuf - 1) 172738032Speter key.dsize = sizeof keybuf - 1; 172864562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 172938032Speter keybuf[key.dsize] = '\0'; 173038032Speter makelower(keybuf); 173138032Speter key.dptr = keybuf; 173238032Speter } 173338032Speter 173438032Speter data.dsize = strlen(rhs); 173538032Speter data.dptr = rhs; 173638032Speter 173738032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 173838032Speter { 173938032Speter key.dsize++; 174038032Speter data.dsize++; 174138032Speter } 174238032Speter 174364562Sgshapiro status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 174464562Sgshapiro if (status > 0) 174538032Speter { 174638032Speter if (!bitset(MF_APPEND, map->map_mflags)) 174738032Speter message("050 Warning: duplicate alias name %s", lhs); 174838032Speter else 174938032Speter { 175038032Speter static char *buf = NULL; 175138032Speter static int bufsiz = 0; 175238032Speter auto int xstat; 175338032Speter datum old; 175438032Speter 175538032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 175690792Sgshapiro (char **) NULL, &xstat); 175738032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 175838032Speter { 175938032Speter old.dsize = strlen(old.dptr); 176038032Speter if (data.dsize + old.dsize + 2 > bufsiz) 176138032Speter { 176238032Speter if (buf != NULL) 176390792Sgshapiro (void) sm_free(buf); 176438032Speter bufsiz = data.dsize + old.dsize + 2; 176590792Sgshapiro buf = sm_pmalloc_x(bufsiz); 176638032Speter } 176790792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 176890792Sgshapiro data.dptr, ",", old.dptr); 176938032Speter data.dsize = data.dsize + old.dsize + 1; 177038032Speter data.dptr = buf; 177138032Speter if (tTd(38, 9)) 177290792Sgshapiro sm_dprintf("ndbm_map_store append=%s\n", 177364562Sgshapiro data.dptr); 177438032Speter } 177538032Speter } 177664562Sgshapiro status = dbm_store((DBM *) map->map_db1, 177764562Sgshapiro key, data, DBM_REPLACE); 177838032Speter } 177964562Sgshapiro if (status != 0) 178064562Sgshapiro syserr("readaliases: dbm put (%s): %d", lhs, status); 178138032Speter} 178238032Speter 178338032Speter 178438032Speter/* 178538032Speter** NDBM_MAP_CLOSE -- close the database 178638032Speter*/ 178738032Speter 178838032Spetervoid 178938032Speterndbm_map_close(map) 179038032Speter register MAP *map; 179138032Speter{ 179238032Speter if (tTd(38, 9)) 179390792Sgshapiro sm_dprintf("ndbm_map_close(%s, %s, %lx)\n", 179438032Speter map->map_mname, map->map_file, map->map_mflags); 179538032Speter 179638032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 179738032Speter { 179864562Sgshapiro# ifdef NDBM_YP_COMPAT 179938032Speter bool inclnull; 180042575Speter char buf[MAXHOSTNAMELEN]; 180138032Speter 180238032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 180338032Speter map->map_mflags &= ~MF_INCLNULL; 180438032Speter 180538032Speter if (strstr(map->map_file, "/yp/") != NULL) 180638032Speter { 180738032Speter long save_mflags = map->map_mflags; 180838032Speter 180938032Speter map->map_mflags |= MF_NOFOLDCASE; 181038032Speter 181190792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%010ld", curtime()); 181238032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 181338032Speter 181438032Speter (void) gethostname(buf, sizeof buf); 181538032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 181638032Speter 181738032Speter map->map_mflags = save_mflags; 181838032Speter } 181938032Speter 182038032Speter if (inclnull) 182138032Speter map->map_mflags |= MF_INCLNULL; 182264562Sgshapiro# endif /* NDBM_YP_COMPAT */ 182338032Speter 182438032Speter /* write out the distinguished alias */ 182538032Speter ndbm_map_store(map, "@", "@"); 182638032Speter } 182738032Speter dbm_close((DBM *) map->map_db1); 182838032Speter 182938032Speter /* release lock (if needed) */ 183064562Sgshapiro# if !LOCK_ON_OPEN 183138032Speter if (map->map_lockfd >= 0) 183238032Speter (void) close(map->map_lockfd); 183364562Sgshapiro# endif /* !LOCK_ON_OPEN */ 183438032Speter} 183538032Speter 183664562Sgshapiro#endif /* NDBM */ 183790792Sgshapiro/* 183838032Speter** NEWDB (Hash and BTree) Modules 183938032Speter*/ 184038032Speter 184190792Sgshapiro#if NEWDB 184238032Speter 184338032Speter/* 184438032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 184538032Speter** 184638032Speter** These do rather bizarre locking. If you can lock on open, 184738032Speter** do that to avoid the condition of opening a database that 184838032Speter** is being rebuilt. If you don't, we'll try to fake it, but 184938032Speter** there will be a race condition. If opening for read-only, 185038032Speter** we immediately release the lock to avoid freezing things up. 185138032Speter** We really ought to hold the lock, but guarantee that we won't 185238032Speter** be pokey about it. That's hard to do. 185338032Speter*/ 185438032Speter 185538032Speter/* these should be K line arguments */ 185664562Sgshapiro# if DB_VERSION_MAJOR < 2 185764562Sgshapiro# define db_cachesize cachesize 185864562Sgshapiro# define h_nelem nelem 185964562Sgshapiro# ifndef DB_CACHE_SIZE 186064562Sgshapiro# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 186164562Sgshapiro# endif /* ! DB_CACHE_SIZE */ 186264562Sgshapiro# ifndef DB_HASH_NELEM 186364562Sgshapiro# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 186464562Sgshapiro# endif /* ! DB_HASH_NELEM */ 186564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 186638032Speter 186738032Speterbool 186838032Speterbt_map_open(map, mode) 186938032Speter MAP *map; 187038032Speter int mode; 187138032Speter{ 187264562Sgshapiro# if DB_VERSION_MAJOR < 2 187338032Speter BTREEINFO btinfo; 187464562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 187564562Sgshapiro# if DB_VERSION_MAJOR == 2 187638032Speter DB_INFO btinfo; 187764562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 187864562Sgshapiro# if DB_VERSION_MAJOR > 2 187964562Sgshapiro void *btinfo = NULL; 188064562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 188138032Speter 188238032Speter if (tTd(38, 2)) 188390792Sgshapiro sm_dprintf("bt_map_open(%s, %s, %d)\n", 188438032Speter map->map_mname, map->map_file, mode); 188538032Speter 188664562Sgshapiro# if DB_VERSION_MAJOR < 3 188764562Sgshapiro memset(&btinfo, '\0', sizeof btinfo); 188864562Sgshapiro# ifdef DB_CACHE_SIZE 188938032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 189064562Sgshapiro# endif /* DB_CACHE_SIZE */ 189164562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 189264562Sgshapiro 189338032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 189438032Speter} 189538032Speter 189638032Speterbool 189738032Speterhash_map_open(map, mode) 189838032Speter MAP *map; 189938032Speter int mode; 190038032Speter{ 190164562Sgshapiro# if DB_VERSION_MAJOR < 2 190238032Speter HASHINFO hinfo; 190364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 190464562Sgshapiro# if DB_VERSION_MAJOR == 2 190538032Speter DB_INFO hinfo; 190664562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 190764562Sgshapiro# if DB_VERSION_MAJOR > 2 190864562Sgshapiro void *hinfo = NULL; 190964562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 191038032Speter 191138032Speter if (tTd(38, 2)) 191290792Sgshapiro sm_dprintf("hash_map_open(%s, %s, %d)\n", 191338032Speter map->map_mname, map->map_file, mode); 191438032Speter 191564562Sgshapiro# if DB_VERSION_MAJOR < 3 191664562Sgshapiro memset(&hinfo, '\0', sizeof hinfo); 191764562Sgshapiro# ifdef DB_HASH_NELEM 191838032Speter hinfo.h_nelem = DB_HASH_NELEM; 191964562Sgshapiro# endif /* DB_HASH_NELEM */ 192064562Sgshapiro# ifdef DB_CACHE_SIZE 192138032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 192264562Sgshapiro# endif /* DB_CACHE_SIZE */ 192364562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 192464562Sgshapiro 192538032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 192638032Speter} 192738032Speter 192864562Sgshapirostatic bool 192938032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 193038032Speter MAP *map; 193138032Speter int mode; 193238032Speter char *mapclassname; 193338032Speter DBTYPE dbtype; 193464562Sgshapiro# if DB_VERSION_MAJOR < 2 193538032Speter const void *openinfo; 193664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 193764562Sgshapiro# if DB_VERSION_MAJOR == 2 193838032Speter DB_INFO *openinfo; 193964562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 194064562Sgshapiro# if DB_VERSION_MAJOR > 2 194164562Sgshapiro void **openinfo; 194264562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 194338032Speter{ 194438032Speter DB *db = NULL; 194538032Speter int i; 194638032Speter int omode; 194738032Speter int smode = S_IREAD; 194838032Speter int fd; 194964562Sgshapiro long sff; 195064562Sgshapiro int save_errno; 195138032Speter struct stat st; 195298121Sgshapiro char buf[MAXPATHLEN]; 195338032Speter 195438032Speter /* do initial file and directory checks */ 195598121Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf) 195698121Sgshapiro { 195798121Sgshapiro errno = 0; 195898121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 195998121Sgshapiro syserr("map \"%s\": map file %s name too long", 196098121Sgshapiro map->map_mname, map->map_file); 196198121Sgshapiro return false; 196298121Sgshapiro } 196338032Speter i = strlen(buf); 196438032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 196598121Sgshapiro { 196698121Sgshapiro if (sm_strlcat(buf, ".db", sizeof buf) >= sizeof buf) 196798121Sgshapiro { 196898121Sgshapiro errno = 0; 196998121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 197098121Sgshapiro syserr("map \"%s\": map file %s name too long", 197198121Sgshapiro map->map_mname, map->map_file); 197298121Sgshapiro return false; 197398121Sgshapiro } 197498121Sgshapiro } 197538032Speter 197638032Speter mode &= O_ACCMODE; 197738032Speter omode = mode; 197838032Speter 197938032Speter sff = SFF_ROOTOK|SFF_REGONLY; 198038032Speter if (mode == O_RDWR) 198138032Speter { 198238032Speter sff |= SFF_CREAT; 198364562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 198438032Speter sff |= SFF_NOSLINK; 198564562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 198638032Speter sff |= SFF_NOHLINK; 198738032Speter smode = S_IWRITE; 198838032Speter } 198938032Speter else 199038032Speter { 199164562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 199238032Speter sff |= SFF_NOWLINK; 199338032Speter } 199464562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 199538032Speter sff |= SFF_SAFEDIRPATH; 199638032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 199764562Sgshapiro 199838032Speter if (i != 0) 199938032Speter { 200038032Speter char *prob = "unsafe"; 200138032Speter 200238032Speter /* cannot open this map */ 200338032Speter if (i == ENOENT) 200438032Speter prob = "missing"; 200538032Speter if (tTd(38, 2)) 200690792Sgshapiro sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i)); 200738032Speter errno = i; 200838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 200938032Speter syserr("%s map \"%s\": %s map file %s", 201038032Speter mapclassname, map->map_mname, prob, buf); 201190792Sgshapiro return false; 201238032Speter } 201338032Speter if (st.st_mode == ST_MODE_NOFILE) 201438032Speter omode |= O_CREAT|O_EXCL; 201538032Speter 201638032Speter map->map_lockfd = -1; 201738032Speter 201864562Sgshapiro# if LOCK_ON_OPEN 201938032Speter if (mode == O_RDWR) 202038032Speter omode |= O_TRUNC|O_EXLOCK; 202138032Speter else 202238032Speter omode |= O_SHLOCK; 202364562Sgshapiro# else /* LOCK_ON_OPEN */ 202438032Speter /* 202538032Speter ** Pre-lock the file to avoid race conditions. In particular, 202638032Speter ** since dbopen returns NULL if the file is zero length, we 202738032Speter ** must have a locked instance around the dbopen. 202838032Speter */ 202938032Speter 203038032Speter fd = open(buf, omode, DBMMODE); 203138032Speter if (fd < 0) 203238032Speter { 203338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 203438032Speter syserr("db_map_open: cannot pre-open database %s", buf); 203590792Sgshapiro return false; 203638032Speter } 203738032Speter 203838032Speter /* make sure no baddies slipped in just before the open... */ 203938032Speter if (filechanged(buf, fd, &st)) 204038032Speter { 204164562Sgshapiro save_errno = errno; 204238032Speter (void) close(fd); 204338032Speter errno = save_errno; 204438032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 204590792Sgshapiro return false; 204638032Speter } 204738032Speter 204838032Speter /* if new file, get the "before" bits for later filechanged check */ 204938032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 205038032Speter { 205164562Sgshapiro save_errno = errno; 205238032Speter (void) close(fd); 205338032Speter errno = save_errno; 205438032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 205538032Speter buf); 205690792Sgshapiro return false; 205738032Speter } 205838032Speter 205938032Speter /* actually lock the pre-opened file */ 206038032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 206138032Speter syserr("db_map_open: cannot lock %s", buf); 206238032Speter 206338032Speter /* set up mode bits for dbopen */ 206438032Speter if (mode == O_RDWR) 206538032Speter omode |= O_TRUNC; 206638032Speter omode &= ~(O_EXCL|O_CREAT); 206764562Sgshapiro# endif /* LOCK_ON_OPEN */ 206838032Speter 206964562Sgshapiro# if DB_VERSION_MAJOR < 2 207038032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 207164562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 207238032Speter { 207338032Speter int flags = 0; 207464562Sgshapiro# if DB_VERSION_MAJOR > 2 207564562Sgshapiro int ret; 207664562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 207738032Speter 207838032Speter if (mode == O_RDONLY) 207938032Speter flags |= DB_RDONLY; 208038032Speter if (bitset(O_CREAT, omode)) 208138032Speter flags |= DB_CREATE; 208238032Speter if (bitset(O_TRUNC, omode)) 208338032Speter flags |= DB_TRUNCATE; 2084110560Sgshapiro SM_DB_FLAG_ADD(flags); 208538032Speter 208664562Sgshapiro# if DB_VERSION_MAJOR > 2 208764562Sgshapiro ret = db_create(&db, NULL, 0); 208864562Sgshapiro# ifdef DB_CACHE_SIZE 208964562Sgshapiro if (ret == 0 && db != NULL) 209064562Sgshapiro { 209164562Sgshapiro ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 209264562Sgshapiro if (ret != 0) 209364562Sgshapiro { 209464562Sgshapiro (void) db->close(db, 0); 209564562Sgshapiro db = NULL; 209664562Sgshapiro } 209764562Sgshapiro } 209864562Sgshapiro# endif /* DB_CACHE_SIZE */ 209964562Sgshapiro# ifdef DB_HASH_NELEM 210064562Sgshapiro if (dbtype == DB_HASH && ret == 0 && db != NULL) 210164562Sgshapiro { 210264562Sgshapiro ret = db->set_h_nelem(db, DB_HASH_NELEM); 210364562Sgshapiro if (ret != 0) 210464562Sgshapiro { 210564562Sgshapiro (void) db->close(db, 0); 210664562Sgshapiro db = NULL; 210764562Sgshapiro } 210864562Sgshapiro } 210964562Sgshapiro# endif /* DB_HASH_NELEM */ 211064562Sgshapiro if (ret == 0 && db != NULL) 211164562Sgshapiro { 2112110560Sgshapiro ret = db->open(db, 2113110560Sgshapiro DBTXN /* transaction for DB 4.1 */ 2114110560Sgshapiro buf, NULL, dbtype, flags, DBMMODE); 211564562Sgshapiro if (ret != 0) 211664562Sgshapiro { 211773188Sgshapiro#ifdef DB_OLD_VERSION 211873188Sgshapiro if (ret == DB_OLD_VERSION) 211973188Sgshapiro ret = EINVAL; 212073188Sgshapiro#endif /* DB_OLD_VERSION */ 212164562Sgshapiro (void) db->close(db, 0); 212264562Sgshapiro db = NULL; 212364562Sgshapiro } 212464562Sgshapiro } 212564562Sgshapiro errno = ret; 212664562Sgshapiro# else /* DB_VERSION_MAJOR > 2 */ 212738032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 212838032Speter NULL, openinfo, &db); 212964562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 213038032Speter } 213164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 213264562Sgshapiro save_errno = errno; 213338032Speter 213464562Sgshapiro# if !LOCK_ON_OPEN 213538032Speter if (mode == O_RDWR) 213638032Speter map->map_lockfd = fd; 213738032Speter else 213838032Speter (void) close(fd); 213964562Sgshapiro# endif /* !LOCK_ON_OPEN */ 214038032Speter 214138032Speter if (db == NULL) 214238032Speter { 214338032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 214490792Sgshapiro aliaswait(map, ".db", false)) 214590792Sgshapiro return true; 214664562Sgshapiro# if !LOCK_ON_OPEN 214738032Speter if (map->map_lockfd >= 0) 214838032Speter (void) close(map->map_lockfd); 214964562Sgshapiro# endif /* !LOCK_ON_OPEN */ 215064562Sgshapiro errno = save_errno; 215138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 215238032Speter syserr("Cannot open %s database %s", 215338032Speter mapclassname, buf); 215490792Sgshapiro return false; 215538032Speter } 215638032Speter 215764562Sgshapiro# if DB_VERSION_MAJOR < 2 215838032Speter fd = db->fd(db); 215964562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 216038032Speter fd = -1; 216138032Speter errno = db->fd(db, &fd); 216264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 216338032Speter if (filechanged(buf, fd, &st)) 216438032Speter { 216564562Sgshapiro save_errno = errno; 216664562Sgshapiro# if DB_VERSION_MAJOR < 2 216764562Sgshapiro (void) db->close(db); 216864562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 216938032Speter errno = db->close(db, 0); 217064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 217164562Sgshapiro# if !LOCK_ON_OPEN 217238032Speter if (map->map_lockfd >= 0) 217364562Sgshapiro (void) close(map->map_lockfd); 217464562Sgshapiro# endif /* !LOCK_ON_OPEN */ 217538032Speter errno = save_errno; 217638032Speter syserr("db_map_open(%s): file changed after open", buf); 217790792Sgshapiro return false; 217838032Speter } 217938032Speter 218038032Speter if (mode == O_RDWR) 218138032Speter map->map_mflags |= MF_LOCKED; 218264562Sgshapiro# if LOCK_ON_OPEN 218338032Speter if (fd >= 0 && mode == O_RDONLY) 218438032Speter { 218538032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 218638032Speter } 218764562Sgshapiro# endif /* LOCK_ON_OPEN */ 218838032Speter 218938032Speter /* try to make sure that at least the database header is on disk */ 219038032Speter if (mode == O_RDWR) 219138032Speter { 219238032Speter (void) db->sync(db, 0); 219342575Speter if (geteuid() == 0 && TrustedUid != 0) 219438032Speter { 219564562Sgshapiro# if HASFCHOWN 219642575Speter if (fchown(fd, TrustedUid, -1) < 0) 219738032Speter { 219838032Speter int err = errno; 219938032Speter 220038032Speter sm_syslog(LOG_ALERT, NOQID, 220138032Speter "ownership change on %s failed: %s", 220290792Sgshapiro buf, sm_errstring(err)); 220338032Speter message("050 ownership change on %s failed: %s", 220490792Sgshapiro buf, sm_errstring(err)); 220538032Speter } 220690792Sgshapiro# else /* HASFCHOWN */ 220790792Sgshapiro sm_syslog(LOG_ALERT, NOQID, 220890792Sgshapiro "no fchown(): cannot change ownership on %s", 220990792Sgshapiro map->map_file); 221090792Sgshapiro message("050 no fchown(): cannot change ownership on %s", 221190792Sgshapiro map->map_file); 221264562Sgshapiro# endif /* HASFCHOWN */ 221338032Speter } 221438032Speter } 221538032Speter 221664562Sgshapiro map->map_db2 = (ARBPTR_T) db; 221764562Sgshapiro 221864562Sgshapiro /* 221964562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 222064562Sgshapiro ** as aliaswait() will call map_lookup() which requires 222164562Sgshapiro ** map_mtime to be set 222264562Sgshapiro */ 222364562Sgshapiro 222438032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 222538032Speter map->map_mtime = st.st_mtime; 222638032Speter 222738032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 222890792Sgshapiro !aliaswait(map, ".db", true)) 222990792Sgshapiro return false; 223090792Sgshapiro return true; 223138032Speter} 223238032Speter 223338032Speter 223438032Speter/* 223538032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 223638032Speter*/ 223738032Speter 223838032Speterchar * 223938032Speterdb_map_lookup(map, name, av, statp) 224038032Speter MAP *map; 224138032Speter char *name; 224238032Speter char **av; 224338032Speter int *statp; 224438032Speter{ 224538032Speter DBT key, val; 224638032Speter register DB *db = (DB *) map->map_db2; 224738032Speter int i; 224838032Speter int st; 224964562Sgshapiro int save_errno; 225038032Speter int fd; 225138032Speter struct stat stbuf; 225238032Speter char keybuf[MAXNAME + 1]; 225398121Sgshapiro char buf[MAXPATHLEN]; 225438032Speter 225564562Sgshapiro memset(&key, '\0', sizeof key); 225664562Sgshapiro memset(&val, '\0', sizeof val); 225738032Speter 225838032Speter if (tTd(38, 20)) 225990792Sgshapiro sm_dprintf("db_map_lookup(%s, %s)\n", 226038032Speter map->map_mname, name); 226138032Speter 226298121Sgshapiro if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf) 226398121Sgshapiro { 226498121Sgshapiro errno = 0; 226598121Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 226698121Sgshapiro syserr("map \"%s\": map file %s name too long", 226798121Sgshapiro map->map_mname, map->map_file); 226898121Sgshapiro return NULL; 226998121Sgshapiro } 227098121Sgshapiro i = strlen(buf); 227138032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 227238032Speter buf[i - 3] = '\0'; 227338032Speter 227438032Speter key.size = strlen(name); 227538032Speter if (key.size > sizeof keybuf - 1) 227638032Speter key.size = sizeof keybuf - 1; 227738032Speter key.data = keybuf; 227864562Sgshapiro memmove(keybuf, name, key.size); 227938032Speter keybuf[key.size] = '\0'; 228038032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 228138032Speter makelower(keybuf); 228238032Speter lockdb: 228364562Sgshapiro# if DB_VERSION_MAJOR < 2 228438032Speter fd = db->fd(db); 228564562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 228638032Speter fd = -1; 228738032Speter errno = db->fd(db, &fd); 228864562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 228938032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 229038032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 229138032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 229238032Speter { 229338032Speter /* Reopen the database to sync the cache */ 229438032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 229538032Speter : O_RDONLY; 229638032Speter 229764562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 229864562Sgshapiro (void) lockfile(fd, buf, ".db", LOCK_UN); 229977349Sgshapiro map->map_mflags |= MF_CLOSING; 230038032Speter map->map_class->map_close(map); 230177349Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 230238032Speter if (map->map_class->map_open(map, omode)) 230338032Speter { 230438032Speter map->map_mflags |= MF_OPEN; 230590792Sgshapiro map->map_pid = CurrentPid; 230638032Speter if ((omode && O_ACCMODE) == O_RDWR) 230738032Speter map->map_mflags |= MF_WRITABLE; 230838032Speter db = (DB *) map->map_db2; 230938032Speter goto lockdb; 231038032Speter } 231138032Speter else 231238032Speter { 231338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 231438032Speter { 231538032Speter extern MAPCLASS BogusMapClass; 231638032Speter 231738032Speter *statp = EX_TEMPFAIL; 231890792Sgshapiro map->map_orgclass = map->map_class; 231938032Speter map->map_class = &BogusMapClass; 232038032Speter map->map_mflags |= MF_OPEN; 232190792Sgshapiro map->map_pid = CurrentPid; 232238032Speter syserr("Cannot reopen DB database %s", 232338032Speter map->map_file); 232438032Speter } 232538032Speter return NULL; 232638032Speter } 232738032Speter } 232838032Speter 232938032Speter st = 1; 233038032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 233138032Speter { 233264562Sgshapiro# if DB_VERSION_MAJOR < 2 233338032Speter st = db->get(db, &key, &val, 0); 233464562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 233538032Speter errno = db->get(db, NULL, &key, &val, 0); 233638032Speter switch (errno) 233738032Speter { 233838032Speter case DB_NOTFOUND: 233938032Speter case DB_KEYEMPTY: 234038032Speter st = 1; 234138032Speter break; 234238032Speter 234338032Speter case 0: 234438032Speter st = 0; 234538032Speter break; 234638032Speter 234738032Speter default: 234838032Speter st = -1; 234938032Speter break; 235038032Speter } 235164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 235238032Speter if (st == 0) 235338032Speter map->map_mflags &= ~MF_TRY1NULL; 235438032Speter } 235538032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 235638032Speter { 235738032Speter key.size++; 235864562Sgshapiro# if DB_VERSION_MAJOR < 2 235938032Speter st = db->get(db, &key, &val, 0); 236064562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 236138032Speter errno = db->get(db, NULL, &key, &val, 0); 236238032Speter switch (errno) 236338032Speter { 236438032Speter case DB_NOTFOUND: 236538032Speter case DB_KEYEMPTY: 236638032Speter st = 1; 236738032Speter break; 236838032Speter 236938032Speter case 0: 237038032Speter st = 0; 237138032Speter break; 237238032Speter 237338032Speter default: 237438032Speter st = -1; 237538032Speter break; 237638032Speter } 237764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 237838032Speter if (st == 0) 237938032Speter map->map_mflags &= ~MF_TRY0NULL; 238038032Speter } 238164562Sgshapiro save_errno = errno; 238238032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 238338032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 238438032Speter if (st != 0) 238538032Speter { 238664562Sgshapiro errno = save_errno; 238738032Speter if (st < 0) 238838032Speter syserr("db_map_lookup: get (%s)", name); 238938032Speter return NULL; 239038032Speter } 239138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 239238032Speter return map_rewrite(map, name, strlen(name), NULL); 239338032Speter else 239438032Speter return map_rewrite(map, val.data, val.size, av); 239538032Speter} 239638032Speter 239738032Speter 239838032Speter/* 239938032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 240038032Speter*/ 240138032Speter 240238032Spetervoid 240338032Speterdb_map_store(map, lhs, rhs) 240438032Speter register MAP *map; 240538032Speter char *lhs; 240638032Speter char *rhs; 240738032Speter{ 240864562Sgshapiro int status; 240938032Speter DBT key; 241038032Speter DBT data; 241138032Speter register DB *db = map->map_db2; 241238032Speter char keybuf[MAXNAME + 1]; 241338032Speter 241464562Sgshapiro memset(&key, '\0', sizeof key); 241564562Sgshapiro memset(&data, '\0', sizeof data); 241638032Speter 241738032Speter if (tTd(38, 12)) 241890792Sgshapiro sm_dprintf("db_map_store(%s, %s, %s)\n", 241938032Speter map->map_mname, lhs, rhs); 242038032Speter 242138032Speter key.size = strlen(lhs); 242238032Speter key.data = lhs; 242338032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 242438032Speter { 242538032Speter if (key.size > sizeof keybuf - 1) 242638032Speter key.size = sizeof keybuf - 1; 242764562Sgshapiro memmove(keybuf, key.data, key.size); 242838032Speter keybuf[key.size] = '\0'; 242938032Speter makelower(keybuf); 243038032Speter key.data = keybuf; 243138032Speter } 243238032Speter 243338032Speter data.size = strlen(rhs); 243438032Speter data.data = rhs; 243538032Speter 243638032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 243738032Speter { 243838032Speter key.size++; 243938032Speter data.size++; 244038032Speter } 244138032Speter 244264562Sgshapiro# if DB_VERSION_MAJOR < 2 244364562Sgshapiro status = db->put(db, &key, &data, R_NOOVERWRITE); 244464562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 244538032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 244638032Speter switch (errno) 244738032Speter { 244838032Speter case DB_KEYEXIST: 244964562Sgshapiro status = 1; 245038032Speter break; 245138032Speter 245238032Speter case 0: 245364562Sgshapiro status = 0; 245438032Speter break; 245538032Speter 245638032Speter default: 245764562Sgshapiro status = -1; 245838032Speter break; 245938032Speter } 246064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 246164562Sgshapiro if (status > 0) 246238032Speter { 246338032Speter if (!bitset(MF_APPEND, map->map_mflags)) 246438032Speter message("050 Warning: duplicate alias name %s", lhs); 246538032Speter else 246638032Speter { 246738032Speter static char *buf = NULL; 246838032Speter static int bufsiz = 0; 246938032Speter DBT old; 247038032Speter 247164562Sgshapiro memset(&old, '\0', sizeof old); 247238032Speter 247364562Sgshapiro old.data = db_map_lookup(map, key.data, 247490792Sgshapiro (char **) NULL, &status); 247538032Speter if (old.data != NULL) 247638032Speter { 247738032Speter old.size = strlen(old.data); 247890792Sgshapiro if (data.size + old.size + 2 > (size_t) bufsiz) 247938032Speter { 248038032Speter if (buf != NULL) 248177349Sgshapiro sm_free(buf); 248238032Speter bufsiz = data.size + old.size + 2; 248390792Sgshapiro buf = sm_pmalloc_x(bufsiz); 248438032Speter } 248590792Sgshapiro (void) sm_strlcpyn(buf, bufsiz, 3, 248690792Sgshapiro (char *) data.data, ",", 248790792Sgshapiro (char *) old.data); 248838032Speter data.size = data.size + old.size + 1; 248938032Speter data.data = buf; 249038032Speter if (tTd(38, 9)) 249190792Sgshapiro sm_dprintf("db_map_store append=%s\n", 249264562Sgshapiro (char *) data.data); 249338032Speter } 249438032Speter } 249564562Sgshapiro# if DB_VERSION_MAJOR < 2 249664562Sgshapiro status = db->put(db, &key, &data, 0); 249764562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 249864562Sgshapiro status = errno = db->put(db, NULL, &key, &data, 0); 249964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 250038032Speter } 250164562Sgshapiro if (status != 0) 250238032Speter syserr("readaliases: db put (%s)", lhs); 250338032Speter} 250438032Speter 250538032Speter 250638032Speter/* 250738032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 250838032Speter*/ 250938032Speter 251038032Spetervoid 251138032Speterdb_map_close(map) 251238032Speter MAP *map; 251338032Speter{ 251438032Speter register DB *db = map->map_db2; 251538032Speter 251638032Speter if (tTd(38, 9)) 251790792Sgshapiro sm_dprintf("db_map_close(%s, %s, %lx)\n", 251838032Speter map->map_mname, map->map_file, map->map_mflags); 251938032Speter 252038032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 252138032Speter { 252238032Speter /* write out the distinguished alias */ 252338032Speter db_map_store(map, "@", "@"); 252438032Speter } 252538032Speter 252638032Speter (void) db->sync(db, 0); 252738032Speter 252864562Sgshapiro# if !LOCK_ON_OPEN 252938032Speter if (map->map_lockfd >= 0) 253038032Speter (void) close(map->map_lockfd); 253164562Sgshapiro# endif /* !LOCK_ON_OPEN */ 253238032Speter 253364562Sgshapiro# if DB_VERSION_MAJOR < 2 253438032Speter if (db->close(db) != 0) 253564562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 253642575Speter /* 253742575Speter ** Berkeley DB can use internal shared memory 253842575Speter ** locking for its memory pool. Closing a map 253942575Speter ** opened by another process will interfere 254042575Speter ** with the shared memory and locks of the parent 254142575Speter ** process leaving things in a bad state. 254243730Speter */ 254343730Speter 254443730Speter /* 254542575Speter ** If this map was not opened by the current 254643730Speter ** process, do not close the map but recover 254742575Speter ** the file descriptor. 254842575Speter */ 254990792Sgshapiro 255090792Sgshapiro if (map->map_pid != CurrentPid) 255142575Speter { 255242575Speter int fd = -1; 255342575Speter 255442575Speter errno = db->fd(db, &fd); 255542575Speter if (fd >= 0) 255642575Speter (void) close(fd); 255742575Speter return; 255842575Speter } 255942575Speter 256038032Speter if ((errno = db->close(db, 0)) != 0) 256164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 256242575Speter syserr("db_map_close(%s, %s, %lx): db close failure", 256342575Speter map->map_mname, map->map_file, map->map_mflags); 256438032Speter} 256564562Sgshapiro#endif /* NEWDB */ 256690792Sgshapiro/* 256738032Speter** NIS Modules 256838032Speter*/ 256938032Speter 257090792Sgshapiro#if NIS 257138032Speter 257238032Speter# ifndef YPERR_BUSY 257338032Speter# define YPERR_BUSY 16 257464562Sgshapiro# endif /* ! YPERR_BUSY */ 257538032Speter 257638032Speter/* 257738032Speter** NIS_MAP_OPEN -- open DBM map 257838032Speter*/ 257938032Speter 258038032Speterbool 258138032Speternis_map_open(map, mode) 258238032Speter MAP *map; 258338032Speter int mode; 258438032Speter{ 258538032Speter int yperr; 258638032Speter register char *p; 258738032Speter auto char *vp; 258838032Speter auto int vsize; 258938032Speter 259038032Speter if (tTd(38, 2)) 259190792Sgshapiro sm_dprintf("nis_map_open(%s, %s, %d)\n", 259238032Speter map->map_mname, map->map_file, mode); 259338032Speter 259438032Speter mode &= O_ACCMODE; 259538032Speter if (mode != O_RDONLY) 259638032Speter { 259738032Speter /* issue a pseudo-error message */ 259890792Sgshapiro errno = SM_EMAPCANTWRITE; 259990792Sgshapiro return false; 260038032Speter } 260138032Speter 260238032Speter p = strchr(map->map_file, '@'); 260338032Speter if (p != NULL) 260438032Speter { 260538032Speter *p++ = '\0'; 260638032Speter if (*p != '\0') 260738032Speter map->map_domain = p; 260838032Speter } 260938032Speter 261038032Speter if (*map->map_file == '\0') 261138032Speter map->map_file = "mail.aliases"; 261238032Speter 261338032Speter if (map->map_domain == NULL) 261438032Speter { 261538032Speter yperr = yp_get_default_domain(&map->map_domain); 261638032Speter if (yperr != 0) 261738032Speter { 261838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 261994334Sgshapiro syserr("451 4.3.5 NIS map %s specified, but NIS not running", 262064562Sgshapiro map->map_file); 262190792Sgshapiro return false; 262238032Speter } 262338032Speter } 262438032Speter 262538032Speter /* check to see if this map actually exists */ 262664562Sgshapiro vp = NULL; 262738032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 262838032Speter &vp, &vsize); 262938032Speter if (tTd(38, 10)) 263090792Sgshapiro sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 263138032Speter map->map_domain, map->map_file, yperr_string(yperr)); 263264562Sgshapiro if (vp != NULL) 263377349Sgshapiro sm_free(vp); 263464562Sgshapiro 263538032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 263638032Speter { 263738032Speter /* 263838032Speter ** We ought to be calling aliaswait() here if this is an 263938032Speter ** alias file, but powerful HP-UX NIS servers apparently 264038032Speter ** don't insert the @:@ token into the alias map when it 264138032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 264238032Speter */ 264338032Speter 264464562Sgshapiro# if 0 264538032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 264690792Sgshapiro aliaswait(map, NULL, true)) 264764562Sgshapiro# endif /* 0 */ 264890792Sgshapiro return true; 264938032Speter } 265038032Speter 265138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 265238032Speter { 265394334Sgshapiro syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s", 265438032Speter map->map_file, map->map_domain, yperr_string(yperr)); 265538032Speter } 265638032Speter 265790792Sgshapiro return false; 265838032Speter} 265938032Speter 266038032Speter 266138032Speter/* 266238032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 266338032Speter*/ 266438032Speter 266538032Speter/* ARGSUSED3 */ 266638032Speterchar * 266738032Speternis_map_lookup(map, name, av, statp) 266838032Speter MAP *map; 266938032Speter char *name; 267038032Speter char **av; 267138032Speter int *statp; 267238032Speter{ 267338032Speter char *vp; 267438032Speter auto int vsize; 267538032Speter int buflen; 267638032Speter int yperr; 267738032Speter char keybuf[MAXNAME + 1]; 267890792Sgshapiro char *SM_NONVOLATILE result = NULL; 267938032Speter 268038032Speter if (tTd(38, 20)) 268190792Sgshapiro sm_dprintf("nis_map_lookup(%s, %s)\n", 268238032Speter map->map_mname, name); 268338032Speter 268438032Speter buflen = strlen(name); 268538032Speter if (buflen > sizeof keybuf - 1) 268638032Speter buflen = sizeof keybuf - 1; 268764562Sgshapiro memmove(keybuf, name, buflen); 268838032Speter keybuf[buflen] = '\0'; 268938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 269038032Speter makelower(keybuf); 269138032Speter yperr = YPERR_KEY; 269264562Sgshapiro vp = NULL; 269338032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 269438032Speter { 269538032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 269638032Speter &vp, &vsize); 269738032Speter if (yperr == 0) 269838032Speter map->map_mflags &= ~MF_TRY1NULL; 269938032Speter } 270038032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 270138032Speter { 270290792Sgshapiro SM_FREE_CLR(vp); 270338032Speter buflen++; 270438032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 270538032Speter &vp, &vsize); 270638032Speter if (yperr == 0) 270738032Speter map->map_mflags &= ~MF_TRY0NULL; 270838032Speter } 270938032Speter if (yperr != 0) 271038032Speter { 271138032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 271238032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 271364562Sgshapiro if (vp != NULL) 271477349Sgshapiro sm_free(vp); 271538032Speter return NULL; 271638032Speter } 271790792Sgshapiro SM_TRY 271890792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 271990792Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 272090792Sgshapiro else 272190792Sgshapiro result = map_rewrite(map, vp, vsize, av); 272290792Sgshapiro SM_FINALLY 272364562Sgshapiro if (vp != NULL) 272477349Sgshapiro sm_free(vp); 272590792Sgshapiro SM_END_TRY 272690792Sgshapiro return result; 272738032Speter} 272838032Speter 272938032Speter 273038032Speter/* 273138032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 273238032Speter*/ 273338032Speter 273464562Sgshapirostatic bool 273538032Speternis_getcanonname(name, hbsize, statp) 273638032Speter char *name; 273738032Speter int hbsize; 273838032Speter int *statp; 273938032Speter{ 274038032Speter char *vp; 274138032Speter auto int vsize; 274238032Speter int keylen; 274338032Speter int yperr; 274490792Sgshapiro static bool try0null = true; 274590792Sgshapiro static bool try1null = true; 274638032Speter static char *yp_domain = NULL; 274738032Speter char host_record[MAXLINE]; 274838032Speter char cbuf[MAXNAME]; 274938032Speter char nbuf[MAXNAME + 1]; 275038032Speter 275138032Speter if (tTd(38, 20)) 275290792Sgshapiro sm_dprintf("nis_getcanonname(%s)\n", name); 275338032Speter 275490792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 275538032Speter { 275638032Speter *statp = EX_UNAVAILABLE; 275790792Sgshapiro return false; 275838032Speter } 275973188Sgshapiro (void) shorten_hostname(nbuf); 276038032Speter keylen = strlen(nbuf); 276138032Speter 276238032Speter if (yp_domain == NULL) 276364562Sgshapiro (void) yp_get_default_domain(&yp_domain); 276438032Speter makelower(nbuf); 276538032Speter yperr = YPERR_KEY; 276664562Sgshapiro vp = NULL; 276738032Speter if (try0null) 276838032Speter { 276938032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 277038032Speter &vp, &vsize); 277138032Speter if (yperr == 0) 277290792Sgshapiro try1null = false; 277338032Speter } 277438032Speter if (yperr == YPERR_KEY && try1null) 277538032Speter { 277690792Sgshapiro SM_FREE_CLR(vp); 277738032Speter keylen++; 277838032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 277938032Speter &vp, &vsize); 278038032Speter if (yperr == 0) 278190792Sgshapiro try0null = false; 278238032Speter } 278338032Speter if (yperr != 0) 278438032Speter { 278538032Speter if (yperr == YPERR_KEY) 278638032Speter *statp = EX_NOHOST; 278738032Speter else if (yperr == YPERR_BUSY) 278838032Speter *statp = EX_TEMPFAIL; 278938032Speter else 279038032Speter *statp = EX_UNAVAILABLE; 279164562Sgshapiro if (vp != NULL) 279277349Sgshapiro sm_free(vp); 279390792Sgshapiro return false; 279438032Speter } 279590792Sgshapiro (void) sm_strlcpy(host_record, vp, sizeof host_record); 279677349Sgshapiro sm_free(vp); 279738032Speter if (tTd(38, 44)) 279890792Sgshapiro sm_dprintf("got record `%s'\n", host_record); 279990792Sgshapiro vp = strpbrk(host_record, "#\n"); 280090792Sgshapiro if (vp != NULL) 280190792Sgshapiro *vp = '\0'; 280273188Sgshapiro if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf)) 280338032Speter { 280438032Speter /* this should not happen, but.... */ 280538032Speter *statp = EX_NOHOST; 280690792Sgshapiro return false; 280738032Speter } 280890792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 280938032Speter { 281038032Speter *statp = EX_UNAVAILABLE; 281190792Sgshapiro return false; 281238032Speter } 281338032Speter *statp = EX_OK; 281490792Sgshapiro return true; 281538032Speter} 281638032Speter 281764562Sgshapiro#endif /* NIS */ 281890792Sgshapiro/* 281938032Speter** NISPLUS Modules 282038032Speter** 282138032Speter** This code donated by Sun Microsystems. 282238032Speter*/ 282338032Speter 282490792Sgshapiro#if NISPLUS 282538032Speter 282664562Sgshapiro# undef NIS /* symbol conflict in nis.h */ 282764562Sgshapiro# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 282864562Sgshapiro# include <rpcsvc/nis.h> 282964562Sgshapiro# include <rpcsvc/nislib.h> 283038032Speter 283164562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 283264562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 283364562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 283464562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 283538032Speter 283638032Speter/* 283738032Speter** NISPLUS_MAP_OPEN -- open nisplus table 283838032Speter*/ 283938032Speter 284038032Speterbool 284138032Speternisplus_map_open(map, mode) 284238032Speter MAP *map; 284338032Speter int mode; 284438032Speter{ 284538032Speter nis_result *res = NULL; 284638032Speter int retry_cnt, max_col, i; 284738032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 284838032Speter 284938032Speter if (tTd(38, 2)) 285090792Sgshapiro sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 285138032Speter map->map_mname, map->map_file, mode); 285238032Speter 285338032Speter mode &= O_ACCMODE; 285438032Speter if (mode != O_RDONLY) 285538032Speter { 285638032Speter errno = EPERM; 285790792Sgshapiro return false; 285838032Speter } 285938032Speter 286038032Speter if (*map->map_file == '\0') 286138032Speter map->map_file = "mail_aliases.org_dir"; 286238032Speter 286338032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 286438032Speter { 286538032Speter /* set default NISPLUS Domain to $m */ 286638032Speter map->map_domain = newstr(nisplus_default_domain()); 286738032Speter if (tTd(38, 2)) 286890792Sgshapiro sm_dprintf("nisplus_map_open(%s): using domain %s\n", 286964562Sgshapiro map->map_file, map->map_domain); 287038032Speter } 287138032Speter if (!PARTIAL_NAME(map->map_file)) 287238032Speter { 287338032Speter map->map_domain = newstr(""); 287490792Sgshapiro (void) sm_strlcpy(qbuf, map->map_file, sizeof qbuf); 287538032Speter } 287638032Speter else 287738032Speter { 287838032Speter /* check to see if this map actually exists */ 287990792Sgshapiro (void) sm_strlcpyn(qbuf, sizeof qbuf, 3, 288090792Sgshapiro map->map_file, ".", map->map_domain); 288138032Speter } 288238032Speter 288338032Speter retry_cnt = 0; 288438032Speter while (res == NULL || res->status != NIS_SUCCESS) 288538032Speter { 288638032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 288738032Speter switch (res->status) 288838032Speter { 288938032Speter case NIS_SUCCESS: 289038032Speter break; 289138032Speter 289238032Speter case NIS_TRYAGAIN: 289338032Speter case NIS_RPCERROR: 289438032Speter case NIS_NAMEUNREACHABLE: 289538032Speter if (retry_cnt++ > 4) 289638032Speter { 289738032Speter errno = EAGAIN; 289890792Sgshapiro return false; 289938032Speter } 290038032Speter /* try not to overwhelm hosed server */ 290138032Speter sleep(2); 290238032Speter break; 290338032Speter 290438032Speter default: /* all other nisplus errors */ 290564562Sgshapiro# if 0 290638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 290794334Sgshapiro syserr("451 4.3.5 Cannot find table %s.%s: %s", 290838032Speter map->map_file, map->map_domain, 290938032Speter nis_sperrno(res->status)); 291064562Sgshapiro# endif /* 0 */ 291138032Speter errno = EAGAIN; 291290792Sgshapiro return false; 291338032Speter } 291438032Speter } 291538032Speter 291638032Speter if (NIS_RES_NUMOBJ(res) != 1 || 291738032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 291838032Speter { 291938032Speter if (tTd(38, 10)) 292090792Sgshapiro sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 292164562Sgshapiro# if 0 292238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 292394334Sgshapiro syserr("451 4.3.5 %s.%s: %s is not a table", 292438032Speter map->map_file, map->map_domain, 292538032Speter nis_sperrno(res->status)); 292664562Sgshapiro# endif /* 0 */ 292738032Speter errno = EBADF; 292890792Sgshapiro return false; 292938032Speter } 293038032Speter /* default key column is column 0 */ 293138032Speter if (map->map_keycolnm == NULL) 293238032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 293338032Speter 293438032Speter max_col = COL_MAX(res); 293538032Speter 293638032Speter /* verify the key column exist */ 293790792Sgshapiro for (i = 0; i < max_col; i++) 293838032Speter { 293964562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 294038032Speter break; 294138032Speter } 294238032Speter if (i == max_col) 294338032Speter { 294438032Speter if (tTd(38, 2)) 294590792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 294638032Speter map->map_file, map->map_keycolnm); 294738032Speter errno = ENOENT; 294890792Sgshapiro return false; 294938032Speter } 295038032Speter 295138032Speter /* default value column is the last column */ 295238032Speter if (map->map_valcolnm == NULL) 295338032Speter { 295438032Speter map->map_valcolno = max_col - 1; 295590792Sgshapiro return true; 295638032Speter } 295738032Speter 295864562Sgshapiro for (i = 0; i< max_col; i++) 295938032Speter { 296038032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 296138032Speter { 296238032Speter map->map_valcolno = i; 296390792Sgshapiro return true; 296438032Speter } 296538032Speter } 296638032Speter 296738032Speter if (tTd(38, 2)) 296890792Sgshapiro sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 296964562Sgshapiro map->map_file, map->map_keycolnm); 297038032Speter errno = ENOENT; 297190792Sgshapiro return false; 297238032Speter} 297338032Speter 297438032Speter 297538032Speter/* 297638032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 297738032Speter*/ 297838032Speter 297938032Speterchar * 298038032Speternisplus_map_lookup(map, name, av, statp) 298138032Speter MAP *map; 298238032Speter char *name; 298338032Speter char **av; 298438032Speter int *statp; 298538032Speter{ 298638032Speter char *p; 298738032Speter auto int vsize; 298838032Speter char *skp; 298938032Speter int skleft; 299038032Speter char search_key[MAXNAME + 4]; 299138032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 299238032Speter nis_result *result; 299338032Speter 299438032Speter if (tTd(38, 20)) 299590792Sgshapiro sm_dprintf("nisplus_map_lookup(%s, %s)\n", 299638032Speter map->map_mname, name); 299738032Speter 299838032Speter if (!bitset(MF_OPEN, map->map_mflags)) 299938032Speter { 300038032Speter if (nisplus_map_open(map, O_RDONLY)) 300142575Speter { 300238032Speter map->map_mflags |= MF_OPEN; 300390792Sgshapiro map->map_pid = CurrentPid; 300442575Speter } 300538032Speter else 300638032Speter { 300738032Speter *statp = EX_UNAVAILABLE; 300838032Speter return NULL; 300938032Speter } 301038032Speter } 301138032Speter 301238032Speter /* 301338032Speter ** Copy the name to the key buffer, escaping double quote characters 301438032Speter ** by doubling them and quoting "]" and "," to avoid having the 301538032Speter ** NIS+ parser choke on them. 301638032Speter */ 301738032Speter 301838032Speter skleft = sizeof search_key - 4; 301938032Speter skp = search_key; 302038032Speter for (p = name; *p != '\0' && skleft > 0; p++) 302138032Speter { 302238032Speter switch (*p) 302338032Speter { 302438032Speter case ']': 302538032Speter case ',': 302638032Speter /* quote the character */ 302738032Speter *skp++ = '"'; 302838032Speter *skp++ = *p; 302938032Speter *skp++ = '"'; 303038032Speter skleft -= 3; 303138032Speter break; 303238032Speter 303338032Speter case '"': 303438032Speter /* double the quote */ 303538032Speter *skp++ = '"'; 303638032Speter skleft--; 303764562Sgshapiro /* FALLTHROUGH */ 303838032Speter 303938032Speter default: 304038032Speter *skp++ = *p; 304138032Speter skleft--; 304238032Speter break; 304338032Speter } 304438032Speter } 304538032Speter *skp = '\0'; 304638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 304738032Speter makelower(search_key); 304838032Speter 304938032Speter /* construct the query */ 305038032Speter if (PARTIAL_NAME(map->map_file)) 305190792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", 305238032Speter map->map_keycolnm, search_key, map->map_file, 305338032Speter map->map_domain); 305438032Speter else 305590792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", 305638032Speter map->map_keycolnm, search_key, map->map_file); 305738032Speter 305838032Speter if (tTd(38, 20)) 305990792Sgshapiro sm_dprintf("qbuf=%s\n", qbuf); 306038032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 306138032Speter if (result->status == NIS_SUCCESS) 306238032Speter { 306338032Speter int count; 306438032Speter char *str; 306538032Speter 306638032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 306738032Speter { 306838032Speter if (LogLevel > 10) 306938032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 307064562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 307164562Sgshapiro map->map_file, count); 307238032Speter 307338032Speter /* ignore second entry */ 307438032Speter if (tTd(38, 20)) 307590792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 307638032Speter name, count); 307738032Speter } 307838032Speter 307938032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 308038032Speter /* set the length of the result */ 308138032Speter if (p == NULL) 308238032Speter p = ""; 308338032Speter vsize = strlen(p); 308438032Speter if (tTd(38, 20)) 308590792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), found %s\n", 308638032Speter name, p); 308738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 308838032Speter str = map_rewrite(map, name, strlen(name), NULL); 308938032Speter else 309038032Speter str = map_rewrite(map, p, vsize, av); 309138032Speter nis_freeresult(result); 309238032Speter *statp = EX_OK; 309338032Speter return str; 309438032Speter } 309538032Speter else 309638032Speter { 309738032Speter if (result->status == NIS_NOTFOUND) 309838032Speter *statp = EX_NOTFOUND; 309938032Speter else if (result->status == NIS_TRYAGAIN) 310038032Speter *statp = EX_TEMPFAIL; 310138032Speter else 310238032Speter { 310338032Speter *statp = EX_UNAVAILABLE; 310438032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 310538032Speter } 310638032Speter } 310738032Speter if (tTd(38, 20)) 310890792Sgshapiro sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 310938032Speter nis_freeresult(result); 311038032Speter return NULL; 311138032Speter} 311238032Speter 311338032Speter 311438032Speter 311538032Speter/* 311638032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 311738032Speter*/ 311838032Speter 311964562Sgshapirostatic bool 312038032Speternisplus_getcanonname(name, hbsize, statp) 312138032Speter char *name; 312238032Speter int hbsize; 312338032Speter int *statp; 312438032Speter{ 312538032Speter char *vp; 312638032Speter auto int vsize; 312738032Speter nis_result *result; 312838032Speter char *p; 312938032Speter char nbuf[MAXNAME + 1]; 313038032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 313138032Speter 313290792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 313338032Speter { 313438032Speter *statp = EX_UNAVAILABLE; 313590792Sgshapiro return false; 313638032Speter } 313773188Sgshapiro (void) shorten_hostname(nbuf); 313838032Speter 313938032Speter p = strchr(nbuf, '.'); 314038032Speter if (p == NULL) 314138032Speter { 314238032Speter /* single token */ 314390792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, 314490792Sgshapiro "[name=%s],hosts.org_dir", nbuf); 314538032Speter } 314638032Speter else if (p[1] != '\0') 314738032Speter { 314838032Speter /* multi token -- take only first token in nbuf */ 314938032Speter *p = '\0'; 315090792Sgshapiro (void) sm_snprintf(qbuf, sizeof qbuf, 315190792Sgshapiro "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 315238032Speter } 315338032Speter else 315438032Speter { 315538032Speter *statp = EX_NOHOST; 315690792Sgshapiro return false; 315738032Speter } 315838032Speter 315938032Speter if (tTd(38, 20)) 316094334Sgshapiro sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 316190792Sgshapiro name, qbuf); 316238032Speter 316338032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 316490792Sgshapiro NULL, NULL); 316538032Speter 316638032Speter if (result->status == NIS_SUCCESS) 316738032Speter { 316838032Speter int count; 316938032Speter char *domain; 317038032Speter 317138032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 317238032Speter { 317338032Speter if (LogLevel > 10) 317438032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 317564562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 317664562Sgshapiro count); 317738032Speter 317838032Speter /* ignore second entry */ 317938032Speter if (tTd(38, 20)) 318094334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 318190792Sgshapiro name, count); 318238032Speter } 318338032Speter 318438032Speter if (tTd(38, 20)) 318594334Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 318690792Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 318738032Speter 318838032Speter 318938032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 319038032Speter vsize = strlen(vp); 319138032Speter if (tTd(38, 20)) 319290792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), found %s\n", 319390792Sgshapiro name, vp); 319438032Speter if (strchr(vp, '.') != NULL) 319538032Speter { 319638032Speter domain = ""; 319738032Speter } 319838032Speter else 319938032Speter { 320038032Speter domain = macvalue('m', CurEnv); 320138032Speter if (domain == NULL) 320238032Speter domain = ""; 320338032Speter } 320438032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 320538032Speter { 320638032Speter if (domain[0] == '\0') 320790792Sgshapiro (void) sm_strlcpy(name, vp, hbsize); 320838032Speter else 320990792Sgshapiro (void) sm_snprintf(name, hbsize, 321090792Sgshapiro "%s.%s", vp, domain); 321138032Speter *statp = EX_OK; 321238032Speter } 321338032Speter else 321438032Speter *statp = EX_NOHOST; 321538032Speter nis_freeresult(result); 321690792Sgshapiro return true; 321738032Speter } 321838032Speter else 321938032Speter { 322038032Speter if (result->status == NIS_NOTFOUND) 322138032Speter *statp = EX_NOHOST; 322238032Speter else if (result->status == NIS_TRYAGAIN) 322338032Speter *statp = EX_TEMPFAIL; 322438032Speter else 322538032Speter *statp = EX_UNAVAILABLE; 322638032Speter } 322738032Speter if (tTd(38, 20)) 322890792Sgshapiro sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 322990792Sgshapiro name, result->status, *statp); 323038032Speter nis_freeresult(result); 323190792Sgshapiro return false; 323238032Speter} 323338032Speter 323438032Speterchar * 323538032Speternisplus_default_domain() 323638032Speter{ 323738032Speter static char default_domain[MAXNAME + 1] = ""; 323838032Speter char *p; 323938032Speter 324038032Speter if (default_domain[0] != '\0') 324164562Sgshapiro return default_domain; 324238032Speter 324338032Speter p = nis_local_directory(); 324490792Sgshapiro (void) sm_strlcpy(default_domain, p, sizeof default_domain); 324538032Speter return default_domain; 324638032Speter} 324738032Speter 324838032Speter#endif /* NISPLUS */ 324990792Sgshapiro/* 325038032Speter** LDAP Modules 325138032Speter*/ 325238032Speter 325364562Sgshapiro/* 325464562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 325564562Sgshapiro*/ 325664562Sgshapiro 325764562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 325864562Sgshapiro 325990792Sgshapiro# if PH_MAP 326064562Sgshapiro# define ph_map_dequote ldapmap_dequote 326164562Sgshapiro# endif /* PH_MAP */ 326264562Sgshapiro 326390792Sgshapirostatic char *ldapmap_dequote __P((char *)); 326490792Sgshapiro 326590792Sgshapirostatic char * 326664562Sgshapiroldapmap_dequote(str) 326764562Sgshapiro char *str; 326864562Sgshapiro{ 326964562Sgshapiro char *p; 327064562Sgshapiro char *start; 327164562Sgshapiro 327264562Sgshapiro if (str == NULL) 327364562Sgshapiro return NULL; 327464562Sgshapiro 327564562Sgshapiro p = str; 327664562Sgshapiro if (*p == '"') 327764562Sgshapiro { 327864562Sgshapiro /* Should probably swallow initial whitespace here */ 327964562Sgshapiro start = ++p; 328064562Sgshapiro } 328164562Sgshapiro else 328264562Sgshapiro return str; 328364562Sgshapiro while (*p != '"' && *p != '\0') 328464562Sgshapiro p++; 328564562Sgshapiro if (*p != '\0') 328664562Sgshapiro *p = '\0'; 328764562Sgshapiro return start; 328864562Sgshapiro} 328964562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 329064562Sgshapiro 329190792Sgshapiro#if LDAPMAP 329238032Speter 329390792Sgshapirostatic SM_LDAP_STRUCT *LDAPDefaults = NULL; 329438032Speter 329538032Speter/* 329664562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 329738032Speter** 329864562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 329964562Sgshapiro** single server connection to a host (with the same host, port, 330064562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 330138032Speter*/ 330238032Speter 330338032Speterbool 330464562Sgshapiroldapmap_open(map, mode) 330538032Speter MAP *map; 330638032Speter int mode; 330738032Speter{ 330890792Sgshapiro SM_LDAP_STRUCT *lmap; 330964562Sgshapiro STAB *s; 331064562Sgshapiro 331138032Speter if (tTd(38, 2)) 331290792Sgshapiro sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 331338032Speter 331438032Speter mode &= O_ACCMODE; 331564562Sgshapiro 331664562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 331738032Speter if (mode != O_RDONLY) 331838032Speter { 331938032Speter /* issue a pseudo-error message */ 332090792Sgshapiro errno = SM_EMAPCANTWRITE; 332190792Sgshapiro return false; 332238032Speter } 332364562Sgshapiro 332490792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 332564562Sgshapiro 332664562Sgshapiro s = ldapmap_findconn(lmap); 332777349Sgshapiro if (s->s_lmap != NULL) 332864562Sgshapiro { 332964562Sgshapiro /* Already have a connection open to this LDAP server */ 333090792Sgshapiro lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 333190792Sgshapiro lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 333277349Sgshapiro 333377349Sgshapiro /* Add this map as head of linked list */ 333477349Sgshapiro lmap->ldap_next = s->s_lmap; 333577349Sgshapiro s->s_lmap = map; 333677349Sgshapiro 333766494Sgshapiro if (tTd(38, 2)) 333890792Sgshapiro sm_dprintf("using cached connection\n"); 333990792Sgshapiro return true; 334064562Sgshapiro } 334164562Sgshapiro 334266494Sgshapiro if (tTd(38, 2)) 334390792Sgshapiro sm_dprintf("opening new connection\n"); 334466494Sgshapiro 334564562Sgshapiro /* No connection yet, connect */ 334690792Sgshapiro if (!sm_ldap_start(map->map_mname, lmap)) 334738032Speter { 334890792Sgshapiro if (errno == ETIMEDOUT) 334938032Speter { 335038032Speter if (LogLevel > 1) 335138032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 335264562Sgshapiro "timeout conning to LDAP server %.100s", 335394334Sgshapiro lmap->ldap_target == NULL ? "localhost" : lmap->ldap_target); 335438032Speter } 335538032Speter 335638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 335738032Speter { 335864562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 335964562Sgshapiro syserr("%s failed to %s in map %s", 336064562Sgshapiro# if USE_LDAP_INIT 336190792Sgshapiro "ldap_init/ldap_bind", 336264562Sgshapiro# else /* USE_LDAP_INIT */ 336364562Sgshapiro "ldap_open", 336464562Sgshapiro# endif /* USE_LDAP_INIT */ 336594334Sgshapiro lmap->ldap_target == NULL ? "localhost" 336694334Sgshapiro : lmap->ldap_target, 336764562Sgshapiro map->map_mname); 336864562Sgshapiro else 336994334Sgshapiro syserr("451 4.3.5 %s failed to %s in map %s", 337064562Sgshapiro# if USE_LDAP_INIT 337190792Sgshapiro "ldap_init/ldap_bind", 337264562Sgshapiro# else /* USE_LDAP_INIT */ 337364562Sgshapiro "ldap_open", 337464562Sgshapiro# endif /* USE_LDAP_INIT */ 337594334Sgshapiro lmap->ldap_target == NULL ? "localhost" 337694334Sgshapiro : lmap->ldap_target, 337764562Sgshapiro map->map_mname); 337838032Speter } 337990792Sgshapiro return false; 338038032Speter } 338138032Speter 338290792Sgshapiro /* Save connection for reuse */ 338390792Sgshapiro s->s_lmap = map; 338490792Sgshapiro return true; 338538032Speter} 338638032Speter 338738032Speter/* 338864562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 338938032Speter*/ 339038032Speter 339138032Spetervoid 339264562Sgshapiroldapmap_close(map) 339338032Speter MAP *map; 339438032Speter{ 339590792Sgshapiro SM_LDAP_STRUCT *lmap; 339664562Sgshapiro STAB *s; 339743730Speter 339864562Sgshapiro if (tTd(38, 2)) 339990792Sgshapiro sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 340064562Sgshapiro 340190792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 340264562Sgshapiro 340364562Sgshapiro /* Check if already closed */ 340464562Sgshapiro if (lmap->ldap_ld == NULL) 340564562Sgshapiro return; 340664562Sgshapiro 340777349Sgshapiro /* Close the LDAP connection */ 340890792Sgshapiro sm_ldap_close(lmap); 340977349Sgshapiro 341077349Sgshapiro /* Mark all the maps that share the connection as closed */ 341164562Sgshapiro s = ldapmap_findconn(lmap); 341264562Sgshapiro 341377349Sgshapiro while (s->s_lmap != NULL) 341477349Sgshapiro { 341577349Sgshapiro MAP *smap = s->s_lmap; 341664562Sgshapiro 341777349Sgshapiro if (tTd(38, 2) && smap != map) 341890792Sgshapiro sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 341990792Sgshapiro map->map_mname, smap->map_mname); 342077349Sgshapiro smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 342190792Sgshapiro lmap = (SM_LDAP_STRUCT *) smap->map_db1; 342264562Sgshapiro lmap->ldap_ld = NULL; 342377349Sgshapiro s->s_lmap = lmap->ldap_next; 342477349Sgshapiro lmap->ldap_next = NULL; 342543730Speter } 342638032Speter} 342738032Speter 342864562Sgshapiro# ifdef SUNET_ID 342943730Speter/* 343090792Sgshapiro** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 343142575Speter** This only makes sense at Stanford University. 343238032Speter*/ 343338032Speter 343490792Sgshapirostatic char * 343538032Spetersunet_id_hash(str) 343638032Speter char *str; 343738032Speter{ 343838032Speter char *p, *p_last; 343938032Speter 344038032Speter p = str; 344138032Speter p_last = p; 344238032Speter while (*p != '\0') 344338032Speter { 344438032Speter if (islower(*p) || isdigit(*p)) 344538032Speter { 344638032Speter *p_last = *p; 344738032Speter p_last++; 344838032Speter } 344938032Speter else if (isupper(*p)) 345038032Speter { 345138032Speter *p_last = tolower(*p); 345238032Speter p_last++; 345338032Speter } 345438032Speter ++p; 345538032Speter } 345638032Speter if (*p_last != '\0') 345738032Speter *p_last = '\0'; 345864562Sgshapiro return str; 345938032Speter} 346064562Sgshapiro# endif /* SUNET_ID */ 346138032Speter 346238032Speter/* 346364562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 346438032Speter*/ 346538032Speter 346638032Speterchar * 346764562Sgshapiroldapmap_lookup(map, name, av, statp) 346838032Speter MAP *map; 346938032Speter char *name; 347038032Speter char **av; 347138032Speter int *statp; 347238032Speter{ 347394334Sgshapiro# if _FFR_LDAP_RECURSION 347494334Sgshapiro int plen = 0; 347594334Sgshapiro int psize = 0; 347694334Sgshapiro# else /* _FFR_LDAP_RECURSION */ 347794334Sgshapiro int entries = 0; 347864562Sgshapiro int i; 347994334Sgshapiro int ret; 348094334Sgshapiro int vsize; 348194334Sgshapiro# endif /* _FFR_LDAP_RECURSION */ 348264562Sgshapiro int msgid; 348390792Sgshapiro int save_errno; 348490792Sgshapiro char *vp, *p; 348564562Sgshapiro char *result = NULL; 348690792Sgshapiro SM_LDAP_STRUCT *lmap = NULL; 348738032Speter char keybuf[MAXNAME + 1]; 348838032Speter 348938032Speter if (tTd(38, 20)) 349090792Sgshapiro sm_dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); 349138032Speter 349238032Speter /* Get ldap struct pointer from map */ 349390792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 349490792Sgshapiro sm_ldap_setopts(lmap->ldap_ld, lmap); 349538032Speter 349690792Sgshapiro (void) sm_strlcpy(keybuf, name, sizeof keybuf); 349738032Speter 349838032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 349964562Sgshapiro { 350064562Sgshapiro# ifdef SUNET_ID 350138032Speter sunet_id_hash(keybuf); 350264562Sgshapiro# else /* SUNET_ID */ 350338032Speter makelower(keybuf); 350464562Sgshapiro# endif /* SUNET_ID */ 350564562Sgshapiro } 350638032Speter 350790792Sgshapiro msgid = sm_ldap_search(lmap, keybuf); 350864562Sgshapiro if (msgid == -1) 350938032Speter { 351090792Sgshapiro errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 351177349Sgshapiro save_errno = errno; 351264562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 351338032Speter { 351464562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 351566494Sgshapiro syserr("Error in ldap_search using %s in map %s", 351690792Sgshapiro keybuf, map->map_mname); 351764562Sgshapiro else 351894334Sgshapiro syserr("451 4.3.5 Error in ldap_search using %s in map %s", 351990792Sgshapiro keybuf, map->map_mname); 352038032Speter } 352164562Sgshapiro *statp = EX_TEMPFAIL; 352290792Sgshapiro switch (save_errno - E_LDAPBASE) 352390792Sgshapiro { 352494334Sgshapiro# ifdef LDAP_SERVER_DOWN 352590792Sgshapiro case LDAP_SERVER_DOWN: 352694334Sgshapiro# endif /* LDAP_SERVER_DOWN */ 352790792Sgshapiro case LDAP_TIMEOUT: 352890792Sgshapiro case LDAP_UNAVAILABLE: 352966494Sgshapiro /* server disappeared, try reopen on next search */ 353077349Sgshapiro ldapmap_close(map); 353190792Sgshapiro break; 353266494Sgshapiro } 353377349Sgshapiro errno = save_errno; 353464562Sgshapiro return NULL; 353564562Sgshapiro } 353664562Sgshapiro 353764562Sgshapiro *statp = EX_NOTFOUND; 353864562Sgshapiro vp = NULL; 353964562Sgshapiro 354090792Sgshapiro# if _FFR_LDAP_RECURSION 354190792Sgshapiro { 354290792Sgshapiro int flags; 354390792Sgshapiro SM_RPOOL_T *rpool; 354490792Sgshapiro 354590792Sgshapiro flags = 0; 354690792Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 354790792Sgshapiro flags |= SM_LDAP_SINGLEMATCH; 354890792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 354990792Sgshapiro flags |= SM_LDAP_MATCHONLY; 355090792Sgshapiro 355190792Sgshapiro /* Create an rpool for search related memory usage */ 355290792Sgshapiro rpool = sm_rpool_new_x(NULL); 355390792Sgshapiro 355490792Sgshapiro p = NULL; 355590792Sgshapiro *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 355694334Sgshapiro rpool, &p, &plen, &psize, NULL); 355790792Sgshapiro save_errno = errno; 355890792Sgshapiro 355990792Sgshapiro /* Copy result so rpool can be freed */ 356090792Sgshapiro if (*statp == EX_OK && p != NULL) 356190792Sgshapiro vp = newstr(p); 356290792Sgshapiro sm_rpool_free(rpool); 356390792Sgshapiro 356490792Sgshapiro /* need to restart LDAP connection? */ 356590792Sgshapiro if (*statp == EX_RESTART) 356690792Sgshapiro { 356790792Sgshapiro *statp = EX_TEMPFAIL; 356890792Sgshapiro ldapmap_close(map); 356990792Sgshapiro } 357090792Sgshapiro 357190792Sgshapiro errno = save_errno; 357290792Sgshapiro if (*statp != EX_OK && *statp != EX_NOTFOUND) 357390792Sgshapiro { 357490792Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 357590792Sgshapiro { 357690792Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 357790792Sgshapiro syserr("Error getting LDAP results in map %s", 357890792Sgshapiro map->map_mname); 357990792Sgshapiro else 358094334Sgshapiro syserr("451 4.3.5 Error getting LDAP results in map %s", 358190792Sgshapiro map->map_mname); 358290792Sgshapiro } 358390792Sgshapiro errno = save_errno; 358490792Sgshapiro return NULL; 358590792Sgshapiro } 358690792Sgshapiro } 358794334Sgshapiro# else /* _FFR_LDAP_RECURSION */ 358890792Sgshapiro 358990792Sgshapiro /* Get results */ 359090792Sgshapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, 359164562Sgshapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 359264562Sgshapiro &(lmap->ldap_timeout)), 359364562Sgshapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 359464562Sgshapiro { 359564562Sgshapiro LDAPMessage *entry; 359664562Sgshapiro 359764562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 359838032Speter { 359964562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, 360064562Sgshapiro lmap->ldap_res); 360164562Sgshapiro if (entries > 1) 360264562Sgshapiro { 360364562Sgshapiro *statp = EX_NOTFOUND; 360464562Sgshapiro if (lmap->ldap_res != NULL) 360564562Sgshapiro { 360664562Sgshapiro ldap_msgfree(lmap->ldap_res); 360764562Sgshapiro lmap->ldap_res = NULL; 360864562Sgshapiro } 360964562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 361064562Sgshapiro if (vp != NULL) 361190792Sgshapiro sm_free(vp); /* XXX */ 361264562Sgshapiro if (tTd(38, 25)) 361390792Sgshapiro sm_dprintf("ldap search found multiple on a single match query\n"); 361464562Sgshapiro return NULL; 361564562Sgshapiro } 361664562Sgshapiro } 361764562Sgshapiro 361864562Sgshapiro /* If we don't want multiple values and we have one, break */ 361964562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 362064562Sgshapiro break; 362164562Sgshapiro 362264562Sgshapiro /* Cycle through all entries */ 362364562Sgshapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 362464562Sgshapiro entry != NULL; 362564562Sgshapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 362664562Sgshapiro { 362764562Sgshapiro BerElement *ber; 362864562Sgshapiro char *attr; 362964562Sgshapiro char **vals = NULL; 363064562Sgshapiro 363164562Sgshapiro /* 363264562Sgshapiro ** If matching only and found an entry, 363364562Sgshapiro ** no need to spin through attributes 363464562Sgshapiro */ 363564562Sgshapiro 363664562Sgshapiro if (*statp == EX_OK && 363764562Sgshapiro bitset(MF_MATCHONLY, map->map_mflags)) 363864562Sgshapiro continue; 363964562Sgshapiro 364094334Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 364164562Sgshapiro /* 364264562Sgshapiro ** Reset value to prevent lingering 364364562Sgshapiro ** LDAP_DECODING_ERROR due to 364464562Sgshapiro ** OpenLDAP 1.X's hack (see below) 364564562Sgshapiro */ 364664562Sgshapiro 364764562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 364894334Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 364964562Sgshapiro 365064562Sgshapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 365164562Sgshapiro &ber); 365264562Sgshapiro attr != NULL; 365364562Sgshapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 365464562Sgshapiro ber)) 365564562Sgshapiro { 365664562Sgshapiro char *tmp, *vp_tmp; 365764562Sgshapiro 365864562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 365964562Sgshapiro { 366064562Sgshapiro vals = ldap_get_values(lmap->ldap_ld, 366164562Sgshapiro entry, 366264562Sgshapiro attr); 366364562Sgshapiro if (vals == NULL) 366464562Sgshapiro { 366590792Sgshapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 366690792Sgshapiro if (save_errno == LDAP_SUCCESS) 366790792Sgshapiro { 366890792Sgshapiro ldap_memfree(attr); 366964562Sgshapiro continue; 367090792Sgshapiro } 367164562Sgshapiro 367264562Sgshapiro /* Must be an error */ 367390792Sgshapiro save_errno += E_LDAPBASE; 367464562Sgshapiro if (!bitset(MF_OPTIONAL, 367564562Sgshapiro map->map_mflags)) 367664562Sgshapiro { 367790792Sgshapiro errno = save_errno; 367864562Sgshapiro if (bitset(MF_NODEFER, 367964562Sgshapiro map->map_mflags)) 368064562Sgshapiro syserr("Error getting LDAP values in map %s", 368164562Sgshapiro map->map_mname); 368264562Sgshapiro else 368394334Sgshapiro syserr("451 4.3.5 Error getting LDAP values in map %s", 368464562Sgshapiro map->map_mname); 368564562Sgshapiro } 368664562Sgshapiro *statp = EX_TEMPFAIL; 368766494Sgshapiro ldap_memfree(attr); 368864562Sgshapiro if (lmap->ldap_res != NULL) 368964562Sgshapiro { 369064562Sgshapiro ldap_msgfree(lmap->ldap_res); 369164562Sgshapiro lmap->ldap_res = NULL; 369264562Sgshapiro } 369364562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, 369464562Sgshapiro msgid); 369564562Sgshapiro if (vp != NULL) 369690792Sgshapiro sm_free(vp); /* XXX */ 369790792Sgshapiro errno = save_errno; 369864562Sgshapiro return NULL; 369964562Sgshapiro } 370064562Sgshapiro } 370164562Sgshapiro 370264562Sgshapiro *statp = EX_OK; 370364562Sgshapiro 370494334Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 370564562Sgshapiro /* 370664562Sgshapiro ** Reset value to prevent lingering 370764562Sgshapiro ** LDAP_DECODING_ERROR due to 370864562Sgshapiro ** OpenLDAP 1.X's hack (see below) 370964562Sgshapiro */ 371064562Sgshapiro 371164562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 371294334Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 371364562Sgshapiro 371464562Sgshapiro /* 371564562Sgshapiro ** If matching only, 371664562Sgshapiro ** no need to spin through entries 371764562Sgshapiro */ 371864562Sgshapiro 371964562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 372090792Sgshapiro { 372190792Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 372290792Sgshapiro ldap_value_free(vals); 372390792Sgshapiro 372490792Sgshapiro ldap_memfree(attr); 372564562Sgshapiro continue; 372690792Sgshapiro } 372764562Sgshapiro 372864562Sgshapiro /* 372964562Sgshapiro ** If we don't want multiple values, 373064562Sgshapiro ** return first found. 373164562Sgshapiro */ 373264562Sgshapiro 373364562Sgshapiro if (map->map_coldelim == '\0') 373464562Sgshapiro { 373564562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 373664562Sgshapiro { 373764562Sgshapiro vp = newstr(attr); 373866494Sgshapiro ldap_memfree(attr); 373964562Sgshapiro break; 374064562Sgshapiro } 374164562Sgshapiro 374264562Sgshapiro if (vals[0] == NULL) 374364562Sgshapiro { 374464562Sgshapiro ldap_value_free(vals); 374566494Sgshapiro ldap_memfree(attr); 374664562Sgshapiro continue; 374764562Sgshapiro } 374864562Sgshapiro 374990792Sgshapiro vsize = strlen(vals[0]) + 1; 375090792Sgshapiro if (lmap->ldap_attrsep != '\0') 375190792Sgshapiro vsize += strlen(attr) + 1; 375290792Sgshapiro vp = xalloc(vsize); 375390792Sgshapiro if (lmap->ldap_attrsep != '\0') 375490792Sgshapiro sm_snprintf(vp, vsize, 375590792Sgshapiro "%s%c%s", 375690792Sgshapiro attr, 375790792Sgshapiro lmap->ldap_attrsep, 375890792Sgshapiro vals[0]); 375990792Sgshapiro else 376090792Sgshapiro sm_strlcpy(vp, vals[0], vsize); 376164562Sgshapiro ldap_value_free(vals); 376266494Sgshapiro ldap_memfree(attr); 376364562Sgshapiro break; 376464562Sgshapiro } 376564562Sgshapiro 376664562Sgshapiro /* attributes only */ 376764562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 376864562Sgshapiro { 376964562Sgshapiro if (vp == NULL) 377064562Sgshapiro vp = newstr(attr); 377164562Sgshapiro else 377264562Sgshapiro { 377364562Sgshapiro vsize = strlen(vp) + 377464562Sgshapiro strlen(attr) + 2; 377564562Sgshapiro tmp = xalloc(vsize); 377690792Sgshapiro (void) sm_snprintf(tmp, 377790792Sgshapiro vsize, "%s%c%s", 377890792Sgshapiro vp, map->map_coldelim, 377990792Sgshapiro attr); 378090792Sgshapiro sm_free(vp); /* XXX */ 378164562Sgshapiro vp = tmp; 378264562Sgshapiro } 378366494Sgshapiro ldap_memfree(attr); 378464562Sgshapiro continue; 378564562Sgshapiro } 378664562Sgshapiro 378764562Sgshapiro /* 378864562Sgshapiro ** If there is more than one, 378964562Sgshapiro ** munge then into a map_coldelim 379064562Sgshapiro ** separated string 379164562Sgshapiro */ 379264562Sgshapiro 379364562Sgshapiro vsize = 0; 379464562Sgshapiro for (i = 0; vals[i] != NULL; i++) 379590792Sgshapiro { 379664562Sgshapiro vsize += strlen(vals[i]) + 1; 379790792Sgshapiro if (lmap->ldap_attrsep != '\0') 379890792Sgshapiro vsize += strlen(attr) + 1; 379990792Sgshapiro } 380064562Sgshapiro vp_tmp = xalloc(vsize); 380164562Sgshapiro *vp_tmp = '\0'; 380264562Sgshapiro 380364562Sgshapiro p = vp_tmp; 380464562Sgshapiro for (i = 0; vals[i] != NULL; i++) 380564562Sgshapiro { 380690792Sgshapiro if (lmap->ldap_attrsep != '\0') 380790792Sgshapiro { 380890792Sgshapiro p += sm_strlcpy(p, attr, 380990792Sgshapiro vsize - (p - vp_tmp)); 3810102528Sgshapiro if (p >= vp_tmp + vsize) 3811102528Sgshapiro syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values"); 381290792Sgshapiro *p++ = lmap->ldap_attrsep; 381390792Sgshapiro } 381490792Sgshapiro p += sm_strlcpy(p, vals[i], 381590792Sgshapiro vsize - (p - vp_tmp)); 381664562Sgshapiro if (p >= vp_tmp + vsize) 381764562Sgshapiro syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values"); 381864562Sgshapiro if (vals[i + 1] != NULL) 381964562Sgshapiro *p++ = map->map_coldelim; 382064562Sgshapiro } 382164562Sgshapiro 382264562Sgshapiro ldap_value_free(vals); 382366494Sgshapiro ldap_memfree(attr); 382464562Sgshapiro if (vp == NULL) 382564562Sgshapiro { 382664562Sgshapiro vp = vp_tmp; 382764562Sgshapiro continue; 382864562Sgshapiro } 382964562Sgshapiro vsize = strlen(vp) + strlen(vp_tmp) + 2; 383064562Sgshapiro tmp = xalloc(vsize); 383190792Sgshapiro (void) sm_snprintf(tmp, vsize, "%s%c%s", 383264562Sgshapiro vp, map->map_coldelim, vp_tmp); 383364562Sgshapiro 383490792Sgshapiro sm_free(vp); /* XXX */ 383590792Sgshapiro sm_free(vp_tmp); /* XXX */ 383664562Sgshapiro vp = tmp; 383764562Sgshapiro } 383890792Sgshapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 383964562Sgshapiro 384064562Sgshapiro /* 384164562Sgshapiro ** We check errno != LDAP_DECODING_ERROR since 384264562Sgshapiro ** OpenLDAP 1.X has a very ugly *undocumented* 384364562Sgshapiro ** hack of returning this error code from 384464562Sgshapiro ** ldap_next_attribute() if the library freed the 384564562Sgshapiro ** ber attribute. See: 384664562Sgshapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 384764562Sgshapiro */ 384864562Sgshapiro 384990792Sgshapiro if (save_errno != LDAP_SUCCESS && 385090792Sgshapiro save_errno != LDAP_DECODING_ERROR) 385164562Sgshapiro { 385264562Sgshapiro /* Must be an error */ 385390792Sgshapiro save_errno += E_LDAPBASE; 385464562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 385564562Sgshapiro { 385690792Sgshapiro errno = save_errno; 385764562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 385864562Sgshapiro syserr("Error getting LDAP attributes in map %s", 385964562Sgshapiro map->map_mname); 386064562Sgshapiro else 386194334Sgshapiro syserr("451 4.3.5 Error getting LDAP attributes in map %s", 386264562Sgshapiro map->map_mname); 386364562Sgshapiro } 386464562Sgshapiro *statp = EX_TEMPFAIL; 386564562Sgshapiro if (lmap->ldap_res != NULL) 386664562Sgshapiro { 386764562Sgshapiro ldap_msgfree(lmap->ldap_res); 386864562Sgshapiro lmap->ldap_res = NULL; 386964562Sgshapiro } 387064562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 387164562Sgshapiro if (vp != NULL) 387290792Sgshapiro sm_free(vp); /* XXX */ 387390792Sgshapiro errno = save_errno; 387464562Sgshapiro return NULL; 387564562Sgshapiro } 387664562Sgshapiro 387764562Sgshapiro /* We don't want multiple values and we have one */ 387864562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 387964562Sgshapiro break; 388064562Sgshapiro } 388190792Sgshapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 388290792Sgshapiro if (save_errno != LDAP_SUCCESS && 388390792Sgshapiro save_errno != LDAP_DECODING_ERROR) 388464562Sgshapiro { 388564562Sgshapiro /* Must be an error */ 388690792Sgshapiro save_errno += E_LDAPBASE; 388738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 388838032Speter { 388990792Sgshapiro errno = save_errno; 389064562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 389164562Sgshapiro syserr("Error getting LDAP entries in map %s", 389264562Sgshapiro map->map_mname); 389364562Sgshapiro else 389494334Sgshapiro syserr("451 4.3.5 Error getting LDAP entries in map %s", 389564562Sgshapiro map->map_mname); 389638032Speter } 389738032Speter *statp = EX_TEMPFAIL; 389864562Sgshapiro if (lmap->ldap_res != NULL) 389964562Sgshapiro { 390064562Sgshapiro ldap_msgfree(lmap->ldap_res); 390164562Sgshapiro lmap->ldap_res = NULL; 390264562Sgshapiro } 390364562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 390464562Sgshapiro if (vp != NULL) 390590792Sgshapiro sm_free(vp); /* XXX */ 390690792Sgshapiro errno = save_errno; 390764562Sgshapiro return NULL; 390838032Speter } 390964562Sgshapiro ldap_msgfree(lmap->ldap_res); 391064562Sgshapiro lmap->ldap_res = NULL; 391138032Speter } 391238032Speter 391364562Sgshapiro if (ret == 0) 391490792Sgshapiro save_errno = ETIMEDOUT; 391564562Sgshapiro else 391690792Sgshapiro save_errno = sm_ldap_geterrno(lmap->ldap_ld); 391790792Sgshapiro if (save_errno != LDAP_SUCCESS) 391838032Speter { 391964562Sgshapiro if (ret != 0) 392090792Sgshapiro save_errno += E_LDAPBASE; 392177349Sgshapiro 392264562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 392364562Sgshapiro { 392490792Sgshapiro errno = save_errno; 392564562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 392664562Sgshapiro syserr("Error getting LDAP results in map %s", 392764562Sgshapiro map->map_mname); 392864562Sgshapiro else 392994334Sgshapiro syserr("451 4.3.5 Error getting LDAP results in map %s", 393064562Sgshapiro map->map_mname); 393164562Sgshapiro } 393264562Sgshapiro *statp = EX_TEMPFAIL; 393364562Sgshapiro if (vp != NULL) 393490792Sgshapiro sm_free(vp); /* XXX */ 393590792Sgshapiro 393690792Sgshapiro switch (save_errno - E_LDAPBASE) 393790792Sgshapiro { 393894334Sgshapiro# ifdef LDAP_SERVER_DOWN 393990792Sgshapiro case LDAP_SERVER_DOWN: 394094334Sgshapiro# endif /* LDAP_SERVER_DOWN */ 394190792Sgshapiro case LDAP_TIMEOUT: 394290792Sgshapiro case LDAP_UNAVAILABLE: 394377349Sgshapiro /* server disappeared, try reopen on next search */ 394477349Sgshapiro ldapmap_close(map); 394590792Sgshapiro break; 394677349Sgshapiro } 394777349Sgshapiro errno = save_errno; 394864562Sgshapiro return NULL; 394938032Speter } 395090792Sgshapiro# endif /* _FFR_LDAP_RECURSION */ 395190792Sgshapiro 395264562Sgshapiro /* Did we match anything? */ 395371345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 395464562Sgshapiro return NULL; 395538032Speter 395664562Sgshapiro if (*statp == EX_OK) 395764562Sgshapiro { 395864562Sgshapiro if (LogLevel > 9) 395964562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 396071345Sgshapiro "ldap %.100s => %s", name, 396171345Sgshapiro vp == NULL ? "<NULL>" : vp); 396264562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 396364562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 396464562Sgshapiro else 396571345Sgshapiro { 396671345Sgshapiro /* vp != NULL according to test above */ 396764562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 396871345Sgshapiro } 396971345Sgshapiro if (vp != NULL) 397090792Sgshapiro sm_free(vp); /* XXX */ 397164562Sgshapiro } 397264562Sgshapiro return result; 397338032Speter} 397438032Speter 397538032Speter/* 397664562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 397764562Sgshapiro** 397864562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 397966494Sgshapiro** secret, and PID so we don't have multiple connections open to 398066494Sgshapiro** the same server for different maps. Need a separate connection 398166494Sgshapiro** per PID since a parent process may close the map before the 398266494Sgshapiro** child is done with it. 398364562Sgshapiro** 398464562Sgshapiro** Parameters: 398564562Sgshapiro** lmap -- LDAP map information 398664562Sgshapiro** 398764562Sgshapiro** Returns: 398864562Sgshapiro** Symbol table entry for the LDAP connection. 398938032Speter*/ 399038032Speter 399164562Sgshapirostatic STAB * 399264562Sgshapiroldapmap_findconn(lmap) 399390792Sgshapiro SM_LDAP_STRUCT *lmap; 399438032Speter{ 399594334Sgshapiro char *format; 399664562Sgshapiro char *nbuf; 399790792Sgshapiro STAB *SM_NONVOLATILE s = NULL; 399838032Speter 399994334Sgshapiro# if _FFR_LDAP_SETVERSION 400094334Sgshapiro format = "%s%c%d%c%d%c%s%c%s%d"; 400194334Sgshapiro# else /* _FFR_LDAP_SETVERSION */ 400294334Sgshapiro format = "%s%c%d%c%s%c%s%d"; 400394334Sgshapiro# endif /* _FFR_LDAP_SETVERSION */ 400494334Sgshapiro nbuf = sm_stringf_x(format, 400594334Sgshapiro (lmap->ldap_target == NULL ? "localhost" 400694334Sgshapiro : lmap->ldap_target), 400790792Sgshapiro CONDELSE, 400890792Sgshapiro lmap->ldap_port, 400990792Sgshapiro CONDELSE, 401094334Sgshapiro# if _FFR_LDAP_SETVERSION 401194334Sgshapiro lmap->ldap_version, 401294334Sgshapiro CONDELSE, 401394334Sgshapiro# endif /* _FFR_LDAP_SETVERSION */ 401490792Sgshapiro (lmap->ldap_binddn == NULL ? "" 401590792Sgshapiro : lmap->ldap_binddn), 401690792Sgshapiro CONDELSE, 401790792Sgshapiro (lmap->ldap_secret == NULL ? "" 401890792Sgshapiro : lmap->ldap_secret), 401990792Sgshapiro (int) CurrentPid); 402090792Sgshapiro SM_TRY 402190792Sgshapiro s = stab(nbuf, ST_LMAP, ST_ENTER); 402290792Sgshapiro SM_FINALLY 402390792Sgshapiro sm_free(nbuf); 402490792Sgshapiro SM_END_TRY 402564562Sgshapiro return s; 402664562Sgshapiro} 402738032Speter/* 402864562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 402964562Sgshapiro*/ 403038032Speter 403190792Sgshapirostatic struct lamvalues LDAPAuthMethods[] = 403264562Sgshapiro{ 403364562Sgshapiro { "none", LDAP_AUTH_NONE }, 403464562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 403564562Sgshapiro# ifdef LDAP_AUTH_KRBV4 403664562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 403764562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 403864562Sgshapiro { NULL, 0 } 403964562Sgshapiro}; 404038032Speter 404190792Sgshapirostatic struct ladvalues LDAPAliasDereference[] = 404264562Sgshapiro{ 404364562Sgshapiro { "never", LDAP_DEREF_NEVER }, 404464562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 404564562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 404664562Sgshapiro { "find", LDAP_DEREF_FINDING }, 404764562Sgshapiro { NULL, 0 } 404864562Sgshapiro}; 404938032Speter 405090792Sgshapirostatic struct lssvalues LDAPSearchScope[] = 405164562Sgshapiro{ 405264562Sgshapiro { "base", LDAP_SCOPE_BASE }, 405364562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 405464562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 405564562Sgshapiro { NULL, 0 } 405664562Sgshapiro}; 405738032Speter 405864562Sgshapirobool 405964562Sgshapiroldapmap_parseargs(map, args) 406064562Sgshapiro MAP *map; 406164562Sgshapiro char *args; 406264562Sgshapiro{ 406390792Sgshapiro bool secretread = true; 406494334Sgshapiro# if _FFR_LDAP_URI 406594334Sgshapiro bool ldaphost = false; 406694334Sgshapiro# endif /* _FFR_LDAP_URI */ 406764562Sgshapiro int i; 406864562Sgshapiro register char *p = args; 406990792Sgshapiro SM_LDAP_STRUCT *lmap; 407064562Sgshapiro struct lamvalues *lam; 407164562Sgshapiro struct ladvalues *lad; 407264562Sgshapiro struct lssvalues *lss; 407390792Sgshapiro char ldapfilt[MAXLINE]; 407464562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 407564562Sgshapiro 407664562Sgshapiro /* Get ldap struct pointer from map */ 407790792Sgshapiro lmap = (SM_LDAP_STRUCT *) map->map_db1; 407864562Sgshapiro 407964562Sgshapiro /* Check if setting the initial LDAP defaults */ 408064562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 408164562Sgshapiro { 408290792Sgshapiro /* We need to alloc an SM_LDAP_STRUCT struct */ 408390792Sgshapiro lmap = (SM_LDAP_STRUCT *) xalloc(sizeof *lmap); 408464562Sgshapiro if (LDAPDefaults == NULL) 408590792Sgshapiro sm_ldap_clear(lmap); 408664562Sgshapiro else 408764562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 408864562Sgshapiro } 408964562Sgshapiro 409064562Sgshapiro /* there is no check whether there is really an argument */ 409164562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 409264562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 409390792Sgshapiro 409490792Sgshapiro /* Check if setting up an alias or file class LDAP map */ 409590792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 409690792Sgshapiro { 409790792Sgshapiro /* Comma separate if used as an alias file */ 409890792Sgshapiro map->map_coldelim = ','; 409990792Sgshapiro if (*args == '\0') 410090792Sgshapiro { 410190792Sgshapiro int n; 410290792Sgshapiro char *lc; 410390792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 410490792Sgshapiro char lcbuf[MAXLINE]; 410590792Sgshapiro 410690792Sgshapiro /* Get $j */ 410790792Sgshapiro expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 410890792Sgshapiro if (jbuf[0] == '\0') 410990792Sgshapiro { 411090792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 411190792Sgshapiro sizeof jbuf); 411290792Sgshapiro } 411390792Sgshapiro 411490792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 411590792Sgshapiro if (lc == NULL) 411690792Sgshapiro lc = ""; 411790792Sgshapiro else 411890792Sgshapiro { 411990792Sgshapiro expand(lc, lcbuf, sizeof lcbuf, CurEnv); 412090792Sgshapiro lc = lcbuf; 412190792Sgshapiro } 412290792Sgshapiro 412390792Sgshapiro n = sm_snprintf(ldapfilt, sizeof ldapfilt, 412490792Sgshapiro "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 412590792Sgshapiro lc, jbuf); 412690792Sgshapiro if (n >= sizeof ldapfilt) 412790792Sgshapiro { 412890792Sgshapiro syserr("%s: Default LDAP string too long", 412990792Sgshapiro map->map_mname); 413090792Sgshapiro return false; 413190792Sgshapiro } 413290792Sgshapiro 413390792Sgshapiro /* default args for an alias LDAP entry */ 413490792Sgshapiro lmap->ldap_filter = ldapfilt; 413590792Sgshapiro lmap->ldap_attr[0] = "sendmailMTAAliasValue"; 413690792Sgshapiro lmap->ldap_attr[1] = NULL; 413790792Sgshapiro } 413890792Sgshapiro } 413990792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 414090792Sgshapiro { 414190792Sgshapiro /* Space separate if used as a file class file */ 414290792Sgshapiro map->map_coldelim = ' '; 414390792Sgshapiro } 414490792Sgshapiro 414538032Speter for (;;) 414638032Speter { 414738032Speter while (isascii(*p) && isspace(*p)) 414838032Speter p++; 414938032Speter if (*p != '-') 415038032Speter break; 415138032Speter switch (*++p) 415238032Speter { 415338032Speter case 'N': 415438032Speter map->map_mflags |= MF_INCLNULL; 415538032Speter map->map_mflags &= ~MF_TRY0NULL; 415638032Speter break; 415738032Speter 415838032Speter case 'O': 415938032Speter map->map_mflags &= ~MF_TRY1NULL; 416038032Speter break; 416138032Speter 416238032Speter case 'o': 416338032Speter map->map_mflags |= MF_OPTIONAL; 416438032Speter break; 416538032Speter 416638032Speter case 'f': 416738032Speter map->map_mflags |= MF_NOFOLDCASE; 416838032Speter break; 416938032Speter 417038032Speter case 'm': 417138032Speter map->map_mflags |= MF_MATCHONLY; 417238032Speter break; 417338032Speter 417438032Speter case 'A': 417538032Speter map->map_mflags |= MF_APPEND; 417638032Speter break; 417738032Speter 417838032Speter case 'q': 417938032Speter map->map_mflags |= MF_KEEPQUOTES; 418038032Speter break; 418138032Speter 418238032Speter case 'a': 418338032Speter map->map_app = ++p; 418438032Speter break; 418538032Speter 418638032Speter case 'T': 418738032Speter map->map_tapp = ++p; 418838032Speter break; 418938032Speter 419064562Sgshapiro case 't': 419164562Sgshapiro map->map_mflags |= MF_NODEFER; 419264562Sgshapiro break; 419364562Sgshapiro 419464562Sgshapiro case 'S': 419564562Sgshapiro map->map_spacesub = *++p; 419664562Sgshapiro break; 419764562Sgshapiro 419864562Sgshapiro case 'D': 419964562Sgshapiro map->map_mflags |= MF_DEFER; 420064562Sgshapiro break; 420164562Sgshapiro 420264562Sgshapiro case 'z': 420364562Sgshapiro if (*++p != '\\') 420464562Sgshapiro map->map_coldelim = *p; 420564562Sgshapiro else 420664562Sgshapiro { 420764562Sgshapiro switch (*++p) 420864562Sgshapiro { 420964562Sgshapiro case 'n': 421064562Sgshapiro map->map_coldelim = '\n'; 421164562Sgshapiro break; 421264562Sgshapiro 421364562Sgshapiro case 't': 421464562Sgshapiro map->map_coldelim = '\t'; 421564562Sgshapiro break; 421664562Sgshapiro 421764562Sgshapiro default: 421864562Sgshapiro map->map_coldelim = '\\'; 421964562Sgshapiro } 422064562Sgshapiro } 422164562Sgshapiro break; 422264562Sgshapiro 422364562Sgshapiro /* Start of ldapmap specific args */ 422490792Sgshapiro case 'V': 422590792Sgshapiro if (*++p != '\\') 422690792Sgshapiro lmap->ldap_attrsep = *p; 422790792Sgshapiro else 422890792Sgshapiro { 422990792Sgshapiro switch (*++p) 423090792Sgshapiro { 423190792Sgshapiro case 'n': 423290792Sgshapiro lmap->ldap_attrsep = '\n'; 423390792Sgshapiro break; 423490792Sgshapiro 423590792Sgshapiro case 't': 423690792Sgshapiro lmap->ldap_attrsep = '\t'; 423790792Sgshapiro break; 423890792Sgshapiro 423990792Sgshapiro default: 424090792Sgshapiro lmap->ldap_attrsep = '\\'; 424190792Sgshapiro } 424290792Sgshapiro } 424390792Sgshapiro break; 424490792Sgshapiro 424538032Speter case 'k': /* search field */ 424638032Speter while (isascii(*++p) && isspace(*p)) 424738032Speter continue; 424864562Sgshapiro lmap->ldap_filter = p; 424938032Speter break; 425038032Speter 425138032Speter case 'v': /* attr to return */ 425238032Speter while (isascii(*++p) && isspace(*p)) 425338032Speter continue; 425464562Sgshapiro lmap->ldap_attr[0] = p; 425564562Sgshapiro lmap->ldap_attr[1] = NULL; 425638032Speter break; 425738032Speter 425864562Sgshapiro case '1': 425964562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 426064562Sgshapiro break; 426164562Sgshapiro 426238032Speter /* args stolen from ldapsearch.c */ 426338032Speter case 'R': /* don't auto chase referrals */ 426464562Sgshapiro# ifdef LDAP_REFERRALS 426538032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 426664562Sgshapiro# else /* LDAP_REFERRALS */ 426790792Sgshapiro syserr("compile with -DLDAP_REFERRALS for referral support"); 426864562Sgshapiro# endif /* LDAP_REFERRALS */ 426938032Speter break; 427038032Speter 427164562Sgshapiro case 'n': /* retrieve attribute names only */ 427264562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 427338032Speter break; 427438032Speter 427564562Sgshapiro case 'r': /* alias dereferencing */ 427664562Sgshapiro while (isascii(*++p) && isspace(*p)) 427764562Sgshapiro continue; 427864562Sgshapiro 427990792Sgshapiro if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 428064562Sgshapiro p += 11; 428164562Sgshapiro 428264562Sgshapiro for (lad = LDAPAliasDereference; 428364562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 428438032Speter { 428590792Sgshapiro if (sm_strncasecmp(p, lad->lad_name, 428690792Sgshapiro strlen(lad->lad_name)) == 0) 428764562Sgshapiro break; 428838032Speter } 428964562Sgshapiro if (lad->lad_name != NULL) 429064562Sgshapiro lmap->ldap_deref = lad->lad_code; 429164562Sgshapiro else 429238032Speter { 429364562Sgshapiro /* bad config line */ 429464562Sgshapiro if (!bitset(MCF_OPTFILE, 429564562Sgshapiro map->map_class->map_cflags)) 429664562Sgshapiro { 429764562Sgshapiro char *ptr; 429864562Sgshapiro 429964562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 430064562Sgshapiro *ptr = '\0'; 430173188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 430264562Sgshapiro p, map->map_mname); 430364562Sgshapiro if (ptr != NULL) 430464562Sgshapiro *ptr = ' '; 430590792Sgshapiro return false; 430664562Sgshapiro } 430738032Speter } 430864562Sgshapiro break; 430964562Sgshapiro 431064562Sgshapiro case 's': /* search scope */ 431164562Sgshapiro while (isascii(*++p) && isspace(*p)) 431264562Sgshapiro continue; 431364562Sgshapiro 431490792Sgshapiro if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 431564562Sgshapiro p += 11; 431664562Sgshapiro 431764562Sgshapiro for (lss = LDAPSearchScope; 431864562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 431938032Speter { 432090792Sgshapiro if (sm_strncasecmp(p, lss->lss_name, 432190792Sgshapiro strlen(lss->lss_name)) == 0) 432264562Sgshapiro break; 432338032Speter } 432464562Sgshapiro if (lss->lss_name != NULL) 432564562Sgshapiro lmap->ldap_scope = lss->lss_code; 432638032Speter else 432764562Sgshapiro { 432864562Sgshapiro /* bad config line */ 432964562Sgshapiro if (!bitset(MCF_OPTFILE, 433064562Sgshapiro map->map_class->map_cflags)) 433138032Speter { 433238032Speter char *ptr; 433338032Speter 433438032Speter if ((ptr = strchr(p, ' ')) != NULL) 433538032Speter *ptr = '\0'; 433673188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 433738032Speter p, map->map_mname); 433838032Speter if (ptr != NULL) 433938032Speter *ptr = ' '; 434090792Sgshapiro return false; 434138032Speter } 434238032Speter } 434338032Speter break; 434438032Speter 434538032Speter case 'h': /* ldap host */ 434638032Speter while (isascii(*++p) && isspace(*p)) 434738032Speter continue; 434894334Sgshapiro# if _FFR_LDAP_URI 434994334Sgshapiro if (lmap->ldap_uri) 435094334Sgshapiro { 435194334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 435294334Sgshapiro map->map_mname); 435394334Sgshapiro return false; 435494334Sgshapiro } 435594334Sgshapiro ldaphost = true; 435694334Sgshapiro# endif /* _FFR_LDAP_URI */ 435794334Sgshapiro lmap->ldap_target = p; 435838032Speter break; 435938032Speter 436038032Speter case 'b': /* search base */ 436138032Speter while (isascii(*++p) && isspace(*p)) 436238032Speter continue; 436364562Sgshapiro lmap->ldap_base = p; 436438032Speter break; 436538032Speter 436638032Speter case 'p': /* ldap port */ 436738032Speter while (isascii(*++p) && isspace(*p)) 436838032Speter continue; 436964562Sgshapiro lmap->ldap_port = atoi(p); 437038032Speter break; 437138032Speter 437238032Speter case 'l': /* time limit */ 437338032Speter while (isascii(*++p) && isspace(*p)) 437438032Speter continue; 437564562Sgshapiro lmap->ldap_timelimit = atoi(p); 437664562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 437738032Speter break; 437838032Speter 437964562Sgshapiro case 'Z': 438064562Sgshapiro while (isascii(*++p) && isspace(*p)) 438164562Sgshapiro continue; 438264562Sgshapiro lmap->ldap_sizelimit = atoi(p); 438364562Sgshapiro break; 438464562Sgshapiro 438564562Sgshapiro case 'd': /* Dn to bind to server as */ 438664562Sgshapiro while (isascii(*++p) && isspace(*p)) 438764562Sgshapiro continue; 438864562Sgshapiro lmap->ldap_binddn = p; 438964562Sgshapiro break; 439064562Sgshapiro 439164562Sgshapiro case 'M': /* Method for binding */ 439264562Sgshapiro while (isascii(*++p) && isspace(*p)) 439364562Sgshapiro continue; 439464562Sgshapiro 439590792Sgshapiro if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 439664562Sgshapiro p += 10; 439764562Sgshapiro 439864562Sgshapiro for (lam = LDAPAuthMethods; 439964562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 440064562Sgshapiro { 440190792Sgshapiro if (sm_strncasecmp(p, lam->lam_name, 440290792Sgshapiro strlen(lam->lam_name)) == 0) 440364562Sgshapiro break; 440464562Sgshapiro } 440564562Sgshapiro if (lam->lam_name != NULL) 440664562Sgshapiro lmap->ldap_method = lam->lam_code; 440764562Sgshapiro else 440864562Sgshapiro { 440964562Sgshapiro /* bad config line */ 441064562Sgshapiro if (!bitset(MCF_OPTFILE, 441164562Sgshapiro map->map_class->map_cflags)) 441264562Sgshapiro { 441364562Sgshapiro char *ptr; 441464562Sgshapiro 441564562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 441664562Sgshapiro *ptr = '\0'; 441773188Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 441864562Sgshapiro p, map->map_mname); 441964562Sgshapiro if (ptr != NULL) 442064562Sgshapiro *ptr = ' '; 442190792Sgshapiro return false; 442264562Sgshapiro } 442364562Sgshapiro } 442464562Sgshapiro 442564562Sgshapiro break; 442664562Sgshapiro 442764562Sgshapiro /* 442864562Sgshapiro ** This is a string that is dependent on the 442964562Sgshapiro ** method used defined above. 443064562Sgshapiro */ 443164562Sgshapiro 443264562Sgshapiro case 'P': /* Secret password for binding */ 443364562Sgshapiro while (isascii(*++p) && isspace(*p)) 443464562Sgshapiro continue; 443564562Sgshapiro lmap->ldap_secret = p; 443690792Sgshapiro secretread = false; 443764562Sgshapiro break; 443864562Sgshapiro 443994334Sgshapiro# if _FFR_LDAP_URI 444094334Sgshapiro case 'H': /* Use LDAP URI */ 444194334Sgshapiro# if !USE_LDAP_INIT 444294334Sgshapiro syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 444394334Sgshapiro map->map_mname); 444494334Sgshapiro return false; 444594334Sgshapiro# else /* !USE_LDAP_INIT */ 444694334Sgshapiro if (ldaphost) 444794334Sgshapiro { 444894334Sgshapiro syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 444994334Sgshapiro map->map_mname); 445094334Sgshapiro return false; 445194334Sgshapiro } 445294334Sgshapiro while (isascii(*++p) && isspace(*p)) 445394334Sgshapiro continue; 445494334Sgshapiro lmap->ldap_target = p; 445594334Sgshapiro lmap->ldap_uri = true; 445694334Sgshapiro break; 445794334Sgshapiro# endif /* !USE_LDAP_INIT */ 445894334Sgshapiro# endif /* _FFR_LDAP_URI */ 445994334Sgshapiro 446094334Sgshapiro# if _FFR_LDAP_SETVERSION 446194334Sgshapiro case 'w': 446294334Sgshapiro /* -w should be for passwd, -P should be for version */ 446394334Sgshapiro while (isascii(*++p) && isspace(*p)) 446494334Sgshapiro continue; 446594334Sgshapiro lmap->ldap_version = atoi(p); 446694334Sgshapiro# ifdef LDAP_VERSION_MAX 446794334Sgshapiro if (lmap->ldap_version > LDAP_VERSION_MAX) 446894334Sgshapiro { 446994334Sgshapiro syserr("LDAP version %d exceeds max of %d in map %s", 447094334Sgshapiro lmap->ldap_version, LDAP_VERSION_MAX, 447194334Sgshapiro map->map_mname); 447294334Sgshapiro return false; 447394334Sgshapiro } 447494334Sgshapiro# endif /* LDAP_VERSION_MAX */ 447594334Sgshapiro# ifdef LDAP_VERSION_MIN 447694334Sgshapiro if (lmap->ldap_version < LDAP_VERSION_MIN) 447794334Sgshapiro { 447894334Sgshapiro syserr("LDAP version %d is lower than min of %d in map %s", 447994334Sgshapiro lmap->ldap_version, LDAP_VERSION_MIN, 448094334Sgshapiro map->map_mname); 448194334Sgshapiro return false; 448294334Sgshapiro } 448394334Sgshapiro# endif /* LDAP_VERSION_MIN */ 448494334Sgshapiro break; 448594334Sgshapiro# endif /* _FFR_LDAP_SETVERSION */ 448694334Sgshapiro 448764562Sgshapiro default: 448864562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 448964562Sgshapiro break; 449038032Speter } 449138032Speter 449264562Sgshapiro /* need to account for quoted strings here */ 449364562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 449438032Speter { 449538032Speter if (*p == '"') 449638032Speter { 449738032Speter while (*++p != '"' && *p != '\0') 449838032Speter continue; 449938032Speter if (*p != '\0') 450038032Speter p++; 450138032Speter } 450238032Speter else 450338032Speter p++; 450438032Speter } 450538032Speter 450638032Speter if (*p != '\0') 450738032Speter *p++ = '\0'; 450838032Speter } 450938032Speter 451038032Speter if (map->map_app != NULL) 451164562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 451238032Speter if (map->map_tapp != NULL) 451364562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 451438032Speter 451538032Speter /* 451642575Speter ** We need to swallow up all the stuff into a struct 451742575Speter ** and dump it into map->map_dbptr1 451838032Speter */ 451938032Speter 452094334Sgshapiro if (lmap->ldap_target != NULL && 452164562Sgshapiro (LDAPDefaults == NULL || 452264562Sgshapiro LDAPDefaults == lmap || 452394334Sgshapiro LDAPDefaults->ldap_target != lmap->ldap_target)) 452494334Sgshapiro lmap->ldap_target = newstr(ldapmap_dequote(lmap->ldap_target)); 452594334Sgshapiro map->map_domain = lmap->ldap_target; 452664562Sgshapiro 452764562Sgshapiro if (lmap->ldap_binddn != NULL && 452864562Sgshapiro (LDAPDefaults == NULL || 452964562Sgshapiro LDAPDefaults == lmap || 453064562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 453164562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 453264562Sgshapiro 453364562Sgshapiro if (lmap->ldap_secret != NULL && 453464562Sgshapiro (LDAPDefaults == NULL || 453564562Sgshapiro LDAPDefaults == lmap || 453664562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 453738032Speter { 453890792Sgshapiro SM_FILE_T *sfd; 453964562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 454038032Speter 454164562Sgshapiro if (DontLockReadFiles) 454264562Sgshapiro sff |= SFF_NOLOCK; 454338032Speter 454464562Sgshapiro /* need to use method to map secret to passwd string */ 454564562Sgshapiro switch (lmap->ldap_method) 454664562Sgshapiro { 454764562Sgshapiro case LDAP_AUTH_NONE: 454864562Sgshapiro /* Do nothing */ 454964562Sgshapiro break; 455038032Speter 455164562Sgshapiro case LDAP_AUTH_SIMPLE: 455238032Speter 455364562Sgshapiro /* 455464562Sgshapiro ** Secret is the name of a file with 455564562Sgshapiro ** the first line as the password. 455664562Sgshapiro */ 455764562Sgshapiro 455864562Sgshapiro /* Already read in the secret? */ 455964562Sgshapiro if (secretread) 456064562Sgshapiro break; 456164562Sgshapiro 456264562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 456364562Sgshapiro O_RDONLY, 0, sff); 456464562Sgshapiro if (sfd == NULL) 456564562Sgshapiro { 456664562Sgshapiro syserr("LDAP map: cannot open secret %s", 456764562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 456890792Sgshapiro return false; 456964562Sgshapiro } 457098121Sgshapiro lmap->ldap_secret = sfgets(m_tmp, sizeof m_tmp, 457166494Sgshapiro sfd, TimeOuts.to_fileopen, 457266494Sgshapiro "ldapmap_parseargs"); 457390792Sgshapiro (void) sm_io_close(sfd, SM_TIME_DEFAULT); 457498121Sgshapiro if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 457598121Sgshapiro { 457698121Sgshapiro syserr("LDAP map: secret in %s too long", 457798121Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 457898121Sgshapiro return false; 457998121Sgshapiro } 458064562Sgshapiro if (lmap->ldap_secret != NULL && 458164562Sgshapiro strlen(m_tmp) > 0) 458264562Sgshapiro { 458364562Sgshapiro /* chomp newline */ 458464562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 458564562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 458664562Sgshapiro 458764562Sgshapiro lmap->ldap_secret = m_tmp; 458864562Sgshapiro } 458964562Sgshapiro break; 459064562Sgshapiro 459164562Sgshapiro# ifdef LDAP_AUTH_KRBV4 459264562Sgshapiro case LDAP_AUTH_KRBV4: 459364562Sgshapiro 459464562Sgshapiro /* 459564562Sgshapiro ** Secret is where the ticket file is 459664562Sgshapiro ** stashed 459764562Sgshapiro */ 459864562Sgshapiro 459998121Sgshapiro (void) sm_snprintf(m_tmp, sizeof m_tmp, 460090792Sgshapiro "KRBTKFILE=%s", 460190792Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 460264562Sgshapiro lmap->ldap_secret = m_tmp; 460364562Sgshapiro break; 460464562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 460564562Sgshapiro 460664562Sgshapiro default: /* Should NEVER get here */ 460764562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 460890792Sgshapiro return false; 460990792Sgshapiro /* NOTREACHED */ 461064562Sgshapiro break; 461164562Sgshapiro } 461238032Speter } 461338032Speter 461464562Sgshapiro if (lmap->ldap_secret != NULL && 461564562Sgshapiro (LDAPDefaults == NULL || 461664562Sgshapiro LDAPDefaults == lmap || 461764562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 461864562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 461938032Speter 462064562Sgshapiro if (lmap->ldap_base != NULL && 462164562Sgshapiro (LDAPDefaults == NULL || 462264562Sgshapiro LDAPDefaults == lmap || 462364562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 462464562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 462564562Sgshapiro 462664562Sgshapiro /* 462764562Sgshapiro ** Save the server from extra work. If request is for a single 462864562Sgshapiro ** match, tell the server to only return enough records to 462964562Sgshapiro ** determine if there is a single match or not. This can not 463064562Sgshapiro ** be one since the server would only return one and we wouldn't 463164562Sgshapiro ** know if there were others available. 463264562Sgshapiro */ 463364562Sgshapiro 463464562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 463564562Sgshapiro lmap->ldap_sizelimit = 2; 463664562Sgshapiro 463764562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 463864562Sgshapiro if (lmap == LDAPDefaults) 463990792Sgshapiro return true; 464064562Sgshapiro 464164562Sgshapiro if (lmap->ldap_filter != NULL) 464264562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 464338032Speter else 464438032Speter { 464538032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 464638032Speter { 464738032Speter syserr("No filter given in map %s", map->map_mname); 464890792Sgshapiro return false; 464938032Speter } 465038032Speter } 465164562Sgshapiro 465264562Sgshapiro if (lmap->ldap_attr[0] != NULL) 465338032Speter { 465494334Sgshapiro# if _FFR_LDAP_RECURSION 465590792Sgshapiro bool recurse = false; 465694334Sgshapiro bool normalseen = false; 465794334Sgshapiro# endif /* _FFR_LDAP_RECURSION */ 465890792Sgshapiro 465964562Sgshapiro i = 0; 466064562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 466164562Sgshapiro lmap->ldap_attr[0] = NULL; 466264562Sgshapiro 466394334Sgshapiro# if _FFR_LDAP_RECURSION 466494334Sgshapiro /* Prime the attr list with the objectClass attribute */ 466594334Sgshapiro lmap->ldap_attr[i] = "objectClass"; 466694334Sgshapiro lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 466794334Sgshapiro lmap->ldap_attr_needobjclass[i] = NULL; 466894334Sgshapiro i++; 466994334Sgshapiro# endif /* _FFR_LDAP_RECURSION */ 467094334Sgshapiro 467164562Sgshapiro while (p != NULL) 467238032Speter { 467364562Sgshapiro char *v; 467464562Sgshapiro 467564562Sgshapiro while (isascii(*p) && isspace(*p)) 467664562Sgshapiro p++; 467764562Sgshapiro if (*p == '\0') 467864562Sgshapiro break; 467964562Sgshapiro v = p; 468064562Sgshapiro p = strchr(v, ','); 468164562Sgshapiro if (p != NULL) 468264562Sgshapiro *p++ = '\0'; 468364562Sgshapiro 468471345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 468564562Sgshapiro { 468664562Sgshapiro syserr("Too many return attributes in %s (max %d)", 468764562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 468890792Sgshapiro return false; 468964562Sgshapiro } 469064562Sgshapiro if (*v != '\0') 469190792Sgshapiro { 469294334Sgshapiro# if _FFR_LDAP_RECURSION 469394334Sgshapiro int j; 469494334Sgshapiro int use; 469590792Sgshapiro char *type; 469694334Sgshapiro char *needobjclass; 469790792Sgshapiro 469890792Sgshapiro type = strchr(v, ':'); 469990792Sgshapiro if (type != NULL) 470094334Sgshapiro { 470190792Sgshapiro *type++ = '\0'; 470294334Sgshapiro needobjclass = strchr(type, ':'); 470394334Sgshapiro if (needobjclass != NULL) 470494334Sgshapiro *needobjclass++ = '\0'; 470594334Sgshapiro } 470694334Sgshapiro else 470794334Sgshapiro { 470894334Sgshapiro needobjclass = NULL; 470994334Sgshapiro } 471090792Sgshapiro 471194334Sgshapiro use = i; 471290792Sgshapiro 471394334Sgshapiro /* allow override on "objectClass" type */ 471494334Sgshapiro if (sm_strcasecmp(v, "objectClass") == 0 && 471594334Sgshapiro lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 471690792Sgshapiro { 471794334Sgshapiro use = 0; 471894334Sgshapiro } 471994334Sgshapiro else 472094334Sgshapiro { 472194334Sgshapiro /* 472294334Sgshapiro ** Don't add something to attribute 472394334Sgshapiro ** list twice. 472494334Sgshapiro */ 472594334Sgshapiro 472694334Sgshapiro for (j = 1; j < i; j++) 472790792Sgshapiro { 472894334Sgshapiro if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 472994334Sgshapiro { 473094334Sgshapiro syserr("Duplicate attribute (%s) in %s", 473194334Sgshapiro v, map->map_mname); 473294334Sgshapiro return false; 473394334Sgshapiro } 473490792Sgshapiro } 473594334Sgshapiro 473694334Sgshapiro lmap->ldap_attr[use] = newstr(v); 473794334Sgshapiro if (needobjclass != NULL && 473894334Sgshapiro *needobjclass != '\0' && 473994334Sgshapiro *needobjclass != '*') 474090792Sgshapiro { 474194334Sgshapiro lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 474294334Sgshapiro } 474394334Sgshapiro else 474494334Sgshapiro { 474594334Sgshapiro lmap->ldap_attr_needobjclass[use] = NULL; 474694334Sgshapiro } 474794334Sgshapiro 474894334Sgshapiro } 474994334Sgshapiro 475094334Sgshapiro if (type != NULL && *type != '\0') 475194334Sgshapiro { 475294334Sgshapiro if (sm_strcasecmp(type, "dn") == 0) 475394334Sgshapiro { 475490792Sgshapiro recurse = true; 475594334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 475690792Sgshapiro } 475790792Sgshapiro else if (sm_strcasecmp(type, "filter") == 0) 475890792Sgshapiro { 475990792Sgshapiro recurse = true; 476094334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 476190792Sgshapiro } 476290792Sgshapiro else if (sm_strcasecmp(type, "url") == 0) 476390792Sgshapiro { 476490792Sgshapiro recurse = true; 476594334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 476690792Sgshapiro } 476794334Sgshapiro else if (sm_strcasecmp(type, "normal") == 0) 476890792Sgshapiro { 476994334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 477094334Sgshapiro normalseen = true; 477190792Sgshapiro } 477290792Sgshapiro else 477390792Sgshapiro { 477490792Sgshapiro syserr("Unknown attribute type (%s) in %s", 477590792Sgshapiro type, map->map_mname); 477690792Sgshapiro return false; 477790792Sgshapiro } 477890792Sgshapiro } 477990792Sgshapiro else 478094334Sgshapiro { 478194334Sgshapiro lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 478294334Sgshapiro normalseen = true; 478394334Sgshapiro } 478494334Sgshapiro# else /* _FFR_LDAP_RECURSION */ 478594334Sgshapiro lmap->ldap_attr[i] = newstr(v); 478694334Sgshapiro# endif /* _FFR_LDAP_RECURSION */ 478790792Sgshapiro i++; 478890792Sgshapiro } 478938032Speter } 479064562Sgshapiro lmap->ldap_attr[i] = NULL; 479194334Sgshapiro# if _FFR_LDAP_RECURSION 479294334Sgshapiro if (recurse && !normalseen) 479390792Sgshapiro { 479494334Sgshapiro syserr("LDAP recursion requested in %s but no returnable attribute given", 479590792Sgshapiro map->map_mname); 479690792Sgshapiro return false; 479790792Sgshapiro } 479890792Sgshapiro if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 479990792Sgshapiro { 480090792Sgshapiro syserr("LDAP recursion requested in %s can not be used with -n", 480190792Sgshapiro map->map_mname); 480290792Sgshapiro return false; 480390792Sgshapiro } 480494334Sgshapiro# endif /* _FFR_LDAP_RECURSION */ 480538032Speter } 480638032Speter map->map_db1 = (ARBPTR_T) lmap; 480790792Sgshapiro return true; 480838032Speter} 480938032Speter 481064562Sgshapiro/* 481164562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 481264562Sgshapiro** 481364562Sgshapiro** Parameters: 481464562Sgshapiro** spec -- map argument string from LDAPDefaults option 481564562Sgshapiro** 481664562Sgshapiro** Returns: 481764562Sgshapiro** None. 481864562Sgshapiro*/ 481964562Sgshapiro 482064562Sgshapirovoid 482164562Sgshapiroldapmap_set_defaults(spec) 482264562Sgshapiro char *spec; 482364562Sgshapiro{ 482473188Sgshapiro STAB *class; 482564562Sgshapiro MAP map; 482664562Sgshapiro 482764562Sgshapiro /* Allocate and set the default values */ 482864562Sgshapiro if (LDAPDefaults == NULL) 482990792Sgshapiro LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 483090792Sgshapiro sm_ldap_clear(LDAPDefaults); 483164562Sgshapiro 483264562Sgshapiro memset(&map, '\0', sizeof map); 483373188Sgshapiro 483473188Sgshapiro /* look up the class */ 483573188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 483673188Sgshapiro if (class == NULL) 483773188Sgshapiro { 483873188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 483973188Sgshapiro return; 484073188Sgshapiro } 484173188Sgshapiro map.map_class = &class->s_mapclass; 484264562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 484373188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 484464562Sgshapiro 484564562Sgshapiro (void) ldapmap_parseargs(&map, spec); 484664562Sgshapiro 484764562Sgshapiro /* These should never be set in LDAPDefaults */ 484864562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 484964562Sgshapiro map.map_spacesub != SpaceSub || 485064562Sgshapiro map.map_app != NULL || 485164562Sgshapiro map.map_tapp != NULL) 485264562Sgshapiro { 485364562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 485490792Sgshapiro SM_FREE_CLR(map.map_app); 485590792Sgshapiro SM_FREE_CLR(map.map_tapp); 485664562Sgshapiro } 485764562Sgshapiro 485864562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 485964562Sgshapiro { 486064562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 486194334Sgshapiro 486264562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 486364562Sgshapiro LDAPDefaults->ldap_filter = NULL; 486464562Sgshapiro } 486564562Sgshapiro 486664562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 486764562Sgshapiro { 486864562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 486964562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 487064562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 487164562Sgshapiro } 487264562Sgshapiro} 487364562Sgshapiro#endif /* LDAPMAP */ 487490792Sgshapiro/* 487564562Sgshapiro** PH map 487664562Sgshapiro*/ 487764562Sgshapiro 487890792Sgshapiro#if PH_MAP 487964562Sgshapiro 488064562Sgshapiro/* 488164562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 488264562Sgshapiro** This code is intended to replace the so-called "ph mailer". 488364562Sgshapiro** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 488464562Sgshapiro*/ 488564562Sgshapiro 488690792Sgshapiro/* what version of the ph map code we're running */ 4887110560Sgshapirostatic char phmap_id[128]; 488864562Sgshapiro 488990792Sgshapiro/* sendmail version for phmap id string */ 489090792Sgshapiroextern const char Version[]; 489190792Sgshapiro 4892110560Sgshapiro/* assume we're using nph-1.1.x if not specified */ 4893110560Sgshapiro# ifndef NPH_VERSION 4894110560Sgshapiro# define NPH_VERSION 10100 4895110560Sgshapiro# endif 4896110560Sgshapiro 4897110560Sgshapiro/* compatibility for versions older than nph-1.2.0 */ 4898110560Sgshapiro# if NPH_VERSION < 10200 4899110560Sgshapiro# define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 4900110560Sgshapiro# define PH_OPEN_DONTID PH_DONTID 4901110560Sgshapiro# define PH_CLOSE_FAST PH_FASTCLOSE 4902110560Sgshapiro# define PH_ERR_DATAERR PH_DATAERR 4903110560Sgshapiro# define PH_ERR_NOMATCH PH_NOMATCH 4904110560Sgshapiro# endif /* NPH_VERSION < 10200 */ 4905110560Sgshapiro 490664562Sgshapiro/* 490764562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 490864562Sgshapiro*/ 490964562Sgshapiro 491064562Sgshapirobool 491164562Sgshapiroph_map_parseargs(map, args) 491264562Sgshapiro MAP *map; 491364562Sgshapiro char *args; 491464562Sgshapiro{ 491590792Sgshapiro register bool done; 491690792Sgshapiro register char *p = args; 491764562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 491864562Sgshapiro 491990792Sgshapiro /* initialize version string */ 492090792Sgshapiro (void) sm_snprintf(phmap_id, sizeof phmap_id, 492190792Sgshapiro "sendmail-%s phmap-20010529 libphclient-%s", 492290792Sgshapiro Version, libphclient_version); 492390792Sgshapiro 492464562Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 492564562Sgshapiro 492664562Sgshapiro /* defaults */ 492764562Sgshapiro pmap->ph_servers = NULL; 492864562Sgshapiro pmap->ph_field_list = NULL; 492990792Sgshapiro pmap->ph = NULL; 493064562Sgshapiro pmap->ph_timeout = 0; 493190792Sgshapiro pmap->ph_fastclose = 0; 493264562Sgshapiro 493364562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 493464562Sgshapiro for (;;) 493564562Sgshapiro { 493664562Sgshapiro while (isascii(*p) && isspace(*p)) 493764562Sgshapiro p++; 493864562Sgshapiro if (*p != '-') 493964562Sgshapiro break; 494064562Sgshapiro switch (*++p) 494164562Sgshapiro { 494264562Sgshapiro case 'N': 494364562Sgshapiro map->map_mflags |= MF_INCLNULL; 494464562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 494564562Sgshapiro break; 494664562Sgshapiro 494764562Sgshapiro case 'O': 494864562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 494964562Sgshapiro break; 495064562Sgshapiro 495164562Sgshapiro case 'o': 495264562Sgshapiro map->map_mflags |= MF_OPTIONAL; 495364562Sgshapiro break; 495464562Sgshapiro 495564562Sgshapiro case 'f': 495664562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 495764562Sgshapiro break; 495864562Sgshapiro 495964562Sgshapiro case 'm': 496064562Sgshapiro map->map_mflags |= MF_MATCHONLY; 496164562Sgshapiro break; 496264562Sgshapiro 496364562Sgshapiro case 'A': 496464562Sgshapiro map->map_mflags |= MF_APPEND; 496564562Sgshapiro break; 496664562Sgshapiro 496764562Sgshapiro case 'q': 496864562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 496964562Sgshapiro break; 497064562Sgshapiro 497164562Sgshapiro case 't': 497264562Sgshapiro map->map_mflags |= MF_NODEFER; 497364562Sgshapiro break; 497464562Sgshapiro 497564562Sgshapiro case 'a': 497664562Sgshapiro map->map_app = ++p; 497764562Sgshapiro break; 497864562Sgshapiro 497964562Sgshapiro case 'T': 498064562Sgshapiro map->map_tapp = ++p; 498164562Sgshapiro break; 498264562Sgshapiro 498364562Sgshapiro case 'l': 498464562Sgshapiro while (isascii(*++p) && isspace(*p)) 498564562Sgshapiro continue; 498664562Sgshapiro pmap->ph_timeout = atoi(p); 498764562Sgshapiro break; 498864562Sgshapiro 498964562Sgshapiro case 'S': 499064562Sgshapiro map->map_spacesub = *++p; 499164562Sgshapiro break; 499264562Sgshapiro 499364562Sgshapiro case 'D': 499464562Sgshapiro map->map_mflags |= MF_DEFER; 499564562Sgshapiro break; 499664562Sgshapiro 499764562Sgshapiro case 'h': /* PH server list */ 499864562Sgshapiro while (isascii(*++p) && isspace(*p)) 499964562Sgshapiro continue; 500064562Sgshapiro pmap->ph_servers = p; 500164562Sgshapiro break; 500264562Sgshapiro 500390792Sgshapiro case 'v': 500490792Sgshapiro sm_syslog(LOG_WARNING, NULL, 500590792Sgshapiro "ph_map_parseargs: WARNING: -v option will be removed in a future release - please use -k instead"); 500690792Sgshapiro /* intentional fallthrough for backward compatibility */ 500790792Sgshapiro /* FALLTHROUGH */ 500890792Sgshapiro 500990792Sgshapiro case 'k': /* fields to search for */ 501064562Sgshapiro while (isascii(*++p) && isspace(*p)) 501164562Sgshapiro continue; 501264562Sgshapiro pmap->ph_field_list = p; 501364562Sgshapiro break; 501464562Sgshapiro 501564562Sgshapiro default: 501690792Sgshapiro syserr("ph_map_parseargs: unknown option -%c", *p); 501764562Sgshapiro } 501864562Sgshapiro 501964562Sgshapiro /* try to account for quoted strings */ 502064562Sgshapiro done = isascii(*p) && isspace(*p); 502164562Sgshapiro while (*p != '\0' && !done) 502264562Sgshapiro { 502364562Sgshapiro if (*p == '"') 502464562Sgshapiro { 502564562Sgshapiro while (*++p != '"' && *p != '\0') 502664562Sgshapiro continue; 502764562Sgshapiro if (*p != '\0') 502864562Sgshapiro p++; 502964562Sgshapiro } 503064562Sgshapiro else 503164562Sgshapiro p++; 503264562Sgshapiro done = isascii(*p) && isspace(*p); 503364562Sgshapiro } 503464562Sgshapiro 503564562Sgshapiro if (*p != '\0') 503664562Sgshapiro *p++ = '\0'; 503764562Sgshapiro } 503864562Sgshapiro 503964562Sgshapiro if (map->map_app != NULL) 504064562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 504164562Sgshapiro if (map->map_tapp != NULL) 504264562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 504364562Sgshapiro 504464562Sgshapiro if (pmap->ph_field_list != NULL) 504564562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 504664562Sgshapiro 504764562Sgshapiro if (pmap->ph_servers != NULL) 504864562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 504964562Sgshapiro else 505064562Sgshapiro { 505164562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 505290792Sgshapiro return false; 505364562Sgshapiro } 505464562Sgshapiro 505564562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 505690792Sgshapiro return true; 505764562Sgshapiro} 505864562Sgshapiro 505964562Sgshapiro/* 506064562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 506164562Sgshapiro*/ 506264562Sgshapiro 506390792Sgshapirovoid 506490792Sgshapiroph_map_close(map) 506564562Sgshapiro MAP *map; 506664562Sgshapiro{ 506764562Sgshapiro PH_MAP_STRUCT *pmap; 506864562Sgshapiro 506964562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 507090792Sgshapiro if (tTd(38, 9)) 507194334Sgshapiro sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 507290792Sgshapiro map->map_mname, pmap->ph_fastclose); 507364562Sgshapiro 507490792Sgshapiro 507590792Sgshapiro if (pmap->ph != NULL) 507664562Sgshapiro { 507790792Sgshapiro ph_set_sendhook(pmap->ph, NULL); 507890792Sgshapiro ph_set_recvhook(pmap->ph, NULL); 507990792Sgshapiro ph_close(pmap->ph, pmap->ph_fastclose); 508064562Sgshapiro } 508190792Sgshapiro 508264562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 508364562Sgshapiro} 508464562Sgshapiro 508564562Sgshapirostatic jmp_buf PHTimeout; 508664562Sgshapiro 508764562Sgshapiro/* ARGSUSED */ 508864562Sgshapirostatic void 508990792Sgshapiroph_timeout(unused) 509090792Sgshapiro int unused; 509164562Sgshapiro{ 509277349Sgshapiro /* 509377349Sgshapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 509477349Sgshapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 509577349Sgshapiro ** DOING. 509677349Sgshapiro */ 509777349Sgshapiro 509877349Sgshapiro errno = ETIMEDOUT; 509964562Sgshapiro longjmp(PHTimeout, 1); 510064562Sgshapiro} 510164562Sgshapiro 510290792Sgshapirostatic void 5103110560Sgshapiro#if NPH_VERSION >= 10200 5104110560Sgshapiroph_map_send_debug(appdata, text) 5105110560Sgshapiro void *appdata; 5106110560Sgshapiro#else 510790792Sgshapiroph_map_send_debug(text) 5108110560Sgshapiro#endif 510990792Sgshapiro char *text; 511064562Sgshapiro{ 511190792Sgshapiro if (LogLevel > 9) 511290792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 511390792Sgshapiro "ph_map_send_debug: ==> %s", text); 511490792Sgshapiro if (tTd(38, 20)) 511590792Sgshapiro sm_dprintf("ph_map_send_debug: ==> %s\n", text); 511690792Sgshapiro} 511764562Sgshapiro 511890792Sgshapirostatic void 5119110560Sgshapiro#if NPH_VERSION >= 10200 5120110560Sgshapiroph_map_recv_debug(appdata, text) 5121110560Sgshapiro void *appdata; 5122110560Sgshapiro#else 512390792Sgshapiroph_map_recv_debug(text) 5124110560Sgshapiro#endif 512590792Sgshapiro char *text; 512690792Sgshapiro{ 512790792Sgshapiro if (LogLevel > 10) 512890792Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 512990792Sgshapiro "ph_map_recv_debug: <== %s", text); 513090792Sgshapiro if (tTd(38, 21)) 513190792Sgshapiro sm_dprintf("ph_map_recv_debug: <== %s\n", text); 513264562Sgshapiro} 513364562Sgshapiro 513490792Sgshapiro/* 513564562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 513664562Sgshapiro*/ 513764562Sgshapirobool 513864562Sgshapiroph_map_open(map, mode) 513964562Sgshapiro MAP *map; 514064562Sgshapiro int mode; 514164562Sgshapiro{ 514290792Sgshapiro PH_MAP_STRUCT *pmap; 514390792Sgshapiro register SM_EVENT *ev = NULL; 514464562Sgshapiro int save_errno = 0; 514590792Sgshapiro char *hostlist, *host; 514664562Sgshapiro 514764562Sgshapiro if (tTd(38, 2)) 514890792Sgshapiro sm_dprintf("ph_map_open(%s)\n", map->map_mname); 514964562Sgshapiro 515064562Sgshapiro mode &= O_ACCMODE; 515164562Sgshapiro if (mode != O_RDONLY) 515264562Sgshapiro { 515364562Sgshapiro /* issue a pseudo-error message */ 515490792Sgshapiro errno = SM_EMAPCANTWRITE; 515590792Sgshapiro return false; 515664562Sgshapiro } 515764562Sgshapiro 515866494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 515966494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 516066494Sgshapiro { 516166494Sgshapiro if (tTd(9, 1)) 516290792Sgshapiro sm_dprintf("ph_map_open(%s) => DEFERRED\n", 516390792Sgshapiro map->map_mname); 516466494Sgshapiro 516566494Sgshapiro /* 516690792Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 516790792Sgshapiro ** a temporary failure using the bogus map and 516890792Sgshapiro ** map->map_tapp instead of the default permanent error. 516966494Sgshapiro */ 517066494Sgshapiro 517166494Sgshapiro map->map_mflags &= ~MF_DEFER; 517290792Sgshapiro return false; 517366494Sgshapiro } 517466494Sgshapiro 517564562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 517690792Sgshapiro pmap->ph_fastclose = 0; /* refresh field for reopen */ 517764562Sgshapiro 517890792Sgshapiro /* try each host in the list */ 517964562Sgshapiro hostlist = newstr(pmap->ph_servers); 518090792Sgshapiro for (host = strtok(hostlist, " "); 518190792Sgshapiro host != NULL; 518290792Sgshapiro host = strtok(NULL, " ")) 518364562Sgshapiro { 518490792Sgshapiro /* set timeout */ 518564562Sgshapiro if (pmap->ph_timeout != 0) 518664562Sgshapiro { 518764562Sgshapiro if (setjmp(PHTimeout) != 0) 518864562Sgshapiro { 518964562Sgshapiro ev = NULL; 519064562Sgshapiro if (LogLevel > 1) 519164562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 519264562Sgshapiro "timeout connecting to PH server %.100s", 519390792Sgshapiro host); 519464562Sgshapiro errno = ETIMEDOUT; 519564562Sgshapiro goto ph_map_open_abort; 519664562Sgshapiro } 519790792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 519864562Sgshapiro } 519990792Sgshapiro 520090792Sgshapiro /* open connection to server */ 5201110560Sgshapiro if (ph_open(&(pmap->ph), host, 5202110560Sgshapiro PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 5203110560Sgshapiro ph_map_send_debug, ph_map_recv_debug 5204110560Sgshapiro#if NPH_VERSION >= 10200 5205110560Sgshapiro , NULL 5206110560Sgshapiro#endif 5207110560Sgshapiro ) == 0 5208110560Sgshapiro && ph_id(pmap->ph, phmap_id) == 0) 520964562Sgshapiro { 521064562Sgshapiro if (ev != NULL) 521190792Sgshapiro sm_clrevent(ev); 521290792Sgshapiro sm_free(hostlist); /* XXX */ 521390792Sgshapiro return true; 521464562Sgshapiro } 521590792Sgshapiro 521664562Sgshapiro ph_map_open_abort: 521790792Sgshapiro save_errno = errno; 521864562Sgshapiro if (ev != NULL) 521990792Sgshapiro sm_clrevent(ev); 5220110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 522190792Sgshapiro ph_map_close(map); 522290792Sgshapiro errno = save_errno; 522390792Sgshapiro } 522464562Sgshapiro 522566494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 522664562Sgshapiro { 522766494Sgshapiro if (errno == 0) 522864562Sgshapiro errno = EAGAIN; 522966494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 523066494Sgshapiro map->map_mname); 523164562Sgshapiro } 523266494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 523364562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 523466494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 523566494Sgshapiro map->map_mname); 523690792Sgshapiro sm_free(hostlist); /* XXX */ 523790792Sgshapiro return false; 523864562Sgshapiro} 523964562Sgshapiro 524064562Sgshapiro/* 524164562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 524264562Sgshapiro*/ 524364562Sgshapiro 524464562Sgshapirochar * 524564562Sgshapiroph_map_lookup(map, key, args, pstat) 524664562Sgshapiro MAP *map; 524764562Sgshapiro char *key; 524864562Sgshapiro char **args; 524964562Sgshapiro int *pstat; 525064562Sgshapiro{ 525190792Sgshapiro int i, save_errno = 0; 525290792Sgshapiro register SM_EVENT *ev = NULL; 525364562Sgshapiro PH_MAP_STRUCT *pmap; 525490792Sgshapiro char *value = NULL; 525564562Sgshapiro 525664562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 525764562Sgshapiro 525864562Sgshapiro *pstat = EX_OK; 525964562Sgshapiro 526090792Sgshapiro /* set timeout */ 526164562Sgshapiro if (pmap->ph_timeout != 0) 526264562Sgshapiro { 526364562Sgshapiro if (setjmp(PHTimeout) != 0) 526464562Sgshapiro { 526564562Sgshapiro ev = NULL; 526664562Sgshapiro if (LogLevel > 1) 526764562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 526864562Sgshapiro "timeout during PH lookup of %.100s", 526964562Sgshapiro key); 527064562Sgshapiro errno = ETIMEDOUT; 527164562Sgshapiro *pstat = EX_TEMPFAIL; 527264562Sgshapiro goto ph_map_lookup_abort; 527364562Sgshapiro } 527490792Sgshapiro ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 527564562Sgshapiro } 527664562Sgshapiro 527790792Sgshapiro /* perform lookup */ 527890792Sgshapiro i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 527990792Sgshapiro if (i == -1) 528090792Sgshapiro *pstat = EX_TEMPFAIL; 5281110560Sgshapiro else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 528290792Sgshapiro *pstat = EX_UNAVAILABLE; 528364562Sgshapiro 528464562Sgshapiro ph_map_lookup_abort: 528564562Sgshapiro if (ev != NULL) 528690792Sgshapiro sm_clrevent(ev); 528764562Sgshapiro 528864562Sgshapiro /* 528990792Sgshapiro ** Close the connection if the timer popped 529064562Sgshapiro ** or we got a temporary PH error 529164562Sgshapiro */ 529264562Sgshapiro 529364562Sgshapiro if (*pstat == EX_TEMPFAIL) 529490792Sgshapiro { 529590792Sgshapiro save_errno = errno; 5296110560Sgshapiro pmap->ph_fastclose = PH_CLOSE_FAST; 529790792Sgshapiro ph_map_close(map); 529890792Sgshapiro errno = save_errno; 529990792Sgshapiro } 530064562Sgshapiro 530164562Sgshapiro if (*pstat == EX_OK) 530264562Sgshapiro { 530364562Sgshapiro if (tTd(38,20)) 530490792Sgshapiro sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 530564562Sgshapiro 530664562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 530790792Sgshapiro return map_rewrite(map, key, strlen(key), NULL); 530864562Sgshapiro else 530990792Sgshapiro return map_rewrite(map, value, strlen(value), args); 531064562Sgshapiro } 531164562Sgshapiro 531264562Sgshapiro return NULL; 531364562Sgshapiro} 531464562Sgshapiro#endif /* PH_MAP */ 531590792Sgshapiro/* 531642575Speter** syslog map 531738032Speter*/ 531838032Speter 531938032Speter#define map_prio map_lockfd /* overload field */ 532038032Speter 532138032Speter/* 532242575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 532338032Speter*/ 532438032Speter 532538032Speterbool 532638032Spetersyslog_map_parseargs(map, args) 532738032Speter MAP *map; 532838032Speter char *args; 532938032Speter{ 533038032Speter char *p = args; 533138032Speter char *priority = NULL; 533238032Speter 533364562Sgshapiro /* there is no check whether there is really an argument */ 533464562Sgshapiro while (*p != '\0') 533538032Speter { 533638032Speter while (isascii(*p) && isspace(*p)) 533738032Speter p++; 533838032Speter if (*p != '-') 533938032Speter break; 534064562Sgshapiro ++p; 534164562Sgshapiro if (*p == 'D') 534264562Sgshapiro { 534364562Sgshapiro map->map_mflags |= MF_DEFER; 534464562Sgshapiro ++p; 534564562Sgshapiro } 534664562Sgshapiro else if (*p == 'S') 534764562Sgshapiro { 534864562Sgshapiro map->map_spacesub = *++p; 534964562Sgshapiro if (*p != '\0') 535064562Sgshapiro p++; 535164562Sgshapiro } 535264562Sgshapiro else if (*p == 'L') 535364562Sgshapiro { 535464562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 535564562Sgshapiro continue; 535664562Sgshapiro if (*p == '\0') 535764562Sgshapiro break; 535864562Sgshapiro priority = p; 535964562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 536064562Sgshapiro p++; 536164562Sgshapiro if (*p != '\0') 536264562Sgshapiro *p++ = '\0'; 536364562Sgshapiro } 536464562Sgshapiro else 536564562Sgshapiro { 536664562Sgshapiro syserr("Illegal option %c map syslog", *p); 536764562Sgshapiro ++p; 536864562Sgshapiro } 536938032Speter } 537038032Speter 537138032Speter if (priority == NULL) 537238032Speter map->map_prio = LOG_INFO; 537338032Speter else 537438032Speter { 537590792Sgshapiro if (sm_strncasecmp("LOG_", priority, 4) == 0) 537638032Speter priority += 4; 537738032Speter 537838032Speter#ifdef LOG_EMERG 537990792Sgshapiro if (sm_strcasecmp("EMERG", priority) == 0) 538038032Speter map->map_prio = LOG_EMERG; 538138032Speter else 538264562Sgshapiro#endif /* LOG_EMERG */ 538338032Speter#ifdef LOG_ALERT 538490792Sgshapiro if (sm_strcasecmp("ALERT", priority) == 0) 538538032Speter map->map_prio = LOG_ALERT; 538638032Speter else 538764562Sgshapiro#endif /* LOG_ALERT */ 538838032Speter#ifdef LOG_CRIT 538990792Sgshapiro if (sm_strcasecmp("CRIT", priority) == 0) 539038032Speter map->map_prio = LOG_CRIT; 539138032Speter else 539264562Sgshapiro#endif /* LOG_CRIT */ 539338032Speter#ifdef LOG_ERR 539490792Sgshapiro if (sm_strcasecmp("ERR", priority) == 0) 539538032Speter map->map_prio = LOG_ERR; 539638032Speter else 539764562Sgshapiro#endif /* LOG_ERR */ 539838032Speter#ifdef LOG_WARNING 539990792Sgshapiro if (sm_strcasecmp("WARNING", priority) == 0) 540038032Speter map->map_prio = LOG_WARNING; 540138032Speter else 540264562Sgshapiro#endif /* LOG_WARNING */ 540338032Speter#ifdef LOG_NOTICE 540490792Sgshapiro if (sm_strcasecmp("NOTICE", priority) == 0) 540538032Speter map->map_prio = LOG_NOTICE; 540638032Speter else 540764562Sgshapiro#endif /* LOG_NOTICE */ 540838032Speter#ifdef LOG_INFO 540990792Sgshapiro if (sm_strcasecmp("INFO", priority) == 0) 541038032Speter map->map_prio = LOG_INFO; 541138032Speter else 541264562Sgshapiro#endif /* LOG_INFO */ 541338032Speter#ifdef LOG_DEBUG 541490792Sgshapiro if (sm_strcasecmp("DEBUG", priority) == 0) 541538032Speter map->map_prio = LOG_DEBUG; 541638032Speter else 541764562Sgshapiro#endif /* LOG_DEBUG */ 541838032Speter { 541990792Sgshapiro syserr("syslog_map_parseargs: Unknown priority %s", 542038032Speter priority); 542190792Sgshapiro return false; 542238032Speter } 542338032Speter } 542490792Sgshapiro return true; 542538032Speter} 542638032Speter 542738032Speter/* 542842575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 542938032Speter*/ 543038032Speter 543138032Speterchar * 543238032Spetersyslog_map_lookup(map, string, args, statp) 543338032Speter MAP *map; 543438032Speter char *string; 543538032Speter char **args; 543638032Speter int *statp; 543738032Speter{ 543838032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 543938032Speter 544038032Speter if (ptr != NULL) 544138032Speter { 544238032Speter if (tTd(38, 20)) 544390792Sgshapiro sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 544464562Sgshapiro map->map_mname, map->map_prio, ptr); 544538032Speter 544638032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 544738032Speter } 544838032Speter 544938032Speter *statp = EX_OK; 545038032Speter return ""; 545138032Speter} 545238032Speter 545390792Sgshapiro/* 545438032Speter** HESIOD Modules 545538032Speter*/ 545638032Speter 545790792Sgshapiro#if HESIOD 545838032Speter 545938032Speterbool 546038032Speterhes_map_open(map, mode) 546138032Speter MAP *map; 546238032Speter int mode; 546338032Speter{ 546438032Speter if (tTd(38, 2)) 546590792Sgshapiro sm_dprintf("hes_map_open(%s, %s, %d)\n", 546638032Speter map->map_mname, map->map_file, mode); 546738032Speter 546838032Speter if (mode != O_RDONLY) 546938032Speter { 547038032Speter /* issue a pseudo-error message */ 547190792Sgshapiro errno = SM_EMAPCANTWRITE; 547290792Sgshapiro return false; 547338032Speter } 547438032Speter 547564562Sgshapiro# ifdef HESIOD_INIT 547638032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 547790792Sgshapiro return true; 547838032Speter 547938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 548094334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 548190792Sgshapiro sm_errstring(errno)); 548290792Sgshapiro return false; 548364562Sgshapiro# else /* HESIOD_INIT */ 548438032Speter if (hes_error() == HES_ER_UNINIT) 548538032Speter hes_init(); 548638032Speter switch (hes_error()) 548738032Speter { 548838032Speter case HES_ER_OK: 548938032Speter case HES_ER_NOTFOUND: 549090792Sgshapiro return true; 549138032Speter } 549238032Speter 549338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 549494334Sgshapiro syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 549538032Speter 549690792Sgshapiro return false; 549764562Sgshapiro# endif /* HESIOD_INIT */ 549838032Speter} 549938032Speter 550038032Speterchar * 550138032Speterhes_map_lookup(map, name, av, statp) 550238032Speter MAP *map; 550338032Speter char *name; 550438032Speter char **av; 550538032Speter int *statp; 550638032Speter{ 550738032Speter char **hp; 550838032Speter 550938032Speter if (tTd(38, 20)) 551090792Sgshapiro sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 551138032Speter 551238032Speter if (name[0] == '\\') 551338032Speter { 551438032Speter char *np; 551538032Speter int nl; 551677349Sgshapiro int save_errno; 551738032Speter char nbuf[MAXNAME]; 551838032Speter 551938032Speter nl = strlen(name); 552038032Speter if (nl < sizeof nbuf - 1) 552138032Speter np = nbuf; 552238032Speter else 552338032Speter np = xalloc(strlen(name) + 2); 552438032Speter np[0] = '\\'; 552590792Sgshapiro (void) sm_strlcpy(&np[1], name, (sizeof nbuf) - 1); 552664562Sgshapiro# ifdef HESIOD_INIT 552738032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 552864562Sgshapiro# else /* HESIOD_INIT */ 552938032Speter hp = hes_resolve(np, map->map_file); 553064562Sgshapiro# endif /* HESIOD_INIT */ 553177349Sgshapiro save_errno = errno; 553238032Speter if (np != nbuf) 553390792Sgshapiro sm_free(np); /* XXX */ 553477349Sgshapiro errno = save_errno; 553538032Speter } 553638032Speter else 553738032Speter { 553864562Sgshapiro# ifdef HESIOD_INIT 553938032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 554064562Sgshapiro# else /* HESIOD_INIT */ 554138032Speter hp = hes_resolve(name, map->map_file); 554264562Sgshapiro# endif /* HESIOD_INIT */ 554338032Speter } 554464562Sgshapiro# ifdef HESIOD_INIT 554577349Sgshapiro if (hp == NULL || *hp == NULL) 554638032Speter { 554738032Speter switch (errno) 554838032Speter { 554938032Speter case ENOENT: 555038032Speter *statp = EX_NOTFOUND; 555138032Speter break; 555238032Speter case ECONNREFUSED: 555338032Speter *statp = EX_TEMPFAIL; 555438032Speter break; 555590792Sgshapiro case EMSGSIZE: 555638032Speter case ENOMEM: 555738032Speter default: 555838032Speter *statp = EX_UNAVAILABLE; 555938032Speter break; 556038032Speter } 556182017Sgshapiro if (hp != NULL) 556282017Sgshapiro hesiod_free_list(HesiodContext, hp); 556338032Speter return NULL; 556438032Speter } 556564562Sgshapiro# else /* HESIOD_INIT */ 556638032Speter if (hp == NULL || hp[0] == NULL) 556738032Speter { 556838032Speter switch (hes_error()) 556938032Speter { 557038032Speter case HES_ER_OK: 557138032Speter *statp = EX_OK; 557238032Speter break; 557338032Speter 557438032Speter case HES_ER_NOTFOUND: 557538032Speter *statp = EX_NOTFOUND; 557638032Speter break; 557738032Speter 557838032Speter case HES_ER_CONFIG: 557938032Speter *statp = EX_UNAVAILABLE; 558038032Speter break; 558138032Speter 558238032Speter case HES_ER_NET: 558338032Speter *statp = EX_TEMPFAIL; 558438032Speter break; 558538032Speter } 558638032Speter return NULL; 558738032Speter } 558864562Sgshapiro# endif /* HESIOD_INIT */ 558938032Speter 559038032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 559138032Speter return map_rewrite(map, name, strlen(name), NULL); 559238032Speter else 559338032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 559438032Speter} 559538032Speter 559690792Sgshapiro/* 559790792Sgshapiro** HES_MAP_CLOSE -- free the Hesiod context 559890792Sgshapiro*/ 559990792Sgshapiro 560090792Sgshapirovoid 560190792Sgshapirohes_map_close(map) 560290792Sgshapiro MAP *map; 560390792Sgshapiro{ 560490792Sgshapiro if (tTd(38, 20)) 560590792Sgshapiro sm_dprintf("hes_map_close(%s)\n", map->map_file); 560690792Sgshapiro 560790792Sgshapiro# ifdef HESIOD_INIT 560890792Sgshapiro /* Free the hesiod context */ 560990792Sgshapiro if (HesiodContext != NULL) 561090792Sgshapiro { 561190792Sgshapiro hesiod_end(HesiodContext); 561290792Sgshapiro HesiodContext = NULL; 561390792Sgshapiro } 561490792Sgshapiro# endif /* HESIOD_INIT */ 561590792Sgshapiro} 561690792Sgshapiro 561764562Sgshapiro#endif /* HESIOD */ 561890792Sgshapiro/* 561938032Speter** NeXT NETINFO Modules 562038032Speter*/ 562138032Speter 562238032Speter#if NETINFO 562338032Speter 562438032Speter# define NETINFO_DEFAULT_DIR "/aliases" 562538032Speter# define NETINFO_DEFAULT_PROPERTY "members" 562638032Speter 562738032Speter/* 562838032Speter** NI_MAP_OPEN -- open NetInfo Aliases 562938032Speter*/ 563038032Speter 563138032Speterbool 563238032Speterni_map_open(map, mode) 563338032Speter MAP *map; 563438032Speter int mode; 563538032Speter{ 563638032Speter if (tTd(38, 2)) 563790792Sgshapiro sm_dprintf("ni_map_open(%s, %s, %d)\n", 563838032Speter map->map_mname, map->map_file, mode); 563938032Speter mode &= O_ACCMODE; 564038032Speter 564138032Speter if (*map->map_file == '\0') 564238032Speter map->map_file = NETINFO_DEFAULT_DIR; 564338032Speter 564438032Speter if (map->map_valcolnm == NULL) 564538032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 564638032Speter 564790792Sgshapiro if (map->map_coldelim == '\0') 564890792Sgshapiro { 564990792Sgshapiro if (bitset(MF_ALIAS, map->map_mflags)) 565090792Sgshapiro map->map_coldelim = ','; 565190792Sgshapiro else if (bitset(MF_FILECLASS, map->map_mflags)) 565290792Sgshapiro map->map_coldelim = ' '; 565390792Sgshapiro } 565490792Sgshapiro return true; 565538032Speter} 565638032Speter 565738032Speter 565838032Speter/* 565938032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 566038032Speter*/ 566138032Speter 566238032Speterchar * 566338032Speterni_map_lookup(map, name, av, statp) 566438032Speter MAP *map; 566538032Speter char *name; 566638032Speter char **av; 566738032Speter int *statp; 566838032Speter{ 566938032Speter char *res; 567038032Speter char *propval; 567138032Speter 567238032Speter if (tTd(38, 20)) 567390792Sgshapiro sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 567438032Speter 567538032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 567638032Speter map->map_valcolnm, map->map_coldelim); 567738032Speter 567838032Speter if (propval == NULL) 567938032Speter return NULL; 568038032Speter 568190792Sgshapiro SM_TRY 568290792Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 568390792Sgshapiro res = map_rewrite(map, name, strlen(name), NULL); 568490792Sgshapiro else 568590792Sgshapiro res = map_rewrite(map, propval, strlen(propval), av); 568690792Sgshapiro SM_FINALLY 568790792Sgshapiro sm_free(propval); 568890792Sgshapiro SM_END_TRY 568938032Speter return res; 569038032Speter} 569138032Speter 569238032Speter 569364562Sgshapirostatic bool 569438032Speterni_getcanonname(name, hbsize, statp) 569538032Speter char *name; 569638032Speter int hbsize; 569738032Speter int *statp; 569838032Speter{ 569938032Speter char *vptr; 570038032Speter char *ptr; 570138032Speter char nbuf[MAXNAME + 1]; 570238032Speter 570338032Speter if (tTd(38, 20)) 570490792Sgshapiro sm_dprintf("ni_getcanonname(%s)\n", name); 570538032Speter 570690792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 570738032Speter { 570838032Speter *statp = EX_UNAVAILABLE; 570990792Sgshapiro return false; 571038032Speter } 571173188Sgshapiro (void) shorten_hostname(nbuf); 571238032Speter 571338032Speter /* we only accept single token search key */ 571438032Speter if (strchr(nbuf, '.')) 571538032Speter { 571638032Speter *statp = EX_NOHOST; 571790792Sgshapiro return false; 571838032Speter } 571938032Speter 572038032Speter /* Do the search */ 572138032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 572238032Speter 572338032Speter if (vptr == NULL) 572438032Speter { 572538032Speter *statp = EX_NOHOST; 572690792Sgshapiro return false; 572738032Speter } 572838032Speter 572938032Speter /* Only want the first machine name */ 573038032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 573138032Speter *ptr = '\0'; 573238032Speter 573390792Sgshapiro if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 573438032Speter { 573577349Sgshapiro sm_free(vptr); 573690792Sgshapiro *statp = EX_UNAVAILABLE; 573790792Sgshapiro return true; 573838032Speter } 573977349Sgshapiro sm_free(vptr); 574090792Sgshapiro *statp = EX_OK; 574190792Sgshapiro return false; 574238032Speter} 574390792Sgshapiro#endif /* NETINFO */ 574438032Speter/* 574538032Speter** TEXT (unindexed text file) Modules 574638032Speter** 574738032Speter** This code donated by Sun Microsystems. 574838032Speter*/ 574938032Speter 575038032Speter#define map_sff map_lockfd /* overload field */ 575138032Speter 575238032Speter 575338032Speter/* 575438032Speter** TEXT_MAP_OPEN -- open text table 575538032Speter*/ 575638032Speter 575738032Speterbool 575838032Spetertext_map_open(map, mode) 575938032Speter MAP *map; 576038032Speter int mode; 576138032Speter{ 576264562Sgshapiro long sff; 576338032Speter int i; 576438032Speter 576538032Speter if (tTd(38, 2)) 576690792Sgshapiro sm_dprintf("text_map_open(%s, %s, %d)\n", 576738032Speter map->map_mname, map->map_file, mode); 576838032Speter 576938032Speter mode &= O_ACCMODE; 577038032Speter if (mode != O_RDONLY) 577138032Speter { 577238032Speter errno = EPERM; 577390792Sgshapiro return false; 577438032Speter } 577538032Speter 577638032Speter if (*map->map_file == '\0') 577738032Speter { 577838032Speter syserr("text map \"%s\": file name required", 577938032Speter map->map_mname); 578090792Sgshapiro return false; 578138032Speter } 578238032Speter 578338032Speter if (map->map_file[0] != '/') 578438032Speter { 578538032Speter syserr("text map \"%s\": file name must be fully qualified", 578638032Speter map->map_mname); 578790792Sgshapiro return false; 578838032Speter } 578938032Speter 579038032Speter sff = SFF_ROOTOK|SFF_REGONLY; 579164562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 579238032Speter sff |= SFF_NOWLINK; 579364562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 579438032Speter sff |= SFF_SAFEDIRPATH; 579538032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 579638032Speter sff, S_IRUSR, NULL)) != 0) 579738032Speter { 579864562Sgshapiro int save_errno = errno; 579964562Sgshapiro 580038032Speter /* cannot open this map */ 580138032Speter if (tTd(38, 2)) 580290792Sgshapiro sm_dprintf("\tunsafe map file: %d\n", i); 580364562Sgshapiro errno = save_errno; 580438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 580538032Speter syserr("text map \"%s\": unsafe map file %s", 580638032Speter map->map_mname, map->map_file); 580790792Sgshapiro return false; 580838032Speter } 580938032Speter 581038032Speter if (map->map_keycolnm == NULL) 581138032Speter map->map_keycolno = 0; 581238032Speter else 581338032Speter { 581438032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 581538032Speter { 581638032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 581738032Speter map->map_mname, map->map_file, 581838032Speter map->map_keycolnm); 581990792Sgshapiro return false; 582038032Speter } 582138032Speter map->map_keycolno = atoi(map->map_keycolnm); 582238032Speter } 582338032Speter 582438032Speter if (map->map_valcolnm == NULL) 582538032Speter map->map_valcolno = 0; 582638032Speter else 582738032Speter { 582838032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 582938032Speter { 583038032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 583138032Speter map->map_mname, map->map_file, 583238032Speter map->map_valcolnm); 583390792Sgshapiro return false; 583438032Speter } 583538032Speter map->map_valcolno = atoi(map->map_valcolnm); 583638032Speter } 583738032Speter 583838032Speter if (tTd(38, 2)) 583938032Speter { 584090792Sgshapiro sm_dprintf("text_map_open(%s, %s): delimiter = ", 584138032Speter map->map_mname, map->map_file); 584238032Speter if (map->map_coldelim == '\0') 584390792Sgshapiro sm_dprintf("(white space)\n"); 584438032Speter else 584590792Sgshapiro sm_dprintf("%c\n", map->map_coldelim); 584638032Speter } 584738032Speter 584838032Speter map->map_sff = sff; 584990792Sgshapiro return true; 585038032Speter} 585138032Speter 585238032Speter 585338032Speter/* 585438032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 585538032Speter*/ 585638032Speter 585738032Speterchar * 585838032Spetertext_map_lookup(map, name, av, statp) 585938032Speter MAP *map; 586038032Speter char *name; 586138032Speter char **av; 586238032Speter int *statp; 586338032Speter{ 586438032Speter char *vp; 586538032Speter auto int vsize; 586638032Speter int buflen; 586790792Sgshapiro SM_FILE_T *f; 586838032Speter char delim; 586938032Speter int key_idx; 587038032Speter bool found_it; 587164562Sgshapiro long sff = map->map_sff; 587238032Speter char search_key[MAXNAME + 1]; 587338032Speter char linebuf[MAXLINE]; 587438032Speter char buf[MAXNAME + 1]; 587538032Speter 587690792Sgshapiro found_it = false; 587738032Speter if (tTd(38, 20)) 587890792Sgshapiro sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 587938032Speter 588038032Speter buflen = strlen(name); 588138032Speter if (buflen > sizeof search_key - 1) 588290792Sgshapiro buflen = sizeof search_key - 1; /* XXX just cut if off? */ 588364562Sgshapiro memmove(search_key, name, buflen); 588438032Speter search_key[buflen] = '\0'; 588538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 588638032Speter makelower(search_key); 588738032Speter 588838032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 588938032Speter if (f == NULL) 589038032Speter { 589138032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 589238032Speter *statp = EX_UNAVAILABLE; 589338032Speter return NULL; 589438032Speter } 589538032Speter key_idx = map->map_keycolno; 589638032Speter delim = map->map_coldelim; 589798121Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, 589898121Sgshapiro linebuf, sizeof linebuf) != NULL) 589938032Speter { 590038032Speter char *p; 590138032Speter 590238032Speter /* skip comment line */ 590338032Speter if (linebuf[0] == '#') 590438032Speter continue; 590538032Speter p = strchr(linebuf, '\n'); 590638032Speter if (p != NULL) 590738032Speter *p = '\0'; 590838032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 590990792Sgshapiro if (p != NULL && sm_strcasecmp(search_key, p) == 0) 591038032Speter { 591190792Sgshapiro found_it = true; 591238032Speter break; 591338032Speter } 591438032Speter } 591590792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 591638032Speter if (!found_it) 591738032Speter { 591838032Speter *statp = EX_NOTFOUND; 591938032Speter return NULL; 592038032Speter } 592138032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 592242575Speter if (vp == NULL) 592342575Speter { 592442575Speter *statp = EX_NOTFOUND; 592542575Speter return NULL; 592642575Speter } 592738032Speter vsize = strlen(vp); 592838032Speter *statp = EX_OK; 592938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 593038032Speter return map_rewrite(map, name, strlen(name), NULL); 593138032Speter else 593238032Speter return map_rewrite(map, vp, vsize, av); 593338032Speter} 593438032Speter 593538032Speter/* 593638032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 593738032Speter*/ 593838032Speter 593964562Sgshapirostatic bool 594038032Spetertext_getcanonname(name, hbsize, statp) 594138032Speter char *name; 594238032Speter int hbsize; 594338032Speter int *statp; 594438032Speter{ 594538032Speter bool found; 594673188Sgshapiro char *dot; 594790792Sgshapiro SM_FILE_T *f; 594838032Speter char linebuf[MAXLINE]; 594938032Speter char cbuf[MAXNAME + 1]; 595038032Speter char nbuf[MAXNAME + 1]; 595138032Speter 595238032Speter if (tTd(38, 20)) 595390792Sgshapiro sm_dprintf("text_getcanonname(%s)\n", name); 595438032Speter 595590792Sgshapiro if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 595638032Speter { 595738032Speter *statp = EX_UNAVAILABLE; 595890792Sgshapiro return false; 595938032Speter } 596073188Sgshapiro dot = shorten_hostname(nbuf); 596138032Speter 596290792Sgshapiro f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 596390792Sgshapiro NULL); 596438032Speter if (f == NULL) 596538032Speter { 596638032Speter *statp = EX_UNAVAILABLE; 596790792Sgshapiro return false; 596838032Speter } 596990792Sgshapiro found = false; 597090792Sgshapiro while (!found && 597198121Sgshapiro sm_io_fgets(f, SM_TIME_DEFAULT, 597298121Sgshapiro linebuf, sizeof linebuf) != NULL) 597338032Speter { 597438032Speter char *p = strpbrk(linebuf, "#\n"); 597538032Speter 597638032Speter if (p != NULL) 597738032Speter *p = '\0'; 597838032Speter if (linebuf[0] != '\0') 597973188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 598073188Sgshapiro cbuf, sizeof cbuf); 598138032Speter } 598290792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 598338032Speter if (!found) 598438032Speter { 598538032Speter *statp = EX_NOHOST; 598690792Sgshapiro return false; 598738032Speter } 598838032Speter 598990792Sgshapiro if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 599038032Speter { 599190792Sgshapiro *statp = EX_UNAVAILABLE; 599290792Sgshapiro return false; 599338032Speter } 599490792Sgshapiro *statp = EX_OK; 599590792Sgshapiro return true; 599638032Speter} 599790792Sgshapiro/* 599838032Speter** STAB (Symbol Table) Modules 599938032Speter*/ 600038032Speter 600138032Speter 600238032Speter/* 600338032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 600438032Speter*/ 600538032Speter 600638032Speter/* ARGSUSED2 */ 600738032Speterchar * 600838032Speterstab_map_lookup(map, name, av, pstat) 600938032Speter register MAP *map; 601038032Speter char *name; 601138032Speter char **av; 601238032Speter int *pstat; 601338032Speter{ 601438032Speter register STAB *s; 601538032Speter 601638032Speter if (tTd(38, 20)) 601790792Sgshapiro sm_dprintf("stab_lookup(%s, %s)\n", 601838032Speter map->map_mname, name); 601938032Speter 602038032Speter s = stab(name, ST_ALIAS, ST_FIND); 602138032Speter if (s != NULL) 602264562Sgshapiro return s->s_alias; 602364562Sgshapiro return NULL; 602438032Speter} 602538032Speter 602638032Speter 602738032Speter/* 602838032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 602938032Speter*/ 603038032Speter 603138032Spetervoid 603238032Speterstab_map_store(map, lhs, rhs) 603338032Speter register MAP *map; 603438032Speter char *lhs; 603538032Speter char *rhs; 603638032Speter{ 603738032Speter register STAB *s; 603838032Speter 603938032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 604038032Speter s->s_alias = newstr(rhs); 604138032Speter} 604238032Speter 604338032Speter 604438032Speter/* 604538032Speter** STAB_MAP_OPEN -- initialize (reads data file) 604638032Speter** 604738032Speter** This is a wierd case -- it is only intended as a fallback for 604838032Speter** aliases. For this reason, opens for write (only during a 604938032Speter** "newaliases") always fails, and opens for read open the 605038032Speter** actual underlying text file instead of the database. 605138032Speter*/ 605238032Speter 605338032Speterbool 605438032Speterstab_map_open(map, mode) 605538032Speter register MAP *map; 605638032Speter int mode; 605738032Speter{ 605890792Sgshapiro SM_FILE_T *af; 605964562Sgshapiro long sff; 606038032Speter struct stat st; 606138032Speter 606238032Speter if (tTd(38, 2)) 606390792Sgshapiro sm_dprintf("stab_map_open(%s, %s, %d)\n", 606438032Speter map->map_mname, map->map_file, mode); 606538032Speter 606638032Speter mode &= O_ACCMODE; 606738032Speter if (mode != O_RDONLY) 606838032Speter { 606938032Speter errno = EPERM; 607090792Sgshapiro return false; 607138032Speter } 607238032Speter 607338032Speter sff = SFF_ROOTOK|SFF_REGONLY; 607464562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 607538032Speter sff |= SFF_NOWLINK; 607664562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 607738032Speter sff |= SFF_SAFEDIRPATH; 607838032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 607938032Speter if (af == NULL) 608090792Sgshapiro return false; 608190792Sgshapiro readaliases(map, af, false, false); 608238032Speter 608390792Sgshapiro if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 608438032Speter map->map_mtime = st.st_mtime; 608590792Sgshapiro (void) sm_io_close(af, SM_TIME_DEFAULT); 608638032Speter 608790792Sgshapiro return true; 608838032Speter} 608990792Sgshapiro/* 609038032Speter** Implicit Modules 609138032Speter** 609238032Speter** Tries several types. For back compatibility of aliases. 609338032Speter*/ 609438032Speter 609538032Speter 609638032Speter/* 609738032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 609838032Speter*/ 609938032Speter 610038032Speterchar * 610138032Speterimpl_map_lookup(map, name, av, pstat) 610238032Speter MAP *map; 610338032Speter char *name; 610438032Speter char **av; 610538032Speter int *pstat; 610638032Speter{ 610738032Speter if (tTd(38, 20)) 610890792Sgshapiro sm_dprintf("impl_map_lookup(%s, %s)\n", 610938032Speter map->map_mname, name); 611038032Speter 611190792Sgshapiro#if NEWDB 611238032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 611338032Speter return db_map_lookup(map, name, av, pstat); 611464562Sgshapiro#endif /* NEWDB */ 611590792Sgshapiro#if NDBM 611638032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 611738032Speter return ndbm_map_lookup(map, name, av, pstat); 611864562Sgshapiro#endif /* NDBM */ 611938032Speter return stab_map_lookup(map, name, av, pstat); 612038032Speter} 612138032Speter 612238032Speter/* 612338032Speter** IMPL_MAP_STORE -- store in open databases 612438032Speter*/ 612538032Speter 612638032Spetervoid 612738032Speterimpl_map_store(map, lhs, rhs) 612838032Speter MAP *map; 612938032Speter char *lhs; 613038032Speter char *rhs; 613138032Speter{ 613238032Speter if (tTd(38, 12)) 613390792Sgshapiro sm_dprintf("impl_map_store(%s, %s, %s)\n", 613438032Speter map->map_mname, lhs, rhs); 613590792Sgshapiro#if NEWDB 613638032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 613738032Speter db_map_store(map, lhs, rhs); 613864562Sgshapiro#endif /* NEWDB */ 613990792Sgshapiro#if NDBM 614038032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 614138032Speter ndbm_map_store(map, lhs, rhs); 614264562Sgshapiro#endif /* NDBM */ 614338032Speter stab_map_store(map, lhs, rhs); 614438032Speter} 614538032Speter 614638032Speter/* 614738032Speter** IMPL_MAP_OPEN -- implicit database open 614838032Speter*/ 614938032Speter 615038032Speterbool 615138032Speterimpl_map_open(map, mode) 615238032Speter MAP *map; 615338032Speter int mode; 615438032Speter{ 615538032Speter if (tTd(38, 2)) 615690792Sgshapiro sm_dprintf("impl_map_open(%s, %s, %d)\n", 615738032Speter map->map_mname, map->map_file, mode); 615838032Speter 615938032Speter mode &= O_ACCMODE; 616090792Sgshapiro#if NEWDB 616138032Speter map->map_mflags |= MF_IMPL_HASH; 616238032Speter if (hash_map_open(map, mode)) 616338032Speter { 616438032Speter# ifdef NDBM_YP_COMPAT 616538032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 616664562Sgshapiro# endif /* NDBM_YP_COMPAT */ 616790792Sgshapiro return true; 616838032Speter } 616938032Speter else 617038032Speter map->map_mflags &= ~MF_IMPL_HASH; 617164562Sgshapiro#endif /* NEWDB */ 617290792Sgshapiro#if NDBM 617338032Speter map->map_mflags |= MF_IMPL_NDBM; 617438032Speter if (ndbm_map_open(map, mode)) 617538032Speter { 617690792Sgshapiro return true; 617738032Speter } 617838032Speter else 617938032Speter map->map_mflags &= ~MF_IMPL_NDBM; 618064562Sgshapiro#endif /* NDBM */ 618138032Speter 618238032Speter#if defined(NEWDB) || defined(NDBM) 618338032Speter if (Verbose) 618438032Speter message("WARNING: cannot open alias database %s%s", 618538032Speter map->map_file, 618638032Speter mode == O_RDONLY ? "; reading text version" : ""); 618764562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 618838032Speter if (mode != O_RDONLY) 618938032Speter usrerr("Cannot rebuild aliases: no database format defined"); 619064562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 619138032Speter 619238032Speter if (mode == O_RDONLY) 619338032Speter return stab_map_open(map, mode); 619438032Speter else 619590792Sgshapiro return false; 619638032Speter} 619738032Speter 619838032Speter 619938032Speter/* 620038032Speter** IMPL_MAP_CLOSE -- close any open database(s) 620138032Speter*/ 620238032Speter 620338032Spetervoid 620438032Speterimpl_map_close(map) 620538032Speter MAP *map; 620638032Speter{ 620738032Speter if (tTd(38, 9)) 620890792Sgshapiro sm_dprintf("impl_map_close(%s, %s, %lx)\n", 620938032Speter map->map_mname, map->map_file, map->map_mflags); 621090792Sgshapiro#if NEWDB 621138032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 621238032Speter { 621338032Speter db_map_close(map); 621438032Speter map->map_mflags &= ~MF_IMPL_HASH; 621538032Speter } 621664562Sgshapiro#endif /* NEWDB */ 621738032Speter 621890792Sgshapiro#if NDBM 621938032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 622038032Speter { 622138032Speter ndbm_map_close(map); 622238032Speter map->map_mflags &= ~MF_IMPL_NDBM; 622338032Speter } 622464562Sgshapiro#endif /* NDBM */ 622538032Speter} 622690792Sgshapiro/* 622738032Speter** User map class. 622838032Speter** 622938032Speter** Provides access to the system password file. 623038032Speter*/ 623138032Speter 623238032Speter/* 623338032Speter** USER_MAP_OPEN -- open user map 623438032Speter** 623538032Speter** Really just binds field names to field numbers. 623638032Speter*/ 623738032Speter 623838032Speterbool 623938032Speteruser_map_open(map, mode) 624038032Speter MAP *map; 624138032Speter int mode; 624238032Speter{ 624338032Speter if (tTd(38, 2)) 624490792Sgshapiro sm_dprintf("user_map_open(%s, %d)\n", 624538032Speter map->map_mname, mode); 624638032Speter 624738032Speter mode &= O_ACCMODE; 624838032Speter if (mode != O_RDONLY) 624938032Speter { 625038032Speter /* issue a pseudo-error message */ 625190792Sgshapiro errno = SM_EMAPCANTWRITE; 625290792Sgshapiro return false; 625338032Speter } 625438032Speter if (map->map_valcolnm == NULL) 625564562Sgshapiro /* EMPTY */ 625638032Speter /* nothing */ ; 625790792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 625838032Speter map->map_valcolno = 1; 625990792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 626038032Speter map->map_valcolno = 2; 626190792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 626238032Speter map->map_valcolno = 3; 626390792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 626438032Speter map->map_valcolno = 4; 626590792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 626638032Speter map->map_valcolno = 5; 626790792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 626838032Speter map->map_valcolno = 6; 626990792Sgshapiro else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 627038032Speter map->map_valcolno = 7; 627138032Speter else 627238032Speter { 627338032Speter syserr("User map %s: unknown column name %s", 627438032Speter map->map_mname, map->map_valcolnm); 627590792Sgshapiro return false; 627638032Speter } 627790792Sgshapiro return true; 627838032Speter} 627938032Speter 628038032Speter 628138032Speter/* 628238032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 628338032Speter*/ 628438032Speter 628538032Speter/* ARGSUSED3 */ 628638032Speterchar * 628738032Speteruser_map_lookup(map, key, av, statp) 628838032Speter MAP *map; 628938032Speter char *key; 629038032Speter char **av; 629138032Speter int *statp; 629238032Speter{ 629338032Speter auto bool fuzzy; 629490792Sgshapiro SM_MBDB_T user; 629538032Speter 629638032Speter if (tTd(38, 20)) 629790792Sgshapiro sm_dprintf("user_map_lookup(%s, %s)\n", 629838032Speter map->map_mname, key); 629938032Speter 630090792Sgshapiro *statp = finduser(key, &fuzzy, &user); 630190792Sgshapiro if (*statp != EX_OK) 630238032Speter return NULL; 630338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 630438032Speter return map_rewrite(map, key, strlen(key), NULL); 630538032Speter else 630638032Speter { 630738032Speter char *rwval = NULL; 630838032Speter char buf[30]; 630938032Speter 631038032Speter switch (map->map_valcolno) 631138032Speter { 631238032Speter case 0: 631338032Speter case 1: 631490792Sgshapiro rwval = user.mbdb_name; 631538032Speter break; 631638032Speter 631738032Speter case 2: 631890792Sgshapiro rwval = "x"; /* passwd no longer supported */ 631938032Speter break; 632038032Speter 632138032Speter case 3: 632290792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%d", 632390792Sgshapiro (int) user.mbdb_uid); 632438032Speter rwval = buf; 632538032Speter break; 632638032Speter 632738032Speter case 4: 632890792Sgshapiro (void) sm_snprintf(buf, sizeof buf, "%d", 632990792Sgshapiro (int) user.mbdb_gid); 633038032Speter rwval = buf; 633138032Speter break; 633238032Speter 633338032Speter case 5: 633490792Sgshapiro rwval = user.mbdb_fullname; 633538032Speter break; 633638032Speter 633738032Speter case 6: 633890792Sgshapiro rwval = user.mbdb_homedir; 633938032Speter break; 634038032Speter 634138032Speter case 7: 634290792Sgshapiro rwval = user.mbdb_shell; 634338032Speter break; 634438032Speter } 634538032Speter return map_rewrite(map, rwval, strlen(rwval), av); 634638032Speter } 634738032Speter} 634890792Sgshapiro/* 634938032Speter** Program map type. 635038032Speter** 635138032Speter** This provides access to arbitrary programs. It should be used 635238032Speter** only very sparingly, since there is no way to bound the cost 635338032Speter** of invoking an arbitrary program. 635438032Speter*/ 635538032Speter 635638032Speterchar * 635738032Speterprog_map_lookup(map, name, av, statp) 635838032Speter MAP *map; 635938032Speter char *name; 636038032Speter char **av; 636138032Speter int *statp; 636238032Speter{ 636338032Speter int i; 636464562Sgshapiro int save_errno; 636538032Speter int fd; 636664562Sgshapiro int status; 636738032Speter auto pid_t pid; 636864562Sgshapiro register char *p; 636938032Speter char *rval; 637038032Speter char *argv[MAXPV + 1]; 637138032Speter char buf[MAXLINE]; 637238032Speter 637338032Speter if (tTd(38, 20)) 637490792Sgshapiro sm_dprintf("prog_map_lookup(%s, %s) %s\n", 637538032Speter map->map_mname, name, map->map_file); 637638032Speter 637738032Speter i = 0; 637838032Speter argv[i++] = map->map_file; 637938032Speter if (map->map_rebuild != NULL) 638038032Speter { 638190792Sgshapiro (void) sm_strlcpy(buf, map->map_rebuild, sizeof buf); 638238032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 638338032Speter { 638438032Speter if (i >= MAXPV - 1) 638538032Speter break; 638638032Speter argv[i++] = p; 638738032Speter } 638838032Speter } 638938032Speter argv[i++] = name; 639038032Speter argv[i] = NULL; 639138032Speter if (tTd(38, 21)) 639238032Speter { 639390792Sgshapiro sm_dprintf("prog_open:"); 639438032Speter for (i = 0; argv[i] != NULL; i++) 639590792Sgshapiro sm_dprintf(" %s", argv[i]); 639690792Sgshapiro sm_dprintf("\n"); 639738032Speter } 639890792Sgshapiro (void) sm_blocksignal(SIGCHLD); 639938032Speter pid = prog_open(argv, &fd, CurEnv); 640038032Speter if (pid < 0) 640138032Speter { 640238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 640338032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 640490792Sgshapiro map->map_mname, sm_errstring(errno)); 640538032Speter else if (tTd(38, 9)) 640690792Sgshapiro sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 640790792Sgshapiro map->map_mname, sm_errstring(errno)); 640838032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 640938032Speter *statp = EX_OSFILE; 641038032Speter return NULL; 641138032Speter } 641238032Speter i = read(fd, buf, sizeof buf - 1); 641338032Speter if (i < 0) 641438032Speter { 641590792Sgshapiro syserr("prog_map_lookup(%s): read error %s", 641690792Sgshapiro map->map_mname, sm_errstring(errno)); 641738032Speter rval = NULL; 641838032Speter } 641938032Speter else if (i == 0) 642038032Speter { 642138032Speter if (tTd(38, 20)) 642290792Sgshapiro sm_dprintf("prog_map_lookup(%s): empty answer\n", 642390792Sgshapiro map->map_mname); 642438032Speter rval = NULL; 642538032Speter } 642638032Speter else 642738032Speter { 642838032Speter buf[i] = '\0'; 642938032Speter p = strchr(buf, '\n'); 643038032Speter if (p != NULL) 643138032Speter *p = '\0'; 643238032Speter 643338032Speter /* collect the return value */ 643438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 643538032Speter rval = map_rewrite(map, name, strlen(name), NULL); 643638032Speter else 643777349Sgshapiro rval = map_rewrite(map, buf, strlen(buf), av); 643838032Speter 643938032Speter /* now flush any additional output */ 644038032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 644138032Speter continue; 644238032Speter } 644338032Speter 644438032Speter /* wait for the process to terminate */ 644564562Sgshapiro (void) close(fd); 644664562Sgshapiro status = waitfor(pid); 644764562Sgshapiro save_errno = errno; 644890792Sgshapiro (void) sm_releasesignal(SIGCHLD); 644964562Sgshapiro errno = save_errno; 645038032Speter 645164562Sgshapiro if (status == -1) 645238032Speter { 645390792Sgshapiro syserr("prog_map_lookup(%s): wait error %s", 645490792Sgshapiro map->map_mname, sm_errstring(errno)); 645538032Speter *statp = EX_SOFTWARE; 645638032Speter rval = NULL; 645738032Speter } 645864562Sgshapiro else if (WIFEXITED(status)) 645938032Speter { 646064562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 646138032Speter rval = NULL; 646238032Speter } 646338032Speter else 646438032Speter { 646538032Speter syserr("prog_map_lookup(%s): child died on signal %d", 646690792Sgshapiro map->map_mname, status); 646738032Speter *statp = EX_UNAVAILABLE; 646838032Speter rval = NULL; 646938032Speter } 647038032Speter return rval; 647138032Speter} 647290792Sgshapiro/* 647338032Speter** Sequenced map type. 647438032Speter** 647538032Speter** Tries each map in order until something matches, much like 647638032Speter** implicit. Stores go to the first map in the list that can 647738032Speter** support storing. 647838032Speter** 647938032Speter** This is slightly unusual in that there are two interfaces. 648038032Speter** The "sequence" interface lets you stack maps arbitrarily. 648138032Speter** The "switch" interface builds a sequence map by looking 648238032Speter** at a system-dependent configuration file such as 648338032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 648438032Speter** 648538032Speter** We don't need an explicit open, since all maps are 648690792Sgshapiro** opened on demand. 648738032Speter*/ 648838032Speter 648938032Speter/* 649038032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 649138032Speter*/ 649238032Speter 649338032Speterbool 649438032Speterseq_map_parse(map, ap) 649538032Speter MAP *map; 649638032Speter char *ap; 649738032Speter{ 649838032Speter int maxmap; 649938032Speter 650038032Speter if (tTd(38, 2)) 650190792Sgshapiro sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 650238032Speter maxmap = 0; 650338032Speter while (*ap != '\0') 650438032Speter { 650538032Speter register char *p; 650638032Speter STAB *s; 650738032Speter 650838032Speter /* find beginning of map name */ 650938032Speter while (isascii(*ap) && isspace(*ap)) 651038032Speter ap++; 651164562Sgshapiro for (p = ap; 651264562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 651364562Sgshapiro p++) 651438032Speter continue; 651538032Speter if (*p != '\0') 651638032Speter *p++ = '\0'; 651738032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 651838032Speter p++; 651938032Speter if (*ap == '\0') 652038032Speter { 652138032Speter ap = p; 652238032Speter continue; 652338032Speter } 652438032Speter s = stab(ap, ST_MAP, ST_FIND); 652538032Speter if (s == NULL) 652638032Speter { 652738032Speter syserr("Sequence map %s: unknown member map %s", 652838032Speter map->map_mname, ap); 652938032Speter } 653090792Sgshapiro else if (maxmap >= MAXMAPSTACK) 653138032Speter { 653238032Speter syserr("Sequence map %s: too many member maps (%d max)", 653338032Speter map->map_mname, MAXMAPSTACK); 653438032Speter maxmap++; 653538032Speter } 653638032Speter else if (maxmap < MAXMAPSTACK) 653738032Speter { 653838032Speter map->map_stack[maxmap++] = &s->s_map; 653938032Speter } 654038032Speter ap = p; 654138032Speter } 654290792Sgshapiro return true; 654338032Speter} 654438032Speter 654538032Speter/* 654638032Speter** SWITCH_MAP_OPEN -- open a switched map 654738032Speter** 654838032Speter** This looks at the system-dependent configuration and builds 654938032Speter** a sequence map that does the same thing. 655038032Speter** 655138032Speter** Every system must define a switch_map_find routine in conf.c 655238032Speter** that will return the list of service types associated with a 655338032Speter** given service class. 655438032Speter*/ 655538032Speter 655638032Speterbool 655738032Speterswitch_map_open(map, mode) 655838032Speter MAP *map; 655938032Speter int mode; 656038032Speter{ 656138032Speter int mapno; 656238032Speter int nmaps; 656338032Speter char *maptype[MAXMAPSTACK]; 656438032Speter 656538032Speter if (tTd(38, 2)) 656690792Sgshapiro sm_dprintf("switch_map_open(%s, %s, %d)\n", 656738032Speter map->map_mname, map->map_file, mode); 656838032Speter 656938032Speter mode &= O_ACCMODE; 657038032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 657138032Speter if (tTd(38, 19)) 657238032Speter { 657390792Sgshapiro sm_dprintf("\tswitch_map_find => %d\n", nmaps); 657438032Speter for (mapno = 0; mapno < nmaps; mapno++) 657590792Sgshapiro sm_dprintf("\t\t%s\n", maptype[mapno]); 657638032Speter } 657738032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 657890792Sgshapiro return false; 657938032Speter 658038032Speter for (mapno = 0; mapno < nmaps; mapno++) 658138032Speter { 658238032Speter register STAB *s; 658338032Speter char nbuf[MAXNAME + 1]; 658438032Speter 658538032Speter if (maptype[mapno] == NULL) 658638032Speter continue; 658790792Sgshapiro (void) sm_strlcpyn(nbuf, sizeof nbuf, 3, 658890792Sgshapiro map->map_mname, ".", maptype[mapno]); 658938032Speter s = stab(nbuf, ST_MAP, ST_FIND); 659038032Speter if (s == NULL) 659138032Speter { 659238032Speter syserr("Switch map %s: unknown member map %s", 659338032Speter map->map_mname, nbuf); 659438032Speter } 659538032Speter else 659638032Speter { 659738032Speter map->map_stack[mapno] = &s->s_map; 659838032Speter if (tTd(38, 4)) 659990792Sgshapiro sm_dprintf("\tmap_stack[%d] = %s:%s\n", 660090792Sgshapiro mapno, 660190792Sgshapiro s->s_map.map_class->map_cname, 660290792Sgshapiro nbuf); 660338032Speter } 660438032Speter } 660590792Sgshapiro return true; 660638032Speter} 660738032Speter 660890792Sgshapiro#if 0 660938032Speter/* 661038032Speter** SEQ_MAP_CLOSE -- close all underlying maps 661138032Speter*/ 661238032Speter 661338032Spetervoid 661438032Speterseq_map_close(map) 661538032Speter MAP *map; 661638032Speter{ 661738032Speter int mapno; 661838032Speter 661938032Speter if (tTd(38, 9)) 662090792Sgshapiro sm_dprintf("seq_map_close(%s)\n", map->map_mname); 662138032Speter 662238032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 662338032Speter { 662438032Speter MAP *mm = map->map_stack[mapno]; 662538032Speter 662638032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 662738032Speter continue; 662877349Sgshapiro mm->map_mflags |= MF_CLOSING; 662938032Speter mm->map_class->map_close(mm); 663077349Sgshapiro mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 663138032Speter } 663238032Speter} 663390792Sgshapiro#endif /* 0 */ 663438032Speter 663538032Speter/* 663638032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 663738032Speter*/ 663838032Speter 663938032Speterchar * 664038032Speterseq_map_lookup(map, key, args, pstat) 664138032Speter MAP *map; 664238032Speter char *key; 664338032Speter char **args; 664438032Speter int *pstat; 664538032Speter{ 664638032Speter int mapno; 664738032Speter int mapbit = 0x01; 664890792Sgshapiro bool tempfail = false; 664938032Speter 665038032Speter if (tTd(38, 20)) 665190792Sgshapiro sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 665238032Speter 665338032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 665438032Speter { 665538032Speter MAP *mm = map->map_stack[mapno]; 665638032Speter char *rv; 665738032Speter 665838032Speter if (mm == NULL) 665938032Speter continue; 666064562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 666164562Sgshapiro !openmap(mm)) 666238032Speter { 666338032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 666438032Speter { 666538032Speter *pstat = EX_UNAVAILABLE; 666638032Speter return NULL; 666738032Speter } 666838032Speter continue; 666938032Speter } 667038032Speter *pstat = EX_OK; 667138032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 667238032Speter if (rv != NULL) 667338032Speter return rv; 667438032Speter if (*pstat == EX_TEMPFAIL) 667538032Speter { 667638032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 667738032Speter return NULL; 667890792Sgshapiro tempfail = true; 667938032Speter } 668038032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 668138032Speter break; 668238032Speter } 668338032Speter if (tempfail) 668438032Speter *pstat = EX_TEMPFAIL; 668538032Speter else if (*pstat == EX_OK) 668638032Speter *pstat = EX_NOTFOUND; 668738032Speter return NULL; 668838032Speter} 668938032Speter 669038032Speter/* 669138032Speter** SEQ_MAP_STORE -- sequenced map store 669238032Speter*/ 669338032Speter 669438032Spetervoid 669538032Speterseq_map_store(map, key, val) 669638032Speter MAP *map; 669738032Speter char *key; 669838032Speter char *val; 669938032Speter{ 670038032Speter int mapno; 670138032Speter 670238032Speter if (tTd(38, 12)) 670390792Sgshapiro sm_dprintf("seq_map_store(%s, %s, %s)\n", 670438032Speter map->map_mname, key, val); 670538032Speter 670638032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 670738032Speter { 670838032Speter MAP *mm = map->map_stack[mapno]; 670938032Speter 671038032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 671138032Speter continue; 671238032Speter 671338032Speter mm->map_class->map_store(mm, key, val); 671438032Speter return; 671538032Speter } 671638032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 671738032Speter map->map_mname, key, val); 671838032Speter} 671990792Sgshapiro/* 672038032Speter** NULL stubs 672138032Speter*/ 672238032Speter 672338032Speter/* ARGSUSED */ 672438032Speterbool 672538032Speternull_map_open(map, mode) 672638032Speter MAP *map; 672738032Speter int mode; 672838032Speter{ 672990792Sgshapiro return true; 673038032Speter} 673138032Speter 673238032Speter/* ARGSUSED */ 673338032Spetervoid 673438032Speternull_map_close(map) 673538032Speter MAP *map; 673638032Speter{ 673738032Speter return; 673838032Speter} 673938032Speter 674038032Speterchar * 674138032Speternull_map_lookup(map, key, args, pstat) 674238032Speter MAP *map; 674338032Speter char *key; 674438032Speter char **args; 674538032Speter int *pstat; 674638032Speter{ 674738032Speter *pstat = EX_NOTFOUND; 674838032Speter return NULL; 674938032Speter} 675038032Speter 675138032Speter/* ARGSUSED */ 675238032Spetervoid 675338032Speternull_map_store(map, key, val) 675438032Speter MAP *map; 675538032Speter char *key; 675638032Speter char *val; 675738032Speter{ 675838032Speter return; 675938032Speter} 676038032Speter 676138032Speter/* 676238032Speter** BOGUS stubs 676338032Speter*/ 676438032Speter 676538032Speterchar * 676638032Speterbogus_map_lookup(map, key, args, pstat) 676738032Speter MAP *map; 676838032Speter char *key; 676938032Speter char **args; 677038032Speter int *pstat; 677138032Speter{ 677238032Speter *pstat = EX_TEMPFAIL; 677338032Speter return NULL; 677438032Speter} 677538032Speter 677638032SpeterMAPCLASS BogusMapClass = 677738032Speter{ 677890792Sgshapiro "bogus-map", NULL, 0, 677990792Sgshapiro NULL, bogus_map_lookup, null_map_store, 678090792Sgshapiro null_map_open, null_map_close, 678138032Speter}; 678290792Sgshapiro/* 678364562Sgshapiro** MACRO modules 678464562Sgshapiro*/ 678564562Sgshapiro 678664562Sgshapirochar * 678764562Sgshapiromacro_map_lookup(map, name, av, statp) 678864562Sgshapiro MAP *map; 678964562Sgshapiro char *name; 679064562Sgshapiro char **av; 679164562Sgshapiro int *statp; 679264562Sgshapiro{ 679364562Sgshapiro int mid; 679464562Sgshapiro 679564562Sgshapiro if (tTd(38, 20)) 679690792Sgshapiro sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 679764562Sgshapiro name == NULL ? "NULL" : name); 679864562Sgshapiro 679964562Sgshapiro if (name == NULL || 680064562Sgshapiro *name == '\0' || 680190792Sgshapiro (mid = macid(name)) == 0) 680264562Sgshapiro { 680364562Sgshapiro *statp = EX_CONFIG; 680464562Sgshapiro return NULL; 680564562Sgshapiro } 680664562Sgshapiro 680764562Sgshapiro if (av[1] == NULL) 680890792Sgshapiro macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 680964562Sgshapiro else 681090792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 681164562Sgshapiro 681264562Sgshapiro *statp = EX_OK; 681364562Sgshapiro return ""; 681464562Sgshapiro} 681590792Sgshapiro/* 681638032Speter** REGEX modules 681738032Speter*/ 681838032Speter 681990792Sgshapiro#if MAP_REGEX 682038032Speter 682138032Speter# include <regex.h> 682238032Speter 682338032Speter# define DEFAULT_DELIM CONDELSE 682438032Speter# define END_OF_FIELDS -1 682538032Speter# define ERRBUF_SIZE 80 682638032Speter# define MAX_MATCH 32 682738032Speter 682864562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 682938032Speter 683038032Speterstruct regex_map 683138032Speter{ 683271345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 683338032Speter int *regex_subfields; /* move to type MAP */ 683464562Sgshapiro char *regex_delim; /* move to type MAP */ 683538032Speter}; 683638032Speter 683738032Speterstatic int 683838032Speterparse_fields(s, ibuf, blen, nr_substrings) 683938032Speter char *s; 684038032Speter int *ibuf; /* array */ 684138032Speter int blen; /* number of elements in ibuf */ 684238032Speter int nr_substrings; /* number of substrings in the pattern */ 684338032Speter{ 684438032Speter register char *cp; 684538032Speter int i = 0; 684690792Sgshapiro bool lastone = false; 684738032Speter 684838032Speter blen--; /* for terminating END_OF_FIELDS */ 684938032Speter cp = s; 685038032Speter do 685138032Speter { 685238032Speter for (;; cp++) 685338032Speter { 685438032Speter if (*cp == ',') 685538032Speter { 685638032Speter *cp = '\0'; 685738032Speter break; 685838032Speter } 685938032Speter if (*cp == '\0') 686038032Speter { 686190792Sgshapiro lastone = true; 686238032Speter break; 686338032Speter } 686438032Speter } 686538032Speter if (i < blen) 686638032Speter { 686738032Speter int val = atoi(s); 686838032Speter 686938032Speter if (val < 0 || val >= nr_substrings) 687038032Speter { 687138032Speter syserr("field (%d) out of range, only %d substrings in pattern", 687238032Speter val, nr_substrings); 687338032Speter return -1; 687438032Speter } 687538032Speter ibuf[i++] = val; 687638032Speter } 687738032Speter else 687838032Speter { 687990792Sgshapiro syserr("too many fields, %d max", blen); 688038032Speter return -1; 688138032Speter } 688238032Speter s = ++cp; 688338032Speter } while (!lastone); 688438032Speter ibuf[i] = END_OF_FIELDS; 688538032Speter return i; 688638032Speter} 688738032Speter 688838032Speterbool 688938032Speterregex_map_init(map, ap) 689038032Speter MAP *map; 689138032Speter char *ap; 689238032Speter{ 689338032Speter int regerr; 689438032Speter struct regex_map *map_p; 689538032Speter register char *p; 689638032Speter char *sub_param = NULL; 689738032Speter int pflags; 689890792Sgshapiro static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 689938032Speter 690038032Speter if (tTd(38, 2)) 690190792Sgshapiro sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 690264562Sgshapiro map->map_mname, ap); 690338032Speter 690438032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 690538032Speter p = ap; 690664562Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof *map_p); 690771345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 690838032Speter 690938032Speter for (;;) 691064562Sgshapiro { 691138032Speter while (isascii(*p) && isspace(*p)) 691238032Speter p++; 691338032Speter if (*p != '-') 691438032Speter break; 691538032Speter switch (*++p) 691638032Speter { 691738032Speter case 'n': /* not */ 691838032Speter map->map_mflags |= MF_REGEX_NOT; 691938032Speter break; 692038032Speter 692138032Speter case 'f': /* case sensitive */ 692238032Speter map->map_mflags |= MF_NOFOLDCASE; 692338032Speter pflags &= ~REG_ICASE; 692438032Speter break; 692538032Speter 692638032Speter case 'b': /* basic regular expressions */ 692738032Speter pflags &= ~REG_EXTENDED; 692838032Speter break; 692938032Speter 693038032Speter case 's': /* substring match () syntax */ 693138032Speter sub_param = ++p; 693238032Speter pflags &= ~REG_NOSUB; 693338032Speter break; 693438032Speter 693538032Speter case 'd': /* delimiter */ 693664562Sgshapiro map_p->regex_delim = ++p; 693738032Speter break; 693838032Speter 693938032Speter case 'a': /* map append */ 694038032Speter map->map_app = ++p; 694138032Speter break; 694238032Speter 694338032Speter case 'm': /* matchonly */ 694438032Speter map->map_mflags |= MF_MATCHONLY; 694538032Speter break; 694638032Speter 6947120256Sgshapiro case 'q': 6948120256Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 6949120256Sgshapiro break; 6950120256Sgshapiro 695164562Sgshapiro case 'S': 695264562Sgshapiro map->map_spacesub = *++p; 695364562Sgshapiro break; 695464562Sgshapiro 695564562Sgshapiro case 'D': 695664562Sgshapiro map->map_mflags |= MF_DEFER; 695764562Sgshapiro break; 695864562Sgshapiro 695938032Speter } 696064562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 696164562Sgshapiro p++; 696264562Sgshapiro if (*p != '\0') 696364562Sgshapiro *p++ = '\0'; 696438032Speter } 696538032Speter if (tTd(38, 3)) 696690792Sgshapiro sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 696738032Speter 696871345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 696938032Speter { 697038032Speter /* Errorhandling */ 697138032Speter char errbuf[ERRBUF_SIZE]; 697238032Speter 697371345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 697490792Sgshapiro errbuf, sizeof errbuf); 697590792Sgshapiro syserr("pattern-compile-error: %s", errbuf); 697690792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 697790792Sgshapiro sm_free(map_p); /* XXX */ 697890792Sgshapiro return false; 697938032Speter } 698038032Speter 698138032Speter if (map->map_app != NULL) 698238032Speter map->map_app = newstr(map->map_app); 698364562Sgshapiro if (map_p->regex_delim != NULL) 698464562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 698538032Speter else 698664562Sgshapiro map_p->regex_delim = defdstr; 698738032Speter 698838032Speter if (!bitset(REG_NOSUB, pflags)) 698938032Speter { 699038032Speter /* substring matching */ 699138032Speter int substrings; 699264562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 699338032Speter 699471345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 699538032Speter 699638032Speter if (tTd(38, 3)) 699790792Sgshapiro sm_dprintf("regex_map_init: nr of substrings %d\n", 699864562Sgshapiro substrings); 699938032Speter 700038032Speter if (substrings >= MAX_MATCH) 700138032Speter { 700290792Sgshapiro syserr("too many substrings, %d max", MAX_MATCH); 700390792Sgshapiro sm_free(map_p->regex_pattern_buf); /* XXX */ 700490792Sgshapiro sm_free(map_p); /* XXX */ 700590792Sgshapiro return false; 700638032Speter } 700738032Speter if (sub_param != NULL && sub_param[0] != '\0') 700838032Speter { 700938032Speter /* optional parameter -sfields */ 701038032Speter if (parse_fields(sub_param, fields, 701138032Speter MAX_MATCH + 1, substrings) == -1) 701290792Sgshapiro return false; 701338032Speter } 701438032Speter else 701538032Speter { 701638032Speter int i; 701738032Speter 701890792Sgshapiro /* set default fields */ 701938032Speter for (i = 0; i < substrings; i++) 702038032Speter fields[i] = i; 702138032Speter fields[i] = END_OF_FIELDS; 702238032Speter } 702338032Speter map_p->regex_subfields = fields; 702438032Speter if (tTd(38, 3)) 702538032Speter { 702638032Speter int *ip; 702738032Speter 702890792Sgshapiro sm_dprintf("regex_map_init: subfields"); 702938032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 703090792Sgshapiro sm_dprintf(" %d", *ip); 703190792Sgshapiro sm_dprintf("\n"); 703238032Speter } 703338032Speter } 703490792Sgshapiro map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 703590792Sgshapiro return true; 703638032Speter} 703738032Speter 703838032Speterstatic char * 703938032Speterregex_map_rewrite(map, s, slen, av) 704038032Speter MAP *map; 704138032Speter const char *s; 704238032Speter size_t slen; 704338032Speter char **av; 704438032Speter{ 704538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 704638032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 704738032Speter else 704877349Sgshapiro return map_rewrite(map, s, slen, av); 704938032Speter} 705038032Speter 705138032Speterchar * 705238032Speterregex_map_lookup(map, name, av, statp) 705338032Speter MAP *map; 705438032Speter char *name; 705538032Speter char **av; 705638032Speter int *statp; 705738032Speter{ 705838032Speter int reg_res; 705938032Speter struct regex_map *map_p; 706038032Speter regmatch_t pmatch[MAX_MATCH]; 706138032Speter 706238032Speter if (tTd(38, 20)) 706338032Speter { 706438032Speter char **cpp; 706538032Speter 706690792Sgshapiro sm_dprintf("regex_map_lookup: key '%s'\n", name); 706764562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 706890792Sgshapiro sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 706938032Speter } 707038032Speter 707138032Speter map_p = (struct regex_map *)(map->map_db1); 707271345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 707364562Sgshapiro name, MAX_MATCH, pmatch, 0); 707438032Speter 707538032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 707638032Speter { 707738032Speter /* option -n */ 707838032Speter if (reg_res == REG_NOMATCH) 707990792Sgshapiro return regex_map_rewrite(map, "", (size_t) 0, av); 708038032Speter else 708138032Speter return NULL; 708238032Speter } 708338032Speter if (reg_res == REG_NOMATCH) 708438032Speter return NULL; 708538032Speter 708638032Speter if (map_p->regex_subfields != NULL) 708738032Speter { 708838032Speter /* option -s */ 708938032Speter static char retbuf[MAXNAME]; 709038032Speter int fields[MAX_MATCH + 1]; 709190792Sgshapiro bool first = true; 709238032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 709390792Sgshapiro bool quotemode = false, bslashmode = false; 709438032Speter register char *dp, *sp; 709538032Speter char *endp, *ldp; 709638032Speter int *ip; 709738032Speter 709838032Speter dp = retbuf; 709938032Speter ldp = retbuf + sizeof(retbuf) - 1; 710038032Speter 710138032Speter if (av[1] != NULL) 710238032Speter { 710338032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 710471345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 710538032Speter { 710638032Speter *statp = EX_CONFIG; 710738032Speter return NULL; 710838032Speter } 710938032Speter ip = fields; 711038032Speter } 711138032Speter else 711238032Speter ip = map_p->regex_subfields; 711338032Speter 711438032Speter for ( ; *ip != END_OF_FIELDS; ip++) 711538032Speter { 711638032Speter if (!first) 711738032Speter { 711864562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 711938032Speter { 712038032Speter if (dp < ldp) 712138032Speter *dp++ = *sp; 712238032Speter } 712338032Speter } 712438032Speter else 712590792Sgshapiro first = false; 712638032Speter 712771345Sgshapiro if (*ip >= MAX_MATCH || 712871345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 712938032Speter continue; 713038032Speter 713138032Speter sp = name + pmatch[*ip].rm_so; 713238032Speter endp = name + pmatch[*ip].rm_eo; 713338032Speter for (; endp > sp; sp++) 713438032Speter { 713538032Speter if (dp < ldp) 713638032Speter { 713764562Sgshapiro if (bslashmode) 713864562Sgshapiro { 713938032Speter *dp++ = *sp; 714090792Sgshapiro bslashmode = false; 714138032Speter } 714264562Sgshapiro else if (quotemode && *sp != '"' && 714338032Speter *sp != '\\') 714438032Speter { 714538032Speter *dp++ = *sp; 714638032Speter } 714790792Sgshapiro else switch (*dp++ = *sp) 714838032Speter { 714990792Sgshapiro case '\\': 715090792Sgshapiro bslashmode = true; 715138032Speter break; 715238032Speter 715390792Sgshapiro case '(': 715438032Speter cmntcnt++; 715538032Speter break; 715638032Speter 715790792Sgshapiro case ')': 715838032Speter cmntcnt--; 715938032Speter break; 716038032Speter 716190792Sgshapiro case '<': 716238032Speter anglecnt++; 716338032Speter break; 716438032Speter 716590792Sgshapiro case '>': 716638032Speter anglecnt--; 716738032Speter break; 716838032Speter 716990792Sgshapiro case ' ': 717038032Speter spacecnt++; 717138032Speter break; 717238032Speter 717390792Sgshapiro case '"': 717438032Speter quotemode = !quotemode; 717538032Speter break; 717638032Speter } 717738032Speter } 717838032Speter } 717938032Speter } 718038032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 718138032Speter bslashmode || spacecnt != 0) 718238032Speter { 718364562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 718464562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 718564562Sgshapiro map->map_mname, name); 718638032Speter return NULL; 718738032Speter } 718838032Speter 718938032Speter *dp = '\0'; 719038032Speter 719138032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 719238032Speter } 719338032Speter return regex_map_rewrite(map, "", (size_t)0, av); 719438032Speter} 719538032Speter#endif /* MAP_REGEX */ 719690792Sgshapiro/* 719764562Sgshapiro** NSD modules 719864562Sgshapiro*/ 719990792Sgshapiro#if MAP_NSD 720064562Sgshapiro 720164562Sgshapiro# include <ndbm.h> 720264562Sgshapiro# define _DATUM_DEFINED 720364562Sgshapiro# include <ns_api.h> 720464562Sgshapiro 720564562Sgshapirotypedef struct ns_map_list 720664562Sgshapiro{ 720790792Sgshapiro ns_map_t *map; /* XXX ns_ ? */ 720890792Sgshapiro char *mapname; 720990792Sgshapiro struct ns_map_list *next; 721064562Sgshapiro} ns_map_list_t; 721164562Sgshapiro 721264562Sgshapirostatic ns_map_t * 721364562Sgshapirons_map_t_find(mapname) 721464562Sgshapiro char *mapname; 721564562Sgshapiro{ 721664562Sgshapiro static ns_map_list_t *ns_maps = NULL; 721764562Sgshapiro ns_map_list_t *ns_map; 721864562Sgshapiro 721964562Sgshapiro /* walk the list of maps looking for the correctly named map */ 722064562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 722164562Sgshapiro { 722264562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 722364562Sgshapiro break; 722464562Sgshapiro } 722564562Sgshapiro 722664562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 722764562Sgshapiro if (ns_map == NULL) 722864562Sgshapiro { 722964562Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 723064562Sgshapiro ns_map->mapname = newstr(mapname); 723164562Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 7232102528Sgshapiro memset(ns_map->map, '\0', sizeof *ns_map->map); 723364562Sgshapiro ns_map->next = ns_maps; 723464562Sgshapiro ns_maps = ns_map; 723564562Sgshapiro } 723664562Sgshapiro return ns_map->map; 723764562Sgshapiro} 723864562Sgshapiro 723964562Sgshapirochar * 724064562Sgshapironsd_map_lookup(map, name, av, statp) 724164562Sgshapiro MAP *map; 724264562Sgshapiro char *name; 724364562Sgshapiro char **av; 724464562Sgshapiro int *statp; 724564562Sgshapiro{ 724671345Sgshapiro int buflen, r; 724764562Sgshapiro char *p; 724864562Sgshapiro ns_map_t *ns_map; 724964562Sgshapiro char keybuf[MAXNAME + 1]; 725064562Sgshapiro char buf[MAXLINE]; 725164562Sgshapiro 725264562Sgshapiro if (tTd(38, 20)) 725390792Sgshapiro sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 725464562Sgshapiro 725564562Sgshapiro buflen = strlen(name); 725664562Sgshapiro if (buflen > sizeof keybuf - 1) 725790792Sgshapiro buflen = sizeof keybuf - 1; /* XXX simply cut off? */ 725864562Sgshapiro memmove(keybuf, name, buflen); 725964562Sgshapiro keybuf[buflen] = '\0'; 726064562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 726164562Sgshapiro makelower(keybuf); 726264562Sgshapiro 726364562Sgshapiro ns_map = ns_map_t_find(map->map_file); 726464562Sgshapiro if (ns_map == NULL) 726564562Sgshapiro { 726664562Sgshapiro if (tTd(38, 20)) 726790792Sgshapiro sm_dprintf("nsd_map_t_find failed\n"); 726871345Sgshapiro *statp = EX_UNAVAILABLE; 726964562Sgshapiro return NULL; 727064562Sgshapiro } 727198121Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 727298121Sgshapiro buf, sizeof buf); 727371345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 727471345Sgshapiro { 727571345Sgshapiro *statp = EX_TEMPFAIL; 727664562Sgshapiro return NULL; 727771345Sgshapiro } 727877349Sgshapiro if (r == NS_BADREQ 727977349Sgshapiro# ifdef NS_NOPERM 728077349Sgshapiro || r == NS_NOPERM 728177349Sgshapiro# endif /* NS_NOPERM */ 728277349Sgshapiro ) 728371345Sgshapiro { 728471345Sgshapiro *statp = EX_CONFIG; 728571345Sgshapiro return NULL; 728671345Sgshapiro } 728771345Sgshapiro if (r != NS_SUCCESS) 728871345Sgshapiro { 728971345Sgshapiro *statp = EX_NOTFOUND; 729071345Sgshapiro return NULL; 729171345Sgshapiro } 729264562Sgshapiro 729371345Sgshapiro *statp = EX_OK; 729471345Sgshapiro 729564562Sgshapiro /* Null out trailing \n */ 729664562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 729764562Sgshapiro *p = '\0'; 729864562Sgshapiro 729964562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 730064562Sgshapiro} 730164562Sgshapiro#endif /* MAP_NSD */ 730264562Sgshapiro 730364562Sgshapirochar * 730464562Sgshapiroarith_map_lookup(map, name, av, statp) 730564562Sgshapiro MAP *map; 730664562Sgshapiro char *name; 730764562Sgshapiro char **av; 730864562Sgshapiro int *statp; 730964562Sgshapiro{ 731064562Sgshapiro long r; 731164562Sgshapiro long v[2]; 731290792Sgshapiro bool res = false; 731364562Sgshapiro bool boolres; 731464562Sgshapiro static char result[16]; 731564562Sgshapiro char **cpp; 731664562Sgshapiro 731764562Sgshapiro if (tTd(38, 2)) 731864562Sgshapiro { 731990792Sgshapiro sm_dprintf("arith_map_lookup: key '%s'\n", name); 732064562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 732190792Sgshapiro sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 732264562Sgshapiro } 732364562Sgshapiro r = 0; 732490792Sgshapiro boolres = false; 732564562Sgshapiro cpp = av; 732664562Sgshapiro *statp = EX_OK; 732764562Sgshapiro 732864562Sgshapiro /* 732964562Sgshapiro ** read arguments for arith map 733064562Sgshapiro ** - no check is made whether they are really numbers 733164562Sgshapiro ** - just ignores args after the second 733264562Sgshapiro */ 733390792Sgshapiro 733464562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 733564562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 733664562Sgshapiro 733764562Sgshapiro /* operator and (at least) two operands given? */ 733864562Sgshapiro if (name != NULL && r == 2) 733964562Sgshapiro { 734090792Sgshapiro switch (*name) 734164562Sgshapiro { 734264562Sgshapiro case '|': 734364562Sgshapiro r = v[0] | v[1]; 734464562Sgshapiro break; 734564562Sgshapiro 734664562Sgshapiro case '&': 734764562Sgshapiro r = v[0] & v[1]; 734864562Sgshapiro break; 734964562Sgshapiro 735064562Sgshapiro case '%': 735164562Sgshapiro if (v[1] == 0) 735264562Sgshapiro return NULL; 735364562Sgshapiro r = v[0] % v[1]; 735464562Sgshapiro break; 735564562Sgshapiro case '+': 735664562Sgshapiro r = v[0] + v[1]; 735764562Sgshapiro break; 735864562Sgshapiro 735964562Sgshapiro case '-': 736064562Sgshapiro r = v[0] - v[1]; 736164562Sgshapiro break; 736264562Sgshapiro 736364562Sgshapiro case '*': 736464562Sgshapiro r = v[0] * v[1]; 736564562Sgshapiro break; 736664562Sgshapiro 736764562Sgshapiro case '/': 736864562Sgshapiro if (v[1] == 0) 736964562Sgshapiro return NULL; 737064562Sgshapiro r = v[0] / v[1]; 737164562Sgshapiro break; 737264562Sgshapiro 737364562Sgshapiro case 'l': 737464562Sgshapiro res = v[0] < v[1]; 737590792Sgshapiro boolres = true; 737664562Sgshapiro break; 737764562Sgshapiro 737864562Sgshapiro case '=': 737964562Sgshapiro res = v[0] == v[1]; 738090792Sgshapiro boolres = true; 738164562Sgshapiro break; 738264562Sgshapiro 738364562Sgshapiro default: 738464562Sgshapiro /* XXX */ 738564562Sgshapiro *statp = EX_CONFIG; 738664562Sgshapiro if (LogLevel > 10) 738764562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 738864562Sgshapiro "arith_map: unknown operator %c", 738964562Sgshapiro isprint(*name) ? *name : '?'); 739064562Sgshapiro return NULL; 739164562Sgshapiro } 739264562Sgshapiro if (boolres) 739390792Sgshapiro (void) sm_snprintf(result, sizeof result, 739490792Sgshapiro res ? "TRUE" : "FALSE"); 739564562Sgshapiro else 739690792Sgshapiro (void) sm_snprintf(result, sizeof result, "%ld", r); 739764562Sgshapiro return result; 739864562Sgshapiro } 739964562Sgshapiro *statp = EX_CONFIG; 740064562Sgshapiro return NULL; 740164562Sgshapiro} 7402