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