map.c revision 66494
138032Speter/* 264562Sgshapiro * Copyright (c) 1998-2000 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 1438032Speter#ifndef lint 1566494Sgshapirostatic char id[] = "@(#)$Id: map.c,v 8.414.4.24 2000/09/27 04:11:29 gshapiro Exp $"; 1664562Sgshapiro#endif /* ! lint */ 1738032Speter 1864562Sgshapiro#include <sendmail.h> 1938032Speter 2064562Sgshapiro 2138032Speter#ifdef NDBM 2238032Speter# include <ndbm.h> 2338032Speter# ifdef R_FIRST 2438032Speter ERROR README: You are running the Berkeley DB version of ndbm.h. See 2538032Speter ERROR README: the README file about tweaking Berkeley DB so it can 2638032Speter ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile 2738032Speter ERROR README: and use -DNEWDB instead. 2864562Sgshapiro# endif /* R_FIRST */ 2964562Sgshapiro#endif /* NDBM */ 3038032Speter#ifdef NEWDB 3138032Speter# include <db.h> 3238032Speter# ifndef DB_VERSION_MAJOR 3338032Speter# define DB_VERSION_MAJOR 1 3464562Sgshapiro# endif /* ! DB_VERSION_MAJOR */ 3564562Sgshapiro#endif /* NEWDB */ 3638032Speter#ifdef NIS 3738032Speter struct dom_binding; /* forward reference needed on IRIX */ 3838032Speter# include <rpcsvc/ypclnt.h> 3938032Speter# ifdef NDBM 4038032Speter# define NDBM_YP_COMPAT /* create YP-compatible NDBM files */ 4164562Sgshapiro# endif /* NDBM */ 4264562Sgshapiro#endif /* NIS */ 4338032Speter 4464562Sgshapiro#ifdef NEWDB 4564562Sgshapiro# if DB_VERSION_MAJOR < 2 4664562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); 4764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 4864562Sgshapiro# if DB_VERSION_MAJOR == 2 4964562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); 5064562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 5164562Sgshapiro# if DB_VERSION_MAJOR > 2 5264562Sgshapirostatic bool db_map_open __P((MAP *, int, char *, DBTYPE, void **)); 5364562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 5464562Sgshapiro#endif /* NEWDB */ 5564562Sgshapirostatic bool extract_canonname __P((char *, char *, char[], int)); 5664562Sgshapiro#ifdef LDAPMAP 5764562Sgshapirostatic void ldapmap_clear __P((LDAPMAP_STRUCT *)); 5864562Sgshapirostatic STAB *ldapmap_findconn __P((LDAPMAP_STRUCT *)); 5964562Sgshapirostatic int ldapmap_geterrno __P((LDAP *)); 6064562Sgshapirostatic void ldapmap_setopts __P((LDAP *, LDAPMAP_STRUCT *)); 6164562Sgshapirostatic bool ldapmap_start __P((MAP *)); 6264562Sgshapirostatic void ldaptimeout __P((int)); 6364562Sgshapiro#endif /* LDAPMAP */ 6464562Sgshapirostatic void map_close __P((STAB *, int)); 6564562Sgshapirostatic void map_init __P((STAB *, int)); 6664562Sgshapiro#ifdef NISPLUS 6764562Sgshapirostatic bool nisplus_getcanonname __P((char *, int, int *)); 6864562Sgshapiro#endif /* NISPLUS */ 6964562Sgshapiro#ifdef NIS 7064562Sgshapirostatic bool nis_getcanonname __P((char *, int, int *)); 7164562Sgshapiro#endif /* NIS */ 7264562Sgshapiro#if NETINFO 7364562Sgshapirostatic bool ni_getcanonname __P((char *, int, int *)); 7464562Sgshapiro#endif /* NETINFO */ 7564562Sgshapirostatic bool text_getcanonname __P((char *, int, int *)); 7664562Sgshapiro 7738032Speter/* 7838032Speter** MAP.C -- implementations for various map classes. 7938032Speter** 8038032Speter** Each map class implements a series of functions: 8138032Speter** 8238032Speter** bool map_parse(MAP *map, char *args) 8338032Speter** Parse the arguments from the config file. Return TRUE 8438032Speter** if they were ok, FALSE otherwise. Fill in map with the 8538032Speter** values. 8638032Speter** 8738032Speter** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 8838032Speter** Look up the key in the given map. If found, do any 8938032Speter** rewriting the map wants (including "args" if desired) 9038032Speter** and return the value. Set *pstat to the appropriate status 9138032Speter** on error and return NULL. Args will be NULL if called 9238032Speter** from the alias routines, although this should probably 9338032Speter** not be relied upon. It is suggested you call map_rewrite 9438032Speter** to return the results -- it takes care of null termination 9538032Speter** and uses a dynamically expanded buffer as needed. 9638032Speter** 9738032Speter** void map_store(MAP *map, char *key, char *value) 9838032Speter** Store the key:value pair in the map. 9938032Speter** 10038032Speter** bool map_open(MAP *map, int mode) 10138032Speter** Open the map for the indicated mode. Mode should 10238032Speter** be either O_RDONLY or O_RDWR. Return TRUE if it 10338032Speter** was opened successfully, FALSE otherwise. If the open 10438032Speter** failed an the MF_OPTIONAL flag is not set, it should 10538032Speter** also print an error. If the MF_ALIAS bit is set 10638032Speter** and this map class understands the @:@ convention, it 10738032Speter** should call aliaswait() before returning. 10838032Speter** 10938032Speter** void map_close(MAP *map) 11038032Speter** Close the map. 11138032Speter** 11238032Speter** This file also includes the implementation for getcanonname. 11338032Speter** It is currently implemented in a pretty ad-hoc manner; it ought 11438032Speter** to be more properly integrated into the map structure. 11538032Speter*/ 11638032Speter 11738032Speter#define DBMMODE 0644 11838032Speter 11938032Speter#ifndef EX_NOTFOUND 12038032Speter# define EX_NOTFOUND EX_NOHOST 12164562Sgshapiro#endif /* ! EX_NOTFOUND */ 12238032Speter 12338032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 12438032Speter# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 12564562Sgshapiro#else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 12638032Speter# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 12764562Sgshapiro#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 12838032Speter 12938032Speter#ifndef O_ACCMODE 13038032Speter# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) 13164562Sgshapiro#endif /* ! O_ACCMODE */ 13238032Speter/* 13338032Speter** MAP_PARSEARGS -- parse config line arguments for database lookup 13438032Speter** 13538032Speter** This is a generic version of the map_parse method. 13638032Speter** 13738032Speter** Parameters: 13838032Speter** map -- the map being initialized. 13938032Speter** ap -- a pointer to the args on the config line. 14038032Speter** 14138032Speter** Returns: 14238032Speter** TRUE -- if everything parsed OK. 14338032Speter** FALSE -- otherwise. 14438032Speter** 14538032Speter** Side Effects: 14638032Speter** null terminates the filename; stores it in map 14738032Speter*/ 14838032Speter 14938032Speterbool 15038032Spetermap_parseargs(map, ap) 15138032Speter MAP *map; 15238032Speter char *ap; 15338032Speter{ 15438032Speter register char *p = ap; 15538032Speter 15664562Sgshapiro /* 15764562Sgshapiro ** there is no check whether there is really an argument, 15864562Sgshapiro ** but that's not important enough to warrant extra code 15964562Sgshapiro */ 16038032Speter map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; 16164562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 16238032Speter for (;;) 16338032Speter { 16438032Speter while (isascii(*p) && isspace(*p)) 16538032Speter p++; 16638032Speter if (*p != '-') 16738032Speter break; 16838032Speter switch (*++p) 16938032Speter { 17038032Speter case 'N': 17138032Speter map->map_mflags |= MF_INCLNULL; 17238032Speter map->map_mflags &= ~MF_TRY0NULL; 17338032Speter break; 17438032Speter 17538032Speter case 'O': 17638032Speter map->map_mflags &= ~MF_TRY1NULL; 17738032Speter break; 17838032Speter 17938032Speter case 'o': 18038032Speter map->map_mflags |= MF_OPTIONAL; 18138032Speter break; 18238032Speter 18338032Speter case 'f': 18438032Speter map->map_mflags |= MF_NOFOLDCASE; 18538032Speter break; 18638032Speter 18738032Speter case 'm': 18838032Speter map->map_mflags |= MF_MATCHONLY; 18938032Speter break; 19038032Speter 19138032Speter case 'A': 19238032Speter map->map_mflags |= MF_APPEND; 19338032Speter break; 19438032Speter 19538032Speter case 'q': 19638032Speter map->map_mflags |= MF_KEEPQUOTES; 19738032Speter break; 19838032Speter 19938032Speter case 'a': 20038032Speter map->map_app = ++p; 20138032Speter break; 20238032Speter 20338032Speter case 'T': 20438032Speter map->map_tapp = ++p; 20538032Speter break; 20638032Speter 20738032Speter case 'k': 20838032Speter while (isascii(*++p) && isspace(*p)) 20938032Speter continue; 21038032Speter map->map_keycolnm = p; 21138032Speter break; 21238032Speter 21338032Speter case 'v': 21438032Speter while (isascii(*++p) && isspace(*p)) 21538032Speter continue; 21638032Speter map->map_valcolnm = p; 21738032Speter break; 21838032Speter 21938032Speter case 'z': 22038032Speter if (*++p != '\\') 22138032Speter map->map_coldelim = *p; 22238032Speter else 22338032Speter { 22438032Speter switch (*++p) 22538032Speter { 22638032Speter case 'n': 22738032Speter map->map_coldelim = '\n'; 22838032Speter break; 22938032Speter 23038032Speter case 't': 23138032Speter map->map_coldelim = '\t'; 23238032Speter break; 23338032Speter 23438032Speter default: 23538032Speter map->map_coldelim = '\\'; 23638032Speter } 23738032Speter } 23838032Speter break; 23938032Speter 24038032Speter case 't': 24138032Speter map->map_mflags |= MF_NODEFER; 24238032Speter break; 24338032Speter 24464562Sgshapiro 24564562Sgshapiro case 'S': 24664562Sgshapiro map->map_spacesub = *++p; 24738032Speter break; 24838032Speter 24964562Sgshapiro case 'D': 25064562Sgshapiro map->map_mflags |= MF_DEFER; 25138032Speter break; 25264562Sgshapiro 25364562Sgshapiro default: 25464562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 25564562Sgshapiro break; 25638032Speter } 25738032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 25838032Speter p++; 25938032Speter if (*p != '\0') 26038032Speter *p++ = '\0'; 26138032Speter } 26238032Speter if (map->map_app != NULL) 26338032Speter map->map_app = newstr(map->map_app); 26438032Speter if (map->map_tapp != NULL) 26538032Speter map->map_tapp = newstr(map->map_tapp); 26638032Speter if (map->map_keycolnm != NULL) 26738032Speter map->map_keycolnm = newstr(map->map_keycolnm); 26838032Speter if (map->map_valcolnm != NULL) 26938032Speter map->map_valcolnm = newstr(map->map_valcolnm); 27038032Speter 27138032Speter if (*p != '\0') 27238032Speter { 27338032Speter map->map_file = p; 27438032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 27538032Speter p++; 27638032Speter if (*p != '\0') 27738032Speter *p++ = '\0'; 27838032Speter map->map_file = newstr(map->map_file); 27938032Speter } 28038032Speter 28138032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 28238032Speter p++; 28338032Speter if (*p != '\0') 28438032Speter map->map_rebuild = newstr(p); 28538032Speter 28638032Speter if (map->map_file == NULL && 28738032Speter !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 28838032Speter { 28938032Speter syserr("No file name for %s map %s", 29038032Speter map->map_class->map_cname, map->map_mname); 29138032Speter return FALSE; 29238032Speter } 29338032Speter return TRUE; 29438032Speter} 29538032Speter/* 29638032Speter** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 29738032Speter** 29838032Speter** It also adds the map_app string. It can be used as a utility 29938032Speter** in the map_lookup method. 30038032Speter** 30138032Speter** Parameters: 30238032Speter** map -- the map that causes this. 30338032Speter** s -- the string to rewrite, NOT necessarily null terminated. 30438032Speter** slen -- the length of s. 30538032Speter** av -- arguments to interpolate into buf. 30638032Speter** 30738032Speter** Returns: 30838032Speter** Pointer to rewritten result. This is static data that 30938032Speter** should be copied if it is to be saved! 31038032Speter** 31138032Speter** Side Effects: 31238032Speter** none. 31338032Speter*/ 31438032Speter 31538032Speterchar * 31638032Spetermap_rewrite(map, s, slen, av) 31738032Speter register MAP *map; 31838032Speter register const char *s; 31938032Speter size_t slen; 32038032Speter char **av; 32138032Speter{ 32238032Speter register char *bp; 32338032Speter register char c; 32438032Speter char **avp; 32538032Speter register char *ap; 32638032Speter size_t l; 32738032Speter size_t len; 32838032Speter static size_t buflen = 0; 32938032Speter static char *buf = NULL; 33038032Speter 33138032Speter if (tTd(39, 1)) 33238032Speter { 33364562Sgshapiro dprintf("map_rewrite(%.*s), av =", (int)slen, s); 33438032Speter if (av == NULL) 33564562Sgshapiro dprintf(" (nullv)"); 33638032Speter else 33738032Speter { 33838032Speter for (avp = av; *avp != NULL; avp++) 33964562Sgshapiro dprintf("\n\t%s", *avp); 34038032Speter } 34164562Sgshapiro dprintf("\n"); 34238032Speter } 34338032Speter 34438032Speter /* count expected size of output (can safely overestimate) */ 34538032Speter l = len = slen; 34638032Speter if (av != NULL) 34738032Speter { 34838032Speter const char *sp = s; 34938032Speter 35038032Speter while (l-- > 0 && (c = *sp++) != '\0') 35138032Speter { 35238032Speter if (c != '%') 35338032Speter continue; 35438032Speter if (l-- <= 0) 35538032Speter break; 35638032Speter c = *sp++; 35738032Speter if (!(isascii(c) && isdigit(c))) 35838032Speter continue; 35938032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 36038032Speter continue; 36138032Speter if (*avp == NULL) 36238032Speter continue; 36338032Speter len += strlen(*avp); 36438032Speter } 36538032Speter } 36638032Speter if (map->map_app != NULL) 36738032Speter len += strlen(map->map_app); 36838032Speter if (buflen < ++len) 36938032Speter { 37038032Speter /* need to malloc additional space */ 37138032Speter buflen = len; 37238032Speter if (buf != NULL) 37338032Speter free(buf); 37438032Speter buf = xalloc(buflen); 37538032Speter } 37638032Speter 37738032Speter bp = buf; 37838032Speter if (av == NULL) 37938032Speter { 38064562Sgshapiro memmove(bp, s, slen); 38138032Speter bp += slen; 38264562Sgshapiro 38364562Sgshapiro /* assert(len > slen); */ 38464562Sgshapiro len -= slen; 38538032Speter } 38638032Speter else 38738032Speter { 38838032Speter while (slen-- > 0 && (c = *s++) != '\0') 38938032Speter { 39038032Speter if (c != '%') 39138032Speter { 39238032Speter pushc: 39364562Sgshapiro if (--len <= 0) 39464562Sgshapiro break; 39538032Speter *bp++ = c; 39638032Speter continue; 39738032Speter } 39838032Speter if (slen-- <= 0 || (c = *s++) == '\0') 39938032Speter c = '%'; 40038032Speter if (c == '%') 40138032Speter goto pushc; 40238032Speter if (!(isascii(c) && isdigit(c))) 40338032Speter { 40438032Speter *bp++ = '%'; 40564562Sgshapiro --len; 40638032Speter goto pushc; 40738032Speter } 40838032Speter for (avp = av; --c >= '0' && *avp != NULL; avp++) 40938032Speter continue; 41038032Speter if (*avp == NULL) 41138032Speter continue; 41238032Speter 41338032Speter /* transliterate argument into output string */ 41464562Sgshapiro for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len) 41538032Speter *bp++ = c; 41638032Speter } 41738032Speter } 41864562Sgshapiro if (map->map_app != NULL && len > 0) 41964562Sgshapiro (void) strlcpy(bp, map->map_app, len); 42038032Speter else 42138032Speter *bp = '\0'; 42238032Speter if (tTd(39, 1)) 42364562Sgshapiro dprintf("map_rewrite => %s\n", buf); 42438032Speter return buf; 42538032Speter} 42638032Speter/* 42764562Sgshapiro** INITMAPS -- rebuild alias maps 42838032Speter** 42938032Speter** Parameters: 43064562Sgshapiro** none. 43138032Speter** 43238032Speter** Returns: 43338032Speter** none. 43438032Speter*/ 43538032Speter 43638032Spetervoid 43764562Sgshapiroinitmaps() 43838032Speter{ 43938032Speter#if XDEBUG 44038032Speter checkfd012("entering initmaps"); 44164562Sgshapiro#endif /* XDEBUG */ 44238032Speter stabapply(map_init, 0); 44338032Speter#if XDEBUG 44438032Speter checkfd012("exiting initmaps"); 44564562Sgshapiro#endif /* XDEBUG */ 44638032Speter} 44764562Sgshapiro/* 44864562Sgshapiro** MAP_INIT -- rebuild a map 44964562Sgshapiro** 45064562Sgshapiro** Parameters: 45164562Sgshapiro** s -- STAB entry: if map: try to rebuild 45264562Sgshapiro** unused -- unused variable 45364562Sgshapiro** 45464562Sgshapiro** Returns: 45564562Sgshapiro** none. 45664562Sgshapiro** 45764562Sgshapiro** Side Effects: 45864562Sgshapiro** will close already open rebuildable map. 45964562Sgshapiro*/ 46038032Speter 46164562Sgshapiro/* ARGSUSED1 */ 46264562Sgshapirostatic void 46364562Sgshapiromap_init(s, unused) 46438032Speter register STAB *s; 46564562Sgshapiro int unused; 46638032Speter{ 46738032Speter register MAP *map; 46838032Speter 46938032Speter /* has to be a map */ 47038032Speter if (s->s_type != ST_MAP) 47138032Speter return; 47238032Speter 47338032Speter map = &s->s_map; 47438032Speter if (!bitset(MF_VALID, map->map_mflags)) 47538032Speter return; 47638032Speter 47738032Speter if (tTd(38, 2)) 47864562Sgshapiro dprintf("map_init(%s:%s, %s)\n", 47938032Speter map->map_class->map_cname == NULL ? "NULL" : 48038032Speter map->map_class->map_cname, 48138032Speter map->map_mname == NULL ? "NULL" : map->map_mname, 48264562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 48338032Speter 48464562Sgshapiro if (!bitset(MF_ALIAS, map->map_mflags) || 48564562Sgshapiro !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 48638032Speter { 48738032Speter if (tTd(38, 3)) 48864562Sgshapiro dprintf("\tnot rebuildable\n"); 48938032Speter return; 49038032Speter } 49138032Speter 49238032Speter /* if already open, close it (for nested open) */ 49338032Speter if (bitset(MF_OPEN, map->map_mflags)) 49438032Speter { 49538032Speter map->map_class->map_close(map); 49638032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 49738032Speter } 49838032Speter 49964562Sgshapiro (void) rebuildaliases(map, FALSE); 50064562Sgshapiro return; 50164562Sgshapiro} 50264562Sgshapiro/* 50364562Sgshapiro** OPENMAP -- open a map 50464562Sgshapiro** 50564562Sgshapiro** Parameters: 50664562Sgshapiro** map -- map to open (it must not be open). 50764562Sgshapiro** 50864562Sgshapiro** Returns: 50964562Sgshapiro** whether open succeeded. 51064562Sgshapiro** 51164562Sgshapiro*/ 51264562Sgshapiro 51364562Sgshapirobool 51464562Sgshapiroopenmap(map) 51564562Sgshapiro MAP *map; 51664562Sgshapiro{ 51764562Sgshapiro bool restore = FALSE; 51864562Sgshapiro bool savehold = HoldErrs; 51964562Sgshapiro bool savequick = QuickAbort; 52064562Sgshapiro int saveerrors = Errors; 52164562Sgshapiro 52264562Sgshapiro if (!bitset(MF_VALID, map->map_mflags)) 52364562Sgshapiro return FALSE; 52464562Sgshapiro 52564562Sgshapiro /* better safe than sorry... */ 52664562Sgshapiro if (bitset(MF_OPEN, map->map_mflags)) 52764562Sgshapiro return TRUE; 52864562Sgshapiro 52964562Sgshapiro /* Don't send a map open error out via SMTP */ 53064562Sgshapiro if ((OnlyOneError || QuickAbort) && 53164562Sgshapiro (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 53238032Speter { 53364562Sgshapiro restore = TRUE; 53464562Sgshapiro HoldErrs = TRUE; 53564562Sgshapiro QuickAbort = FALSE; 53638032Speter } 53738032Speter 53864562Sgshapiro errno = 0; 53938032Speter if (map->map_class->map_open(map, O_RDONLY)) 54038032Speter { 54138032Speter if (tTd(38, 4)) 54264562Sgshapiro dprintf("openmap()\t%s:%s %s: valid\n", 54338032Speter map->map_class->map_cname == NULL ? "NULL" : 54438032Speter map->map_class->map_cname, 54538032Speter map->map_mname == NULL ? "NULL" : 54638032Speter map->map_mname, 54738032Speter map->map_file == NULL ? "NULL" : 54838032Speter map->map_file); 54938032Speter map->map_mflags |= MF_OPEN; 55042575Speter map->map_pid = getpid(); 55138032Speter } 55238032Speter else 55338032Speter { 55438032Speter if (tTd(38, 4)) 55564562Sgshapiro dprintf("openmap()\t%s:%s %s: invalid%s%s\n", 55638032Speter map->map_class->map_cname == NULL ? "NULL" : 55738032Speter map->map_class->map_cname, 55838032Speter map->map_mname == NULL ? "NULL" : 55938032Speter map->map_mname, 56038032Speter map->map_file == NULL ? "NULL" : 56138032Speter map->map_file, 56264562Sgshapiro errno == 0 ? "" : ": ", 56364562Sgshapiro errno == 0 ? "" : errstring(errno)); 56438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 56538032Speter { 56638032Speter extern MAPCLASS BogusMapClass; 56738032Speter 56838032Speter map->map_class = &BogusMapClass; 56938032Speter map->map_mflags |= MF_OPEN; 57042575Speter map->map_pid = getpid(); 57166494Sgshapiro MapOpenErr = TRUE; 57238032Speter } 57364562Sgshapiro else 57464562Sgshapiro { 57564562Sgshapiro /* don't try again */ 57664562Sgshapiro map->map_mflags &= ~MF_VALID; 57764562Sgshapiro } 57838032Speter } 57964562Sgshapiro 58064562Sgshapiro if (restore) 58164562Sgshapiro { 58264562Sgshapiro Errors = saveerrors; 58364562Sgshapiro HoldErrs = savehold; 58464562Sgshapiro QuickAbort = savequick; 58564562Sgshapiro } 58664562Sgshapiro 58764562Sgshapiro return bitset(MF_OPEN, map->map_mflags); 58838032Speter} 58938032Speter/* 59042575Speter** CLOSEMAPS -- close all open maps opened by the current pid. 59142575Speter** 59242575Speter** Parameters: 59342575Speter** none 59442575Speter** 59542575Speter** Returns: 59642575Speter** none. 59742575Speter*/ 59842575Speter 59942575Spetervoid 60042575Speterclosemaps() 60142575Speter{ 60242575Speter stabapply(map_close, 0); 60342575Speter} 60464562Sgshapiro/* 60564562Sgshapiro** MAP_CLOSE -- close a map opened by the current pid. 60664562Sgshapiro** 60764562Sgshapiro** Parameters: 60864562Sgshapiro** s -- STAB entry: if map: try to open 60964562Sgshapiro** second parameter is unused (required by stabapply()) 61064562Sgshapiro** 61164562Sgshapiro** Returns: 61264562Sgshapiro** none. 61364562Sgshapiro*/ 61442575Speter 61542575Speter/* ARGSUSED1 */ 61664562Sgshapirostatic void 61742575Spetermap_close(s, unused) 61842575Speter register STAB *s; 61942575Speter int unused; 62042575Speter{ 62142575Speter MAP *map; 62242575Speter 62342575Speter if (s->s_type != ST_MAP) 62442575Speter return; 62564562Sgshapiro 62642575Speter map = &s->s_map; 62742575Speter 62842575Speter if (!bitset(MF_VALID, map->map_mflags) || 62942575Speter !bitset(MF_OPEN, map->map_mflags) || 63042575Speter map->map_pid != getpid()) 63142575Speter return; 63264562Sgshapiro 63342575Speter if (tTd(38, 5)) 63464562Sgshapiro dprintf("closemaps: closing %s (%s)\n", 63564562Sgshapiro map->map_mname == NULL ? "NULL" : map->map_mname, 63664562Sgshapiro map->map_file == NULL ? "NULL" : map->map_file); 63764562Sgshapiro 63842575Speter map->map_class->map_close(map); 63942575Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 64042575Speter} 64142575Speter/* 64238032Speter** GETCANONNAME -- look up name using service switch 64338032Speter** 64438032Speter** Parameters: 64538032Speter** host -- the host name to look up. 64638032Speter** hbsize -- the size of the host buffer. 64738032Speter** trymx -- if set, try MX records. 64838032Speter** 64938032Speter** Returns: 65038032Speter** TRUE -- if the host was found. 65138032Speter** FALSE -- otherwise. 65238032Speter*/ 65338032Speter 65438032Speterbool 65538032Spetergetcanonname(host, hbsize, trymx) 65638032Speter char *host; 65738032Speter int hbsize; 65838032Speter bool trymx; 65938032Speter{ 66038032Speter int nmaps; 66138032Speter int mapno; 66238032Speter bool found = FALSE; 66338032Speter bool got_tempfail = FALSE; 66464562Sgshapiro auto int status; 66538032Speter char *maptype[MAXMAPSTACK]; 66638032Speter short mapreturn[MAXMAPACTIONS]; 66738032Speter 66838032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 66938032Speter for (mapno = 0; mapno < nmaps; mapno++) 67038032Speter { 67138032Speter int i; 67238032Speter 67338032Speter if (tTd(38, 20)) 67464562Sgshapiro dprintf("getcanonname(%s), trying %s\n", 67538032Speter host, maptype[mapno]); 67638032Speter if (strcmp("files", maptype[mapno]) == 0) 67738032Speter { 67864562Sgshapiro found = text_getcanonname(host, hbsize, &status); 67938032Speter } 68038032Speter#ifdef NIS 68138032Speter else if (strcmp("nis", maptype[mapno]) == 0) 68238032Speter { 68364562Sgshapiro found = nis_getcanonname(host, hbsize, &status); 68438032Speter } 68564562Sgshapiro#endif /* NIS */ 68638032Speter#ifdef NISPLUS 68738032Speter else if (strcmp("nisplus", maptype[mapno]) == 0) 68838032Speter { 68964562Sgshapiro found = nisplus_getcanonname(host, hbsize, &status); 69038032Speter } 69164562Sgshapiro#endif /* NISPLUS */ 69238032Speter#if NAMED_BIND 69338032Speter else if (strcmp("dns", maptype[mapno]) == 0) 69438032Speter { 69564562Sgshapiro found = dns_getcanonname(host, hbsize, trymx, &status); 69638032Speter } 69764562Sgshapiro#endif /* NAMED_BIND */ 69838032Speter#if NETINFO 69938032Speter else if (strcmp("netinfo", maptype[mapno]) == 0) 70038032Speter { 70164562Sgshapiro found = ni_getcanonname(host, hbsize, &status); 70238032Speter } 70364562Sgshapiro#endif /* NETINFO */ 70438032Speter else 70538032Speter { 70638032Speter found = FALSE; 70764562Sgshapiro status = EX_UNAVAILABLE; 70838032Speter } 70938032Speter 71038032Speter /* 71138032Speter ** Heuristic: if $m is not set, we are running during system 71238032Speter ** startup. In this case, when a name is apparently found 71338032Speter ** but has no dot, treat is as not found. This avoids 71438032Speter ** problems if /etc/hosts has no FQDN but is listed first 71538032Speter ** in the service switch. 71638032Speter */ 71738032Speter 71838032Speter if (found && 71938032Speter (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 72038032Speter break; 72138032Speter 72238032Speter /* see if we should continue */ 72364562Sgshapiro if (status == EX_TEMPFAIL) 72438032Speter { 72538032Speter i = MA_TRYAGAIN; 72638032Speter got_tempfail = TRUE; 72738032Speter } 72864562Sgshapiro else if (status == EX_NOTFOUND) 72938032Speter i = MA_NOTFOUND; 73038032Speter else 73138032Speter i = MA_UNAVAIL; 73238032Speter if (bitset(1 << mapno, mapreturn[i])) 73338032Speter break; 73438032Speter } 73538032Speter 73638032Speter if (found) 73738032Speter { 73838032Speter char *d; 73938032Speter 74038032Speter if (tTd(38, 20)) 74164562Sgshapiro dprintf("getcanonname(%s), found\n", host); 74238032Speter 74338032Speter /* 74438032Speter ** If returned name is still single token, compensate 74538032Speter ** by tagging on $m. This is because some sites set 74638032Speter ** up their DNS or NIS databases wrong. 74738032Speter */ 74838032Speter 74938032Speter if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 75038032Speter { 75138032Speter d = macvalue('m', CurEnv); 75238032Speter if (d != NULL && 75338032Speter hbsize > (int) (strlen(host) + strlen(d) + 1)) 75438032Speter { 75538032Speter if (host[strlen(host) - 1] != '.') 75664562Sgshapiro (void) strlcat(host, ".", hbsize); 75764562Sgshapiro (void) strlcat(host, d, hbsize); 75838032Speter } 75938032Speter else 76038032Speter return FALSE; 76138032Speter } 76238032Speter return TRUE; 76338032Speter } 76438032Speter 76538032Speter if (tTd(38, 20)) 76664562Sgshapiro dprintf("getcanonname(%s), failed, status=%d\n", host, status); 76738032Speter 76838032Speter#if NAMED_BIND 76938032Speter if (got_tempfail) 77038032Speter h_errno = TRY_AGAIN; 77138032Speter else 77238032Speter h_errno = HOST_NOT_FOUND; 77364562Sgshapiro#endif /* NAMED_BIND */ 77438032Speter 77538032Speter return FALSE; 77638032Speter} 77738032Speter/* 77838032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 77938032Speter** 78038032Speter** Parameters: 78138032Speter** name -- the name against which to match. 78238032Speter** line -- the /etc/hosts line. 78338032Speter** cbuf -- the location to store the result. 78438032Speter** cbuflen -- the size of cbuf. 78538032Speter** 78638032Speter** Returns: 78738032Speter** TRUE -- if the line matched the desired name. 78838032Speter** FALSE -- otherwise. 78938032Speter*/ 79038032Speter 79164562Sgshapirostatic bool 79238032Speterextract_canonname(name, line, cbuf, cbuflen) 79338032Speter char *name; 79438032Speter char *line; 79538032Speter char cbuf[]; 79638032Speter int cbuflen; 79738032Speter{ 79838032Speter int i; 79938032Speter char *p; 80038032Speter bool found = FALSE; 80138032Speter 80238032Speter cbuf[0] = '\0'; 80338032Speter if (line[0] == '#') 80438032Speter return FALSE; 80538032Speter 80638032Speter for (i = 1; ; i++) 80738032Speter { 80838032Speter char nbuf[MAXNAME + 1]; 80938032Speter 81038032Speter p = get_column(line, i, '\0', nbuf, sizeof nbuf); 81138032Speter if (p == NULL) 81238032Speter break; 81338032Speter if (*p == '\0') 81438032Speter continue; 81538032Speter if (cbuf[0] == '\0' || 81638032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 81738032Speter { 81838032Speter snprintf(cbuf, cbuflen, "%s", p); 81938032Speter } 82038032Speter if (strcasecmp(name, p) == 0) 82138032Speter found = TRUE; 82238032Speter } 82338032Speter if (found && strchr(cbuf, '.') == NULL) 82438032Speter { 82538032Speter /* try to add a domain on the end of the name */ 82638032Speter char *domain = macvalue('m', CurEnv); 82738032Speter 82838032Speter if (domain != NULL && 82964562Sgshapiro strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 83038032Speter { 83164562Sgshapiro p = &cbuf[i]; 83238032Speter *p++ = '.'; 83364562Sgshapiro (void) strlcpy(p, domain, cbuflen - i - 1); 83438032Speter } 83538032Speter } 83638032Speter return found; 83738032Speter} 83838032Speter/* 83938032Speter** NDBM modules 84038032Speter*/ 84138032Speter 84238032Speter#ifdef NDBM 84338032Speter 84438032Speter/* 84538032Speter** NDBM_MAP_OPEN -- DBM-style map open 84638032Speter*/ 84738032Speter 84838032Speterbool 84938032Speterndbm_map_open(map, mode) 85038032Speter MAP *map; 85138032Speter int mode; 85238032Speter{ 85338032Speter register DBM *dbm; 85464562Sgshapiro int save_errno; 85538032Speter int dfd; 85638032Speter int pfd; 85764562Sgshapiro long sff; 85838032Speter int ret; 85938032Speter int smode = S_IREAD; 86038032Speter char dirfile[MAXNAME + 1]; 86138032Speter char pagfile[MAXNAME + 1]; 86264562Sgshapiro struct stat st; 86338032Speter struct stat std, stp; 86438032Speter 86538032Speter if (tTd(38, 2)) 86664562Sgshapiro dprintf("ndbm_map_open(%s, %s, %d)\n", 86738032Speter map->map_mname, map->map_file, mode); 86838032Speter map->map_lockfd = -1; 86938032Speter mode &= O_ACCMODE; 87038032Speter 87138032Speter /* do initial file and directory checks */ 87238032Speter snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file); 87338032Speter snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file); 87438032Speter sff = SFF_ROOTOK|SFF_REGONLY; 87538032Speter if (mode == O_RDWR) 87638032Speter { 87738032Speter sff |= SFF_CREAT; 87864562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 87938032Speter sff |= SFF_NOSLINK; 88064562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 88138032Speter sff |= SFF_NOHLINK; 88238032Speter smode = S_IWRITE; 88338032Speter } 88438032Speter else 88538032Speter { 88664562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 88738032Speter sff |= SFF_NOWLINK; 88838032Speter } 88964562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 89038032Speter sff |= SFF_SAFEDIRPATH; 89138032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 89238032Speter sff, smode, &std); 89338032Speter if (ret == 0) 89438032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 89538032Speter sff, smode, &stp); 89664562Sgshapiro 89764562Sgshapiro# if !_FFR_REMOVE_AUTOREBUILD 89838032Speter if (ret == ENOENT && AutoRebuild && 89938032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && 90038032Speter (bitset(MF_IMPL_NDBM, map->map_mflags) || 90138032Speter bitset(MF_ALIAS, map->map_mflags)) && 90238032Speter mode == O_RDONLY) 90338032Speter { 90438032Speter bool impl = bitset(MF_IMPL_NDBM, map->map_mflags); 90538032Speter 90638032Speter /* may be able to rebuild */ 90738032Speter map->map_mflags &= ~MF_IMPL_NDBM; 90838032Speter if (!rebuildaliases(map, TRUE)) 90938032Speter return FALSE; 91038032Speter if (impl) 91138032Speter return impl_map_open(map, O_RDONLY); 91238032Speter else 91338032Speter return ndbm_map_open(map, O_RDONLY); 91438032Speter } 91564562Sgshapiro# endif /* !_FFR_REMOVE_AUTOREBUILD */ 91664562Sgshapiro 91738032Speter if (ret != 0) 91838032Speter { 91938032Speter char *prob = "unsafe"; 92038032Speter 92138032Speter /* cannot open this map */ 92238032Speter if (ret == ENOENT) 92338032Speter prob = "missing"; 92438032Speter if (tTd(38, 2)) 92564562Sgshapiro dprintf("\t%s map file: %d\n", prob, ret); 92638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 92738032Speter syserr("dbm map \"%s\": %s map file %s", 92838032Speter map->map_mname, prob, map->map_file); 92938032Speter return FALSE; 93038032Speter } 93138032Speter if (std.st_mode == ST_MODE_NOFILE) 93238032Speter mode |= O_CREAT|O_EXCL; 93338032Speter 93464562Sgshapiro# if LOCK_ON_OPEN 93538032Speter if (mode == O_RDONLY) 93638032Speter mode |= O_SHLOCK; 93738032Speter else 93838032Speter mode |= O_TRUNC|O_EXLOCK; 93964562Sgshapiro# else /* LOCK_ON_OPEN */ 94038032Speter if ((mode & O_ACCMODE) == O_RDWR) 94138032Speter { 94264562Sgshapiro# if NOFTRUNCATE 94338032Speter /* 94438032Speter ** Warning: race condition. Try to lock the file as 94538032Speter ** quickly as possible after opening it. 94638032Speter ** This may also have security problems on some systems, 94738032Speter ** but there isn't anything we can do about it. 94838032Speter */ 94938032Speter 95038032Speter mode |= O_TRUNC; 95164562Sgshapiro# else /* NOFTRUNCATE */ 95238032Speter /* 95338032Speter ** This ugly code opens the map without truncating it, 95438032Speter ** locks the file, then truncates it. Necessary to 95538032Speter ** avoid race conditions. 95638032Speter */ 95738032Speter 95838032Speter int dirfd; 95938032Speter int pagfd; 96064562Sgshapiro long sff = SFF_CREAT|SFF_OPENASROOT; 96138032Speter 96264562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 96338032Speter sff |= SFF_NOSLINK; 96464562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 96538032Speter sff |= SFF_NOHLINK; 96638032Speter 96738032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 96838032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 96938032Speter 97038032Speter if (dirfd < 0 || pagfd < 0) 97138032Speter { 97264562Sgshapiro save_errno = errno; 97338032Speter if (dirfd >= 0) 97438032Speter (void) close(dirfd); 97538032Speter if (pagfd >= 0) 97638032Speter (void) close(pagfd); 97738032Speter errno = save_errno; 97838032Speter syserr("ndbm_map_open: cannot create database %s", 97938032Speter map->map_file); 98038032Speter return FALSE; 98138032Speter } 98238032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 98338032Speter ftruncate(pagfd, (off_t) 0) < 0) 98438032Speter { 98564562Sgshapiro save_errno = errno; 98638032Speter (void) close(dirfd); 98738032Speter (void) close(pagfd); 98838032Speter errno = save_errno; 98938032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 99038032Speter map->map_file); 99138032Speter return FALSE; 99238032Speter } 99338032Speter 99438032Speter /* if new file, get "before" bits for later filechanged check */ 99538032Speter if (std.st_mode == ST_MODE_NOFILE && 99638032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 99738032Speter { 99864562Sgshapiro save_errno = errno; 99938032Speter (void) close(dirfd); 100038032Speter (void) close(pagfd); 100138032Speter errno = save_errno; 100238032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 100338032Speter map->map_file); 100438032Speter return FALSE; 100538032Speter } 100638032Speter 100738032Speter /* have to save the lock for the duration (bletch) */ 100838032Speter map->map_lockfd = dirfd; 100964562Sgshapiro (void) close(pagfd); 101038032Speter 101138032Speter /* twiddle bits for dbm_open */ 101238032Speter mode &= ~(O_CREAT|O_EXCL); 101364562Sgshapiro# endif /* NOFTRUNCATE */ 101438032Speter } 101564562Sgshapiro# endif /* LOCK_ON_OPEN */ 101638032Speter 101738032Speter /* open the database */ 101838032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 101938032Speter if (dbm == NULL) 102038032Speter { 102164562Sgshapiro save_errno = errno; 102238032Speter if (bitset(MF_ALIAS, map->map_mflags) && 102338032Speter aliaswait(map, ".pag", FALSE)) 102438032Speter return TRUE; 102564562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 102638032Speter if (map->map_lockfd >= 0) 102764562Sgshapiro (void) close(map->map_lockfd); 102864562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 102938032Speter errno = save_errno; 103038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 103138032Speter syserr("Cannot open DBM database %s", map->map_file); 103238032Speter return FALSE; 103338032Speter } 103438032Speter dfd = dbm_dirfno(dbm); 103538032Speter pfd = dbm_pagfno(dbm); 103638032Speter if (dfd == pfd) 103738032Speter { 103838032Speter /* heuristic: if files are linked, this is actually gdbm */ 103938032Speter dbm_close(dbm); 104064562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 104138032Speter if (map->map_lockfd >= 0) 104264562Sgshapiro (void) close(map->map_lockfd); 104364562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 104438032Speter errno = 0; 104538032Speter syserr("dbm map \"%s\": cannot support GDBM", 104638032Speter map->map_mname); 104738032Speter return FALSE; 104838032Speter } 104938032Speter 105038032Speter if (filechanged(dirfile, dfd, &std) || 105138032Speter filechanged(pagfile, pfd, &stp)) 105238032Speter { 105364562Sgshapiro save_errno = errno; 105438032Speter dbm_close(dbm); 105564562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 105638032Speter if (map->map_lockfd >= 0) 105764562Sgshapiro (void) close(map->map_lockfd); 105864562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 105938032Speter errno = save_errno; 106038032Speter syserr("ndbm_map_open(%s): file changed after open", 106138032Speter map->map_file); 106238032Speter return FALSE; 106338032Speter } 106438032Speter 106538032Speter map->map_db1 = (ARBPTR_T) dbm; 106664562Sgshapiro 106764562Sgshapiro /* 106864562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 106964562Sgshapiro ** as aliaswait() will call map_lookup() which requires 107064562Sgshapiro ** map_mtime to be set 107164562Sgshapiro */ 107264562Sgshapiro 107364562Sgshapiro if (fstat(dfd, &st) >= 0) 107464562Sgshapiro map->map_mtime = st.st_mtime; 107564562Sgshapiro 107638032Speter if (mode == O_RDONLY) 107738032Speter { 107864562Sgshapiro# if LOCK_ON_OPEN 107938032Speter if (dfd >= 0) 108038032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 108138032Speter if (pfd >= 0) 108238032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 108364562Sgshapiro# endif /* LOCK_ON_OPEN */ 108438032Speter if (bitset(MF_ALIAS, map->map_mflags) && 108538032Speter !aliaswait(map, ".pag", TRUE)) 108638032Speter return FALSE; 108738032Speter } 108838032Speter else 108938032Speter { 109038032Speter map->map_mflags |= MF_LOCKED; 109142575Speter if (geteuid() == 0 && TrustedUid != 0) 109238032Speter { 109364562Sgshapiro# if HASFCHOWN 109442575Speter if (fchown(dfd, TrustedUid, -1) < 0 || 109542575Speter fchown(pfd, TrustedUid, -1) < 0) 109638032Speter { 109738032Speter int err = errno; 109838032Speter 109938032Speter sm_syslog(LOG_ALERT, NOQID, 110038032Speter "ownership change on %s failed: %s", 110138032Speter map->map_file, errstring(err)); 110238032Speter message("050 ownership change on %s failed: %s", 110338032Speter map->map_file, errstring(err)); 110438032Speter } 110564562Sgshapiro# endif /* HASFCHOWN */ 110638032Speter } 110738032Speter } 110838032Speter return TRUE; 110938032Speter} 111038032Speter 111138032Speter 111238032Speter/* 111338032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 111438032Speter*/ 111538032Speter 111638032Speterchar * 111738032Speterndbm_map_lookup(map, name, av, statp) 111838032Speter MAP *map; 111938032Speter char *name; 112038032Speter char **av; 112138032Speter int *statp; 112238032Speter{ 112338032Speter datum key, val; 112438032Speter int fd; 112538032Speter char keybuf[MAXNAME + 1]; 112638032Speter struct stat stbuf; 112738032Speter 112838032Speter if (tTd(38, 20)) 112964562Sgshapiro dprintf("ndbm_map_lookup(%s, %s)\n", 113038032Speter map->map_mname, name); 113138032Speter 113238032Speter key.dptr = name; 113338032Speter key.dsize = strlen(name); 113438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 113538032Speter { 113638032Speter if (key.dsize > sizeof keybuf - 1) 113738032Speter key.dsize = sizeof keybuf - 1; 113864562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 113938032Speter keybuf[key.dsize] = '\0'; 114038032Speter makelower(keybuf); 114138032Speter key.dptr = keybuf; 114238032Speter } 114338032Speterlockdbm: 114438032Speter fd = dbm_dirfno((DBM *) map->map_db1); 114538032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 114638032Speter (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 114738032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 114838032Speter { 114938032Speter /* Reopen the database to sync the cache */ 115038032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 115138032Speter : O_RDONLY; 115238032Speter 115364562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 115464562Sgshapiro (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 115538032Speter map->map_class->map_close(map); 115638032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 115738032Speter if (map->map_class->map_open(map, omode)) 115838032Speter { 115938032Speter map->map_mflags |= MF_OPEN; 116042575Speter map->map_pid = getpid(); 116138032Speter if ((omode && O_ACCMODE) == O_RDWR) 116238032Speter map->map_mflags |= MF_WRITABLE; 116338032Speter goto lockdbm; 116438032Speter } 116538032Speter else 116638032Speter { 116738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 116838032Speter { 116938032Speter extern MAPCLASS BogusMapClass; 117038032Speter 117138032Speter *statp = EX_TEMPFAIL; 117238032Speter map->map_class = &BogusMapClass; 117338032Speter map->map_mflags |= MF_OPEN; 117442575Speter map->map_pid = getpid(); 117538032Speter syserr("Cannot reopen NDBM database %s", 117638032Speter map->map_file); 117738032Speter } 117838032Speter return NULL; 117938032Speter } 118038032Speter } 118138032Speter val.dptr = NULL; 118238032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 118338032Speter { 118438032Speter val = dbm_fetch((DBM *) map->map_db1, key); 118538032Speter if (val.dptr != NULL) 118638032Speter map->map_mflags &= ~MF_TRY1NULL; 118738032Speter } 118838032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 118938032Speter { 119038032Speter key.dsize++; 119138032Speter val = dbm_fetch((DBM *) map->map_db1, key); 119238032Speter if (val.dptr != NULL) 119338032Speter map->map_mflags &= ~MF_TRY0NULL; 119438032Speter } 119538032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 119638032Speter (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 119738032Speter if (val.dptr == NULL) 119838032Speter return NULL; 119938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 120038032Speter return map_rewrite(map, name, strlen(name), NULL); 120138032Speter else 120238032Speter return map_rewrite(map, val.dptr, val.dsize, av); 120338032Speter} 120438032Speter 120538032Speter 120638032Speter/* 120738032Speter** NDBM_MAP_STORE -- store a datum in the database 120838032Speter*/ 120938032Speter 121038032Spetervoid 121138032Speterndbm_map_store(map, lhs, rhs) 121238032Speter register MAP *map; 121338032Speter char *lhs; 121438032Speter char *rhs; 121538032Speter{ 121638032Speter datum key; 121738032Speter datum data; 121864562Sgshapiro int status; 121938032Speter char keybuf[MAXNAME + 1]; 122038032Speter 122138032Speter if (tTd(38, 12)) 122264562Sgshapiro dprintf("ndbm_map_store(%s, %s, %s)\n", 122338032Speter map->map_mname, lhs, rhs); 122438032Speter 122538032Speter key.dsize = strlen(lhs); 122638032Speter key.dptr = lhs; 122738032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 122838032Speter { 122938032Speter if (key.dsize > sizeof keybuf - 1) 123038032Speter key.dsize = sizeof keybuf - 1; 123164562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 123238032Speter keybuf[key.dsize] = '\0'; 123338032Speter makelower(keybuf); 123438032Speter key.dptr = keybuf; 123538032Speter } 123638032Speter 123738032Speter data.dsize = strlen(rhs); 123838032Speter data.dptr = rhs; 123938032Speter 124038032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 124138032Speter { 124238032Speter key.dsize++; 124338032Speter data.dsize++; 124438032Speter } 124538032Speter 124664562Sgshapiro status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 124764562Sgshapiro if (status > 0) 124838032Speter { 124938032Speter if (!bitset(MF_APPEND, map->map_mflags)) 125038032Speter message("050 Warning: duplicate alias name %s", lhs); 125138032Speter else 125238032Speter { 125338032Speter static char *buf = NULL; 125438032Speter static int bufsiz = 0; 125538032Speter auto int xstat; 125638032Speter datum old; 125738032Speter 125838032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 125938032Speter (char **)NULL, &xstat); 126038032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 126138032Speter { 126238032Speter old.dsize = strlen(old.dptr); 126338032Speter if (data.dsize + old.dsize + 2 > bufsiz) 126438032Speter { 126538032Speter if (buf != NULL) 126638032Speter (void) free(buf); 126738032Speter bufsiz = data.dsize + old.dsize + 2; 126838032Speter buf = xalloc(bufsiz); 126938032Speter } 127038032Speter snprintf(buf, bufsiz, "%s,%s", 127138032Speter data.dptr, old.dptr); 127238032Speter data.dsize = data.dsize + old.dsize + 1; 127338032Speter data.dptr = buf; 127438032Speter if (tTd(38, 9)) 127564562Sgshapiro dprintf("ndbm_map_store append=%s\n", 127664562Sgshapiro data.dptr); 127738032Speter } 127838032Speter } 127964562Sgshapiro status = dbm_store((DBM *) map->map_db1, 128064562Sgshapiro key, data, DBM_REPLACE); 128138032Speter } 128264562Sgshapiro if (status != 0) 128364562Sgshapiro syserr("readaliases: dbm put (%s): %d", lhs, status); 128438032Speter} 128538032Speter 128638032Speter 128738032Speter/* 128838032Speter** NDBM_MAP_CLOSE -- close the database 128938032Speter*/ 129038032Speter 129138032Spetervoid 129238032Speterndbm_map_close(map) 129338032Speter register MAP *map; 129438032Speter{ 129538032Speter if (tTd(38, 9)) 129664562Sgshapiro dprintf("ndbm_map_close(%s, %s, %lx)\n", 129738032Speter map->map_mname, map->map_file, map->map_mflags); 129838032Speter 129938032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 130038032Speter { 130164562Sgshapiro# ifdef NDBM_YP_COMPAT 130238032Speter bool inclnull; 130342575Speter char buf[MAXHOSTNAMELEN]; 130438032Speter 130538032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 130638032Speter map->map_mflags &= ~MF_INCLNULL; 130738032Speter 130838032Speter if (strstr(map->map_file, "/yp/") != NULL) 130938032Speter { 131038032Speter long save_mflags = map->map_mflags; 131138032Speter 131238032Speter map->map_mflags |= MF_NOFOLDCASE; 131338032Speter 131438032Speter (void) snprintf(buf, sizeof buf, "%010ld", curtime()); 131538032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 131638032Speter 131738032Speter (void) gethostname(buf, sizeof buf); 131838032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 131938032Speter 132038032Speter map->map_mflags = save_mflags; 132138032Speter } 132238032Speter 132338032Speter if (inclnull) 132438032Speter map->map_mflags |= MF_INCLNULL; 132564562Sgshapiro# endif /* NDBM_YP_COMPAT */ 132638032Speter 132738032Speter /* write out the distinguished alias */ 132838032Speter ndbm_map_store(map, "@", "@"); 132938032Speter } 133038032Speter dbm_close((DBM *) map->map_db1); 133138032Speter 133238032Speter /* release lock (if needed) */ 133364562Sgshapiro# if !LOCK_ON_OPEN 133438032Speter if (map->map_lockfd >= 0) 133538032Speter (void) close(map->map_lockfd); 133664562Sgshapiro# endif /* !LOCK_ON_OPEN */ 133738032Speter} 133838032Speter 133964562Sgshapiro#endif /* NDBM */ 134038032Speter/* 134138032Speter** NEWDB (Hash and BTree) Modules 134238032Speter*/ 134338032Speter 134438032Speter#ifdef NEWDB 134538032Speter 134638032Speter/* 134738032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 134838032Speter** 134938032Speter** These do rather bizarre locking. If you can lock on open, 135038032Speter** do that to avoid the condition of opening a database that 135138032Speter** is being rebuilt. If you don't, we'll try to fake it, but 135238032Speter** there will be a race condition. If opening for read-only, 135338032Speter** we immediately release the lock to avoid freezing things up. 135438032Speter** We really ought to hold the lock, but guarantee that we won't 135538032Speter** be pokey about it. That's hard to do. 135638032Speter*/ 135738032Speter 135838032Speter/* these should be K line arguments */ 135964562Sgshapiro# if DB_VERSION_MAJOR < 2 136064562Sgshapiro# define db_cachesize cachesize 136164562Sgshapiro# define h_nelem nelem 136264562Sgshapiro# ifndef DB_CACHE_SIZE 136364562Sgshapiro# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 136464562Sgshapiro# endif /* ! DB_CACHE_SIZE */ 136564562Sgshapiro# ifndef DB_HASH_NELEM 136664562Sgshapiro# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 136764562Sgshapiro# endif /* ! DB_HASH_NELEM */ 136864562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 136938032Speter 137038032Speterbool 137138032Speterbt_map_open(map, mode) 137238032Speter MAP *map; 137338032Speter int mode; 137438032Speter{ 137564562Sgshapiro# if DB_VERSION_MAJOR < 2 137638032Speter BTREEINFO btinfo; 137764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 137864562Sgshapiro# if DB_VERSION_MAJOR == 2 137938032Speter DB_INFO btinfo; 138064562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 138164562Sgshapiro# if DB_VERSION_MAJOR > 2 138264562Sgshapiro void *btinfo = NULL; 138364562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 138438032Speter 138538032Speter if (tTd(38, 2)) 138664562Sgshapiro dprintf("bt_map_open(%s, %s, %d)\n", 138738032Speter map->map_mname, map->map_file, mode); 138838032Speter 138964562Sgshapiro# if DB_VERSION_MAJOR < 3 139064562Sgshapiro memset(&btinfo, '\0', sizeof btinfo); 139164562Sgshapiro# ifdef DB_CACHE_SIZE 139238032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 139364562Sgshapiro# endif /* DB_CACHE_SIZE */ 139464562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 139564562Sgshapiro 139638032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 139738032Speter} 139838032Speter 139938032Speterbool 140038032Speterhash_map_open(map, mode) 140138032Speter MAP *map; 140238032Speter int mode; 140338032Speter{ 140464562Sgshapiro# if DB_VERSION_MAJOR < 2 140538032Speter HASHINFO hinfo; 140664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 140764562Sgshapiro# if DB_VERSION_MAJOR == 2 140838032Speter DB_INFO hinfo; 140964562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 141064562Sgshapiro# if DB_VERSION_MAJOR > 2 141164562Sgshapiro void *hinfo = NULL; 141264562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 141338032Speter 141438032Speter if (tTd(38, 2)) 141564562Sgshapiro dprintf("hash_map_open(%s, %s, %d)\n", 141638032Speter map->map_mname, map->map_file, mode); 141738032Speter 141864562Sgshapiro# if DB_VERSION_MAJOR < 3 141964562Sgshapiro memset(&hinfo, '\0', sizeof hinfo); 142064562Sgshapiro# ifdef DB_HASH_NELEM 142138032Speter hinfo.h_nelem = DB_HASH_NELEM; 142264562Sgshapiro# endif /* DB_HASH_NELEM */ 142364562Sgshapiro# ifdef DB_CACHE_SIZE 142438032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 142564562Sgshapiro# endif /* DB_CACHE_SIZE */ 142664562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 142764562Sgshapiro 142838032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 142938032Speter} 143038032Speter 143164562Sgshapirostatic bool 143238032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 143338032Speter MAP *map; 143438032Speter int mode; 143538032Speter char *mapclassname; 143638032Speter DBTYPE dbtype; 143764562Sgshapiro# if DB_VERSION_MAJOR < 2 143838032Speter const void *openinfo; 143964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 144064562Sgshapiro# if DB_VERSION_MAJOR == 2 144138032Speter DB_INFO *openinfo; 144264562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 144364562Sgshapiro# if DB_VERSION_MAJOR > 2 144464562Sgshapiro void **openinfo; 144564562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 144638032Speter{ 144738032Speter DB *db = NULL; 144838032Speter int i; 144938032Speter int omode; 145038032Speter int smode = S_IREAD; 145138032Speter int fd; 145264562Sgshapiro long sff; 145364562Sgshapiro int save_errno; 145438032Speter struct stat st; 145538032Speter char buf[MAXNAME + 1]; 145638032Speter 145738032Speter /* do initial file and directory checks */ 145864562Sgshapiro (void) strlcpy(buf, map->map_file, sizeof buf - 3); 145938032Speter i = strlen(buf); 146038032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 146164562Sgshapiro (void) strlcat(buf, ".db", sizeof buf); 146238032Speter 146338032Speter mode &= O_ACCMODE; 146438032Speter omode = mode; 146538032Speter 146638032Speter sff = SFF_ROOTOK|SFF_REGONLY; 146738032Speter if (mode == O_RDWR) 146838032Speter { 146938032Speter sff |= SFF_CREAT; 147064562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 147138032Speter sff |= SFF_NOSLINK; 147264562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 147338032Speter sff |= SFF_NOHLINK; 147438032Speter smode = S_IWRITE; 147538032Speter } 147638032Speter else 147738032Speter { 147864562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 147938032Speter sff |= SFF_NOWLINK; 148038032Speter } 148164562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 148238032Speter sff |= SFF_SAFEDIRPATH; 148338032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 148464562Sgshapiro 148564562Sgshapiro# if !_FFR_REMOVE_AUTOREBUILD 148638032Speter if (i == ENOENT && AutoRebuild && 148738032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && 148838032Speter (bitset(MF_IMPL_HASH, map->map_mflags) || 148938032Speter bitset(MF_ALIAS, map->map_mflags)) && 149038032Speter mode == O_RDONLY) 149138032Speter { 149238032Speter bool impl = bitset(MF_IMPL_HASH, map->map_mflags); 149338032Speter 149438032Speter /* may be able to rebuild */ 149538032Speter map->map_mflags &= ~MF_IMPL_HASH; 149638032Speter if (!rebuildaliases(map, TRUE)) 149738032Speter return FALSE; 149838032Speter if (impl) 149938032Speter return impl_map_open(map, O_RDONLY); 150038032Speter else 150138032Speter return db_map_open(map, O_RDONLY, mapclassname, 150238032Speter dbtype, openinfo); 150338032Speter } 150464562Sgshapiro# endif /* !_FFR_REMOVE_AUTOREBUILD */ 150538032Speter 150638032Speter if (i != 0) 150738032Speter { 150838032Speter char *prob = "unsafe"; 150938032Speter 151038032Speter /* cannot open this map */ 151138032Speter if (i == ENOENT) 151238032Speter prob = "missing"; 151338032Speter if (tTd(38, 2)) 151464562Sgshapiro dprintf("\t%s map file: %s\n", prob, errstring(i)); 151538032Speter errno = i; 151638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 151738032Speter syserr("%s map \"%s\": %s map file %s", 151838032Speter mapclassname, map->map_mname, prob, buf); 151938032Speter return FALSE; 152038032Speter } 152138032Speter if (st.st_mode == ST_MODE_NOFILE) 152238032Speter omode |= O_CREAT|O_EXCL; 152338032Speter 152438032Speter map->map_lockfd = -1; 152538032Speter 152664562Sgshapiro# if LOCK_ON_OPEN 152738032Speter if (mode == O_RDWR) 152838032Speter omode |= O_TRUNC|O_EXLOCK; 152938032Speter else 153038032Speter omode |= O_SHLOCK; 153164562Sgshapiro# else /* LOCK_ON_OPEN */ 153238032Speter /* 153338032Speter ** Pre-lock the file to avoid race conditions. In particular, 153438032Speter ** since dbopen returns NULL if the file is zero length, we 153538032Speter ** must have a locked instance around the dbopen. 153638032Speter */ 153738032Speter 153838032Speter fd = open(buf, omode, DBMMODE); 153938032Speter if (fd < 0) 154038032Speter { 154138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 154238032Speter syserr("db_map_open: cannot pre-open database %s", buf); 154338032Speter return FALSE; 154438032Speter } 154538032Speter 154638032Speter /* make sure no baddies slipped in just before the open... */ 154738032Speter if (filechanged(buf, fd, &st)) 154838032Speter { 154964562Sgshapiro save_errno = errno; 155038032Speter (void) close(fd); 155138032Speter errno = save_errno; 155238032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 155338032Speter return FALSE; 155438032Speter } 155538032Speter 155638032Speter /* if new file, get the "before" bits for later filechanged check */ 155738032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 155838032Speter { 155964562Sgshapiro save_errno = errno; 156038032Speter (void) close(fd); 156138032Speter errno = save_errno; 156238032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 156338032Speter buf); 156438032Speter return FALSE; 156538032Speter } 156638032Speter 156738032Speter /* actually lock the pre-opened file */ 156838032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 156938032Speter syserr("db_map_open: cannot lock %s", buf); 157038032Speter 157138032Speter /* set up mode bits for dbopen */ 157238032Speter if (mode == O_RDWR) 157338032Speter omode |= O_TRUNC; 157438032Speter omode &= ~(O_EXCL|O_CREAT); 157564562Sgshapiro# endif /* LOCK_ON_OPEN */ 157638032Speter 157764562Sgshapiro# if DB_VERSION_MAJOR < 2 157838032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 157964562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 158038032Speter { 158138032Speter int flags = 0; 158264562Sgshapiro# if DB_VERSION_MAJOR > 2 158364562Sgshapiro int ret; 158464562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 158538032Speter 158638032Speter if (mode == O_RDONLY) 158738032Speter flags |= DB_RDONLY; 158838032Speter if (bitset(O_CREAT, omode)) 158938032Speter flags |= DB_CREATE; 159038032Speter if (bitset(O_TRUNC, omode)) 159138032Speter flags |= DB_TRUNCATE; 159238032Speter 159364562Sgshapiro# if !HASFLOCK && defined(DB_FCNTL_LOCKING) 159464562Sgshapiro flags |= DB_FCNTL_LOCKING; 159564562Sgshapiro# endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ 159664562Sgshapiro 159764562Sgshapiro# if DB_VERSION_MAJOR > 2 159864562Sgshapiro ret = db_create(&db, NULL, 0); 159964562Sgshapiro# ifdef DB_CACHE_SIZE 160064562Sgshapiro if (ret == 0 && db != NULL) 160164562Sgshapiro { 160264562Sgshapiro ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 160364562Sgshapiro if (ret != 0) 160464562Sgshapiro { 160564562Sgshapiro (void) db->close(db, 0); 160664562Sgshapiro db = NULL; 160764562Sgshapiro } 160864562Sgshapiro } 160964562Sgshapiro# endif /* DB_CACHE_SIZE */ 161064562Sgshapiro# ifdef DB_HASH_NELEM 161164562Sgshapiro if (dbtype == DB_HASH && ret == 0 && db != NULL) 161264562Sgshapiro { 161364562Sgshapiro ret = db->set_h_nelem(db, DB_HASH_NELEM); 161464562Sgshapiro if (ret != 0) 161564562Sgshapiro { 161664562Sgshapiro (void) db->close(db, 0); 161764562Sgshapiro db = NULL; 161864562Sgshapiro } 161964562Sgshapiro } 162064562Sgshapiro# endif /* DB_HASH_NELEM */ 162164562Sgshapiro if (ret == 0 && db != NULL) 162264562Sgshapiro { 162364562Sgshapiro ret = db->open(db, buf, NULL, dbtype, flags, DBMMODE); 162464562Sgshapiro if (ret != 0) 162564562Sgshapiro { 162664562Sgshapiro (void) db->close(db, 0); 162764562Sgshapiro db = NULL; 162864562Sgshapiro } 162964562Sgshapiro } 163064562Sgshapiro errno = ret; 163164562Sgshapiro# else /* DB_VERSION_MAJOR > 2 */ 163238032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 163338032Speter NULL, openinfo, &db); 163464562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 163538032Speter } 163664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 163764562Sgshapiro save_errno = errno; 163838032Speter 163964562Sgshapiro# if !LOCK_ON_OPEN 164038032Speter if (mode == O_RDWR) 164138032Speter map->map_lockfd = fd; 164238032Speter else 164338032Speter (void) close(fd); 164464562Sgshapiro# endif /* !LOCK_ON_OPEN */ 164538032Speter 164638032Speter if (db == NULL) 164738032Speter { 164838032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 164938032Speter aliaswait(map, ".db", FALSE)) 165038032Speter return TRUE; 165164562Sgshapiro# if !LOCK_ON_OPEN 165238032Speter if (map->map_lockfd >= 0) 165338032Speter (void) close(map->map_lockfd); 165464562Sgshapiro# endif /* !LOCK_ON_OPEN */ 165564562Sgshapiro errno = save_errno; 165638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 165738032Speter syserr("Cannot open %s database %s", 165838032Speter mapclassname, buf); 165938032Speter return FALSE; 166038032Speter } 166138032Speter 166264562Sgshapiro# if DB_VERSION_MAJOR < 2 166338032Speter fd = db->fd(db); 166464562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 166538032Speter fd = -1; 166638032Speter errno = db->fd(db, &fd); 166764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 166838032Speter if (filechanged(buf, fd, &st)) 166938032Speter { 167064562Sgshapiro save_errno = errno; 167164562Sgshapiro# if DB_VERSION_MAJOR < 2 167264562Sgshapiro (void) db->close(db); 167364562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 167438032Speter errno = db->close(db, 0); 167564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 167664562Sgshapiro# if !LOCK_ON_OPEN 167738032Speter if (map->map_lockfd >= 0) 167864562Sgshapiro (void) close(map->map_lockfd); 167964562Sgshapiro# endif /* !LOCK_ON_OPEN */ 168038032Speter errno = save_errno; 168138032Speter syserr("db_map_open(%s): file changed after open", buf); 168238032Speter return FALSE; 168338032Speter } 168438032Speter 168538032Speter if (mode == O_RDWR) 168638032Speter map->map_mflags |= MF_LOCKED; 168764562Sgshapiro# if LOCK_ON_OPEN 168838032Speter if (fd >= 0 && mode == O_RDONLY) 168938032Speter { 169038032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 169138032Speter } 169264562Sgshapiro# endif /* LOCK_ON_OPEN */ 169338032Speter 169438032Speter /* try to make sure that at least the database header is on disk */ 169538032Speter if (mode == O_RDWR) 169638032Speter { 169738032Speter (void) db->sync(db, 0); 169842575Speter if (geteuid() == 0 && TrustedUid != 0) 169938032Speter { 170064562Sgshapiro# if HASFCHOWN 170142575Speter if (fchown(fd, TrustedUid, -1) < 0) 170238032Speter { 170338032Speter int err = errno; 170438032Speter 170538032Speter sm_syslog(LOG_ALERT, NOQID, 170638032Speter "ownership change on %s failed: %s", 170738032Speter buf, errstring(err)); 170838032Speter message("050 ownership change on %s failed: %s", 170938032Speter buf, errstring(err)); 171038032Speter } 171164562Sgshapiro# endif /* HASFCHOWN */ 171238032Speter } 171338032Speter } 171438032Speter 171564562Sgshapiro map->map_db2 = (ARBPTR_T) db; 171664562Sgshapiro 171764562Sgshapiro /* 171864562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 171964562Sgshapiro ** as aliaswait() will call map_lookup() which requires 172064562Sgshapiro ** map_mtime to be set 172164562Sgshapiro */ 172264562Sgshapiro 172338032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 172438032Speter map->map_mtime = st.st_mtime; 172538032Speter 172638032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 172738032Speter !aliaswait(map, ".db", TRUE)) 172838032Speter return FALSE; 172938032Speter return TRUE; 173038032Speter} 173138032Speter 173238032Speter 173338032Speter/* 173438032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 173538032Speter*/ 173638032Speter 173738032Speterchar * 173838032Speterdb_map_lookup(map, name, av, statp) 173938032Speter MAP *map; 174038032Speter char *name; 174138032Speter char **av; 174238032Speter int *statp; 174338032Speter{ 174438032Speter DBT key, val; 174538032Speter register DB *db = (DB *) map->map_db2; 174638032Speter int i; 174738032Speter int st; 174864562Sgshapiro int save_errno; 174938032Speter int fd; 175038032Speter struct stat stbuf; 175138032Speter char keybuf[MAXNAME + 1]; 175238032Speter char buf[MAXNAME + 1]; 175338032Speter 175464562Sgshapiro memset(&key, '\0', sizeof key); 175564562Sgshapiro memset(&val, '\0', sizeof val); 175638032Speter 175738032Speter if (tTd(38, 20)) 175864562Sgshapiro dprintf("db_map_lookup(%s, %s)\n", 175938032Speter map->map_mname, name); 176038032Speter 176138032Speter i = strlen(map->map_file); 176238032Speter if (i > MAXNAME) 176338032Speter i = MAXNAME; 176464562Sgshapiro (void) strlcpy(buf, map->map_file, i + 1); 176538032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 176638032Speter buf[i - 3] = '\0'; 176738032Speter 176838032Speter key.size = strlen(name); 176938032Speter if (key.size > sizeof keybuf - 1) 177038032Speter key.size = sizeof keybuf - 1; 177138032Speter key.data = keybuf; 177264562Sgshapiro memmove(keybuf, name, key.size); 177338032Speter keybuf[key.size] = '\0'; 177438032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 177538032Speter makelower(keybuf); 177638032Speter lockdb: 177764562Sgshapiro# if DB_VERSION_MAJOR < 2 177838032Speter fd = db->fd(db); 177964562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 178038032Speter fd = -1; 178138032Speter errno = db->fd(db, &fd); 178264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 178338032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 178438032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 178538032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 178638032Speter { 178738032Speter /* Reopen the database to sync the cache */ 178838032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 178938032Speter : O_RDONLY; 179038032Speter 179164562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 179264562Sgshapiro (void) lockfile(fd, buf, ".db", LOCK_UN); 179338032Speter map->map_class->map_close(map); 179438032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 179538032Speter if (map->map_class->map_open(map, omode)) 179638032Speter { 179738032Speter map->map_mflags |= MF_OPEN; 179842575Speter map->map_pid = getpid(); 179938032Speter if ((omode && O_ACCMODE) == O_RDWR) 180038032Speter map->map_mflags |= MF_WRITABLE; 180138032Speter db = (DB *) map->map_db2; 180238032Speter goto lockdb; 180338032Speter } 180438032Speter else 180538032Speter { 180638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 180738032Speter { 180838032Speter extern MAPCLASS BogusMapClass; 180938032Speter 181038032Speter *statp = EX_TEMPFAIL; 181138032Speter map->map_class = &BogusMapClass; 181238032Speter map->map_mflags |= MF_OPEN; 181342575Speter map->map_pid = getpid(); 181438032Speter syserr("Cannot reopen DB database %s", 181538032Speter map->map_file); 181638032Speter } 181738032Speter return NULL; 181838032Speter } 181938032Speter } 182038032Speter 182138032Speter st = 1; 182238032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 182338032Speter { 182464562Sgshapiro# if DB_VERSION_MAJOR < 2 182538032Speter st = db->get(db, &key, &val, 0); 182664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 182738032Speter errno = db->get(db, NULL, &key, &val, 0); 182838032Speter switch (errno) 182938032Speter { 183038032Speter case DB_NOTFOUND: 183138032Speter case DB_KEYEMPTY: 183238032Speter st = 1; 183338032Speter break; 183438032Speter 183538032Speter case 0: 183638032Speter st = 0; 183738032Speter break; 183838032Speter 183938032Speter default: 184038032Speter st = -1; 184138032Speter break; 184238032Speter } 184364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 184438032Speter if (st == 0) 184538032Speter map->map_mflags &= ~MF_TRY1NULL; 184638032Speter } 184738032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 184838032Speter { 184938032Speter key.size++; 185064562Sgshapiro# if DB_VERSION_MAJOR < 2 185138032Speter st = db->get(db, &key, &val, 0); 185264562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 185338032Speter errno = db->get(db, NULL, &key, &val, 0); 185438032Speter switch (errno) 185538032Speter { 185638032Speter case DB_NOTFOUND: 185738032Speter case DB_KEYEMPTY: 185838032Speter st = 1; 185938032Speter break; 186038032Speter 186138032Speter case 0: 186238032Speter st = 0; 186338032Speter break; 186438032Speter 186538032Speter default: 186638032Speter st = -1; 186738032Speter break; 186838032Speter } 186964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 187038032Speter if (st == 0) 187138032Speter map->map_mflags &= ~MF_TRY0NULL; 187238032Speter } 187364562Sgshapiro save_errno = errno; 187438032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 187538032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 187638032Speter if (st != 0) 187738032Speter { 187864562Sgshapiro errno = save_errno; 187938032Speter if (st < 0) 188038032Speter syserr("db_map_lookup: get (%s)", name); 188138032Speter return NULL; 188238032Speter } 188338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 188438032Speter return map_rewrite(map, name, strlen(name), NULL); 188538032Speter else 188638032Speter return map_rewrite(map, val.data, val.size, av); 188738032Speter} 188838032Speter 188938032Speter 189038032Speter/* 189138032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 189238032Speter*/ 189338032Speter 189438032Spetervoid 189538032Speterdb_map_store(map, lhs, rhs) 189638032Speter register MAP *map; 189738032Speter char *lhs; 189838032Speter char *rhs; 189938032Speter{ 190064562Sgshapiro int status; 190138032Speter DBT key; 190238032Speter DBT data; 190338032Speter register DB *db = map->map_db2; 190438032Speter char keybuf[MAXNAME + 1]; 190538032Speter 190664562Sgshapiro memset(&key, '\0', sizeof key); 190764562Sgshapiro memset(&data, '\0', sizeof data); 190838032Speter 190938032Speter if (tTd(38, 12)) 191064562Sgshapiro dprintf("db_map_store(%s, %s, %s)\n", 191138032Speter map->map_mname, lhs, rhs); 191238032Speter 191338032Speter key.size = strlen(lhs); 191438032Speter key.data = lhs; 191538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 191638032Speter { 191738032Speter if (key.size > sizeof keybuf - 1) 191838032Speter key.size = sizeof keybuf - 1; 191964562Sgshapiro memmove(keybuf, key.data, key.size); 192038032Speter keybuf[key.size] = '\0'; 192138032Speter makelower(keybuf); 192238032Speter key.data = keybuf; 192338032Speter } 192438032Speter 192538032Speter data.size = strlen(rhs); 192638032Speter data.data = rhs; 192738032Speter 192838032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 192938032Speter { 193038032Speter key.size++; 193138032Speter data.size++; 193238032Speter } 193338032Speter 193464562Sgshapiro# if DB_VERSION_MAJOR < 2 193564562Sgshapiro status = db->put(db, &key, &data, R_NOOVERWRITE); 193664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 193738032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 193838032Speter switch (errno) 193938032Speter { 194038032Speter case DB_KEYEXIST: 194164562Sgshapiro status = 1; 194238032Speter break; 194338032Speter 194438032Speter case 0: 194564562Sgshapiro status = 0; 194638032Speter break; 194738032Speter 194838032Speter default: 194964562Sgshapiro status = -1; 195038032Speter break; 195138032Speter } 195264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 195364562Sgshapiro if (status > 0) 195438032Speter { 195538032Speter if (!bitset(MF_APPEND, map->map_mflags)) 195638032Speter message("050 Warning: duplicate alias name %s", lhs); 195738032Speter else 195838032Speter { 195938032Speter static char *buf = NULL; 196038032Speter static int bufsiz = 0; 196138032Speter DBT old; 196238032Speter 196364562Sgshapiro memset(&old, '\0', sizeof old); 196438032Speter 196564562Sgshapiro old.data = db_map_lookup(map, key.data, 196664562Sgshapiro (char **)NULL, &status); 196738032Speter if (old.data != NULL) 196838032Speter { 196938032Speter old.size = strlen(old.data); 197064562Sgshapiro if (data.size + old.size + 2 > (size_t)bufsiz) 197138032Speter { 197238032Speter if (buf != NULL) 197338032Speter (void) free(buf); 197438032Speter bufsiz = data.size + old.size + 2; 197538032Speter buf = xalloc(bufsiz); 197638032Speter } 197738032Speter snprintf(buf, bufsiz, "%s,%s", 197838032Speter (char *) data.data, (char *) old.data); 197938032Speter data.size = data.size + old.size + 1; 198038032Speter data.data = buf; 198138032Speter if (tTd(38, 9)) 198264562Sgshapiro dprintf("db_map_store append=%s\n", 198364562Sgshapiro (char *) data.data); 198438032Speter } 198538032Speter } 198664562Sgshapiro# if DB_VERSION_MAJOR < 2 198764562Sgshapiro status = db->put(db, &key, &data, 0); 198864562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 198964562Sgshapiro status = errno = db->put(db, NULL, &key, &data, 0); 199064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 199138032Speter } 199264562Sgshapiro if (status != 0) 199338032Speter syserr("readaliases: db put (%s)", lhs); 199438032Speter} 199538032Speter 199638032Speter 199738032Speter/* 199838032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 199938032Speter*/ 200038032Speter 200138032Spetervoid 200238032Speterdb_map_close(map) 200338032Speter MAP *map; 200438032Speter{ 200538032Speter register DB *db = map->map_db2; 200638032Speter 200738032Speter if (tTd(38, 9)) 200864562Sgshapiro dprintf("db_map_close(%s, %s, %lx)\n", 200938032Speter map->map_mname, map->map_file, map->map_mflags); 201038032Speter 201138032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 201238032Speter { 201338032Speter /* write out the distinguished alias */ 201438032Speter db_map_store(map, "@", "@"); 201538032Speter } 201638032Speter 201738032Speter (void) db->sync(db, 0); 201838032Speter 201964562Sgshapiro# if !LOCK_ON_OPEN 202038032Speter if (map->map_lockfd >= 0) 202138032Speter (void) close(map->map_lockfd); 202264562Sgshapiro# endif /* !LOCK_ON_OPEN */ 202338032Speter 202464562Sgshapiro# if DB_VERSION_MAJOR < 2 202538032Speter if (db->close(db) != 0) 202664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 202742575Speter /* 202842575Speter ** Berkeley DB can use internal shared memory 202942575Speter ** locking for its memory pool. Closing a map 203042575Speter ** opened by another process will interfere 203142575Speter ** with the shared memory and locks of the parent 203242575Speter ** process leaving things in a bad state. 203343730Speter */ 203443730Speter 203543730Speter /* 203642575Speter ** If this map was not opened by the current 203743730Speter ** process, do not close the map but recover 203842575Speter ** the file descriptor. 203942575Speter */ 204042575Speter if (map->map_pid != getpid()) 204142575Speter { 204242575Speter int fd = -1; 204342575Speter 204442575Speter errno = db->fd(db, &fd); 204542575Speter if (fd >= 0) 204642575Speter (void) close(fd); 204742575Speter return; 204842575Speter } 204942575Speter 205038032Speter if ((errno = db->close(db, 0)) != 0) 205164562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 205242575Speter syserr("db_map_close(%s, %s, %lx): db close failure", 205342575Speter map->map_mname, map->map_file, map->map_mflags); 205438032Speter} 205564562Sgshapiro#endif /* NEWDB */ 205638032Speter/* 205738032Speter** NIS Modules 205838032Speter*/ 205938032Speter 206064562Sgshapiro#ifdef NIS 206138032Speter 206238032Speter# ifndef YPERR_BUSY 206338032Speter# define YPERR_BUSY 16 206464562Sgshapiro# endif /* ! YPERR_BUSY */ 206538032Speter 206638032Speter/* 206738032Speter** NIS_MAP_OPEN -- open DBM map 206838032Speter*/ 206938032Speter 207038032Speterbool 207138032Speternis_map_open(map, mode) 207238032Speter MAP *map; 207338032Speter int mode; 207438032Speter{ 207538032Speter int yperr; 207638032Speter register char *p; 207738032Speter auto char *vp; 207838032Speter auto int vsize; 207938032Speter 208038032Speter if (tTd(38, 2)) 208164562Sgshapiro dprintf("nis_map_open(%s, %s, %d)\n", 208238032Speter map->map_mname, map->map_file, mode); 208338032Speter 208438032Speter mode &= O_ACCMODE; 208538032Speter if (mode != O_RDONLY) 208638032Speter { 208738032Speter /* issue a pseudo-error message */ 208864562Sgshapiro# ifdef ENOSYS 208938032Speter errno = ENOSYS; 209064562Sgshapiro# else /* ENOSYS */ 209164562Sgshapiro# ifdef EFTYPE 209238032Speter errno = EFTYPE; 209364562Sgshapiro# else /* EFTYPE */ 209438032Speter errno = ENXIO; 209564562Sgshapiro# endif /* EFTYPE */ 209664562Sgshapiro# endif /* ENOSYS */ 209738032Speter return FALSE; 209838032Speter } 209938032Speter 210038032Speter p = strchr(map->map_file, '@'); 210138032Speter if (p != NULL) 210238032Speter { 210338032Speter *p++ = '\0'; 210438032Speter if (*p != '\0') 210538032Speter map->map_domain = p; 210638032Speter } 210738032Speter 210838032Speter if (*map->map_file == '\0') 210938032Speter map->map_file = "mail.aliases"; 211038032Speter 211138032Speter if (map->map_domain == NULL) 211238032Speter { 211338032Speter yperr = yp_get_default_domain(&map->map_domain); 211438032Speter if (yperr != 0) 211538032Speter { 211638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 211764562Sgshapiro syserr("421 4.3.5 NIS map %s specified, but NIS not running", 211864562Sgshapiro map->map_file); 211938032Speter return FALSE; 212038032Speter } 212138032Speter } 212238032Speter 212338032Speter /* check to see if this map actually exists */ 212464562Sgshapiro vp = NULL; 212538032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 212638032Speter &vp, &vsize); 212738032Speter if (tTd(38, 10)) 212864562Sgshapiro dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 212938032Speter map->map_domain, map->map_file, yperr_string(yperr)); 213064562Sgshapiro if (vp != NULL) 213164562Sgshapiro free(vp); 213264562Sgshapiro 213338032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 213438032Speter { 213538032Speter /* 213638032Speter ** We ought to be calling aliaswait() here if this is an 213738032Speter ** alias file, but powerful HP-UX NIS servers apparently 213838032Speter ** don't insert the @:@ token into the alias map when it 213938032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 214038032Speter */ 214138032Speter 214264562Sgshapiro# if 0 214338032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 214438032Speter aliaswait(map, NULL, TRUE)) 214564562Sgshapiro# endif /* 0 */ 214638032Speter return TRUE; 214738032Speter } 214838032Speter 214938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 215038032Speter { 215164562Sgshapiro syserr("421 4.0.0 Cannot bind to map %s in domain %s: %s", 215238032Speter map->map_file, map->map_domain, yperr_string(yperr)); 215338032Speter } 215438032Speter 215538032Speter return FALSE; 215638032Speter} 215738032Speter 215838032Speter 215938032Speter/* 216038032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 216138032Speter*/ 216238032Speter 216338032Speter/* ARGSUSED3 */ 216438032Speterchar * 216538032Speternis_map_lookup(map, name, av, statp) 216638032Speter MAP *map; 216738032Speter char *name; 216838032Speter char **av; 216938032Speter int *statp; 217038032Speter{ 217138032Speter char *vp; 217238032Speter auto int vsize; 217338032Speter int buflen; 217438032Speter int yperr; 217538032Speter char keybuf[MAXNAME + 1]; 217638032Speter 217738032Speter if (tTd(38, 20)) 217864562Sgshapiro dprintf("nis_map_lookup(%s, %s)\n", 217938032Speter map->map_mname, name); 218038032Speter 218138032Speter buflen = strlen(name); 218238032Speter if (buflen > sizeof keybuf - 1) 218338032Speter buflen = sizeof keybuf - 1; 218464562Sgshapiro memmove(keybuf, name, buflen); 218538032Speter keybuf[buflen] = '\0'; 218638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 218738032Speter makelower(keybuf); 218838032Speter yperr = YPERR_KEY; 218964562Sgshapiro vp = NULL; 219038032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 219138032Speter { 219238032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 219338032Speter &vp, &vsize); 219438032Speter if (yperr == 0) 219538032Speter map->map_mflags &= ~MF_TRY1NULL; 219638032Speter } 219738032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 219838032Speter { 219964562Sgshapiro if (vp != NULL) 220064562Sgshapiro { 220164562Sgshapiro free(vp); 220264562Sgshapiro vp = NULL; 220364562Sgshapiro } 220438032Speter buflen++; 220538032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 220638032Speter &vp, &vsize); 220738032Speter if (yperr == 0) 220838032Speter map->map_mflags &= ~MF_TRY0NULL; 220938032Speter } 221038032Speter if (yperr != 0) 221138032Speter { 221238032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 221338032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 221464562Sgshapiro if (vp != NULL) 221564562Sgshapiro free(vp); 221638032Speter return NULL; 221738032Speter } 221838032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 221938032Speter return map_rewrite(map, name, strlen(name), NULL); 222038032Speter else 222164562Sgshapiro { 222264562Sgshapiro char *ret; 222364562Sgshapiro 222464562Sgshapiro ret = map_rewrite(map, vp, vsize, av); 222564562Sgshapiro if (vp != NULL) 222664562Sgshapiro free(vp); 222764562Sgshapiro return ret; 222864562Sgshapiro } 222938032Speter} 223038032Speter 223138032Speter 223238032Speter/* 223338032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 223438032Speter*/ 223538032Speter 223664562Sgshapirostatic bool 223738032Speternis_getcanonname(name, hbsize, statp) 223838032Speter char *name; 223938032Speter int hbsize; 224038032Speter int *statp; 224138032Speter{ 224238032Speter char *vp; 224338032Speter auto int vsize; 224438032Speter int keylen; 224538032Speter int yperr; 224638032Speter static bool try0null = TRUE; 224738032Speter static bool try1null = TRUE; 224838032Speter static char *yp_domain = NULL; 224938032Speter char host_record[MAXLINE]; 225038032Speter char cbuf[MAXNAME]; 225138032Speter char nbuf[MAXNAME + 1]; 225238032Speter 225338032Speter if (tTd(38, 20)) 225464562Sgshapiro dprintf("nis_getcanonname(%s)\n", name); 225538032Speter 225664562Sgshapiro if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 225738032Speter { 225838032Speter *statp = EX_UNAVAILABLE; 225938032Speter return FALSE; 226038032Speter } 226138032Speter shorten_hostname(nbuf); 226238032Speter keylen = strlen(nbuf); 226338032Speter 226438032Speter if (yp_domain == NULL) 226564562Sgshapiro (void) yp_get_default_domain(&yp_domain); 226638032Speter makelower(nbuf); 226738032Speter yperr = YPERR_KEY; 226864562Sgshapiro vp = NULL; 226938032Speter if (try0null) 227038032Speter { 227138032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 227238032Speter &vp, &vsize); 227338032Speter if (yperr == 0) 227438032Speter try1null = FALSE; 227538032Speter } 227638032Speter if (yperr == YPERR_KEY && try1null) 227738032Speter { 227864562Sgshapiro if (vp != NULL) 227964562Sgshapiro { 228064562Sgshapiro free(vp); 228164562Sgshapiro vp = NULL; 228264562Sgshapiro } 228338032Speter keylen++; 228438032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 228538032Speter &vp, &vsize); 228638032Speter if (yperr == 0) 228738032Speter try0null = FALSE; 228838032Speter } 228938032Speter if (yperr != 0) 229038032Speter { 229138032Speter if (yperr == YPERR_KEY) 229238032Speter *statp = EX_NOHOST; 229338032Speter else if (yperr == YPERR_BUSY) 229438032Speter *statp = EX_TEMPFAIL; 229538032Speter else 229638032Speter *statp = EX_UNAVAILABLE; 229764562Sgshapiro if (vp != NULL) 229864562Sgshapiro free(vp); 229938032Speter return FALSE; 230038032Speter } 230164562Sgshapiro (void) strlcpy(host_record, vp, sizeof host_record); 230264562Sgshapiro free(vp); 230338032Speter if (tTd(38, 44)) 230464562Sgshapiro dprintf("got record `%s'\n", host_record); 230538032Speter if (!extract_canonname(nbuf, host_record, cbuf, sizeof cbuf)) 230638032Speter { 230738032Speter /* this should not happen, but.... */ 230838032Speter *statp = EX_NOHOST; 230938032Speter return FALSE; 231038032Speter } 231138032Speter if (hbsize < strlen(cbuf)) 231238032Speter { 231338032Speter *statp = EX_UNAVAILABLE; 231438032Speter return FALSE; 231538032Speter } 231664562Sgshapiro (void) strlcpy(name, cbuf, hbsize); 231738032Speter *statp = EX_OK; 231838032Speter return TRUE; 231938032Speter} 232038032Speter 232164562Sgshapiro#endif /* NIS */ 232238032Speter/* 232338032Speter** NISPLUS Modules 232438032Speter** 232538032Speter** This code donated by Sun Microsystems. 232638032Speter*/ 232738032Speter 232838032Speter#ifdef NISPLUS 232938032Speter 233064562Sgshapiro# undef NIS /* symbol conflict in nis.h */ 233164562Sgshapiro# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 233264562Sgshapiro# include <rpcsvc/nis.h> 233364562Sgshapiro# include <rpcsvc/nislib.h> 233438032Speter 233564562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 233664562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 233764562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 233864562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 233938032Speter 234038032Speter/* 234138032Speter** NISPLUS_MAP_OPEN -- open nisplus table 234238032Speter*/ 234338032Speter 234438032Speterbool 234538032Speternisplus_map_open(map, mode) 234638032Speter MAP *map; 234738032Speter int mode; 234838032Speter{ 234938032Speter nis_result *res = NULL; 235038032Speter int retry_cnt, max_col, i; 235138032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 235238032Speter 235338032Speter if (tTd(38, 2)) 235464562Sgshapiro dprintf("nisplus_map_open(%s, %s, %d)\n", 235538032Speter map->map_mname, map->map_file, mode); 235638032Speter 235738032Speter mode &= O_ACCMODE; 235838032Speter if (mode != O_RDONLY) 235938032Speter { 236038032Speter errno = EPERM; 236138032Speter return FALSE; 236238032Speter } 236338032Speter 236438032Speter if (*map->map_file == '\0') 236538032Speter map->map_file = "mail_aliases.org_dir"; 236638032Speter 236738032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 236838032Speter { 236938032Speter /* set default NISPLUS Domain to $m */ 237038032Speter map->map_domain = newstr(nisplus_default_domain()); 237138032Speter if (tTd(38, 2)) 237264562Sgshapiro dprintf("nisplus_map_open(%s): using domain %s\n", 237364562Sgshapiro map->map_file, map->map_domain); 237438032Speter } 237538032Speter if (!PARTIAL_NAME(map->map_file)) 237638032Speter { 237738032Speter map->map_domain = newstr(""); 237838032Speter snprintf(qbuf, sizeof qbuf, "%s", map->map_file); 237938032Speter } 238038032Speter else 238138032Speter { 238238032Speter /* check to see if this map actually exists */ 238338032Speter snprintf(qbuf, sizeof qbuf, "%s.%s", 238438032Speter map->map_file, map->map_domain); 238538032Speter } 238638032Speter 238738032Speter retry_cnt = 0; 238838032Speter while (res == NULL || res->status != NIS_SUCCESS) 238938032Speter { 239038032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 239138032Speter switch (res->status) 239238032Speter { 239338032Speter case NIS_SUCCESS: 239438032Speter break; 239538032Speter 239638032Speter case NIS_TRYAGAIN: 239738032Speter case NIS_RPCERROR: 239838032Speter case NIS_NAMEUNREACHABLE: 239938032Speter if (retry_cnt++ > 4) 240038032Speter { 240138032Speter errno = EAGAIN; 240238032Speter return FALSE; 240338032Speter } 240438032Speter /* try not to overwhelm hosed server */ 240538032Speter sleep(2); 240638032Speter break; 240738032Speter 240838032Speter default: /* all other nisplus errors */ 240964562Sgshapiro# if 0 241038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 241164562Sgshapiro syserr("421 4.0.0 Cannot find table %s.%s: %s", 241238032Speter map->map_file, map->map_domain, 241338032Speter nis_sperrno(res->status)); 241464562Sgshapiro# endif /* 0 */ 241538032Speter errno = EAGAIN; 241638032Speter return FALSE; 241738032Speter } 241838032Speter } 241938032Speter 242038032Speter if (NIS_RES_NUMOBJ(res) != 1 || 242138032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 242238032Speter { 242338032Speter if (tTd(38, 10)) 242464562Sgshapiro dprintf("nisplus_map_open: %s is not a table\n", qbuf); 242564562Sgshapiro# if 0 242638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 242764562Sgshapiro syserr("421 4.0.0 %s.%s: %s is not a table", 242838032Speter map->map_file, map->map_domain, 242938032Speter nis_sperrno(res->status)); 243064562Sgshapiro# endif /* 0 */ 243138032Speter errno = EBADF; 243238032Speter return FALSE; 243338032Speter } 243438032Speter /* default key column is column 0 */ 243538032Speter if (map->map_keycolnm == NULL) 243638032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 243738032Speter 243838032Speter max_col = COL_MAX(res); 243938032Speter 244038032Speter /* verify the key column exist */ 244164562Sgshapiro for (i = 0; i< max_col; i++) 244238032Speter { 244364562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 244438032Speter break; 244538032Speter } 244638032Speter if (i == max_col) 244738032Speter { 244838032Speter if (tTd(38, 2)) 244964562Sgshapiro dprintf("nisplus_map_open(%s): can not find key column %s\n", 245038032Speter map->map_file, map->map_keycolnm); 245138032Speter errno = ENOENT; 245238032Speter return FALSE; 245338032Speter } 245438032Speter 245538032Speter /* default value column is the last column */ 245638032Speter if (map->map_valcolnm == NULL) 245738032Speter { 245838032Speter map->map_valcolno = max_col - 1; 245938032Speter return TRUE; 246038032Speter } 246138032Speter 246264562Sgshapiro for (i = 0; i< max_col; i++) 246338032Speter { 246438032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 246538032Speter { 246638032Speter map->map_valcolno = i; 246738032Speter return TRUE; 246838032Speter } 246938032Speter } 247038032Speter 247138032Speter if (tTd(38, 2)) 247264562Sgshapiro dprintf("nisplus_map_open(%s): can not find column %s\n", 247364562Sgshapiro map->map_file, map->map_keycolnm); 247438032Speter errno = ENOENT; 247538032Speter return FALSE; 247638032Speter} 247738032Speter 247838032Speter 247938032Speter/* 248038032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 248138032Speter*/ 248238032Speter 248338032Speterchar * 248438032Speternisplus_map_lookup(map, name, av, statp) 248538032Speter MAP *map; 248638032Speter char *name; 248738032Speter char **av; 248838032Speter int *statp; 248938032Speter{ 249038032Speter char *p; 249138032Speter auto int vsize; 249238032Speter char *skp; 249338032Speter int skleft; 249438032Speter char search_key[MAXNAME + 4]; 249538032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 249638032Speter nis_result *result; 249738032Speter 249838032Speter if (tTd(38, 20)) 249964562Sgshapiro dprintf("nisplus_map_lookup(%s, %s)\n", 250038032Speter map->map_mname, name); 250138032Speter 250238032Speter if (!bitset(MF_OPEN, map->map_mflags)) 250338032Speter { 250438032Speter if (nisplus_map_open(map, O_RDONLY)) 250542575Speter { 250638032Speter map->map_mflags |= MF_OPEN; 250742575Speter map->map_pid = getpid(); 250842575Speter } 250938032Speter else 251038032Speter { 251138032Speter *statp = EX_UNAVAILABLE; 251238032Speter return NULL; 251338032Speter } 251438032Speter } 251538032Speter 251638032Speter /* 251738032Speter ** Copy the name to the key buffer, escaping double quote characters 251838032Speter ** by doubling them and quoting "]" and "," to avoid having the 251938032Speter ** NIS+ parser choke on them. 252038032Speter */ 252138032Speter 252238032Speter skleft = sizeof search_key - 4; 252338032Speter skp = search_key; 252438032Speter for (p = name; *p != '\0' && skleft > 0; p++) 252538032Speter { 252638032Speter switch (*p) 252738032Speter { 252838032Speter case ']': 252938032Speter case ',': 253038032Speter /* quote the character */ 253138032Speter *skp++ = '"'; 253238032Speter *skp++ = *p; 253338032Speter *skp++ = '"'; 253438032Speter skleft -= 3; 253538032Speter break; 253638032Speter 253738032Speter case '"': 253838032Speter /* double the quote */ 253938032Speter *skp++ = '"'; 254038032Speter skleft--; 254164562Sgshapiro /* FALLTHROUGH */ 254238032Speter 254338032Speter default: 254438032Speter *skp++ = *p; 254538032Speter skleft--; 254638032Speter break; 254738032Speter } 254838032Speter } 254938032Speter *skp = '\0'; 255038032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 255138032Speter makelower(search_key); 255238032Speter 255338032Speter /* construct the query */ 255438032Speter if (PARTIAL_NAME(map->map_file)) 255538032Speter snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", 255638032Speter map->map_keycolnm, search_key, map->map_file, 255738032Speter map->map_domain); 255838032Speter else 255938032Speter snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", 256038032Speter map->map_keycolnm, search_key, map->map_file); 256138032Speter 256238032Speter if (tTd(38, 20)) 256364562Sgshapiro dprintf("qbuf=%s\n", qbuf); 256438032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 256538032Speter if (result->status == NIS_SUCCESS) 256638032Speter { 256738032Speter int count; 256838032Speter char *str; 256938032Speter 257038032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 257138032Speter { 257238032Speter if (LogLevel > 10) 257338032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 257464562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 257564562Sgshapiro map->map_file, count); 257638032Speter 257738032Speter /* ignore second entry */ 257838032Speter if (tTd(38, 20)) 257964562Sgshapiro dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 258038032Speter name, count); 258138032Speter } 258238032Speter 258338032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 258438032Speter /* set the length of the result */ 258538032Speter if (p == NULL) 258638032Speter p = ""; 258738032Speter vsize = strlen(p); 258838032Speter if (tTd(38, 20)) 258964562Sgshapiro dprintf("nisplus_map_lookup(%s), found %s\n", 259038032Speter name, p); 259138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 259238032Speter str = map_rewrite(map, name, strlen(name), NULL); 259338032Speter else 259438032Speter str = map_rewrite(map, p, vsize, av); 259538032Speter nis_freeresult(result); 259638032Speter *statp = EX_OK; 259738032Speter return str; 259838032Speter } 259938032Speter else 260038032Speter { 260138032Speter if (result->status == NIS_NOTFOUND) 260238032Speter *statp = EX_NOTFOUND; 260338032Speter else if (result->status == NIS_TRYAGAIN) 260438032Speter *statp = EX_TEMPFAIL; 260538032Speter else 260638032Speter { 260738032Speter *statp = EX_UNAVAILABLE; 260838032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 260938032Speter } 261038032Speter } 261138032Speter if (tTd(38, 20)) 261264562Sgshapiro dprintf("nisplus_map_lookup(%s), failed\n", name); 261338032Speter nis_freeresult(result); 261438032Speter return NULL; 261538032Speter} 261638032Speter 261738032Speter 261838032Speter 261938032Speter/* 262038032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 262138032Speter*/ 262238032Speter 262364562Sgshapirostatic bool 262438032Speternisplus_getcanonname(name, hbsize, statp) 262538032Speter char *name; 262638032Speter int hbsize; 262738032Speter int *statp; 262838032Speter{ 262938032Speter char *vp; 263038032Speter auto int vsize; 263138032Speter nis_result *result; 263238032Speter char *p; 263338032Speter char nbuf[MAXNAME + 1]; 263438032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 263538032Speter 263638032Speter if (strlen(name) >= sizeof nbuf) 263738032Speter { 263838032Speter *statp = EX_UNAVAILABLE; 263938032Speter return FALSE; 264038032Speter } 264164562Sgshapiro (void) strlcpy(nbuf, name, sizeof nbuf); 264238032Speter shorten_hostname(nbuf); 264338032Speter 264438032Speter p = strchr(nbuf, '.'); 264538032Speter if (p == NULL) 264638032Speter { 264738032Speter /* single token */ 264838032Speter snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir", nbuf); 264938032Speter } 265038032Speter else if (p[1] != '\0') 265138032Speter { 265238032Speter /* multi token -- take only first token in nbuf */ 265338032Speter *p = '\0'; 265438032Speter snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir.%s", 265538032Speter nbuf, &p[1]); 265638032Speter } 265738032Speter else 265838032Speter { 265938032Speter *statp = EX_NOHOST; 266038032Speter return FALSE; 266138032Speter } 266238032Speter 266338032Speter if (tTd(38, 20)) 266464562Sgshapiro dprintf("\nnisplus_getcanoname(%s), qbuf=%s\n", 266564562Sgshapiro name, qbuf); 266638032Speter 266738032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 266838032Speter NULL, NULL); 266938032Speter 267038032Speter if (result->status == NIS_SUCCESS) 267138032Speter { 267238032Speter int count; 267338032Speter char *domain; 267438032Speter 267538032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 267638032Speter { 267738032Speter if (LogLevel > 10) 267838032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 267964562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 268064562Sgshapiro count); 268138032Speter 268238032Speter /* ignore second entry */ 268338032Speter if (tTd(38, 20)) 268464562Sgshapiro dprintf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n", 268538032Speter name, count); 268638032Speter } 268738032Speter 268838032Speter if (tTd(38, 20)) 268964562Sgshapiro dprintf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 269064562Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 269138032Speter 269238032Speter 269338032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 269438032Speter vsize = strlen(vp); 269538032Speter if (tTd(38, 20)) 269664562Sgshapiro dprintf("nisplus_getcanonname(%s), found %s\n", 269738032Speter name, vp); 269838032Speter if (strchr(vp, '.') != NULL) 269938032Speter { 270038032Speter domain = ""; 270138032Speter } 270238032Speter else 270338032Speter { 270438032Speter domain = macvalue('m', CurEnv); 270538032Speter if (domain == NULL) 270638032Speter domain = ""; 270738032Speter } 270838032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 270938032Speter { 271038032Speter if (domain[0] == '\0') 271164562Sgshapiro (void) strlcpy(name, vp, hbsize); 271238032Speter else 271338032Speter snprintf(name, hbsize, "%s.%s", vp, domain); 271438032Speter *statp = EX_OK; 271538032Speter } 271638032Speter else 271738032Speter *statp = EX_NOHOST; 271838032Speter nis_freeresult(result); 271938032Speter return TRUE; 272038032Speter } 272138032Speter else 272238032Speter { 272338032Speter if (result->status == NIS_NOTFOUND) 272438032Speter *statp = EX_NOHOST; 272538032Speter else if (result->status == NIS_TRYAGAIN) 272638032Speter *statp = EX_TEMPFAIL; 272738032Speter else 272838032Speter *statp = EX_UNAVAILABLE; 272938032Speter } 273038032Speter if (tTd(38, 20)) 273164562Sgshapiro dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 273238032Speter name, result->status, *statp); 273338032Speter nis_freeresult(result); 273438032Speter return FALSE; 273538032Speter} 273638032Speter 273738032Speterchar * 273838032Speternisplus_default_domain() 273938032Speter{ 274038032Speter static char default_domain[MAXNAME + 1] = ""; 274138032Speter char *p; 274238032Speter 274338032Speter if (default_domain[0] != '\0') 274464562Sgshapiro return default_domain; 274538032Speter 274638032Speter p = nis_local_directory(); 274738032Speter snprintf(default_domain, sizeof default_domain, "%s", p); 274838032Speter return default_domain; 274938032Speter} 275038032Speter 275138032Speter#endif /* NISPLUS */ 275238032Speter/* 275338032Speter** LDAP Modules 275438032Speter*/ 275538032Speter 275664562Sgshapiro/* 275764562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 275864562Sgshapiro*/ 275964562Sgshapiro 276064562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 276164562Sgshapiro 276264562Sgshapiro# ifdef PH_MAP 276364562Sgshapiro# define ph_map_dequote ldapmap_dequote 276464562Sgshapiro# endif /* PH_MAP */ 276564562Sgshapiro 276664562Sgshapirochar * 276764562Sgshapiroldapmap_dequote(str) 276864562Sgshapiro char *str; 276964562Sgshapiro{ 277064562Sgshapiro char *p; 277164562Sgshapiro char *start; 277264562Sgshapiro 277364562Sgshapiro if (str == NULL) 277464562Sgshapiro return NULL; 277564562Sgshapiro 277664562Sgshapiro p = str; 277764562Sgshapiro if (*p == '"') 277864562Sgshapiro { 277964562Sgshapiro /* Should probably swallow initial whitespace here */ 278064562Sgshapiro start = ++p; 278164562Sgshapiro } 278264562Sgshapiro else 278364562Sgshapiro return str; 278464562Sgshapiro while (*p != '"' && *p != '\0') 278564562Sgshapiro p++; 278664562Sgshapiro if (*p != '\0') 278764562Sgshapiro *p = '\0'; 278864562Sgshapiro return start; 278964562Sgshapiro} 279064562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 279164562Sgshapiro 279238032Speter#ifdef LDAPMAP 279338032Speter 279464562SgshapiroLDAPMAP_STRUCT *LDAPDefaults = NULL; 279538032Speter 279638032Speter/* 279764562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 279838032Speter** 279964562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 280064562Sgshapiro** single server connection to a host (with the same host, port, 280164562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 280238032Speter*/ 280338032Speter 280438032Speterbool 280564562Sgshapiroldapmap_open(map, mode) 280638032Speter MAP *map; 280738032Speter int mode; 280838032Speter{ 280964562Sgshapiro LDAPMAP_STRUCT *lmap; 281064562Sgshapiro STAB *s; 281164562Sgshapiro 281238032Speter if (tTd(38, 2)) 281366494Sgshapiro dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 281438032Speter 281538032Speter mode &= O_ACCMODE; 281664562Sgshapiro 281764562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 281838032Speter if (mode != O_RDONLY) 281938032Speter { 282038032Speter /* issue a pseudo-error message */ 282164562Sgshapiro# ifdef ENOSYS 282238032Speter errno = ENOSYS; 282364562Sgshapiro# else /* ENOSYS */ 282464562Sgshapiro# ifdef EFTYPE 282538032Speter errno = EFTYPE; 282664562Sgshapiro# else /* EFTYPE */ 282738032Speter errno = ENXIO; 282864562Sgshapiro# endif /* EFTYPE */ 282964562Sgshapiro# endif /* ENOSYS */ 283038032Speter return FALSE; 283138032Speter } 283264562Sgshapiro 283364562Sgshapiro /* Comma separate if used as an alias file */ 283464562Sgshapiro if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 283564562Sgshapiro map->map_coldelim = ','; 283664562Sgshapiro 283764562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 283864562Sgshapiro 283964562Sgshapiro s = ldapmap_findconn(lmap); 284064562Sgshapiro if (s->s_ldap != NULL) 284164562Sgshapiro { 284264562Sgshapiro /* Already have a connection open to this LDAP server */ 284364562Sgshapiro lmap->ldap_ld = s->s_ldap; 284466494Sgshapiro if (tTd(38, 2)) 284566494Sgshapiro dprintf("using cached connection\n"); 284664562Sgshapiro return TRUE; 284764562Sgshapiro } 284864562Sgshapiro 284966494Sgshapiro if (tTd(38, 2)) 285066494Sgshapiro dprintf("opening new connection\n"); 285166494Sgshapiro 285264562Sgshapiro /* No connection yet, connect */ 285364562Sgshapiro if (!ldapmap_start(map)) 285464562Sgshapiro return FALSE; 285564562Sgshapiro 285664562Sgshapiro /* Save connection for reuse */ 285764562Sgshapiro s->s_ldap = lmap->ldap_ld; 285838032Speter return TRUE; 285938032Speter} 286038032Speter 286138032Speter/* 286264562Sgshapiro** LDAPMAP_START -- actually connect to an LDAP server 286338032Speter** 286464562Sgshapiro** Parameters: 286564562Sgshapiro** map -- the map being opened. 286664562Sgshapiro** 286764562Sgshapiro** Returns: 286864562Sgshapiro** TRUE if connection is successful, FALSE otherwise. 286964562Sgshapiro** 287064562Sgshapiro** Side Effects: 287164562Sgshapiro** Populates lmap->ldap_ld. 287238032Speter*/ 287338032Speter 287438032Speterstatic jmp_buf LDAPTimeout; 287538032Speter 287664562Sgshapirostatic bool 287764562Sgshapiroldapmap_start(map) 287838032Speter MAP *map; 287938032Speter{ 288064562Sgshapiro register int bind_result; 288164562Sgshapiro int save_errno; 288264562Sgshapiro register EVENT *ev = NULL; 288364562Sgshapiro LDAPMAP_STRUCT *lmap; 288438032Speter LDAP *ld; 288538032Speter 288638032Speter if (tTd(38, 2)) 288764562Sgshapiro dprintf("ldapmap_start(%s)\n", map->map_mname); 288838032Speter 288964562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 289038032Speter 289138032Speter if (tTd(38,9)) 289264562Sgshapiro dprintf("ldapmap_start(%s, %d)\n", 289364562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host, 289464562Sgshapiro lmap->ldap_port); 289538032Speter 289664562Sgshapiro# if USE_LDAP_INIT 289764562Sgshapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 289864562Sgshapiro# else /* USE_LDAP_INIT */ 289964562Sgshapiro /* 290064562Sgshapiro ** If using ldap_open(), the actual connection to the server 290164562Sgshapiro ** happens now so we need the timeout here. For ldap_init(), 290264562Sgshapiro ** the connection happens at bind time. 290364562Sgshapiro */ 290438032Speter 290538032Speter /* set the timeout */ 290664562Sgshapiro if (lmap->ldap_timeout.tv_sec != 0) 290738032Speter { 290838032Speter if (setjmp(LDAPTimeout) != 0) 290938032Speter { 291038032Speter if (LogLevel > 1) 291138032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 291264562Sgshapiro "timeout conning to LDAP server %.100s", 291364562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); 291464562Sgshapiro return FALSE; 291538032Speter } 291664562Sgshapiro ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); 291738032Speter } 291838032Speter 291964562Sgshapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 292064562Sgshapiro save_errno = errno; 292142575Speter 292264562Sgshapiro /* clear the event if it has not sprung */ 292364562Sgshapiro if (ev != NULL) 292442575Speter clrevent(ev); 292564562Sgshapiro# endif /* USE_LDAP_INIT */ 292642575Speter 292764562Sgshapiro errno = save_errno; 292842575Speter if (ld == NULL) 292938032Speter { 293038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 293138032Speter { 293264562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 293364562Sgshapiro syserr("%s failed to %s in map %s", 293464562Sgshapiro# if USE_LDAP_INIT 293564562Sgshapiro "ldap_init", 293664562Sgshapiro# else /* USE_LDAP_INIT */ 293764562Sgshapiro "ldap_open", 293864562Sgshapiro# endif /* USE_LDAP_INIT */ 293964562Sgshapiro lmap->ldap_host == NULL ? "localhost" 294064562Sgshapiro : lmap->ldap_host, 294164562Sgshapiro map->map_mname); 294264562Sgshapiro else 294364562Sgshapiro syserr("421 4.0.0 %s failed to %s in map %s", 294464562Sgshapiro# if USE_LDAP_INIT 294564562Sgshapiro "ldap_init", 294664562Sgshapiro# else /* USE_LDAP_INIT */ 294764562Sgshapiro "ldap_open", 294864562Sgshapiro# endif /* USE_LDAP_INIT */ 294964562Sgshapiro lmap->ldap_host == NULL ? "localhost" 295064562Sgshapiro : lmap->ldap_host, 295164562Sgshapiro map->map_mname); 295238032Speter } 295338032Speter return FALSE; 295438032Speter } 295538032Speter 295664562Sgshapiro ldapmap_setopts(ld, lmap); 295738032Speter 295864562Sgshapiro# if USE_LDAP_INIT 295964562Sgshapiro /* 296064562Sgshapiro ** If using ldap_init(), the actual connection to the server 296164562Sgshapiro ** happens at ldap_bind_s() so we need the timeout here. 296264562Sgshapiro */ 296364562Sgshapiro 296464562Sgshapiro /* set the timeout */ 296564562Sgshapiro if (lmap->ldap_timeout.tv_sec != 0) 296638032Speter { 296764562Sgshapiro if (setjmp(LDAPTimeout) != 0) 296838032Speter { 296964562Sgshapiro if (LogLevel > 1) 297064562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 297164562Sgshapiro "timeout conning to LDAP server %.100s", 297264562Sgshapiro lmap->ldap_host == NULL ? "localhost" 297364562Sgshapiro : lmap->ldap_host); 297464562Sgshapiro return FALSE; 297538032Speter } 297664562Sgshapiro ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); 297738032Speter } 297864562Sgshapiro# endif /* USE_LDAP_INIT */ 297964562Sgshapiro 298064562Sgshapiro# ifdef LDAP_AUTH_KRBV4 298164562Sgshapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 298264562Sgshapiro lmap->ldap_secret != NULL) 298338032Speter { 298464562Sgshapiro /* 298564562Sgshapiro ** Need to put ticket in environment here instead of 298664562Sgshapiro ** during parseargs as there may be different tickets 298764562Sgshapiro ** for different LDAP connections. 298864562Sgshapiro */ 298964562Sgshapiro 299064562Sgshapiro (void) putenv(lmap->ldap_secret); 299138032Speter } 299264562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 299338032Speter 299464562Sgshapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 299564562Sgshapiro lmap->ldap_secret, lmap->ldap_method); 299664562Sgshapiro 299764562Sgshapiro# if USE_LDAP_INIT 299864562Sgshapiro /* clear the event if it has not sprung */ 299964562Sgshapiro if (ev != NULL) 300064562Sgshapiro clrevent(ev); 300164562Sgshapiro# endif /* USE_LDAP_INIT */ 300264562Sgshapiro 300364562Sgshapiro if (bind_result != LDAP_SUCCESS) 300464562Sgshapiro { 300564562Sgshapiro errno = bind_result + E_LDAPBASE; 300664562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 300764562Sgshapiro { 300864562Sgshapiro syserr("421 4.0.0 Cannot bind to map %s in ldap server %s", 300964562Sgshapiro map->map_mname, 301064562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); 301164562Sgshapiro } 301264562Sgshapiro return FALSE; 301364562Sgshapiro } 301464562Sgshapiro 301564562Sgshapiro /* We need to cast ld into the map structure */ 301664562Sgshapiro lmap->ldap_ld = ld; 301764562Sgshapiro return TRUE; 301838032Speter} 301938032Speter 302064562Sgshapiro/* ARGSUSED */ 302164562Sgshapirostatic void 302264562Sgshapiroldaptimeout(sig_no) 302364562Sgshapiro int sig_no; 302464562Sgshapiro{ 302564562Sgshapiro longjmp(LDAPTimeout, 1); 302664562Sgshapiro} 302738032Speter 302838032Speter/* 302964562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 303038032Speter*/ 303138032Speter 303238032Spetervoid 303364562Sgshapiroldapmap_close(map) 303438032Speter MAP *map; 303538032Speter{ 303664562Sgshapiro LDAPMAP_STRUCT *lmap; 303764562Sgshapiro STAB *s; 303843730Speter 303964562Sgshapiro if (tTd(38, 2)) 304064562Sgshapiro dprintf("ldapmap_close(%s)\n", map->map_mname); 304164562Sgshapiro 304264562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 304364562Sgshapiro 304464562Sgshapiro /* Check if already closed */ 304564562Sgshapiro if (lmap->ldap_ld == NULL) 304664562Sgshapiro return; 304764562Sgshapiro 304864562Sgshapiro s = ldapmap_findconn(lmap); 304964562Sgshapiro 305064562Sgshapiro /* Check if already closed */ 305164562Sgshapiro if (s->s_ldap == NULL) 305264562Sgshapiro return; 305364562Sgshapiro 305464562Sgshapiro /* If same as saved connection, stored connection is going away */ 305564562Sgshapiro if (s->s_ldap == lmap->ldap_ld) 305664562Sgshapiro s->s_ldap = NULL; 305764562Sgshapiro 305864562Sgshapiro if (lmap->ldap_ld != NULL) 305943730Speter { 306064562Sgshapiro ldap_unbind(lmap->ldap_ld); 306164562Sgshapiro lmap->ldap_ld = NULL; 306243730Speter } 306338032Speter} 306438032Speter 306564562Sgshapiro# ifdef SUNET_ID 306643730Speter/* 306742575Speter** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form 306842575Speter** This only makes sense at Stanford University. 306938032Speter*/ 307038032Speter 307138032Speterchar * 307238032Spetersunet_id_hash(str) 307338032Speter char *str; 307438032Speter{ 307538032Speter char *p, *p_last; 307638032Speter 307738032Speter p = str; 307838032Speter p_last = p; 307938032Speter while (*p != '\0') 308038032Speter { 308138032Speter if (islower(*p) || isdigit(*p)) 308238032Speter { 308338032Speter *p_last = *p; 308438032Speter p_last++; 308538032Speter } 308638032Speter else if (isupper(*p)) 308738032Speter { 308838032Speter *p_last = tolower(*p); 308938032Speter p_last++; 309038032Speter } 309138032Speter ++p; 309238032Speter } 309338032Speter if (*p_last != '\0') 309438032Speter *p_last = '\0'; 309564562Sgshapiro return str; 309638032Speter} 309764562Sgshapiro# endif /* SUNET_ID */ 309838032Speter 309938032Speter/* 310064562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 310138032Speter*/ 310238032Speter 310338032Speterchar * 310464562Sgshapiroldapmap_lookup(map, name, av, statp) 310538032Speter MAP *map; 310638032Speter char *name; 310738032Speter char **av; 310838032Speter int *statp; 310938032Speter{ 311064562Sgshapiro int i; 311164562Sgshapiro int entries = 0; 311264562Sgshapiro int msgid; 311364562Sgshapiro int ret; 311464562Sgshapiro int vsize; 311564562Sgshapiro char *fp, *vp; 311664562Sgshapiro char *p, *q; 311764562Sgshapiro char *result = NULL; 311864562Sgshapiro LDAPMAP_STRUCT *lmap = NULL; 311938032Speter char keybuf[MAXNAME + 1]; 312064562Sgshapiro char filter[LDAPMAP_MAX_FILTER + 1]; 312138032Speter 312238032Speter if (tTd(38, 20)) 312364562Sgshapiro dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); 312438032Speter 312538032Speter /* Get ldap struct pointer from map */ 312664562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 312764562Sgshapiro ldapmap_setopts(lmap->ldap_ld, lmap); 312838032Speter 312964562Sgshapiro (void) strlcpy(keybuf, name, sizeof keybuf); 313038032Speter 313138032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 313264562Sgshapiro { 313364562Sgshapiro# ifdef SUNET_ID 313438032Speter sunet_id_hash(keybuf); 313564562Sgshapiro# else /* SUNET_ID */ 313638032Speter makelower(keybuf); 313764562Sgshapiro# endif /* SUNET_ID */ 313864562Sgshapiro } 313938032Speter 314042575Speter /* substitute keybuf into filter, perhaps multiple times */ 314164562Sgshapiro memset(filter, '\0', sizeof filter); 314242575Speter fp = filter; 314364562Sgshapiro p = lmap->ldap_filter; 314442575Speter while ((q = strchr(p, '%')) != NULL) 314542575Speter { 314642575Speter if (q[1] == 's') 314742575Speter { 314842575Speter snprintf(fp, SPACELEFT(filter, fp), "%.*s%s", 314966494Sgshapiro (int) (q - p), p, keybuf); 315064562Sgshapiro fp += strlen(fp); 315142575Speter p = q + 2; 315242575Speter } 315364562Sgshapiro else if (q[1] == '0') 315464562Sgshapiro { 315564562Sgshapiro char *k = keybuf; 315664562Sgshapiro 315764562Sgshapiro snprintf(fp, SPACELEFT(filter, fp), "%.*s", 315866494Sgshapiro (int) (q - p), p); 315964562Sgshapiro fp += strlen(fp); 316064562Sgshapiro p = q + 2; 316164562Sgshapiro 316264562Sgshapiro /* Properly escape LDAP special characters */ 316364562Sgshapiro while (SPACELEFT(filter, fp) > 0 && 316464562Sgshapiro *k != '\0') 316564562Sgshapiro { 316664562Sgshapiro if (*k == '*' || *k == '(' || 316764562Sgshapiro *k == ')' || *k == '\\') 316864562Sgshapiro { 316964562Sgshapiro (void) strlcat(fp, 317064562Sgshapiro (*k == '*' ? "\\2A" : 317164562Sgshapiro (*k == '(' ? "\\28" : 317264562Sgshapiro (*k == ')' ? "\\29" : 317364562Sgshapiro (*k == '\\' ? "\\5C" : 317464562Sgshapiro "\00")))), 317564562Sgshapiro SPACELEFT(filter, fp)); 317664562Sgshapiro fp += strlen(fp); 317764562Sgshapiro k++; 317864562Sgshapiro } 317964562Sgshapiro else 318064562Sgshapiro *fp++ = *k++; 318164562Sgshapiro } 318264562Sgshapiro } 318342575Speter else 318442575Speter { 318542575Speter snprintf(fp, SPACELEFT(filter, fp), "%.*s", 318666494Sgshapiro (int) (q - p + 1), p); 318742575Speter p = q + (q[1] == '%' ? 2 : 1); 318864562Sgshapiro fp += strlen(fp); 318942575Speter } 319042575Speter } 319142575Speter snprintf(fp, SPACELEFT(filter, fp), "%s", p); 319242575Speter if (tTd(38, 20)) 319364562Sgshapiro dprintf("ldap search filter=%s\n", filter); 319438032Speter 319564562Sgshapiro lmap->ldap_res = NULL; 319664562Sgshapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, 319764562Sgshapiro filter, 319864562Sgshapiro (lmap->ldap_attr[0] == NULL ? NULL : 319964562Sgshapiro lmap->ldap_attr), 320064562Sgshapiro lmap->ldap_attrsonly); 320164562Sgshapiro if (msgid == -1) 320238032Speter { 320364562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 320464562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 320538032Speter { 320664562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 320766494Sgshapiro syserr("Error in ldap_search using %s in map %s", 320864562Sgshapiro filter, map->map_mname); 320964562Sgshapiro else 321066494Sgshapiro syserr("421 4.0.0 Error in ldap_search using %s in map %s", 321164562Sgshapiro filter, map->map_mname); 321238032Speter } 321364562Sgshapiro *statp = EX_TEMPFAIL; 321466494Sgshapiro#ifdef LDAP_SERVER_DOWN 321566494Sgshapiro if (errno == LDAP_SERVER_DOWN) 321666494Sgshapiro { 321766494Sgshapiro int save_errno = errno; 321866494Sgshapiro 321966494Sgshapiro /* server disappeared, try reopen on next search */ 322066494Sgshapiro map->map_class->map_close(map); 322166494Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 322266494Sgshapiro errno = save_errno; 322366494Sgshapiro } 322466494Sgshapiro#endif /* LDAP_SERVER_DOWN */ 322564562Sgshapiro return NULL; 322664562Sgshapiro } 322764562Sgshapiro 322864562Sgshapiro *statp = EX_NOTFOUND; 322964562Sgshapiro vp = NULL; 323064562Sgshapiro 323164562Sgshapiro /* Get results (all if MF_NOREWRITE, otherwise one by one) */ 323264562Sgshapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 323364562Sgshapiro bitset(MF_NOREWRITE, map->map_mflags), 323464562Sgshapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 323564562Sgshapiro &(lmap->ldap_timeout)), 323664562Sgshapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 323764562Sgshapiro { 323864562Sgshapiro LDAPMessage *entry; 323964562Sgshapiro 324064562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 324138032Speter { 324264562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, 324364562Sgshapiro lmap->ldap_res); 324464562Sgshapiro if (entries > 1) 324564562Sgshapiro { 324664562Sgshapiro *statp = EX_NOTFOUND; 324764562Sgshapiro if (lmap->ldap_res != NULL) 324864562Sgshapiro { 324964562Sgshapiro ldap_msgfree(lmap->ldap_res); 325064562Sgshapiro lmap->ldap_res = NULL; 325164562Sgshapiro } 325264562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 325364562Sgshapiro if (vp != NULL) 325464562Sgshapiro free(vp); 325564562Sgshapiro if (tTd(38, 25)) 325664562Sgshapiro dprintf("ldap search found multiple on a single match query\n"); 325764562Sgshapiro return NULL; 325864562Sgshapiro } 325964562Sgshapiro } 326064562Sgshapiro 326164562Sgshapiro /* If we don't want multiple values and we have one, break */ 326264562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 326364562Sgshapiro break; 326464562Sgshapiro 326564562Sgshapiro /* Cycle through all entries */ 326664562Sgshapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 326764562Sgshapiro entry != NULL; 326864562Sgshapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 326964562Sgshapiro { 327064562Sgshapiro BerElement *ber; 327164562Sgshapiro char *attr; 327264562Sgshapiro char **vals = NULL; 327364562Sgshapiro 327464562Sgshapiro /* 327564562Sgshapiro ** If matching only and found an entry, 327664562Sgshapiro ** no need to spin through attributes 327764562Sgshapiro */ 327864562Sgshapiro 327964562Sgshapiro if (*statp == EX_OK && 328064562Sgshapiro bitset(MF_MATCHONLY, map->map_mflags)) 328164562Sgshapiro continue; 328264562Sgshapiro 328364562Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 328464562Sgshapiro /* 328564562Sgshapiro ** Reset value to prevent lingering 328664562Sgshapiro ** LDAP_DECODING_ERROR due to 328764562Sgshapiro ** OpenLDAP 1.X's hack (see below) 328864562Sgshapiro */ 328964562Sgshapiro 329064562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 329164562Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 329264562Sgshapiro 329364562Sgshapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 329464562Sgshapiro &ber); 329564562Sgshapiro attr != NULL; 329664562Sgshapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 329764562Sgshapiro ber)) 329864562Sgshapiro { 329964562Sgshapiro char *tmp, *vp_tmp; 330064562Sgshapiro 330164562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 330264562Sgshapiro { 330364562Sgshapiro vals = ldap_get_values(lmap->ldap_ld, 330464562Sgshapiro entry, 330564562Sgshapiro attr); 330664562Sgshapiro if (vals == NULL) 330764562Sgshapiro { 330864562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 330964562Sgshapiro if (errno == LDAP_SUCCESS) 331064562Sgshapiro continue; 331164562Sgshapiro 331264562Sgshapiro /* Must be an error */ 331364562Sgshapiro errno += E_LDAPBASE; 331464562Sgshapiro if (!bitset(MF_OPTIONAL, 331564562Sgshapiro map->map_mflags)) 331664562Sgshapiro { 331764562Sgshapiro if (bitset(MF_NODEFER, 331864562Sgshapiro map->map_mflags)) 331964562Sgshapiro syserr("Error getting LDAP values in map %s", 332064562Sgshapiro map->map_mname); 332164562Sgshapiro else 332264562Sgshapiro syserr("421 4.0.0 Error getting LDAP values in map %s", 332364562Sgshapiro map->map_mname); 332464562Sgshapiro } 332564562Sgshapiro *statp = EX_TEMPFAIL; 332664562Sgshapiro# if USING_NETSCAPE_LDAP 332766494Sgshapiro ldap_memfree(attr); 332864562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 332964562Sgshapiro if (lmap->ldap_res != NULL) 333064562Sgshapiro { 333164562Sgshapiro ldap_msgfree(lmap->ldap_res); 333264562Sgshapiro lmap->ldap_res = NULL; 333364562Sgshapiro } 333464562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, 333564562Sgshapiro msgid); 333664562Sgshapiro if (vp != NULL) 333764562Sgshapiro free(vp); 333864562Sgshapiro return NULL; 333964562Sgshapiro } 334064562Sgshapiro } 334164562Sgshapiro 334264562Sgshapiro *statp = EX_OK; 334364562Sgshapiro 334464562Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 334564562Sgshapiro /* 334664562Sgshapiro ** Reset value to prevent lingering 334764562Sgshapiro ** LDAP_DECODING_ERROR due to 334864562Sgshapiro ** OpenLDAP 1.X's hack (see below) 334964562Sgshapiro */ 335064562Sgshapiro 335164562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 335264562Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 335364562Sgshapiro 335464562Sgshapiro /* 335564562Sgshapiro ** If matching only, 335664562Sgshapiro ** no need to spin through entries 335764562Sgshapiro */ 335864562Sgshapiro 335964562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 336064562Sgshapiro continue; 336164562Sgshapiro 336264562Sgshapiro /* 336364562Sgshapiro ** If we don't want multiple values, 336464562Sgshapiro ** return first found. 336564562Sgshapiro */ 336664562Sgshapiro 336764562Sgshapiro if (map->map_coldelim == '\0') 336864562Sgshapiro { 336964562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 337064562Sgshapiro { 337164562Sgshapiro vp = newstr(attr); 337264562Sgshapiro# if USING_NETSCAPE_LDAP 337366494Sgshapiro ldap_memfree(attr); 337464562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 337564562Sgshapiro break; 337664562Sgshapiro } 337764562Sgshapiro 337864562Sgshapiro if (vals[0] == NULL) 337964562Sgshapiro { 338064562Sgshapiro ldap_value_free(vals); 338164562Sgshapiro# if USING_NETSCAPE_LDAP 338266494Sgshapiro ldap_memfree(attr); 338364562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 338464562Sgshapiro continue; 338564562Sgshapiro } 338664562Sgshapiro 338764562Sgshapiro vp = newstr(vals[0]); 338864562Sgshapiro ldap_value_free(vals); 338964562Sgshapiro# if USING_NETSCAPE_LDAP 339066494Sgshapiro ldap_memfree(attr); 339164562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 339264562Sgshapiro break; 339364562Sgshapiro } 339464562Sgshapiro 339564562Sgshapiro /* attributes only */ 339664562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 339764562Sgshapiro { 339864562Sgshapiro if (vp == NULL) 339964562Sgshapiro vp = newstr(attr); 340064562Sgshapiro else 340164562Sgshapiro { 340264562Sgshapiro vsize = strlen(vp) + 340364562Sgshapiro strlen(attr) + 2; 340464562Sgshapiro tmp = xalloc(vsize); 340564562Sgshapiro snprintf(tmp, vsize, "%s%c%s", 340664562Sgshapiro vp, map->map_coldelim, 340764562Sgshapiro attr); 340864562Sgshapiro free(vp); 340964562Sgshapiro vp = tmp; 341064562Sgshapiro } 341164562Sgshapiro# if USING_NETSCAPE_LDAP 341266494Sgshapiro ldap_memfree(attr); 341364562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 341464562Sgshapiro continue; 341564562Sgshapiro } 341664562Sgshapiro 341764562Sgshapiro /* 341864562Sgshapiro ** If there is more than one, 341964562Sgshapiro ** munge then into a map_coldelim 342064562Sgshapiro ** separated string 342164562Sgshapiro */ 342264562Sgshapiro 342364562Sgshapiro vsize = 0; 342464562Sgshapiro for (i = 0; vals[i] != NULL; i++) 342564562Sgshapiro vsize += strlen(vals[i]) + 1; 342664562Sgshapiro vp_tmp = xalloc(vsize); 342764562Sgshapiro *vp_tmp = '\0'; 342864562Sgshapiro 342964562Sgshapiro p = vp_tmp; 343064562Sgshapiro for (i = 0; vals[i] != NULL; i++) 343164562Sgshapiro { 343264562Sgshapiro p += strlcpy(p, vals[i], 343364562Sgshapiro vsize - (p - vp_tmp)); 343464562Sgshapiro if (p >= vp_tmp + vsize) 343564562Sgshapiro syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values"); 343664562Sgshapiro if (vals[i + 1] != NULL) 343764562Sgshapiro *p++ = map->map_coldelim; 343864562Sgshapiro } 343964562Sgshapiro 344064562Sgshapiro ldap_value_free(vals); 344164562Sgshapiro# if USING_NETSCAPE_LDAP 344266494Sgshapiro ldap_memfree(attr); 344364562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 344464562Sgshapiro if (vp == NULL) 344564562Sgshapiro { 344664562Sgshapiro vp = vp_tmp; 344764562Sgshapiro continue; 344864562Sgshapiro } 344964562Sgshapiro vsize = strlen(vp) + strlen(vp_tmp) + 2; 345064562Sgshapiro tmp = xalloc(vsize); 345164562Sgshapiro snprintf(tmp, vsize, "%s%c%s", 345264562Sgshapiro vp, map->map_coldelim, vp_tmp); 345364562Sgshapiro 345464562Sgshapiro free(vp); 345564562Sgshapiro free(vp_tmp); 345664562Sgshapiro vp = tmp; 345764562Sgshapiro } 345864562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 345964562Sgshapiro 346064562Sgshapiro /* 346164562Sgshapiro ** We check errno != LDAP_DECODING_ERROR since 346264562Sgshapiro ** OpenLDAP 1.X has a very ugly *undocumented* 346364562Sgshapiro ** hack of returning this error code from 346464562Sgshapiro ** ldap_next_attribute() if the library freed the 346564562Sgshapiro ** ber attribute. See: 346664562Sgshapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 346764562Sgshapiro */ 346864562Sgshapiro 346964562Sgshapiro if (errno != LDAP_SUCCESS && 347064562Sgshapiro errno != LDAP_DECODING_ERROR) 347164562Sgshapiro { 347264562Sgshapiro /* Must be an error */ 347364562Sgshapiro errno += E_LDAPBASE; 347464562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 347564562Sgshapiro { 347664562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 347764562Sgshapiro syserr("Error getting LDAP attributes in map %s", 347864562Sgshapiro map->map_mname); 347964562Sgshapiro else 348064562Sgshapiro syserr("421 4.0.0 Error getting LDAP attributes in map %s", 348164562Sgshapiro map->map_mname); 348264562Sgshapiro } 348364562Sgshapiro *statp = EX_TEMPFAIL; 348464562Sgshapiro if (lmap->ldap_res != NULL) 348564562Sgshapiro { 348664562Sgshapiro ldap_msgfree(lmap->ldap_res); 348764562Sgshapiro lmap->ldap_res = NULL; 348864562Sgshapiro } 348964562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 349064562Sgshapiro if (vp != NULL) 349164562Sgshapiro free(vp); 349264562Sgshapiro return NULL; 349364562Sgshapiro } 349464562Sgshapiro 349564562Sgshapiro /* We don't want multiple values and we have one */ 349664562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 349764562Sgshapiro break; 349864562Sgshapiro } 349964562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 350064562Sgshapiro if (errno != LDAP_SUCCESS && errno != LDAP_DECODING_ERROR) 350164562Sgshapiro { 350264562Sgshapiro /* Must be an error */ 350364562Sgshapiro errno += E_LDAPBASE; 350438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 350538032Speter { 350664562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 350764562Sgshapiro syserr("Error getting LDAP entries in map %s", 350864562Sgshapiro map->map_mname); 350964562Sgshapiro else 351064562Sgshapiro syserr("421 4.0.0 Error getting LDAP entries in map %s", 351164562Sgshapiro map->map_mname); 351238032Speter } 351338032Speter *statp = EX_TEMPFAIL; 351464562Sgshapiro if (lmap->ldap_res != NULL) 351564562Sgshapiro { 351664562Sgshapiro ldap_msgfree(lmap->ldap_res); 351764562Sgshapiro lmap->ldap_res = NULL; 351864562Sgshapiro } 351964562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 352064562Sgshapiro if (vp != NULL) 352164562Sgshapiro free(vp); 352264562Sgshapiro return NULL; 352338032Speter } 352464562Sgshapiro ldap_msgfree(lmap->ldap_res); 352564562Sgshapiro lmap->ldap_res = NULL; 352638032Speter } 352738032Speter 352864562Sgshapiro /* 352964562Sgshapiro ** If grabbing all results at once for MF_NOREWRITE and 353064562Sgshapiro ** only want a single match, make sure that's all we have 353164562Sgshapiro */ 353264562Sgshapiro 353364562Sgshapiro if (ret == LDAP_RES_SEARCH_RESULT && 353464562Sgshapiro bitset(MF_NOREWRITE|MF_SINGLEMATCH, map->map_mflags)) 353538032Speter { 353664562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, lmap->ldap_res); 353764562Sgshapiro if (entries > 1) 353864562Sgshapiro { 353964562Sgshapiro *statp = EX_NOTFOUND; 354064562Sgshapiro if (lmap->ldap_res != NULL) 354164562Sgshapiro { 354264562Sgshapiro ldap_msgfree(lmap->ldap_res); 354364562Sgshapiro lmap->ldap_res = NULL; 354464562Sgshapiro } 354564562Sgshapiro if (vp != NULL) 354664562Sgshapiro free(vp); 354764562Sgshapiro return NULL; 354864562Sgshapiro } 354964562Sgshapiro *statp = EX_OK; 355038032Speter } 355138032Speter 355264562Sgshapiro if (ret == 0) 355364562Sgshapiro errno = ETIMEDOUT; 355464562Sgshapiro else 355564562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 355664562Sgshapiro if (errno != LDAP_SUCCESS) 355738032Speter { 355864562Sgshapiro /* Must be an error */ 355964562Sgshapiro if (ret != 0) 356064562Sgshapiro errno += E_LDAPBASE; 356164562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 356264562Sgshapiro { 356364562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 356464562Sgshapiro syserr("Error getting LDAP results in map %s", 356564562Sgshapiro map->map_mname); 356664562Sgshapiro else 356764562Sgshapiro syserr("421 4.0.0 Error getting LDAP results in map %s", 356864562Sgshapiro map->map_mname); 356964562Sgshapiro } 357064562Sgshapiro *statp = EX_TEMPFAIL; 357164562Sgshapiro if (vp != NULL) 357264562Sgshapiro free(vp); 357364562Sgshapiro return NULL; 357438032Speter } 357538032Speter 357664562Sgshapiro /* Did we match anything? */ 357764562Sgshapiro if (vp == NULL) 357864562Sgshapiro return NULL; 357938032Speter 358064562Sgshapiro /* 358164562Sgshapiro ** If MF_NOREWRITE, we are special map which doesn't 358264562Sgshapiro ** actually return a map value. Instead, we don't free 358364562Sgshapiro ** ldap_res and let the calling function process the LDAP 358464562Sgshapiro ** results. The caller should ldap_msgfree(lmap->ldap_res). 358564562Sgshapiro */ 358638032Speter 358764562Sgshapiro if (bitset(MF_NOREWRITE, map->map_mflags)) 358864562Sgshapiro { 358964562Sgshapiro /* vp != NULL due to test above */ 359064562Sgshapiro free(vp); 359164562Sgshapiro return ""; 359264562Sgshapiro } 359338032Speter 359464562Sgshapiro if (*statp == EX_OK) 359564562Sgshapiro { 359664562Sgshapiro /* vp != NULL due to test above */ 359764562Sgshapiro if (LogLevel > 9) 359864562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 359964562Sgshapiro "ldap %.100s => %s", name, vp); 360064562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 360164562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 360264562Sgshapiro else 360364562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 360464562Sgshapiro free(vp); 360564562Sgshapiro } 360664562Sgshapiro return result; 360738032Speter} 360838032Speter 360938032Speter/* 361064562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 361164562Sgshapiro** 361264562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 361366494Sgshapiro** secret, and PID so we don't have multiple connections open to 361466494Sgshapiro** the same server for different maps. Need a separate connection 361566494Sgshapiro** per PID since a parent process may close the map before the 361666494Sgshapiro** child is done with it. 361764562Sgshapiro** 361864562Sgshapiro** Parameters: 361964562Sgshapiro** lmap -- LDAP map information 362064562Sgshapiro** 362164562Sgshapiro** Returns: 362264562Sgshapiro** Symbol table entry for the LDAP connection. 362364562Sgshapiro** 362438032Speter*/ 362538032Speter 362664562Sgshapirostatic STAB * 362764562Sgshapiroldapmap_findconn(lmap) 362864562Sgshapiro LDAPMAP_STRUCT *lmap; 362938032Speter{ 363064562Sgshapiro int len; 363164562Sgshapiro char *nbuf; 363264562Sgshapiro STAB *s; 363338032Speter 363464562Sgshapiro len = (lmap->ldap_host == NULL ? strlen("localhost") : 363564562Sgshapiro strlen(lmap->ldap_host)) + 1 + 8 + 1 + 363664562Sgshapiro (lmap->ldap_binddn == NULL ? 0 : strlen(lmap->ldap_binddn)) + 363764562Sgshapiro 1 + 363864562Sgshapiro (lmap->ldap_secret == NULL ? 0 : strlen(lmap->ldap_secret)) + 363966494Sgshapiro 8 + 1; 364064562Sgshapiro nbuf = xalloc(len); 364166494Sgshapiro snprintf(nbuf, len, "%s%c%d%c%s%c%s%d", 364264562Sgshapiro (lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host), 364364562Sgshapiro CONDELSE, 364464562Sgshapiro lmap->ldap_port, 364564562Sgshapiro CONDELSE, 364664562Sgshapiro (lmap->ldap_binddn == NULL ? "" : lmap->ldap_binddn), 364764562Sgshapiro CONDELSE, 364866494Sgshapiro (lmap->ldap_secret == NULL ? "" : lmap->ldap_secret), 364966494Sgshapiro getpid()); 365064562Sgshapiro s = stab(nbuf, ST_LDAP, ST_ENTER); 365164562Sgshapiro free(nbuf); 365264562Sgshapiro return s; 365364562Sgshapiro} 365464562Sgshapiro/* 365564562Sgshapiro** LDAPMAP_SETOPTS -- set LDAP options 365664562Sgshapiro** 365764562Sgshapiro** Parameters: 365864562Sgshapiro** ld -- LDAP session handle 365964562Sgshapiro** lmap -- LDAP map information 366064562Sgshapiro** 366164562Sgshapiro** Returns: 366264562Sgshapiro** None. 366364562Sgshapiro** 366464562Sgshapiro*/ 366564562Sgshapiro 366664562Sgshapirostatic void 366764562Sgshapiroldapmap_setopts(ld, lmap) 366864562Sgshapiro LDAP *ld; 366964562Sgshapiro LDAPMAP_STRUCT *lmap; 367064562Sgshapiro{ 367164562Sgshapiro# if USE_LDAP_SET_OPTION 367264562Sgshapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 367364562Sgshapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 367464562Sgshapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 367538032Speter else 367664562Sgshapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 367764562Sgshapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 367864562Sgshapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 367964562Sgshapiro# else /* USE_LDAP_SET_OPTION */ 368064562Sgshapiro /* From here on in we can use ldap internal timelimits */ 368164562Sgshapiro ld->ld_deref = lmap->ldap_deref; 368264562Sgshapiro ld->ld_options = lmap->ldap_options; 368364562Sgshapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 368464562Sgshapiro ld->ld_timelimit = lmap->ldap_timelimit; 368564562Sgshapiro# endif /* USE_LDAP_SET_OPTION */ 368638032Speter} 368764562Sgshapiro/* 368864562Sgshapiro** LDAPMAP_GETERRNO -- get ldap errno value 368964562Sgshapiro** 369064562Sgshapiro** Parameters: 369164562Sgshapiro** ld -- LDAP session handle 369264562Sgshapiro** 369364562Sgshapiro** Returns: 369464562Sgshapiro** LDAP errno. 369564562Sgshapiro** 369664562Sgshapiro*/ 369738032Speter 369864562Sgshapirostatic int 369964562Sgshapiroldapmap_geterrno(ld) 370064562Sgshapiro LDAP *ld; 370164562Sgshapiro{ 370264562Sgshapiro int err = LDAP_SUCCESS; 370364562Sgshapiro 370464562Sgshapiro# if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 370564562Sgshapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 370664562Sgshapiro# else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 370764562Sgshapiro# ifdef LDAP_OPT_SIZELIMIT 370864562Sgshapiro err = ldap_get_lderrno(ld, NULL, NULL); 370964562Sgshapiro# else /* LDAP_OPT_SIZELIMIT */ 371064562Sgshapiro err = ld->ld_errno; 371164562Sgshapiro 371264562Sgshapiro /* 371364562Sgshapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 371464562Sgshapiro ** OpenLDAP 1.X's hack (see above) 371564562Sgshapiro */ 371664562Sgshapiro 371764562Sgshapiro ld->ld_errno = LDAP_SUCCESS; 371864562Sgshapiro# endif /* LDAP_OPT_SIZELIMIT */ 371964562Sgshapiro# endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 372064562Sgshapiro return err; 372164562Sgshapiro} 372264562Sgshapiro 372338032Speter/* 372464562Sgshapiro** LDAPX_MAP_PARSEARGS -- print warning about use of ldapx map. 372538032Speter*/ 372638032Speter 372738032Speterbool 372864562Sgshapiroldapx_map_parseargs(map, args) 372938032Speter MAP *map; 373038032Speter char *args; 373138032Speter{ 373264562Sgshapiro printf("Warning: The \"ldapx\" map class is deprecated and will be removed in a future\n"); 373364562Sgshapiro printf(" version. Use the \"ldap\" map class instead for map \"%s\".\n", 373464562Sgshapiro map->map_mname); 373564562Sgshapiro return ldapmap_parseargs(map, args); 373664562Sgshapiro} 373738032Speter 373864562Sgshapiro/* 373964562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 374064562Sgshapiro*/ 374138032Speter 374264562Sgshapirostruct lamvalues LDAPAuthMethods[] = 374364562Sgshapiro{ 374464562Sgshapiro { "none", LDAP_AUTH_NONE }, 374564562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 374664562Sgshapiro# ifdef LDAP_AUTH_KRBV4 374764562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 374864562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 374964562Sgshapiro { NULL, 0 } 375064562Sgshapiro}; 375138032Speter 375264562Sgshapirostruct ladvalues LDAPAliasDereference[] = 375364562Sgshapiro{ 375464562Sgshapiro { "never", LDAP_DEREF_NEVER }, 375564562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 375664562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 375764562Sgshapiro { "find", LDAP_DEREF_FINDING }, 375864562Sgshapiro { NULL, 0 } 375964562Sgshapiro}; 376038032Speter 376164562Sgshapirostruct lssvalues LDAPSearchScope[] = 376264562Sgshapiro{ 376364562Sgshapiro { "base", LDAP_SCOPE_BASE }, 376464562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 376564562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 376664562Sgshapiro { NULL, 0 } 376764562Sgshapiro}; 376838032Speter 376964562Sgshapirobool 377064562Sgshapiroldapmap_parseargs(map, args) 377164562Sgshapiro MAP *map; 377264562Sgshapiro char *args; 377364562Sgshapiro{ 377464562Sgshapiro bool secretread = TRUE; 377564562Sgshapiro int i; 377664562Sgshapiro register char *p = args; 377764562Sgshapiro LDAPMAP_STRUCT *lmap; 377864562Sgshapiro struct lamvalues *lam; 377964562Sgshapiro struct ladvalues *lad; 378064562Sgshapiro struct lssvalues *lss; 378164562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 378264562Sgshapiro 378364562Sgshapiro /* Get ldap struct pointer from map */ 378464562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 378564562Sgshapiro 378664562Sgshapiro /* Check if setting the initial LDAP defaults */ 378764562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 378864562Sgshapiro { 378964562Sgshapiro /* We need to alloc an LDAPMAP_STRUCT struct */ 379064562Sgshapiro lmap = (LDAPMAP_STRUCT *) xalloc(sizeof *lmap); 379164562Sgshapiro if (LDAPDefaults == NULL) 379264562Sgshapiro ldapmap_clear(lmap); 379364562Sgshapiro else 379464562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 379564562Sgshapiro } 379664562Sgshapiro 379764562Sgshapiro /* there is no check whether there is really an argument */ 379864562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 379964562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 380038032Speter for (;;) 380138032Speter { 380238032Speter while (isascii(*p) && isspace(*p)) 380338032Speter p++; 380438032Speter if (*p != '-') 380538032Speter break; 380638032Speter switch (*++p) 380738032Speter { 380838032Speter case 'N': 380938032Speter map->map_mflags |= MF_INCLNULL; 381038032Speter map->map_mflags &= ~MF_TRY0NULL; 381138032Speter break; 381238032Speter 381338032Speter case 'O': 381438032Speter map->map_mflags &= ~MF_TRY1NULL; 381538032Speter break; 381638032Speter 381738032Speter case 'o': 381838032Speter map->map_mflags |= MF_OPTIONAL; 381938032Speter break; 382038032Speter 382138032Speter case 'f': 382238032Speter map->map_mflags |= MF_NOFOLDCASE; 382338032Speter break; 382438032Speter 382538032Speter case 'm': 382638032Speter map->map_mflags |= MF_MATCHONLY; 382738032Speter break; 382838032Speter 382938032Speter case 'A': 383038032Speter map->map_mflags |= MF_APPEND; 383138032Speter break; 383238032Speter 383338032Speter case 'q': 383438032Speter map->map_mflags |= MF_KEEPQUOTES; 383538032Speter break; 383638032Speter 383738032Speter case 'a': 383838032Speter map->map_app = ++p; 383938032Speter break; 384038032Speter 384138032Speter case 'T': 384238032Speter map->map_tapp = ++p; 384338032Speter break; 384438032Speter 384564562Sgshapiro case 't': 384664562Sgshapiro map->map_mflags |= MF_NODEFER; 384764562Sgshapiro break; 384864562Sgshapiro 384964562Sgshapiro case 'S': 385064562Sgshapiro map->map_spacesub = *++p; 385164562Sgshapiro break; 385264562Sgshapiro 385364562Sgshapiro case 'D': 385464562Sgshapiro map->map_mflags |= MF_DEFER; 385564562Sgshapiro break; 385664562Sgshapiro 385764562Sgshapiro case 'z': 385864562Sgshapiro if (*++p != '\\') 385964562Sgshapiro map->map_coldelim = *p; 386064562Sgshapiro else 386164562Sgshapiro { 386264562Sgshapiro switch (*++p) 386364562Sgshapiro { 386464562Sgshapiro case 'n': 386564562Sgshapiro map->map_coldelim = '\n'; 386664562Sgshapiro break; 386764562Sgshapiro 386864562Sgshapiro case 't': 386964562Sgshapiro map->map_coldelim = '\t'; 387064562Sgshapiro break; 387164562Sgshapiro 387264562Sgshapiro default: 387364562Sgshapiro map->map_coldelim = '\\'; 387464562Sgshapiro } 387564562Sgshapiro } 387664562Sgshapiro break; 387764562Sgshapiro 387864562Sgshapiro /* Start of ldapmap specific args */ 387938032Speter case 'k': /* search field */ 388038032Speter while (isascii(*++p) && isspace(*p)) 388138032Speter continue; 388264562Sgshapiro lmap->ldap_filter = p; 388338032Speter break; 388438032Speter 388538032Speter case 'v': /* attr to return */ 388638032Speter while (isascii(*++p) && isspace(*p)) 388738032Speter continue; 388864562Sgshapiro lmap->ldap_attr[0] = p; 388964562Sgshapiro lmap->ldap_attr[1] = NULL; 389038032Speter break; 389138032Speter 389264562Sgshapiro case '1': 389364562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 389464562Sgshapiro break; 389564562Sgshapiro 389638032Speter /* args stolen from ldapsearch.c */ 389738032Speter case 'R': /* don't auto chase referrals */ 389864562Sgshapiro# ifdef LDAP_REFERRALS 389938032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 390064562Sgshapiro# else /* LDAP_REFERRALS */ 390138032Speter syserr("compile with -DLDAP_REFERRALS for referral support\n"); 390264562Sgshapiro# endif /* LDAP_REFERRALS */ 390338032Speter break; 390438032Speter 390564562Sgshapiro case 'n': /* retrieve attribute names only */ 390664562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 390738032Speter break; 390838032Speter 390964562Sgshapiro case 'r': /* alias dereferencing */ 391064562Sgshapiro while (isascii(*++p) && isspace(*p)) 391164562Sgshapiro continue; 391264562Sgshapiro 391364562Sgshapiro if (strncasecmp(p, "LDAP_DEREF_", 11) == 0) 391464562Sgshapiro p += 11; 391564562Sgshapiro 391664562Sgshapiro for (lad = LDAPAliasDereference; 391764562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 391838032Speter { 391964562Sgshapiro if (strncasecmp(p, lad->lad_name, 392064562Sgshapiro strlen(lad->lad_name)) == 0) 392164562Sgshapiro break; 392238032Speter } 392364562Sgshapiro if (lad->lad_name != NULL) 392464562Sgshapiro lmap->ldap_deref = lad->lad_code; 392564562Sgshapiro else 392638032Speter { 392764562Sgshapiro /* bad config line */ 392864562Sgshapiro if (!bitset(MCF_OPTFILE, 392964562Sgshapiro map->map_class->map_cflags)) 393064562Sgshapiro { 393164562Sgshapiro char *ptr; 393264562Sgshapiro 393364562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 393464562Sgshapiro *ptr = '\0'; 393564562Sgshapiro syserr("Deref must be [never|always|search|find] not %s in map %s", 393664562Sgshapiro p, map->map_mname); 393764562Sgshapiro if (ptr != NULL) 393864562Sgshapiro *ptr = ' '; 393964562Sgshapiro return FALSE; 394064562Sgshapiro } 394138032Speter } 394264562Sgshapiro break; 394364562Sgshapiro 394464562Sgshapiro case 's': /* search scope */ 394564562Sgshapiro while (isascii(*++p) && isspace(*p)) 394664562Sgshapiro continue; 394764562Sgshapiro 394864562Sgshapiro if (strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 394964562Sgshapiro p += 11; 395064562Sgshapiro 395164562Sgshapiro for (lss = LDAPSearchScope; 395264562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 395338032Speter { 395464562Sgshapiro if (strncasecmp(p, lss->lss_name, 395564562Sgshapiro strlen(lss->lss_name)) == 0) 395664562Sgshapiro break; 395738032Speter } 395864562Sgshapiro if (lss->lss_name != NULL) 395964562Sgshapiro lmap->ldap_scope = lss->lss_code; 396038032Speter else 396164562Sgshapiro { 396264562Sgshapiro /* bad config line */ 396364562Sgshapiro if (!bitset(MCF_OPTFILE, 396464562Sgshapiro map->map_class->map_cflags)) 396538032Speter { 396638032Speter char *ptr; 396738032Speter 396838032Speter if ((ptr = strchr(p, ' ')) != NULL) 396938032Speter *ptr = '\0'; 397038032Speter syserr("Scope must be [base|one|sub] not %s in map %s", 397138032Speter p, map->map_mname); 397238032Speter if (ptr != NULL) 397338032Speter *ptr = ' '; 397438032Speter return FALSE; 397538032Speter } 397638032Speter } 397738032Speter break; 397838032Speter 397938032Speter case 'h': /* ldap host */ 398038032Speter while (isascii(*++p) && isspace(*p)) 398138032Speter continue; 398264562Sgshapiro lmap->ldap_host = p; 398338032Speter break; 398438032Speter 398538032Speter case 'b': /* search base */ 398638032Speter while (isascii(*++p) && isspace(*p)) 398738032Speter continue; 398864562Sgshapiro lmap->ldap_base = p; 398938032Speter break; 399038032Speter 399138032Speter case 'p': /* ldap port */ 399238032Speter while (isascii(*++p) && isspace(*p)) 399338032Speter continue; 399464562Sgshapiro lmap->ldap_port = atoi(p); 399538032Speter break; 399638032Speter 399738032Speter case 'l': /* time limit */ 399838032Speter while (isascii(*++p) && isspace(*p)) 399938032Speter continue; 400064562Sgshapiro lmap->ldap_timelimit = atoi(p); 400164562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 400238032Speter break; 400338032Speter 400464562Sgshapiro case 'Z': 400564562Sgshapiro while (isascii(*++p) && isspace(*p)) 400664562Sgshapiro continue; 400764562Sgshapiro lmap->ldap_sizelimit = atoi(p); 400864562Sgshapiro break; 400964562Sgshapiro 401064562Sgshapiro case 'd': /* Dn to bind to server as */ 401164562Sgshapiro while (isascii(*++p) && isspace(*p)) 401264562Sgshapiro continue; 401364562Sgshapiro lmap->ldap_binddn = p; 401464562Sgshapiro break; 401564562Sgshapiro 401664562Sgshapiro case 'M': /* Method for binding */ 401764562Sgshapiro while (isascii(*++p) && isspace(*p)) 401864562Sgshapiro continue; 401964562Sgshapiro 402064562Sgshapiro if (strncasecmp(p, "LDAP_AUTH_", 10) == 0) 402164562Sgshapiro p += 10; 402264562Sgshapiro 402364562Sgshapiro for (lam = LDAPAuthMethods; 402464562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 402564562Sgshapiro { 402664562Sgshapiro if (strncasecmp(p, lam->lam_name, 402764562Sgshapiro strlen(lam->lam_name)) == 0) 402864562Sgshapiro break; 402964562Sgshapiro } 403064562Sgshapiro if (lam->lam_name != NULL) 403164562Sgshapiro lmap->ldap_method = lam->lam_code; 403264562Sgshapiro else 403364562Sgshapiro { 403464562Sgshapiro /* bad config line */ 403564562Sgshapiro if (!bitset(MCF_OPTFILE, 403664562Sgshapiro map->map_class->map_cflags)) 403764562Sgshapiro { 403864562Sgshapiro char *ptr; 403964562Sgshapiro 404064562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 404164562Sgshapiro *ptr = '\0'; 404264562Sgshapiro syserr("Method for binding must be [none|simple|krbv4] not %s in map %s", 404364562Sgshapiro p, map->map_mname); 404464562Sgshapiro if (ptr != NULL) 404564562Sgshapiro *ptr = ' '; 404664562Sgshapiro return FALSE; 404764562Sgshapiro } 404864562Sgshapiro } 404964562Sgshapiro 405064562Sgshapiro break; 405164562Sgshapiro 405264562Sgshapiro /* 405364562Sgshapiro ** This is a string that is dependent on the 405464562Sgshapiro ** method used defined above. 405564562Sgshapiro */ 405664562Sgshapiro 405764562Sgshapiro case 'P': /* Secret password for binding */ 405864562Sgshapiro while (isascii(*++p) && isspace(*p)) 405964562Sgshapiro continue; 406064562Sgshapiro lmap->ldap_secret = p; 406164562Sgshapiro secretread = FALSE; 406264562Sgshapiro break; 406364562Sgshapiro 406464562Sgshapiro default: 406564562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 406664562Sgshapiro break; 406738032Speter } 406838032Speter 406964562Sgshapiro /* need to account for quoted strings here */ 407064562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 407138032Speter { 407238032Speter if (*p == '"') 407338032Speter { 407438032Speter while (*++p != '"' && *p != '\0') 407538032Speter continue; 407638032Speter if (*p != '\0') 407738032Speter p++; 407838032Speter } 407938032Speter else 408038032Speter p++; 408138032Speter } 408238032Speter 408338032Speter if (*p != '\0') 408438032Speter *p++ = '\0'; 408538032Speter } 408638032Speter 408738032Speter if (map->map_app != NULL) 408864562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 408938032Speter if (map->map_tapp != NULL) 409064562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 409138032Speter 409238032Speter /* 409342575Speter ** We need to swallow up all the stuff into a struct 409442575Speter ** and dump it into map->map_dbptr1 409538032Speter */ 409638032Speter 409764562Sgshapiro if (lmap->ldap_host != NULL && 409864562Sgshapiro (LDAPDefaults == NULL || 409964562Sgshapiro LDAPDefaults == lmap || 410064562Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 410164562Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 410264562Sgshapiro map->map_domain = lmap->ldap_host; 410364562Sgshapiro 410464562Sgshapiro if (lmap->ldap_binddn != NULL && 410564562Sgshapiro (LDAPDefaults == NULL || 410664562Sgshapiro LDAPDefaults == lmap || 410764562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 410864562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 410964562Sgshapiro 411064562Sgshapiro if (lmap->ldap_secret != NULL && 411164562Sgshapiro (LDAPDefaults == NULL || 411264562Sgshapiro LDAPDefaults == lmap || 411364562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 411438032Speter { 411564562Sgshapiro FILE *sfd; 411664562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 411738032Speter 411864562Sgshapiro if (DontLockReadFiles) 411964562Sgshapiro sff |= SFF_NOLOCK; 412038032Speter 412164562Sgshapiro /* need to use method to map secret to passwd string */ 412264562Sgshapiro switch (lmap->ldap_method) 412364562Sgshapiro { 412464562Sgshapiro case LDAP_AUTH_NONE: 412564562Sgshapiro /* Do nothing */ 412664562Sgshapiro break; 412738032Speter 412864562Sgshapiro case LDAP_AUTH_SIMPLE: 412938032Speter 413064562Sgshapiro /* 413164562Sgshapiro ** Secret is the name of a file with 413264562Sgshapiro ** the first line as the password. 413364562Sgshapiro */ 413464562Sgshapiro 413564562Sgshapiro /* Already read in the secret? */ 413664562Sgshapiro if (secretread) 413764562Sgshapiro break; 413864562Sgshapiro 413964562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 414064562Sgshapiro O_RDONLY, 0, sff); 414164562Sgshapiro if (sfd == NULL) 414264562Sgshapiro { 414364562Sgshapiro syserr("LDAP map: cannot open secret %s", 414464562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 414564562Sgshapiro return FALSE; 414664562Sgshapiro } 414764562Sgshapiro lmap->ldap_secret = sfgets(m_tmp, LDAPMAP_MAX_PASSWD, 414866494Sgshapiro sfd, TimeOuts.to_fileopen, 414966494Sgshapiro "ldapmap_parseargs"); 415064562Sgshapiro (void) fclose(sfd); 415164562Sgshapiro if (lmap->ldap_secret != NULL && 415264562Sgshapiro strlen(m_tmp) > 0) 415364562Sgshapiro { 415464562Sgshapiro /* chomp newline */ 415564562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 415664562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 415764562Sgshapiro 415864562Sgshapiro lmap->ldap_secret = m_tmp; 415964562Sgshapiro } 416064562Sgshapiro break; 416164562Sgshapiro 416264562Sgshapiro# ifdef LDAP_AUTH_KRBV4 416364562Sgshapiro case LDAP_AUTH_KRBV4: 416464562Sgshapiro 416564562Sgshapiro /* 416664562Sgshapiro ** Secret is where the ticket file is 416764562Sgshapiro ** stashed 416864562Sgshapiro */ 416964562Sgshapiro 417064562Sgshapiro snprintf(m_tmp, MAXPATHLEN + LDAPMAP_MAX_PASSWD, 417164562Sgshapiro "KRBTKFILE=%s", 417264562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 417364562Sgshapiro lmap->ldap_secret = m_tmp; 417464562Sgshapiro break; 417564562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 417664562Sgshapiro 417764562Sgshapiro default: /* Should NEVER get here */ 417864562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 417964562Sgshapiro return FALSE; 418064562Sgshapiro break; 418164562Sgshapiro } 418238032Speter } 418338032Speter 418464562Sgshapiro if (lmap->ldap_secret != NULL && 418564562Sgshapiro (LDAPDefaults == NULL || 418664562Sgshapiro LDAPDefaults == lmap || 418764562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 418864562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 418938032Speter 419064562Sgshapiro if (lmap->ldap_base != NULL && 419164562Sgshapiro (LDAPDefaults == NULL || 419264562Sgshapiro LDAPDefaults == lmap || 419364562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 419464562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 419564562Sgshapiro 419664562Sgshapiro /* 419764562Sgshapiro ** Save the server from extra work. If request is for a single 419864562Sgshapiro ** match, tell the server to only return enough records to 419964562Sgshapiro ** determine if there is a single match or not. This can not 420064562Sgshapiro ** be one since the server would only return one and we wouldn't 420164562Sgshapiro ** know if there were others available. 420264562Sgshapiro */ 420364562Sgshapiro 420464562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 420564562Sgshapiro lmap->ldap_sizelimit = 2; 420664562Sgshapiro 420764562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 420864562Sgshapiro if (lmap == LDAPDefaults) 420964562Sgshapiro return TRUE; 421064562Sgshapiro 421164562Sgshapiro if (lmap->ldap_filter != NULL) 421264562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 421338032Speter else 421438032Speter { 421538032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 421638032Speter { 421738032Speter syserr("No filter given in map %s", map->map_mname); 421838032Speter return FALSE; 421938032Speter } 422038032Speter } 422164562Sgshapiro 422264562Sgshapiro if (lmap->ldap_attr[0] != NULL) 422338032Speter { 422464562Sgshapiro i = 0; 422564562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 422664562Sgshapiro lmap->ldap_attr[0] = NULL; 422764562Sgshapiro 422864562Sgshapiro while (p != NULL) 422938032Speter { 423064562Sgshapiro char *v; 423164562Sgshapiro 423264562Sgshapiro while (isascii(*p) && isspace(*p)) 423364562Sgshapiro p++; 423464562Sgshapiro if (*p == '\0') 423564562Sgshapiro break; 423664562Sgshapiro v = p; 423764562Sgshapiro p = strchr(v, ','); 423864562Sgshapiro if (p != NULL) 423964562Sgshapiro *p++ = '\0'; 424064562Sgshapiro 424164562Sgshapiro if (i == LDAPMAP_MAX_ATTR) 424264562Sgshapiro { 424364562Sgshapiro syserr("Too many return attributes in %s (max %d)", 424464562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 424564562Sgshapiro return FALSE; 424664562Sgshapiro } 424764562Sgshapiro if (*v != '\0') 424864562Sgshapiro lmap->ldap_attr[i++] = newstr(v); 424938032Speter } 425064562Sgshapiro lmap->ldap_attr[i] = NULL; 425138032Speter } 425238032Speter 425338032Speter map->map_db1 = (ARBPTR_T) lmap; 425438032Speter return TRUE; 425538032Speter} 425638032Speter 425764562Sgshapiro/* 425864562Sgshapiro** LDAPMAP_CLEAR -- set default values for LDAPMAP_STRUCT 425964562Sgshapiro** 426064562Sgshapiro** Parameters: 426164562Sgshapiro** lmap -- pointer to LDAPMAP_STRUCT to clear 426264562Sgshapiro** 426364562Sgshapiro** Returns: 426464562Sgshapiro** None. 426564562Sgshapiro** 426664562Sgshapiro*/ 426764562Sgshapiro 426864562Sgshapirostatic void 426964562Sgshapiroldapmap_clear(lmap) 427064562Sgshapiro LDAPMAP_STRUCT *lmap; 427164562Sgshapiro{ 427264562Sgshapiro lmap->ldap_host = NULL; 427364562Sgshapiro lmap->ldap_port = LDAP_PORT; 427464562Sgshapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 427564562Sgshapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 427664562Sgshapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 427764562Sgshapiro# ifdef LDAP_REFERRALS 427864562Sgshapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 427964562Sgshapiro# else /* LDAP_REFERRALS */ 428064562Sgshapiro lmap->ldap_options = 0; 428164562Sgshapiro# endif /* LDAP_REFERRALS */ 428264562Sgshapiro lmap->ldap_binddn = NULL; 428364562Sgshapiro lmap->ldap_secret = NULL; 428464562Sgshapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 428564562Sgshapiro lmap->ldap_base = NULL; 428664562Sgshapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 428764562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 428864562Sgshapiro lmap->ldap_timeout.tv_sec = 0; 428964562Sgshapiro lmap->ldap_timeout.tv_usec = 0; 429064562Sgshapiro lmap->ldap_ld = NULL; 429164562Sgshapiro lmap->ldap_filter = NULL; 429264562Sgshapiro lmap->ldap_attr[0] = NULL; 429364562Sgshapiro lmap->ldap_res = NULL; 429464562Sgshapiro} 429538032Speter/* 429664562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 429764562Sgshapiro** 429864562Sgshapiro** Parameters: 429964562Sgshapiro** spec -- map argument string from LDAPDefaults option 430064562Sgshapiro** 430164562Sgshapiro** Returns: 430264562Sgshapiro** None. 430364562Sgshapiro** 430464562Sgshapiro*/ 430564562Sgshapiro 430664562Sgshapirovoid 430764562Sgshapiroldapmap_set_defaults(spec) 430864562Sgshapiro char *spec; 430964562Sgshapiro{ 431064562Sgshapiro MAP map; 431164562Sgshapiro 431264562Sgshapiro /* Allocate and set the default values */ 431364562Sgshapiro if (LDAPDefaults == NULL) 431464562Sgshapiro LDAPDefaults = (LDAPMAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 431564562Sgshapiro ldapmap_clear(LDAPDefaults); 431664562Sgshapiro 431764562Sgshapiro memset(&map, '\0', sizeof map); 431864562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 431964562Sgshapiro 432064562Sgshapiro (void) ldapmap_parseargs(&map, spec); 432164562Sgshapiro 432264562Sgshapiro /* These should never be set in LDAPDefaults */ 432364562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 432464562Sgshapiro map.map_spacesub != SpaceSub || 432564562Sgshapiro map.map_app != NULL || 432664562Sgshapiro map.map_tapp != NULL) 432764562Sgshapiro { 432864562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 432964562Sgshapiro if (map.map_app != NULL) 433064562Sgshapiro { 433164562Sgshapiro free(map.map_app); 433264562Sgshapiro map.map_app = NULL; 433364562Sgshapiro } 433464562Sgshapiro if (map.map_tapp != NULL) 433564562Sgshapiro { 433664562Sgshapiro free(map.map_tapp); 433764562Sgshapiro map.map_tapp = NULL; 433864562Sgshapiro } 433964562Sgshapiro } 434064562Sgshapiro 434164562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 434264562Sgshapiro { 434364562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 434464562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 434564562Sgshapiro LDAPDefaults->ldap_filter = NULL; 434664562Sgshapiro } 434764562Sgshapiro 434864562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 434964562Sgshapiro { 435064562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 435164562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 435264562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 435364562Sgshapiro } 435464562Sgshapiro} 435564562Sgshapiro#endif /* LDAPMAP */ 435664562Sgshapiro/* 435764562Sgshapiro** PH map 435864562Sgshapiro*/ 435964562Sgshapiro 436064562Sgshapiro#ifdef PH_MAP 436164562Sgshapiro 436264562Sgshapiro/* 436364562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 436464562Sgshapiro** This code is intended to replace the so-called "ph mailer". 436564562Sgshapiro** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 436664562Sgshapiro*/ 436764562Sgshapiro 436864562Sgshapiro# include <qiapi.h> 436964562Sgshapiro# include <qicode.h> 437064562Sgshapiro 437164562Sgshapiro/* 437264562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 437364562Sgshapiro*/ 437464562Sgshapiro 437564562Sgshapirobool 437664562Sgshapiroph_map_parseargs(map, args) 437764562Sgshapiro MAP *map; 437864562Sgshapiro char *args; 437964562Sgshapiro{ 438064562Sgshapiro int i; 438164562Sgshapiro register int done; 438264562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 438364562Sgshapiro register char *p = args; 438464562Sgshapiro 438564562Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 438664562Sgshapiro 438764562Sgshapiro /* defaults */ 438864562Sgshapiro pmap->ph_servers = NULL; 438964562Sgshapiro pmap->ph_field_list = NULL; 439064562Sgshapiro pmap->ph_to_server = NULL; 439164562Sgshapiro pmap->ph_from_server = NULL; 439264562Sgshapiro pmap->ph_sockfd = -1; 439364562Sgshapiro pmap->ph_timeout = 0; 439464562Sgshapiro 439564562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 439664562Sgshapiro for (;;) 439764562Sgshapiro { 439864562Sgshapiro while (isascii(*p) && isspace(*p)) 439964562Sgshapiro p++; 440064562Sgshapiro if (*p != '-') 440164562Sgshapiro break; 440264562Sgshapiro switch (*++p) 440364562Sgshapiro { 440464562Sgshapiro case 'N': 440564562Sgshapiro map->map_mflags |= MF_INCLNULL; 440664562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 440764562Sgshapiro break; 440864562Sgshapiro 440964562Sgshapiro case 'O': 441064562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 441164562Sgshapiro break; 441264562Sgshapiro 441364562Sgshapiro case 'o': 441464562Sgshapiro map->map_mflags |= MF_OPTIONAL; 441564562Sgshapiro break; 441664562Sgshapiro 441764562Sgshapiro case 'f': 441864562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 441964562Sgshapiro break; 442064562Sgshapiro 442164562Sgshapiro case 'm': 442264562Sgshapiro map->map_mflags |= MF_MATCHONLY; 442364562Sgshapiro break; 442464562Sgshapiro 442564562Sgshapiro case 'A': 442664562Sgshapiro map->map_mflags |= MF_APPEND; 442764562Sgshapiro break; 442864562Sgshapiro 442964562Sgshapiro case 'q': 443064562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 443164562Sgshapiro break; 443264562Sgshapiro 443364562Sgshapiro case 't': 443464562Sgshapiro map->map_mflags |= MF_NODEFER; 443564562Sgshapiro break; 443664562Sgshapiro 443764562Sgshapiro case 'a': 443864562Sgshapiro map->map_app = ++p; 443964562Sgshapiro break; 444064562Sgshapiro 444164562Sgshapiro case 'T': 444264562Sgshapiro map->map_tapp = ++p; 444364562Sgshapiro break; 444464562Sgshapiro 444564562Sgshapiro#if _FFR_PHMAP_TIMEOUT 444664562Sgshapiro case 'l': 444764562Sgshapiro while (isascii(*++p) && isspace(*p)) 444864562Sgshapiro continue; 444964562Sgshapiro pmap->ph_timeout = atoi(p); 445064562Sgshapiro break; 445164562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 445264562Sgshapiro 445364562Sgshapiro case 'S': 445464562Sgshapiro map->map_spacesub = *++p; 445564562Sgshapiro break; 445664562Sgshapiro 445764562Sgshapiro case 'D': 445864562Sgshapiro map->map_mflags |= MF_DEFER; 445964562Sgshapiro break; 446064562Sgshapiro 446164562Sgshapiro case 'h': /* PH server list */ 446264562Sgshapiro while (isascii(*++p) && isspace(*p)) 446364562Sgshapiro continue; 446464562Sgshapiro pmap->ph_servers = p; 446564562Sgshapiro break; 446664562Sgshapiro 446764562Sgshapiro case 'v': /* fields to search for */ 446864562Sgshapiro while (isascii(*++p) && isspace(*p)) 446964562Sgshapiro continue; 447064562Sgshapiro pmap->ph_field_list = p; 447164562Sgshapiro break; 447264562Sgshapiro 447364562Sgshapiro default: 447464562Sgshapiro syserr("ph_map_parseargs: unknown option -%c\n", *p); 447564562Sgshapiro } 447664562Sgshapiro 447764562Sgshapiro /* try to account for quoted strings */ 447864562Sgshapiro done = isascii(*p) && isspace(*p); 447964562Sgshapiro while (*p != '\0' && !done) 448064562Sgshapiro { 448164562Sgshapiro if (*p == '"') 448264562Sgshapiro { 448364562Sgshapiro while (*++p != '"' && *p != '\0') 448464562Sgshapiro continue; 448564562Sgshapiro if (*p != '\0') 448664562Sgshapiro p++; 448764562Sgshapiro } 448864562Sgshapiro else 448964562Sgshapiro p++; 449064562Sgshapiro done = isascii(*p) && isspace(*p); 449164562Sgshapiro } 449264562Sgshapiro 449364562Sgshapiro if (*p != '\0') 449464562Sgshapiro *p++ = '\0'; 449564562Sgshapiro } 449664562Sgshapiro 449764562Sgshapiro if (map->map_app != NULL) 449864562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 449964562Sgshapiro if (map->map_tapp != NULL) 450064562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 450164562Sgshapiro 450264562Sgshapiro if (pmap->ph_field_list != NULL) 450364562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 450464562Sgshapiro else 450564562Sgshapiro pmap->ph_field_list = DEFAULT_PH_MAP_FIELDS; 450664562Sgshapiro 450764562Sgshapiro if (pmap->ph_servers != NULL) 450864562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 450964562Sgshapiro else 451064562Sgshapiro { 451164562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 451264562Sgshapiro return FALSE; 451364562Sgshapiro } 451464562Sgshapiro 451564562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 451664562Sgshapiro return TRUE; 451764562Sgshapiro} 451864562Sgshapiro 451964562Sgshapiro#if _FFR_PHMAP_TIMEOUT 452064562Sgshapiro/* 452164562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 452264562Sgshapiro*/ 452364562Sgshapiro 452464562Sgshapirostatic void 452564562Sgshapiroph_map_safeclose(map) 452664562Sgshapiro MAP *map; 452764562Sgshapiro{ 452864562Sgshapiro int save_errno = errno; 452964562Sgshapiro PH_MAP_STRUCT *pmap; 453064562Sgshapiro 453164562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 453264562Sgshapiro 453364562Sgshapiro if (pmap->ph_sockfd != -1) 453464562Sgshapiro { 453564562Sgshapiro (void) close(pmap->ph_sockfd); 453664562Sgshapiro pmap->ph_sockfd = -1; 453764562Sgshapiro } 453864562Sgshapiro if (pmap->ph_from_server != NULL) 453964562Sgshapiro { 454064562Sgshapiro (void) fclose(pmap->ph_from_server); 454164562Sgshapiro pmap->ph_from_server = NULL; 454264562Sgshapiro } 454364562Sgshapiro if (pmap->ph_to_server != NULL) 454464562Sgshapiro { 454564562Sgshapiro (void) fclose(pmap->ph_to_server); 454664562Sgshapiro pmap->ph_to_server = NULL; 454764562Sgshapiro } 454864562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 454964562Sgshapiro errno = save_errno; 455064562Sgshapiro} 455164562Sgshapiro 455264562Sgshapirovoid 455364562Sgshapiroph_map_close(map) 455464562Sgshapiro MAP *map; 455564562Sgshapiro{ 455664562Sgshapiro PH_MAP_STRUCT *pmap; 455764562Sgshapiro 455864562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 455964562Sgshapiro (void) fprintf(pmap->ph_to_server, "quit\n"); 456064562Sgshapiro (void) fflush(pmap->ph_to_server); 456164562Sgshapiro ph_map_safeclose(map); 456264562Sgshapiro} 456364562Sgshapiro 456464562Sgshapirostatic jmp_buf PHTimeout; 456564562Sgshapiro 456664562Sgshapiro/* ARGSUSED */ 456764562Sgshapirostatic void 456864562Sgshapiroph_timeout_func(sig_no) 456964562Sgshapiro int sig_no; 457064562Sgshapiro{ 457164562Sgshapiro longjmp(PHTimeout, 1); 457264562Sgshapiro} 457364562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 457464562Sgshapiro/* 457564562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 457664562Sgshapiro*/ 457764562Sgshapiro 457864562Sgshapirovoid 457964562Sgshapiroph_map_close(map) 458064562Sgshapiro MAP *map; 458164562Sgshapiro{ 458264562Sgshapiro PH_MAP_STRUCT *pmap; 458364562Sgshapiro 458464562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 458564562Sgshapiro CloseQi(pmap->ph_to_server, pmap->ph_from_server); 458664562Sgshapiro pmap->ph_to_server = NULL; 458764562Sgshapiro pmap->ph_from_server = NULL; 458864562Sgshapiro} 458964562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 459064562Sgshapiro 459164562Sgshapiro/* 459264562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 459364562Sgshapiro*/ 459464562Sgshapirobool 459564562Sgshapiroph_map_open(map, mode) 459664562Sgshapiro MAP *map; 459764562Sgshapiro int mode; 459864562Sgshapiro{ 459964562Sgshapiro#if !_FFR_PHMAP_TIMEOUT 460064562Sgshapiro int save_errno = 0; 460164562Sgshapiro#endif /* !_FFR_PHMAP_TIMEOUT */ 460264562Sgshapiro int j; 460364562Sgshapiro char *hostlist, *tmp; 460464562Sgshapiro QIR *server_data = NULL; 460564562Sgshapiro PH_MAP_STRUCT *pmap; 460664562Sgshapiro#if _FFR_PHMAP_TIMEOUT 460764562Sgshapiro register EVENT *ev = NULL; 460864562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 460964562Sgshapiro 461064562Sgshapiro if (tTd(38, 2)) 461164562Sgshapiro dprintf("ph_map_open(%s)\n", map->map_mname); 461264562Sgshapiro 461364562Sgshapiro mode &= O_ACCMODE; 461464562Sgshapiro if (mode != O_RDONLY) 461564562Sgshapiro { 461664562Sgshapiro /* issue a pseudo-error message */ 461764562Sgshapiro# ifdef ENOSYS 461864562Sgshapiro errno = ENOSYS; 461964562Sgshapiro# else /* ENOSYS */ 462064562Sgshapiro# ifdef EFTYPE 462164562Sgshapiro errno = EFTYPE; 462264562Sgshapiro# else /* EFTYPE */ 462364562Sgshapiro errno = ENXIO; 462464562Sgshapiro# endif /* EFTYPE */ 462564562Sgshapiro# endif /* ENOSYS */ 462664562Sgshapiro return FALSE; 462764562Sgshapiro } 462864562Sgshapiro 462966494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 463066494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 463166494Sgshapiro { 463266494Sgshapiro if (tTd(9, 1)) 463366494Sgshapiro dprintf("ph_map_open(%s) => DEFERRED\n", 463466494Sgshapiro map->map_mname); 463566494Sgshapiro 463666494Sgshapiro /* 463766494Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 463866494Sgshapiro ** a temporary failure using the bogus map and 463966494Sgshapiro ** map->map_tapp instead of the default permanent error. 464066494Sgshapiro */ 464166494Sgshapiro 464266494Sgshapiro map->map_mflags &= ~MF_DEFER; 464366494Sgshapiro return FALSE; 464466494Sgshapiro } 464566494Sgshapiro 464664562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 464764562Sgshapiro 464864562Sgshapiro hostlist = newstr(pmap->ph_servers); 464964562Sgshapiro tmp = strtok(hostlist, " "); 465064562Sgshapiro do 465164562Sgshapiro { 465264562Sgshapiro#if _FFR_PHMAP_TIMEOUT 465364562Sgshapiro if (pmap->ph_timeout != 0) 465464562Sgshapiro { 465564562Sgshapiro if (setjmp(PHTimeout) != 0) 465664562Sgshapiro { 465764562Sgshapiro ev = NULL; 465864562Sgshapiro if (LogLevel > 1) 465964562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 466064562Sgshapiro "timeout connecting to PH server %.100s", 466164562Sgshapiro tmp); 466264562Sgshapiro# ifdef ETIMEDOUT 466364562Sgshapiro errno = ETIMEDOUT; 466464562Sgshapiro# else /* ETIMEDOUT */ 466566494Sgshapiro errno = EAGAIN; 466664562Sgshapiro# endif /* ETIMEDOUT */ 466764562Sgshapiro goto ph_map_open_abort; 466864562Sgshapiro } 466964562Sgshapiro ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); 467064562Sgshapiro } 467164562Sgshapiro if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) && 467264562Sgshapiro !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server), 467364562Sgshapiro &(pmap->ph_from_server)) && 467464562Sgshapiro fprintf(pmap->ph_to_server, "id sendmail+phmap\n") >= 0 && 467564562Sgshapiro fflush(pmap->ph_to_server) == 0 && 467664562Sgshapiro (server_data = ReadQi(pmap->ph_from_server, &j)) != NULL && 467764562Sgshapiro server_data->code == 200) 467864562Sgshapiro { 467964562Sgshapiro if (ev != NULL) 468064562Sgshapiro clrevent(ev); 468164562Sgshapiro FreeQIR(server_data); 468264562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 468364562Sgshapiro if (OpenQi(tmp, &(pmap->ph_to_server), 468464562Sgshapiro &(pmap->ph_from_server)) >= 0) 468564562Sgshapiro { 468664562Sgshapiro if (fprintf(pmap->ph_to_server, 468764562Sgshapiro "id sendmail+phmap\n") < 0 || 468864562Sgshapiro fflush(pmap->ph_to_server) < 0 || 468964562Sgshapiro (server_data = ReadQi(pmap->ph_from_server, 469064562Sgshapiro &j)) == NULL || 469164562Sgshapiro server_data->code != 200) 469264562Sgshapiro { 469364562Sgshapiro save_errno = errno; 469464562Sgshapiro CloseQi(pmap->ph_to_server, 469564562Sgshapiro pmap->ph_from_server); 469664562Sgshapiro continue; 469764562Sgshapiro } 469864562Sgshapiro if (server_data != NULL) 469964562Sgshapiro FreeQIR(server_data); 470064562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 470164562Sgshapiro free(hostlist); 470264562Sgshapiro return TRUE; 470364562Sgshapiro } 470464562Sgshapiro#if _FFR_PHMAP_TIMEOUT 470564562Sgshapiro ph_map_open_abort: 470664562Sgshapiro if (ev != NULL) 470764562Sgshapiro clrevent(ev); 470864562Sgshapiro ph_map_safeclose(map); 470964562Sgshapiro if (server_data != NULL) 471064562Sgshapiro { 471164562Sgshapiro FreeQIR(server_data); 471264562Sgshapiro server_data = NULL; 471364562Sgshapiro } 471464562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 471564562Sgshapiro save_errno = errno; 471664562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 471764562Sgshapiro } while (tmp = strtok(NULL, " ")); 471864562Sgshapiro 471964562Sgshapiro#if !_FFR_PHMAP_TIMEOUT 472064562Sgshapiro errno = save_errno; 472164562Sgshapiro#endif /* !_FFR_PHMAP_TIMEOUT */ 472266494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 472364562Sgshapiro { 472466494Sgshapiro if (errno == 0) 472564562Sgshapiro errno = EAGAIN; 472666494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 472766494Sgshapiro map->map_mname); 472864562Sgshapiro } 472966494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 473064562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 473166494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 473266494Sgshapiro map->map_mname); 473364562Sgshapiro free(hostlist); 473464562Sgshapiro return FALSE; 473564562Sgshapiro} 473664562Sgshapiro 473764562Sgshapiro/* 473864562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 473964562Sgshapiro*/ 474064562Sgshapiro 474164562Sgshapiro#if _FFR_PHMAP_TIMEOUT 474264562Sgshapiro# define MAX_PH_FIELDS 20 474364562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 474464562Sgshapiro 474564562Sgshapirochar * 474664562Sgshapiroph_map_lookup(map, key, args, pstat) 474764562Sgshapiro MAP *map; 474864562Sgshapiro char *key; 474964562Sgshapiro char **args; 475064562Sgshapiro int *pstat; 475164562Sgshapiro{ 475264562Sgshapiro int j; 475364562Sgshapiro size_t sz; 475464562Sgshapiro char *tmp, *tmp2; 475564562Sgshapiro char *message = NULL, *field = NULL, *fmtkey; 475664562Sgshapiro QIR *server_data = NULL; 475764562Sgshapiro QIR *qirp; 475864562Sgshapiro char keybuf[MAXKEY + 1], fieldbuf[101]; 475964562Sgshapiro#if _FFR_PHMAP_TIMEOUT 476064562Sgshapiro QIR *hold_data[MAX_PH_FIELDS]; 476164562Sgshapiro int hold_data_idx = 0; 476264562Sgshapiro register EVENT *ev = NULL; 476364562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 476464562Sgshapiro PH_MAP_STRUCT *pmap; 476564562Sgshapiro 476664562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 476764562Sgshapiro 476864562Sgshapiro *pstat = EX_OK; 476964562Sgshapiro 477064562Sgshapiro#if _FFR_PHMAP_TIMEOUT 477164562Sgshapiro if (pmap->ph_timeout != 0) 477264562Sgshapiro { 477364562Sgshapiro if (setjmp(PHTimeout) != 0) 477464562Sgshapiro { 477564562Sgshapiro ev = NULL; 477664562Sgshapiro if (LogLevel > 1) 477764562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 477864562Sgshapiro "timeout during PH lookup of %.100s", 477964562Sgshapiro key); 478064562Sgshapiro# ifdef ETIMEDOUT 478164562Sgshapiro errno = ETIMEDOUT; 478264562Sgshapiro# else /* ETIMEDOUT */ 478364562Sgshapiro errno = 0; 478464562Sgshapiro# endif /* ETIMEDOUT */ 478564562Sgshapiro *pstat = EX_TEMPFAIL; 478664562Sgshapiro goto ph_map_lookup_abort; 478764562Sgshapiro } 478864562Sgshapiro ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); 478964562Sgshapiro } 479064562Sgshapiro 479164562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 479264562Sgshapiro /* check all relevant fields */ 479364562Sgshapiro tmp = pmap->ph_field_list; 479464562Sgshapiro do 479564562Sgshapiro { 479664562Sgshapiro#if _FFR_PHMAP_TIMEOUT 479764562Sgshapiro server_data = NULL; 479864562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 479964562Sgshapiro while (isascii(*tmp) && isspace(*tmp)) 480064562Sgshapiro tmp++; 480164562Sgshapiro if (*tmp == '\0') 480264562Sgshapiro break; 480364562Sgshapiro sz = strcspn(tmp, " ") + 1; 480464562Sgshapiro if (sz > sizeof fieldbuf) 480564562Sgshapiro sz = sizeof fieldbuf; 480664562Sgshapiro (void) strlcpy(fieldbuf, tmp, sz); 480764562Sgshapiro field = fieldbuf; 480864562Sgshapiro tmp += sz; 480964562Sgshapiro 481064562Sgshapiro (void) strlcpy(keybuf, key, sizeof keybuf); 481164562Sgshapiro fmtkey = keybuf; 481264562Sgshapiro if (strcmp(field, "alias") == 0) 481364562Sgshapiro { 481464562Sgshapiro /* 481564562Sgshapiro ** for alias lookups, replace any punctuation 481664562Sgshapiro ** characters with '-' 481764562Sgshapiro */ 481864562Sgshapiro 481964562Sgshapiro for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) 482064562Sgshapiro { 482164562Sgshapiro if (isascii(*tmp2) && ispunct(*tmp2)) 482264562Sgshapiro *tmp2 = '-'; 482364562Sgshapiro } 482464562Sgshapiro tmp2 = field; 482564562Sgshapiro } 482664562Sgshapiro else if (strcmp(field,"spacedname") == 0) 482764562Sgshapiro { 482864562Sgshapiro /* 482964562Sgshapiro ** for "spaced" name lookups, replace any 483064562Sgshapiro ** punctuation characters with a space 483164562Sgshapiro */ 483264562Sgshapiro 483364562Sgshapiro for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) 483464562Sgshapiro { 483564562Sgshapiro if (isascii(*tmp2) && ispunct(*tmp2) && 483664562Sgshapiro *tmp2 != '*') 483764562Sgshapiro *tmp2 = ' '; 483864562Sgshapiro } 483964562Sgshapiro tmp2 = &(field[6]); 484064562Sgshapiro } 484164562Sgshapiro else 484264562Sgshapiro tmp2 = field; 484364562Sgshapiro 484464562Sgshapiro if (LogLevel > 9) 484564562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 484664562Sgshapiro "ph_map_lookup: query %s=\"%s\" return email", 484764562Sgshapiro tmp2, fmtkey); 484864562Sgshapiro if (tTd(38, 20)) 484964562Sgshapiro dprintf("ph_map_lookup: query %s=\"%s\" return email\n", 485064562Sgshapiro tmp2, fmtkey); 485164562Sgshapiro 485264562Sgshapiro j = 0; 485364562Sgshapiro 485464562Sgshapiro if (fprintf(pmap->ph_to_server, "query %s=%s return email\n", 485564562Sgshapiro tmp2, fmtkey) < 0) 485664562Sgshapiro message = "qi query command failed"; 485764562Sgshapiro else if (fflush(pmap->ph_to_server) < 0) 485864562Sgshapiro message = "qi fflush failed"; 485964562Sgshapiro else if ((server_data = ReadQi(pmap->ph_from_server, 486064562Sgshapiro &j)) == NULL) 486164562Sgshapiro message = "ReadQi() returned NULL"; 486264562Sgshapiro 486364562Sgshapiro#if _FFR_PHMAP_TIMEOUT 486464562Sgshapiro if ((hold_data[hold_data_idx] = server_data) != NULL) 486564562Sgshapiro { 486664562Sgshapiro /* save pointer for later free() */ 486764562Sgshapiro hold_data_idx++; 486864562Sgshapiro } 486964562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 487064562Sgshapiro 487164562Sgshapiro if (server_data == NULL || 487264562Sgshapiro (server_data->code >= 400 && 487364562Sgshapiro server_data->code < 500)) 487464562Sgshapiro { 487564562Sgshapiro /* temporary failure */ 487664562Sgshapiro *pstat = EX_TEMPFAIL; 487764562Sgshapiro#if _FFR_PHMAP_TIMEOUT 487864562Sgshapiro break; 487964562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 488064562Sgshapiro if (server_data != NULL) 488164562Sgshapiro { 488264562Sgshapiro FreeQIR(server_data); 488364562Sgshapiro server_data = NULL; 488464562Sgshapiro } 488564562Sgshapiro return NULL; 488664562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 488764562Sgshapiro } 488864562Sgshapiro 488964562Sgshapiro /* 489064562Sgshapiro ** if we found a single match, break out. 489164562Sgshapiro ** otherwise, try the next field. 489264562Sgshapiro */ 489364562Sgshapiro 489464562Sgshapiro if (j == 1) 489564562Sgshapiro break; 489664562Sgshapiro 489764562Sgshapiro /* 489864562Sgshapiro ** check for a single response which is an error: 489964562Sgshapiro ** ReadQi() doesn't set j on error responses, 490064562Sgshapiro ** but we should stop here instead of moving on if 490164562Sgshapiro ** it happens (e.g., alias found but email field empty) 490264562Sgshapiro */ 490364562Sgshapiro 490464562Sgshapiro for (qirp = server_data; 490564562Sgshapiro qirp != NULL && qirp->code < 0; 490664562Sgshapiro qirp++) 490764562Sgshapiro { 490864562Sgshapiro if (tTd(38, 20)) 490964562Sgshapiro dprintf("ph_map_lookup: QIR: %d:%d:%d:%s\n", 491064562Sgshapiro qirp->code, qirp->subcode, qirp->field, 491164562Sgshapiro (qirp->message ? qirp->message 491264562Sgshapiro : "[NULL]")); 491364562Sgshapiro if (qirp->code <= -500) 491464562Sgshapiro { 491564562Sgshapiro j = 0; 491664562Sgshapiro goto ph_map_lookup_abort; 491764562Sgshapiro } 491864562Sgshapiro } 491964562Sgshapiro 492064562Sgshapiro#if _FFR_PHMAP_TIMEOUT 492164562Sgshapiro } while (*tmp != '\0' && hold_data_idx < MAX_PH_FIELDS); 492264562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 492364562Sgshapiro } while (*tmp != '\0'); 492464562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 492564562Sgshapiro 492664562Sgshapiro ph_map_lookup_abort: 492764562Sgshapiro#if _FFR_PHMAP_TIMEOUT 492864562Sgshapiro if (ev != NULL) 492964562Sgshapiro clrevent(ev); 493064562Sgshapiro 493164562Sgshapiro /* 493264562Sgshapiro ** Return EX_TEMPFAIL if the timer popped 493364562Sgshapiro ** or we got a temporary PH error 493464562Sgshapiro */ 493564562Sgshapiro 493664562Sgshapiro if (*pstat == EX_TEMPFAIL) 493764562Sgshapiro ph_map_safeclose(map); 493864562Sgshapiro 493964562Sgshapiro /* if we didn't find a single match, bail out */ 494064562Sgshapiro if (*pstat == EX_OK && j != 1) 494164562Sgshapiro *pstat = EX_UNAVAILABLE; 494264562Sgshapiro 494364562Sgshapiro if (*pstat == EX_OK) 494464562Sgshapiro { 494564562Sgshapiro /* 494664562Sgshapiro ** skip leading whitespace and chop at first address 494764562Sgshapiro */ 494864562Sgshapiro 494964562Sgshapiro for (tmp = server_data->message; 495064562Sgshapiro isascii(*tmp) && isspace(*tmp); 495164562Sgshapiro tmp++) 495264562Sgshapiro continue; 495364562Sgshapiro 495464562Sgshapiro for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) 495564562Sgshapiro { 495664562Sgshapiro if (isascii(*tmp2) && isspace(*tmp2)) 495764562Sgshapiro { 495864562Sgshapiro *tmp2 = '\0'; 495964562Sgshapiro break; 496064562Sgshapiro } 496164562Sgshapiro } 496264562Sgshapiro 496364562Sgshapiro if (tTd(38,20)) 496464562Sgshapiro dprintf("ph_map_lookup: %s => %s\n", key, tmp); 496564562Sgshapiro 496664562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 496764562Sgshapiro message = map_rewrite(map, key, strlen(key), NULL); 496864562Sgshapiro else 496964562Sgshapiro message = map_rewrite(map, tmp, strlen(tmp), args); 497064562Sgshapiro } 497164562Sgshapiro 497264562Sgshapiro /* 497364562Sgshapiro ** Deferred free() of returned server_data values 497464562Sgshapiro ** the deferral is to avoid the risk of a free() being 497564562Sgshapiro ** interrupted by the event timer. By now the timeout event 497664562Sgshapiro ** has been cleared and none of the data is still in use. 497764562Sgshapiro */ 497864562Sgshapiro 497964562Sgshapiro while (--hold_data_idx >= 0) 498064562Sgshapiro { 498164562Sgshapiro if (hold_data[hold_data_idx] != NULL) 498264562Sgshapiro FreeQIR(hold_data[hold_data_idx]); 498364562Sgshapiro } 498464562Sgshapiro 498564562Sgshapiro if (*pstat == EX_OK) 498664562Sgshapiro return message; 498764562Sgshapiro 498864562Sgshapiro return NULL; 498964562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 499064562Sgshapiro /* if we didn't find a single match, bail out */ 499164562Sgshapiro if (j != 1) 499264562Sgshapiro { 499364562Sgshapiro *pstat = EX_UNAVAILABLE; 499464562Sgshapiro if (server_data != NULL) 499564562Sgshapiro { 499664562Sgshapiro FreeQIR(server_data); 499764562Sgshapiro server_data = NULL; 499864562Sgshapiro } 499964562Sgshapiro return NULL; 500064562Sgshapiro } 500164562Sgshapiro 500264562Sgshapiro /* 500364562Sgshapiro ** skip leading whitespace and chop at first address 500464562Sgshapiro */ 500564562Sgshapiro 500664562Sgshapiro for (tmp = server_data->message; 500764562Sgshapiro isascii(*tmp) && isspace(*tmp); 500864562Sgshapiro tmp++) 500964562Sgshapiro continue; 501064562Sgshapiro 501164562Sgshapiro for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) 501264562Sgshapiro { 501364562Sgshapiro if (isascii(*tmp2) && isspace(*tmp2)) 501464562Sgshapiro { 501564562Sgshapiro *tmp2 = '\0'; 501664562Sgshapiro break; 501764562Sgshapiro } 501864562Sgshapiro } 501964562Sgshapiro 502064562Sgshapiro if (tTd(38,20)) 502164562Sgshapiro dprintf("ph_map_lookup: %s => %s\n", key, tmp); 502264562Sgshapiro 502364562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 502464562Sgshapiro message = map_rewrite(map, key, strlen(key), NULL); 502564562Sgshapiro else 502664562Sgshapiro message = map_rewrite(map, tmp, strlen(tmp), args); 502764562Sgshapiro if (server_data != NULL) 502864562Sgshapiro { 502964562Sgshapiro FreeQIR(server_data); 503064562Sgshapiro server_data = NULL; 503164562Sgshapiro } 503264562Sgshapiro return message; 503364562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 503464562Sgshapiro} 503564562Sgshapiro#endif /* PH_MAP */ 503664562Sgshapiro/* 503742575Speter** syslog map 503838032Speter*/ 503938032Speter 504038032Speter#define map_prio map_lockfd /* overload field */ 504138032Speter 504238032Speter/* 504342575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 504438032Speter*/ 504538032Speter 504638032Speterbool 504738032Spetersyslog_map_parseargs(map, args) 504838032Speter MAP *map; 504938032Speter char *args; 505038032Speter{ 505138032Speter char *p = args; 505238032Speter char *priority = NULL; 505338032Speter 505464562Sgshapiro /* there is no check whether there is really an argument */ 505564562Sgshapiro while (*p != '\0') 505638032Speter { 505738032Speter while (isascii(*p) && isspace(*p)) 505838032Speter p++; 505938032Speter if (*p != '-') 506038032Speter break; 506164562Sgshapiro ++p; 506264562Sgshapiro if (*p == 'D') 506364562Sgshapiro { 506464562Sgshapiro map->map_mflags |= MF_DEFER; 506564562Sgshapiro ++p; 506664562Sgshapiro } 506764562Sgshapiro else if (*p == 'S') 506864562Sgshapiro { 506964562Sgshapiro map->map_spacesub = *++p; 507064562Sgshapiro if (*p != '\0') 507164562Sgshapiro p++; 507264562Sgshapiro } 507364562Sgshapiro else if (*p == 'L') 507464562Sgshapiro { 507564562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 507664562Sgshapiro continue; 507764562Sgshapiro if (*p == '\0') 507864562Sgshapiro break; 507964562Sgshapiro priority = p; 508064562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 508164562Sgshapiro p++; 508264562Sgshapiro if (*p != '\0') 508364562Sgshapiro *p++ = '\0'; 508464562Sgshapiro } 508564562Sgshapiro else 508664562Sgshapiro { 508764562Sgshapiro syserr("Illegal option %c map syslog", *p); 508864562Sgshapiro ++p; 508964562Sgshapiro } 509038032Speter } 509138032Speter 509238032Speter if (priority == NULL) 509338032Speter map->map_prio = LOG_INFO; 509438032Speter else 509538032Speter { 509638032Speter if (strncasecmp("LOG_", priority, 4) == 0) 509738032Speter priority += 4; 509838032Speter 509938032Speter#ifdef LOG_EMERG 510038032Speter if (strcasecmp("EMERG", priority) == 0) 510138032Speter map->map_prio = LOG_EMERG; 510238032Speter else 510364562Sgshapiro#endif /* LOG_EMERG */ 510438032Speter#ifdef LOG_ALERT 510538032Speter if (strcasecmp("ALERT", priority) == 0) 510638032Speter map->map_prio = LOG_ALERT; 510738032Speter else 510864562Sgshapiro#endif /* LOG_ALERT */ 510938032Speter#ifdef LOG_CRIT 511038032Speter if (strcasecmp("CRIT", priority) == 0) 511138032Speter map->map_prio = LOG_CRIT; 511238032Speter else 511364562Sgshapiro#endif /* LOG_CRIT */ 511438032Speter#ifdef LOG_ERR 511538032Speter if (strcasecmp("ERR", priority) == 0) 511638032Speter map->map_prio = LOG_ERR; 511738032Speter else 511864562Sgshapiro#endif /* LOG_ERR */ 511938032Speter#ifdef LOG_WARNING 512038032Speter if (strcasecmp("WARNING", priority) == 0) 512138032Speter map->map_prio = LOG_WARNING; 512238032Speter else 512364562Sgshapiro#endif /* LOG_WARNING */ 512438032Speter#ifdef LOG_NOTICE 512538032Speter if (strcasecmp("NOTICE", priority) == 0) 512638032Speter map->map_prio = LOG_NOTICE; 512738032Speter else 512864562Sgshapiro#endif /* LOG_NOTICE */ 512938032Speter#ifdef LOG_INFO 513038032Speter if (strcasecmp("INFO", priority) == 0) 513138032Speter map->map_prio = LOG_INFO; 513238032Speter else 513364562Sgshapiro#endif /* LOG_INFO */ 513438032Speter#ifdef LOG_DEBUG 513538032Speter if (strcasecmp("DEBUG", priority) == 0) 513638032Speter map->map_prio = LOG_DEBUG; 513738032Speter else 513864562Sgshapiro#endif /* LOG_DEBUG */ 513938032Speter { 514038032Speter syserr("syslog_map_parseargs: Unknown priority %s\n", 514138032Speter priority); 514238032Speter return FALSE; 514338032Speter } 514438032Speter } 514538032Speter return TRUE; 514638032Speter} 514738032Speter 514838032Speter/* 514942575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 515038032Speter*/ 515138032Speter 515238032Speterchar * 515338032Spetersyslog_map_lookup(map, string, args, statp) 515438032Speter MAP *map; 515538032Speter char *string; 515638032Speter char **args; 515738032Speter int *statp; 515838032Speter{ 515938032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 516038032Speter 516138032Speter if (ptr != NULL) 516238032Speter { 516338032Speter if (tTd(38, 20)) 516464562Sgshapiro dprintf("syslog_map_lookup(%s (priority %d): %s\n", 516564562Sgshapiro map->map_mname, map->map_prio, ptr); 516638032Speter 516738032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 516838032Speter } 516938032Speter 517038032Speter *statp = EX_OK; 517138032Speter return ""; 517238032Speter} 517338032Speter 517438032Speter/* 517538032Speter** HESIOD Modules 517638032Speter*/ 517738032Speter 517838032Speter#ifdef HESIOD 517938032Speter 518038032Speterbool 518138032Speterhes_map_open(map, mode) 518238032Speter MAP *map; 518338032Speter int mode; 518438032Speter{ 518538032Speter if (tTd(38, 2)) 518664562Sgshapiro dprintf("hes_map_open(%s, %s, %d)\n", 518738032Speter map->map_mname, map->map_file, mode); 518838032Speter 518938032Speter if (mode != O_RDONLY) 519038032Speter { 519138032Speter /* issue a pseudo-error message */ 519264562Sgshapiro# ifdef ENOSYS 519338032Speter errno = ENOSYS; 519464562Sgshapiro# else /* ENOSYS */ 519564562Sgshapiro# ifdef EFTYPE 519638032Speter errno = EFTYPE; 519764562Sgshapiro# else /* EFTYPE */ 519838032Speter errno = ENXIO; 519964562Sgshapiro# endif /* EFTYPE */ 520064562Sgshapiro# endif /* ENOSYS */ 520138032Speter return FALSE; 520238032Speter } 520338032Speter 520464562Sgshapiro# ifdef HESIOD_INIT 520538032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 520638032Speter return TRUE; 520738032Speter 520838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 520964562Sgshapiro syserr("421 4.0.0 cannot initialize Hesiod map (%s)", 521038032Speter errstring(errno)); 521138032Speter return FALSE; 521264562Sgshapiro# else /* HESIOD_INIT */ 521338032Speter if (hes_error() == HES_ER_UNINIT) 521438032Speter hes_init(); 521538032Speter switch (hes_error()) 521638032Speter { 521738032Speter case HES_ER_OK: 521838032Speter case HES_ER_NOTFOUND: 521938032Speter return TRUE; 522038032Speter } 522138032Speter 522238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 522364562Sgshapiro syserr("421 4.0.0 cannot initialize Hesiod map (%d)", hes_error()); 522438032Speter 522538032Speter return FALSE; 522664562Sgshapiro# endif /* HESIOD_INIT */ 522738032Speter} 522838032Speter 522938032Speterchar * 523038032Speterhes_map_lookup(map, name, av, statp) 523138032Speter MAP *map; 523238032Speter char *name; 523338032Speter char **av; 523438032Speter int *statp; 523538032Speter{ 523638032Speter char **hp; 523738032Speter 523838032Speter if (tTd(38, 20)) 523964562Sgshapiro dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 524038032Speter 524138032Speter if (name[0] == '\\') 524238032Speter { 524338032Speter char *np; 524438032Speter int nl; 524538032Speter char nbuf[MAXNAME]; 524638032Speter 524738032Speter nl = strlen(name); 524838032Speter if (nl < sizeof nbuf - 1) 524938032Speter np = nbuf; 525038032Speter else 525138032Speter np = xalloc(strlen(name) + 2); 525238032Speter np[0] = '\\'; 525364562Sgshapiro (void) strlcpy(&np[1], name, (sizeof nbuf) - 1); 525464562Sgshapiro# ifdef HESIOD_INIT 525538032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 525664562Sgshapiro# else /* HESIOD_INIT */ 525738032Speter hp = hes_resolve(np, map->map_file); 525864562Sgshapiro# endif /* HESIOD_INIT */ 525938032Speter if (np != nbuf) 526038032Speter free(np); 526138032Speter } 526238032Speter else 526338032Speter { 526464562Sgshapiro# ifdef HESIOD_INIT 526538032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 526664562Sgshapiro# else /* HESIOD_INIT */ 526738032Speter hp = hes_resolve(name, map->map_file); 526864562Sgshapiro# endif /* HESIOD_INIT */ 526938032Speter } 527064562Sgshapiro# ifdef HESIOD_INIT 527138032Speter if (hp == NULL) 527238032Speter return NULL; 527338032Speter if (*hp == NULL) 527438032Speter { 527538032Speter hesiod_free_list(HesiodContext, hp); 527638032Speter switch (errno) 527738032Speter { 527838032Speter case ENOENT: 527938032Speter *statp = EX_NOTFOUND; 528038032Speter break; 528138032Speter case ECONNREFUSED: 528238032Speter case EMSGSIZE: 528338032Speter *statp = EX_TEMPFAIL; 528438032Speter break; 528538032Speter case ENOMEM: 528638032Speter default: 528738032Speter *statp = EX_UNAVAILABLE; 528838032Speter break; 528938032Speter } 529038032Speter return NULL; 529138032Speter } 529264562Sgshapiro# else /* HESIOD_INIT */ 529338032Speter if (hp == NULL || hp[0] == NULL) 529438032Speter { 529538032Speter switch (hes_error()) 529638032Speter { 529738032Speter case HES_ER_OK: 529838032Speter *statp = EX_OK; 529938032Speter break; 530038032Speter 530138032Speter case HES_ER_NOTFOUND: 530238032Speter *statp = EX_NOTFOUND; 530338032Speter break; 530438032Speter 530538032Speter case HES_ER_CONFIG: 530638032Speter *statp = EX_UNAVAILABLE; 530738032Speter break; 530838032Speter 530938032Speter case HES_ER_NET: 531038032Speter *statp = EX_TEMPFAIL; 531138032Speter break; 531238032Speter } 531338032Speter return NULL; 531438032Speter } 531564562Sgshapiro# endif /* HESIOD_INIT */ 531638032Speter 531738032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 531838032Speter return map_rewrite(map, name, strlen(name), NULL); 531938032Speter else 532038032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 532138032Speter} 532238032Speter 532364562Sgshapiro#endif /* HESIOD */ 532438032Speter/* 532538032Speter** NeXT NETINFO Modules 532638032Speter*/ 532738032Speter 532838032Speter#if NETINFO 532938032Speter 533038032Speter# define NETINFO_DEFAULT_DIR "/aliases" 533138032Speter# define NETINFO_DEFAULT_PROPERTY "members" 533238032Speter 533338032Speter/* 533438032Speter** NI_MAP_OPEN -- open NetInfo Aliases 533538032Speter*/ 533638032Speter 533738032Speterbool 533838032Speterni_map_open(map, mode) 533938032Speter MAP *map; 534038032Speter int mode; 534138032Speter{ 534238032Speter if (tTd(38, 2)) 534364562Sgshapiro dprintf("ni_map_open(%s, %s, %d)\n", 534438032Speter map->map_mname, map->map_file, mode); 534538032Speter mode &= O_ACCMODE; 534638032Speter 534738032Speter if (*map->map_file == '\0') 534838032Speter map->map_file = NETINFO_DEFAULT_DIR; 534938032Speter 535038032Speter if (map->map_valcolnm == NULL) 535138032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 535238032Speter 535338032Speter if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 535438032Speter map->map_coldelim = ','; 535538032Speter 535638032Speter return TRUE; 535738032Speter} 535838032Speter 535938032Speter 536038032Speter/* 536138032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 536238032Speter*/ 536338032Speter 536438032Speterchar * 536538032Speterni_map_lookup(map, name, av, statp) 536638032Speter MAP *map; 536738032Speter char *name; 536838032Speter char **av; 536938032Speter int *statp; 537038032Speter{ 537138032Speter char *res; 537238032Speter char *propval; 537338032Speter 537438032Speter if (tTd(38, 20)) 537564562Sgshapiro dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 537638032Speter 537738032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 537838032Speter map->map_valcolnm, map->map_coldelim); 537938032Speter 538038032Speter if (propval == NULL) 538138032Speter return NULL; 538238032Speter 538338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 538438032Speter res = map_rewrite(map, name, strlen(name), NULL); 538538032Speter else 538638032Speter res = map_rewrite(map, propval, strlen(propval), av); 538738032Speter free(propval); 538838032Speter return res; 538938032Speter} 539038032Speter 539138032Speter 539264562Sgshapirostatic bool 539338032Speterni_getcanonname(name, hbsize, statp) 539438032Speter char *name; 539538032Speter int hbsize; 539638032Speter int *statp; 539738032Speter{ 539838032Speter char *vptr; 539938032Speter char *ptr; 540038032Speter char nbuf[MAXNAME + 1]; 540138032Speter 540238032Speter if (tTd(38, 20)) 540364562Sgshapiro dprintf("ni_getcanonname(%s)\n", name); 540438032Speter 540564562Sgshapiro if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 540638032Speter { 540738032Speter *statp = EX_UNAVAILABLE; 540838032Speter return FALSE; 540938032Speter } 541038032Speter shorten_hostname(nbuf); 541138032Speter 541238032Speter /* we only accept single token search key */ 541338032Speter if (strchr(nbuf, '.')) 541438032Speter { 541538032Speter *statp = EX_NOHOST; 541638032Speter return FALSE; 541738032Speter } 541838032Speter 541938032Speter /* Do the search */ 542038032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 542138032Speter 542238032Speter if (vptr == NULL) 542338032Speter { 542438032Speter *statp = EX_NOHOST; 542538032Speter return FALSE; 542638032Speter } 542738032Speter 542838032Speter /* Only want the first machine name */ 542938032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 543038032Speter *ptr = '\0'; 543138032Speter 543238032Speter if (hbsize >= strlen(vptr)) 543338032Speter { 543464562Sgshapiro (void) strlcpy(name, vptr, hbsize); 543564562Sgshapiro free(vptr); 543638032Speter *statp = EX_OK; 543738032Speter return TRUE; 543838032Speter } 543938032Speter *statp = EX_UNAVAILABLE; 544038032Speter free(vptr); 544138032Speter return FALSE; 544238032Speter} 544338032Speter 544438032Speter 544538032Speter/* 544638032Speter** NI_PROPVAL -- NetInfo property value lookup routine 544738032Speter** 544838032Speter** Parameters: 544938032Speter** keydir -- the NetInfo directory name in which to search 545038032Speter** for the key. 545138032Speter** keyprop -- the name of the property in which to find the 545238032Speter** property we are interested. Defaults to "name". 545338032Speter** keyval -- the value for which we are really searching. 545438032Speter** valprop -- the property name for the value in which we 545538032Speter** are interested. 545638032Speter** sepchar -- if non-nil, this can be multiple-valued, and 545738032Speter** we should return a string separated by this 545838032Speter** character. 545938032Speter** 546038032Speter** Returns: 546138032Speter** NULL -- if: 546238032Speter** 1. the directory is not found 546338032Speter** 2. the property name is not found 546438032Speter** 3. the property contains multiple values 546564562Sgshapiro** 4. some error occurred 546638032Speter** else -- the value of the lookup. 546738032Speter** 546838032Speter** Example: 546938032Speter** To search for an alias value, use: 547038032Speter** ni_propval("/aliases", "name", aliasname, "members", ',') 547138032Speter** 547238032Speter** Notes: 547364562Sgshapiro** Caller should free the return value of ni_proval 547438032Speter*/ 547538032Speter 547638032Speter# include <netinfo/ni.h> 547738032Speter 547864562Sgshapiro# define LOCAL_NETINFO_DOMAIN "." 547964562Sgshapiro# define PARENT_NETINFO_DOMAIN ".." 548064562Sgshapiro# define MAX_NI_LEVELS 256 548138032Speter 548238032Speterchar * 548338032Speterni_propval(keydir, keyprop, keyval, valprop, sepchar) 548438032Speter char *keydir; 548538032Speter char *keyprop; 548638032Speter char *keyval; 548738032Speter char *valprop; 548838032Speter int sepchar; 548938032Speter{ 549038032Speter char *propval = NULL; 549138032Speter int i; 549264562Sgshapiro int j, alen, l; 549338032Speter void *ni = NULL; 549438032Speter void *lastni = NULL; 549538032Speter ni_status nis; 549638032Speter ni_id nid; 549738032Speter ni_namelist ninl; 549838032Speter register char *p; 549938032Speter char keybuf[1024]; 550038032Speter 550138032Speter /* 550238032Speter ** Create the full key from the two parts. 550338032Speter ** 550438032Speter ** Note that directory can end with, e.g., "name=" to specify 550538032Speter ** an alternate search property. 550638032Speter */ 550738032Speter 550838032Speter i = strlen(keydir) + strlen(keyval) + 2; 550938032Speter if (keyprop != NULL) 551038032Speter i += strlen(keyprop) + 1; 551164562Sgshapiro if (i >= sizeof keybuf) 551238032Speter return NULL; 551364562Sgshapiro (void) strlcpy(keybuf, keydir, sizeof keybuf); 551464562Sgshapiro (void) strlcat(keybuf, "/", sizeof keybuf); 551538032Speter if (keyprop != NULL) 551638032Speter { 551764562Sgshapiro (void) strlcat(keybuf, keyprop, sizeof keybuf); 551864562Sgshapiro (void) strlcat(keybuf, "=", sizeof keybuf); 551938032Speter } 552064562Sgshapiro (void) strlcat(keybuf, keyval, sizeof keybuf); 552138032Speter 552238032Speter if (tTd(38, 21)) 552364562Sgshapiro dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", 552438032Speter keydir, keyprop, keyval, valprop, sepchar, keybuf); 552538032Speter /* 552638032Speter ** If the passed directory and property name are found 552738032Speter ** in one of netinfo domains we need to search (starting 552838032Speter ** from the local domain moving all the way back to the 552938032Speter ** root domain) set propval to the property's value 553038032Speter ** and return it. 553138032Speter */ 553238032Speter 553338032Speter for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) 553438032Speter { 553538032Speter if (i == 0) 553638032Speter { 553738032Speter nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 553838032Speter if (tTd(38, 20)) 553964562Sgshapiro dprintf("ni_open(LOCAL) = %d\n", nis); 554038032Speter } 554138032Speter else 554238032Speter { 554338032Speter if (lastni != NULL) 554438032Speter ni_free(lastni); 554538032Speter lastni = ni; 554638032Speter nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 554738032Speter if (tTd(38, 20)) 554864562Sgshapiro dprintf("ni_open(PARENT) = %d\n", nis); 554938032Speter } 555038032Speter 555138032Speter /* 555238032Speter ** Don't bother if we didn't get a handle on a 555338032Speter ** proper domain. This is not necessarily an error. 555438032Speter ** We would get a positive ni_status if, for instance 555538032Speter ** we never found the directory or property and tried 555638032Speter ** to open the parent of the root domain! 555738032Speter */ 555838032Speter 555938032Speter if (nis != 0) 556038032Speter break; 556138032Speter 556238032Speter /* 556338032Speter ** Find the path to the server information. 556438032Speter */ 556538032Speter 556638032Speter if (ni_pathsearch(ni, &nid, keybuf) != 0) 556738032Speter continue; 556838032Speter 556938032Speter /* 557038032Speter ** Find associated value information. 557138032Speter */ 557238032Speter 557338032Speter if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 557438032Speter continue; 557538032Speter 557638032Speter if (tTd(38, 20)) 557764562Sgshapiro dprintf("ni_lookupprop: len=%d\n", 557864562Sgshapiro ninl.ni_namelist_len); 557964562Sgshapiro 558038032Speter /* 558138032Speter ** See if we have an acceptable number of values. 558238032Speter */ 558338032Speter 558438032Speter if (ninl.ni_namelist_len <= 0) 558538032Speter continue; 558638032Speter 558738032Speter if (sepchar == '\0' && ninl.ni_namelist_len > 1) 558838032Speter { 558938032Speter ni_namelist_free(&ninl); 559038032Speter continue; 559138032Speter } 559238032Speter 559338032Speter /* 559438032Speter ** Calculate number of bytes needed and build result 559538032Speter */ 559638032Speter 559738032Speter alen = 1; 559838032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 559938032Speter alen += strlen(ninl.ni_namelist_val[j]) + 1; 560038032Speter propval = p = xalloc(alen); 560138032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 560238032Speter { 560364562Sgshapiro (void) strlcpy(p, ninl.ni_namelist_val[j], alen); 560464562Sgshapiro l = strlen(p); 560564562Sgshapiro p += l; 560638032Speter *p++ = sepchar; 560764562Sgshapiro alen -= l + 1; 560838032Speter } 560938032Speter *--p = '\0'; 561038032Speter 561138032Speter ni_namelist_free(&ninl); 561238032Speter } 561338032Speter 561438032Speter /* 561538032Speter ** Clean up. 561638032Speter */ 561738032Speter 561838032Speter if (ni != NULL) 561938032Speter ni_free(ni); 562038032Speter if (lastni != NULL && ni != lastni) 562138032Speter ni_free(lastni); 562238032Speter if (tTd(38, 20)) 562364562Sgshapiro dprintf("ni_propval returns: '%s'\n", propval); 562438032Speter 562538032Speter return propval; 562638032Speter} 562738032Speter 562842575Speter#endif /* NETINFO */ 562938032Speter/* 563038032Speter** TEXT (unindexed text file) Modules 563138032Speter** 563238032Speter** This code donated by Sun Microsystems. 563338032Speter*/ 563438032Speter 563538032Speter#define map_sff map_lockfd /* overload field */ 563638032Speter 563738032Speter 563838032Speter/* 563938032Speter** TEXT_MAP_OPEN -- open text table 564038032Speter*/ 564138032Speter 564238032Speterbool 564338032Spetertext_map_open(map, mode) 564438032Speter MAP *map; 564538032Speter int mode; 564638032Speter{ 564764562Sgshapiro long sff; 564838032Speter int i; 564938032Speter 565038032Speter if (tTd(38, 2)) 565164562Sgshapiro dprintf("text_map_open(%s, %s, %d)\n", 565238032Speter map->map_mname, map->map_file, mode); 565338032Speter 565438032Speter mode &= O_ACCMODE; 565538032Speter if (mode != O_RDONLY) 565638032Speter { 565738032Speter errno = EPERM; 565838032Speter return FALSE; 565938032Speter } 566038032Speter 566138032Speter if (*map->map_file == '\0') 566238032Speter { 566338032Speter syserr("text map \"%s\": file name required", 566438032Speter map->map_mname); 566538032Speter return FALSE; 566638032Speter } 566738032Speter 566838032Speter if (map->map_file[0] != '/') 566938032Speter { 567038032Speter syserr("text map \"%s\": file name must be fully qualified", 567138032Speter map->map_mname); 567238032Speter return FALSE; 567338032Speter } 567438032Speter 567538032Speter sff = SFF_ROOTOK|SFF_REGONLY; 567664562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 567738032Speter sff |= SFF_NOWLINK; 567864562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 567938032Speter sff |= SFF_SAFEDIRPATH; 568038032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 568138032Speter sff, S_IRUSR, NULL)) != 0) 568238032Speter { 568364562Sgshapiro int save_errno = errno; 568464562Sgshapiro 568538032Speter /* cannot open this map */ 568638032Speter if (tTd(38, 2)) 568764562Sgshapiro dprintf("\tunsafe map file: %d\n", i); 568864562Sgshapiro errno = save_errno; 568938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 569038032Speter syserr("text map \"%s\": unsafe map file %s", 569138032Speter map->map_mname, map->map_file); 569238032Speter return FALSE; 569338032Speter } 569438032Speter 569538032Speter if (map->map_keycolnm == NULL) 569638032Speter map->map_keycolno = 0; 569738032Speter else 569838032Speter { 569938032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 570038032Speter { 570138032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 570238032Speter map->map_mname, map->map_file, 570338032Speter map->map_keycolnm); 570438032Speter return FALSE; 570538032Speter } 570638032Speter map->map_keycolno = atoi(map->map_keycolnm); 570738032Speter } 570838032Speter 570938032Speter if (map->map_valcolnm == NULL) 571038032Speter map->map_valcolno = 0; 571138032Speter else 571238032Speter { 571338032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 571438032Speter { 571538032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 571638032Speter map->map_mname, map->map_file, 571738032Speter map->map_valcolnm); 571838032Speter return FALSE; 571938032Speter } 572038032Speter map->map_valcolno = atoi(map->map_valcolnm); 572138032Speter } 572238032Speter 572338032Speter if (tTd(38, 2)) 572438032Speter { 572564562Sgshapiro dprintf("text_map_open(%s, %s): delimiter = ", 572638032Speter map->map_mname, map->map_file); 572738032Speter if (map->map_coldelim == '\0') 572864562Sgshapiro dprintf("(white space)\n"); 572938032Speter else 573064562Sgshapiro dprintf("%c\n", map->map_coldelim); 573138032Speter } 573238032Speter 573338032Speter map->map_sff = sff; 573438032Speter return TRUE; 573538032Speter} 573638032Speter 573738032Speter 573838032Speter/* 573938032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 574038032Speter*/ 574138032Speter 574238032Speterchar * 574338032Spetertext_map_lookup(map, name, av, statp) 574438032Speter MAP *map; 574538032Speter char *name; 574638032Speter char **av; 574738032Speter int *statp; 574838032Speter{ 574938032Speter char *vp; 575038032Speter auto int vsize; 575138032Speter int buflen; 575238032Speter FILE *f; 575338032Speter char delim; 575438032Speter int key_idx; 575538032Speter bool found_it; 575664562Sgshapiro long sff = map->map_sff; 575738032Speter char search_key[MAXNAME + 1]; 575838032Speter char linebuf[MAXLINE]; 575938032Speter char buf[MAXNAME + 1]; 576038032Speter 576138032Speter found_it = FALSE; 576238032Speter if (tTd(38, 20)) 576364562Sgshapiro dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 576438032Speter 576538032Speter buflen = strlen(name); 576638032Speter if (buflen > sizeof search_key - 1) 576738032Speter buflen = sizeof search_key - 1; 576864562Sgshapiro memmove(search_key, name, buflen); 576938032Speter search_key[buflen] = '\0'; 577038032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 577138032Speter makelower(search_key); 577238032Speter 577338032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 577438032Speter if (f == NULL) 577538032Speter { 577638032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 577738032Speter *statp = EX_UNAVAILABLE; 577838032Speter return NULL; 577938032Speter } 578038032Speter key_idx = map->map_keycolno; 578138032Speter delim = map->map_coldelim; 578238032Speter while (fgets(linebuf, MAXLINE, f) != NULL) 578338032Speter { 578438032Speter char *p; 578538032Speter 578638032Speter /* skip comment line */ 578738032Speter if (linebuf[0] == '#') 578838032Speter continue; 578938032Speter p = strchr(linebuf, '\n'); 579038032Speter if (p != NULL) 579138032Speter *p = '\0'; 579238032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 579338032Speter if (p != NULL && strcasecmp(search_key, p) == 0) 579438032Speter { 579538032Speter found_it = TRUE; 579638032Speter break; 579738032Speter } 579838032Speter } 579964562Sgshapiro (void) fclose(f); 580038032Speter if (!found_it) 580138032Speter { 580238032Speter *statp = EX_NOTFOUND; 580338032Speter return NULL; 580438032Speter } 580538032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 580642575Speter if (vp == NULL) 580742575Speter { 580842575Speter *statp = EX_NOTFOUND; 580942575Speter return NULL; 581042575Speter } 581138032Speter vsize = strlen(vp); 581238032Speter *statp = EX_OK; 581338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 581438032Speter return map_rewrite(map, name, strlen(name), NULL); 581538032Speter else 581638032Speter return map_rewrite(map, vp, vsize, av); 581738032Speter} 581838032Speter 581938032Speter/* 582038032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 582138032Speter*/ 582238032Speter 582364562Sgshapirostatic bool 582438032Spetertext_getcanonname(name, hbsize, statp) 582538032Speter char *name; 582638032Speter int hbsize; 582738032Speter int *statp; 582838032Speter{ 582938032Speter bool found; 583038032Speter FILE *f; 583138032Speter char linebuf[MAXLINE]; 583238032Speter char cbuf[MAXNAME + 1]; 583338032Speter char nbuf[MAXNAME + 1]; 583438032Speter 583538032Speter if (tTd(38, 20)) 583664562Sgshapiro dprintf("text_getcanonname(%s)\n", name); 583738032Speter 583838032Speter if (strlen(name) >= (SIZE_T) sizeof nbuf) 583938032Speter { 584038032Speter *statp = EX_UNAVAILABLE; 584138032Speter return FALSE; 584238032Speter } 584364562Sgshapiro (void) strlcpy(nbuf, name, sizeof nbuf); 584438032Speter shorten_hostname(nbuf); 584538032Speter 584638032Speter f = fopen(HostsFile, "r"); 584738032Speter if (f == NULL) 584838032Speter { 584938032Speter *statp = EX_UNAVAILABLE; 585038032Speter return FALSE; 585138032Speter } 585238032Speter found = FALSE; 585338032Speter while (!found && fgets(linebuf, MAXLINE, f) != NULL) 585438032Speter { 585538032Speter char *p = strpbrk(linebuf, "#\n"); 585638032Speter 585738032Speter if (p != NULL) 585838032Speter *p = '\0'; 585938032Speter if (linebuf[0] != '\0') 586038032Speter found = extract_canonname(nbuf, linebuf, cbuf, sizeof cbuf); 586138032Speter } 586264562Sgshapiro (void) fclose(f); 586338032Speter if (!found) 586438032Speter { 586538032Speter *statp = EX_NOHOST; 586638032Speter return FALSE; 586738032Speter } 586838032Speter 586938032Speter if ((SIZE_T) hbsize >= strlen(cbuf)) 587038032Speter { 587164562Sgshapiro (void) strlcpy(name, cbuf, hbsize); 587238032Speter *statp = EX_OK; 587338032Speter return TRUE; 587438032Speter } 587538032Speter *statp = EX_UNAVAILABLE; 587638032Speter return FALSE; 587738032Speter} 587838032Speter/* 587938032Speter** STAB (Symbol Table) Modules 588038032Speter*/ 588138032Speter 588238032Speter 588338032Speter/* 588438032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 588538032Speter*/ 588638032Speter 588738032Speter/* ARGSUSED2 */ 588838032Speterchar * 588938032Speterstab_map_lookup(map, name, av, pstat) 589038032Speter register MAP *map; 589138032Speter char *name; 589238032Speter char **av; 589338032Speter int *pstat; 589438032Speter{ 589538032Speter register STAB *s; 589638032Speter 589738032Speter if (tTd(38, 20)) 589864562Sgshapiro dprintf("stab_lookup(%s, %s)\n", 589938032Speter map->map_mname, name); 590038032Speter 590138032Speter s = stab(name, ST_ALIAS, ST_FIND); 590238032Speter if (s != NULL) 590364562Sgshapiro return s->s_alias; 590464562Sgshapiro return NULL; 590538032Speter} 590638032Speter 590738032Speter 590838032Speter/* 590938032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 591038032Speter*/ 591138032Speter 591238032Spetervoid 591338032Speterstab_map_store(map, lhs, rhs) 591438032Speter register MAP *map; 591538032Speter char *lhs; 591638032Speter char *rhs; 591738032Speter{ 591838032Speter register STAB *s; 591938032Speter 592038032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 592138032Speter s->s_alias = newstr(rhs); 592238032Speter} 592338032Speter 592438032Speter 592538032Speter/* 592638032Speter** STAB_MAP_OPEN -- initialize (reads data file) 592738032Speter** 592838032Speter** This is a wierd case -- it is only intended as a fallback for 592938032Speter** aliases. For this reason, opens for write (only during a 593038032Speter** "newaliases") always fails, and opens for read open the 593138032Speter** actual underlying text file instead of the database. 593238032Speter*/ 593338032Speter 593438032Speterbool 593538032Speterstab_map_open(map, mode) 593638032Speter register MAP *map; 593738032Speter int mode; 593838032Speter{ 593938032Speter FILE *af; 594064562Sgshapiro long sff; 594138032Speter struct stat st; 594238032Speter 594338032Speter if (tTd(38, 2)) 594464562Sgshapiro dprintf("stab_map_open(%s, %s, %d)\n", 594538032Speter map->map_mname, map->map_file, mode); 594638032Speter 594738032Speter mode &= O_ACCMODE; 594838032Speter if (mode != O_RDONLY) 594938032Speter { 595038032Speter errno = EPERM; 595138032Speter return FALSE; 595238032Speter } 595338032Speter 595438032Speter sff = SFF_ROOTOK|SFF_REGONLY; 595564562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 595638032Speter sff |= SFF_NOWLINK; 595764562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 595838032Speter sff |= SFF_SAFEDIRPATH; 595938032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 596038032Speter if (af == NULL) 596138032Speter return FALSE; 596238032Speter readaliases(map, af, FALSE, FALSE); 596338032Speter 596438032Speter if (fstat(fileno(af), &st) >= 0) 596538032Speter map->map_mtime = st.st_mtime; 596664562Sgshapiro (void) fclose(af); 596738032Speter 596838032Speter return TRUE; 596938032Speter} 597038032Speter/* 597138032Speter** Implicit Modules 597238032Speter** 597338032Speter** Tries several types. For back compatibility of aliases. 597438032Speter*/ 597538032Speter 597638032Speter 597738032Speter/* 597838032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 597938032Speter*/ 598038032Speter 598138032Speterchar * 598238032Speterimpl_map_lookup(map, name, av, pstat) 598338032Speter MAP *map; 598438032Speter char *name; 598538032Speter char **av; 598638032Speter int *pstat; 598738032Speter{ 598838032Speter if (tTd(38, 20)) 598964562Sgshapiro dprintf("impl_map_lookup(%s, %s)\n", 599038032Speter map->map_mname, name); 599138032Speter 599238032Speter#ifdef NEWDB 599338032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 599438032Speter return db_map_lookup(map, name, av, pstat); 599564562Sgshapiro#endif /* NEWDB */ 599638032Speter#ifdef NDBM 599738032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 599838032Speter return ndbm_map_lookup(map, name, av, pstat); 599964562Sgshapiro#endif /* NDBM */ 600038032Speter return stab_map_lookup(map, name, av, pstat); 600138032Speter} 600238032Speter 600338032Speter/* 600438032Speter** IMPL_MAP_STORE -- store in open databases 600538032Speter*/ 600638032Speter 600738032Spetervoid 600838032Speterimpl_map_store(map, lhs, rhs) 600938032Speter MAP *map; 601038032Speter char *lhs; 601138032Speter char *rhs; 601238032Speter{ 601338032Speter if (tTd(38, 12)) 601464562Sgshapiro dprintf("impl_map_store(%s, %s, %s)\n", 601538032Speter map->map_mname, lhs, rhs); 601638032Speter#ifdef NEWDB 601738032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 601838032Speter db_map_store(map, lhs, rhs); 601964562Sgshapiro#endif /* NEWDB */ 602038032Speter#ifdef NDBM 602138032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 602238032Speter ndbm_map_store(map, lhs, rhs); 602364562Sgshapiro#endif /* NDBM */ 602438032Speter stab_map_store(map, lhs, rhs); 602538032Speter} 602638032Speter 602738032Speter/* 602838032Speter** IMPL_MAP_OPEN -- implicit database open 602938032Speter*/ 603038032Speter 603138032Speterbool 603238032Speterimpl_map_open(map, mode) 603338032Speter MAP *map; 603438032Speter int mode; 603538032Speter{ 603638032Speter if (tTd(38, 2)) 603764562Sgshapiro dprintf("impl_map_open(%s, %s, %d)\n", 603838032Speter map->map_mname, map->map_file, mode); 603938032Speter 604038032Speter mode &= O_ACCMODE; 604138032Speter#ifdef NEWDB 604238032Speter map->map_mflags |= MF_IMPL_HASH; 604338032Speter if (hash_map_open(map, mode)) 604438032Speter { 604538032Speter# ifdef NDBM_YP_COMPAT 604638032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 604764562Sgshapiro# endif /* NDBM_YP_COMPAT */ 604838032Speter return TRUE; 604938032Speter } 605038032Speter else 605138032Speter map->map_mflags &= ~MF_IMPL_HASH; 605264562Sgshapiro#endif /* NEWDB */ 605338032Speter#ifdef NDBM 605438032Speter map->map_mflags |= MF_IMPL_NDBM; 605538032Speter if (ndbm_map_open(map, mode)) 605638032Speter { 605738032Speter return TRUE; 605838032Speter } 605938032Speter else 606038032Speter map->map_mflags &= ~MF_IMPL_NDBM; 606164562Sgshapiro#endif /* NDBM */ 606238032Speter 606338032Speter#if defined(NEWDB) || defined(NDBM) 606438032Speter if (Verbose) 606538032Speter message("WARNING: cannot open alias database %s%s", 606638032Speter map->map_file, 606738032Speter mode == O_RDONLY ? "; reading text version" : ""); 606864562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 606938032Speter if (mode != O_RDONLY) 607038032Speter usrerr("Cannot rebuild aliases: no database format defined"); 607164562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 607238032Speter 607338032Speter if (mode == O_RDONLY) 607438032Speter return stab_map_open(map, mode); 607538032Speter else 607638032Speter return FALSE; 607738032Speter} 607838032Speter 607938032Speter 608038032Speter/* 608138032Speter** IMPL_MAP_CLOSE -- close any open database(s) 608238032Speter*/ 608338032Speter 608438032Spetervoid 608538032Speterimpl_map_close(map) 608638032Speter MAP *map; 608738032Speter{ 608838032Speter if (tTd(38, 9)) 608964562Sgshapiro dprintf("impl_map_close(%s, %s, %lx)\n", 609038032Speter map->map_mname, map->map_file, map->map_mflags); 609138032Speter#ifdef NEWDB 609238032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 609338032Speter { 609438032Speter db_map_close(map); 609538032Speter map->map_mflags &= ~MF_IMPL_HASH; 609638032Speter } 609764562Sgshapiro#endif /* NEWDB */ 609838032Speter 609938032Speter#ifdef NDBM 610038032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 610138032Speter { 610238032Speter ndbm_map_close(map); 610338032Speter map->map_mflags &= ~MF_IMPL_NDBM; 610438032Speter } 610564562Sgshapiro#endif /* NDBM */ 610638032Speter} 610738032Speter/* 610838032Speter** User map class. 610938032Speter** 611038032Speter** Provides access to the system password file. 611138032Speter*/ 611238032Speter 611338032Speter/* 611438032Speter** USER_MAP_OPEN -- open user map 611538032Speter** 611638032Speter** Really just binds field names to field numbers. 611738032Speter*/ 611838032Speter 611938032Speterbool 612038032Speteruser_map_open(map, mode) 612138032Speter MAP *map; 612238032Speter int mode; 612338032Speter{ 612438032Speter if (tTd(38, 2)) 612564562Sgshapiro dprintf("user_map_open(%s, %d)\n", 612638032Speter map->map_mname, mode); 612738032Speter 612838032Speter mode &= O_ACCMODE; 612938032Speter if (mode != O_RDONLY) 613038032Speter { 613138032Speter /* issue a pseudo-error message */ 613238032Speter#ifdef ENOSYS 613338032Speter errno = ENOSYS; 613464562Sgshapiro#else /* ENOSYS */ 613538032Speter# ifdef EFTYPE 613638032Speter errno = EFTYPE; 613764562Sgshapiro# else /* EFTYPE */ 613838032Speter errno = ENXIO; 613964562Sgshapiro# endif /* EFTYPE */ 614064562Sgshapiro#endif /* ENOSYS */ 614138032Speter return FALSE; 614238032Speter } 614338032Speter if (map->map_valcolnm == NULL) 614464562Sgshapiro /* EMPTY */ 614538032Speter /* nothing */ ; 614638032Speter else if (strcasecmp(map->map_valcolnm, "name") == 0) 614738032Speter map->map_valcolno = 1; 614838032Speter else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 614938032Speter map->map_valcolno = 2; 615038032Speter else if (strcasecmp(map->map_valcolnm, "uid") == 0) 615138032Speter map->map_valcolno = 3; 615238032Speter else if (strcasecmp(map->map_valcolnm, "gid") == 0) 615338032Speter map->map_valcolno = 4; 615438032Speter else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 615538032Speter map->map_valcolno = 5; 615638032Speter else if (strcasecmp(map->map_valcolnm, "dir") == 0) 615738032Speter map->map_valcolno = 6; 615838032Speter else if (strcasecmp(map->map_valcolnm, "shell") == 0) 615938032Speter map->map_valcolno = 7; 616038032Speter else 616138032Speter { 616238032Speter syserr("User map %s: unknown column name %s", 616338032Speter map->map_mname, map->map_valcolnm); 616438032Speter return FALSE; 616538032Speter } 616638032Speter return TRUE; 616738032Speter} 616838032Speter 616938032Speter 617038032Speter/* 617138032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 617238032Speter*/ 617338032Speter 617438032Speter/* ARGSUSED3 */ 617538032Speterchar * 617638032Speteruser_map_lookup(map, key, av, statp) 617738032Speter MAP *map; 617838032Speter char *key; 617938032Speter char **av; 618038032Speter int *statp; 618138032Speter{ 618238032Speter struct passwd *pw; 618338032Speter auto bool fuzzy; 618438032Speter 618538032Speter if (tTd(38, 20)) 618664562Sgshapiro dprintf("user_map_lookup(%s, %s)\n", 618738032Speter map->map_mname, key); 618838032Speter 618938032Speter pw = finduser(key, &fuzzy); 619038032Speter if (pw == NULL) 619138032Speter return NULL; 619238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 619338032Speter return map_rewrite(map, key, strlen(key), NULL); 619438032Speter else 619538032Speter { 619638032Speter char *rwval = NULL; 619738032Speter char buf[30]; 619838032Speter 619938032Speter switch (map->map_valcolno) 620038032Speter { 620138032Speter case 0: 620238032Speter case 1: 620338032Speter rwval = pw->pw_name; 620438032Speter break; 620538032Speter 620638032Speter case 2: 620738032Speter rwval = pw->pw_passwd; 620838032Speter break; 620938032Speter 621038032Speter case 3: 621164562Sgshapiro snprintf(buf, sizeof buf, "%d", (int) pw->pw_uid); 621238032Speter rwval = buf; 621338032Speter break; 621438032Speter 621538032Speter case 4: 621664562Sgshapiro snprintf(buf, sizeof buf, "%d", (int) pw->pw_gid); 621738032Speter rwval = buf; 621838032Speter break; 621938032Speter 622038032Speter case 5: 622138032Speter rwval = pw->pw_gecos; 622238032Speter break; 622338032Speter 622438032Speter case 6: 622538032Speter rwval = pw->pw_dir; 622638032Speter break; 622738032Speter 622838032Speter case 7: 622938032Speter rwval = pw->pw_shell; 623038032Speter break; 623138032Speter } 623238032Speter return map_rewrite(map, rwval, strlen(rwval), av); 623338032Speter } 623438032Speter} 623538032Speter/* 623638032Speter** Program map type. 623738032Speter** 623838032Speter** This provides access to arbitrary programs. It should be used 623938032Speter** only very sparingly, since there is no way to bound the cost 624038032Speter** of invoking an arbitrary program. 624138032Speter*/ 624238032Speter 624338032Speterchar * 624438032Speterprog_map_lookup(map, name, av, statp) 624538032Speter MAP *map; 624638032Speter char *name; 624738032Speter char **av; 624838032Speter int *statp; 624938032Speter{ 625038032Speter int i; 625164562Sgshapiro int save_errno; 625238032Speter int fd; 625364562Sgshapiro int status; 625438032Speter auto pid_t pid; 625564562Sgshapiro register char *p; 625638032Speter char *rval; 625738032Speter char *argv[MAXPV + 1]; 625838032Speter char buf[MAXLINE]; 625938032Speter 626038032Speter if (tTd(38, 20)) 626164562Sgshapiro dprintf("prog_map_lookup(%s, %s) %s\n", 626238032Speter map->map_mname, name, map->map_file); 626338032Speter 626438032Speter i = 0; 626538032Speter argv[i++] = map->map_file; 626638032Speter if (map->map_rebuild != NULL) 626738032Speter { 626838032Speter snprintf(buf, sizeof buf, "%s", map->map_rebuild); 626938032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 627038032Speter { 627138032Speter if (i >= MAXPV - 1) 627238032Speter break; 627338032Speter argv[i++] = p; 627438032Speter } 627538032Speter } 627638032Speter argv[i++] = name; 627738032Speter argv[i] = NULL; 627838032Speter if (tTd(38, 21)) 627938032Speter { 628064562Sgshapiro dprintf("prog_open:"); 628138032Speter for (i = 0; argv[i] != NULL; i++) 628264562Sgshapiro dprintf(" %s", argv[i]); 628364562Sgshapiro dprintf("\n"); 628438032Speter } 628538032Speter (void) blocksignal(SIGCHLD); 628638032Speter pid = prog_open(argv, &fd, CurEnv); 628738032Speter if (pid < 0) 628838032Speter { 628938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 629038032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 629138032Speter map->map_mname, errstring(errno)); 629238032Speter else if (tTd(38, 9)) 629364562Sgshapiro dprintf("prog_map_lookup(%s) failed (%s) -- closing", 629438032Speter map->map_mname, errstring(errno)); 629538032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 629638032Speter *statp = EX_OSFILE; 629738032Speter return NULL; 629838032Speter } 629938032Speter i = read(fd, buf, sizeof buf - 1); 630038032Speter if (i < 0) 630138032Speter { 630238032Speter syserr("prog_map_lookup(%s): read error %s\n", 630338032Speter map->map_mname, errstring(errno)); 630438032Speter rval = NULL; 630538032Speter } 630638032Speter else if (i == 0) 630738032Speter { 630838032Speter if (tTd(38, 20)) 630964562Sgshapiro dprintf("prog_map_lookup(%s): empty answer\n", 631038032Speter map->map_mname); 631138032Speter rval = NULL; 631238032Speter } 631338032Speter else 631438032Speter { 631538032Speter buf[i] = '\0'; 631638032Speter p = strchr(buf, '\n'); 631738032Speter if (p != NULL) 631838032Speter *p = '\0'; 631938032Speter 632038032Speter /* collect the return value */ 632138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 632238032Speter rval = map_rewrite(map, name, strlen(name), NULL); 632338032Speter else 632438032Speter rval = map_rewrite(map, buf, strlen(buf), NULL); 632538032Speter 632638032Speter /* now flush any additional output */ 632738032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 632838032Speter continue; 632938032Speter } 633038032Speter 633138032Speter /* wait for the process to terminate */ 633264562Sgshapiro (void) close(fd); 633364562Sgshapiro status = waitfor(pid); 633464562Sgshapiro save_errno = errno; 633538032Speter (void) releasesignal(SIGCHLD); 633664562Sgshapiro errno = save_errno; 633738032Speter 633864562Sgshapiro if (status == -1) 633938032Speter { 634038032Speter syserr("prog_map_lookup(%s): wait error %s\n", 634138032Speter map->map_mname, errstring(errno)); 634238032Speter *statp = EX_SOFTWARE; 634338032Speter rval = NULL; 634438032Speter } 634564562Sgshapiro else if (WIFEXITED(status)) 634638032Speter { 634764562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 634838032Speter rval = NULL; 634938032Speter } 635038032Speter else 635138032Speter { 635238032Speter syserr("prog_map_lookup(%s): child died on signal %d", 635364562Sgshapiro map->map_mname, status); 635438032Speter *statp = EX_UNAVAILABLE; 635538032Speter rval = NULL; 635638032Speter } 635738032Speter return rval; 635838032Speter} 635938032Speter/* 636038032Speter** Sequenced map type. 636138032Speter** 636238032Speter** Tries each map in order until something matches, much like 636338032Speter** implicit. Stores go to the first map in the list that can 636438032Speter** support storing. 636538032Speter** 636638032Speter** This is slightly unusual in that there are two interfaces. 636738032Speter** The "sequence" interface lets you stack maps arbitrarily. 636838032Speter** The "switch" interface builds a sequence map by looking 636938032Speter** at a system-dependent configuration file such as 637038032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 637138032Speter** 637238032Speter** We don't need an explicit open, since all maps are 637338032Speter** opened during startup, including underlying maps. 637438032Speter*/ 637538032Speter 637638032Speter/* 637738032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 637838032Speter*/ 637938032Speter 638038032Speterbool 638138032Speterseq_map_parse(map, ap) 638238032Speter MAP *map; 638338032Speter char *ap; 638438032Speter{ 638538032Speter int maxmap; 638638032Speter 638738032Speter if (tTd(38, 2)) 638864562Sgshapiro dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 638938032Speter maxmap = 0; 639038032Speter while (*ap != '\0') 639138032Speter { 639238032Speter register char *p; 639338032Speter STAB *s; 639438032Speter 639538032Speter /* find beginning of map name */ 639638032Speter while (isascii(*ap) && isspace(*ap)) 639738032Speter ap++; 639864562Sgshapiro for (p = ap; 639964562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 640064562Sgshapiro p++) 640138032Speter continue; 640238032Speter if (*p != '\0') 640338032Speter *p++ = '\0'; 640438032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 640538032Speter p++; 640638032Speter if (*ap == '\0') 640738032Speter { 640838032Speter ap = p; 640938032Speter continue; 641038032Speter } 641138032Speter s = stab(ap, ST_MAP, ST_FIND); 641238032Speter if (s == NULL) 641338032Speter { 641438032Speter syserr("Sequence map %s: unknown member map %s", 641538032Speter map->map_mname, ap); 641638032Speter } 641738032Speter else if (maxmap == MAXMAPSTACK) 641838032Speter { 641938032Speter syserr("Sequence map %s: too many member maps (%d max)", 642038032Speter map->map_mname, MAXMAPSTACK); 642138032Speter maxmap++; 642238032Speter } 642338032Speter else if (maxmap < MAXMAPSTACK) 642438032Speter { 642538032Speter map->map_stack[maxmap++] = &s->s_map; 642638032Speter } 642738032Speter ap = p; 642838032Speter } 642938032Speter return TRUE; 643038032Speter} 643138032Speter 643238032Speter 643338032Speter/* 643438032Speter** SWITCH_MAP_OPEN -- open a switched map 643538032Speter** 643638032Speter** This looks at the system-dependent configuration and builds 643738032Speter** a sequence map that does the same thing. 643838032Speter** 643938032Speter** Every system must define a switch_map_find routine in conf.c 644038032Speter** that will return the list of service types associated with a 644138032Speter** given service class. 644238032Speter*/ 644338032Speter 644438032Speterbool 644538032Speterswitch_map_open(map, mode) 644638032Speter MAP *map; 644738032Speter int mode; 644838032Speter{ 644938032Speter int mapno; 645038032Speter int nmaps; 645138032Speter char *maptype[MAXMAPSTACK]; 645238032Speter 645338032Speter if (tTd(38, 2)) 645464562Sgshapiro dprintf("switch_map_open(%s, %s, %d)\n", 645538032Speter map->map_mname, map->map_file, mode); 645638032Speter 645738032Speter mode &= O_ACCMODE; 645838032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 645938032Speter if (tTd(38, 19)) 646038032Speter { 646164562Sgshapiro dprintf("\tswitch_map_find => %d\n", nmaps); 646238032Speter for (mapno = 0; mapno < nmaps; mapno++) 646364562Sgshapiro dprintf("\t\t%s\n", maptype[mapno]); 646438032Speter } 646538032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 646638032Speter return FALSE; 646738032Speter 646838032Speter for (mapno = 0; mapno < nmaps; mapno++) 646938032Speter { 647038032Speter register STAB *s; 647138032Speter char nbuf[MAXNAME + 1]; 647238032Speter 647338032Speter if (maptype[mapno] == NULL) 647438032Speter continue; 647538032Speter (void) snprintf(nbuf, sizeof nbuf, "%s.%s", 647638032Speter map->map_mname, maptype[mapno]); 647738032Speter s = stab(nbuf, ST_MAP, ST_FIND); 647838032Speter if (s == NULL) 647938032Speter { 648038032Speter syserr("Switch map %s: unknown member map %s", 648138032Speter map->map_mname, nbuf); 648238032Speter } 648338032Speter else 648438032Speter { 648538032Speter map->map_stack[mapno] = &s->s_map; 648638032Speter if (tTd(38, 4)) 648764562Sgshapiro dprintf("\tmap_stack[%d] = %s:%s\n", 648838032Speter mapno, s->s_map.map_class->map_cname, 648938032Speter nbuf); 649038032Speter } 649138032Speter } 649238032Speter return TRUE; 649338032Speter} 649438032Speter 649538032Speter 649638032Speter/* 649738032Speter** SEQ_MAP_CLOSE -- close all underlying maps 649838032Speter*/ 649938032Speter 650038032Spetervoid 650138032Speterseq_map_close(map) 650238032Speter MAP *map; 650338032Speter{ 650438032Speter int mapno; 650538032Speter 650638032Speter if (tTd(38, 9)) 650764562Sgshapiro dprintf("seq_map_close(%s)\n", map->map_mname); 650838032Speter 650938032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 651038032Speter { 651138032Speter MAP *mm = map->map_stack[mapno]; 651238032Speter 651338032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 651438032Speter continue; 651538032Speter mm->map_class->map_close(mm); 651638032Speter mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 651738032Speter } 651838032Speter} 651938032Speter 652038032Speter 652138032Speter/* 652238032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 652338032Speter*/ 652438032Speter 652538032Speterchar * 652638032Speterseq_map_lookup(map, key, args, pstat) 652738032Speter MAP *map; 652838032Speter char *key; 652938032Speter char **args; 653038032Speter int *pstat; 653138032Speter{ 653238032Speter int mapno; 653338032Speter int mapbit = 0x01; 653438032Speter bool tempfail = FALSE; 653538032Speter 653638032Speter if (tTd(38, 20)) 653764562Sgshapiro dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 653838032Speter 653938032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 654038032Speter { 654138032Speter MAP *mm = map->map_stack[mapno]; 654238032Speter char *rv; 654338032Speter 654438032Speter if (mm == NULL) 654538032Speter continue; 654664562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 654764562Sgshapiro !openmap(mm)) 654838032Speter { 654938032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 655038032Speter { 655138032Speter *pstat = EX_UNAVAILABLE; 655238032Speter return NULL; 655338032Speter } 655438032Speter continue; 655538032Speter } 655638032Speter *pstat = EX_OK; 655738032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 655838032Speter if (rv != NULL) 655938032Speter return rv; 656038032Speter if (*pstat == EX_TEMPFAIL) 656138032Speter { 656238032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 656338032Speter return NULL; 656438032Speter tempfail = TRUE; 656538032Speter } 656638032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 656738032Speter break; 656838032Speter } 656938032Speter if (tempfail) 657038032Speter *pstat = EX_TEMPFAIL; 657138032Speter else if (*pstat == EX_OK) 657238032Speter *pstat = EX_NOTFOUND; 657338032Speter return NULL; 657438032Speter} 657538032Speter 657638032Speter 657738032Speter/* 657838032Speter** SEQ_MAP_STORE -- sequenced map store 657938032Speter*/ 658038032Speter 658138032Spetervoid 658238032Speterseq_map_store(map, key, val) 658338032Speter MAP *map; 658438032Speter char *key; 658538032Speter char *val; 658638032Speter{ 658738032Speter int mapno; 658838032Speter 658938032Speter if (tTd(38, 12)) 659064562Sgshapiro dprintf("seq_map_store(%s, %s, %s)\n", 659138032Speter map->map_mname, key, val); 659238032Speter 659338032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 659438032Speter { 659538032Speter MAP *mm = map->map_stack[mapno]; 659638032Speter 659738032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 659838032Speter continue; 659938032Speter 660038032Speter mm->map_class->map_store(mm, key, val); 660138032Speter return; 660238032Speter } 660338032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 660438032Speter map->map_mname, key, val); 660538032Speter} 660638032Speter/* 660738032Speter** NULL stubs 660838032Speter*/ 660938032Speter 661038032Speter/* ARGSUSED */ 661138032Speterbool 661238032Speternull_map_open(map, mode) 661338032Speter MAP *map; 661438032Speter int mode; 661538032Speter{ 661638032Speter return TRUE; 661738032Speter} 661838032Speter 661938032Speter/* ARGSUSED */ 662038032Spetervoid 662138032Speternull_map_close(map) 662238032Speter MAP *map; 662338032Speter{ 662438032Speter return; 662538032Speter} 662638032Speter 662738032Speterchar * 662838032Speternull_map_lookup(map, key, args, pstat) 662938032Speter MAP *map; 663038032Speter char *key; 663138032Speter char **args; 663238032Speter int *pstat; 663338032Speter{ 663438032Speter *pstat = EX_NOTFOUND; 663538032Speter return NULL; 663638032Speter} 663738032Speter 663838032Speter/* ARGSUSED */ 663938032Spetervoid 664038032Speternull_map_store(map, key, val) 664138032Speter MAP *map; 664238032Speter char *key; 664338032Speter char *val; 664438032Speter{ 664538032Speter return; 664638032Speter} 664738032Speter 664838032Speter 664938032Speter/* 665038032Speter** BOGUS stubs 665138032Speter*/ 665238032Speter 665338032Speterchar * 665438032Speterbogus_map_lookup(map, key, args, pstat) 665538032Speter MAP *map; 665638032Speter char *key; 665738032Speter char **args; 665838032Speter int *pstat; 665938032Speter{ 666038032Speter *pstat = EX_TEMPFAIL; 666138032Speter return NULL; 666238032Speter} 666338032Speter 666438032SpeterMAPCLASS BogusMapClass = 666538032Speter{ 666638032Speter "bogus-map", NULL, 0, 666738032Speter NULL, bogus_map_lookup, null_map_store, 666838032Speter null_map_open, null_map_close, 666938032Speter}; 667038032Speter/* 667164562Sgshapiro** MACRO modules 667264562Sgshapiro*/ 667364562Sgshapiro 667464562Sgshapirochar * 667564562Sgshapiromacro_map_lookup(map, name, av, statp) 667664562Sgshapiro MAP *map; 667764562Sgshapiro char *name; 667864562Sgshapiro char **av; 667964562Sgshapiro int *statp; 668064562Sgshapiro{ 668164562Sgshapiro int mid; 668264562Sgshapiro 668364562Sgshapiro if (tTd(38, 20)) 668464562Sgshapiro dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 668564562Sgshapiro name == NULL ? "NULL" : name); 668664562Sgshapiro 668764562Sgshapiro if (name == NULL || 668864562Sgshapiro *name == '\0' || 668964562Sgshapiro (mid = macid(name, NULL)) == '\0') 669064562Sgshapiro { 669164562Sgshapiro *statp = EX_CONFIG; 669264562Sgshapiro return NULL; 669364562Sgshapiro } 669464562Sgshapiro 669564562Sgshapiro if (av[1] == NULL) 669664562Sgshapiro define(mid, NULL, CurEnv); 669764562Sgshapiro else 669864562Sgshapiro define(mid, newstr(av[1]), CurEnv); 669964562Sgshapiro 670064562Sgshapiro *statp = EX_OK; 670164562Sgshapiro return ""; 670264562Sgshapiro} 670364562Sgshapiro/* 670438032Speter** REGEX modules 670538032Speter*/ 670638032Speter 670738032Speter#ifdef MAP_REGEX 670838032Speter 670938032Speter# include <regex.h> 671038032Speter 671138032Speter# define DEFAULT_DELIM CONDELSE 671238032Speter 671338032Speter# define END_OF_FIELDS -1 671438032Speter 671538032Speter# define ERRBUF_SIZE 80 671638032Speter# define MAX_MATCH 32 671738032Speter 671864562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 671938032Speter 672038032Speterstruct regex_map 672138032Speter{ 672264562Sgshapiro regex_t regex_pattern_buf; /* xalloc it */ 672338032Speter int *regex_subfields; /* move to type MAP */ 672464562Sgshapiro char *regex_delim; /* move to type MAP */ 672538032Speter}; 672638032Speter 672738032Speterstatic int 672838032Speterparse_fields(s, ibuf, blen, nr_substrings) 672938032Speter char *s; 673038032Speter int *ibuf; /* array */ 673138032Speter int blen; /* number of elements in ibuf */ 673238032Speter int nr_substrings; /* number of substrings in the pattern */ 673338032Speter{ 673438032Speter register char *cp; 673538032Speter int i = 0; 673638032Speter bool lastone = FALSE; 673738032Speter 673838032Speter blen--; /* for terminating END_OF_FIELDS */ 673938032Speter cp = s; 674038032Speter do 674138032Speter { 674238032Speter for (;; cp++) 674338032Speter { 674438032Speter if (*cp == ',') 674538032Speter { 674638032Speter *cp = '\0'; 674738032Speter break; 674838032Speter } 674938032Speter if (*cp == '\0') 675038032Speter { 675138032Speter lastone = TRUE; 675238032Speter break; 675338032Speter } 675438032Speter } 675538032Speter if (i < blen) 675638032Speter { 675738032Speter int val = atoi(s); 675838032Speter 675938032Speter if (val < 0 || val >= nr_substrings) 676038032Speter { 676138032Speter syserr("field (%d) out of range, only %d substrings in pattern", 676238032Speter val, nr_substrings); 676338032Speter return -1; 676438032Speter } 676538032Speter ibuf[i++] = val; 676638032Speter } 676738032Speter else 676838032Speter { 676938032Speter syserr("too many fields, %d max\n", blen); 677038032Speter return -1; 677138032Speter } 677238032Speter s = ++cp; 677338032Speter } while (!lastone); 677438032Speter ibuf[i] = END_OF_FIELDS; 677538032Speter return i; 677638032Speter} 677738032Speter 677838032Speterbool 677938032Speterregex_map_init(map, ap) 678038032Speter MAP *map; 678138032Speter char *ap; 678238032Speter{ 678338032Speter int regerr; 678438032Speter struct regex_map *map_p; 678538032Speter register char *p; 678638032Speter char *sub_param = NULL; 678738032Speter int pflags; 678838032Speter static char defdstr[] = { (char)DEFAULT_DELIM, '\0' }; 678938032Speter 679038032Speter if (tTd(38, 2)) 679164562Sgshapiro dprintf("regex_map_init: mapname '%s', args '%s'\n", 679264562Sgshapiro map->map_mname, ap); 679338032Speter 679438032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 679538032Speter 679638032Speter p = ap; 679738032Speter 679864562Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof *map_p); 679938032Speter 680038032Speter for (;;) 680164562Sgshapiro { 680238032Speter while (isascii(*p) && isspace(*p)) 680338032Speter p++; 680438032Speter if (*p != '-') 680538032Speter break; 680638032Speter switch (*++p) 680738032Speter { 680838032Speter case 'n': /* not */ 680938032Speter map->map_mflags |= MF_REGEX_NOT; 681038032Speter break; 681138032Speter 681238032Speter case 'f': /* case sensitive */ 681338032Speter map->map_mflags |= MF_NOFOLDCASE; 681438032Speter pflags &= ~REG_ICASE; 681538032Speter break; 681638032Speter 681738032Speter case 'b': /* basic regular expressions */ 681838032Speter pflags &= ~REG_EXTENDED; 681938032Speter break; 682038032Speter 682138032Speter case 's': /* substring match () syntax */ 682238032Speter sub_param = ++p; 682338032Speter pflags &= ~REG_NOSUB; 682438032Speter break; 682538032Speter 682638032Speter case 'd': /* delimiter */ 682764562Sgshapiro map_p->regex_delim = ++p; 682838032Speter break; 682938032Speter 683038032Speter case 'a': /* map append */ 683138032Speter map->map_app = ++p; 683238032Speter break; 683338032Speter 683438032Speter case 'm': /* matchonly */ 683538032Speter map->map_mflags |= MF_MATCHONLY; 683638032Speter break; 683738032Speter 683864562Sgshapiro case 'S': 683964562Sgshapiro map->map_spacesub = *++p; 684064562Sgshapiro break; 684164562Sgshapiro 684264562Sgshapiro case 'D': 684364562Sgshapiro map->map_mflags |= MF_DEFER; 684464562Sgshapiro break; 684564562Sgshapiro 684638032Speter } 684764562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 684864562Sgshapiro p++; 684964562Sgshapiro if (*p != '\0') 685064562Sgshapiro *p++ = '\0'; 685138032Speter } 685238032Speter if (tTd(38, 3)) 685364562Sgshapiro dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 685438032Speter 685564562Sgshapiro if ((regerr = regcomp(&(map_p->regex_pattern_buf), p, pflags)) != 0) 685638032Speter { 685738032Speter /* Errorhandling */ 685838032Speter char errbuf[ERRBUF_SIZE]; 685938032Speter 686064562Sgshapiro (void) regerror(regerr, &(map_p->regex_pattern_buf), 686164562Sgshapiro errbuf, ERRBUF_SIZE); 686238032Speter syserr("pattern-compile-error: %s\n", errbuf); 686338032Speter free(map_p); 686438032Speter return FALSE; 686538032Speter } 686638032Speter 686738032Speter if (map->map_app != NULL) 686838032Speter map->map_app = newstr(map->map_app); 686964562Sgshapiro if (map_p->regex_delim != NULL) 687064562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 687138032Speter else 687264562Sgshapiro map_p->regex_delim = defdstr; 687338032Speter 687438032Speter if (!bitset(REG_NOSUB, pflags)) 687538032Speter { 687638032Speter /* substring matching */ 687738032Speter int substrings; 687864562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 687938032Speter 688064562Sgshapiro substrings = map_p->regex_pattern_buf.re_nsub + 1; 688138032Speter 688238032Speter if (tTd(38, 3)) 688364562Sgshapiro dprintf("regex_map_init: nr of substrings %d\n", 688464562Sgshapiro substrings); 688538032Speter 688638032Speter if (substrings >= MAX_MATCH) 688738032Speter { 688838032Speter syserr("too many substrings, %d max\n", MAX_MATCH); 688938032Speter free(map_p); 689038032Speter return FALSE; 689138032Speter } 689238032Speter if (sub_param != NULL && sub_param[0] != '\0') 689338032Speter { 689438032Speter /* optional parameter -sfields */ 689538032Speter if (parse_fields(sub_param, fields, 689638032Speter MAX_MATCH + 1, substrings) == -1) 689738032Speter return FALSE; 689838032Speter } 689938032Speter else 690038032Speter { 690164562Sgshapiro /* set default fields */ 690238032Speter int i; 690338032Speter 690438032Speter for (i = 0; i < substrings; i++) 690538032Speter fields[i] = i; 690638032Speter fields[i] = END_OF_FIELDS; 690738032Speter } 690838032Speter map_p->regex_subfields = fields; 690938032Speter if (tTd(38, 3)) 691038032Speter { 691138032Speter int *ip; 691238032Speter 691364562Sgshapiro dprintf("regex_map_init: subfields"); 691438032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 691564562Sgshapiro dprintf(" %d", *ip); 691664562Sgshapiro dprintf("\n"); 691738032Speter } 691838032Speter } 691938032Speter map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */ 692038032Speter 692138032Speter return TRUE; 692238032Speter} 692338032Speter 692438032Speterstatic char * 692538032Speterregex_map_rewrite(map, s, slen, av) 692638032Speter MAP *map; 692738032Speter const char *s; 692838032Speter size_t slen; 692938032Speter char **av; 693038032Speter{ 693138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 693238032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 693338032Speter else 693438032Speter return map_rewrite(map, s, slen, NULL); 693538032Speter} 693638032Speter 693738032Speterchar * 693838032Speterregex_map_lookup(map, name, av, statp) 693938032Speter MAP *map; 694038032Speter char *name; 694138032Speter char **av; 694238032Speter int *statp; 694338032Speter{ 694438032Speter int reg_res; 694538032Speter struct regex_map *map_p; 694638032Speter regmatch_t pmatch[MAX_MATCH]; 694738032Speter 694838032Speter if (tTd(38, 20)) 694938032Speter { 695038032Speter char **cpp; 695138032Speter 695264562Sgshapiro dprintf("regex_map_lookup: key '%s'\n", name); 695364562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 695464562Sgshapiro dprintf("regex_map_lookup: arg '%s'\n", *cpp); 695538032Speter } 695638032Speter 695738032Speter map_p = (struct regex_map *)(map->map_db1); 695864562Sgshapiro reg_res = regexec(&(map_p->regex_pattern_buf), 695964562Sgshapiro name, MAX_MATCH, pmatch, 0); 696038032Speter 696138032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 696238032Speter { 696338032Speter /* option -n */ 696438032Speter if (reg_res == REG_NOMATCH) 696538032Speter return regex_map_rewrite(map, "", (size_t)0, av); 696638032Speter else 696738032Speter return NULL; 696838032Speter } 696938032Speter if (reg_res == REG_NOMATCH) 697038032Speter return NULL; 697138032Speter 697238032Speter if (map_p->regex_subfields != NULL) 697338032Speter { 697438032Speter /* option -s */ 697538032Speter static char retbuf[MAXNAME]; 697638032Speter int fields[MAX_MATCH + 1]; 697738032Speter bool first = TRUE; 697838032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 697938032Speter bool quotemode = FALSE, bslashmode = FALSE; 698038032Speter register char *dp, *sp; 698138032Speter char *endp, *ldp; 698238032Speter int *ip; 698338032Speter 698438032Speter dp = retbuf; 698538032Speter ldp = retbuf + sizeof(retbuf) - 1; 698638032Speter 698738032Speter if (av[1] != NULL) 698838032Speter { 698938032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 699064562Sgshapiro (int) map_p->regex_pattern_buf.re_nsub + 1) == -1) 699138032Speter { 699238032Speter *statp = EX_CONFIG; 699338032Speter return NULL; 699438032Speter } 699538032Speter ip = fields; 699638032Speter } 699738032Speter else 699838032Speter ip = map_p->regex_subfields; 699938032Speter 700038032Speter for ( ; *ip != END_OF_FIELDS; ip++) 700138032Speter { 700238032Speter if (!first) 700338032Speter { 700464562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 700538032Speter { 700638032Speter if (dp < ldp) 700738032Speter *dp++ = *sp; 700838032Speter } 700938032Speter } 701038032Speter else 701138032Speter first = FALSE; 701238032Speter 701338032Speter 701438032Speter if (pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 701538032Speter continue; 701638032Speter 701738032Speter sp = name + pmatch[*ip].rm_so; 701838032Speter endp = name + pmatch[*ip].rm_eo; 701938032Speter for (; endp > sp; sp++) 702038032Speter { 702138032Speter if (dp < ldp) 702238032Speter { 702364562Sgshapiro if (bslashmode) 702464562Sgshapiro { 702538032Speter *dp++ = *sp; 702638032Speter bslashmode = FALSE; 702738032Speter } 702864562Sgshapiro else if (quotemode && *sp != '"' && 702938032Speter *sp != '\\') 703038032Speter { 703138032Speter *dp++ = *sp; 703238032Speter } 703338032Speter else switch(*dp++ = *sp) 703438032Speter { 703538032Speter case '\\': 703638032Speter bslashmode = TRUE; 703738032Speter break; 703838032Speter 703938032Speter case '(': 704038032Speter cmntcnt++; 704138032Speter break; 704238032Speter 704338032Speter case ')': 704438032Speter cmntcnt--; 704538032Speter break; 704638032Speter 704738032Speter case '<': 704838032Speter anglecnt++; 704938032Speter break; 705038032Speter 705138032Speter case '>': 705238032Speter anglecnt--; 705338032Speter break; 705438032Speter 705538032Speter case ' ': 705638032Speter spacecnt++; 705738032Speter break; 705838032Speter 705938032Speter case '"': 706038032Speter quotemode = !quotemode; 706138032Speter break; 706238032Speter } 706338032Speter } 706438032Speter } 706538032Speter } 706638032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 706738032Speter bslashmode || spacecnt != 0) 706838032Speter { 706964562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 707064562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 707164562Sgshapiro map->map_mname, name); 707238032Speter return NULL; 707338032Speter } 707438032Speter 707538032Speter *dp = '\0'; 707638032Speter 707738032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 707838032Speter } 707938032Speter return regex_map_rewrite(map, "", (size_t)0, av); 708038032Speter} 708138032Speter#endif /* MAP_REGEX */ 708264562Sgshapiro/* 708364562Sgshapiro** NSD modules 708464562Sgshapiro*/ 708564562Sgshapiro#ifdef MAP_NSD 708664562Sgshapiro 708764562Sgshapiro# include <ndbm.h> 708864562Sgshapiro# define _DATUM_DEFINED 708964562Sgshapiro# include <ns_api.h> 709064562Sgshapiro 709164562Sgshapirotypedef struct ns_map_list 709264562Sgshapiro{ 709364562Sgshapiro ns_map_t *map; 709464562Sgshapiro char *mapname; 709564562Sgshapiro struct ns_map_list *next; 709664562Sgshapiro} ns_map_list_t; 709764562Sgshapiro 709864562Sgshapirostatic ns_map_t * 709964562Sgshapirons_map_t_find(mapname) 710064562Sgshapiro char *mapname; 710164562Sgshapiro{ 710264562Sgshapiro static ns_map_list_t *ns_maps = NULL; 710364562Sgshapiro ns_map_list_t *ns_map; 710464562Sgshapiro 710564562Sgshapiro /* walk the list of maps looking for the correctly named map */ 710664562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 710764562Sgshapiro { 710864562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 710964562Sgshapiro break; 711064562Sgshapiro } 711164562Sgshapiro 711264562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 711364562Sgshapiro if (ns_map == NULL) 711464562Sgshapiro { 711564562Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 711664562Sgshapiro ns_map->mapname = newstr(mapname); 711764562Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 711864562Sgshapiro ns_map->next = ns_maps; 711964562Sgshapiro ns_maps = ns_map; 712064562Sgshapiro } 712164562Sgshapiro return ns_map->map; 712264562Sgshapiro} 712364562Sgshapiro 712464562Sgshapirochar * 712564562Sgshapironsd_map_lookup(map, name, av, statp) 712664562Sgshapiro MAP *map; 712764562Sgshapiro char *name; 712864562Sgshapiro char **av; 712964562Sgshapiro int *statp; 713064562Sgshapiro{ 713164562Sgshapiro int buflen; 713264562Sgshapiro char *p; 713364562Sgshapiro ns_map_t *ns_map; 713464562Sgshapiro char keybuf[MAXNAME + 1]; 713564562Sgshapiro char buf[MAXLINE]; 713664562Sgshapiro 713764562Sgshapiro if (tTd(38, 20)) 713864562Sgshapiro dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 713964562Sgshapiro 714064562Sgshapiro buflen = strlen(name); 714164562Sgshapiro if (buflen > sizeof keybuf - 1) 714264562Sgshapiro buflen = sizeof keybuf - 1; 714364562Sgshapiro memmove(keybuf, name, buflen); 714464562Sgshapiro keybuf[buflen] = '\0'; 714564562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 714664562Sgshapiro makelower(keybuf); 714764562Sgshapiro 714864562Sgshapiro ns_map = ns_map_t_find(map->map_file); 714964562Sgshapiro if (ns_map == NULL) 715064562Sgshapiro { 715164562Sgshapiro if (tTd(38, 20)) 715264562Sgshapiro dprintf("nsd_map_t_find failed\n"); 715364562Sgshapiro return NULL; 715464562Sgshapiro } 715564562Sgshapiro 715664562Sgshapiro if (ns_lookup(ns_map, NULL, map->map_file, 715764562Sgshapiro keybuf, NULL, buf, MAXLINE) == NULL) 715864562Sgshapiro return NULL; 715964562Sgshapiro 716064562Sgshapiro /* Null out trailing \n */ 716164562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 716264562Sgshapiro *p = '\0'; 716364562Sgshapiro 716464562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 716564562Sgshapiro} 716664562Sgshapiro#endif /* MAP_NSD */ 716764562Sgshapiro 716864562Sgshapirochar * 716964562Sgshapiroarith_map_lookup(map, name, av, statp) 717064562Sgshapiro MAP *map; 717164562Sgshapiro char *name; 717264562Sgshapiro char **av; 717364562Sgshapiro int *statp; 717464562Sgshapiro{ 717564562Sgshapiro long r; 717664562Sgshapiro long v[2]; 717764562Sgshapiro bool res = FALSE; 717864562Sgshapiro bool boolres; 717964562Sgshapiro static char result[16]; 718064562Sgshapiro char **cpp; 718164562Sgshapiro 718264562Sgshapiro if (tTd(38, 2)) 718364562Sgshapiro { 718464562Sgshapiro dprintf("arith_map_lookup: key '%s'\n", name); 718564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 718664562Sgshapiro dprintf("arith_map_lookup: arg '%s'\n", *cpp); 718764562Sgshapiro } 718864562Sgshapiro r = 0; 718964562Sgshapiro boolres = FALSE; 719064562Sgshapiro cpp = av; 719164562Sgshapiro *statp = EX_OK; 719264562Sgshapiro 719364562Sgshapiro /* 719464562Sgshapiro ** read arguments for arith map 719564562Sgshapiro ** - no check is made whether they are really numbers 719664562Sgshapiro ** - just ignores args after the second 719764562Sgshapiro */ 719864562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 719964562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 720064562Sgshapiro 720164562Sgshapiro /* operator and (at least) two operands given? */ 720264562Sgshapiro if (name != NULL && r == 2) 720364562Sgshapiro { 720464562Sgshapiro switch(*name) 720564562Sgshapiro { 720664562Sgshapiro#if _FFR_ARITH 720764562Sgshapiro case '|': 720864562Sgshapiro r = v[0] | v[1]; 720964562Sgshapiro break; 721064562Sgshapiro 721164562Sgshapiro case '&': 721264562Sgshapiro r = v[0] & v[1]; 721364562Sgshapiro break; 721464562Sgshapiro 721564562Sgshapiro case '%': 721664562Sgshapiro if (v[1] == 0) 721764562Sgshapiro return NULL; 721864562Sgshapiro r = v[0] % v[1]; 721964562Sgshapiro break; 722064562Sgshapiro#endif /* _FFR_ARITH */ 722164562Sgshapiro 722264562Sgshapiro case '+': 722364562Sgshapiro r = v[0] + v[1]; 722464562Sgshapiro break; 722564562Sgshapiro 722664562Sgshapiro case '-': 722764562Sgshapiro r = v[0] - v[1]; 722864562Sgshapiro break; 722964562Sgshapiro 723064562Sgshapiro case '*': 723164562Sgshapiro r = v[0] * v[1]; 723264562Sgshapiro break; 723364562Sgshapiro 723464562Sgshapiro case '/': 723564562Sgshapiro if (v[1] == 0) 723664562Sgshapiro return NULL; 723764562Sgshapiro r = v[0] / v[1]; 723864562Sgshapiro break; 723964562Sgshapiro 724064562Sgshapiro case 'l': 724164562Sgshapiro res = v[0] < v[1]; 724264562Sgshapiro boolres = TRUE; 724364562Sgshapiro break; 724464562Sgshapiro 724564562Sgshapiro case '=': 724664562Sgshapiro res = v[0] == v[1]; 724764562Sgshapiro boolres = TRUE; 724864562Sgshapiro break; 724964562Sgshapiro 725064562Sgshapiro default: 725164562Sgshapiro /* XXX */ 725264562Sgshapiro *statp = EX_CONFIG; 725364562Sgshapiro if (LogLevel > 10) 725464562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 725564562Sgshapiro "arith_map: unknown operator %c", 725664562Sgshapiro isprint(*name) ? *name : '?'); 725764562Sgshapiro return NULL; 725864562Sgshapiro } 725964562Sgshapiro if (boolres) 726064562Sgshapiro snprintf(result, sizeof result, res ? "TRUE" : "FALSE"); 726164562Sgshapiro else 726264562Sgshapiro snprintf(result, sizeof result, "%ld", r); 726364562Sgshapiro return result; 726464562Sgshapiro } 726564562Sgshapiro *statp = EX_CONFIG; 726664562Sgshapiro return NULL; 726764562Sgshapiro} 7268