map.c revision 73188
138032Speter/* 273188Sgshapiro * Copyright (c) 1998-2001 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 1573188Sgshapirostatic char id[] = "@(#)$Id: map.c,v 8.414.4.39 2001/02/22 18:56:22 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 */ 5573188Sgshapirostatic bool extract_canonname __P((char *, 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) 77073188Sgshapiro SM_SET_H_ERRNO(TRY_AGAIN); 77138032Speter else 77273188Sgshapiro SM_SET_H_ERRNO(HOST_NOT_FOUND); 77364562Sgshapiro#endif /* NAMED_BIND */ 77438032Speter return FALSE; 77538032Speter} 77638032Speter/* 77738032Speter** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 77838032Speter** 77938032Speter** Parameters: 78038032Speter** name -- the name against which to match. 78173188Sgshapiro** dot -- where to reinsert '.' to get FQDN 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 79273188Sgshapiroextract_canonname(name, dot, line, cbuf, cbuflen) 79338032Speter char *name; 79473188Sgshapiro char *dot; 79538032Speter char *line; 79638032Speter char cbuf[]; 79738032Speter int cbuflen; 79838032Speter{ 79938032Speter int i; 80038032Speter char *p; 80138032Speter bool found = FALSE; 80238032Speter 80338032Speter cbuf[0] = '\0'; 80438032Speter if (line[0] == '#') 80538032Speter return FALSE; 80638032Speter 80738032Speter for (i = 1; ; i++) 80838032Speter { 80938032Speter char nbuf[MAXNAME + 1]; 81038032Speter 81138032Speter p = get_column(line, i, '\0', nbuf, sizeof nbuf); 81238032Speter if (p == NULL) 81338032Speter break; 81438032Speter if (*p == '\0') 81538032Speter continue; 81638032Speter if (cbuf[0] == '\0' || 81738032Speter (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 81838032Speter { 81938032Speter snprintf(cbuf, cbuflen, "%s", p); 82038032Speter } 82138032Speter if (strcasecmp(name, p) == 0) 82238032Speter found = TRUE; 82373188Sgshapiro else if (dot != NULL) 82473188Sgshapiro { 82573188Sgshapiro /* try looking for the FQDN as well */ 82673188Sgshapiro *dot = '.'; 82773188Sgshapiro if (strcasecmp(name, p) == 0) 82873188Sgshapiro found = TRUE; 82973188Sgshapiro *dot = '\0'; 83073188Sgshapiro } 83138032Speter } 83238032Speter if (found && strchr(cbuf, '.') == NULL) 83338032Speter { 83438032Speter /* try to add a domain on the end of the name */ 83538032Speter char *domain = macvalue('m', CurEnv); 83638032Speter 83738032Speter if (domain != NULL && 83864562Sgshapiro strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 83938032Speter { 84064562Sgshapiro p = &cbuf[i]; 84138032Speter *p++ = '.'; 84264562Sgshapiro (void) strlcpy(p, domain, cbuflen - i - 1); 84338032Speter } 84438032Speter } 84538032Speter return found; 84638032Speter} 84738032Speter/* 84838032Speter** NDBM modules 84938032Speter*/ 85038032Speter 85138032Speter#ifdef NDBM 85238032Speter 85338032Speter/* 85438032Speter** NDBM_MAP_OPEN -- DBM-style map open 85538032Speter*/ 85638032Speter 85738032Speterbool 85838032Speterndbm_map_open(map, mode) 85938032Speter MAP *map; 86038032Speter int mode; 86138032Speter{ 86238032Speter register DBM *dbm; 86364562Sgshapiro int save_errno; 86438032Speter int dfd; 86538032Speter int pfd; 86664562Sgshapiro long sff; 86738032Speter int ret; 86838032Speter int smode = S_IREAD; 86938032Speter char dirfile[MAXNAME + 1]; 87038032Speter char pagfile[MAXNAME + 1]; 87164562Sgshapiro struct stat st; 87238032Speter struct stat std, stp; 87338032Speter 87438032Speter if (tTd(38, 2)) 87564562Sgshapiro dprintf("ndbm_map_open(%s, %s, %d)\n", 87638032Speter map->map_mname, map->map_file, mode); 87738032Speter map->map_lockfd = -1; 87838032Speter mode &= O_ACCMODE; 87938032Speter 88038032Speter /* do initial file and directory checks */ 88138032Speter snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file); 88238032Speter snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file); 88338032Speter sff = SFF_ROOTOK|SFF_REGONLY; 88438032Speter if (mode == O_RDWR) 88538032Speter { 88638032Speter sff |= SFF_CREAT; 88764562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 88838032Speter sff |= SFF_NOSLINK; 88964562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 89038032Speter sff |= SFF_NOHLINK; 89138032Speter smode = S_IWRITE; 89238032Speter } 89338032Speter else 89438032Speter { 89564562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 89638032Speter sff |= SFF_NOWLINK; 89738032Speter } 89864562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 89938032Speter sff |= SFF_SAFEDIRPATH; 90038032Speter ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 90138032Speter sff, smode, &std); 90238032Speter if (ret == 0) 90338032Speter ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 90438032Speter sff, smode, &stp); 90564562Sgshapiro 90664562Sgshapiro# if !_FFR_REMOVE_AUTOREBUILD 90738032Speter if (ret == ENOENT && AutoRebuild && 90838032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && 90938032Speter (bitset(MF_IMPL_NDBM, map->map_mflags) || 91038032Speter bitset(MF_ALIAS, map->map_mflags)) && 91138032Speter mode == O_RDONLY) 91238032Speter { 91338032Speter bool impl = bitset(MF_IMPL_NDBM, map->map_mflags); 91438032Speter 91538032Speter /* may be able to rebuild */ 91638032Speter map->map_mflags &= ~MF_IMPL_NDBM; 91738032Speter if (!rebuildaliases(map, TRUE)) 91838032Speter return FALSE; 91938032Speter if (impl) 92038032Speter return impl_map_open(map, O_RDONLY); 92138032Speter else 92238032Speter return ndbm_map_open(map, O_RDONLY); 92338032Speter } 92464562Sgshapiro# endif /* !_FFR_REMOVE_AUTOREBUILD */ 92564562Sgshapiro 92638032Speter if (ret != 0) 92738032Speter { 92838032Speter char *prob = "unsafe"; 92938032Speter 93038032Speter /* cannot open this map */ 93138032Speter if (ret == ENOENT) 93238032Speter prob = "missing"; 93338032Speter if (tTd(38, 2)) 93464562Sgshapiro dprintf("\t%s map file: %d\n", prob, ret); 93538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 93638032Speter syserr("dbm map \"%s\": %s map file %s", 93738032Speter map->map_mname, prob, map->map_file); 93838032Speter return FALSE; 93938032Speter } 94038032Speter if (std.st_mode == ST_MODE_NOFILE) 94138032Speter mode |= O_CREAT|O_EXCL; 94238032Speter 94364562Sgshapiro# if LOCK_ON_OPEN 94438032Speter if (mode == O_RDONLY) 94538032Speter mode |= O_SHLOCK; 94638032Speter else 94738032Speter mode |= O_TRUNC|O_EXLOCK; 94864562Sgshapiro# else /* LOCK_ON_OPEN */ 94938032Speter if ((mode & O_ACCMODE) == O_RDWR) 95038032Speter { 95164562Sgshapiro# if NOFTRUNCATE 95238032Speter /* 95338032Speter ** Warning: race condition. Try to lock the file as 95438032Speter ** quickly as possible after opening it. 95538032Speter ** This may also have security problems on some systems, 95638032Speter ** but there isn't anything we can do about it. 95738032Speter */ 95838032Speter 95938032Speter mode |= O_TRUNC; 96064562Sgshapiro# else /* NOFTRUNCATE */ 96138032Speter /* 96238032Speter ** This ugly code opens the map without truncating it, 96338032Speter ** locks the file, then truncates it. Necessary to 96438032Speter ** avoid race conditions. 96538032Speter */ 96638032Speter 96738032Speter int dirfd; 96838032Speter int pagfd; 96964562Sgshapiro long sff = SFF_CREAT|SFF_OPENASROOT; 97038032Speter 97164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 97238032Speter sff |= SFF_NOSLINK; 97364562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 97438032Speter sff |= SFF_NOHLINK; 97538032Speter 97638032Speter dirfd = safeopen(dirfile, mode, DBMMODE, sff); 97738032Speter pagfd = safeopen(pagfile, mode, DBMMODE, sff); 97838032Speter 97938032Speter if (dirfd < 0 || pagfd < 0) 98038032Speter { 98164562Sgshapiro save_errno = errno; 98238032Speter if (dirfd >= 0) 98338032Speter (void) close(dirfd); 98438032Speter if (pagfd >= 0) 98538032Speter (void) close(pagfd); 98638032Speter errno = save_errno; 98738032Speter syserr("ndbm_map_open: cannot create database %s", 98838032Speter map->map_file); 98938032Speter return FALSE; 99038032Speter } 99138032Speter if (ftruncate(dirfd, (off_t) 0) < 0 || 99238032Speter ftruncate(pagfd, (off_t) 0) < 0) 99338032Speter { 99464562Sgshapiro save_errno = errno; 99538032Speter (void) close(dirfd); 99638032Speter (void) close(pagfd); 99738032Speter errno = save_errno; 99838032Speter syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 99938032Speter map->map_file); 100038032Speter return FALSE; 100138032Speter } 100238032Speter 100338032Speter /* if new file, get "before" bits for later filechanged check */ 100438032Speter if (std.st_mode == ST_MODE_NOFILE && 100538032Speter (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 100638032Speter { 100764562Sgshapiro save_errno = errno; 100838032Speter (void) close(dirfd); 100938032Speter (void) close(pagfd); 101038032Speter errno = save_errno; 101138032Speter syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 101238032Speter map->map_file); 101338032Speter return FALSE; 101438032Speter } 101538032Speter 101638032Speter /* have to save the lock for the duration (bletch) */ 101738032Speter map->map_lockfd = dirfd; 101864562Sgshapiro (void) close(pagfd); 101938032Speter 102038032Speter /* twiddle bits for dbm_open */ 102138032Speter mode &= ~(O_CREAT|O_EXCL); 102264562Sgshapiro# endif /* NOFTRUNCATE */ 102338032Speter } 102464562Sgshapiro# endif /* LOCK_ON_OPEN */ 102538032Speter 102638032Speter /* open the database */ 102738032Speter dbm = dbm_open(map->map_file, mode, DBMMODE); 102838032Speter if (dbm == NULL) 102938032Speter { 103064562Sgshapiro save_errno = errno; 103138032Speter if (bitset(MF_ALIAS, map->map_mflags) && 103238032Speter aliaswait(map, ".pag", FALSE)) 103338032Speter return TRUE; 103464562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 103538032Speter if (map->map_lockfd >= 0) 103664562Sgshapiro (void) close(map->map_lockfd); 103764562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 103838032Speter errno = save_errno; 103938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 104038032Speter syserr("Cannot open DBM database %s", map->map_file); 104138032Speter return FALSE; 104238032Speter } 104338032Speter dfd = dbm_dirfno(dbm); 104438032Speter pfd = dbm_pagfno(dbm); 104538032Speter if (dfd == pfd) 104638032Speter { 104738032Speter /* heuristic: if files are linked, this is actually gdbm */ 104838032Speter dbm_close(dbm); 104964562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 105038032Speter if (map->map_lockfd >= 0) 105164562Sgshapiro (void) close(map->map_lockfd); 105264562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 105338032Speter errno = 0; 105438032Speter syserr("dbm map \"%s\": cannot support GDBM", 105538032Speter map->map_mname); 105638032Speter return FALSE; 105738032Speter } 105838032Speter 105938032Speter if (filechanged(dirfile, dfd, &std) || 106038032Speter filechanged(pagfile, pfd, &stp)) 106138032Speter { 106264562Sgshapiro save_errno = errno; 106338032Speter dbm_close(dbm); 106464562Sgshapiro# if !LOCK_ON_OPEN && !NOFTRUNCATE 106538032Speter if (map->map_lockfd >= 0) 106664562Sgshapiro (void) close(map->map_lockfd); 106764562Sgshapiro# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 106838032Speter errno = save_errno; 106938032Speter syserr("ndbm_map_open(%s): file changed after open", 107038032Speter map->map_file); 107138032Speter return FALSE; 107238032Speter } 107338032Speter 107438032Speter map->map_db1 = (ARBPTR_T) dbm; 107564562Sgshapiro 107664562Sgshapiro /* 107764562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 107864562Sgshapiro ** as aliaswait() will call map_lookup() which requires 107964562Sgshapiro ** map_mtime to be set 108064562Sgshapiro */ 108164562Sgshapiro 108264562Sgshapiro if (fstat(dfd, &st) >= 0) 108364562Sgshapiro map->map_mtime = st.st_mtime; 108464562Sgshapiro 108538032Speter if (mode == O_RDONLY) 108638032Speter { 108764562Sgshapiro# if LOCK_ON_OPEN 108838032Speter if (dfd >= 0) 108938032Speter (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 109038032Speter if (pfd >= 0) 109138032Speter (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 109264562Sgshapiro# endif /* LOCK_ON_OPEN */ 109338032Speter if (bitset(MF_ALIAS, map->map_mflags) && 109438032Speter !aliaswait(map, ".pag", TRUE)) 109538032Speter return FALSE; 109638032Speter } 109738032Speter else 109838032Speter { 109938032Speter map->map_mflags |= MF_LOCKED; 110042575Speter if (geteuid() == 0 && TrustedUid != 0) 110138032Speter { 110264562Sgshapiro# if HASFCHOWN 110342575Speter if (fchown(dfd, TrustedUid, -1) < 0 || 110442575Speter fchown(pfd, TrustedUid, -1) < 0) 110538032Speter { 110638032Speter int err = errno; 110738032Speter 110838032Speter sm_syslog(LOG_ALERT, NOQID, 110938032Speter "ownership change on %s failed: %s", 111038032Speter map->map_file, errstring(err)); 111138032Speter message("050 ownership change on %s failed: %s", 111238032Speter map->map_file, errstring(err)); 111338032Speter } 111464562Sgshapiro# endif /* HASFCHOWN */ 111538032Speter } 111638032Speter } 111738032Speter return TRUE; 111838032Speter} 111938032Speter 112038032Speter 112138032Speter/* 112238032Speter** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 112338032Speter*/ 112438032Speter 112538032Speterchar * 112638032Speterndbm_map_lookup(map, name, av, statp) 112738032Speter MAP *map; 112838032Speter char *name; 112938032Speter char **av; 113038032Speter int *statp; 113138032Speter{ 113238032Speter datum key, val; 113338032Speter int fd; 113438032Speter char keybuf[MAXNAME + 1]; 113538032Speter struct stat stbuf; 113638032Speter 113738032Speter if (tTd(38, 20)) 113864562Sgshapiro dprintf("ndbm_map_lookup(%s, %s)\n", 113938032Speter map->map_mname, name); 114038032Speter 114138032Speter key.dptr = name; 114238032Speter key.dsize = strlen(name); 114338032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 114438032Speter { 114538032Speter if (key.dsize > sizeof keybuf - 1) 114638032Speter key.dsize = sizeof keybuf - 1; 114764562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 114838032Speter keybuf[key.dsize] = '\0'; 114938032Speter makelower(keybuf); 115038032Speter key.dptr = keybuf; 115138032Speter } 115238032Speterlockdbm: 115338032Speter fd = dbm_dirfno((DBM *) map->map_db1); 115438032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 115538032Speter (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); 115638032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 115738032Speter { 115838032Speter /* Reopen the database to sync the cache */ 115938032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 116038032Speter : O_RDONLY; 116138032Speter 116264562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 116364562Sgshapiro (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 116438032Speter map->map_class->map_close(map); 116538032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 116638032Speter if (map->map_class->map_open(map, omode)) 116738032Speter { 116838032Speter map->map_mflags |= MF_OPEN; 116942575Speter map->map_pid = getpid(); 117038032Speter if ((omode && O_ACCMODE) == O_RDWR) 117138032Speter map->map_mflags |= MF_WRITABLE; 117238032Speter goto lockdbm; 117338032Speter } 117438032Speter else 117538032Speter { 117638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 117738032Speter { 117838032Speter extern MAPCLASS BogusMapClass; 117938032Speter 118038032Speter *statp = EX_TEMPFAIL; 118138032Speter map->map_class = &BogusMapClass; 118238032Speter map->map_mflags |= MF_OPEN; 118342575Speter map->map_pid = getpid(); 118438032Speter syserr("Cannot reopen NDBM database %s", 118538032Speter map->map_file); 118638032Speter } 118738032Speter return NULL; 118838032Speter } 118938032Speter } 119038032Speter val.dptr = NULL; 119138032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 119238032Speter { 119338032Speter val = dbm_fetch((DBM *) map->map_db1, key); 119438032Speter if (val.dptr != NULL) 119538032Speter map->map_mflags &= ~MF_TRY1NULL; 119638032Speter } 119738032Speter if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 119838032Speter { 119938032Speter key.dsize++; 120038032Speter val = dbm_fetch((DBM *) map->map_db1, key); 120138032Speter if (val.dptr != NULL) 120238032Speter map->map_mflags &= ~MF_TRY0NULL; 120338032Speter } 120438032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 120538032Speter (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); 120638032Speter if (val.dptr == NULL) 120738032Speter return NULL; 120838032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 120938032Speter return map_rewrite(map, name, strlen(name), NULL); 121038032Speter else 121138032Speter return map_rewrite(map, val.dptr, val.dsize, av); 121238032Speter} 121338032Speter 121438032Speter 121538032Speter/* 121638032Speter** NDBM_MAP_STORE -- store a datum in the database 121738032Speter*/ 121838032Speter 121938032Spetervoid 122038032Speterndbm_map_store(map, lhs, rhs) 122138032Speter register MAP *map; 122238032Speter char *lhs; 122338032Speter char *rhs; 122438032Speter{ 122538032Speter datum key; 122638032Speter datum data; 122764562Sgshapiro int status; 122838032Speter char keybuf[MAXNAME + 1]; 122938032Speter 123038032Speter if (tTd(38, 12)) 123164562Sgshapiro dprintf("ndbm_map_store(%s, %s, %s)\n", 123238032Speter map->map_mname, lhs, rhs); 123338032Speter 123438032Speter key.dsize = strlen(lhs); 123538032Speter key.dptr = lhs; 123638032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 123738032Speter { 123838032Speter if (key.dsize > sizeof keybuf - 1) 123938032Speter key.dsize = sizeof keybuf - 1; 124064562Sgshapiro memmove(keybuf, key.dptr, key.dsize); 124138032Speter keybuf[key.dsize] = '\0'; 124238032Speter makelower(keybuf); 124338032Speter key.dptr = keybuf; 124438032Speter } 124538032Speter 124638032Speter data.dsize = strlen(rhs); 124738032Speter data.dptr = rhs; 124838032Speter 124938032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 125038032Speter { 125138032Speter key.dsize++; 125238032Speter data.dsize++; 125338032Speter } 125438032Speter 125564562Sgshapiro status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 125664562Sgshapiro if (status > 0) 125738032Speter { 125838032Speter if (!bitset(MF_APPEND, map->map_mflags)) 125938032Speter message("050 Warning: duplicate alias name %s", lhs); 126038032Speter else 126138032Speter { 126238032Speter static char *buf = NULL; 126338032Speter static int bufsiz = 0; 126438032Speter auto int xstat; 126538032Speter datum old; 126638032Speter 126738032Speter old.dptr = ndbm_map_lookup(map, key.dptr, 126838032Speter (char **)NULL, &xstat); 126938032Speter if (old.dptr != NULL && *(char *) old.dptr != '\0') 127038032Speter { 127138032Speter old.dsize = strlen(old.dptr); 127238032Speter if (data.dsize + old.dsize + 2 > bufsiz) 127338032Speter { 127438032Speter if (buf != NULL) 127538032Speter (void) free(buf); 127638032Speter bufsiz = data.dsize + old.dsize + 2; 127738032Speter buf = xalloc(bufsiz); 127838032Speter } 127938032Speter snprintf(buf, bufsiz, "%s,%s", 128038032Speter data.dptr, old.dptr); 128138032Speter data.dsize = data.dsize + old.dsize + 1; 128238032Speter data.dptr = buf; 128338032Speter if (tTd(38, 9)) 128464562Sgshapiro dprintf("ndbm_map_store append=%s\n", 128564562Sgshapiro data.dptr); 128638032Speter } 128738032Speter } 128864562Sgshapiro status = dbm_store((DBM *) map->map_db1, 128964562Sgshapiro key, data, DBM_REPLACE); 129038032Speter } 129164562Sgshapiro if (status != 0) 129264562Sgshapiro syserr("readaliases: dbm put (%s): %d", lhs, status); 129338032Speter} 129438032Speter 129538032Speter 129638032Speter/* 129738032Speter** NDBM_MAP_CLOSE -- close the database 129838032Speter*/ 129938032Speter 130038032Spetervoid 130138032Speterndbm_map_close(map) 130238032Speter register MAP *map; 130338032Speter{ 130438032Speter if (tTd(38, 9)) 130564562Sgshapiro dprintf("ndbm_map_close(%s, %s, %lx)\n", 130638032Speter map->map_mname, map->map_file, map->map_mflags); 130738032Speter 130838032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 130938032Speter { 131064562Sgshapiro# ifdef NDBM_YP_COMPAT 131138032Speter bool inclnull; 131242575Speter char buf[MAXHOSTNAMELEN]; 131338032Speter 131438032Speter inclnull = bitset(MF_INCLNULL, map->map_mflags); 131538032Speter map->map_mflags &= ~MF_INCLNULL; 131638032Speter 131738032Speter if (strstr(map->map_file, "/yp/") != NULL) 131838032Speter { 131938032Speter long save_mflags = map->map_mflags; 132038032Speter 132138032Speter map->map_mflags |= MF_NOFOLDCASE; 132238032Speter 132338032Speter (void) snprintf(buf, sizeof buf, "%010ld", curtime()); 132438032Speter ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 132538032Speter 132638032Speter (void) gethostname(buf, sizeof buf); 132738032Speter ndbm_map_store(map, "YP_MASTER_NAME", buf); 132838032Speter 132938032Speter map->map_mflags = save_mflags; 133038032Speter } 133138032Speter 133238032Speter if (inclnull) 133338032Speter map->map_mflags |= MF_INCLNULL; 133464562Sgshapiro# endif /* NDBM_YP_COMPAT */ 133538032Speter 133638032Speter /* write out the distinguished alias */ 133738032Speter ndbm_map_store(map, "@", "@"); 133838032Speter } 133938032Speter dbm_close((DBM *) map->map_db1); 134038032Speter 134138032Speter /* release lock (if needed) */ 134264562Sgshapiro# if !LOCK_ON_OPEN 134338032Speter if (map->map_lockfd >= 0) 134438032Speter (void) close(map->map_lockfd); 134564562Sgshapiro# endif /* !LOCK_ON_OPEN */ 134638032Speter} 134738032Speter 134864562Sgshapiro#endif /* NDBM */ 134938032Speter/* 135038032Speter** NEWDB (Hash and BTree) Modules 135138032Speter*/ 135238032Speter 135338032Speter#ifdef NEWDB 135438032Speter 135538032Speter/* 135638032Speter** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 135738032Speter** 135838032Speter** These do rather bizarre locking. If you can lock on open, 135938032Speter** do that to avoid the condition of opening a database that 136038032Speter** is being rebuilt. If you don't, we'll try to fake it, but 136138032Speter** there will be a race condition. If opening for read-only, 136238032Speter** we immediately release the lock to avoid freezing things up. 136338032Speter** We really ought to hold the lock, but guarantee that we won't 136438032Speter** be pokey about it. That's hard to do. 136538032Speter*/ 136638032Speter 136738032Speter/* these should be K line arguments */ 136864562Sgshapiro# if DB_VERSION_MAJOR < 2 136964562Sgshapiro# define db_cachesize cachesize 137064562Sgshapiro# define h_nelem nelem 137164562Sgshapiro# ifndef DB_CACHE_SIZE 137264562Sgshapiro# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 137364562Sgshapiro# endif /* ! DB_CACHE_SIZE */ 137464562Sgshapiro# ifndef DB_HASH_NELEM 137564562Sgshapiro# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 137664562Sgshapiro# endif /* ! DB_HASH_NELEM */ 137764562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 137838032Speter 137938032Speterbool 138038032Speterbt_map_open(map, mode) 138138032Speter MAP *map; 138238032Speter int mode; 138338032Speter{ 138464562Sgshapiro# if DB_VERSION_MAJOR < 2 138538032Speter BTREEINFO btinfo; 138664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 138764562Sgshapiro# if DB_VERSION_MAJOR == 2 138838032Speter DB_INFO btinfo; 138964562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 139064562Sgshapiro# if DB_VERSION_MAJOR > 2 139164562Sgshapiro void *btinfo = NULL; 139264562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 139338032Speter 139438032Speter if (tTd(38, 2)) 139564562Sgshapiro dprintf("bt_map_open(%s, %s, %d)\n", 139638032Speter map->map_mname, map->map_file, mode); 139738032Speter 139864562Sgshapiro# if DB_VERSION_MAJOR < 3 139964562Sgshapiro memset(&btinfo, '\0', sizeof btinfo); 140064562Sgshapiro# ifdef DB_CACHE_SIZE 140138032Speter btinfo.db_cachesize = DB_CACHE_SIZE; 140264562Sgshapiro# endif /* DB_CACHE_SIZE */ 140364562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 140464562Sgshapiro 140538032Speter return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 140638032Speter} 140738032Speter 140838032Speterbool 140938032Speterhash_map_open(map, mode) 141038032Speter MAP *map; 141138032Speter int mode; 141238032Speter{ 141364562Sgshapiro# if DB_VERSION_MAJOR < 2 141438032Speter HASHINFO hinfo; 141564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 141664562Sgshapiro# if DB_VERSION_MAJOR == 2 141738032Speter DB_INFO hinfo; 141864562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 141964562Sgshapiro# if DB_VERSION_MAJOR > 2 142064562Sgshapiro void *hinfo = NULL; 142164562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 142238032Speter 142338032Speter if (tTd(38, 2)) 142464562Sgshapiro dprintf("hash_map_open(%s, %s, %d)\n", 142538032Speter map->map_mname, map->map_file, mode); 142638032Speter 142764562Sgshapiro# if DB_VERSION_MAJOR < 3 142864562Sgshapiro memset(&hinfo, '\0', sizeof hinfo); 142964562Sgshapiro# ifdef DB_HASH_NELEM 143038032Speter hinfo.h_nelem = DB_HASH_NELEM; 143164562Sgshapiro# endif /* DB_HASH_NELEM */ 143264562Sgshapiro# ifdef DB_CACHE_SIZE 143338032Speter hinfo.db_cachesize = DB_CACHE_SIZE; 143464562Sgshapiro# endif /* DB_CACHE_SIZE */ 143564562Sgshapiro# endif /* DB_VERSION_MAJOR < 3 */ 143664562Sgshapiro 143738032Speter return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 143838032Speter} 143938032Speter 144064562Sgshapirostatic bool 144138032Speterdb_map_open(map, mode, mapclassname, dbtype, openinfo) 144238032Speter MAP *map; 144338032Speter int mode; 144438032Speter char *mapclassname; 144538032Speter DBTYPE dbtype; 144664562Sgshapiro# if DB_VERSION_MAJOR < 2 144738032Speter const void *openinfo; 144864562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 144964562Sgshapiro# if DB_VERSION_MAJOR == 2 145038032Speter DB_INFO *openinfo; 145164562Sgshapiro# endif /* DB_VERSION_MAJOR == 2 */ 145264562Sgshapiro# if DB_VERSION_MAJOR > 2 145364562Sgshapiro void **openinfo; 145464562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 145538032Speter{ 145638032Speter DB *db = NULL; 145738032Speter int i; 145838032Speter int omode; 145938032Speter int smode = S_IREAD; 146038032Speter int fd; 146164562Sgshapiro long sff; 146264562Sgshapiro int save_errno; 146338032Speter struct stat st; 146438032Speter char buf[MAXNAME + 1]; 146538032Speter 146638032Speter /* do initial file and directory checks */ 146764562Sgshapiro (void) strlcpy(buf, map->map_file, sizeof buf - 3); 146838032Speter i = strlen(buf); 146938032Speter if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 147064562Sgshapiro (void) strlcat(buf, ".db", sizeof buf); 147138032Speter 147238032Speter mode &= O_ACCMODE; 147338032Speter omode = mode; 147438032Speter 147538032Speter sff = SFF_ROOTOK|SFF_REGONLY; 147638032Speter if (mode == O_RDWR) 147738032Speter { 147838032Speter sff |= SFF_CREAT; 147964562Sgshapiro if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 148038032Speter sff |= SFF_NOSLINK; 148164562Sgshapiro if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 148238032Speter sff |= SFF_NOHLINK; 148338032Speter smode = S_IWRITE; 148438032Speter } 148538032Speter else 148638032Speter { 148764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 148838032Speter sff |= SFF_NOWLINK; 148938032Speter } 149064562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 149138032Speter sff |= SFF_SAFEDIRPATH; 149238032Speter i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 149364562Sgshapiro 149464562Sgshapiro# if !_FFR_REMOVE_AUTOREBUILD 149538032Speter if (i == ENOENT && AutoRebuild && 149638032Speter bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && 149738032Speter (bitset(MF_IMPL_HASH, map->map_mflags) || 149838032Speter bitset(MF_ALIAS, map->map_mflags)) && 149938032Speter mode == O_RDONLY) 150038032Speter { 150138032Speter bool impl = bitset(MF_IMPL_HASH, map->map_mflags); 150238032Speter 150338032Speter /* may be able to rebuild */ 150438032Speter map->map_mflags &= ~MF_IMPL_HASH; 150538032Speter if (!rebuildaliases(map, TRUE)) 150638032Speter return FALSE; 150738032Speter if (impl) 150838032Speter return impl_map_open(map, O_RDONLY); 150938032Speter else 151038032Speter return db_map_open(map, O_RDONLY, mapclassname, 151138032Speter dbtype, openinfo); 151238032Speter } 151364562Sgshapiro# endif /* !_FFR_REMOVE_AUTOREBUILD */ 151438032Speter 151538032Speter if (i != 0) 151638032Speter { 151738032Speter char *prob = "unsafe"; 151838032Speter 151938032Speter /* cannot open this map */ 152038032Speter if (i == ENOENT) 152138032Speter prob = "missing"; 152238032Speter if (tTd(38, 2)) 152364562Sgshapiro dprintf("\t%s map file: %s\n", prob, errstring(i)); 152438032Speter errno = i; 152538032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 152638032Speter syserr("%s map \"%s\": %s map file %s", 152738032Speter mapclassname, map->map_mname, prob, buf); 152838032Speter return FALSE; 152938032Speter } 153038032Speter if (st.st_mode == ST_MODE_NOFILE) 153138032Speter omode |= O_CREAT|O_EXCL; 153238032Speter 153338032Speter map->map_lockfd = -1; 153438032Speter 153564562Sgshapiro# if LOCK_ON_OPEN 153638032Speter if (mode == O_RDWR) 153738032Speter omode |= O_TRUNC|O_EXLOCK; 153838032Speter else 153938032Speter omode |= O_SHLOCK; 154064562Sgshapiro# else /* LOCK_ON_OPEN */ 154138032Speter /* 154238032Speter ** Pre-lock the file to avoid race conditions. In particular, 154338032Speter ** since dbopen returns NULL if the file is zero length, we 154438032Speter ** must have a locked instance around the dbopen. 154538032Speter */ 154638032Speter 154738032Speter fd = open(buf, omode, DBMMODE); 154838032Speter if (fd < 0) 154938032Speter { 155038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 155138032Speter syserr("db_map_open: cannot pre-open database %s", buf); 155238032Speter return FALSE; 155338032Speter } 155438032Speter 155538032Speter /* make sure no baddies slipped in just before the open... */ 155638032Speter if (filechanged(buf, fd, &st)) 155738032Speter { 155864562Sgshapiro save_errno = errno; 155938032Speter (void) close(fd); 156038032Speter errno = save_errno; 156138032Speter syserr("db_map_open(%s): file changed after pre-open", buf); 156238032Speter return FALSE; 156338032Speter } 156438032Speter 156538032Speter /* if new file, get the "before" bits for later filechanged check */ 156638032Speter if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 156738032Speter { 156864562Sgshapiro save_errno = errno; 156938032Speter (void) close(fd); 157038032Speter errno = save_errno; 157138032Speter syserr("db_map_open(%s): cannot fstat pre-opened file", 157238032Speter buf); 157338032Speter return FALSE; 157438032Speter } 157538032Speter 157638032Speter /* actually lock the pre-opened file */ 157738032Speter if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 157838032Speter syserr("db_map_open: cannot lock %s", buf); 157938032Speter 158038032Speter /* set up mode bits for dbopen */ 158138032Speter if (mode == O_RDWR) 158238032Speter omode |= O_TRUNC; 158338032Speter omode &= ~(O_EXCL|O_CREAT); 158464562Sgshapiro# endif /* LOCK_ON_OPEN */ 158538032Speter 158664562Sgshapiro# if DB_VERSION_MAJOR < 2 158738032Speter db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 158864562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 158938032Speter { 159038032Speter int flags = 0; 159164562Sgshapiro# if DB_VERSION_MAJOR > 2 159264562Sgshapiro int ret; 159364562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 159438032Speter 159538032Speter if (mode == O_RDONLY) 159638032Speter flags |= DB_RDONLY; 159738032Speter if (bitset(O_CREAT, omode)) 159838032Speter flags |= DB_CREATE; 159938032Speter if (bitset(O_TRUNC, omode)) 160038032Speter flags |= DB_TRUNCATE; 160138032Speter 160264562Sgshapiro# if !HASFLOCK && defined(DB_FCNTL_LOCKING) 160364562Sgshapiro flags |= DB_FCNTL_LOCKING; 160464562Sgshapiro# endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ 160564562Sgshapiro 160664562Sgshapiro# if DB_VERSION_MAJOR > 2 160764562Sgshapiro ret = db_create(&db, NULL, 0); 160864562Sgshapiro# ifdef DB_CACHE_SIZE 160964562Sgshapiro if (ret == 0 && db != NULL) 161064562Sgshapiro { 161164562Sgshapiro ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 161264562Sgshapiro if (ret != 0) 161364562Sgshapiro { 161464562Sgshapiro (void) db->close(db, 0); 161564562Sgshapiro db = NULL; 161664562Sgshapiro } 161764562Sgshapiro } 161864562Sgshapiro# endif /* DB_CACHE_SIZE */ 161964562Sgshapiro# ifdef DB_HASH_NELEM 162064562Sgshapiro if (dbtype == DB_HASH && ret == 0 && db != NULL) 162164562Sgshapiro { 162264562Sgshapiro ret = db->set_h_nelem(db, DB_HASH_NELEM); 162364562Sgshapiro if (ret != 0) 162464562Sgshapiro { 162564562Sgshapiro (void) db->close(db, 0); 162664562Sgshapiro db = NULL; 162764562Sgshapiro } 162864562Sgshapiro } 162964562Sgshapiro# endif /* DB_HASH_NELEM */ 163064562Sgshapiro if (ret == 0 && db != NULL) 163164562Sgshapiro { 163264562Sgshapiro ret = db->open(db, buf, NULL, dbtype, flags, DBMMODE); 163364562Sgshapiro if (ret != 0) 163464562Sgshapiro { 163573188Sgshapiro#ifdef DB_OLD_VERSION 163673188Sgshapiro if (ret == DB_OLD_VERSION) 163773188Sgshapiro ret = EINVAL; 163873188Sgshapiro#endif /* DB_OLD_VERSION */ 163964562Sgshapiro (void) db->close(db, 0); 164064562Sgshapiro db = NULL; 164164562Sgshapiro } 164264562Sgshapiro } 164364562Sgshapiro errno = ret; 164464562Sgshapiro# else /* DB_VERSION_MAJOR > 2 */ 164538032Speter errno = db_open(buf, dbtype, flags, DBMMODE, 164638032Speter NULL, openinfo, &db); 164764562Sgshapiro# endif /* DB_VERSION_MAJOR > 2 */ 164838032Speter } 164964562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 165064562Sgshapiro save_errno = errno; 165138032Speter 165264562Sgshapiro# if !LOCK_ON_OPEN 165338032Speter if (mode == O_RDWR) 165438032Speter map->map_lockfd = fd; 165538032Speter else 165638032Speter (void) close(fd); 165764562Sgshapiro# endif /* !LOCK_ON_OPEN */ 165838032Speter 165938032Speter if (db == NULL) 166038032Speter { 166138032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 166238032Speter aliaswait(map, ".db", FALSE)) 166338032Speter return TRUE; 166464562Sgshapiro# if !LOCK_ON_OPEN 166538032Speter if (map->map_lockfd >= 0) 166638032Speter (void) close(map->map_lockfd); 166764562Sgshapiro# endif /* !LOCK_ON_OPEN */ 166864562Sgshapiro errno = save_errno; 166938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 167038032Speter syserr("Cannot open %s database %s", 167138032Speter mapclassname, buf); 167238032Speter return FALSE; 167338032Speter } 167438032Speter 167564562Sgshapiro# if DB_VERSION_MAJOR < 2 167638032Speter fd = db->fd(db); 167764562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 167838032Speter fd = -1; 167938032Speter errno = db->fd(db, &fd); 168064562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 168138032Speter if (filechanged(buf, fd, &st)) 168238032Speter { 168364562Sgshapiro save_errno = errno; 168464562Sgshapiro# if DB_VERSION_MAJOR < 2 168564562Sgshapiro (void) db->close(db); 168664562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 168738032Speter errno = db->close(db, 0); 168864562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 168964562Sgshapiro# if !LOCK_ON_OPEN 169038032Speter if (map->map_lockfd >= 0) 169164562Sgshapiro (void) close(map->map_lockfd); 169264562Sgshapiro# endif /* !LOCK_ON_OPEN */ 169338032Speter errno = save_errno; 169438032Speter syserr("db_map_open(%s): file changed after open", buf); 169538032Speter return FALSE; 169638032Speter } 169738032Speter 169838032Speter if (mode == O_RDWR) 169938032Speter map->map_mflags |= MF_LOCKED; 170064562Sgshapiro# if LOCK_ON_OPEN 170138032Speter if (fd >= 0 && mode == O_RDONLY) 170238032Speter { 170338032Speter (void) lockfile(fd, buf, NULL, LOCK_UN); 170438032Speter } 170564562Sgshapiro# endif /* LOCK_ON_OPEN */ 170638032Speter 170738032Speter /* try to make sure that at least the database header is on disk */ 170838032Speter if (mode == O_RDWR) 170938032Speter { 171038032Speter (void) db->sync(db, 0); 171142575Speter if (geteuid() == 0 && TrustedUid != 0) 171238032Speter { 171364562Sgshapiro# if HASFCHOWN 171442575Speter if (fchown(fd, TrustedUid, -1) < 0) 171538032Speter { 171638032Speter int err = errno; 171738032Speter 171838032Speter sm_syslog(LOG_ALERT, NOQID, 171938032Speter "ownership change on %s failed: %s", 172038032Speter buf, errstring(err)); 172138032Speter message("050 ownership change on %s failed: %s", 172238032Speter buf, errstring(err)); 172338032Speter } 172464562Sgshapiro# endif /* HASFCHOWN */ 172538032Speter } 172638032Speter } 172738032Speter 172864562Sgshapiro map->map_db2 = (ARBPTR_T) db; 172964562Sgshapiro 173064562Sgshapiro /* 173164562Sgshapiro ** Need to set map_mtime before the call to aliaswait() 173264562Sgshapiro ** as aliaswait() will call map_lookup() which requires 173364562Sgshapiro ** map_mtime to be set 173464562Sgshapiro */ 173564562Sgshapiro 173638032Speter if (fd >= 0 && fstat(fd, &st) >= 0) 173738032Speter map->map_mtime = st.st_mtime; 173838032Speter 173938032Speter if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 174038032Speter !aliaswait(map, ".db", TRUE)) 174138032Speter return FALSE; 174238032Speter return TRUE; 174338032Speter} 174438032Speter 174538032Speter 174638032Speter/* 174738032Speter** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 174838032Speter*/ 174938032Speter 175038032Speterchar * 175138032Speterdb_map_lookup(map, name, av, statp) 175238032Speter MAP *map; 175338032Speter char *name; 175438032Speter char **av; 175538032Speter int *statp; 175638032Speter{ 175738032Speter DBT key, val; 175838032Speter register DB *db = (DB *) map->map_db2; 175938032Speter int i; 176038032Speter int st; 176164562Sgshapiro int save_errno; 176238032Speter int fd; 176338032Speter struct stat stbuf; 176438032Speter char keybuf[MAXNAME + 1]; 176538032Speter char buf[MAXNAME + 1]; 176638032Speter 176764562Sgshapiro memset(&key, '\0', sizeof key); 176864562Sgshapiro memset(&val, '\0', sizeof val); 176938032Speter 177038032Speter if (tTd(38, 20)) 177164562Sgshapiro dprintf("db_map_lookup(%s, %s)\n", 177238032Speter map->map_mname, name); 177338032Speter 177438032Speter i = strlen(map->map_file); 177538032Speter if (i > MAXNAME) 177638032Speter i = MAXNAME; 177764562Sgshapiro (void) strlcpy(buf, map->map_file, i + 1); 177838032Speter if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 177938032Speter buf[i - 3] = '\0'; 178038032Speter 178138032Speter key.size = strlen(name); 178238032Speter if (key.size > sizeof keybuf - 1) 178338032Speter key.size = sizeof keybuf - 1; 178438032Speter key.data = keybuf; 178564562Sgshapiro memmove(keybuf, name, key.size); 178638032Speter keybuf[key.size] = '\0'; 178738032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 178838032Speter makelower(keybuf); 178938032Speter lockdb: 179064562Sgshapiro# if DB_VERSION_MAJOR < 2 179138032Speter fd = db->fd(db); 179264562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 179338032Speter fd = -1; 179438032Speter errno = db->fd(db, &fd); 179564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 179638032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 179738032Speter (void) lockfile(fd, buf, ".db", LOCK_SH); 179838032Speter if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 179938032Speter { 180038032Speter /* Reopen the database to sync the cache */ 180138032Speter int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 180238032Speter : O_RDONLY; 180338032Speter 180464562Sgshapiro if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 180564562Sgshapiro (void) lockfile(fd, buf, ".db", LOCK_UN); 180638032Speter map->map_class->map_close(map); 180738032Speter map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 180838032Speter if (map->map_class->map_open(map, omode)) 180938032Speter { 181038032Speter map->map_mflags |= MF_OPEN; 181142575Speter map->map_pid = getpid(); 181238032Speter if ((omode && O_ACCMODE) == O_RDWR) 181338032Speter map->map_mflags |= MF_WRITABLE; 181438032Speter db = (DB *) map->map_db2; 181538032Speter goto lockdb; 181638032Speter } 181738032Speter else 181838032Speter { 181938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 182038032Speter { 182138032Speter extern MAPCLASS BogusMapClass; 182238032Speter 182338032Speter *statp = EX_TEMPFAIL; 182438032Speter map->map_class = &BogusMapClass; 182538032Speter map->map_mflags |= MF_OPEN; 182642575Speter map->map_pid = getpid(); 182738032Speter syserr("Cannot reopen DB database %s", 182838032Speter map->map_file); 182938032Speter } 183038032Speter return NULL; 183138032Speter } 183238032Speter } 183338032Speter 183438032Speter st = 1; 183538032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 183638032Speter { 183764562Sgshapiro# if DB_VERSION_MAJOR < 2 183838032Speter st = db->get(db, &key, &val, 0); 183964562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 184038032Speter errno = db->get(db, NULL, &key, &val, 0); 184138032Speter switch (errno) 184238032Speter { 184338032Speter case DB_NOTFOUND: 184438032Speter case DB_KEYEMPTY: 184538032Speter st = 1; 184638032Speter break; 184738032Speter 184838032Speter case 0: 184938032Speter st = 0; 185038032Speter break; 185138032Speter 185238032Speter default: 185338032Speter st = -1; 185438032Speter break; 185538032Speter } 185664562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 185738032Speter if (st == 0) 185838032Speter map->map_mflags &= ~MF_TRY1NULL; 185938032Speter } 186038032Speter if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 186138032Speter { 186238032Speter key.size++; 186364562Sgshapiro# if DB_VERSION_MAJOR < 2 186438032Speter st = db->get(db, &key, &val, 0); 186564562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 186638032Speter errno = db->get(db, NULL, &key, &val, 0); 186738032Speter switch (errno) 186838032Speter { 186938032Speter case DB_NOTFOUND: 187038032Speter case DB_KEYEMPTY: 187138032Speter st = 1; 187238032Speter break; 187338032Speter 187438032Speter case 0: 187538032Speter st = 0; 187638032Speter break; 187738032Speter 187838032Speter default: 187938032Speter st = -1; 188038032Speter break; 188138032Speter } 188264562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 188338032Speter if (st == 0) 188438032Speter map->map_mflags &= ~MF_TRY0NULL; 188538032Speter } 188664562Sgshapiro save_errno = errno; 188738032Speter if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 188838032Speter (void) lockfile(fd, buf, ".db", LOCK_UN); 188938032Speter if (st != 0) 189038032Speter { 189164562Sgshapiro errno = save_errno; 189238032Speter if (st < 0) 189338032Speter syserr("db_map_lookup: get (%s)", name); 189438032Speter return NULL; 189538032Speter } 189638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 189738032Speter return map_rewrite(map, name, strlen(name), NULL); 189838032Speter else 189938032Speter return map_rewrite(map, val.data, val.size, av); 190038032Speter} 190138032Speter 190238032Speter 190338032Speter/* 190438032Speter** DB_MAP_STORE -- store a datum in the NEWDB database 190538032Speter*/ 190638032Speter 190738032Spetervoid 190838032Speterdb_map_store(map, lhs, rhs) 190938032Speter register MAP *map; 191038032Speter char *lhs; 191138032Speter char *rhs; 191238032Speter{ 191364562Sgshapiro int status; 191438032Speter DBT key; 191538032Speter DBT data; 191638032Speter register DB *db = map->map_db2; 191738032Speter char keybuf[MAXNAME + 1]; 191838032Speter 191964562Sgshapiro memset(&key, '\0', sizeof key); 192064562Sgshapiro memset(&data, '\0', sizeof data); 192138032Speter 192238032Speter if (tTd(38, 12)) 192364562Sgshapiro dprintf("db_map_store(%s, %s, %s)\n", 192438032Speter map->map_mname, lhs, rhs); 192538032Speter 192638032Speter key.size = strlen(lhs); 192738032Speter key.data = lhs; 192838032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 192938032Speter { 193038032Speter if (key.size > sizeof keybuf - 1) 193138032Speter key.size = sizeof keybuf - 1; 193264562Sgshapiro memmove(keybuf, key.data, key.size); 193338032Speter keybuf[key.size] = '\0'; 193438032Speter makelower(keybuf); 193538032Speter key.data = keybuf; 193638032Speter } 193738032Speter 193838032Speter data.size = strlen(rhs); 193938032Speter data.data = rhs; 194038032Speter 194138032Speter if (bitset(MF_INCLNULL, map->map_mflags)) 194238032Speter { 194338032Speter key.size++; 194438032Speter data.size++; 194538032Speter } 194638032Speter 194764562Sgshapiro# if DB_VERSION_MAJOR < 2 194864562Sgshapiro status = db->put(db, &key, &data, R_NOOVERWRITE); 194964562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 195038032Speter errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 195138032Speter switch (errno) 195238032Speter { 195338032Speter case DB_KEYEXIST: 195464562Sgshapiro status = 1; 195538032Speter break; 195638032Speter 195738032Speter case 0: 195864562Sgshapiro status = 0; 195938032Speter break; 196038032Speter 196138032Speter default: 196264562Sgshapiro status = -1; 196338032Speter break; 196438032Speter } 196564562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 196664562Sgshapiro if (status > 0) 196738032Speter { 196838032Speter if (!bitset(MF_APPEND, map->map_mflags)) 196938032Speter message("050 Warning: duplicate alias name %s", lhs); 197038032Speter else 197138032Speter { 197238032Speter static char *buf = NULL; 197338032Speter static int bufsiz = 0; 197438032Speter DBT old; 197538032Speter 197664562Sgshapiro memset(&old, '\0', sizeof old); 197738032Speter 197864562Sgshapiro old.data = db_map_lookup(map, key.data, 197964562Sgshapiro (char **)NULL, &status); 198038032Speter if (old.data != NULL) 198138032Speter { 198238032Speter old.size = strlen(old.data); 198364562Sgshapiro if (data.size + old.size + 2 > (size_t)bufsiz) 198438032Speter { 198538032Speter if (buf != NULL) 198638032Speter (void) free(buf); 198738032Speter bufsiz = data.size + old.size + 2; 198838032Speter buf = xalloc(bufsiz); 198938032Speter } 199038032Speter snprintf(buf, bufsiz, "%s,%s", 199138032Speter (char *) data.data, (char *) old.data); 199238032Speter data.size = data.size + old.size + 1; 199338032Speter data.data = buf; 199438032Speter if (tTd(38, 9)) 199564562Sgshapiro dprintf("db_map_store append=%s\n", 199664562Sgshapiro (char *) data.data); 199738032Speter } 199838032Speter } 199964562Sgshapiro# if DB_VERSION_MAJOR < 2 200064562Sgshapiro status = db->put(db, &key, &data, 0); 200164562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 200264562Sgshapiro status = errno = db->put(db, NULL, &key, &data, 0); 200364562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 200438032Speter } 200564562Sgshapiro if (status != 0) 200638032Speter syserr("readaliases: db put (%s)", lhs); 200738032Speter} 200838032Speter 200938032Speter 201038032Speter/* 201138032Speter** DB_MAP_CLOSE -- add distinguished entries and close the database 201238032Speter*/ 201338032Speter 201438032Spetervoid 201538032Speterdb_map_close(map) 201638032Speter MAP *map; 201738032Speter{ 201838032Speter register DB *db = map->map_db2; 201938032Speter 202038032Speter if (tTd(38, 9)) 202164562Sgshapiro dprintf("db_map_close(%s, %s, %lx)\n", 202238032Speter map->map_mname, map->map_file, map->map_mflags); 202338032Speter 202438032Speter if (bitset(MF_WRITABLE, map->map_mflags)) 202538032Speter { 202638032Speter /* write out the distinguished alias */ 202738032Speter db_map_store(map, "@", "@"); 202838032Speter } 202938032Speter 203038032Speter (void) db->sync(db, 0); 203138032Speter 203264562Sgshapiro# if !LOCK_ON_OPEN 203338032Speter if (map->map_lockfd >= 0) 203438032Speter (void) close(map->map_lockfd); 203564562Sgshapiro# endif /* !LOCK_ON_OPEN */ 203638032Speter 203764562Sgshapiro# if DB_VERSION_MAJOR < 2 203838032Speter if (db->close(db) != 0) 203964562Sgshapiro# else /* DB_VERSION_MAJOR < 2 */ 204042575Speter /* 204142575Speter ** Berkeley DB can use internal shared memory 204242575Speter ** locking for its memory pool. Closing a map 204342575Speter ** opened by another process will interfere 204442575Speter ** with the shared memory and locks of the parent 204542575Speter ** process leaving things in a bad state. 204643730Speter */ 204743730Speter 204843730Speter /* 204942575Speter ** If this map was not opened by the current 205043730Speter ** process, do not close the map but recover 205142575Speter ** the file descriptor. 205242575Speter */ 205342575Speter if (map->map_pid != getpid()) 205442575Speter { 205542575Speter int fd = -1; 205642575Speter 205742575Speter errno = db->fd(db, &fd); 205842575Speter if (fd >= 0) 205942575Speter (void) close(fd); 206042575Speter return; 206142575Speter } 206242575Speter 206338032Speter if ((errno = db->close(db, 0)) != 0) 206464562Sgshapiro# endif /* DB_VERSION_MAJOR < 2 */ 206542575Speter syserr("db_map_close(%s, %s, %lx): db close failure", 206642575Speter map->map_mname, map->map_file, map->map_mflags); 206738032Speter} 206864562Sgshapiro#endif /* NEWDB */ 206938032Speter/* 207038032Speter** NIS Modules 207138032Speter*/ 207238032Speter 207364562Sgshapiro#ifdef NIS 207438032Speter 207538032Speter# ifndef YPERR_BUSY 207638032Speter# define YPERR_BUSY 16 207764562Sgshapiro# endif /* ! YPERR_BUSY */ 207838032Speter 207938032Speter/* 208038032Speter** NIS_MAP_OPEN -- open DBM map 208138032Speter*/ 208238032Speter 208338032Speterbool 208438032Speternis_map_open(map, mode) 208538032Speter MAP *map; 208638032Speter int mode; 208738032Speter{ 208838032Speter int yperr; 208938032Speter register char *p; 209038032Speter auto char *vp; 209138032Speter auto int vsize; 209238032Speter 209338032Speter if (tTd(38, 2)) 209464562Sgshapiro dprintf("nis_map_open(%s, %s, %d)\n", 209538032Speter map->map_mname, map->map_file, mode); 209638032Speter 209738032Speter mode &= O_ACCMODE; 209838032Speter if (mode != O_RDONLY) 209938032Speter { 210038032Speter /* issue a pseudo-error message */ 210164562Sgshapiro# ifdef ENOSYS 210238032Speter errno = ENOSYS; 210364562Sgshapiro# else /* ENOSYS */ 210464562Sgshapiro# ifdef EFTYPE 210538032Speter errno = EFTYPE; 210664562Sgshapiro# else /* EFTYPE */ 210738032Speter errno = ENXIO; 210864562Sgshapiro# endif /* EFTYPE */ 210964562Sgshapiro# endif /* ENOSYS */ 211038032Speter return FALSE; 211138032Speter } 211238032Speter 211338032Speter p = strchr(map->map_file, '@'); 211438032Speter if (p != NULL) 211538032Speter { 211638032Speter *p++ = '\0'; 211738032Speter if (*p != '\0') 211838032Speter map->map_domain = p; 211938032Speter } 212038032Speter 212138032Speter if (*map->map_file == '\0') 212238032Speter map->map_file = "mail.aliases"; 212338032Speter 212438032Speter if (map->map_domain == NULL) 212538032Speter { 212638032Speter yperr = yp_get_default_domain(&map->map_domain); 212738032Speter if (yperr != 0) 212838032Speter { 212938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 213064562Sgshapiro syserr("421 4.3.5 NIS map %s specified, but NIS not running", 213164562Sgshapiro map->map_file); 213238032Speter return FALSE; 213338032Speter } 213438032Speter } 213538032Speter 213638032Speter /* check to see if this map actually exists */ 213764562Sgshapiro vp = NULL; 213838032Speter yperr = yp_match(map->map_domain, map->map_file, "@", 1, 213938032Speter &vp, &vsize); 214038032Speter if (tTd(38, 10)) 214164562Sgshapiro dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 214238032Speter map->map_domain, map->map_file, yperr_string(yperr)); 214364562Sgshapiro if (vp != NULL) 214464562Sgshapiro free(vp); 214564562Sgshapiro 214638032Speter if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 214738032Speter { 214838032Speter /* 214938032Speter ** We ought to be calling aliaswait() here if this is an 215038032Speter ** alias file, but powerful HP-UX NIS servers apparently 215138032Speter ** don't insert the @:@ token into the alias map when it 215238032Speter ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 215338032Speter */ 215438032Speter 215564562Sgshapiro# if 0 215638032Speter if (!bitset(MF_ALIAS, map->map_mflags) || 215738032Speter aliaswait(map, NULL, TRUE)) 215864562Sgshapiro# endif /* 0 */ 215938032Speter return TRUE; 216038032Speter } 216138032Speter 216238032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 216338032Speter { 216464562Sgshapiro syserr("421 4.0.0 Cannot bind to map %s in domain %s: %s", 216538032Speter map->map_file, map->map_domain, yperr_string(yperr)); 216638032Speter } 216738032Speter 216838032Speter return FALSE; 216938032Speter} 217038032Speter 217138032Speter 217238032Speter/* 217338032Speter** NIS_MAP_LOOKUP -- look up a datum in a NIS map 217438032Speter*/ 217538032Speter 217638032Speter/* ARGSUSED3 */ 217738032Speterchar * 217838032Speternis_map_lookup(map, name, av, statp) 217938032Speter MAP *map; 218038032Speter char *name; 218138032Speter char **av; 218238032Speter int *statp; 218338032Speter{ 218438032Speter char *vp; 218538032Speter auto int vsize; 218638032Speter int buflen; 218738032Speter int yperr; 218838032Speter char keybuf[MAXNAME + 1]; 218938032Speter 219038032Speter if (tTd(38, 20)) 219164562Sgshapiro dprintf("nis_map_lookup(%s, %s)\n", 219238032Speter map->map_mname, name); 219338032Speter 219438032Speter buflen = strlen(name); 219538032Speter if (buflen > sizeof keybuf - 1) 219638032Speter buflen = sizeof keybuf - 1; 219764562Sgshapiro memmove(keybuf, name, buflen); 219838032Speter keybuf[buflen] = '\0'; 219938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 220038032Speter makelower(keybuf); 220138032Speter yperr = YPERR_KEY; 220264562Sgshapiro vp = NULL; 220338032Speter if (bitset(MF_TRY0NULL, map->map_mflags)) 220438032Speter { 220538032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 220638032Speter &vp, &vsize); 220738032Speter if (yperr == 0) 220838032Speter map->map_mflags &= ~MF_TRY1NULL; 220938032Speter } 221038032Speter if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 221138032Speter { 221264562Sgshapiro if (vp != NULL) 221364562Sgshapiro { 221464562Sgshapiro free(vp); 221564562Sgshapiro vp = NULL; 221664562Sgshapiro } 221738032Speter buflen++; 221838032Speter yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 221938032Speter &vp, &vsize); 222038032Speter if (yperr == 0) 222138032Speter map->map_mflags &= ~MF_TRY0NULL; 222238032Speter } 222338032Speter if (yperr != 0) 222438032Speter { 222538032Speter if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 222638032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 222764562Sgshapiro if (vp != NULL) 222864562Sgshapiro free(vp); 222938032Speter return NULL; 223038032Speter } 223138032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 223238032Speter return map_rewrite(map, name, strlen(name), NULL); 223338032Speter else 223464562Sgshapiro { 223564562Sgshapiro char *ret; 223664562Sgshapiro 223764562Sgshapiro ret = map_rewrite(map, vp, vsize, av); 223864562Sgshapiro if (vp != NULL) 223964562Sgshapiro free(vp); 224064562Sgshapiro return ret; 224164562Sgshapiro } 224238032Speter} 224338032Speter 224438032Speter 224538032Speter/* 224638032Speter** NIS_GETCANONNAME -- look up canonical name in NIS 224738032Speter*/ 224838032Speter 224964562Sgshapirostatic bool 225038032Speternis_getcanonname(name, hbsize, statp) 225138032Speter char *name; 225238032Speter int hbsize; 225338032Speter int *statp; 225438032Speter{ 225538032Speter char *vp; 225638032Speter auto int vsize; 225738032Speter int keylen; 225838032Speter int yperr; 225938032Speter static bool try0null = TRUE; 226038032Speter static bool try1null = TRUE; 226138032Speter static char *yp_domain = NULL; 226238032Speter char host_record[MAXLINE]; 226338032Speter char cbuf[MAXNAME]; 226438032Speter char nbuf[MAXNAME + 1]; 226538032Speter 226638032Speter if (tTd(38, 20)) 226764562Sgshapiro dprintf("nis_getcanonname(%s)\n", name); 226838032Speter 226964562Sgshapiro if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 227038032Speter { 227138032Speter *statp = EX_UNAVAILABLE; 227238032Speter return FALSE; 227338032Speter } 227473188Sgshapiro (void) shorten_hostname(nbuf); 227538032Speter keylen = strlen(nbuf); 227638032Speter 227738032Speter if (yp_domain == NULL) 227864562Sgshapiro (void) yp_get_default_domain(&yp_domain); 227938032Speter makelower(nbuf); 228038032Speter yperr = YPERR_KEY; 228164562Sgshapiro vp = NULL; 228238032Speter if (try0null) 228338032Speter { 228438032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 228538032Speter &vp, &vsize); 228638032Speter if (yperr == 0) 228738032Speter try1null = FALSE; 228838032Speter } 228938032Speter if (yperr == YPERR_KEY && try1null) 229038032Speter { 229164562Sgshapiro if (vp != NULL) 229264562Sgshapiro { 229364562Sgshapiro free(vp); 229464562Sgshapiro vp = NULL; 229564562Sgshapiro } 229638032Speter keylen++; 229738032Speter yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 229838032Speter &vp, &vsize); 229938032Speter if (yperr == 0) 230038032Speter try0null = FALSE; 230138032Speter } 230238032Speter if (yperr != 0) 230338032Speter { 230438032Speter if (yperr == YPERR_KEY) 230538032Speter *statp = EX_NOHOST; 230638032Speter else if (yperr == YPERR_BUSY) 230738032Speter *statp = EX_TEMPFAIL; 230838032Speter else 230938032Speter *statp = EX_UNAVAILABLE; 231064562Sgshapiro if (vp != NULL) 231164562Sgshapiro free(vp); 231238032Speter return FALSE; 231338032Speter } 231464562Sgshapiro (void) strlcpy(host_record, vp, sizeof host_record); 231564562Sgshapiro free(vp); 231638032Speter if (tTd(38, 44)) 231764562Sgshapiro dprintf("got record `%s'\n", host_record); 231873188Sgshapiro if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf)) 231938032Speter { 232038032Speter /* this should not happen, but.... */ 232138032Speter *statp = EX_NOHOST; 232238032Speter return FALSE; 232338032Speter } 232473188Sgshapiro if (hbsize <= strlen(cbuf)) 232538032Speter { 232638032Speter *statp = EX_UNAVAILABLE; 232738032Speter return FALSE; 232838032Speter } 232964562Sgshapiro (void) strlcpy(name, cbuf, hbsize); 233038032Speter *statp = EX_OK; 233138032Speter return TRUE; 233238032Speter} 233338032Speter 233464562Sgshapiro#endif /* NIS */ 233538032Speter/* 233638032Speter** NISPLUS Modules 233738032Speter** 233838032Speter** This code donated by Sun Microsystems. 233938032Speter*/ 234038032Speter 234138032Speter#ifdef NISPLUS 234238032Speter 234364562Sgshapiro# undef NIS /* symbol conflict in nis.h */ 234464562Sgshapiro# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 234564562Sgshapiro# include <rpcsvc/nis.h> 234664562Sgshapiro# include <rpcsvc/nislib.h> 234738032Speter 234864562Sgshapiro# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 234964562Sgshapiro# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 235064562Sgshapiro# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 235164562Sgshapiro# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 235238032Speter 235338032Speter/* 235438032Speter** NISPLUS_MAP_OPEN -- open nisplus table 235538032Speter*/ 235638032Speter 235738032Speterbool 235838032Speternisplus_map_open(map, mode) 235938032Speter MAP *map; 236038032Speter int mode; 236138032Speter{ 236238032Speter nis_result *res = NULL; 236338032Speter int retry_cnt, max_col, i; 236438032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 236538032Speter 236638032Speter if (tTd(38, 2)) 236764562Sgshapiro dprintf("nisplus_map_open(%s, %s, %d)\n", 236838032Speter map->map_mname, map->map_file, mode); 236938032Speter 237038032Speter mode &= O_ACCMODE; 237138032Speter if (mode != O_RDONLY) 237238032Speter { 237338032Speter errno = EPERM; 237438032Speter return FALSE; 237538032Speter } 237638032Speter 237738032Speter if (*map->map_file == '\0') 237838032Speter map->map_file = "mail_aliases.org_dir"; 237938032Speter 238038032Speter if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 238138032Speter { 238238032Speter /* set default NISPLUS Domain to $m */ 238338032Speter map->map_domain = newstr(nisplus_default_domain()); 238438032Speter if (tTd(38, 2)) 238564562Sgshapiro dprintf("nisplus_map_open(%s): using domain %s\n", 238664562Sgshapiro map->map_file, map->map_domain); 238738032Speter } 238838032Speter if (!PARTIAL_NAME(map->map_file)) 238938032Speter { 239038032Speter map->map_domain = newstr(""); 239138032Speter snprintf(qbuf, sizeof qbuf, "%s", map->map_file); 239238032Speter } 239338032Speter else 239438032Speter { 239538032Speter /* check to see if this map actually exists */ 239638032Speter snprintf(qbuf, sizeof qbuf, "%s.%s", 239738032Speter map->map_file, map->map_domain); 239838032Speter } 239938032Speter 240038032Speter retry_cnt = 0; 240138032Speter while (res == NULL || res->status != NIS_SUCCESS) 240238032Speter { 240338032Speter res = nis_lookup(qbuf, FOLLOW_LINKS); 240438032Speter switch (res->status) 240538032Speter { 240638032Speter case NIS_SUCCESS: 240738032Speter break; 240838032Speter 240938032Speter case NIS_TRYAGAIN: 241038032Speter case NIS_RPCERROR: 241138032Speter case NIS_NAMEUNREACHABLE: 241238032Speter if (retry_cnt++ > 4) 241338032Speter { 241438032Speter errno = EAGAIN; 241538032Speter return FALSE; 241638032Speter } 241738032Speter /* try not to overwhelm hosed server */ 241838032Speter sleep(2); 241938032Speter break; 242038032Speter 242138032Speter default: /* all other nisplus errors */ 242264562Sgshapiro# if 0 242338032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 242464562Sgshapiro syserr("421 4.0.0 Cannot find table %s.%s: %s", 242538032Speter map->map_file, map->map_domain, 242638032Speter nis_sperrno(res->status)); 242764562Sgshapiro# endif /* 0 */ 242838032Speter errno = EAGAIN; 242938032Speter return FALSE; 243038032Speter } 243138032Speter } 243238032Speter 243338032Speter if (NIS_RES_NUMOBJ(res) != 1 || 243438032Speter (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 243538032Speter { 243638032Speter if (tTd(38, 10)) 243764562Sgshapiro dprintf("nisplus_map_open: %s is not a table\n", qbuf); 243864562Sgshapiro# if 0 243938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 244064562Sgshapiro syserr("421 4.0.0 %s.%s: %s is not a table", 244138032Speter map->map_file, map->map_domain, 244238032Speter nis_sperrno(res->status)); 244364562Sgshapiro# endif /* 0 */ 244438032Speter errno = EBADF; 244538032Speter return FALSE; 244638032Speter } 244738032Speter /* default key column is column 0 */ 244838032Speter if (map->map_keycolnm == NULL) 244938032Speter map->map_keycolnm = newstr(COL_NAME(res,0)); 245038032Speter 245138032Speter max_col = COL_MAX(res); 245238032Speter 245338032Speter /* verify the key column exist */ 245464562Sgshapiro for (i = 0; i< max_col; i++) 245538032Speter { 245664562Sgshapiro if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 245738032Speter break; 245838032Speter } 245938032Speter if (i == max_col) 246038032Speter { 246138032Speter if (tTd(38, 2)) 246264562Sgshapiro dprintf("nisplus_map_open(%s): can not find key column %s\n", 246338032Speter map->map_file, map->map_keycolnm); 246438032Speter errno = ENOENT; 246538032Speter return FALSE; 246638032Speter } 246738032Speter 246838032Speter /* default value column is the last column */ 246938032Speter if (map->map_valcolnm == NULL) 247038032Speter { 247138032Speter map->map_valcolno = max_col - 1; 247238032Speter return TRUE; 247338032Speter } 247438032Speter 247564562Sgshapiro for (i = 0; i< max_col; i++) 247638032Speter { 247738032Speter if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 247838032Speter { 247938032Speter map->map_valcolno = i; 248038032Speter return TRUE; 248138032Speter } 248238032Speter } 248338032Speter 248438032Speter if (tTd(38, 2)) 248564562Sgshapiro dprintf("nisplus_map_open(%s): can not find column %s\n", 248664562Sgshapiro map->map_file, map->map_keycolnm); 248738032Speter errno = ENOENT; 248838032Speter return FALSE; 248938032Speter} 249038032Speter 249138032Speter 249238032Speter/* 249338032Speter** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 249438032Speter*/ 249538032Speter 249638032Speterchar * 249738032Speternisplus_map_lookup(map, name, av, statp) 249838032Speter MAP *map; 249938032Speter char *name; 250038032Speter char **av; 250138032Speter int *statp; 250238032Speter{ 250338032Speter char *p; 250438032Speter auto int vsize; 250538032Speter char *skp; 250638032Speter int skleft; 250738032Speter char search_key[MAXNAME + 4]; 250838032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 250938032Speter nis_result *result; 251038032Speter 251138032Speter if (tTd(38, 20)) 251264562Sgshapiro dprintf("nisplus_map_lookup(%s, %s)\n", 251338032Speter map->map_mname, name); 251438032Speter 251538032Speter if (!bitset(MF_OPEN, map->map_mflags)) 251638032Speter { 251738032Speter if (nisplus_map_open(map, O_RDONLY)) 251842575Speter { 251938032Speter map->map_mflags |= MF_OPEN; 252042575Speter map->map_pid = getpid(); 252142575Speter } 252238032Speter else 252338032Speter { 252438032Speter *statp = EX_UNAVAILABLE; 252538032Speter return NULL; 252638032Speter } 252738032Speter } 252838032Speter 252938032Speter /* 253038032Speter ** Copy the name to the key buffer, escaping double quote characters 253138032Speter ** by doubling them and quoting "]" and "," to avoid having the 253238032Speter ** NIS+ parser choke on them. 253338032Speter */ 253438032Speter 253538032Speter skleft = sizeof search_key - 4; 253638032Speter skp = search_key; 253738032Speter for (p = name; *p != '\0' && skleft > 0; p++) 253838032Speter { 253938032Speter switch (*p) 254038032Speter { 254138032Speter case ']': 254238032Speter case ',': 254338032Speter /* quote the character */ 254438032Speter *skp++ = '"'; 254538032Speter *skp++ = *p; 254638032Speter *skp++ = '"'; 254738032Speter skleft -= 3; 254838032Speter break; 254938032Speter 255038032Speter case '"': 255138032Speter /* double the quote */ 255238032Speter *skp++ = '"'; 255338032Speter skleft--; 255464562Sgshapiro /* FALLTHROUGH */ 255538032Speter 255638032Speter default: 255738032Speter *skp++ = *p; 255838032Speter skleft--; 255938032Speter break; 256038032Speter } 256138032Speter } 256238032Speter *skp = '\0'; 256338032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 256438032Speter makelower(search_key); 256538032Speter 256638032Speter /* construct the query */ 256738032Speter if (PARTIAL_NAME(map->map_file)) 256838032Speter snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", 256938032Speter map->map_keycolnm, search_key, map->map_file, 257038032Speter map->map_domain); 257138032Speter else 257238032Speter snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", 257338032Speter map->map_keycolnm, search_key, map->map_file); 257438032Speter 257538032Speter if (tTd(38, 20)) 257664562Sgshapiro dprintf("qbuf=%s\n", qbuf); 257738032Speter result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 257838032Speter if (result->status == NIS_SUCCESS) 257938032Speter { 258038032Speter int count; 258138032Speter char *str; 258238032Speter 258338032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 258438032Speter { 258538032Speter if (LogLevel > 10) 258638032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 258764562Sgshapiro "%s: lookup error, expected 1 entry, got %d", 258864562Sgshapiro map->map_file, count); 258938032Speter 259038032Speter /* ignore second entry */ 259138032Speter if (tTd(38, 20)) 259264562Sgshapiro dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 259338032Speter name, count); 259438032Speter } 259538032Speter 259638032Speter p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 259738032Speter /* set the length of the result */ 259838032Speter if (p == NULL) 259938032Speter p = ""; 260038032Speter vsize = strlen(p); 260138032Speter if (tTd(38, 20)) 260264562Sgshapiro dprintf("nisplus_map_lookup(%s), found %s\n", 260338032Speter name, p); 260438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 260538032Speter str = map_rewrite(map, name, strlen(name), NULL); 260638032Speter else 260738032Speter str = map_rewrite(map, p, vsize, av); 260838032Speter nis_freeresult(result); 260938032Speter *statp = EX_OK; 261038032Speter return str; 261138032Speter } 261238032Speter else 261338032Speter { 261438032Speter if (result->status == NIS_NOTFOUND) 261538032Speter *statp = EX_NOTFOUND; 261638032Speter else if (result->status == NIS_TRYAGAIN) 261738032Speter *statp = EX_TEMPFAIL; 261838032Speter else 261938032Speter { 262038032Speter *statp = EX_UNAVAILABLE; 262138032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 262238032Speter } 262338032Speter } 262438032Speter if (tTd(38, 20)) 262564562Sgshapiro dprintf("nisplus_map_lookup(%s), failed\n", name); 262638032Speter nis_freeresult(result); 262738032Speter return NULL; 262838032Speter} 262938032Speter 263038032Speter 263138032Speter 263238032Speter/* 263338032Speter** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 263438032Speter*/ 263538032Speter 263664562Sgshapirostatic bool 263738032Speternisplus_getcanonname(name, hbsize, statp) 263838032Speter char *name; 263938032Speter int hbsize; 264038032Speter int *statp; 264138032Speter{ 264238032Speter char *vp; 264338032Speter auto int vsize; 264438032Speter nis_result *result; 264538032Speter char *p; 264638032Speter char nbuf[MAXNAME + 1]; 264738032Speter char qbuf[MAXLINE + NIS_MAXNAMELEN]; 264838032Speter 264938032Speter if (strlen(name) >= sizeof nbuf) 265038032Speter { 265138032Speter *statp = EX_UNAVAILABLE; 265238032Speter return FALSE; 265338032Speter } 265464562Sgshapiro (void) strlcpy(nbuf, name, sizeof nbuf); 265573188Sgshapiro (void) shorten_hostname(nbuf); 265638032Speter 265738032Speter p = strchr(nbuf, '.'); 265838032Speter if (p == NULL) 265938032Speter { 266038032Speter /* single token */ 266138032Speter snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir", nbuf); 266238032Speter } 266338032Speter else if (p[1] != '\0') 266438032Speter { 266538032Speter /* multi token -- take only first token in nbuf */ 266638032Speter *p = '\0'; 266738032Speter snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir.%s", 266838032Speter nbuf, &p[1]); 266938032Speter } 267038032Speter else 267138032Speter { 267238032Speter *statp = EX_NOHOST; 267338032Speter return FALSE; 267438032Speter } 267538032Speter 267638032Speter if (tTd(38, 20)) 267764562Sgshapiro dprintf("\nnisplus_getcanoname(%s), qbuf=%s\n", 267864562Sgshapiro name, qbuf); 267938032Speter 268038032Speter result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 268138032Speter NULL, NULL); 268238032Speter 268338032Speter if (result->status == NIS_SUCCESS) 268438032Speter { 268538032Speter int count; 268638032Speter char *domain; 268738032Speter 268838032Speter if ((count = NIS_RES_NUMOBJ(result)) != 1) 268938032Speter { 269038032Speter if (LogLevel > 10) 269138032Speter sm_syslog(LOG_WARNING, CurEnv->e_id, 269264562Sgshapiro "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 269364562Sgshapiro count); 269438032Speter 269538032Speter /* ignore second entry */ 269638032Speter if (tTd(38, 20)) 269764562Sgshapiro dprintf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n", 269838032Speter name, count); 269938032Speter } 270038032Speter 270138032Speter if (tTd(38, 20)) 270264562Sgshapiro dprintf("nisplus_getcanoname(%s), found in directory \"%s\"\n", 270364562Sgshapiro name, (NIS_RES_OBJECT(result))->zo_domain); 270438032Speter 270538032Speter 270638032Speter vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 270738032Speter vsize = strlen(vp); 270838032Speter if (tTd(38, 20)) 270964562Sgshapiro dprintf("nisplus_getcanonname(%s), found %s\n", 271038032Speter name, vp); 271138032Speter if (strchr(vp, '.') != NULL) 271238032Speter { 271338032Speter domain = ""; 271438032Speter } 271538032Speter else 271638032Speter { 271738032Speter domain = macvalue('m', CurEnv); 271838032Speter if (domain == NULL) 271938032Speter domain = ""; 272038032Speter } 272138032Speter if (hbsize > vsize + (int) strlen(domain) + 1) 272238032Speter { 272338032Speter if (domain[0] == '\0') 272464562Sgshapiro (void) strlcpy(name, vp, hbsize); 272538032Speter else 272638032Speter snprintf(name, hbsize, "%s.%s", vp, domain); 272738032Speter *statp = EX_OK; 272838032Speter } 272938032Speter else 273038032Speter *statp = EX_NOHOST; 273138032Speter nis_freeresult(result); 273238032Speter return TRUE; 273338032Speter } 273438032Speter else 273538032Speter { 273638032Speter if (result->status == NIS_NOTFOUND) 273738032Speter *statp = EX_NOHOST; 273838032Speter else if (result->status == NIS_TRYAGAIN) 273938032Speter *statp = EX_TEMPFAIL; 274038032Speter else 274138032Speter *statp = EX_UNAVAILABLE; 274238032Speter } 274338032Speter if (tTd(38, 20)) 274464562Sgshapiro dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 274538032Speter name, result->status, *statp); 274638032Speter nis_freeresult(result); 274738032Speter return FALSE; 274838032Speter} 274938032Speter 275038032Speterchar * 275138032Speternisplus_default_domain() 275238032Speter{ 275338032Speter static char default_domain[MAXNAME + 1] = ""; 275438032Speter char *p; 275538032Speter 275638032Speter if (default_domain[0] != '\0') 275764562Sgshapiro return default_domain; 275838032Speter 275938032Speter p = nis_local_directory(); 276038032Speter snprintf(default_domain, sizeof default_domain, "%s", p); 276138032Speter return default_domain; 276238032Speter} 276338032Speter 276438032Speter#endif /* NISPLUS */ 276538032Speter/* 276638032Speter** LDAP Modules 276738032Speter*/ 276838032Speter 276964562Sgshapiro/* 277064562Sgshapiro** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 277164562Sgshapiro*/ 277264562Sgshapiro 277364562Sgshapiro#if defined(LDAPMAP) || defined(PH_MAP) 277464562Sgshapiro 277564562Sgshapiro# ifdef PH_MAP 277664562Sgshapiro# define ph_map_dequote ldapmap_dequote 277764562Sgshapiro# endif /* PH_MAP */ 277864562Sgshapiro 277964562Sgshapirochar * 278064562Sgshapiroldapmap_dequote(str) 278164562Sgshapiro char *str; 278264562Sgshapiro{ 278364562Sgshapiro char *p; 278464562Sgshapiro char *start; 278564562Sgshapiro 278664562Sgshapiro if (str == NULL) 278764562Sgshapiro return NULL; 278864562Sgshapiro 278964562Sgshapiro p = str; 279064562Sgshapiro if (*p == '"') 279164562Sgshapiro { 279264562Sgshapiro /* Should probably swallow initial whitespace here */ 279364562Sgshapiro start = ++p; 279464562Sgshapiro } 279564562Sgshapiro else 279664562Sgshapiro return str; 279764562Sgshapiro while (*p != '"' && *p != '\0') 279864562Sgshapiro p++; 279964562Sgshapiro if (*p != '\0') 280064562Sgshapiro *p = '\0'; 280164562Sgshapiro return start; 280264562Sgshapiro} 280364562Sgshapiro#endif /* defined(LDAPMAP) || defined(PH_MAP) */ 280464562Sgshapiro 280538032Speter#ifdef LDAPMAP 280638032Speter 280764562SgshapiroLDAPMAP_STRUCT *LDAPDefaults = NULL; 280838032Speter 280938032Speter/* 281064562Sgshapiro** LDAPMAP_OPEN -- open LDAP map 281138032Speter** 281264562Sgshapiro** Connect to the LDAP server. Re-use existing connections since a 281364562Sgshapiro** single server connection to a host (with the same host, port, 281464562Sgshapiro** bind DN, and secret) can answer queries for multiple maps. 281538032Speter*/ 281638032Speter 281738032Speterbool 281864562Sgshapiroldapmap_open(map, mode) 281938032Speter MAP *map; 282038032Speter int mode; 282138032Speter{ 282264562Sgshapiro LDAPMAP_STRUCT *lmap; 282364562Sgshapiro STAB *s; 282464562Sgshapiro 282538032Speter if (tTd(38, 2)) 282666494Sgshapiro dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 282738032Speter 282838032Speter mode &= O_ACCMODE; 282964562Sgshapiro 283064562Sgshapiro /* sendmail doesn't have the ability to write to LDAP (yet) */ 283138032Speter if (mode != O_RDONLY) 283238032Speter { 283338032Speter /* issue a pseudo-error message */ 283464562Sgshapiro# ifdef ENOSYS 283538032Speter errno = ENOSYS; 283664562Sgshapiro# else /* ENOSYS */ 283764562Sgshapiro# ifdef EFTYPE 283838032Speter errno = EFTYPE; 283964562Sgshapiro# else /* EFTYPE */ 284038032Speter errno = ENXIO; 284164562Sgshapiro# endif /* EFTYPE */ 284264562Sgshapiro# endif /* ENOSYS */ 284338032Speter return FALSE; 284438032Speter } 284564562Sgshapiro 284664562Sgshapiro /* Comma separate if used as an alias file */ 284764562Sgshapiro if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 284864562Sgshapiro map->map_coldelim = ','; 284964562Sgshapiro 285064562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 285164562Sgshapiro 285264562Sgshapiro s = ldapmap_findconn(lmap); 285364562Sgshapiro if (s->s_ldap != NULL) 285464562Sgshapiro { 285564562Sgshapiro /* Already have a connection open to this LDAP server */ 285664562Sgshapiro lmap->ldap_ld = s->s_ldap; 285766494Sgshapiro if (tTd(38, 2)) 285866494Sgshapiro dprintf("using cached connection\n"); 285964562Sgshapiro return TRUE; 286064562Sgshapiro } 286164562Sgshapiro 286266494Sgshapiro if (tTd(38, 2)) 286366494Sgshapiro dprintf("opening new connection\n"); 286466494Sgshapiro 286564562Sgshapiro /* No connection yet, connect */ 286664562Sgshapiro if (!ldapmap_start(map)) 286764562Sgshapiro return FALSE; 286864562Sgshapiro 286964562Sgshapiro /* Save connection for reuse */ 287064562Sgshapiro s->s_ldap = lmap->ldap_ld; 287138032Speter return TRUE; 287238032Speter} 287338032Speter 287438032Speter/* 287564562Sgshapiro** LDAPMAP_START -- actually connect to an LDAP server 287638032Speter** 287764562Sgshapiro** Parameters: 287864562Sgshapiro** map -- the map being opened. 287964562Sgshapiro** 288064562Sgshapiro** Returns: 288164562Sgshapiro** TRUE if connection is successful, FALSE otherwise. 288264562Sgshapiro** 288364562Sgshapiro** Side Effects: 288464562Sgshapiro** Populates lmap->ldap_ld. 288538032Speter*/ 288638032Speter 288738032Speterstatic jmp_buf LDAPTimeout; 288838032Speter 288964562Sgshapirostatic bool 289064562Sgshapiroldapmap_start(map) 289138032Speter MAP *map; 289238032Speter{ 289364562Sgshapiro register int bind_result; 289464562Sgshapiro int save_errno; 289564562Sgshapiro register EVENT *ev = NULL; 289664562Sgshapiro LDAPMAP_STRUCT *lmap; 289738032Speter LDAP *ld; 289838032Speter 289938032Speter if (tTd(38, 2)) 290064562Sgshapiro dprintf("ldapmap_start(%s)\n", map->map_mname); 290138032Speter 290264562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 290338032Speter 290438032Speter if (tTd(38,9)) 290564562Sgshapiro dprintf("ldapmap_start(%s, %d)\n", 290664562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host, 290764562Sgshapiro lmap->ldap_port); 290838032Speter 290964562Sgshapiro# if USE_LDAP_INIT 291064562Sgshapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 291171345Sgshapiro save_errno = errno; 291264562Sgshapiro# else /* USE_LDAP_INIT */ 291364562Sgshapiro /* 291464562Sgshapiro ** If using ldap_open(), the actual connection to the server 291564562Sgshapiro ** happens now so we need the timeout here. For ldap_init(), 291664562Sgshapiro ** the connection happens at bind time. 291764562Sgshapiro */ 291838032Speter 291938032Speter /* set the timeout */ 292064562Sgshapiro if (lmap->ldap_timeout.tv_sec != 0) 292138032Speter { 292238032Speter if (setjmp(LDAPTimeout) != 0) 292338032Speter { 292438032Speter if (LogLevel > 1) 292538032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 292664562Sgshapiro "timeout conning to LDAP server %.100s", 292764562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); 292864562Sgshapiro return FALSE; 292938032Speter } 293064562Sgshapiro ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); 293138032Speter } 293238032Speter 293364562Sgshapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 293464562Sgshapiro save_errno = errno; 293542575Speter 293664562Sgshapiro /* clear the event if it has not sprung */ 293764562Sgshapiro if (ev != NULL) 293842575Speter clrevent(ev); 293964562Sgshapiro# endif /* USE_LDAP_INIT */ 294042575Speter 294164562Sgshapiro errno = save_errno; 294242575Speter if (ld == NULL) 294338032Speter { 294438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 294538032Speter { 294664562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 294764562Sgshapiro syserr("%s failed to %s in map %s", 294864562Sgshapiro# if USE_LDAP_INIT 294964562Sgshapiro "ldap_init", 295064562Sgshapiro# else /* USE_LDAP_INIT */ 295164562Sgshapiro "ldap_open", 295264562Sgshapiro# endif /* USE_LDAP_INIT */ 295364562Sgshapiro lmap->ldap_host == NULL ? "localhost" 295464562Sgshapiro : lmap->ldap_host, 295564562Sgshapiro map->map_mname); 295664562Sgshapiro else 295764562Sgshapiro syserr("421 4.0.0 %s failed to %s in map %s", 295864562Sgshapiro# if USE_LDAP_INIT 295964562Sgshapiro "ldap_init", 296064562Sgshapiro# else /* USE_LDAP_INIT */ 296164562Sgshapiro "ldap_open", 296264562Sgshapiro# endif /* USE_LDAP_INIT */ 296364562Sgshapiro lmap->ldap_host == NULL ? "localhost" 296464562Sgshapiro : lmap->ldap_host, 296564562Sgshapiro map->map_mname); 296638032Speter } 296738032Speter return FALSE; 296838032Speter } 296938032Speter 297064562Sgshapiro ldapmap_setopts(ld, lmap); 297138032Speter 297264562Sgshapiro# if USE_LDAP_INIT 297364562Sgshapiro /* 297464562Sgshapiro ** If using ldap_init(), the actual connection to the server 297564562Sgshapiro ** happens at ldap_bind_s() so we need the timeout here. 297664562Sgshapiro */ 297764562Sgshapiro 297864562Sgshapiro /* set the timeout */ 297964562Sgshapiro if (lmap->ldap_timeout.tv_sec != 0) 298038032Speter { 298164562Sgshapiro if (setjmp(LDAPTimeout) != 0) 298238032Speter { 298364562Sgshapiro if (LogLevel > 1) 298464562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 298564562Sgshapiro "timeout conning to LDAP server %.100s", 298664562Sgshapiro lmap->ldap_host == NULL ? "localhost" 298764562Sgshapiro : lmap->ldap_host); 298864562Sgshapiro return FALSE; 298938032Speter } 299064562Sgshapiro ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); 299138032Speter } 299264562Sgshapiro# endif /* USE_LDAP_INIT */ 299364562Sgshapiro 299464562Sgshapiro# ifdef LDAP_AUTH_KRBV4 299564562Sgshapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 299664562Sgshapiro lmap->ldap_secret != NULL) 299738032Speter { 299864562Sgshapiro /* 299964562Sgshapiro ** Need to put ticket in environment here instead of 300064562Sgshapiro ** during parseargs as there may be different tickets 300164562Sgshapiro ** for different LDAP connections. 300264562Sgshapiro */ 300364562Sgshapiro 300464562Sgshapiro (void) putenv(lmap->ldap_secret); 300538032Speter } 300664562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 300738032Speter 300864562Sgshapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 300964562Sgshapiro lmap->ldap_secret, lmap->ldap_method); 301064562Sgshapiro 301164562Sgshapiro# if USE_LDAP_INIT 301264562Sgshapiro /* clear the event if it has not sprung */ 301364562Sgshapiro if (ev != NULL) 301464562Sgshapiro clrevent(ev); 301564562Sgshapiro# endif /* USE_LDAP_INIT */ 301664562Sgshapiro 301764562Sgshapiro if (bind_result != LDAP_SUCCESS) 301864562Sgshapiro { 301964562Sgshapiro errno = bind_result + E_LDAPBASE; 302064562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 302164562Sgshapiro { 302264562Sgshapiro syserr("421 4.0.0 Cannot bind to map %s in ldap server %s", 302364562Sgshapiro map->map_mname, 302464562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); 302564562Sgshapiro } 302664562Sgshapiro return FALSE; 302764562Sgshapiro } 302864562Sgshapiro 302964562Sgshapiro /* We need to cast ld into the map structure */ 303064562Sgshapiro lmap->ldap_ld = ld; 303164562Sgshapiro return TRUE; 303238032Speter} 303338032Speter 303464562Sgshapiro/* ARGSUSED */ 303564562Sgshapirostatic void 303664562Sgshapiroldaptimeout(sig_no) 303764562Sgshapiro int sig_no; 303864562Sgshapiro{ 303964562Sgshapiro longjmp(LDAPTimeout, 1); 304064562Sgshapiro} 304138032Speter 304238032Speter/* 304364562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 304438032Speter*/ 304538032Speter 304638032Spetervoid 304764562Sgshapiroldapmap_close(map) 304838032Speter MAP *map; 304938032Speter{ 305064562Sgshapiro LDAPMAP_STRUCT *lmap; 305164562Sgshapiro STAB *s; 305243730Speter 305364562Sgshapiro if (tTd(38, 2)) 305464562Sgshapiro dprintf("ldapmap_close(%s)\n", map->map_mname); 305564562Sgshapiro 305664562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 305764562Sgshapiro 305864562Sgshapiro /* Check if already closed */ 305964562Sgshapiro if (lmap->ldap_ld == NULL) 306064562Sgshapiro return; 306164562Sgshapiro 306264562Sgshapiro s = ldapmap_findconn(lmap); 306364562Sgshapiro 306464562Sgshapiro /* Check if already closed */ 306564562Sgshapiro if (s->s_ldap == NULL) 306664562Sgshapiro return; 306764562Sgshapiro 306864562Sgshapiro /* If same as saved connection, stored connection is going away */ 306964562Sgshapiro if (s->s_ldap == lmap->ldap_ld) 307064562Sgshapiro s->s_ldap = NULL; 307164562Sgshapiro 307264562Sgshapiro if (lmap->ldap_ld != NULL) 307343730Speter { 307464562Sgshapiro ldap_unbind(lmap->ldap_ld); 307564562Sgshapiro lmap->ldap_ld = NULL; 307643730Speter } 307738032Speter} 307838032Speter 307964562Sgshapiro# ifdef SUNET_ID 308043730Speter/* 308142575Speter** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form 308242575Speter** This only makes sense at Stanford University. 308338032Speter*/ 308438032Speter 308538032Speterchar * 308638032Spetersunet_id_hash(str) 308738032Speter char *str; 308838032Speter{ 308938032Speter char *p, *p_last; 309038032Speter 309138032Speter p = str; 309238032Speter p_last = p; 309338032Speter while (*p != '\0') 309438032Speter { 309538032Speter if (islower(*p) || isdigit(*p)) 309638032Speter { 309738032Speter *p_last = *p; 309838032Speter p_last++; 309938032Speter } 310038032Speter else if (isupper(*p)) 310138032Speter { 310238032Speter *p_last = tolower(*p); 310338032Speter p_last++; 310438032Speter } 310538032Speter ++p; 310638032Speter } 310738032Speter if (*p_last != '\0') 310838032Speter *p_last = '\0'; 310964562Sgshapiro return str; 311038032Speter} 311164562Sgshapiro# endif /* SUNET_ID */ 311238032Speter 311338032Speter/* 311464562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 311538032Speter*/ 311638032Speter 311738032Speterchar * 311864562Sgshapiroldapmap_lookup(map, name, av, statp) 311938032Speter MAP *map; 312038032Speter char *name; 312138032Speter char **av; 312238032Speter int *statp; 312338032Speter{ 312464562Sgshapiro int i; 312564562Sgshapiro int entries = 0; 312664562Sgshapiro int msgid; 312764562Sgshapiro int ret; 312864562Sgshapiro int vsize; 312964562Sgshapiro char *fp, *vp; 313064562Sgshapiro char *p, *q; 313164562Sgshapiro char *result = NULL; 313264562Sgshapiro LDAPMAP_STRUCT *lmap = NULL; 313338032Speter char keybuf[MAXNAME + 1]; 313464562Sgshapiro char filter[LDAPMAP_MAX_FILTER + 1]; 313538032Speter 313638032Speter if (tTd(38, 20)) 313764562Sgshapiro dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); 313838032Speter 313938032Speter /* Get ldap struct pointer from map */ 314064562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 314164562Sgshapiro ldapmap_setopts(lmap->ldap_ld, lmap); 314238032Speter 314364562Sgshapiro (void) strlcpy(keybuf, name, sizeof keybuf); 314438032Speter 314538032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 314664562Sgshapiro { 314764562Sgshapiro# ifdef SUNET_ID 314838032Speter sunet_id_hash(keybuf); 314964562Sgshapiro# else /* SUNET_ID */ 315038032Speter makelower(keybuf); 315164562Sgshapiro# endif /* SUNET_ID */ 315264562Sgshapiro } 315338032Speter 315442575Speter /* substitute keybuf into filter, perhaps multiple times */ 315564562Sgshapiro memset(filter, '\0', sizeof filter); 315642575Speter fp = filter; 315764562Sgshapiro p = lmap->ldap_filter; 315842575Speter while ((q = strchr(p, '%')) != NULL) 315942575Speter { 316042575Speter if (q[1] == 's') 316142575Speter { 316242575Speter snprintf(fp, SPACELEFT(filter, fp), "%.*s%s", 316366494Sgshapiro (int) (q - p), p, keybuf); 316464562Sgshapiro fp += strlen(fp); 316542575Speter p = q + 2; 316642575Speter } 316764562Sgshapiro else if (q[1] == '0') 316864562Sgshapiro { 316964562Sgshapiro char *k = keybuf; 317064562Sgshapiro 317164562Sgshapiro snprintf(fp, SPACELEFT(filter, fp), "%.*s", 317266494Sgshapiro (int) (q - p), p); 317364562Sgshapiro fp += strlen(fp); 317464562Sgshapiro p = q + 2; 317564562Sgshapiro 317664562Sgshapiro /* Properly escape LDAP special characters */ 317764562Sgshapiro while (SPACELEFT(filter, fp) > 0 && 317864562Sgshapiro *k != '\0') 317964562Sgshapiro { 318064562Sgshapiro if (*k == '*' || *k == '(' || 318164562Sgshapiro *k == ')' || *k == '\\') 318264562Sgshapiro { 318364562Sgshapiro (void) strlcat(fp, 318464562Sgshapiro (*k == '*' ? "\\2A" : 318564562Sgshapiro (*k == '(' ? "\\28" : 318664562Sgshapiro (*k == ')' ? "\\29" : 318764562Sgshapiro (*k == '\\' ? "\\5C" : 318864562Sgshapiro "\00")))), 318964562Sgshapiro SPACELEFT(filter, fp)); 319064562Sgshapiro fp += strlen(fp); 319164562Sgshapiro k++; 319264562Sgshapiro } 319364562Sgshapiro else 319464562Sgshapiro *fp++ = *k++; 319564562Sgshapiro } 319664562Sgshapiro } 319742575Speter else 319842575Speter { 319942575Speter snprintf(fp, SPACELEFT(filter, fp), "%.*s", 320066494Sgshapiro (int) (q - p + 1), p); 320142575Speter p = q + (q[1] == '%' ? 2 : 1); 320264562Sgshapiro fp += strlen(fp); 320342575Speter } 320442575Speter } 320542575Speter snprintf(fp, SPACELEFT(filter, fp), "%s", p); 320642575Speter if (tTd(38, 20)) 320764562Sgshapiro dprintf("ldap search filter=%s\n", filter); 320838032Speter 320964562Sgshapiro lmap->ldap_res = NULL; 321064562Sgshapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, 321164562Sgshapiro filter, 321264562Sgshapiro (lmap->ldap_attr[0] == NULL ? NULL : 321364562Sgshapiro lmap->ldap_attr), 321464562Sgshapiro lmap->ldap_attrsonly); 321564562Sgshapiro if (msgid == -1) 321638032Speter { 321764562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 321864562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 321938032Speter { 322064562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 322166494Sgshapiro syserr("Error in ldap_search using %s in map %s", 322264562Sgshapiro filter, map->map_mname); 322364562Sgshapiro else 322466494Sgshapiro syserr("421 4.0.0 Error in ldap_search using %s in map %s", 322564562Sgshapiro filter, map->map_mname); 322638032Speter } 322764562Sgshapiro *statp = EX_TEMPFAIL; 322866494Sgshapiro#ifdef LDAP_SERVER_DOWN 322966494Sgshapiro if (errno == LDAP_SERVER_DOWN) 323066494Sgshapiro { 323166494Sgshapiro int save_errno = errno; 323266494Sgshapiro 323366494Sgshapiro /* server disappeared, try reopen on next search */ 323466494Sgshapiro map->map_class->map_close(map); 323566494Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 323666494Sgshapiro errno = save_errno; 323766494Sgshapiro } 323866494Sgshapiro#endif /* LDAP_SERVER_DOWN */ 323964562Sgshapiro return NULL; 324064562Sgshapiro } 324164562Sgshapiro 324264562Sgshapiro *statp = EX_NOTFOUND; 324364562Sgshapiro vp = NULL; 324464562Sgshapiro 324564562Sgshapiro /* Get results (all if MF_NOREWRITE, otherwise one by one) */ 324664562Sgshapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 324764562Sgshapiro bitset(MF_NOREWRITE, map->map_mflags), 324864562Sgshapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 324964562Sgshapiro &(lmap->ldap_timeout)), 325064562Sgshapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 325164562Sgshapiro { 325264562Sgshapiro LDAPMessage *entry; 325364562Sgshapiro 325464562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 325538032Speter { 325664562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, 325764562Sgshapiro lmap->ldap_res); 325864562Sgshapiro if (entries > 1) 325964562Sgshapiro { 326064562Sgshapiro *statp = EX_NOTFOUND; 326164562Sgshapiro if (lmap->ldap_res != NULL) 326264562Sgshapiro { 326364562Sgshapiro ldap_msgfree(lmap->ldap_res); 326464562Sgshapiro lmap->ldap_res = NULL; 326564562Sgshapiro } 326664562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 326764562Sgshapiro if (vp != NULL) 326864562Sgshapiro free(vp); 326964562Sgshapiro if (tTd(38, 25)) 327064562Sgshapiro dprintf("ldap search found multiple on a single match query\n"); 327164562Sgshapiro return NULL; 327264562Sgshapiro } 327364562Sgshapiro } 327464562Sgshapiro 327564562Sgshapiro /* If we don't want multiple values and we have one, break */ 327664562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 327764562Sgshapiro break; 327864562Sgshapiro 327964562Sgshapiro /* Cycle through all entries */ 328064562Sgshapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 328164562Sgshapiro entry != NULL; 328264562Sgshapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 328364562Sgshapiro { 328464562Sgshapiro BerElement *ber; 328564562Sgshapiro char *attr; 328664562Sgshapiro char **vals = NULL; 328764562Sgshapiro 328864562Sgshapiro /* 328964562Sgshapiro ** If matching only and found an entry, 329064562Sgshapiro ** no need to spin through attributes 329164562Sgshapiro */ 329264562Sgshapiro 329364562Sgshapiro if (*statp == EX_OK && 329464562Sgshapiro bitset(MF_MATCHONLY, map->map_mflags)) 329564562Sgshapiro continue; 329664562Sgshapiro 329764562Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 329864562Sgshapiro /* 329964562Sgshapiro ** Reset value to prevent lingering 330064562Sgshapiro ** LDAP_DECODING_ERROR due to 330164562Sgshapiro ** OpenLDAP 1.X's hack (see below) 330264562Sgshapiro */ 330364562Sgshapiro 330464562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 330564562Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 330664562Sgshapiro 330764562Sgshapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 330864562Sgshapiro &ber); 330964562Sgshapiro attr != NULL; 331064562Sgshapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 331164562Sgshapiro ber)) 331264562Sgshapiro { 331364562Sgshapiro char *tmp, *vp_tmp; 331464562Sgshapiro 331564562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 331664562Sgshapiro { 331764562Sgshapiro vals = ldap_get_values(lmap->ldap_ld, 331864562Sgshapiro entry, 331964562Sgshapiro attr); 332064562Sgshapiro if (vals == NULL) 332164562Sgshapiro { 332264562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 332364562Sgshapiro if (errno == LDAP_SUCCESS) 332464562Sgshapiro continue; 332564562Sgshapiro 332664562Sgshapiro /* Must be an error */ 332764562Sgshapiro errno += E_LDAPBASE; 332864562Sgshapiro if (!bitset(MF_OPTIONAL, 332964562Sgshapiro map->map_mflags)) 333064562Sgshapiro { 333164562Sgshapiro if (bitset(MF_NODEFER, 333264562Sgshapiro map->map_mflags)) 333364562Sgshapiro syserr("Error getting LDAP values in map %s", 333464562Sgshapiro map->map_mname); 333564562Sgshapiro else 333664562Sgshapiro syserr("421 4.0.0 Error getting LDAP values in map %s", 333764562Sgshapiro map->map_mname); 333864562Sgshapiro } 333964562Sgshapiro *statp = EX_TEMPFAIL; 334064562Sgshapiro# if USING_NETSCAPE_LDAP 334166494Sgshapiro ldap_memfree(attr); 334264562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 334364562Sgshapiro if (lmap->ldap_res != NULL) 334464562Sgshapiro { 334564562Sgshapiro ldap_msgfree(lmap->ldap_res); 334664562Sgshapiro lmap->ldap_res = NULL; 334764562Sgshapiro } 334864562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, 334964562Sgshapiro msgid); 335064562Sgshapiro if (vp != NULL) 335164562Sgshapiro free(vp); 335264562Sgshapiro return NULL; 335364562Sgshapiro } 335464562Sgshapiro } 335564562Sgshapiro 335664562Sgshapiro *statp = EX_OK; 335764562Sgshapiro 335864562Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 335964562Sgshapiro /* 336064562Sgshapiro ** Reset value to prevent lingering 336164562Sgshapiro ** LDAP_DECODING_ERROR due to 336264562Sgshapiro ** OpenLDAP 1.X's hack (see below) 336364562Sgshapiro */ 336464562Sgshapiro 336564562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 336664562Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 336764562Sgshapiro 336864562Sgshapiro /* 336964562Sgshapiro ** If matching only, 337064562Sgshapiro ** no need to spin through entries 337164562Sgshapiro */ 337264562Sgshapiro 337364562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 337464562Sgshapiro continue; 337564562Sgshapiro 337664562Sgshapiro /* 337764562Sgshapiro ** If we don't want multiple values, 337864562Sgshapiro ** return first found. 337964562Sgshapiro */ 338064562Sgshapiro 338164562Sgshapiro if (map->map_coldelim == '\0') 338264562Sgshapiro { 338364562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 338464562Sgshapiro { 338564562Sgshapiro vp = newstr(attr); 338664562Sgshapiro# if USING_NETSCAPE_LDAP 338766494Sgshapiro ldap_memfree(attr); 338864562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 338964562Sgshapiro break; 339064562Sgshapiro } 339164562Sgshapiro 339264562Sgshapiro if (vals[0] == NULL) 339364562Sgshapiro { 339464562Sgshapiro ldap_value_free(vals); 339564562Sgshapiro# if USING_NETSCAPE_LDAP 339666494Sgshapiro ldap_memfree(attr); 339764562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 339864562Sgshapiro continue; 339964562Sgshapiro } 340064562Sgshapiro 340164562Sgshapiro vp = newstr(vals[0]); 340264562Sgshapiro ldap_value_free(vals); 340364562Sgshapiro# if USING_NETSCAPE_LDAP 340466494Sgshapiro ldap_memfree(attr); 340564562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 340664562Sgshapiro break; 340764562Sgshapiro } 340864562Sgshapiro 340964562Sgshapiro /* attributes only */ 341064562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 341164562Sgshapiro { 341264562Sgshapiro if (vp == NULL) 341364562Sgshapiro vp = newstr(attr); 341464562Sgshapiro else 341564562Sgshapiro { 341664562Sgshapiro vsize = strlen(vp) + 341764562Sgshapiro strlen(attr) + 2; 341864562Sgshapiro tmp = xalloc(vsize); 341964562Sgshapiro snprintf(tmp, vsize, "%s%c%s", 342064562Sgshapiro vp, map->map_coldelim, 342164562Sgshapiro attr); 342264562Sgshapiro free(vp); 342364562Sgshapiro vp = tmp; 342464562Sgshapiro } 342564562Sgshapiro# if USING_NETSCAPE_LDAP 342666494Sgshapiro ldap_memfree(attr); 342764562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 342864562Sgshapiro continue; 342964562Sgshapiro } 343064562Sgshapiro 343164562Sgshapiro /* 343264562Sgshapiro ** If there is more than one, 343364562Sgshapiro ** munge then into a map_coldelim 343464562Sgshapiro ** separated string 343564562Sgshapiro */ 343664562Sgshapiro 343764562Sgshapiro vsize = 0; 343864562Sgshapiro for (i = 0; vals[i] != NULL; i++) 343964562Sgshapiro vsize += strlen(vals[i]) + 1; 344064562Sgshapiro vp_tmp = xalloc(vsize); 344164562Sgshapiro *vp_tmp = '\0'; 344264562Sgshapiro 344364562Sgshapiro p = vp_tmp; 344464562Sgshapiro for (i = 0; vals[i] != NULL; i++) 344564562Sgshapiro { 344664562Sgshapiro p += strlcpy(p, vals[i], 344764562Sgshapiro vsize - (p - vp_tmp)); 344864562Sgshapiro if (p >= vp_tmp + vsize) 344964562Sgshapiro syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values"); 345064562Sgshapiro if (vals[i + 1] != NULL) 345164562Sgshapiro *p++ = map->map_coldelim; 345264562Sgshapiro } 345364562Sgshapiro 345464562Sgshapiro ldap_value_free(vals); 345564562Sgshapiro# if USING_NETSCAPE_LDAP 345666494Sgshapiro ldap_memfree(attr); 345764562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 345864562Sgshapiro if (vp == NULL) 345964562Sgshapiro { 346064562Sgshapiro vp = vp_tmp; 346164562Sgshapiro continue; 346264562Sgshapiro } 346364562Sgshapiro vsize = strlen(vp) + strlen(vp_tmp) + 2; 346464562Sgshapiro tmp = xalloc(vsize); 346564562Sgshapiro snprintf(tmp, vsize, "%s%c%s", 346664562Sgshapiro vp, map->map_coldelim, vp_tmp); 346764562Sgshapiro 346864562Sgshapiro free(vp); 346964562Sgshapiro free(vp_tmp); 347064562Sgshapiro vp = tmp; 347164562Sgshapiro } 347264562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 347364562Sgshapiro 347464562Sgshapiro /* 347564562Sgshapiro ** We check errno != LDAP_DECODING_ERROR since 347664562Sgshapiro ** OpenLDAP 1.X has a very ugly *undocumented* 347764562Sgshapiro ** hack of returning this error code from 347864562Sgshapiro ** ldap_next_attribute() if the library freed the 347964562Sgshapiro ** ber attribute. See: 348064562Sgshapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 348164562Sgshapiro */ 348264562Sgshapiro 348364562Sgshapiro if (errno != LDAP_SUCCESS && 348464562Sgshapiro errno != LDAP_DECODING_ERROR) 348564562Sgshapiro { 348664562Sgshapiro /* Must be an error */ 348764562Sgshapiro errno += E_LDAPBASE; 348864562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 348964562Sgshapiro { 349064562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 349164562Sgshapiro syserr("Error getting LDAP attributes in map %s", 349264562Sgshapiro map->map_mname); 349364562Sgshapiro else 349464562Sgshapiro syserr("421 4.0.0 Error getting LDAP attributes in map %s", 349564562Sgshapiro map->map_mname); 349664562Sgshapiro } 349764562Sgshapiro *statp = EX_TEMPFAIL; 349864562Sgshapiro if (lmap->ldap_res != NULL) 349964562Sgshapiro { 350064562Sgshapiro ldap_msgfree(lmap->ldap_res); 350164562Sgshapiro lmap->ldap_res = NULL; 350264562Sgshapiro } 350364562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 350464562Sgshapiro if (vp != NULL) 350564562Sgshapiro free(vp); 350664562Sgshapiro return NULL; 350764562Sgshapiro } 350864562Sgshapiro 350964562Sgshapiro /* We don't want multiple values and we have one */ 351064562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 351164562Sgshapiro break; 351264562Sgshapiro } 351364562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 351464562Sgshapiro if (errno != LDAP_SUCCESS && errno != LDAP_DECODING_ERROR) 351564562Sgshapiro { 351664562Sgshapiro /* Must be an error */ 351764562Sgshapiro errno += E_LDAPBASE; 351838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 351938032Speter { 352064562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 352164562Sgshapiro syserr("Error getting LDAP entries in map %s", 352264562Sgshapiro map->map_mname); 352364562Sgshapiro else 352464562Sgshapiro syserr("421 4.0.0 Error getting LDAP entries in map %s", 352564562Sgshapiro map->map_mname); 352638032Speter } 352738032Speter *statp = EX_TEMPFAIL; 352864562Sgshapiro if (lmap->ldap_res != NULL) 352964562Sgshapiro { 353064562Sgshapiro ldap_msgfree(lmap->ldap_res); 353164562Sgshapiro lmap->ldap_res = NULL; 353264562Sgshapiro } 353364562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 353464562Sgshapiro if (vp != NULL) 353564562Sgshapiro free(vp); 353664562Sgshapiro return NULL; 353738032Speter } 353864562Sgshapiro ldap_msgfree(lmap->ldap_res); 353964562Sgshapiro lmap->ldap_res = NULL; 354038032Speter } 354138032Speter 354264562Sgshapiro /* 354364562Sgshapiro ** If grabbing all results at once for MF_NOREWRITE and 354464562Sgshapiro ** only want a single match, make sure that's all we have 354564562Sgshapiro */ 354664562Sgshapiro 354764562Sgshapiro if (ret == LDAP_RES_SEARCH_RESULT && 354864562Sgshapiro bitset(MF_NOREWRITE|MF_SINGLEMATCH, map->map_mflags)) 354938032Speter { 355064562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, lmap->ldap_res); 355164562Sgshapiro if (entries > 1) 355264562Sgshapiro { 355364562Sgshapiro *statp = EX_NOTFOUND; 355464562Sgshapiro if (lmap->ldap_res != NULL) 355564562Sgshapiro { 355664562Sgshapiro ldap_msgfree(lmap->ldap_res); 355764562Sgshapiro lmap->ldap_res = NULL; 355864562Sgshapiro } 355964562Sgshapiro if (vp != NULL) 356064562Sgshapiro free(vp); 356164562Sgshapiro return NULL; 356264562Sgshapiro } 356364562Sgshapiro *statp = EX_OK; 356438032Speter } 356538032Speter 356664562Sgshapiro if (ret == 0) 356764562Sgshapiro errno = ETIMEDOUT; 356864562Sgshapiro else 356964562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 357064562Sgshapiro if (errno != LDAP_SUCCESS) 357138032Speter { 357264562Sgshapiro /* Must be an error */ 357364562Sgshapiro if (ret != 0) 357464562Sgshapiro errno += E_LDAPBASE; 357564562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 357664562Sgshapiro { 357764562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 357864562Sgshapiro syserr("Error getting LDAP results in map %s", 357964562Sgshapiro map->map_mname); 358064562Sgshapiro else 358164562Sgshapiro syserr("421 4.0.0 Error getting LDAP results in map %s", 358264562Sgshapiro map->map_mname); 358364562Sgshapiro } 358464562Sgshapiro *statp = EX_TEMPFAIL; 358564562Sgshapiro if (vp != NULL) 358664562Sgshapiro free(vp); 358764562Sgshapiro return NULL; 358838032Speter } 358938032Speter 359064562Sgshapiro /* Did we match anything? */ 359171345Sgshapiro if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 359264562Sgshapiro return NULL; 359338032Speter 359464562Sgshapiro /* 359564562Sgshapiro ** If MF_NOREWRITE, we are special map which doesn't 359664562Sgshapiro ** actually return a map value. Instead, we don't free 359764562Sgshapiro ** ldap_res and let the calling function process the LDAP 359864562Sgshapiro ** results. The caller should ldap_msgfree(lmap->ldap_res). 359964562Sgshapiro */ 360038032Speter 360164562Sgshapiro if (bitset(MF_NOREWRITE, map->map_mflags)) 360264562Sgshapiro { 360371345Sgshapiro if (vp != NULL) 360471345Sgshapiro free(vp); 360564562Sgshapiro return ""; 360664562Sgshapiro } 360738032Speter 360864562Sgshapiro if (*statp == EX_OK) 360964562Sgshapiro { 361064562Sgshapiro if (LogLevel > 9) 361164562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 361271345Sgshapiro "ldap %.100s => %s", name, 361371345Sgshapiro vp == NULL ? "<NULL>" : vp); 361464562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 361564562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 361664562Sgshapiro else 361771345Sgshapiro { 361871345Sgshapiro /* vp != NULL according to test above */ 361964562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 362071345Sgshapiro } 362171345Sgshapiro if (vp != NULL) 362271345Sgshapiro free(vp); 362364562Sgshapiro } 362464562Sgshapiro return result; 362538032Speter} 362638032Speter 362738032Speter/* 362864562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 362964562Sgshapiro** 363064562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 363166494Sgshapiro** secret, and PID so we don't have multiple connections open to 363266494Sgshapiro** the same server for different maps. Need a separate connection 363366494Sgshapiro** per PID since a parent process may close the map before the 363466494Sgshapiro** child is done with it. 363564562Sgshapiro** 363664562Sgshapiro** Parameters: 363764562Sgshapiro** lmap -- LDAP map information 363864562Sgshapiro** 363964562Sgshapiro** Returns: 364064562Sgshapiro** Symbol table entry for the LDAP connection. 364164562Sgshapiro** 364238032Speter*/ 364338032Speter 364464562Sgshapirostatic STAB * 364564562Sgshapiroldapmap_findconn(lmap) 364664562Sgshapiro LDAPMAP_STRUCT *lmap; 364738032Speter{ 364864562Sgshapiro int len; 364964562Sgshapiro char *nbuf; 365064562Sgshapiro STAB *s; 365138032Speter 365264562Sgshapiro len = (lmap->ldap_host == NULL ? strlen("localhost") : 365364562Sgshapiro strlen(lmap->ldap_host)) + 1 + 8 + 1 + 365464562Sgshapiro (lmap->ldap_binddn == NULL ? 0 : strlen(lmap->ldap_binddn)) + 365564562Sgshapiro 1 + 365664562Sgshapiro (lmap->ldap_secret == NULL ? 0 : strlen(lmap->ldap_secret)) + 365766494Sgshapiro 8 + 1; 365864562Sgshapiro nbuf = xalloc(len); 365966494Sgshapiro snprintf(nbuf, len, "%s%c%d%c%s%c%s%d", 366064562Sgshapiro (lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host), 366164562Sgshapiro CONDELSE, 366264562Sgshapiro lmap->ldap_port, 366364562Sgshapiro CONDELSE, 366464562Sgshapiro (lmap->ldap_binddn == NULL ? "" : lmap->ldap_binddn), 366564562Sgshapiro CONDELSE, 366666494Sgshapiro (lmap->ldap_secret == NULL ? "" : lmap->ldap_secret), 366766494Sgshapiro getpid()); 366864562Sgshapiro s = stab(nbuf, ST_LDAP, ST_ENTER); 366964562Sgshapiro free(nbuf); 367064562Sgshapiro return s; 367164562Sgshapiro} 367264562Sgshapiro/* 367364562Sgshapiro** LDAPMAP_SETOPTS -- set LDAP options 367464562Sgshapiro** 367564562Sgshapiro** Parameters: 367664562Sgshapiro** ld -- LDAP session handle 367764562Sgshapiro** lmap -- LDAP map information 367864562Sgshapiro** 367964562Sgshapiro** Returns: 368064562Sgshapiro** None. 368164562Sgshapiro** 368264562Sgshapiro*/ 368364562Sgshapiro 368464562Sgshapirostatic void 368564562Sgshapiroldapmap_setopts(ld, lmap) 368664562Sgshapiro LDAP *ld; 368764562Sgshapiro LDAPMAP_STRUCT *lmap; 368864562Sgshapiro{ 368964562Sgshapiro# if USE_LDAP_SET_OPTION 369064562Sgshapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 369164562Sgshapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 369264562Sgshapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 369338032Speter else 369464562Sgshapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 369564562Sgshapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 369664562Sgshapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 369764562Sgshapiro# else /* USE_LDAP_SET_OPTION */ 369864562Sgshapiro /* From here on in we can use ldap internal timelimits */ 369964562Sgshapiro ld->ld_deref = lmap->ldap_deref; 370064562Sgshapiro ld->ld_options = lmap->ldap_options; 370164562Sgshapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 370264562Sgshapiro ld->ld_timelimit = lmap->ldap_timelimit; 370364562Sgshapiro# endif /* USE_LDAP_SET_OPTION */ 370438032Speter} 370564562Sgshapiro/* 370664562Sgshapiro** LDAPMAP_GETERRNO -- get ldap errno value 370764562Sgshapiro** 370864562Sgshapiro** Parameters: 370964562Sgshapiro** ld -- LDAP session handle 371064562Sgshapiro** 371164562Sgshapiro** Returns: 371264562Sgshapiro** LDAP errno. 371364562Sgshapiro** 371464562Sgshapiro*/ 371538032Speter 371664562Sgshapirostatic int 371764562Sgshapiroldapmap_geterrno(ld) 371864562Sgshapiro LDAP *ld; 371964562Sgshapiro{ 372064562Sgshapiro int err = LDAP_SUCCESS; 372164562Sgshapiro 372264562Sgshapiro# if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 372364562Sgshapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 372464562Sgshapiro# else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 372564562Sgshapiro# ifdef LDAP_OPT_SIZELIMIT 372664562Sgshapiro err = ldap_get_lderrno(ld, NULL, NULL); 372764562Sgshapiro# else /* LDAP_OPT_SIZELIMIT */ 372864562Sgshapiro err = ld->ld_errno; 372964562Sgshapiro 373064562Sgshapiro /* 373164562Sgshapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 373264562Sgshapiro ** OpenLDAP 1.X's hack (see above) 373364562Sgshapiro */ 373464562Sgshapiro 373564562Sgshapiro ld->ld_errno = LDAP_SUCCESS; 373664562Sgshapiro# endif /* LDAP_OPT_SIZELIMIT */ 373764562Sgshapiro# endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 373864562Sgshapiro return err; 373964562Sgshapiro} 374064562Sgshapiro 374138032Speter/* 374264562Sgshapiro** LDAPX_MAP_PARSEARGS -- print warning about use of ldapx map. 374338032Speter*/ 374438032Speter 374538032Speterbool 374664562Sgshapiroldapx_map_parseargs(map, args) 374738032Speter MAP *map; 374838032Speter char *args; 374938032Speter{ 375064562Sgshapiro printf("Warning: The \"ldapx\" map class is deprecated and will be removed in a future\n"); 375164562Sgshapiro printf(" version. Use the \"ldap\" map class instead for map \"%s\".\n", 375264562Sgshapiro map->map_mname); 375364562Sgshapiro return ldapmap_parseargs(map, args); 375464562Sgshapiro} 375538032Speter 375664562Sgshapiro/* 375764562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 375864562Sgshapiro*/ 375938032Speter 376064562Sgshapirostruct lamvalues LDAPAuthMethods[] = 376164562Sgshapiro{ 376264562Sgshapiro { "none", LDAP_AUTH_NONE }, 376364562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 376464562Sgshapiro# ifdef LDAP_AUTH_KRBV4 376564562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 376664562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 376764562Sgshapiro { NULL, 0 } 376864562Sgshapiro}; 376938032Speter 377064562Sgshapirostruct ladvalues LDAPAliasDereference[] = 377164562Sgshapiro{ 377264562Sgshapiro { "never", LDAP_DEREF_NEVER }, 377364562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 377464562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 377564562Sgshapiro { "find", LDAP_DEREF_FINDING }, 377664562Sgshapiro { NULL, 0 } 377764562Sgshapiro}; 377838032Speter 377964562Sgshapirostruct lssvalues LDAPSearchScope[] = 378064562Sgshapiro{ 378164562Sgshapiro { "base", LDAP_SCOPE_BASE }, 378264562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 378364562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 378464562Sgshapiro { NULL, 0 } 378564562Sgshapiro}; 378638032Speter 378764562Sgshapirobool 378864562Sgshapiroldapmap_parseargs(map, args) 378964562Sgshapiro MAP *map; 379064562Sgshapiro char *args; 379164562Sgshapiro{ 379264562Sgshapiro bool secretread = TRUE; 379364562Sgshapiro int i; 379464562Sgshapiro register char *p = args; 379564562Sgshapiro LDAPMAP_STRUCT *lmap; 379664562Sgshapiro struct lamvalues *lam; 379764562Sgshapiro struct ladvalues *lad; 379864562Sgshapiro struct lssvalues *lss; 379964562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 380064562Sgshapiro 380164562Sgshapiro /* Get ldap struct pointer from map */ 380264562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 380364562Sgshapiro 380464562Sgshapiro /* Check if setting the initial LDAP defaults */ 380564562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 380664562Sgshapiro { 380764562Sgshapiro /* We need to alloc an LDAPMAP_STRUCT struct */ 380864562Sgshapiro lmap = (LDAPMAP_STRUCT *) xalloc(sizeof *lmap); 380964562Sgshapiro if (LDAPDefaults == NULL) 381064562Sgshapiro ldapmap_clear(lmap); 381164562Sgshapiro else 381264562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 381364562Sgshapiro } 381464562Sgshapiro 381564562Sgshapiro /* there is no check whether there is really an argument */ 381664562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 381764562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 381838032Speter for (;;) 381938032Speter { 382038032Speter while (isascii(*p) && isspace(*p)) 382138032Speter p++; 382238032Speter if (*p != '-') 382338032Speter break; 382438032Speter switch (*++p) 382538032Speter { 382638032Speter case 'N': 382738032Speter map->map_mflags |= MF_INCLNULL; 382838032Speter map->map_mflags &= ~MF_TRY0NULL; 382938032Speter break; 383038032Speter 383138032Speter case 'O': 383238032Speter map->map_mflags &= ~MF_TRY1NULL; 383338032Speter break; 383438032Speter 383538032Speter case 'o': 383638032Speter map->map_mflags |= MF_OPTIONAL; 383738032Speter break; 383838032Speter 383938032Speter case 'f': 384038032Speter map->map_mflags |= MF_NOFOLDCASE; 384138032Speter break; 384238032Speter 384338032Speter case 'm': 384438032Speter map->map_mflags |= MF_MATCHONLY; 384538032Speter break; 384638032Speter 384738032Speter case 'A': 384838032Speter map->map_mflags |= MF_APPEND; 384938032Speter break; 385038032Speter 385138032Speter case 'q': 385238032Speter map->map_mflags |= MF_KEEPQUOTES; 385338032Speter break; 385438032Speter 385538032Speter case 'a': 385638032Speter map->map_app = ++p; 385738032Speter break; 385838032Speter 385938032Speter case 'T': 386038032Speter map->map_tapp = ++p; 386138032Speter break; 386238032Speter 386364562Sgshapiro case 't': 386464562Sgshapiro map->map_mflags |= MF_NODEFER; 386564562Sgshapiro break; 386664562Sgshapiro 386764562Sgshapiro case 'S': 386864562Sgshapiro map->map_spacesub = *++p; 386964562Sgshapiro break; 387064562Sgshapiro 387164562Sgshapiro case 'D': 387264562Sgshapiro map->map_mflags |= MF_DEFER; 387364562Sgshapiro break; 387464562Sgshapiro 387564562Sgshapiro case 'z': 387664562Sgshapiro if (*++p != '\\') 387764562Sgshapiro map->map_coldelim = *p; 387864562Sgshapiro else 387964562Sgshapiro { 388064562Sgshapiro switch (*++p) 388164562Sgshapiro { 388264562Sgshapiro case 'n': 388364562Sgshapiro map->map_coldelim = '\n'; 388464562Sgshapiro break; 388564562Sgshapiro 388664562Sgshapiro case 't': 388764562Sgshapiro map->map_coldelim = '\t'; 388864562Sgshapiro break; 388964562Sgshapiro 389064562Sgshapiro default: 389164562Sgshapiro map->map_coldelim = '\\'; 389264562Sgshapiro } 389364562Sgshapiro } 389464562Sgshapiro break; 389564562Sgshapiro 389664562Sgshapiro /* Start of ldapmap specific args */ 389738032Speter case 'k': /* search field */ 389838032Speter while (isascii(*++p) && isspace(*p)) 389938032Speter continue; 390064562Sgshapiro lmap->ldap_filter = p; 390138032Speter break; 390238032Speter 390338032Speter case 'v': /* attr to return */ 390438032Speter while (isascii(*++p) && isspace(*p)) 390538032Speter continue; 390664562Sgshapiro lmap->ldap_attr[0] = p; 390764562Sgshapiro lmap->ldap_attr[1] = NULL; 390838032Speter break; 390938032Speter 391064562Sgshapiro case '1': 391164562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 391264562Sgshapiro break; 391364562Sgshapiro 391438032Speter /* args stolen from ldapsearch.c */ 391538032Speter case 'R': /* don't auto chase referrals */ 391664562Sgshapiro# ifdef LDAP_REFERRALS 391738032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 391864562Sgshapiro# else /* LDAP_REFERRALS */ 391938032Speter syserr("compile with -DLDAP_REFERRALS for referral support\n"); 392064562Sgshapiro# endif /* LDAP_REFERRALS */ 392138032Speter break; 392238032Speter 392364562Sgshapiro case 'n': /* retrieve attribute names only */ 392464562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 392538032Speter break; 392638032Speter 392764562Sgshapiro case 'r': /* alias dereferencing */ 392864562Sgshapiro while (isascii(*++p) && isspace(*p)) 392964562Sgshapiro continue; 393064562Sgshapiro 393164562Sgshapiro if (strncasecmp(p, "LDAP_DEREF_", 11) == 0) 393264562Sgshapiro p += 11; 393364562Sgshapiro 393464562Sgshapiro for (lad = LDAPAliasDereference; 393564562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 393638032Speter { 393764562Sgshapiro if (strncasecmp(p, lad->lad_name, 393864562Sgshapiro strlen(lad->lad_name)) == 0) 393964562Sgshapiro break; 394038032Speter } 394164562Sgshapiro if (lad->lad_name != NULL) 394264562Sgshapiro lmap->ldap_deref = lad->lad_code; 394364562Sgshapiro else 394438032Speter { 394564562Sgshapiro /* bad config line */ 394664562Sgshapiro if (!bitset(MCF_OPTFILE, 394764562Sgshapiro map->map_class->map_cflags)) 394864562Sgshapiro { 394964562Sgshapiro char *ptr; 395064562Sgshapiro 395164562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 395264562Sgshapiro *ptr = '\0'; 395373188Sgshapiro syserr("Deref must be [never|always|search|find] (not %s) in map %s", 395464562Sgshapiro p, map->map_mname); 395564562Sgshapiro if (ptr != NULL) 395664562Sgshapiro *ptr = ' '; 395764562Sgshapiro return FALSE; 395864562Sgshapiro } 395938032Speter } 396064562Sgshapiro break; 396164562Sgshapiro 396264562Sgshapiro case 's': /* search scope */ 396364562Sgshapiro while (isascii(*++p) && isspace(*p)) 396464562Sgshapiro continue; 396564562Sgshapiro 396664562Sgshapiro if (strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 396764562Sgshapiro p += 11; 396864562Sgshapiro 396964562Sgshapiro for (lss = LDAPSearchScope; 397064562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 397138032Speter { 397264562Sgshapiro if (strncasecmp(p, lss->lss_name, 397364562Sgshapiro strlen(lss->lss_name)) == 0) 397464562Sgshapiro break; 397538032Speter } 397664562Sgshapiro if (lss->lss_name != NULL) 397764562Sgshapiro lmap->ldap_scope = lss->lss_code; 397838032Speter else 397964562Sgshapiro { 398064562Sgshapiro /* bad config line */ 398164562Sgshapiro if (!bitset(MCF_OPTFILE, 398264562Sgshapiro map->map_class->map_cflags)) 398338032Speter { 398438032Speter char *ptr; 398538032Speter 398638032Speter if ((ptr = strchr(p, ' ')) != NULL) 398738032Speter *ptr = '\0'; 398873188Sgshapiro syserr("Scope must be [base|one|sub] (not %s) in map %s", 398938032Speter p, map->map_mname); 399038032Speter if (ptr != NULL) 399138032Speter *ptr = ' '; 399238032Speter return FALSE; 399338032Speter } 399438032Speter } 399538032Speter break; 399638032Speter 399738032Speter case 'h': /* ldap host */ 399838032Speter while (isascii(*++p) && isspace(*p)) 399938032Speter continue; 400064562Sgshapiro lmap->ldap_host = p; 400138032Speter break; 400238032Speter 400338032Speter case 'b': /* search base */ 400438032Speter while (isascii(*++p) && isspace(*p)) 400538032Speter continue; 400664562Sgshapiro lmap->ldap_base = p; 400738032Speter break; 400838032Speter 400938032Speter case 'p': /* ldap port */ 401038032Speter while (isascii(*++p) && isspace(*p)) 401138032Speter continue; 401264562Sgshapiro lmap->ldap_port = atoi(p); 401338032Speter break; 401438032Speter 401538032Speter case 'l': /* time limit */ 401638032Speter while (isascii(*++p) && isspace(*p)) 401738032Speter continue; 401864562Sgshapiro lmap->ldap_timelimit = atoi(p); 401964562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 402038032Speter break; 402138032Speter 402264562Sgshapiro case 'Z': 402364562Sgshapiro while (isascii(*++p) && isspace(*p)) 402464562Sgshapiro continue; 402564562Sgshapiro lmap->ldap_sizelimit = atoi(p); 402664562Sgshapiro break; 402764562Sgshapiro 402864562Sgshapiro case 'd': /* Dn to bind to server as */ 402964562Sgshapiro while (isascii(*++p) && isspace(*p)) 403064562Sgshapiro continue; 403164562Sgshapiro lmap->ldap_binddn = p; 403264562Sgshapiro break; 403364562Sgshapiro 403464562Sgshapiro case 'M': /* Method for binding */ 403564562Sgshapiro while (isascii(*++p) && isspace(*p)) 403664562Sgshapiro continue; 403764562Sgshapiro 403864562Sgshapiro if (strncasecmp(p, "LDAP_AUTH_", 10) == 0) 403964562Sgshapiro p += 10; 404064562Sgshapiro 404164562Sgshapiro for (lam = LDAPAuthMethods; 404264562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 404364562Sgshapiro { 404464562Sgshapiro if (strncasecmp(p, lam->lam_name, 404564562Sgshapiro strlen(lam->lam_name)) == 0) 404664562Sgshapiro break; 404764562Sgshapiro } 404864562Sgshapiro if (lam->lam_name != NULL) 404964562Sgshapiro lmap->ldap_method = lam->lam_code; 405064562Sgshapiro else 405164562Sgshapiro { 405264562Sgshapiro /* bad config line */ 405364562Sgshapiro if (!bitset(MCF_OPTFILE, 405464562Sgshapiro map->map_class->map_cflags)) 405564562Sgshapiro { 405664562Sgshapiro char *ptr; 405764562Sgshapiro 405864562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 405964562Sgshapiro *ptr = '\0'; 406073188Sgshapiro syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 406164562Sgshapiro p, map->map_mname); 406264562Sgshapiro if (ptr != NULL) 406364562Sgshapiro *ptr = ' '; 406464562Sgshapiro return FALSE; 406564562Sgshapiro } 406664562Sgshapiro } 406764562Sgshapiro 406864562Sgshapiro break; 406964562Sgshapiro 407064562Sgshapiro /* 407164562Sgshapiro ** This is a string that is dependent on the 407264562Sgshapiro ** method used defined above. 407364562Sgshapiro */ 407464562Sgshapiro 407564562Sgshapiro case 'P': /* Secret password for binding */ 407664562Sgshapiro while (isascii(*++p) && isspace(*p)) 407764562Sgshapiro continue; 407864562Sgshapiro lmap->ldap_secret = p; 407964562Sgshapiro secretread = FALSE; 408064562Sgshapiro break; 408164562Sgshapiro 408264562Sgshapiro default: 408364562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 408464562Sgshapiro break; 408538032Speter } 408638032Speter 408764562Sgshapiro /* need to account for quoted strings here */ 408864562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 408938032Speter { 409038032Speter if (*p == '"') 409138032Speter { 409238032Speter while (*++p != '"' && *p != '\0') 409338032Speter continue; 409438032Speter if (*p != '\0') 409538032Speter p++; 409638032Speter } 409738032Speter else 409838032Speter p++; 409938032Speter } 410038032Speter 410138032Speter if (*p != '\0') 410238032Speter *p++ = '\0'; 410338032Speter } 410438032Speter 410538032Speter if (map->map_app != NULL) 410664562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 410738032Speter if (map->map_tapp != NULL) 410864562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 410938032Speter 411038032Speter /* 411142575Speter ** We need to swallow up all the stuff into a struct 411242575Speter ** and dump it into map->map_dbptr1 411338032Speter */ 411438032Speter 411564562Sgshapiro if (lmap->ldap_host != NULL && 411664562Sgshapiro (LDAPDefaults == NULL || 411764562Sgshapiro LDAPDefaults == lmap || 411864562Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 411964562Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 412064562Sgshapiro map->map_domain = lmap->ldap_host; 412164562Sgshapiro 412264562Sgshapiro if (lmap->ldap_binddn != NULL && 412364562Sgshapiro (LDAPDefaults == NULL || 412464562Sgshapiro LDAPDefaults == lmap || 412564562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 412664562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 412764562Sgshapiro 412864562Sgshapiro if (lmap->ldap_secret != NULL && 412964562Sgshapiro (LDAPDefaults == NULL || 413064562Sgshapiro LDAPDefaults == lmap || 413164562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 413238032Speter { 413364562Sgshapiro FILE *sfd; 413464562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 413538032Speter 413664562Sgshapiro if (DontLockReadFiles) 413764562Sgshapiro sff |= SFF_NOLOCK; 413838032Speter 413964562Sgshapiro /* need to use method to map secret to passwd string */ 414064562Sgshapiro switch (lmap->ldap_method) 414164562Sgshapiro { 414264562Sgshapiro case LDAP_AUTH_NONE: 414364562Sgshapiro /* Do nothing */ 414464562Sgshapiro break; 414538032Speter 414664562Sgshapiro case LDAP_AUTH_SIMPLE: 414738032Speter 414864562Sgshapiro /* 414964562Sgshapiro ** Secret is the name of a file with 415064562Sgshapiro ** the first line as the password. 415164562Sgshapiro */ 415264562Sgshapiro 415364562Sgshapiro /* Already read in the secret? */ 415464562Sgshapiro if (secretread) 415564562Sgshapiro break; 415664562Sgshapiro 415764562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 415864562Sgshapiro O_RDONLY, 0, sff); 415964562Sgshapiro if (sfd == NULL) 416064562Sgshapiro { 416164562Sgshapiro syserr("LDAP map: cannot open secret %s", 416264562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 416364562Sgshapiro return FALSE; 416464562Sgshapiro } 416564562Sgshapiro lmap->ldap_secret = sfgets(m_tmp, LDAPMAP_MAX_PASSWD, 416666494Sgshapiro sfd, TimeOuts.to_fileopen, 416766494Sgshapiro "ldapmap_parseargs"); 416864562Sgshapiro (void) fclose(sfd); 416964562Sgshapiro if (lmap->ldap_secret != NULL && 417064562Sgshapiro strlen(m_tmp) > 0) 417164562Sgshapiro { 417264562Sgshapiro /* chomp newline */ 417364562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 417464562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 417564562Sgshapiro 417664562Sgshapiro lmap->ldap_secret = m_tmp; 417764562Sgshapiro } 417864562Sgshapiro break; 417964562Sgshapiro 418064562Sgshapiro# ifdef LDAP_AUTH_KRBV4 418164562Sgshapiro case LDAP_AUTH_KRBV4: 418264562Sgshapiro 418364562Sgshapiro /* 418464562Sgshapiro ** Secret is where the ticket file is 418564562Sgshapiro ** stashed 418664562Sgshapiro */ 418764562Sgshapiro 418864562Sgshapiro snprintf(m_tmp, MAXPATHLEN + LDAPMAP_MAX_PASSWD, 418964562Sgshapiro "KRBTKFILE=%s", 419064562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 419164562Sgshapiro lmap->ldap_secret = m_tmp; 419264562Sgshapiro break; 419364562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 419464562Sgshapiro 419564562Sgshapiro default: /* Should NEVER get here */ 419664562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 419764562Sgshapiro return FALSE; 419864562Sgshapiro break; 419964562Sgshapiro } 420038032Speter } 420138032Speter 420264562Sgshapiro if (lmap->ldap_secret != NULL && 420364562Sgshapiro (LDAPDefaults == NULL || 420464562Sgshapiro LDAPDefaults == lmap || 420564562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 420664562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 420738032Speter 420864562Sgshapiro if (lmap->ldap_base != NULL && 420964562Sgshapiro (LDAPDefaults == NULL || 421064562Sgshapiro LDAPDefaults == lmap || 421164562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 421264562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 421364562Sgshapiro 421464562Sgshapiro /* 421564562Sgshapiro ** Save the server from extra work. If request is for a single 421664562Sgshapiro ** match, tell the server to only return enough records to 421764562Sgshapiro ** determine if there is a single match or not. This can not 421864562Sgshapiro ** be one since the server would only return one and we wouldn't 421964562Sgshapiro ** know if there were others available. 422064562Sgshapiro */ 422164562Sgshapiro 422264562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 422364562Sgshapiro lmap->ldap_sizelimit = 2; 422464562Sgshapiro 422564562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 422664562Sgshapiro if (lmap == LDAPDefaults) 422764562Sgshapiro return TRUE; 422864562Sgshapiro 422964562Sgshapiro if (lmap->ldap_filter != NULL) 423064562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 423138032Speter else 423238032Speter { 423338032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 423438032Speter { 423538032Speter syserr("No filter given in map %s", map->map_mname); 423638032Speter return FALSE; 423738032Speter } 423838032Speter } 423964562Sgshapiro 424064562Sgshapiro if (lmap->ldap_attr[0] != NULL) 424138032Speter { 424264562Sgshapiro i = 0; 424364562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 424464562Sgshapiro lmap->ldap_attr[0] = NULL; 424564562Sgshapiro 424664562Sgshapiro while (p != NULL) 424738032Speter { 424864562Sgshapiro char *v; 424964562Sgshapiro 425064562Sgshapiro while (isascii(*p) && isspace(*p)) 425164562Sgshapiro p++; 425264562Sgshapiro if (*p == '\0') 425364562Sgshapiro break; 425464562Sgshapiro v = p; 425564562Sgshapiro p = strchr(v, ','); 425664562Sgshapiro if (p != NULL) 425764562Sgshapiro *p++ = '\0'; 425864562Sgshapiro 425971345Sgshapiro if (i >= LDAPMAP_MAX_ATTR) 426064562Sgshapiro { 426164562Sgshapiro syserr("Too many return attributes in %s (max %d)", 426264562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 426364562Sgshapiro return FALSE; 426464562Sgshapiro } 426564562Sgshapiro if (*v != '\0') 426664562Sgshapiro lmap->ldap_attr[i++] = newstr(v); 426738032Speter } 426864562Sgshapiro lmap->ldap_attr[i] = NULL; 426938032Speter } 427038032Speter 427138032Speter map->map_db1 = (ARBPTR_T) lmap; 427238032Speter return TRUE; 427338032Speter} 427438032Speter 427564562Sgshapiro/* 427664562Sgshapiro** LDAPMAP_CLEAR -- set default values for LDAPMAP_STRUCT 427764562Sgshapiro** 427864562Sgshapiro** Parameters: 427964562Sgshapiro** lmap -- pointer to LDAPMAP_STRUCT to clear 428064562Sgshapiro** 428164562Sgshapiro** Returns: 428264562Sgshapiro** None. 428364562Sgshapiro** 428464562Sgshapiro*/ 428564562Sgshapiro 428664562Sgshapirostatic void 428764562Sgshapiroldapmap_clear(lmap) 428864562Sgshapiro LDAPMAP_STRUCT *lmap; 428964562Sgshapiro{ 429064562Sgshapiro lmap->ldap_host = NULL; 429164562Sgshapiro lmap->ldap_port = LDAP_PORT; 429264562Sgshapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 429364562Sgshapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 429464562Sgshapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 429564562Sgshapiro# ifdef LDAP_REFERRALS 429664562Sgshapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 429764562Sgshapiro# else /* LDAP_REFERRALS */ 429864562Sgshapiro lmap->ldap_options = 0; 429964562Sgshapiro# endif /* LDAP_REFERRALS */ 430064562Sgshapiro lmap->ldap_binddn = NULL; 430164562Sgshapiro lmap->ldap_secret = NULL; 430264562Sgshapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 430364562Sgshapiro lmap->ldap_base = NULL; 430464562Sgshapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 430564562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 430664562Sgshapiro lmap->ldap_timeout.tv_sec = 0; 430764562Sgshapiro lmap->ldap_timeout.tv_usec = 0; 430864562Sgshapiro lmap->ldap_ld = NULL; 430964562Sgshapiro lmap->ldap_filter = NULL; 431064562Sgshapiro lmap->ldap_attr[0] = NULL; 431164562Sgshapiro lmap->ldap_res = NULL; 431264562Sgshapiro} 431338032Speter/* 431464562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 431564562Sgshapiro** 431664562Sgshapiro** Parameters: 431764562Sgshapiro** spec -- map argument string from LDAPDefaults option 431864562Sgshapiro** 431964562Sgshapiro** Returns: 432064562Sgshapiro** None. 432164562Sgshapiro** 432264562Sgshapiro*/ 432364562Sgshapiro 432464562Sgshapirovoid 432564562Sgshapiroldapmap_set_defaults(spec) 432664562Sgshapiro char *spec; 432764562Sgshapiro{ 432873188Sgshapiro STAB *class; 432964562Sgshapiro MAP map; 433064562Sgshapiro 433164562Sgshapiro /* Allocate and set the default values */ 433264562Sgshapiro if (LDAPDefaults == NULL) 433364562Sgshapiro LDAPDefaults = (LDAPMAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 433464562Sgshapiro ldapmap_clear(LDAPDefaults); 433564562Sgshapiro 433664562Sgshapiro memset(&map, '\0', sizeof map); 433773188Sgshapiro 433873188Sgshapiro /* look up the class */ 433973188Sgshapiro class = stab("ldap", ST_MAPCLASS, ST_FIND); 434073188Sgshapiro if (class == NULL) 434173188Sgshapiro { 434273188Sgshapiro syserr("readcf: LDAPDefaultSpec: class ldap not available"); 434373188Sgshapiro return; 434473188Sgshapiro } 434573188Sgshapiro map.map_class = &class->s_mapclass; 434664562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 434773188Sgshapiro map.map_mname = "O LDAPDefaultSpec"; 434864562Sgshapiro 434964562Sgshapiro (void) ldapmap_parseargs(&map, spec); 435064562Sgshapiro 435164562Sgshapiro /* These should never be set in LDAPDefaults */ 435264562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 435364562Sgshapiro map.map_spacesub != SpaceSub || 435464562Sgshapiro map.map_app != NULL || 435564562Sgshapiro map.map_tapp != NULL) 435664562Sgshapiro { 435764562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 435864562Sgshapiro if (map.map_app != NULL) 435964562Sgshapiro { 436064562Sgshapiro free(map.map_app); 436164562Sgshapiro map.map_app = NULL; 436264562Sgshapiro } 436364562Sgshapiro if (map.map_tapp != NULL) 436464562Sgshapiro { 436564562Sgshapiro free(map.map_tapp); 436664562Sgshapiro map.map_tapp = NULL; 436764562Sgshapiro } 436864562Sgshapiro } 436964562Sgshapiro 437064562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 437164562Sgshapiro { 437264562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 437364562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 437464562Sgshapiro LDAPDefaults->ldap_filter = NULL; 437564562Sgshapiro } 437664562Sgshapiro 437764562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 437864562Sgshapiro { 437964562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 438064562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 438164562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 438264562Sgshapiro } 438364562Sgshapiro} 438464562Sgshapiro#endif /* LDAPMAP */ 438564562Sgshapiro/* 438664562Sgshapiro** PH map 438764562Sgshapiro*/ 438864562Sgshapiro 438964562Sgshapiro#ifdef PH_MAP 439064562Sgshapiro 439164562Sgshapiro/* 439264562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 439364562Sgshapiro** This code is intended to replace the so-called "ph mailer". 439464562Sgshapiro** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 439564562Sgshapiro*/ 439664562Sgshapiro 439764562Sgshapiro# include <qiapi.h> 439864562Sgshapiro# include <qicode.h> 439964562Sgshapiro 440064562Sgshapiro/* 440164562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 440264562Sgshapiro*/ 440364562Sgshapiro 440464562Sgshapirobool 440564562Sgshapiroph_map_parseargs(map, args) 440664562Sgshapiro MAP *map; 440764562Sgshapiro char *args; 440864562Sgshapiro{ 440964562Sgshapiro int i; 441064562Sgshapiro register int done; 441164562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 441264562Sgshapiro register char *p = args; 441364562Sgshapiro 441464562Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 441564562Sgshapiro 441664562Sgshapiro /* defaults */ 441764562Sgshapiro pmap->ph_servers = NULL; 441864562Sgshapiro pmap->ph_field_list = NULL; 441964562Sgshapiro pmap->ph_to_server = NULL; 442064562Sgshapiro pmap->ph_from_server = NULL; 442164562Sgshapiro pmap->ph_sockfd = -1; 442264562Sgshapiro pmap->ph_timeout = 0; 442364562Sgshapiro 442464562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 442564562Sgshapiro for (;;) 442664562Sgshapiro { 442764562Sgshapiro while (isascii(*p) && isspace(*p)) 442864562Sgshapiro p++; 442964562Sgshapiro if (*p != '-') 443064562Sgshapiro break; 443164562Sgshapiro switch (*++p) 443264562Sgshapiro { 443364562Sgshapiro case 'N': 443464562Sgshapiro map->map_mflags |= MF_INCLNULL; 443564562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 443664562Sgshapiro break; 443764562Sgshapiro 443864562Sgshapiro case 'O': 443964562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 444064562Sgshapiro break; 444164562Sgshapiro 444264562Sgshapiro case 'o': 444364562Sgshapiro map->map_mflags |= MF_OPTIONAL; 444464562Sgshapiro break; 444564562Sgshapiro 444664562Sgshapiro case 'f': 444764562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 444864562Sgshapiro break; 444964562Sgshapiro 445064562Sgshapiro case 'm': 445164562Sgshapiro map->map_mflags |= MF_MATCHONLY; 445264562Sgshapiro break; 445364562Sgshapiro 445464562Sgshapiro case 'A': 445564562Sgshapiro map->map_mflags |= MF_APPEND; 445664562Sgshapiro break; 445764562Sgshapiro 445864562Sgshapiro case 'q': 445964562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 446064562Sgshapiro break; 446164562Sgshapiro 446264562Sgshapiro case 't': 446364562Sgshapiro map->map_mflags |= MF_NODEFER; 446464562Sgshapiro break; 446564562Sgshapiro 446664562Sgshapiro case 'a': 446764562Sgshapiro map->map_app = ++p; 446864562Sgshapiro break; 446964562Sgshapiro 447064562Sgshapiro case 'T': 447164562Sgshapiro map->map_tapp = ++p; 447264562Sgshapiro break; 447364562Sgshapiro 447464562Sgshapiro#if _FFR_PHMAP_TIMEOUT 447564562Sgshapiro case 'l': 447664562Sgshapiro while (isascii(*++p) && isspace(*p)) 447764562Sgshapiro continue; 447864562Sgshapiro pmap->ph_timeout = atoi(p); 447964562Sgshapiro break; 448064562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 448164562Sgshapiro 448264562Sgshapiro case 'S': 448364562Sgshapiro map->map_spacesub = *++p; 448464562Sgshapiro break; 448564562Sgshapiro 448664562Sgshapiro case 'D': 448764562Sgshapiro map->map_mflags |= MF_DEFER; 448864562Sgshapiro break; 448964562Sgshapiro 449064562Sgshapiro case 'h': /* PH server list */ 449164562Sgshapiro while (isascii(*++p) && isspace(*p)) 449264562Sgshapiro continue; 449364562Sgshapiro pmap->ph_servers = p; 449464562Sgshapiro break; 449564562Sgshapiro 449664562Sgshapiro case 'v': /* fields to search for */ 449764562Sgshapiro while (isascii(*++p) && isspace(*p)) 449864562Sgshapiro continue; 449964562Sgshapiro pmap->ph_field_list = p; 450064562Sgshapiro break; 450164562Sgshapiro 450264562Sgshapiro default: 450364562Sgshapiro syserr("ph_map_parseargs: unknown option -%c\n", *p); 450464562Sgshapiro } 450564562Sgshapiro 450664562Sgshapiro /* try to account for quoted strings */ 450764562Sgshapiro done = isascii(*p) && isspace(*p); 450864562Sgshapiro while (*p != '\0' && !done) 450964562Sgshapiro { 451064562Sgshapiro if (*p == '"') 451164562Sgshapiro { 451264562Sgshapiro while (*++p != '"' && *p != '\0') 451364562Sgshapiro continue; 451464562Sgshapiro if (*p != '\0') 451564562Sgshapiro p++; 451664562Sgshapiro } 451764562Sgshapiro else 451864562Sgshapiro p++; 451964562Sgshapiro done = isascii(*p) && isspace(*p); 452064562Sgshapiro } 452164562Sgshapiro 452264562Sgshapiro if (*p != '\0') 452364562Sgshapiro *p++ = '\0'; 452464562Sgshapiro } 452564562Sgshapiro 452664562Sgshapiro if (map->map_app != NULL) 452764562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 452864562Sgshapiro if (map->map_tapp != NULL) 452964562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 453064562Sgshapiro 453164562Sgshapiro if (pmap->ph_field_list != NULL) 453264562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 453364562Sgshapiro else 453464562Sgshapiro pmap->ph_field_list = DEFAULT_PH_MAP_FIELDS; 453564562Sgshapiro 453664562Sgshapiro if (pmap->ph_servers != NULL) 453764562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 453864562Sgshapiro else 453964562Sgshapiro { 454064562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 454164562Sgshapiro return FALSE; 454264562Sgshapiro } 454364562Sgshapiro 454464562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 454564562Sgshapiro return TRUE; 454664562Sgshapiro} 454764562Sgshapiro 454864562Sgshapiro#if _FFR_PHMAP_TIMEOUT 454964562Sgshapiro/* 455064562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 455164562Sgshapiro*/ 455264562Sgshapiro 455364562Sgshapirostatic void 455464562Sgshapiroph_map_safeclose(map) 455564562Sgshapiro MAP *map; 455664562Sgshapiro{ 455764562Sgshapiro int save_errno = errno; 455864562Sgshapiro PH_MAP_STRUCT *pmap; 455964562Sgshapiro 456064562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 456164562Sgshapiro 456264562Sgshapiro if (pmap->ph_sockfd != -1) 456364562Sgshapiro { 456464562Sgshapiro (void) close(pmap->ph_sockfd); 456564562Sgshapiro pmap->ph_sockfd = -1; 456664562Sgshapiro } 456764562Sgshapiro if (pmap->ph_from_server != NULL) 456864562Sgshapiro { 456964562Sgshapiro (void) fclose(pmap->ph_from_server); 457064562Sgshapiro pmap->ph_from_server = NULL; 457164562Sgshapiro } 457264562Sgshapiro if (pmap->ph_to_server != NULL) 457364562Sgshapiro { 457464562Sgshapiro (void) fclose(pmap->ph_to_server); 457564562Sgshapiro pmap->ph_to_server = NULL; 457664562Sgshapiro } 457764562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 457864562Sgshapiro errno = save_errno; 457964562Sgshapiro} 458064562Sgshapiro 458164562Sgshapirovoid 458264562Sgshapiroph_map_close(map) 458364562Sgshapiro MAP *map; 458464562Sgshapiro{ 458564562Sgshapiro PH_MAP_STRUCT *pmap; 458664562Sgshapiro 458764562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 458864562Sgshapiro (void) fprintf(pmap->ph_to_server, "quit\n"); 458964562Sgshapiro (void) fflush(pmap->ph_to_server); 459064562Sgshapiro ph_map_safeclose(map); 459164562Sgshapiro} 459264562Sgshapiro 459364562Sgshapirostatic jmp_buf PHTimeout; 459464562Sgshapiro 459564562Sgshapiro/* ARGSUSED */ 459664562Sgshapirostatic void 459764562Sgshapiroph_timeout_func(sig_no) 459864562Sgshapiro int sig_no; 459964562Sgshapiro{ 460064562Sgshapiro longjmp(PHTimeout, 1); 460164562Sgshapiro} 460264562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 460364562Sgshapiro/* 460464562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 460564562Sgshapiro*/ 460664562Sgshapiro 460764562Sgshapirovoid 460864562Sgshapiroph_map_close(map) 460964562Sgshapiro MAP *map; 461064562Sgshapiro{ 461164562Sgshapiro PH_MAP_STRUCT *pmap; 461264562Sgshapiro 461364562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 461464562Sgshapiro CloseQi(pmap->ph_to_server, pmap->ph_from_server); 461564562Sgshapiro pmap->ph_to_server = NULL; 461664562Sgshapiro pmap->ph_from_server = NULL; 461764562Sgshapiro} 461864562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 461964562Sgshapiro 462064562Sgshapiro/* 462164562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 462264562Sgshapiro*/ 462364562Sgshapirobool 462464562Sgshapiroph_map_open(map, mode) 462564562Sgshapiro MAP *map; 462664562Sgshapiro int mode; 462764562Sgshapiro{ 462864562Sgshapiro#if !_FFR_PHMAP_TIMEOUT 462964562Sgshapiro int save_errno = 0; 463064562Sgshapiro#endif /* !_FFR_PHMAP_TIMEOUT */ 463164562Sgshapiro int j; 463264562Sgshapiro char *hostlist, *tmp; 463364562Sgshapiro QIR *server_data = NULL; 463464562Sgshapiro PH_MAP_STRUCT *pmap; 463564562Sgshapiro#if _FFR_PHMAP_TIMEOUT 463664562Sgshapiro register EVENT *ev = NULL; 463764562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 463864562Sgshapiro 463964562Sgshapiro if (tTd(38, 2)) 464064562Sgshapiro dprintf("ph_map_open(%s)\n", map->map_mname); 464164562Sgshapiro 464264562Sgshapiro mode &= O_ACCMODE; 464364562Sgshapiro if (mode != O_RDONLY) 464464562Sgshapiro { 464564562Sgshapiro /* issue a pseudo-error message */ 464664562Sgshapiro# ifdef ENOSYS 464764562Sgshapiro errno = ENOSYS; 464864562Sgshapiro# else /* ENOSYS */ 464964562Sgshapiro# ifdef EFTYPE 465064562Sgshapiro errno = EFTYPE; 465164562Sgshapiro# else /* EFTYPE */ 465264562Sgshapiro errno = ENXIO; 465364562Sgshapiro# endif /* EFTYPE */ 465464562Sgshapiro# endif /* ENOSYS */ 465564562Sgshapiro return FALSE; 465664562Sgshapiro } 465764562Sgshapiro 465866494Sgshapiro if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 465966494Sgshapiro bitset(MF_DEFER, map->map_mflags)) 466066494Sgshapiro { 466166494Sgshapiro if (tTd(9, 1)) 466266494Sgshapiro dprintf("ph_map_open(%s) => DEFERRED\n", 466371345Sgshapiro map->map_mname); 466466494Sgshapiro 466566494Sgshapiro /* 466666494Sgshapiro ** Unset MF_DEFER here so that map_lookup() returns 466766494Sgshapiro ** a temporary failure using the bogus map and 466866494Sgshapiro ** map->map_tapp instead of the default permanent error. 466966494Sgshapiro */ 467066494Sgshapiro 467166494Sgshapiro map->map_mflags &= ~MF_DEFER; 467266494Sgshapiro return FALSE; 467366494Sgshapiro } 467466494Sgshapiro 467564562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 467664562Sgshapiro 467764562Sgshapiro hostlist = newstr(pmap->ph_servers); 467864562Sgshapiro tmp = strtok(hostlist, " "); 467964562Sgshapiro do 468064562Sgshapiro { 468164562Sgshapiro#if _FFR_PHMAP_TIMEOUT 468264562Sgshapiro if (pmap->ph_timeout != 0) 468364562Sgshapiro { 468464562Sgshapiro if (setjmp(PHTimeout) != 0) 468564562Sgshapiro { 468664562Sgshapiro ev = NULL; 468764562Sgshapiro if (LogLevel > 1) 468864562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 468964562Sgshapiro "timeout connecting to PH server %.100s", 469064562Sgshapiro tmp); 469164562Sgshapiro# ifdef ETIMEDOUT 469264562Sgshapiro errno = ETIMEDOUT; 469364562Sgshapiro# else /* ETIMEDOUT */ 469466494Sgshapiro errno = EAGAIN; 469564562Sgshapiro# endif /* ETIMEDOUT */ 469664562Sgshapiro goto ph_map_open_abort; 469764562Sgshapiro } 469864562Sgshapiro ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); 469964562Sgshapiro } 470064562Sgshapiro if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) && 470164562Sgshapiro !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server), 470264562Sgshapiro &(pmap->ph_from_server)) && 470364562Sgshapiro fprintf(pmap->ph_to_server, "id sendmail+phmap\n") >= 0 && 470464562Sgshapiro fflush(pmap->ph_to_server) == 0 && 470564562Sgshapiro (server_data = ReadQi(pmap->ph_from_server, &j)) != NULL && 470664562Sgshapiro server_data->code == 200) 470764562Sgshapiro { 470864562Sgshapiro if (ev != NULL) 470964562Sgshapiro clrevent(ev); 471064562Sgshapiro FreeQIR(server_data); 471164562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 471264562Sgshapiro if (OpenQi(tmp, &(pmap->ph_to_server), 471364562Sgshapiro &(pmap->ph_from_server)) >= 0) 471464562Sgshapiro { 471564562Sgshapiro if (fprintf(pmap->ph_to_server, 471664562Sgshapiro "id sendmail+phmap\n") < 0 || 471764562Sgshapiro fflush(pmap->ph_to_server) < 0 || 471864562Sgshapiro (server_data = ReadQi(pmap->ph_from_server, 471964562Sgshapiro &j)) == NULL || 472064562Sgshapiro server_data->code != 200) 472164562Sgshapiro { 472264562Sgshapiro save_errno = errno; 472364562Sgshapiro CloseQi(pmap->ph_to_server, 472464562Sgshapiro pmap->ph_from_server); 472564562Sgshapiro continue; 472664562Sgshapiro } 472764562Sgshapiro if (server_data != NULL) 472864562Sgshapiro FreeQIR(server_data); 472964562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 473064562Sgshapiro free(hostlist); 473164562Sgshapiro return TRUE; 473264562Sgshapiro } 473364562Sgshapiro#if _FFR_PHMAP_TIMEOUT 473464562Sgshapiro ph_map_open_abort: 473564562Sgshapiro if (ev != NULL) 473664562Sgshapiro clrevent(ev); 473764562Sgshapiro ph_map_safeclose(map); 473864562Sgshapiro if (server_data != NULL) 473964562Sgshapiro { 474064562Sgshapiro FreeQIR(server_data); 474164562Sgshapiro server_data = NULL; 474264562Sgshapiro } 474364562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 474464562Sgshapiro save_errno = errno; 474564562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 474664562Sgshapiro } while (tmp = strtok(NULL, " ")); 474764562Sgshapiro 474864562Sgshapiro#if !_FFR_PHMAP_TIMEOUT 474964562Sgshapiro errno = save_errno; 475064562Sgshapiro#endif /* !_FFR_PHMAP_TIMEOUT */ 475166494Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 475264562Sgshapiro { 475366494Sgshapiro if (errno == 0) 475464562Sgshapiro errno = EAGAIN; 475566494Sgshapiro syserr("ph_map_open: %s: cannot connect to PH server", 475666494Sgshapiro map->map_mname); 475764562Sgshapiro } 475866494Sgshapiro else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 475964562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 476066494Sgshapiro "ph_map_open: %s: cannot connect to PH server", 476166494Sgshapiro map->map_mname); 476264562Sgshapiro free(hostlist); 476364562Sgshapiro return FALSE; 476464562Sgshapiro} 476564562Sgshapiro 476664562Sgshapiro/* 476764562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 476864562Sgshapiro*/ 476964562Sgshapiro 477064562Sgshapiro#if _FFR_PHMAP_TIMEOUT 477164562Sgshapiro# define MAX_PH_FIELDS 20 477264562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 477364562Sgshapiro 477464562Sgshapirochar * 477564562Sgshapiroph_map_lookup(map, key, args, pstat) 477664562Sgshapiro MAP *map; 477764562Sgshapiro char *key; 477864562Sgshapiro char **args; 477964562Sgshapiro int *pstat; 478064562Sgshapiro{ 478164562Sgshapiro int j; 478264562Sgshapiro size_t sz; 478364562Sgshapiro char *tmp, *tmp2; 478464562Sgshapiro char *message = NULL, *field = NULL, *fmtkey; 478564562Sgshapiro QIR *server_data = NULL; 478664562Sgshapiro QIR *qirp; 478764562Sgshapiro char keybuf[MAXKEY + 1], fieldbuf[101]; 478864562Sgshapiro#if _FFR_PHMAP_TIMEOUT 478964562Sgshapiro QIR *hold_data[MAX_PH_FIELDS]; 479064562Sgshapiro int hold_data_idx = 0; 479164562Sgshapiro register EVENT *ev = NULL; 479264562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 479364562Sgshapiro PH_MAP_STRUCT *pmap; 479464562Sgshapiro 479564562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 479664562Sgshapiro 479764562Sgshapiro *pstat = EX_OK; 479864562Sgshapiro 479964562Sgshapiro#if _FFR_PHMAP_TIMEOUT 480064562Sgshapiro if (pmap->ph_timeout != 0) 480164562Sgshapiro { 480264562Sgshapiro if (setjmp(PHTimeout) != 0) 480364562Sgshapiro { 480464562Sgshapiro ev = NULL; 480564562Sgshapiro if (LogLevel > 1) 480664562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 480764562Sgshapiro "timeout during PH lookup of %.100s", 480864562Sgshapiro key); 480964562Sgshapiro# ifdef ETIMEDOUT 481064562Sgshapiro errno = ETIMEDOUT; 481164562Sgshapiro# else /* ETIMEDOUT */ 481264562Sgshapiro errno = 0; 481364562Sgshapiro# endif /* ETIMEDOUT */ 481464562Sgshapiro *pstat = EX_TEMPFAIL; 481564562Sgshapiro goto ph_map_lookup_abort; 481664562Sgshapiro } 481764562Sgshapiro ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); 481864562Sgshapiro } 481964562Sgshapiro 482064562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 482164562Sgshapiro /* check all relevant fields */ 482264562Sgshapiro tmp = pmap->ph_field_list; 482364562Sgshapiro do 482464562Sgshapiro { 482564562Sgshapiro#if _FFR_PHMAP_TIMEOUT 482664562Sgshapiro server_data = NULL; 482764562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 482864562Sgshapiro while (isascii(*tmp) && isspace(*tmp)) 482964562Sgshapiro tmp++; 483064562Sgshapiro if (*tmp == '\0') 483164562Sgshapiro break; 483264562Sgshapiro sz = strcspn(tmp, " ") + 1; 483364562Sgshapiro if (sz > sizeof fieldbuf) 483464562Sgshapiro sz = sizeof fieldbuf; 483564562Sgshapiro (void) strlcpy(fieldbuf, tmp, sz); 483664562Sgshapiro field = fieldbuf; 483764562Sgshapiro tmp += sz; 483864562Sgshapiro 483964562Sgshapiro (void) strlcpy(keybuf, key, sizeof keybuf); 484064562Sgshapiro fmtkey = keybuf; 484164562Sgshapiro if (strcmp(field, "alias") == 0) 484264562Sgshapiro { 484364562Sgshapiro /* 484464562Sgshapiro ** for alias lookups, replace any punctuation 484564562Sgshapiro ** characters with '-' 484664562Sgshapiro */ 484764562Sgshapiro 484864562Sgshapiro for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) 484964562Sgshapiro { 485064562Sgshapiro if (isascii(*tmp2) && ispunct(*tmp2)) 485164562Sgshapiro *tmp2 = '-'; 485264562Sgshapiro } 485364562Sgshapiro tmp2 = field; 485464562Sgshapiro } 485564562Sgshapiro else if (strcmp(field,"spacedname") == 0) 485664562Sgshapiro { 485764562Sgshapiro /* 485864562Sgshapiro ** for "spaced" name lookups, replace any 485964562Sgshapiro ** punctuation characters with a space 486064562Sgshapiro */ 486164562Sgshapiro 486264562Sgshapiro for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) 486364562Sgshapiro { 486464562Sgshapiro if (isascii(*tmp2) && ispunct(*tmp2) && 486564562Sgshapiro *tmp2 != '*') 486664562Sgshapiro *tmp2 = ' '; 486764562Sgshapiro } 486864562Sgshapiro tmp2 = &(field[6]); 486964562Sgshapiro } 487064562Sgshapiro else 487164562Sgshapiro tmp2 = field; 487264562Sgshapiro 487364562Sgshapiro if (LogLevel > 9) 487464562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 487564562Sgshapiro "ph_map_lookup: query %s=\"%s\" return email", 487664562Sgshapiro tmp2, fmtkey); 487764562Sgshapiro if (tTd(38, 20)) 487864562Sgshapiro dprintf("ph_map_lookup: query %s=\"%s\" return email\n", 487964562Sgshapiro tmp2, fmtkey); 488064562Sgshapiro 488164562Sgshapiro j = 0; 488264562Sgshapiro 488364562Sgshapiro if (fprintf(pmap->ph_to_server, "query %s=%s return email\n", 488464562Sgshapiro tmp2, fmtkey) < 0) 488564562Sgshapiro message = "qi query command failed"; 488664562Sgshapiro else if (fflush(pmap->ph_to_server) < 0) 488764562Sgshapiro message = "qi fflush failed"; 488864562Sgshapiro else if ((server_data = ReadQi(pmap->ph_from_server, 488964562Sgshapiro &j)) == NULL) 489064562Sgshapiro message = "ReadQi() returned NULL"; 489164562Sgshapiro 489264562Sgshapiro#if _FFR_PHMAP_TIMEOUT 489364562Sgshapiro if ((hold_data[hold_data_idx] = server_data) != NULL) 489464562Sgshapiro { 489564562Sgshapiro /* save pointer for later free() */ 489664562Sgshapiro hold_data_idx++; 489764562Sgshapiro } 489864562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 489964562Sgshapiro 490064562Sgshapiro if (server_data == NULL || 490164562Sgshapiro (server_data->code >= 400 && 490264562Sgshapiro server_data->code < 500)) 490364562Sgshapiro { 490464562Sgshapiro /* temporary failure */ 490564562Sgshapiro *pstat = EX_TEMPFAIL; 490664562Sgshapiro#if _FFR_PHMAP_TIMEOUT 490764562Sgshapiro break; 490864562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 490964562Sgshapiro if (server_data != NULL) 491064562Sgshapiro { 491164562Sgshapiro FreeQIR(server_data); 491264562Sgshapiro server_data = NULL; 491364562Sgshapiro } 491464562Sgshapiro return NULL; 491564562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 491664562Sgshapiro } 491764562Sgshapiro 491864562Sgshapiro /* 491964562Sgshapiro ** if we found a single match, break out. 492064562Sgshapiro ** otherwise, try the next field. 492164562Sgshapiro */ 492264562Sgshapiro 492364562Sgshapiro if (j == 1) 492464562Sgshapiro break; 492564562Sgshapiro 492664562Sgshapiro /* 492764562Sgshapiro ** check for a single response which is an error: 492864562Sgshapiro ** ReadQi() doesn't set j on error responses, 492964562Sgshapiro ** but we should stop here instead of moving on if 493064562Sgshapiro ** it happens (e.g., alias found but email field empty) 493164562Sgshapiro */ 493264562Sgshapiro 493364562Sgshapiro for (qirp = server_data; 493464562Sgshapiro qirp != NULL && qirp->code < 0; 493564562Sgshapiro qirp++) 493664562Sgshapiro { 493764562Sgshapiro if (tTd(38, 20)) 493864562Sgshapiro dprintf("ph_map_lookup: QIR: %d:%d:%d:%s\n", 493964562Sgshapiro qirp->code, qirp->subcode, qirp->field, 494064562Sgshapiro (qirp->message ? qirp->message 494164562Sgshapiro : "[NULL]")); 494264562Sgshapiro if (qirp->code <= -500) 494364562Sgshapiro { 494464562Sgshapiro j = 0; 494564562Sgshapiro goto ph_map_lookup_abort; 494664562Sgshapiro } 494764562Sgshapiro } 494864562Sgshapiro 494964562Sgshapiro#if _FFR_PHMAP_TIMEOUT 495064562Sgshapiro } while (*tmp != '\0' && hold_data_idx < MAX_PH_FIELDS); 495164562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 495264562Sgshapiro } while (*tmp != '\0'); 495364562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 495464562Sgshapiro 495564562Sgshapiro ph_map_lookup_abort: 495664562Sgshapiro#if _FFR_PHMAP_TIMEOUT 495764562Sgshapiro if (ev != NULL) 495864562Sgshapiro clrevent(ev); 495964562Sgshapiro 496064562Sgshapiro /* 496164562Sgshapiro ** Return EX_TEMPFAIL if the timer popped 496264562Sgshapiro ** or we got a temporary PH error 496364562Sgshapiro */ 496464562Sgshapiro 496564562Sgshapiro if (*pstat == EX_TEMPFAIL) 496664562Sgshapiro ph_map_safeclose(map); 496764562Sgshapiro 496864562Sgshapiro /* if we didn't find a single match, bail out */ 496964562Sgshapiro if (*pstat == EX_OK && j != 1) 497064562Sgshapiro *pstat = EX_UNAVAILABLE; 497164562Sgshapiro 497264562Sgshapiro if (*pstat == EX_OK) 497364562Sgshapiro { 497464562Sgshapiro /* 497564562Sgshapiro ** skip leading whitespace and chop at first address 497664562Sgshapiro */ 497764562Sgshapiro 497864562Sgshapiro for (tmp = server_data->message; 497964562Sgshapiro isascii(*tmp) && isspace(*tmp); 498064562Sgshapiro tmp++) 498164562Sgshapiro continue; 498264562Sgshapiro 498364562Sgshapiro for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) 498464562Sgshapiro { 498564562Sgshapiro if (isascii(*tmp2) && isspace(*tmp2)) 498664562Sgshapiro { 498764562Sgshapiro *tmp2 = '\0'; 498864562Sgshapiro break; 498964562Sgshapiro } 499064562Sgshapiro } 499164562Sgshapiro 499264562Sgshapiro if (tTd(38,20)) 499364562Sgshapiro dprintf("ph_map_lookup: %s => %s\n", key, tmp); 499464562Sgshapiro 499564562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 499664562Sgshapiro message = map_rewrite(map, key, strlen(key), NULL); 499764562Sgshapiro else 499864562Sgshapiro message = map_rewrite(map, tmp, strlen(tmp), args); 499964562Sgshapiro } 500064562Sgshapiro 500164562Sgshapiro /* 500264562Sgshapiro ** Deferred free() of returned server_data values 500364562Sgshapiro ** the deferral is to avoid the risk of a free() being 500464562Sgshapiro ** interrupted by the event timer. By now the timeout event 500564562Sgshapiro ** has been cleared and none of the data is still in use. 500664562Sgshapiro */ 500764562Sgshapiro 500864562Sgshapiro while (--hold_data_idx >= 0) 500964562Sgshapiro { 501064562Sgshapiro if (hold_data[hold_data_idx] != NULL) 501164562Sgshapiro FreeQIR(hold_data[hold_data_idx]); 501264562Sgshapiro } 501364562Sgshapiro 501464562Sgshapiro if (*pstat == EX_OK) 501564562Sgshapiro return message; 501664562Sgshapiro 501764562Sgshapiro return NULL; 501864562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 501964562Sgshapiro /* if we didn't find a single match, bail out */ 502064562Sgshapiro if (j != 1) 502164562Sgshapiro { 502264562Sgshapiro *pstat = EX_UNAVAILABLE; 502364562Sgshapiro if (server_data != NULL) 502464562Sgshapiro { 502564562Sgshapiro FreeQIR(server_data); 502664562Sgshapiro server_data = NULL; 502764562Sgshapiro } 502864562Sgshapiro return NULL; 502964562Sgshapiro } 503064562Sgshapiro 503164562Sgshapiro /* 503264562Sgshapiro ** skip leading whitespace and chop at first address 503364562Sgshapiro */ 503464562Sgshapiro 503564562Sgshapiro for (tmp = server_data->message; 503664562Sgshapiro isascii(*tmp) && isspace(*tmp); 503764562Sgshapiro tmp++) 503864562Sgshapiro continue; 503964562Sgshapiro 504064562Sgshapiro for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) 504164562Sgshapiro { 504264562Sgshapiro if (isascii(*tmp2) && isspace(*tmp2)) 504364562Sgshapiro { 504464562Sgshapiro *tmp2 = '\0'; 504564562Sgshapiro break; 504664562Sgshapiro } 504764562Sgshapiro } 504864562Sgshapiro 504964562Sgshapiro if (tTd(38,20)) 505064562Sgshapiro dprintf("ph_map_lookup: %s => %s\n", key, tmp); 505164562Sgshapiro 505264562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 505364562Sgshapiro message = map_rewrite(map, key, strlen(key), NULL); 505464562Sgshapiro else 505564562Sgshapiro message = map_rewrite(map, tmp, strlen(tmp), args); 505664562Sgshapiro if (server_data != NULL) 505764562Sgshapiro { 505864562Sgshapiro FreeQIR(server_data); 505964562Sgshapiro server_data = NULL; 506064562Sgshapiro } 506164562Sgshapiro return message; 506264562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 506364562Sgshapiro} 506464562Sgshapiro#endif /* PH_MAP */ 506564562Sgshapiro/* 506642575Speter** syslog map 506738032Speter*/ 506838032Speter 506938032Speter#define map_prio map_lockfd /* overload field */ 507038032Speter 507138032Speter/* 507242575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 507338032Speter*/ 507438032Speter 507538032Speterbool 507638032Spetersyslog_map_parseargs(map, args) 507738032Speter MAP *map; 507838032Speter char *args; 507938032Speter{ 508038032Speter char *p = args; 508138032Speter char *priority = NULL; 508238032Speter 508364562Sgshapiro /* there is no check whether there is really an argument */ 508464562Sgshapiro while (*p != '\0') 508538032Speter { 508638032Speter while (isascii(*p) && isspace(*p)) 508738032Speter p++; 508838032Speter if (*p != '-') 508938032Speter break; 509064562Sgshapiro ++p; 509164562Sgshapiro if (*p == 'D') 509264562Sgshapiro { 509364562Sgshapiro map->map_mflags |= MF_DEFER; 509464562Sgshapiro ++p; 509564562Sgshapiro } 509664562Sgshapiro else if (*p == 'S') 509764562Sgshapiro { 509864562Sgshapiro map->map_spacesub = *++p; 509964562Sgshapiro if (*p != '\0') 510064562Sgshapiro p++; 510164562Sgshapiro } 510264562Sgshapiro else if (*p == 'L') 510364562Sgshapiro { 510464562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 510564562Sgshapiro continue; 510664562Sgshapiro if (*p == '\0') 510764562Sgshapiro break; 510864562Sgshapiro priority = p; 510964562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 511064562Sgshapiro p++; 511164562Sgshapiro if (*p != '\0') 511264562Sgshapiro *p++ = '\0'; 511364562Sgshapiro } 511464562Sgshapiro else 511564562Sgshapiro { 511664562Sgshapiro syserr("Illegal option %c map syslog", *p); 511764562Sgshapiro ++p; 511864562Sgshapiro } 511938032Speter } 512038032Speter 512138032Speter if (priority == NULL) 512238032Speter map->map_prio = LOG_INFO; 512338032Speter else 512438032Speter { 512538032Speter if (strncasecmp("LOG_", priority, 4) == 0) 512638032Speter priority += 4; 512738032Speter 512838032Speter#ifdef LOG_EMERG 512938032Speter if (strcasecmp("EMERG", priority) == 0) 513038032Speter map->map_prio = LOG_EMERG; 513138032Speter else 513264562Sgshapiro#endif /* LOG_EMERG */ 513338032Speter#ifdef LOG_ALERT 513438032Speter if (strcasecmp("ALERT", priority) == 0) 513538032Speter map->map_prio = LOG_ALERT; 513638032Speter else 513764562Sgshapiro#endif /* LOG_ALERT */ 513838032Speter#ifdef LOG_CRIT 513938032Speter if (strcasecmp("CRIT", priority) == 0) 514038032Speter map->map_prio = LOG_CRIT; 514138032Speter else 514264562Sgshapiro#endif /* LOG_CRIT */ 514338032Speter#ifdef LOG_ERR 514438032Speter if (strcasecmp("ERR", priority) == 0) 514538032Speter map->map_prio = LOG_ERR; 514638032Speter else 514764562Sgshapiro#endif /* LOG_ERR */ 514838032Speter#ifdef LOG_WARNING 514938032Speter if (strcasecmp("WARNING", priority) == 0) 515038032Speter map->map_prio = LOG_WARNING; 515138032Speter else 515264562Sgshapiro#endif /* LOG_WARNING */ 515338032Speter#ifdef LOG_NOTICE 515438032Speter if (strcasecmp("NOTICE", priority) == 0) 515538032Speter map->map_prio = LOG_NOTICE; 515638032Speter else 515764562Sgshapiro#endif /* LOG_NOTICE */ 515838032Speter#ifdef LOG_INFO 515938032Speter if (strcasecmp("INFO", priority) == 0) 516038032Speter map->map_prio = LOG_INFO; 516138032Speter else 516264562Sgshapiro#endif /* LOG_INFO */ 516338032Speter#ifdef LOG_DEBUG 516438032Speter if (strcasecmp("DEBUG", priority) == 0) 516538032Speter map->map_prio = LOG_DEBUG; 516638032Speter else 516764562Sgshapiro#endif /* LOG_DEBUG */ 516838032Speter { 516938032Speter syserr("syslog_map_parseargs: Unknown priority %s\n", 517038032Speter priority); 517138032Speter return FALSE; 517238032Speter } 517338032Speter } 517438032Speter return TRUE; 517538032Speter} 517638032Speter 517738032Speter/* 517842575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 517938032Speter*/ 518038032Speter 518138032Speterchar * 518238032Spetersyslog_map_lookup(map, string, args, statp) 518338032Speter MAP *map; 518438032Speter char *string; 518538032Speter char **args; 518638032Speter int *statp; 518738032Speter{ 518838032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 518938032Speter 519038032Speter if (ptr != NULL) 519138032Speter { 519238032Speter if (tTd(38, 20)) 519364562Sgshapiro dprintf("syslog_map_lookup(%s (priority %d): %s\n", 519464562Sgshapiro map->map_mname, map->map_prio, ptr); 519538032Speter 519638032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 519738032Speter } 519838032Speter 519938032Speter *statp = EX_OK; 520038032Speter return ""; 520138032Speter} 520238032Speter 520338032Speter/* 520438032Speter** HESIOD Modules 520538032Speter*/ 520638032Speter 520738032Speter#ifdef HESIOD 520838032Speter 520938032Speterbool 521038032Speterhes_map_open(map, mode) 521138032Speter MAP *map; 521238032Speter int mode; 521338032Speter{ 521438032Speter if (tTd(38, 2)) 521564562Sgshapiro dprintf("hes_map_open(%s, %s, %d)\n", 521638032Speter map->map_mname, map->map_file, mode); 521738032Speter 521838032Speter if (mode != O_RDONLY) 521938032Speter { 522038032Speter /* issue a pseudo-error message */ 522164562Sgshapiro# ifdef ENOSYS 522238032Speter errno = ENOSYS; 522364562Sgshapiro# else /* ENOSYS */ 522464562Sgshapiro# ifdef EFTYPE 522538032Speter errno = EFTYPE; 522664562Sgshapiro# else /* EFTYPE */ 522738032Speter errno = ENXIO; 522864562Sgshapiro# endif /* EFTYPE */ 522964562Sgshapiro# endif /* ENOSYS */ 523038032Speter return FALSE; 523138032Speter } 523238032Speter 523364562Sgshapiro# ifdef HESIOD_INIT 523438032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 523538032Speter return TRUE; 523638032Speter 523738032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 523864562Sgshapiro syserr("421 4.0.0 cannot initialize Hesiod map (%s)", 523938032Speter errstring(errno)); 524038032Speter return FALSE; 524164562Sgshapiro# else /* HESIOD_INIT */ 524238032Speter if (hes_error() == HES_ER_UNINIT) 524338032Speter hes_init(); 524438032Speter switch (hes_error()) 524538032Speter { 524638032Speter case HES_ER_OK: 524738032Speter case HES_ER_NOTFOUND: 524838032Speter return TRUE; 524938032Speter } 525038032Speter 525138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 525264562Sgshapiro syserr("421 4.0.0 cannot initialize Hesiod map (%d)", hes_error()); 525338032Speter 525438032Speter return FALSE; 525564562Sgshapiro# endif /* HESIOD_INIT */ 525638032Speter} 525738032Speter 525838032Speterchar * 525938032Speterhes_map_lookup(map, name, av, statp) 526038032Speter MAP *map; 526138032Speter char *name; 526238032Speter char **av; 526338032Speter int *statp; 526438032Speter{ 526538032Speter char **hp; 526638032Speter 526738032Speter if (tTd(38, 20)) 526864562Sgshapiro dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 526938032Speter 527038032Speter if (name[0] == '\\') 527138032Speter { 527238032Speter char *np; 527338032Speter int nl; 527438032Speter char nbuf[MAXNAME]; 527538032Speter 527638032Speter nl = strlen(name); 527738032Speter if (nl < sizeof nbuf - 1) 527838032Speter np = nbuf; 527938032Speter else 528038032Speter np = xalloc(strlen(name) + 2); 528138032Speter np[0] = '\\'; 528264562Sgshapiro (void) strlcpy(&np[1], name, (sizeof nbuf) - 1); 528364562Sgshapiro# ifdef HESIOD_INIT 528438032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 528564562Sgshapiro# else /* HESIOD_INIT */ 528638032Speter hp = hes_resolve(np, map->map_file); 528764562Sgshapiro# endif /* HESIOD_INIT */ 528838032Speter if (np != nbuf) 528938032Speter free(np); 529038032Speter } 529138032Speter else 529238032Speter { 529364562Sgshapiro# ifdef HESIOD_INIT 529438032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 529564562Sgshapiro# else /* HESIOD_INIT */ 529638032Speter hp = hes_resolve(name, map->map_file); 529764562Sgshapiro# endif /* HESIOD_INIT */ 529838032Speter } 529964562Sgshapiro# ifdef HESIOD_INIT 530038032Speter if (hp == NULL) 530138032Speter return NULL; 530238032Speter if (*hp == NULL) 530338032Speter { 530438032Speter hesiod_free_list(HesiodContext, hp); 530538032Speter switch (errno) 530638032Speter { 530738032Speter case ENOENT: 530838032Speter *statp = EX_NOTFOUND; 530938032Speter break; 531038032Speter case ECONNREFUSED: 531138032Speter case EMSGSIZE: 531238032Speter *statp = EX_TEMPFAIL; 531338032Speter break; 531438032Speter case ENOMEM: 531538032Speter default: 531638032Speter *statp = EX_UNAVAILABLE; 531738032Speter break; 531838032Speter } 531938032Speter return NULL; 532038032Speter } 532164562Sgshapiro# else /* HESIOD_INIT */ 532238032Speter if (hp == NULL || hp[0] == NULL) 532338032Speter { 532438032Speter switch (hes_error()) 532538032Speter { 532638032Speter case HES_ER_OK: 532738032Speter *statp = EX_OK; 532838032Speter break; 532938032Speter 533038032Speter case HES_ER_NOTFOUND: 533138032Speter *statp = EX_NOTFOUND; 533238032Speter break; 533338032Speter 533438032Speter case HES_ER_CONFIG: 533538032Speter *statp = EX_UNAVAILABLE; 533638032Speter break; 533738032Speter 533838032Speter case HES_ER_NET: 533938032Speter *statp = EX_TEMPFAIL; 534038032Speter break; 534138032Speter } 534238032Speter return NULL; 534338032Speter } 534464562Sgshapiro# endif /* HESIOD_INIT */ 534538032Speter 534638032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 534738032Speter return map_rewrite(map, name, strlen(name), NULL); 534838032Speter else 534938032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 535038032Speter} 535138032Speter 535264562Sgshapiro#endif /* HESIOD */ 535338032Speter/* 535438032Speter** NeXT NETINFO Modules 535538032Speter*/ 535638032Speter 535738032Speter#if NETINFO 535838032Speter 535938032Speter# define NETINFO_DEFAULT_DIR "/aliases" 536038032Speter# define NETINFO_DEFAULT_PROPERTY "members" 536138032Speter 536238032Speter/* 536338032Speter** NI_MAP_OPEN -- open NetInfo Aliases 536438032Speter*/ 536538032Speter 536638032Speterbool 536738032Speterni_map_open(map, mode) 536838032Speter MAP *map; 536938032Speter int mode; 537038032Speter{ 537138032Speter if (tTd(38, 2)) 537264562Sgshapiro dprintf("ni_map_open(%s, %s, %d)\n", 537338032Speter map->map_mname, map->map_file, mode); 537438032Speter mode &= O_ACCMODE; 537538032Speter 537638032Speter if (*map->map_file == '\0') 537738032Speter map->map_file = NETINFO_DEFAULT_DIR; 537838032Speter 537938032Speter if (map->map_valcolnm == NULL) 538038032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 538138032Speter 538238032Speter if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 538338032Speter map->map_coldelim = ','; 538438032Speter 538538032Speter return TRUE; 538638032Speter} 538738032Speter 538838032Speter 538938032Speter/* 539038032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 539138032Speter*/ 539238032Speter 539338032Speterchar * 539438032Speterni_map_lookup(map, name, av, statp) 539538032Speter MAP *map; 539638032Speter char *name; 539738032Speter char **av; 539838032Speter int *statp; 539938032Speter{ 540038032Speter char *res; 540138032Speter char *propval; 540238032Speter 540338032Speter if (tTd(38, 20)) 540464562Sgshapiro dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 540538032Speter 540638032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 540738032Speter map->map_valcolnm, map->map_coldelim); 540838032Speter 540938032Speter if (propval == NULL) 541038032Speter return NULL; 541138032Speter 541238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 541338032Speter res = map_rewrite(map, name, strlen(name), NULL); 541438032Speter else 541538032Speter res = map_rewrite(map, propval, strlen(propval), av); 541638032Speter free(propval); 541738032Speter return res; 541838032Speter} 541938032Speter 542038032Speter 542164562Sgshapirostatic bool 542238032Speterni_getcanonname(name, hbsize, statp) 542338032Speter char *name; 542438032Speter int hbsize; 542538032Speter int *statp; 542638032Speter{ 542738032Speter char *vptr; 542838032Speter char *ptr; 542938032Speter char nbuf[MAXNAME + 1]; 543038032Speter 543138032Speter if (tTd(38, 20)) 543264562Sgshapiro dprintf("ni_getcanonname(%s)\n", name); 543338032Speter 543464562Sgshapiro if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 543538032Speter { 543638032Speter *statp = EX_UNAVAILABLE; 543738032Speter return FALSE; 543838032Speter } 543973188Sgshapiro (void) shorten_hostname(nbuf); 544038032Speter 544138032Speter /* we only accept single token search key */ 544238032Speter if (strchr(nbuf, '.')) 544338032Speter { 544438032Speter *statp = EX_NOHOST; 544538032Speter return FALSE; 544638032Speter } 544738032Speter 544838032Speter /* Do the search */ 544938032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 545038032Speter 545138032Speter if (vptr == NULL) 545238032Speter { 545338032Speter *statp = EX_NOHOST; 545438032Speter return FALSE; 545538032Speter } 545638032Speter 545738032Speter /* Only want the first machine name */ 545838032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 545938032Speter *ptr = '\0'; 546038032Speter 546138032Speter if (hbsize >= strlen(vptr)) 546238032Speter { 546364562Sgshapiro (void) strlcpy(name, vptr, hbsize); 546464562Sgshapiro free(vptr); 546538032Speter *statp = EX_OK; 546638032Speter return TRUE; 546738032Speter } 546838032Speter *statp = EX_UNAVAILABLE; 546938032Speter free(vptr); 547038032Speter return FALSE; 547138032Speter} 547238032Speter 547338032Speter 547438032Speter/* 547538032Speter** NI_PROPVAL -- NetInfo property value lookup routine 547638032Speter** 547738032Speter** Parameters: 547838032Speter** keydir -- the NetInfo directory name in which to search 547938032Speter** for the key. 548038032Speter** keyprop -- the name of the property in which to find the 548138032Speter** property we are interested. Defaults to "name". 548238032Speter** keyval -- the value for which we are really searching. 548338032Speter** valprop -- the property name for the value in which we 548438032Speter** are interested. 548538032Speter** sepchar -- if non-nil, this can be multiple-valued, and 548638032Speter** we should return a string separated by this 548738032Speter** character. 548838032Speter** 548938032Speter** Returns: 549038032Speter** NULL -- if: 549138032Speter** 1. the directory is not found 549238032Speter** 2. the property name is not found 549338032Speter** 3. the property contains multiple values 549464562Sgshapiro** 4. some error occurred 549538032Speter** else -- the value of the lookup. 549638032Speter** 549738032Speter** Example: 549838032Speter** To search for an alias value, use: 549938032Speter** ni_propval("/aliases", "name", aliasname, "members", ',') 550038032Speter** 550138032Speter** Notes: 550264562Sgshapiro** Caller should free the return value of ni_proval 550338032Speter*/ 550438032Speter 550538032Speter# include <netinfo/ni.h> 550638032Speter 550764562Sgshapiro# define LOCAL_NETINFO_DOMAIN "." 550864562Sgshapiro# define PARENT_NETINFO_DOMAIN ".." 550964562Sgshapiro# define MAX_NI_LEVELS 256 551038032Speter 551138032Speterchar * 551238032Speterni_propval(keydir, keyprop, keyval, valprop, sepchar) 551338032Speter char *keydir; 551438032Speter char *keyprop; 551538032Speter char *keyval; 551638032Speter char *valprop; 551738032Speter int sepchar; 551838032Speter{ 551938032Speter char *propval = NULL; 552038032Speter int i; 552164562Sgshapiro int j, alen, l; 552238032Speter void *ni = NULL; 552338032Speter void *lastni = NULL; 552438032Speter ni_status nis; 552538032Speter ni_id nid; 552638032Speter ni_namelist ninl; 552738032Speter register char *p; 552838032Speter char keybuf[1024]; 552938032Speter 553038032Speter /* 553138032Speter ** Create the full key from the two parts. 553238032Speter ** 553338032Speter ** Note that directory can end with, e.g., "name=" to specify 553438032Speter ** an alternate search property. 553538032Speter */ 553638032Speter 553738032Speter i = strlen(keydir) + strlen(keyval) + 2; 553838032Speter if (keyprop != NULL) 553938032Speter i += strlen(keyprop) + 1; 554064562Sgshapiro if (i >= sizeof keybuf) 554138032Speter return NULL; 554264562Sgshapiro (void) strlcpy(keybuf, keydir, sizeof keybuf); 554364562Sgshapiro (void) strlcat(keybuf, "/", sizeof keybuf); 554438032Speter if (keyprop != NULL) 554538032Speter { 554664562Sgshapiro (void) strlcat(keybuf, keyprop, sizeof keybuf); 554764562Sgshapiro (void) strlcat(keybuf, "=", sizeof keybuf); 554838032Speter } 554964562Sgshapiro (void) strlcat(keybuf, keyval, sizeof keybuf); 555038032Speter 555138032Speter if (tTd(38, 21)) 555264562Sgshapiro dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", 555338032Speter keydir, keyprop, keyval, valprop, sepchar, keybuf); 555438032Speter /* 555538032Speter ** If the passed directory and property name are found 555638032Speter ** in one of netinfo domains we need to search (starting 555738032Speter ** from the local domain moving all the way back to the 555838032Speter ** root domain) set propval to the property's value 555938032Speter ** and return it. 556038032Speter */ 556138032Speter 556238032Speter for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) 556338032Speter { 556438032Speter if (i == 0) 556538032Speter { 556638032Speter nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 556738032Speter if (tTd(38, 20)) 556864562Sgshapiro dprintf("ni_open(LOCAL) = %d\n", nis); 556938032Speter } 557038032Speter else 557138032Speter { 557238032Speter if (lastni != NULL) 557338032Speter ni_free(lastni); 557438032Speter lastni = ni; 557538032Speter nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 557638032Speter if (tTd(38, 20)) 557764562Sgshapiro dprintf("ni_open(PARENT) = %d\n", nis); 557838032Speter } 557938032Speter 558038032Speter /* 558138032Speter ** Don't bother if we didn't get a handle on a 558238032Speter ** proper domain. This is not necessarily an error. 558338032Speter ** We would get a positive ni_status if, for instance 558438032Speter ** we never found the directory or property and tried 558538032Speter ** to open the parent of the root domain! 558638032Speter */ 558738032Speter 558838032Speter if (nis != 0) 558938032Speter break; 559038032Speter 559138032Speter /* 559238032Speter ** Find the path to the server information. 559338032Speter */ 559438032Speter 559538032Speter if (ni_pathsearch(ni, &nid, keybuf) != 0) 559638032Speter continue; 559738032Speter 559838032Speter /* 559938032Speter ** Find associated value information. 560038032Speter */ 560138032Speter 560238032Speter if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 560338032Speter continue; 560438032Speter 560538032Speter if (tTd(38, 20)) 560664562Sgshapiro dprintf("ni_lookupprop: len=%d\n", 560764562Sgshapiro ninl.ni_namelist_len); 560864562Sgshapiro 560938032Speter /* 561038032Speter ** See if we have an acceptable number of values. 561138032Speter */ 561238032Speter 561338032Speter if (ninl.ni_namelist_len <= 0) 561438032Speter continue; 561538032Speter 561638032Speter if (sepchar == '\0' && ninl.ni_namelist_len > 1) 561738032Speter { 561838032Speter ni_namelist_free(&ninl); 561938032Speter continue; 562038032Speter } 562138032Speter 562238032Speter /* 562338032Speter ** Calculate number of bytes needed and build result 562438032Speter */ 562538032Speter 562638032Speter alen = 1; 562738032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 562838032Speter alen += strlen(ninl.ni_namelist_val[j]) + 1; 562938032Speter propval = p = xalloc(alen); 563038032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 563138032Speter { 563264562Sgshapiro (void) strlcpy(p, ninl.ni_namelist_val[j], alen); 563364562Sgshapiro l = strlen(p); 563464562Sgshapiro p += l; 563538032Speter *p++ = sepchar; 563664562Sgshapiro alen -= l + 1; 563738032Speter } 563838032Speter *--p = '\0'; 563938032Speter 564038032Speter ni_namelist_free(&ninl); 564138032Speter } 564238032Speter 564338032Speter /* 564438032Speter ** Clean up. 564538032Speter */ 564638032Speter 564738032Speter if (ni != NULL) 564838032Speter ni_free(ni); 564938032Speter if (lastni != NULL && ni != lastni) 565038032Speter ni_free(lastni); 565138032Speter if (tTd(38, 20)) 565264562Sgshapiro dprintf("ni_propval returns: '%s'\n", propval); 565338032Speter 565438032Speter return propval; 565538032Speter} 565638032Speter 565742575Speter#endif /* NETINFO */ 565838032Speter/* 565938032Speter** TEXT (unindexed text file) Modules 566038032Speter** 566138032Speter** This code donated by Sun Microsystems. 566238032Speter*/ 566338032Speter 566438032Speter#define map_sff map_lockfd /* overload field */ 566538032Speter 566638032Speter 566738032Speter/* 566838032Speter** TEXT_MAP_OPEN -- open text table 566938032Speter*/ 567038032Speter 567138032Speterbool 567238032Spetertext_map_open(map, mode) 567338032Speter MAP *map; 567438032Speter int mode; 567538032Speter{ 567664562Sgshapiro long sff; 567738032Speter int i; 567838032Speter 567938032Speter if (tTd(38, 2)) 568064562Sgshapiro dprintf("text_map_open(%s, %s, %d)\n", 568138032Speter map->map_mname, map->map_file, mode); 568238032Speter 568338032Speter mode &= O_ACCMODE; 568438032Speter if (mode != O_RDONLY) 568538032Speter { 568638032Speter errno = EPERM; 568738032Speter return FALSE; 568838032Speter } 568938032Speter 569038032Speter if (*map->map_file == '\0') 569138032Speter { 569238032Speter syserr("text map \"%s\": file name required", 569338032Speter map->map_mname); 569438032Speter return FALSE; 569538032Speter } 569638032Speter 569738032Speter if (map->map_file[0] != '/') 569838032Speter { 569938032Speter syserr("text map \"%s\": file name must be fully qualified", 570038032Speter map->map_mname); 570138032Speter return FALSE; 570238032Speter } 570338032Speter 570438032Speter sff = SFF_ROOTOK|SFF_REGONLY; 570564562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 570638032Speter sff |= SFF_NOWLINK; 570764562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 570838032Speter sff |= SFF_SAFEDIRPATH; 570938032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 571038032Speter sff, S_IRUSR, NULL)) != 0) 571138032Speter { 571264562Sgshapiro int save_errno = errno; 571364562Sgshapiro 571438032Speter /* cannot open this map */ 571538032Speter if (tTd(38, 2)) 571664562Sgshapiro dprintf("\tunsafe map file: %d\n", i); 571764562Sgshapiro errno = save_errno; 571838032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 571938032Speter syserr("text map \"%s\": unsafe map file %s", 572038032Speter map->map_mname, map->map_file); 572138032Speter return FALSE; 572238032Speter } 572338032Speter 572438032Speter if (map->map_keycolnm == NULL) 572538032Speter map->map_keycolno = 0; 572638032Speter else 572738032Speter { 572838032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 572938032Speter { 573038032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 573138032Speter map->map_mname, map->map_file, 573238032Speter map->map_keycolnm); 573338032Speter return FALSE; 573438032Speter } 573538032Speter map->map_keycolno = atoi(map->map_keycolnm); 573638032Speter } 573738032Speter 573838032Speter if (map->map_valcolnm == NULL) 573938032Speter map->map_valcolno = 0; 574038032Speter else 574138032Speter { 574238032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 574338032Speter { 574438032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 574538032Speter map->map_mname, map->map_file, 574638032Speter map->map_valcolnm); 574738032Speter return FALSE; 574838032Speter } 574938032Speter map->map_valcolno = atoi(map->map_valcolnm); 575038032Speter } 575138032Speter 575238032Speter if (tTd(38, 2)) 575338032Speter { 575464562Sgshapiro dprintf("text_map_open(%s, %s): delimiter = ", 575538032Speter map->map_mname, map->map_file); 575638032Speter if (map->map_coldelim == '\0') 575764562Sgshapiro dprintf("(white space)\n"); 575838032Speter else 575964562Sgshapiro dprintf("%c\n", map->map_coldelim); 576038032Speter } 576138032Speter 576238032Speter map->map_sff = sff; 576338032Speter return TRUE; 576438032Speter} 576538032Speter 576638032Speter 576738032Speter/* 576838032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 576938032Speter*/ 577038032Speter 577138032Speterchar * 577238032Spetertext_map_lookup(map, name, av, statp) 577338032Speter MAP *map; 577438032Speter char *name; 577538032Speter char **av; 577638032Speter int *statp; 577738032Speter{ 577838032Speter char *vp; 577938032Speter auto int vsize; 578038032Speter int buflen; 578138032Speter FILE *f; 578238032Speter char delim; 578338032Speter int key_idx; 578438032Speter bool found_it; 578564562Sgshapiro long sff = map->map_sff; 578638032Speter char search_key[MAXNAME + 1]; 578738032Speter char linebuf[MAXLINE]; 578838032Speter char buf[MAXNAME + 1]; 578938032Speter 579038032Speter found_it = FALSE; 579138032Speter if (tTd(38, 20)) 579264562Sgshapiro dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 579338032Speter 579438032Speter buflen = strlen(name); 579538032Speter if (buflen > sizeof search_key - 1) 579638032Speter buflen = sizeof search_key - 1; 579764562Sgshapiro memmove(search_key, name, buflen); 579838032Speter search_key[buflen] = '\0'; 579938032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 580038032Speter makelower(search_key); 580138032Speter 580238032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 580338032Speter if (f == NULL) 580438032Speter { 580538032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 580638032Speter *statp = EX_UNAVAILABLE; 580738032Speter return NULL; 580838032Speter } 580938032Speter key_idx = map->map_keycolno; 581038032Speter delim = map->map_coldelim; 581138032Speter while (fgets(linebuf, MAXLINE, f) != NULL) 581238032Speter { 581338032Speter char *p; 581438032Speter 581538032Speter /* skip comment line */ 581638032Speter if (linebuf[0] == '#') 581738032Speter continue; 581838032Speter p = strchr(linebuf, '\n'); 581938032Speter if (p != NULL) 582038032Speter *p = '\0'; 582138032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 582238032Speter if (p != NULL && strcasecmp(search_key, p) == 0) 582338032Speter { 582438032Speter found_it = TRUE; 582538032Speter break; 582638032Speter } 582738032Speter } 582864562Sgshapiro (void) fclose(f); 582938032Speter if (!found_it) 583038032Speter { 583138032Speter *statp = EX_NOTFOUND; 583238032Speter return NULL; 583338032Speter } 583438032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 583542575Speter if (vp == NULL) 583642575Speter { 583742575Speter *statp = EX_NOTFOUND; 583842575Speter return NULL; 583942575Speter } 584038032Speter vsize = strlen(vp); 584138032Speter *statp = EX_OK; 584238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 584338032Speter return map_rewrite(map, name, strlen(name), NULL); 584438032Speter else 584538032Speter return map_rewrite(map, vp, vsize, av); 584638032Speter} 584738032Speter 584838032Speter/* 584938032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 585038032Speter*/ 585138032Speter 585264562Sgshapirostatic bool 585338032Spetertext_getcanonname(name, hbsize, statp) 585438032Speter char *name; 585538032Speter int hbsize; 585638032Speter int *statp; 585738032Speter{ 585838032Speter bool found; 585973188Sgshapiro char *dot; 586038032Speter FILE *f; 586138032Speter char linebuf[MAXLINE]; 586238032Speter char cbuf[MAXNAME + 1]; 586338032Speter char nbuf[MAXNAME + 1]; 586438032Speter 586538032Speter if (tTd(38, 20)) 586664562Sgshapiro dprintf("text_getcanonname(%s)\n", name); 586738032Speter 586838032Speter if (strlen(name) >= (SIZE_T) sizeof nbuf) 586938032Speter { 587038032Speter *statp = EX_UNAVAILABLE; 587138032Speter return FALSE; 587238032Speter } 587364562Sgshapiro (void) strlcpy(nbuf, name, sizeof nbuf); 587473188Sgshapiro dot = shorten_hostname(nbuf); 587538032Speter 587638032Speter f = fopen(HostsFile, "r"); 587738032Speter if (f == NULL) 587838032Speter { 587938032Speter *statp = EX_UNAVAILABLE; 588038032Speter return FALSE; 588138032Speter } 588238032Speter found = FALSE; 588338032Speter while (!found && fgets(linebuf, MAXLINE, f) != NULL) 588438032Speter { 588538032Speter char *p = strpbrk(linebuf, "#\n"); 588638032Speter 588738032Speter if (p != NULL) 588838032Speter *p = '\0'; 588938032Speter if (linebuf[0] != '\0') 589073188Sgshapiro found = extract_canonname(nbuf, dot, linebuf, 589173188Sgshapiro cbuf, sizeof cbuf); 589238032Speter } 589364562Sgshapiro (void) fclose(f); 589438032Speter if (!found) 589538032Speter { 589638032Speter *statp = EX_NOHOST; 589738032Speter return FALSE; 589838032Speter } 589938032Speter 590038032Speter if ((SIZE_T) hbsize >= strlen(cbuf)) 590138032Speter { 590264562Sgshapiro (void) strlcpy(name, cbuf, hbsize); 590338032Speter *statp = EX_OK; 590438032Speter return TRUE; 590538032Speter } 590638032Speter *statp = EX_UNAVAILABLE; 590738032Speter return FALSE; 590838032Speter} 590938032Speter/* 591038032Speter** STAB (Symbol Table) Modules 591138032Speter*/ 591238032Speter 591338032Speter 591438032Speter/* 591538032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 591638032Speter*/ 591738032Speter 591838032Speter/* ARGSUSED2 */ 591938032Speterchar * 592038032Speterstab_map_lookup(map, name, av, pstat) 592138032Speter register MAP *map; 592238032Speter char *name; 592338032Speter char **av; 592438032Speter int *pstat; 592538032Speter{ 592638032Speter register STAB *s; 592738032Speter 592838032Speter if (tTd(38, 20)) 592964562Sgshapiro dprintf("stab_lookup(%s, %s)\n", 593038032Speter map->map_mname, name); 593138032Speter 593238032Speter s = stab(name, ST_ALIAS, ST_FIND); 593338032Speter if (s != NULL) 593464562Sgshapiro return s->s_alias; 593564562Sgshapiro return NULL; 593638032Speter} 593738032Speter 593838032Speter 593938032Speter/* 594038032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 594138032Speter*/ 594238032Speter 594338032Spetervoid 594438032Speterstab_map_store(map, lhs, rhs) 594538032Speter register MAP *map; 594638032Speter char *lhs; 594738032Speter char *rhs; 594838032Speter{ 594938032Speter register STAB *s; 595038032Speter 595138032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 595238032Speter s->s_alias = newstr(rhs); 595338032Speter} 595438032Speter 595538032Speter 595638032Speter/* 595738032Speter** STAB_MAP_OPEN -- initialize (reads data file) 595838032Speter** 595938032Speter** This is a wierd case -- it is only intended as a fallback for 596038032Speter** aliases. For this reason, opens for write (only during a 596138032Speter** "newaliases") always fails, and opens for read open the 596238032Speter** actual underlying text file instead of the database. 596338032Speter*/ 596438032Speter 596538032Speterbool 596638032Speterstab_map_open(map, mode) 596738032Speter register MAP *map; 596838032Speter int mode; 596938032Speter{ 597038032Speter FILE *af; 597164562Sgshapiro long sff; 597238032Speter struct stat st; 597338032Speter 597438032Speter if (tTd(38, 2)) 597564562Sgshapiro dprintf("stab_map_open(%s, %s, %d)\n", 597638032Speter map->map_mname, map->map_file, mode); 597738032Speter 597838032Speter mode &= O_ACCMODE; 597938032Speter if (mode != O_RDONLY) 598038032Speter { 598138032Speter errno = EPERM; 598238032Speter return FALSE; 598338032Speter } 598438032Speter 598538032Speter sff = SFF_ROOTOK|SFF_REGONLY; 598664562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 598738032Speter sff |= SFF_NOWLINK; 598864562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 598938032Speter sff |= SFF_SAFEDIRPATH; 599038032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 599138032Speter if (af == NULL) 599238032Speter return FALSE; 599338032Speter readaliases(map, af, FALSE, FALSE); 599438032Speter 599538032Speter if (fstat(fileno(af), &st) >= 0) 599638032Speter map->map_mtime = st.st_mtime; 599764562Sgshapiro (void) fclose(af); 599838032Speter 599938032Speter return TRUE; 600038032Speter} 600138032Speter/* 600238032Speter** Implicit Modules 600338032Speter** 600438032Speter** Tries several types. For back compatibility of aliases. 600538032Speter*/ 600638032Speter 600738032Speter 600838032Speter/* 600938032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 601038032Speter*/ 601138032Speter 601238032Speterchar * 601338032Speterimpl_map_lookup(map, name, av, pstat) 601438032Speter MAP *map; 601538032Speter char *name; 601638032Speter char **av; 601738032Speter int *pstat; 601838032Speter{ 601938032Speter if (tTd(38, 20)) 602064562Sgshapiro dprintf("impl_map_lookup(%s, %s)\n", 602138032Speter map->map_mname, name); 602238032Speter 602338032Speter#ifdef NEWDB 602438032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 602538032Speter return db_map_lookup(map, name, av, pstat); 602664562Sgshapiro#endif /* NEWDB */ 602738032Speter#ifdef NDBM 602838032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 602938032Speter return ndbm_map_lookup(map, name, av, pstat); 603064562Sgshapiro#endif /* NDBM */ 603138032Speter return stab_map_lookup(map, name, av, pstat); 603238032Speter} 603338032Speter 603438032Speter/* 603538032Speter** IMPL_MAP_STORE -- store in open databases 603638032Speter*/ 603738032Speter 603838032Spetervoid 603938032Speterimpl_map_store(map, lhs, rhs) 604038032Speter MAP *map; 604138032Speter char *lhs; 604238032Speter char *rhs; 604338032Speter{ 604438032Speter if (tTd(38, 12)) 604564562Sgshapiro dprintf("impl_map_store(%s, %s, %s)\n", 604638032Speter map->map_mname, lhs, rhs); 604738032Speter#ifdef NEWDB 604838032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 604938032Speter db_map_store(map, lhs, rhs); 605064562Sgshapiro#endif /* NEWDB */ 605138032Speter#ifdef NDBM 605238032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 605338032Speter ndbm_map_store(map, lhs, rhs); 605464562Sgshapiro#endif /* NDBM */ 605538032Speter stab_map_store(map, lhs, rhs); 605638032Speter} 605738032Speter 605838032Speter/* 605938032Speter** IMPL_MAP_OPEN -- implicit database open 606038032Speter*/ 606138032Speter 606238032Speterbool 606338032Speterimpl_map_open(map, mode) 606438032Speter MAP *map; 606538032Speter int mode; 606638032Speter{ 606738032Speter if (tTd(38, 2)) 606864562Sgshapiro dprintf("impl_map_open(%s, %s, %d)\n", 606938032Speter map->map_mname, map->map_file, mode); 607038032Speter 607138032Speter mode &= O_ACCMODE; 607238032Speter#ifdef NEWDB 607338032Speter map->map_mflags |= MF_IMPL_HASH; 607438032Speter if (hash_map_open(map, mode)) 607538032Speter { 607638032Speter# ifdef NDBM_YP_COMPAT 607738032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 607864562Sgshapiro# endif /* NDBM_YP_COMPAT */ 607938032Speter return TRUE; 608038032Speter } 608138032Speter else 608238032Speter map->map_mflags &= ~MF_IMPL_HASH; 608364562Sgshapiro#endif /* NEWDB */ 608438032Speter#ifdef NDBM 608538032Speter map->map_mflags |= MF_IMPL_NDBM; 608638032Speter if (ndbm_map_open(map, mode)) 608738032Speter { 608838032Speter return TRUE; 608938032Speter } 609038032Speter else 609138032Speter map->map_mflags &= ~MF_IMPL_NDBM; 609264562Sgshapiro#endif /* NDBM */ 609338032Speter 609438032Speter#if defined(NEWDB) || defined(NDBM) 609538032Speter if (Verbose) 609638032Speter message("WARNING: cannot open alias database %s%s", 609738032Speter map->map_file, 609838032Speter mode == O_RDONLY ? "; reading text version" : ""); 609964562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 610038032Speter if (mode != O_RDONLY) 610138032Speter usrerr("Cannot rebuild aliases: no database format defined"); 610264562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 610338032Speter 610438032Speter if (mode == O_RDONLY) 610538032Speter return stab_map_open(map, mode); 610638032Speter else 610738032Speter return FALSE; 610838032Speter} 610938032Speter 611038032Speter 611138032Speter/* 611238032Speter** IMPL_MAP_CLOSE -- close any open database(s) 611338032Speter*/ 611438032Speter 611538032Spetervoid 611638032Speterimpl_map_close(map) 611738032Speter MAP *map; 611838032Speter{ 611938032Speter if (tTd(38, 9)) 612064562Sgshapiro dprintf("impl_map_close(%s, %s, %lx)\n", 612138032Speter map->map_mname, map->map_file, map->map_mflags); 612238032Speter#ifdef NEWDB 612338032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 612438032Speter { 612538032Speter db_map_close(map); 612638032Speter map->map_mflags &= ~MF_IMPL_HASH; 612738032Speter } 612864562Sgshapiro#endif /* NEWDB */ 612938032Speter 613038032Speter#ifdef NDBM 613138032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 613238032Speter { 613338032Speter ndbm_map_close(map); 613438032Speter map->map_mflags &= ~MF_IMPL_NDBM; 613538032Speter } 613664562Sgshapiro#endif /* NDBM */ 613738032Speter} 613838032Speter/* 613938032Speter** User map class. 614038032Speter** 614138032Speter** Provides access to the system password file. 614238032Speter*/ 614338032Speter 614438032Speter/* 614538032Speter** USER_MAP_OPEN -- open user map 614638032Speter** 614738032Speter** Really just binds field names to field numbers. 614838032Speter*/ 614938032Speter 615038032Speterbool 615138032Speteruser_map_open(map, mode) 615238032Speter MAP *map; 615338032Speter int mode; 615438032Speter{ 615538032Speter if (tTd(38, 2)) 615664562Sgshapiro dprintf("user_map_open(%s, %d)\n", 615738032Speter map->map_mname, mode); 615838032Speter 615938032Speter mode &= O_ACCMODE; 616038032Speter if (mode != O_RDONLY) 616138032Speter { 616238032Speter /* issue a pseudo-error message */ 616338032Speter#ifdef ENOSYS 616438032Speter errno = ENOSYS; 616564562Sgshapiro#else /* ENOSYS */ 616638032Speter# ifdef EFTYPE 616738032Speter errno = EFTYPE; 616864562Sgshapiro# else /* EFTYPE */ 616938032Speter errno = ENXIO; 617064562Sgshapiro# endif /* EFTYPE */ 617164562Sgshapiro#endif /* ENOSYS */ 617238032Speter return FALSE; 617338032Speter } 617438032Speter if (map->map_valcolnm == NULL) 617564562Sgshapiro /* EMPTY */ 617638032Speter /* nothing */ ; 617738032Speter else if (strcasecmp(map->map_valcolnm, "name") == 0) 617838032Speter map->map_valcolno = 1; 617938032Speter else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 618038032Speter map->map_valcolno = 2; 618138032Speter else if (strcasecmp(map->map_valcolnm, "uid") == 0) 618238032Speter map->map_valcolno = 3; 618338032Speter else if (strcasecmp(map->map_valcolnm, "gid") == 0) 618438032Speter map->map_valcolno = 4; 618538032Speter else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 618638032Speter map->map_valcolno = 5; 618738032Speter else if (strcasecmp(map->map_valcolnm, "dir") == 0) 618838032Speter map->map_valcolno = 6; 618938032Speter else if (strcasecmp(map->map_valcolnm, "shell") == 0) 619038032Speter map->map_valcolno = 7; 619138032Speter else 619238032Speter { 619338032Speter syserr("User map %s: unknown column name %s", 619438032Speter map->map_mname, map->map_valcolnm); 619538032Speter return FALSE; 619638032Speter } 619738032Speter return TRUE; 619838032Speter} 619938032Speter 620038032Speter 620138032Speter/* 620238032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 620338032Speter*/ 620438032Speter 620538032Speter/* ARGSUSED3 */ 620638032Speterchar * 620738032Speteruser_map_lookup(map, key, av, statp) 620838032Speter MAP *map; 620938032Speter char *key; 621038032Speter char **av; 621138032Speter int *statp; 621238032Speter{ 621338032Speter struct passwd *pw; 621438032Speter auto bool fuzzy; 621538032Speter 621638032Speter if (tTd(38, 20)) 621764562Sgshapiro dprintf("user_map_lookup(%s, %s)\n", 621838032Speter map->map_mname, key); 621938032Speter 622038032Speter pw = finduser(key, &fuzzy); 622138032Speter if (pw == NULL) 622238032Speter return NULL; 622338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 622438032Speter return map_rewrite(map, key, strlen(key), NULL); 622538032Speter else 622638032Speter { 622738032Speter char *rwval = NULL; 622838032Speter char buf[30]; 622938032Speter 623038032Speter switch (map->map_valcolno) 623138032Speter { 623238032Speter case 0: 623338032Speter case 1: 623438032Speter rwval = pw->pw_name; 623538032Speter break; 623638032Speter 623738032Speter case 2: 623838032Speter rwval = pw->pw_passwd; 623938032Speter break; 624038032Speter 624138032Speter case 3: 624264562Sgshapiro snprintf(buf, sizeof buf, "%d", (int) pw->pw_uid); 624338032Speter rwval = buf; 624438032Speter break; 624538032Speter 624638032Speter case 4: 624764562Sgshapiro snprintf(buf, sizeof buf, "%d", (int) pw->pw_gid); 624838032Speter rwval = buf; 624938032Speter break; 625038032Speter 625138032Speter case 5: 625238032Speter rwval = pw->pw_gecos; 625338032Speter break; 625438032Speter 625538032Speter case 6: 625638032Speter rwval = pw->pw_dir; 625738032Speter break; 625838032Speter 625938032Speter case 7: 626038032Speter rwval = pw->pw_shell; 626138032Speter break; 626238032Speter } 626338032Speter return map_rewrite(map, rwval, strlen(rwval), av); 626438032Speter } 626538032Speter} 626638032Speter/* 626738032Speter** Program map type. 626838032Speter** 626938032Speter** This provides access to arbitrary programs. It should be used 627038032Speter** only very sparingly, since there is no way to bound the cost 627138032Speter** of invoking an arbitrary program. 627238032Speter*/ 627338032Speter 627438032Speterchar * 627538032Speterprog_map_lookup(map, name, av, statp) 627638032Speter MAP *map; 627738032Speter char *name; 627838032Speter char **av; 627938032Speter int *statp; 628038032Speter{ 628138032Speter int i; 628264562Sgshapiro int save_errno; 628338032Speter int fd; 628464562Sgshapiro int status; 628538032Speter auto pid_t pid; 628664562Sgshapiro register char *p; 628738032Speter char *rval; 628838032Speter char *argv[MAXPV + 1]; 628938032Speter char buf[MAXLINE]; 629038032Speter 629138032Speter if (tTd(38, 20)) 629264562Sgshapiro dprintf("prog_map_lookup(%s, %s) %s\n", 629338032Speter map->map_mname, name, map->map_file); 629438032Speter 629538032Speter i = 0; 629638032Speter argv[i++] = map->map_file; 629738032Speter if (map->map_rebuild != NULL) 629838032Speter { 629938032Speter snprintf(buf, sizeof buf, "%s", map->map_rebuild); 630038032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 630138032Speter { 630238032Speter if (i >= MAXPV - 1) 630338032Speter break; 630438032Speter argv[i++] = p; 630538032Speter } 630638032Speter } 630738032Speter argv[i++] = name; 630838032Speter argv[i] = NULL; 630938032Speter if (tTd(38, 21)) 631038032Speter { 631164562Sgshapiro dprintf("prog_open:"); 631238032Speter for (i = 0; argv[i] != NULL; i++) 631364562Sgshapiro dprintf(" %s", argv[i]); 631464562Sgshapiro dprintf("\n"); 631538032Speter } 631638032Speter (void) blocksignal(SIGCHLD); 631738032Speter pid = prog_open(argv, &fd, CurEnv); 631838032Speter if (pid < 0) 631938032Speter { 632038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 632138032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 632238032Speter map->map_mname, errstring(errno)); 632338032Speter else if (tTd(38, 9)) 632464562Sgshapiro dprintf("prog_map_lookup(%s) failed (%s) -- closing", 632538032Speter map->map_mname, errstring(errno)); 632638032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 632738032Speter *statp = EX_OSFILE; 632838032Speter return NULL; 632938032Speter } 633038032Speter i = read(fd, buf, sizeof buf - 1); 633138032Speter if (i < 0) 633238032Speter { 633338032Speter syserr("prog_map_lookup(%s): read error %s\n", 633438032Speter map->map_mname, errstring(errno)); 633538032Speter rval = NULL; 633638032Speter } 633738032Speter else if (i == 0) 633838032Speter { 633938032Speter if (tTd(38, 20)) 634064562Sgshapiro dprintf("prog_map_lookup(%s): empty answer\n", 634138032Speter map->map_mname); 634238032Speter rval = NULL; 634338032Speter } 634438032Speter else 634538032Speter { 634638032Speter buf[i] = '\0'; 634738032Speter p = strchr(buf, '\n'); 634838032Speter if (p != NULL) 634938032Speter *p = '\0'; 635038032Speter 635138032Speter /* collect the return value */ 635238032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 635338032Speter rval = map_rewrite(map, name, strlen(name), NULL); 635438032Speter else 635538032Speter rval = map_rewrite(map, buf, strlen(buf), NULL); 635638032Speter 635738032Speter /* now flush any additional output */ 635838032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 635938032Speter continue; 636038032Speter } 636138032Speter 636238032Speter /* wait for the process to terminate */ 636364562Sgshapiro (void) close(fd); 636464562Sgshapiro status = waitfor(pid); 636564562Sgshapiro save_errno = errno; 636638032Speter (void) releasesignal(SIGCHLD); 636764562Sgshapiro errno = save_errno; 636838032Speter 636964562Sgshapiro if (status == -1) 637038032Speter { 637138032Speter syserr("prog_map_lookup(%s): wait error %s\n", 637238032Speter map->map_mname, errstring(errno)); 637338032Speter *statp = EX_SOFTWARE; 637438032Speter rval = NULL; 637538032Speter } 637664562Sgshapiro else if (WIFEXITED(status)) 637738032Speter { 637864562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 637938032Speter rval = NULL; 638038032Speter } 638138032Speter else 638238032Speter { 638338032Speter syserr("prog_map_lookup(%s): child died on signal %d", 638464562Sgshapiro map->map_mname, status); 638538032Speter *statp = EX_UNAVAILABLE; 638638032Speter rval = NULL; 638738032Speter } 638838032Speter return rval; 638938032Speter} 639038032Speter/* 639138032Speter** Sequenced map type. 639238032Speter** 639338032Speter** Tries each map in order until something matches, much like 639438032Speter** implicit. Stores go to the first map in the list that can 639538032Speter** support storing. 639638032Speter** 639738032Speter** This is slightly unusual in that there are two interfaces. 639838032Speter** The "sequence" interface lets you stack maps arbitrarily. 639938032Speter** The "switch" interface builds a sequence map by looking 640038032Speter** at a system-dependent configuration file such as 640138032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 640238032Speter** 640338032Speter** We don't need an explicit open, since all maps are 640438032Speter** opened during startup, including underlying maps. 640538032Speter*/ 640638032Speter 640738032Speter/* 640838032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 640938032Speter*/ 641038032Speter 641138032Speterbool 641238032Speterseq_map_parse(map, ap) 641338032Speter MAP *map; 641438032Speter char *ap; 641538032Speter{ 641638032Speter int maxmap; 641738032Speter 641838032Speter if (tTd(38, 2)) 641964562Sgshapiro dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 642038032Speter maxmap = 0; 642138032Speter while (*ap != '\0') 642238032Speter { 642338032Speter register char *p; 642438032Speter STAB *s; 642538032Speter 642638032Speter /* find beginning of map name */ 642738032Speter while (isascii(*ap) && isspace(*ap)) 642838032Speter ap++; 642964562Sgshapiro for (p = ap; 643064562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 643164562Sgshapiro p++) 643238032Speter continue; 643338032Speter if (*p != '\0') 643438032Speter *p++ = '\0'; 643538032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 643638032Speter p++; 643738032Speter if (*ap == '\0') 643838032Speter { 643938032Speter ap = p; 644038032Speter continue; 644138032Speter } 644238032Speter s = stab(ap, ST_MAP, ST_FIND); 644338032Speter if (s == NULL) 644438032Speter { 644538032Speter syserr("Sequence map %s: unknown member map %s", 644638032Speter map->map_mname, ap); 644738032Speter } 644838032Speter else if (maxmap == MAXMAPSTACK) 644938032Speter { 645038032Speter syserr("Sequence map %s: too many member maps (%d max)", 645138032Speter map->map_mname, MAXMAPSTACK); 645238032Speter maxmap++; 645338032Speter } 645438032Speter else if (maxmap < MAXMAPSTACK) 645538032Speter { 645638032Speter map->map_stack[maxmap++] = &s->s_map; 645738032Speter } 645838032Speter ap = p; 645938032Speter } 646038032Speter return TRUE; 646138032Speter} 646238032Speter 646338032Speter 646438032Speter/* 646538032Speter** SWITCH_MAP_OPEN -- open a switched map 646638032Speter** 646738032Speter** This looks at the system-dependent configuration and builds 646838032Speter** a sequence map that does the same thing. 646938032Speter** 647038032Speter** Every system must define a switch_map_find routine in conf.c 647138032Speter** that will return the list of service types associated with a 647238032Speter** given service class. 647338032Speter*/ 647438032Speter 647538032Speterbool 647638032Speterswitch_map_open(map, mode) 647738032Speter MAP *map; 647838032Speter int mode; 647938032Speter{ 648038032Speter int mapno; 648138032Speter int nmaps; 648238032Speter char *maptype[MAXMAPSTACK]; 648338032Speter 648438032Speter if (tTd(38, 2)) 648564562Sgshapiro dprintf("switch_map_open(%s, %s, %d)\n", 648638032Speter map->map_mname, map->map_file, mode); 648738032Speter 648838032Speter mode &= O_ACCMODE; 648938032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 649038032Speter if (tTd(38, 19)) 649138032Speter { 649264562Sgshapiro dprintf("\tswitch_map_find => %d\n", nmaps); 649338032Speter for (mapno = 0; mapno < nmaps; mapno++) 649464562Sgshapiro dprintf("\t\t%s\n", maptype[mapno]); 649538032Speter } 649638032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 649738032Speter return FALSE; 649838032Speter 649938032Speter for (mapno = 0; mapno < nmaps; mapno++) 650038032Speter { 650138032Speter register STAB *s; 650238032Speter char nbuf[MAXNAME + 1]; 650338032Speter 650438032Speter if (maptype[mapno] == NULL) 650538032Speter continue; 650638032Speter (void) snprintf(nbuf, sizeof nbuf, "%s.%s", 650738032Speter map->map_mname, maptype[mapno]); 650838032Speter s = stab(nbuf, ST_MAP, ST_FIND); 650938032Speter if (s == NULL) 651038032Speter { 651138032Speter syserr("Switch map %s: unknown member map %s", 651238032Speter map->map_mname, nbuf); 651338032Speter } 651438032Speter else 651538032Speter { 651638032Speter map->map_stack[mapno] = &s->s_map; 651738032Speter if (tTd(38, 4)) 651864562Sgshapiro dprintf("\tmap_stack[%d] = %s:%s\n", 651938032Speter mapno, s->s_map.map_class->map_cname, 652038032Speter nbuf); 652138032Speter } 652238032Speter } 652338032Speter return TRUE; 652438032Speter} 652538032Speter 652638032Speter 652738032Speter/* 652838032Speter** SEQ_MAP_CLOSE -- close all underlying maps 652938032Speter*/ 653038032Speter 653138032Spetervoid 653238032Speterseq_map_close(map) 653338032Speter MAP *map; 653438032Speter{ 653538032Speter int mapno; 653638032Speter 653738032Speter if (tTd(38, 9)) 653864562Sgshapiro dprintf("seq_map_close(%s)\n", map->map_mname); 653938032Speter 654038032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 654138032Speter { 654238032Speter MAP *mm = map->map_stack[mapno]; 654338032Speter 654438032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 654538032Speter continue; 654638032Speter mm->map_class->map_close(mm); 654738032Speter mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 654838032Speter } 654938032Speter} 655038032Speter 655138032Speter 655238032Speter/* 655338032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 655438032Speter*/ 655538032Speter 655638032Speterchar * 655738032Speterseq_map_lookup(map, key, args, pstat) 655838032Speter MAP *map; 655938032Speter char *key; 656038032Speter char **args; 656138032Speter int *pstat; 656238032Speter{ 656338032Speter int mapno; 656438032Speter int mapbit = 0x01; 656538032Speter bool tempfail = FALSE; 656638032Speter 656738032Speter if (tTd(38, 20)) 656864562Sgshapiro dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 656938032Speter 657038032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 657138032Speter { 657238032Speter MAP *mm = map->map_stack[mapno]; 657338032Speter char *rv; 657438032Speter 657538032Speter if (mm == NULL) 657638032Speter continue; 657764562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 657864562Sgshapiro !openmap(mm)) 657938032Speter { 658038032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 658138032Speter { 658238032Speter *pstat = EX_UNAVAILABLE; 658338032Speter return NULL; 658438032Speter } 658538032Speter continue; 658638032Speter } 658738032Speter *pstat = EX_OK; 658838032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 658938032Speter if (rv != NULL) 659038032Speter return rv; 659138032Speter if (*pstat == EX_TEMPFAIL) 659238032Speter { 659338032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 659438032Speter return NULL; 659538032Speter tempfail = TRUE; 659638032Speter } 659738032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 659838032Speter break; 659938032Speter } 660038032Speter if (tempfail) 660138032Speter *pstat = EX_TEMPFAIL; 660238032Speter else if (*pstat == EX_OK) 660338032Speter *pstat = EX_NOTFOUND; 660438032Speter return NULL; 660538032Speter} 660638032Speter 660738032Speter 660838032Speter/* 660938032Speter** SEQ_MAP_STORE -- sequenced map store 661038032Speter*/ 661138032Speter 661238032Spetervoid 661338032Speterseq_map_store(map, key, val) 661438032Speter MAP *map; 661538032Speter char *key; 661638032Speter char *val; 661738032Speter{ 661838032Speter int mapno; 661938032Speter 662038032Speter if (tTd(38, 12)) 662164562Sgshapiro dprintf("seq_map_store(%s, %s, %s)\n", 662238032Speter map->map_mname, key, val); 662338032Speter 662438032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 662538032Speter { 662638032Speter MAP *mm = map->map_stack[mapno]; 662738032Speter 662838032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 662938032Speter continue; 663038032Speter 663138032Speter mm->map_class->map_store(mm, key, val); 663238032Speter return; 663338032Speter } 663438032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 663538032Speter map->map_mname, key, val); 663638032Speter} 663738032Speter/* 663838032Speter** NULL stubs 663938032Speter*/ 664038032Speter 664138032Speter/* ARGSUSED */ 664238032Speterbool 664338032Speternull_map_open(map, mode) 664438032Speter MAP *map; 664538032Speter int mode; 664638032Speter{ 664738032Speter return TRUE; 664838032Speter} 664938032Speter 665038032Speter/* ARGSUSED */ 665138032Spetervoid 665238032Speternull_map_close(map) 665338032Speter MAP *map; 665438032Speter{ 665538032Speter return; 665638032Speter} 665738032Speter 665838032Speterchar * 665938032Speternull_map_lookup(map, key, args, pstat) 666038032Speter MAP *map; 666138032Speter char *key; 666238032Speter char **args; 666338032Speter int *pstat; 666438032Speter{ 666538032Speter *pstat = EX_NOTFOUND; 666638032Speter return NULL; 666738032Speter} 666838032Speter 666938032Speter/* ARGSUSED */ 667038032Spetervoid 667138032Speternull_map_store(map, key, val) 667238032Speter MAP *map; 667338032Speter char *key; 667438032Speter char *val; 667538032Speter{ 667638032Speter return; 667738032Speter} 667838032Speter 667938032Speter 668038032Speter/* 668138032Speter** BOGUS stubs 668238032Speter*/ 668338032Speter 668438032Speterchar * 668538032Speterbogus_map_lookup(map, key, args, pstat) 668638032Speter MAP *map; 668738032Speter char *key; 668838032Speter char **args; 668938032Speter int *pstat; 669038032Speter{ 669138032Speter *pstat = EX_TEMPFAIL; 669238032Speter return NULL; 669338032Speter} 669438032Speter 669538032SpeterMAPCLASS BogusMapClass = 669638032Speter{ 669738032Speter "bogus-map", NULL, 0, 669838032Speter NULL, bogus_map_lookup, null_map_store, 669938032Speter null_map_open, null_map_close, 670038032Speter}; 670138032Speter/* 670264562Sgshapiro** MACRO modules 670364562Sgshapiro*/ 670464562Sgshapiro 670564562Sgshapirochar * 670664562Sgshapiromacro_map_lookup(map, name, av, statp) 670764562Sgshapiro MAP *map; 670864562Sgshapiro char *name; 670964562Sgshapiro char **av; 671064562Sgshapiro int *statp; 671164562Sgshapiro{ 671264562Sgshapiro int mid; 671364562Sgshapiro 671464562Sgshapiro if (tTd(38, 20)) 671564562Sgshapiro dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 671664562Sgshapiro name == NULL ? "NULL" : name); 671764562Sgshapiro 671864562Sgshapiro if (name == NULL || 671964562Sgshapiro *name == '\0' || 672064562Sgshapiro (mid = macid(name, NULL)) == '\0') 672164562Sgshapiro { 672264562Sgshapiro *statp = EX_CONFIG; 672364562Sgshapiro return NULL; 672464562Sgshapiro } 672564562Sgshapiro 672664562Sgshapiro if (av[1] == NULL) 672764562Sgshapiro define(mid, NULL, CurEnv); 672864562Sgshapiro else 672964562Sgshapiro define(mid, newstr(av[1]), CurEnv); 673064562Sgshapiro 673164562Sgshapiro *statp = EX_OK; 673264562Sgshapiro return ""; 673364562Sgshapiro} 673464562Sgshapiro/* 673538032Speter** REGEX modules 673638032Speter*/ 673738032Speter 673838032Speter#ifdef MAP_REGEX 673938032Speter 674038032Speter# include <regex.h> 674138032Speter 674238032Speter# define DEFAULT_DELIM CONDELSE 674338032Speter 674438032Speter# define END_OF_FIELDS -1 674538032Speter 674638032Speter# define ERRBUF_SIZE 80 674738032Speter# define MAX_MATCH 32 674838032Speter 674964562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 675038032Speter 675138032Speterstruct regex_map 675238032Speter{ 675371345Sgshapiro regex_t *regex_pattern_buf; /* xalloc it */ 675438032Speter int *regex_subfields; /* move to type MAP */ 675564562Sgshapiro char *regex_delim; /* move to type MAP */ 675638032Speter}; 675738032Speter 675838032Speterstatic int 675938032Speterparse_fields(s, ibuf, blen, nr_substrings) 676038032Speter char *s; 676138032Speter int *ibuf; /* array */ 676238032Speter int blen; /* number of elements in ibuf */ 676338032Speter int nr_substrings; /* number of substrings in the pattern */ 676438032Speter{ 676538032Speter register char *cp; 676638032Speter int i = 0; 676738032Speter bool lastone = FALSE; 676838032Speter 676938032Speter blen--; /* for terminating END_OF_FIELDS */ 677038032Speter cp = s; 677138032Speter do 677238032Speter { 677338032Speter for (;; cp++) 677438032Speter { 677538032Speter if (*cp == ',') 677638032Speter { 677738032Speter *cp = '\0'; 677838032Speter break; 677938032Speter } 678038032Speter if (*cp == '\0') 678138032Speter { 678238032Speter lastone = TRUE; 678338032Speter break; 678438032Speter } 678538032Speter } 678638032Speter if (i < blen) 678738032Speter { 678838032Speter int val = atoi(s); 678938032Speter 679038032Speter if (val < 0 || val >= nr_substrings) 679138032Speter { 679238032Speter syserr("field (%d) out of range, only %d substrings in pattern", 679338032Speter val, nr_substrings); 679438032Speter return -1; 679538032Speter } 679638032Speter ibuf[i++] = val; 679738032Speter } 679838032Speter else 679938032Speter { 680038032Speter syserr("too many fields, %d max\n", blen); 680138032Speter return -1; 680238032Speter } 680338032Speter s = ++cp; 680438032Speter } while (!lastone); 680538032Speter ibuf[i] = END_OF_FIELDS; 680638032Speter return i; 680738032Speter} 680838032Speter 680938032Speterbool 681038032Speterregex_map_init(map, ap) 681138032Speter MAP *map; 681238032Speter char *ap; 681338032Speter{ 681438032Speter int regerr; 681538032Speter struct regex_map *map_p; 681638032Speter register char *p; 681738032Speter char *sub_param = NULL; 681838032Speter int pflags; 681938032Speter static char defdstr[] = { (char)DEFAULT_DELIM, '\0' }; 682038032Speter 682138032Speter if (tTd(38, 2)) 682264562Sgshapiro dprintf("regex_map_init: mapname '%s', args '%s'\n", 682364562Sgshapiro map->map_mname, ap); 682438032Speter 682538032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 682638032Speter 682738032Speter p = ap; 682838032Speter 682964562Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof *map_p); 683071345Sgshapiro map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 683138032Speter 683238032Speter for (;;) 683364562Sgshapiro { 683438032Speter while (isascii(*p) && isspace(*p)) 683538032Speter p++; 683638032Speter if (*p != '-') 683738032Speter break; 683838032Speter switch (*++p) 683938032Speter { 684038032Speter case 'n': /* not */ 684138032Speter map->map_mflags |= MF_REGEX_NOT; 684238032Speter break; 684338032Speter 684438032Speter case 'f': /* case sensitive */ 684538032Speter map->map_mflags |= MF_NOFOLDCASE; 684638032Speter pflags &= ~REG_ICASE; 684738032Speter break; 684838032Speter 684938032Speter case 'b': /* basic regular expressions */ 685038032Speter pflags &= ~REG_EXTENDED; 685138032Speter break; 685238032Speter 685338032Speter case 's': /* substring match () syntax */ 685438032Speter sub_param = ++p; 685538032Speter pflags &= ~REG_NOSUB; 685638032Speter break; 685738032Speter 685838032Speter case 'd': /* delimiter */ 685964562Sgshapiro map_p->regex_delim = ++p; 686038032Speter break; 686138032Speter 686238032Speter case 'a': /* map append */ 686338032Speter map->map_app = ++p; 686438032Speter break; 686538032Speter 686638032Speter case 'm': /* matchonly */ 686738032Speter map->map_mflags |= MF_MATCHONLY; 686838032Speter break; 686938032Speter 687064562Sgshapiro case 'S': 687164562Sgshapiro map->map_spacesub = *++p; 687264562Sgshapiro break; 687364562Sgshapiro 687464562Sgshapiro case 'D': 687564562Sgshapiro map->map_mflags |= MF_DEFER; 687664562Sgshapiro break; 687764562Sgshapiro 687838032Speter } 687964562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 688064562Sgshapiro p++; 688164562Sgshapiro if (*p != '\0') 688264562Sgshapiro *p++ = '\0'; 688338032Speter } 688438032Speter if (tTd(38, 3)) 688564562Sgshapiro dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 688638032Speter 688771345Sgshapiro if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 688838032Speter { 688938032Speter /* Errorhandling */ 689038032Speter char errbuf[ERRBUF_SIZE]; 689138032Speter 689271345Sgshapiro (void) regerror(regerr, map_p->regex_pattern_buf, 689364562Sgshapiro errbuf, ERRBUF_SIZE); 689438032Speter syserr("pattern-compile-error: %s\n", errbuf); 689571345Sgshapiro free(map_p->regex_pattern_buf); 689638032Speter free(map_p); 689738032Speter return FALSE; 689838032Speter } 689938032Speter 690038032Speter if (map->map_app != NULL) 690138032Speter map->map_app = newstr(map->map_app); 690264562Sgshapiro if (map_p->regex_delim != NULL) 690364562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 690438032Speter else 690564562Sgshapiro map_p->regex_delim = defdstr; 690638032Speter 690738032Speter if (!bitset(REG_NOSUB, pflags)) 690838032Speter { 690938032Speter /* substring matching */ 691038032Speter int substrings; 691164562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 691238032Speter 691371345Sgshapiro substrings = map_p->regex_pattern_buf->re_nsub + 1; 691438032Speter 691538032Speter if (tTd(38, 3)) 691664562Sgshapiro dprintf("regex_map_init: nr of substrings %d\n", 691764562Sgshapiro substrings); 691838032Speter 691938032Speter if (substrings >= MAX_MATCH) 692038032Speter { 692138032Speter syserr("too many substrings, %d max\n", MAX_MATCH); 692271345Sgshapiro free(map_p->regex_pattern_buf); 692338032Speter free(map_p); 692438032Speter return FALSE; 692538032Speter } 692638032Speter if (sub_param != NULL && sub_param[0] != '\0') 692738032Speter { 692838032Speter /* optional parameter -sfields */ 692938032Speter if (parse_fields(sub_param, fields, 693038032Speter MAX_MATCH + 1, substrings) == -1) 693138032Speter return FALSE; 693238032Speter } 693338032Speter else 693438032Speter { 693564562Sgshapiro /* set default fields */ 693638032Speter int i; 693738032Speter 693838032Speter for (i = 0; i < substrings; i++) 693938032Speter fields[i] = i; 694038032Speter fields[i] = END_OF_FIELDS; 694138032Speter } 694238032Speter map_p->regex_subfields = fields; 694338032Speter if (tTd(38, 3)) 694438032Speter { 694538032Speter int *ip; 694638032Speter 694764562Sgshapiro dprintf("regex_map_init: subfields"); 694838032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 694964562Sgshapiro dprintf(" %d", *ip); 695064562Sgshapiro dprintf("\n"); 695138032Speter } 695238032Speter } 695338032Speter map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */ 695438032Speter 695538032Speter return TRUE; 695638032Speter} 695738032Speter 695838032Speterstatic char * 695938032Speterregex_map_rewrite(map, s, slen, av) 696038032Speter MAP *map; 696138032Speter const char *s; 696238032Speter size_t slen; 696338032Speter char **av; 696438032Speter{ 696538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 696638032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 696738032Speter else 696838032Speter return map_rewrite(map, s, slen, NULL); 696938032Speter} 697038032Speter 697138032Speterchar * 697238032Speterregex_map_lookup(map, name, av, statp) 697338032Speter MAP *map; 697438032Speter char *name; 697538032Speter char **av; 697638032Speter int *statp; 697738032Speter{ 697838032Speter int reg_res; 697938032Speter struct regex_map *map_p; 698038032Speter regmatch_t pmatch[MAX_MATCH]; 698138032Speter 698238032Speter if (tTd(38, 20)) 698338032Speter { 698438032Speter char **cpp; 698538032Speter 698664562Sgshapiro dprintf("regex_map_lookup: key '%s'\n", name); 698764562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 698864562Sgshapiro dprintf("regex_map_lookup: arg '%s'\n", *cpp); 698938032Speter } 699038032Speter 699138032Speter map_p = (struct regex_map *)(map->map_db1); 699271345Sgshapiro reg_res = regexec(map_p->regex_pattern_buf, 699364562Sgshapiro name, MAX_MATCH, pmatch, 0); 699438032Speter 699538032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 699638032Speter { 699738032Speter /* option -n */ 699838032Speter if (reg_res == REG_NOMATCH) 699938032Speter return regex_map_rewrite(map, "", (size_t)0, av); 700038032Speter else 700138032Speter return NULL; 700238032Speter } 700338032Speter if (reg_res == REG_NOMATCH) 700438032Speter return NULL; 700538032Speter 700638032Speter if (map_p->regex_subfields != NULL) 700738032Speter { 700838032Speter /* option -s */ 700938032Speter static char retbuf[MAXNAME]; 701038032Speter int fields[MAX_MATCH + 1]; 701138032Speter bool first = TRUE; 701238032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 701338032Speter bool quotemode = FALSE, bslashmode = FALSE; 701438032Speter register char *dp, *sp; 701538032Speter char *endp, *ldp; 701638032Speter int *ip; 701738032Speter 701838032Speter dp = retbuf; 701938032Speter ldp = retbuf + sizeof(retbuf) - 1; 702038032Speter 702138032Speter if (av[1] != NULL) 702238032Speter { 702338032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 702471345Sgshapiro (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 702538032Speter { 702638032Speter *statp = EX_CONFIG; 702738032Speter return NULL; 702838032Speter } 702938032Speter ip = fields; 703038032Speter } 703138032Speter else 703238032Speter ip = map_p->regex_subfields; 703338032Speter 703438032Speter for ( ; *ip != END_OF_FIELDS; ip++) 703538032Speter { 703638032Speter if (!first) 703738032Speter { 703864562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 703938032Speter { 704038032Speter if (dp < ldp) 704138032Speter *dp++ = *sp; 704238032Speter } 704338032Speter } 704438032Speter else 704538032Speter first = FALSE; 704638032Speter 704738032Speter 704871345Sgshapiro if (*ip >= MAX_MATCH || 704971345Sgshapiro pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 705038032Speter continue; 705138032Speter 705238032Speter sp = name + pmatch[*ip].rm_so; 705338032Speter endp = name + pmatch[*ip].rm_eo; 705438032Speter for (; endp > sp; sp++) 705538032Speter { 705638032Speter if (dp < ldp) 705738032Speter { 705864562Sgshapiro if (bslashmode) 705964562Sgshapiro { 706038032Speter *dp++ = *sp; 706138032Speter bslashmode = FALSE; 706238032Speter } 706364562Sgshapiro else if (quotemode && *sp != '"' && 706438032Speter *sp != '\\') 706538032Speter { 706638032Speter *dp++ = *sp; 706738032Speter } 706838032Speter else switch(*dp++ = *sp) 706938032Speter { 707038032Speter case '\\': 707138032Speter bslashmode = TRUE; 707238032Speter break; 707338032Speter 707438032Speter case '(': 707538032Speter cmntcnt++; 707638032Speter break; 707738032Speter 707838032Speter case ')': 707938032Speter cmntcnt--; 708038032Speter break; 708138032Speter 708238032Speter case '<': 708338032Speter anglecnt++; 708438032Speter break; 708538032Speter 708638032Speter case '>': 708738032Speter anglecnt--; 708838032Speter break; 708938032Speter 709038032Speter case ' ': 709138032Speter spacecnt++; 709238032Speter break; 709338032Speter 709438032Speter case '"': 709538032Speter quotemode = !quotemode; 709638032Speter break; 709738032Speter } 709838032Speter } 709938032Speter } 710038032Speter } 710138032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 710238032Speter bslashmode || spacecnt != 0) 710338032Speter { 710464562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 710564562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 710664562Sgshapiro map->map_mname, name); 710738032Speter return NULL; 710838032Speter } 710938032Speter 711038032Speter *dp = '\0'; 711138032Speter 711238032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 711338032Speter } 711438032Speter return regex_map_rewrite(map, "", (size_t)0, av); 711538032Speter} 711638032Speter#endif /* MAP_REGEX */ 711764562Sgshapiro/* 711864562Sgshapiro** NSD modules 711964562Sgshapiro*/ 712064562Sgshapiro#ifdef MAP_NSD 712164562Sgshapiro 712264562Sgshapiro# include <ndbm.h> 712364562Sgshapiro# define _DATUM_DEFINED 712464562Sgshapiro# include <ns_api.h> 712564562Sgshapiro 712664562Sgshapirotypedef struct ns_map_list 712764562Sgshapiro{ 712864562Sgshapiro ns_map_t *map; 712964562Sgshapiro char *mapname; 713064562Sgshapiro struct ns_map_list *next; 713164562Sgshapiro} ns_map_list_t; 713264562Sgshapiro 713364562Sgshapirostatic ns_map_t * 713464562Sgshapirons_map_t_find(mapname) 713564562Sgshapiro char *mapname; 713664562Sgshapiro{ 713764562Sgshapiro static ns_map_list_t *ns_maps = NULL; 713864562Sgshapiro ns_map_list_t *ns_map; 713964562Sgshapiro 714064562Sgshapiro /* walk the list of maps looking for the correctly named map */ 714164562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 714264562Sgshapiro { 714364562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 714464562Sgshapiro break; 714564562Sgshapiro } 714664562Sgshapiro 714764562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 714864562Sgshapiro if (ns_map == NULL) 714964562Sgshapiro { 715064562Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 715164562Sgshapiro ns_map->mapname = newstr(mapname); 715264562Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 715364562Sgshapiro ns_map->next = ns_maps; 715464562Sgshapiro ns_maps = ns_map; 715564562Sgshapiro } 715664562Sgshapiro return ns_map->map; 715764562Sgshapiro} 715864562Sgshapiro 715964562Sgshapirochar * 716064562Sgshapironsd_map_lookup(map, name, av, statp) 716164562Sgshapiro MAP *map; 716264562Sgshapiro char *name; 716364562Sgshapiro char **av; 716464562Sgshapiro int *statp; 716564562Sgshapiro{ 716671345Sgshapiro int buflen, r; 716764562Sgshapiro char *p; 716864562Sgshapiro ns_map_t *ns_map; 716964562Sgshapiro char keybuf[MAXNAME + 1]; 717064562Sgshapiro char buf[MAXLINE]; 717164562Sgshapiro 717264562Sgshapiro if (tTd(38, 20)) 717364562Sgshapiro dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 717464562Sgshapiro 717564562Sgshapiro buflen = strlen(name); 717664562Sgshapiro if (buflen > sizeof keybuf - 1) 717764562Sgshapiro buflen = sizeof keybuf - 1; 717864562Sgshapiro memmove(keybuf, name, buflen); 717964562Sgshapiro keybuf[buflen] = '\0'; 718064562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 718164562Sgshapiro makelower(keybuf); 718264562Sgshapiro 718364562Sgshapiro ns_map = ns_map_t_find(map->map_file); 718464562Sgshapiro if (ns_map == NULL) 718564562Sgshapiro { 718664562Sgshapiro if (tTd(38, 20)) 718764562Sgshapiro dprintf("nsd_map_t_find failed\n"); 718871345Sgshapiro *statp = EX_UNAVAILABLE; 718964562Sgshapiro return NULL; 719064562Sgshapiro } 719171345Sgshapiro r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, buf, MAXLINE); 719271345Sgshapiro if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 719371345Sgshapiro { 719471345Sgshapiro *statp = EX_TEMPFAIL; 719564562Sgshapiro return NULL; 719671345Sgshapiro } 719771345Sgshapiro if (r == NS_BADREQ || r == NS_NOPERM) 719871345Sgshapiro { 719971345Sgshapiro *statp = EX_CONFIG; 720071345Sgshapiro return NULL; 720171345Sgshapiro } 720271345Sgshapiro if (r != NS_SUCCESS) 720371345Sgshapiro { 720471345Sgshapiro *statp = EX_NOTFOUND; 720571345Sgshapiro return NULL; 720671345Sgshapiro } 720764562Sgshapiro 720871345Sgshapiro *statp = EX_OK; 720971345Sgshapiro 721064562Sgshapiro /* Null out trailing \n */ 721164562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 721264562Sgshapiro *p = '\0'; 721364562Sgshapiro 721464562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 721564562Sgshapiro} 721664562Sgshapiro#endif /* MAP_NSD */ 721764562Sgshapiro 721864562Sgshapirochar * 721964562Sgshapiroarith_map_lookup(map, name, av, statp) 722064562Sgshapiro MAP *map; 722164562Sgshapiro char *name; 722264562Sgshapiro char **av; 722364562Sgshapiro int *statp; 722464562Sgshapiro{ 722564562Sgshapiro long r; 722664562Sgshapiro long v[2]; 722764562Sgshapiro bool res = FALSE; 722864562Sgshapiro bool boolres; 722964562Sgshapiro static char result[16]; 723064562Sgshapiro char **cpp; 723164562Sgshapiro 723264562Sgshapiro if (tTd(38, 2)) 723364562Sgshapiro { 723464562Sgshapiro dprintf("arith_map_lookup: key '%s'\n", name); 723564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 723664562Sgshapiro dprintf("arith_map_lookup: arg '%s'\n", *cpp); 723764562Sgshapiro } 723864562Sgshapiro r = 0; 723964562Sgshapiro boolres = FALSE; 724064562Sgshapiro cpp = av; 724164562Sgshapiro *statp = EX_OK; 724264562Sgshapiro 724364562Sgshapiro /* 724464562Sgshapiro ** read arguments for arith map 724564562Sgshapiro ** - no check is made whether they are really numbers 724664562Sgshapiro ** - just ignores args after the second 724764562Sgshapiro */ 724864562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 724964562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 725064562Sgshapiro 725164562Sgshapiro /* operator and (at least) two operands given? */ 725264562Sgshapiro if (name != NULL && r == 2) 725364562Sgshapiro { 725464562Sgshapiro switch(*name) 725564562Sgshapiro { 725664562Sgshapiro#if _FFR_ARITH 725764562Sgshapiro case '|': 725864562Sgshapiro r = v[0] | v[1]; 725964562Sgshapiro break; 726064562Sgshapiro 726164562Sgshapiro case '&': 726264562Sgshapiro r = v[0] & v[1]; 726364562Sgshapiro break; 726464562Sgshapiro 726564562Sgshapiro case '%': 726664562Sgshapiro if (v[1] == 0) 726764562Sgshapiro return NULL; 726864562Sgshapiro r = v[0] % v[1]; 726964562Sgshapiro break; 727064562Sgshapiro#endif /* _FFR_ARITH */ 727164562Sgshapiro 727264562Sgshapiro case '+': 727364562Sgshapiro r = v[0] + v[1]; 727464562Sgshapiro break; 727564562Sgshapiro 727664562Sgshapiro case '-': 727764562Sgshapiro r = v[0] - v[1]; 727864562Sgshapiro break; 727964562Sgshapiro 728064562Sgshapiro case '*': 728164562Sgshapiro r = v[0] * v[1]; 728264562Sgshapiro break; 728364562Sgshapiro 728464562Sgshapiro case '/': 728564562Sgshapiro if (v[1] == 0) 728664562Sgshapiro return NULL; 728764562Sgshapiro r = v[0] / v[1]; 728864562Sgshapiro break; 728964562Sgshapiro 729064562Sgshapiro case 'l': 729164562Sgshapiro res = v[0] < v[1]; 729264562Sgshapiro boolres = TRUE; 729364562Sgshapiro break; 729464562Sgshapiro 729564562Sgshapiro case '=': 729664562Sgshapiro res = v[0] == v[1]; 729764562Sgshapiro boolres = TRUE; 729864562Sgshapiro break; 729964562Sgshapiro 730064562Sgshapiro default: 730164562Sgshapiro /* XXX */ 730264562Sgshapiro *statp = EX_CONFIG; 730364562Sgshapiro if (LogLevel > 10) 730464562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 730564562Sgshapiro "arith_map: unknown operator %c", 730664562Sgshapiro isprint(*name) ? *name : '?'); 730764562Sgshapiro return NULL; 730864562Sgshapiro } 730964562Sgshapiro if (boolres) 731064562Sgshapiro snprintf(result, sizeof result, res ? "TRUE" : "FALSE"); 731164562Sgshapiro else 731264562Sgshapiro snprintf(result, sizeof result, "%ld", r); 731364562Sgshapiro return result; 731464562Sgshapiro } 731564562Sgshapiro *statp = EX_CONFIG; 731664562Sgshapiro return NULL; 731764562Sgshapiro} 7318