map.c revision 64562
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 1564562Sgshapirostatic char id[] = "@(#)$Id: map.c,v 8.414.4.13 2000/07/14 16:48:21 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(); 57138032Speter } 57264562Sgshapiro else 57364562Sgshapiro { 57464562Sgshapiro /* don't try again */ 57564562Sgshapiro map->map_mflags &= ~MF_VALID; 57664562Sgshapiro } 57738032Speter } 57864562Sgshapiro 57964562Sgshapiro if (restore) 58064562Sgshapiro { 58164562Sgshapiro Errors = saveerrors; 58264562Sgshapiro HoldErrs = savehold; 58364562Sgshapiro QuickAbort = savequick; 58464562Sgshapiro } 58564562Sgshapiro 58664562Sgshapiro return bitset(MF_OPEN, map->map_mflags); 58738032Speter} 58838032Speter/* 58942575Speter** CLOSEMAPS -- close all open maps opened by the current pid. 59042575Speter** 59142575Speter** Parameters: 59242575Speter** none 59342575Speter** 59442575Speter** Returns: 59542575Speter** none. 59642575Speter*/ 59742575Speter 59842575Spetervoid 59942575Speterclosemaps() 60042575Speter{ 60142575Speter stabapply(map_close, 0); 60242575Speter} 60364562Sgshapiro/* 60464562Sgshapiro** MAP_CLOSE -- close a map opened by the current pid. 60564562Sgshapiro** 60664562Sgshapiro** Parameters: 60764562Sgshapiro** s -- STAB entry: if map: try to open 60864562Sgshapiro** second parameter is unused (required by stabapply()) 60964562Sgshapiro** 61064562Sgshapiro** Returns: 61164562Sgshapiro** none. 61264562Sgshapiro*/ 61342575Speter 61442575Speter/* ARGSUSED1 */ 61564562Sgshapirostatic void 61642575Spetermap_close(s, unused) 61742575Speter register STAB *s; 61842575Speter int unused; 61942575Speter{ 62042575Speter MAP *map; 62142575Speter 62242575Speter if (s->s_type != ST_MAP) 62342575Speter return; 62464562Sgshapiro 62542575Speter map = &s->s_map; 62642575Speter 62742575Speter if (!bitset(MF_VALID, map->map_mflags) || 62842575Speter !bitset(MF_OPEN, map->map_mflags) || 62964562Sgshapiro bitset(MF_SHARED, 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)) 281364562Sgshapiro dprintf("ldapmap_open(%s, %d)\n", 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; 284464562Sgshapiro map->map_mflags |= MF_SHARED; 284564562Sgshapiro return TRUE; 284664562Sgshapiro } 284764562Sgshapiro 284864562Sgshapiro /* No connection yet, connect */ 284964562Sgshapiro if (!ldapmap_start(map)) 285064562Sgshapiro return FALSE; 285164562Sgshapiro 285264562Sgshapiro /* Save connection for reuse */ 285364562Sgshapiro s->s_ldap = lmap->ldap_ld; 285438032Speter return TRUE; 285538032Speter} 285638032Speter 285738032Speter/* 285864562Sgshapiro** LDAPMAP_START -- actually connect to an LDAP server 285938032Speter** 286064562Sgshapiro** Parameters: 286164562Sgshapiro** map -- the map being opened. 286264562Sgshapiro** 286364562Sgshapiro** Returns: 286464562Sgshapiro** TRUE if connection is successful, FALSE otherwise. 286564562Sgshapiro** 286664562Sgshapiro** Side Effects: 286764562Sgshapiro** Populates lmap->ldap_ld. 286838032Speter*/ 286938032Speter 287038032Speterstatic jmp_buf LDAPTimeout; 287138032Speter 287264562Sgshapirostatic bool 287364562Sgshapiroldapmap_start(map) 287438032Speter MAP *map; 287538032Speter{ 287664562Sgshapiro register int bind_result; 287764562Sgshapiro int save_errno; 287864562Sgshapiro register EVENT *ev = NULL; 287964562Sgshapiro LDAPMAP_STRUCT *lmap; 288038032Speter LDAP *ld; 288138032Speter 288238032Speter if (tTd(38, 2)) 288364562Sgshapiro dprintf("ldapmap_start(%s)\n", map->map_mname); 288438032Speter 288564562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 288638032Speter 288738032Speter if (tTd(38,9)) 288864562Sgshapiro dprintf("ldapmap_start(%s, %d)\n", 288964562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host, 289064562Sgshapiro lmap->ldap_port); 289138032Speter 289264562Sgshapiro# if USE_LDAP_INIT 289364562Sgshapiro ld = ldap_init(lmap->ldap_host, lmap->ldap_port); 289464562Sgshapiro# else /* USE_LDAP_INIT */ 289564562Sgshapiro /* 289664562Sgshapiro ** If using ldap_open(), the actual connection to the server 289764562Sgshapiro ** happens now so we need the timeout here. For ldap_init(), 289864562Sgshapiro ** the connection happens at bind time. 289964562Sgshapiro */ 290038032Speter 290138032Speter /* set the timeout */ 290264562Sgshapiro if (lmap->ldap_timeout.tv_sec != 0) 290338032Speter { 290438032Speter if (setjmp(LDAPTimeout) != 0) 290538032Speter { 290638032Speter if (LogLevel > 1) 290738032Speter sm_syslog(LOG_NOTICE, CurEnv->e_id, 290864562Sgshapiro "timeout conning to LDAP server %.100s", 290964562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); 291064562Sgshapiro return FALSE; 291138032Speter } 291264562Sgshapiro ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); 291338032Speter } 291438032Speter 291564562Sgshapiro ld = ldap_open(lmap->ldap_host, lmap->ldap_port); 291664562Sgshapiro save_errno = errno; 291742575Speter 291864562Sgshapiro /* clear the event if it has not sprung */ 291964562Sgshapiro if (ev != NULL) 292042575Speter clrevent(ev); 292164562Sgshapiro# endif /* USE_LDAP_INIT */ 292242575Speter 292364562Sgshapiro errno = save_errno; 292442575Speter if (ld == NULL) 292538032Speter { 292638032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 292738032Speter { 292864562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 292964562Sgshapiro syserr("%s failed to %s in map %s", 293064562Sgshapiro# if USE_LDAP_INIT 293164562Sgshapiro "ldap_init", 293264562Sgshapiro# else /* USE_LDAP_INIT */ 293364562Sgshapiro "ldap_open", 293464562Sgshapiro# endif /* USE_LDAP_INIT */ 293564562Sgshapiro lmap->ldap_host == NULL ? "localhost" 293664562Sgshapiro : lmap->ldap_host, 293764562Sgshapiro map->map_mname); 293864562Sgshapiro else 293964562Sgshapiro syserr("421 4.0.0 %s failed to %s in map %s", 294064562Sgshapiro# if USE_LDAP_INIT 294164562Sgshapiro "ldap_init", 294264562Sgshapiro# else /* USE_LDAP_INIT */ 294364562Sgshapiro "ldap_open", 294464562Sgshapiro# endif /* USE_LDAP_INIT */ 294564562Sgshapiro lmap->ldap_host == NULL ? "localhost" 294664562Sgshapiro : lmap->ldap_host, 294764562Sgshapiro map->map_mname); 294838032Speter } 294938032Speter return FALSE; 295038032Speter } 295138032Speter 295264562Sgshapiro ldapmap_setopts(ld, lmap); 295338032Speter 295464562Sgshapiro# if USE_LDAP_INIT 295564562Sgshapiro /* 295664562Sgshapiro ** If using ldap_init(), the actual connection to the server 295764562Sgshapiro ** happens at ldap_bind_s() so we need the timeout here. 295864562Sgshapiro */ 295964562Sgshapiro 296064562Sgshapiro /* set the timeout */ 296164562Sgshapiro if (lmap->ldap_timeout.tv_sec != 0) 296238032Speter { 296364562Sgshapiro if (setjmp(LDAPTimeout) != 0) 296438032Speter { 296564562Sgshapiro if (LogLevel > 1) 296664562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 296764562Sgshapiro "timeout conning to LDAP server %.100s", 296864562Sgshapiro lmap->ldap_host == NULL ? "localhost" 296964562Sgshapiro : lmap->ldap_host); 297064562Sgshapiro return FALSE; 297138032Speter } 297264562Sgshapiro ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); 297338032Speter } 297464562Sgshapiro# endif /* USE_LDAP_INIT */ 297564562Sgshapiro 297664562Sgshapiro# ifdef LDAP_AUTH_KRBV4 297764562Sgshapiro if (lmap->ldap_method == LDAP_AUTH_KRBV4 && 297864562Sgshapiro lmap->ldap_secret != NULL) 297938032Speter { 298064562Sgshapiro /* 298164562Sgshapiro ** Need to put ticket in environment here instead of 298264562Sgshapiro ** during parseargs as there may be different tickets 298364562Sgshapiro ** for different LDAP connections. 298464562Sgshapiro */ 298564562Sgshapiro 298664562Sgshapiro (void) putenv(lmap->ldap_secret); 298738032Speter } 298864562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 298938032Speter 299064562Sgshapiro bind_result = ldap_bind_s(ld, lmap->ldap_binddn, 299164562Sgshapiro lmap->ldap_secret, lmap->ldap_method); 299264562Sgshapiro 299364562Sgshapiro# if USE_LDAP_INIT 299464562Sgshapiro /* clear the event if it has not sprung */ 299564562Sgshapiro if (ev != NULL) 299664562Sgshapiro clrevent(ev); 299764562Sgshapiro# endif /* USE_LDAP_INIT */ 299864562Sgshapiro 299964562Sgshapiro if (bind_result != LDAP_SUCCESS) 300064562Sgshapiro { 300164562Sgshapiro errno = bind_result + E_LDAPBASE; 300264562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 300364562Sgshapiro { 300464562Sgshapiro syserr("421 4.0.0 Cannot bind to map %s in ldap server %s", 300564562Sgshapiro map->map_mname, 300664562Sgshapiro lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); 300764562Sgshapiro } 300864562Sgshapiro return FALSE; 300964562Sgshapiro } 301064562Sgshapiro 301164562Sgshapiro /* We need to cast ld into the map structure */ 301264562Sgshapiro lmap->ldap_ld = ld; 301364562Sgshapiro return TRUE; 301438032Speter} 301538032Speter 301664562Sgshapiro/* ARGSUSED */ 301764562Sgshapirostatic void 301864562Sgshapiroldaptimeout(sig_no) 301964562Sgshapiro int sig_no; 302064562Sgshapiro{ 302164562Sgshapiro longjmp(LDAPTimeout, 1); 302264562Sgshapiro} 302338032Speter 302438032Speter/* 302564562Sgshapiro** LDAPMAP_CLOSE -- close ldap map 302638032Speter*/ 302738032Speter 302838032Spetervoid 302964562Sgshapiroldapmap_close(map) 303038032Speter MAP *map; 303138032Speter{ 303264562Sgshapiro LDAPMAP_STRUCT *lmap; 303364562Sgshapiro STAB *s; 303443730Speter 303564562Sgshapiro if (tTd(38, 2)) 303664562Sgshapiro dprintf("ldapmap_close(%s)\n", map->map_mname); 303764562Sgshapiro 303864562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 303964562Sgshapiro 304064562Sgshapiro /* Check if already closed */ 304164562Sgshapiro if (lmap->ldap_ld == NULL) 304264562Sgshapiro return; 304364562Sgshapiro 304464562Sgshapiro s = ldapmap_findconn(lmap); 304564562Sgshapiro 304664562Sgshapiro /* Check if already closed */ 304764562Sgshapiro if (s->s_ldap == NULL) 304864562Sgshapiro return; 304964562Sgshapiro 305064562Sgshapiro /* If same as saved connection, stored connection is going away */ 305164562Sgshapiro if (s->s_ldap == lmap->ldap_ld) 305264562Sgshapiro s->s_ldap = NULL; 305364562Sgshapiro 305464562Sgshapiro if (lmap->ldap_ld != NULL) 305543730Speter { 305664562Sgshapiro ldap_unbind(lmap->ldap_ld); 305764562Sgshapiro lmap->ldap_ld = NULL; 305843730Speter } 305938032Speter} 306038032Speter 306164562Sgshapiro# ifdef SUNET_ID 306243730Speter/* 306342575Speter** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form 306442575Speter** This only makes sense at Stanford University. 306538032Speter*/ 306638032Speter 306738032Speterchar * 306838032Spetersunet_id_hash(str) 306938032Speter char *str; 307038032Speter{ 307138032Speter char *p, *p_last; 307238032Speter 307338032Speter p = str; 307438032Speter p_last = p; 307538032Speter while (*p != '\0') 307638032Speter { 307738032Speter if (islower(*p) || isdigit(*p)) 307838032Speter { 307938032Speter *p_last = *p; 308038032Speter p_last++; 308138032Speter } 308238032Speter else if (isupper(*p)) 308338032Speter { 308438032Speter *p_last = tolower(*p); 308538032Speter p_last++; 308638032Speter } 308738032Speter ++p; 308838032Speter } 308938032Speter if (*p_last != '\0') 309038032Speter *p_last = '\0'; 309164562Sgshapiro return str; 309238032Speter} 309364562Sgshapiro# endif /* SUNET_ID */ 309438032Speter 309538032Speter/* 309664562Sgshapiro** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 309738032Speter*/ 309838032Speter 309938032Speterchar * 310064562Sgshapiroldapmap_lookup(map, name, av, statp) 310138032Speter MAP *map; 310238032Speter char *name; 310338032Speter char **av; 310438032Speter int *statp; 310538032Speter{ 310664562Sgshapiro int i; 310764562Sgshapiro int entries = 0; 310864562Sgshapiro int msgid; 310964562Sgshapiro int ret; 311064562Sgshapiro int vsize; 311164562Sgshapiro char *fp, *vp; 311264562Sgshapiro char *p, *q; 311364562Sgshapiro char *result = NULL; 311464562Sgshapiro LDAPMAP_STRUCT *lmap = NULL; 311538032Speter char keybuf[MAXNAME + 1]; 311664562Sgshapiro char filter[LDAPMAP_MAX_FILTER + 1]; 311738032Speter 311838032Speter if (tTd(38, 20)) 311964562Sgshapiro dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); 312038032Speter 312138032Speter /* Get ldap struct pointer from map */ 312264562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 312364562Sgshapiro ldapmap_setopts(lmap->ldap_ld, lmap); 312438032Speter 312564562Sgshapiro (void) strlcpy(keybuf, name, sizeof keybuf); 312638032Speter 312738032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 312864562Sgshapiro { 312964562Sgshapiro# ifdef SUNET_ID 313038032Speter sunet_id_hash(keybuf); 313164562Sgshapiro# else /* SUNET_ID */ 313238032Speter makelower(keybuf); 313364562Sgshapiro# endif /* SUNET_ID */ 313464562Sgshapiro } 313538032Speter 313642575Speter /* substitute keybuf into filter, perhaps multiple times */ 313764562Sgshapiro memset(filter, '\0', sizeof filter); 313842575Speter fp = filter; 313964562Sgshapiro p = lmap->ldap_filter; 314042575Speter while ((q = strchr(p, '%')) != NULL) 314142575Speter { 314242575Speter if (q[1] == 's') 314342575Speter { 314442575Speter snprintf(fp, SPACELEFT(filter, fp), "%.*s%s", 314542575Speter q - p, p, keybuf); 314664562Sgshapiro fp += strlen(fp); 314742575Speter p = q + 2; 314842575Speter } 314964562Sgshapiro else if (q[1] == '0') 315064562Sgshapiro { 315164562Sgshapiro char *k = keybuf; 315264562Sgshapiro 315364562Sgshapiro snprintf(fp, SPACELEFT(filter, fp), "%.*s", 315464562Sgshapiro q - p, p); 315564562Sgshapiro fp += strlen(fp); 315664562Sgshapiro p = q + 2; 315764562Sgshapiro 315864562Sgshapiro /* Properly escape LDAP special characters */ 315964562Sgshapiro while (SPACELEFT(filter, fp) > 0 && 316064562Sgshapiro *k != '\0') 316164562Sgshapiro { 316264562Sgshapiro if (*k == '*' || *k == '(' || 316364562Sgshapiro *k == ')' || *k == '\\') 316464562Sgshapiro { 316564562Sgshapiro (void) strlcat(fp, 316664562Sgshapiro (*k == '*' ? "\\2A" : 316764562Sgshapiro (*k == '(' ? "\\28" : 316864562Sgshapiro (*k == ')' ? "\\29" : 316964562Sgshapiro (*k == '\\' ? "\\5C" : 317064562Sgshapiro "\00")))), 317164562Sgshapiro SPACELEFT(filter, fp)); 317264562Sgshapiro fp += strlen(fp); 317364562Sgshapiro k++; 317464562Sgshapiro } 317564562Sgshapiro else 317664562Sgshapiro *fp++ = *k++; 317764562Sgshapiro } 317864562Sgshapiro } 317942575Speter else 318042575Speter { 318142575Speter snprintf(fp, SPACELEFT(filter, fp), "%.*s", 318242575Speter q - p + 1, p); 318342575Speter p = q + (q[1] == '%' ? 2 : 1); 318464562Sgshapiro fp += strlen(fp); 318542575Speter } 318642575Speter } 318742575Speter snprintf(fp, SPACELEFT(filter, fp), "%s", p); 318842575Speter if (tTd(38, 20)) 318964562Sgshapiro dprintf("ldap search filter=%s\n", filter); 319038032Speter 319164562Sgshapiro lmap->ldap_res = NULL; 319264562Sgshapiro msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, 319364562Sgshapiro filter, 319464562Sgshapiro (lmap->ldap_attr[0] == NULL ? NULL : 319564562Sgshapiro lmap->ldap_attr), 319664562Sgshapiro lmap->ldap_attrsonly); 319764562Sgshapiro if (msgid == -1) 319838032Speter { 319964562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 320064562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 320138032Speter { 320264562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 320364562Sgshapiro syserr("Error in ldap_search_st using %s in map %s", 320464562Sgshapiro filter, map->map_mname); 320564562Sgshapiro else 320664562Sgshapiro syserr("421 4.0.0 Error in ldap_search_st using %s in map %s", 320764562Sgshapiro filter, map->map_mname); 320838032Speter } 320964562Sgshapiro *statp = EX_TEMPFAIL; 321064562Sgshapiro return NULL; 321164562Sgshapiro } 321264562Sgshapiro 321364562Sgshapiro *statp = EX_NOTFOUND; 321464562Sgshapiro vp = NULL; 321564562Sgshapiro 321664562Sgshapiro /* Get results (all if MF_NOREWRITE, otherwise one by one) */ 321764562Sgshapiro while ((ret = ldap_result(lmap->ldap_ld, msgid, 321864562Sgshapiro bitset(MF_NOREWRITE, map->map_mflags), 321964562Sgshapiro (lmap->ldap_timeout.tv_sec == 0 ? NULL : 322064562Sgshapiro &(lmap->ldap_timeout)), 322164562Sgshapiro &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) 322264562Sgshapiro { 322364562Sgshapiro LDAPMessage *entry; 322464562Sgshapiro 322564562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 322638032Speter { 322764562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, 322864562Sgshapiro lmap->ldap_res); 322964562Sgshapiro if (entries > 1) 323064562Sgshapiro { 323164562Sgshapiro *statp = EX_NOTFOUND; 323264562Sgshapiro if (lmap->ldap_res != NULL) 323364562Sgshapiro { 323464562Sgshapiro ldap_msgfree(lmap->ldap_res); 323564562Sgshapiro lmap->ldap_res = NULL; 323664562Sgshapiro } 323764562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 323864562Sgshapiro if (vp != NULL) 323964562Sgshapiro free(vp); 324064562Sgshapiro if (tTd(38, 25)) 324164562Sgshapiro dprintf("ldap search found multiple on a single match query\n"); 324264562Sgshapiro return NULL; 324364562Sgshapiro } 324464562Sgshapiro } 324564562Sgshapiro 324664562Sgshapiro /* If we don't want multiple values and we have one, break */ 324764562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 324864562Sgshapiro break; 324964562Sgshapiro 325064562Sgshapiro /* Cycle through all entries */ 325164562Sgshapiro for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); 325264562Sgshapiro entry != NULL; 325364562Sgshapiro entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) 325464562Sgshapiro { 325564562Sgshapiro BerElement *ber; 325664562Sgshapiro char *attr; 325764562Sgshapiro char **vals = NULL; 325864562Sgshapiro 325964562Sgshapiro /* 326064562Sgshapiro ** If matching only and found an entry, 326164562Sgshapiro ** no need to spin through attributes 326264562Sgshapiro */ 326364562Sgshapiro 326464562Sgshapiro if (*statp == EX_OK && 326564562Sgshapiro bitset(MF_MATCHONLY, map->map_mflags)) 326664562Sgshapiro continue; 326764562Sgshapiro 326864562Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 326964562Sgshapiro /* 327064562Sgshapiro ** Reset value to prevent lingering 327164562Sgshapiro ** LDAP_DECODING_ERROR due to 327264562Sgshapiro ** OpenLDAP 1.X's hack (see below) 327364562Sgshapiro */ 327464562Sgshapiro 327564562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 327664562Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 327764562Sgshapiro 327864562Sgshapiro for (attr = ldap_first_attribute(lmap->ldap_ld, entry, 327964562Sgshapiro &ber); 328064562Sgshapiro attr != NULL; 328164562Sgshapiro attr = ldap_next_attribute(lmap->ldap_ld, entry, 328264562Sgshapiro ber)) 328364562Sgshapiro { 328464562Sgshapiro char *tmp, *vp_tmp; 328564562Sgshapiro 328664562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_FALSE) 328764562Sgshapiro { 328864562Sgshapiro vals = ldap_get_values(lmap->ldap_ld, 328964562Sgshapiro entry, 329064562Sgshapiro attr); 329164562Sgshapiro if (vals == NULL) 329264562Sgshapiro { 329364562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 329464562Sgshapiro if (errno == LDAP_SUCCESS) 329564562Sgshapiro continue; 329664562Sgshapiro 329764562Sgshapiro /* Must be an error */ 329864562Sgshapiro errno += E_LDAPBASE; 329964562Sgshapiro if (!bitset(MF_OPTIONAL, 330064562Sgshapiro map->map_mflags)) 330164562Sgshapiro { 330264562Sgshapiro if (bitset(MF_NODEFER, 330364562Sgshapiro map->map_mflags)) 330464562Sgshapiro syserr("Error getting LDAP values in map %s", 330564562Sgshapiro map->map_mname); 330664562Sgshapiro else 330764562Sgshapiro syserr("421 4.0.0 Error getting LDAP values in map %s", 330864562Sgshapiro map->map_mname); 330964562Sgshapiro } 331064562Sgshapiro *statp = EX_TEMPFAIL; 331164562Sgshapiro# if USING_NETSCAPE_LDAP 331264562Sgshapiro ldap_mem_free(attr); 331364562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 331464562Sgshapiro if (lmap->ldap_res != NULL) 331564562Sgshapiro { 331664562Sgshapiro ldap_msgfree(lmap->ldap_res); 331764562Sgshapiro lmap->ldap_res = NULL; 331864562Sgshapiro } 331964562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, 332064562Sgshapiro msgid); 332164562Sgshapiro if (vp != NULL) 332264562Sgshapiro free(vp); 332364562Sgshapiro return NULL; 332464562Sgshapiro } 332564562Sgshapiro } 332664562Sgshapiro 332764562Sgshapiro *statp = EX_OK; 332864562Sgshapiro 332964562Sgshapiro# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 333064562Sgshapiro /* 333164562Sgshapiro ** Reset value to prevent lingering 333264562Sgshapiro ** LDAP_DECODING_ERROR due to 333364562Sgshapiro ** OpenLDAP 1.X's hack (see below) 333464562Sgshapiro */ 333564562Sgshapiro 333664562Sgshapiro lmap->ldap_ld->ld_errno = LDAP_SUCCESS; 333764562Sgshapiro# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 333864562Sgshapiro 333964562Sgshapiro /* 334064562Sgshapiro ** If matching only, 334164562Sgshapiro ** no need to spin through entries 334264562Sgshapiro */ 334364562Sgshapiro 334464562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 334564562Sgshapiro continue; 334664562Sgshapiro 334764562Sgshapiro /* 334864562Sgshapiro ** If we don't want multiple values, 334964562Sgshapiro ** return first found. 335064562Sgshapiro */ 335164562Sgshapiro 335264562Sgshapiro if (map->map_coldelim == '\0') 335364562Sgshapiro { 335464562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 335564562Sgshapiro { 335664562Sgshapiro vp = newstr(attr); 335764562Sgshapiro# if USING_NETSCAPE_LDAP 335864562Sgshapiro ldap_mem_free(attr); 335964562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 336064562Sgshapiro break; 336164562Sgshapiro } 336264562Sgshapiro 336364562Sgshapiro if (vals[0] == NULL) 336464562Sgshapiro { 336564562Sgshapiro ldap_value_free(vals); 336664562Sgshapiro# if USING_NETSCAPE_LDAP 336764562Sgshapiro ldap_mem_free(attr); 336864562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 336964562Sgshapiro continue; 337064562Sgshapiro } 337164562Sgshapiro 337264562Sgshapiro vp = newstr(vals[0]); 337364562Sgshapiro ldap_value_free(vals); 337464562Sgshapiro# if USING_NETSCAPE_LDAP 337564562Sgshapiro ldap_mem_free(attr); 337664562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 337764562Sgshapiro break; 337864562Sgshapiro } 337964562Sgshapiro 338064562Sgshapiro /* attributes only */ 338164562Sgshapiro if (lmap->ldap_attrsonly == LDAPMAP_TRUE) 338264562Sgshapiro { 338364562Sgshapiro if (vp == NULL) 338464562Sgshapiro vp = newstr(attr); 338564562Sgshapiro else 338664562Sgshapiro { 338764562Sgshapiro vsize = strlen(vp) + 338864562Sgshapiro strlen(attr) + 2; 338964562Sgshapiro tmp = xalloc(vsize); 339064562Sgshapiro snprintf(tmp, vsize, "%s%c%s", 339164562Sgshapiro vp, map->map_coldelim, 339264562Sgshapiro attr); 339364562Sgshapiro free(vp); 339464562Sgshapiro vp = tmp; 339564562Sgshapiro } 339664562Sgshapiro# if USING_NETSCAPE_LDAP 339764562Sgshapiro ldap_mem_free(attr); 339864562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 339964562Sgshapiro continue; 340064562Sgshapiro } 340164562Sgshapiro 340264562Sgshapiro /* 340364562Sgshapiro ** If there is more than one, 340464562Sgshapiro ** munge then into a map_coldelim 340564562Sgshapiro ** separated string 340664562Sgshapiro */ 340764562Sgshapiro 340864562Sgshapiro vsize = 0; 340964562Sgshapiro for (i = 0; vals[i] != NULL; i++) 341064562Sgshapiro vsize += strlen(vals[i]) + 1; 341164562Sgshapiro vp_tmp = xalloc(vsize); 341264562Sgshapiro *vp_tmp = '\0'; 341364562Sgshapiro 341464562Sgshapiro p = vp_tmp; 341564562Sgshapiro for (i = 0; vals[i] != NULL; i++) 341664562Sgshapiro { 341764562Sgshapiro p += strlcpy(p, vals[i], 341864562Sgshapiro vsize - (p - vp_tmp)); 341964562Sgshapiro if (p >= vp_tmp + vsize) 342064562Sgshapiro syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values"); 342164562Sgshapiro if (vals[i + 1] != NULL) 342264562Sgshapiro *p++ = map->map_coldelim; 342364562Sgshapiro } 342464562Sgshapiro 342564562Sgshapiro ldap_value_free(vals); 342664562Sgshapiro# if USING_NETSCAPE_LDAP 342764562Sgshapiro ldap_mem_free(attr); 342864562Sgshapiro# endif /* USING_NETSCAPE_LDAP */ 342964562Sgshapiro if (vp == NULL) 343064562Sgshapiro { 343164562Sgshapiro vp = vp_tmp; 343264562Sgshapiro continue; 343364562Sgshapiro } 343464562Sgshapiro vsize = strlen(vp) + strlen(vp_tmp) + 2; 343564562Sgshapiro tmp = xalloc(vsize); 343664562Sgshapiro snprintf(tmp, vsize, "%s%c%s", 343764562Sgshapiro vp, map->map_coldelim, vp_tmp); 343864562Sgshapiro 343964562Sgshapiro free(vp); 344064562Sgshapiro free(vp_tmp); 344164562Sgshapiro vp = tmp; 344264562Sgshapiro } 344364562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 344464562Sgshapiro 344564562Sgshapiro /* 344664562Sgshapiro ** We check errno != LDAP_DECODING_ERROR since 344764562Sgshapiro ** OpenLDAP 1.X has a very ugly *undocumented* 344864562Sgshapiro ** hack of returning this error code from 344964562Sgshapiro ** ldap_next_attribute() if the library freed the 345064562Sgshapiro ** ber attribute. See: 345164562Sgshapiro ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 345264562Sgshapiro */ 345364562Sgshapiro 345464562Sgshapiro if (errno != LDAP_SUCCESS && 345564562Sgshapiro errno != LDAP_DECODING_ERROR) 345664562Sgshapiro { 345764562Sgshapiro /* Must be an error */ 345864562Sgshapiro errno += E_LDAPBASE; 345964562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 346064562Sgshapiro { 346164562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 346264562Sgshapiro syserr("Error getting LDAP attributes in map %s", 346364562Sgshapiro map->map_mname); 346464562Sgshapiro else 346564562Sgshapiro syserr("421 4.0.0 Error getting LDAP attributes in map %s", 346664562Sgshapiro map->map_mname); 346764562Sgshapiro } 346864562Sgshapiro *statp = EX_TEMPFAIL; 346964562Sgshapiro if (lmap->ldap_res != NULL) 347064562Sgshapiro { 347164562Sgshapiro ldap_msgfree(lmap->ldap_res); 347264562Sgshapiro lmap->ldap_res = NULL; 347364562Sgshapiro } 347464562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 347564562Sgshapiro if (vp != NULL) 347664562Sgshapiro free(vp); 347764562Sgshapiro return NULL; 347864562Sgshapiro } 347964562Sgshapiro 348064562Sgshapiro /* We don't want multiple values and we have one */ 348164562Sgshapiro if (map->map_coldelim == '\0' && vp != NULL) 348264562Sgshapiro break; 348364562Sgshapiro } 348464562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 348564562Sgshapiro if (errno != LDAP_SUCCESS && errno != LDAP_DECODING_ERROR) 348664562Sgshapiro { 348764562Sgshapiro /* Must be an error */ 348864562Sgshapiro errno += E_LDAPBASE; 348938032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 349038032Speter { 349164562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 349264562Sgshapiro syserr("Error getting LDAP entries in map %s", 349364562Sgshapiro map->map_mname); 349464562Sgshapiro else 349564562Sgshapiro syserr("421 4.0.0 Error getting LDAP entries in map %s", 349664562Sgshapiro map->map_mname); 349738032Speter } 349838032Speter *statp = EX_TEMPFAIL; 349964562Sgshapiro if (lmap->ldap_res != NULL) 350064562Sgshapiro { 350164562Sgshapiro ldap_msgfree(lmap->ldap_res); 350264562Sgshapiro lmap->ldap_res = NULL; 350364562Sgshapiro } 350464562Sgshapiro (void) ldap_abandon(lmap->ldap_ld, msgid); 350564562Sgshapiro if (vp != NULL) 350664562Sgshapiro free(vp); 350764562Sgshapiro return NULL; 350838032Speter } 350964562Sgshapiro ldap_msgfree(lmap->ldap_res); 351064562Sgshapiro lmap->ldap_res = NULL; 351138032Speter } 351238032Speter 351364562Sgshapiro /* 351464562Sgshapiro ** If grabbing all results at once for MF_NOREWRITE and 351564562Sgshapiro ** only want a single match, make sure that's all we have 351664562Sgshapiro */ 351764562Sgshapiro 351864562Sgshapiro if (ret == LDAP_RES_SEARCH_RESULT && 351964562Sgshapiro bitset(MF_NOREWRITE|MF_SINGLEMATCH, map->map_mflags)) 352038032Speter { 352164562Sgshapiro entries += ldap_count_entries(lmap->ldap_ld, lmap->ldap_res); 352264562Sgshapiro if (entries > 1) 352364562Sgshapiro { 352464562Sgshapiro *statp = EX_NOTFOUND; 352564562Sgshapiro if (lmap->ldap_res != NULL) 352664562Sgshapiro { 352764562Sgshapiro ldap_msgfree(lmap->ldap_res); 352864562Sgshapiro lmap->ldap_res = NULL; 352964562Sgshapiro } 353064562Sgshapiro if (vp != NULL) 353164562Sgshapiro free(vp); 353264562Sgshapiro return NULL; 353364562Sgshapiro } 353464562Sgshapiro *statp = EX_OK; 353538032Speter } 353638032Speter 353764562Sgshapiro if (ret == 0) 353864562Sgshapiro errno = ETIMEDOUT; 353964562Sgshapiro else 354064562Sgshapiro errno = ldapmap_geterrno(lmap->ldap_ld); 354164562Sgshapiro if (errno != LDAP_SUCCESS) 354238032Speter { 354364562Sgshapiro /* Must be an error */ 354464562Sgshapiro if (ret != 0) 354564562Sgshapiro errno += E_LDAPBASE; 354664562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 354764562Sgshapiro { 354864562Sgshapiro if (bitset(MF_NODEFER, map->map_mflags)) 354964562Sgshapiro syserr("Error getting LDAP results in map %s", 355064562Sgshapiro map->map_mname); 355164562Sgshapiro else 355264562Sgshapiro syserr("421 4.0.0 Error getting LDAP results in map %s", 355364562Sgshapiro map->map_mname); 355464562Sgshapiro } 355564562Sgshapiro *statp = EX_TEMPFAIL; 355664562Sgshapiro if (vp != NULL) 355764562Sgshapiro free(vp); 355864562Sgshapiro return NULL; 355938032Speter } 356038032Speter 356164562Sgshapiro /* Did we match anything? */ 356264562Sgshapiro if (vp == NULL) 356364562Sgshapiro return NULL; 356438032Speter 356564562Sgshapiro /* 356664562Sgshapiro ** If MF_NOREWRITE, we are special map which doesn't 356764562Sgshapiro ** actually return a map value. Instead, we don't free 356864562Sgshapiro ** ldap_res and let the calling function process the LDAP 356964562Sgshapiro ** results. The caller should ldap_msgfree(lmap->ldap_res). 357064562Sgshapiro */ 357138032Speter 357264562Sgshapiro if (bitset(MF_NOREWRITE, map->map_mflags)) 357364562Sgshapiro { 357464562Sgshapiro /* vp != NULL due to test above */ 357564562Sgshapiro free(vp); 357664562Sgshapiro return ""; 357764562Sgshapiro } 357838032Speter 357964562Sgshapiro if (*statp == EX_OK) 358064562Sgshapiro { 358164562Sgshapiro /* vp != NULL due to test above */ 358264562Sgshapiro if (LogLevel > 9) 358364562Sgshapiro sm_syslog(LOG_INFO, CurEnv->e_id, 358464562Sgshapiro "ldap %.100s => %s", name, vp); 358564562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 358664562Sgshapiro result = map_rewrite(map, name, strlen(name), NULL); 358764562Sgshapiro else 358864562Sgshapiro result = map_rewrite(map, vp, strlen(vp), av); 358964562Sgshapiro free(vp); 359064562Sgshapiro } 359164562Sgshapiro return result; 359238032Speter} 359338032Speter 359438032Speter/* 359564562Sgshapiro** LDAPMAP_FINDCONN -- find an LDAP connection to the server 359664562Sgshapiro** 359764562Sgshapiro** Cache LDAP connections based on the host, port, bind DN, 359864562Sgshapiro** and secret so we don't have multiple connections open to 359964562Sgshapiro** the same server for different maps. 360064562Sgshapiro** 360164562Sgshapiro** Parameters: 360264562Sgshapiro** lmap -- LDAP map information 360364562Sgshapiro** 360464562Sgshapiro** Returns: 360564562Sgshapiro** Symbol table entry for the LDAP connection. 360664562Sgshapiro** 360738032Speter*/ 360838032Speter 360964562Sgshapirostatic STAB * 361064562Sgshapiroldapmap_findconn(lmap) 361164562Sgshapiro LDAPMAP_STRUCT *lmap; 361238032Speter{ 361364562Sgshapiro int len; 361464562Sgshapiro char *nbuf; 361564562Sgshapiro STAB *s; 361638032Speter 361764562Sgshapiro len = (lmap->ldap_host == NULL ? strlen("localhost") : 361864562Sgshapiro strlen(lmap->ldap_host)) + 1 + 8 + 1 + 361964562Sgshapiro (lmap->ldap_binddn == NULL ? 0 : strlen(lmap->ldap_binddn)) + 362064562Sgshapiro 1 + 362164562Sgshapiro (lmap->ldap_secret == NULL ? 0 : strlen(lmap->ldap_secret)) + 362264562Sgshapiro 1; 362364562Sgshapiro nbuf = xalloc(len); 362464562Sgshapiro snprintf(nbuf, len, "%s%c%d%c%s%c%s", 362564562Sgshapiro (lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host), 362664562Sgshapiro CONDELSE, 362764562Sgshapiro lmap->ldap_port, 362864562Sgshapiro CONDELSE, 362964562Sgshapiro (lmap->ldap_binddn == NULL ? "" : lmap->ldap_binddn), 363064562Sgshapiro CONDELSE, 363164562Sgshapiro (lmap->ldap_secret == NULL ? "" : lmap->ldap_secret)); 363264562Sgshapiro s = stab(nbuf, ST_LDAP, ST_ENTER); 363364562Sgshapiro free(nbuf); 363464562Sgshapiro return s; 363564562Sgshapiro} 363664562Sgshapiro/* 363764562Sgshapiro** LDAPMAP_SETOPTS -- set LDAP options 363864562Sgshapiro** 363964562Sgshapiro** Parameters: 364064562Sgshapiro** ld -- LDAP session handle 364164562Sgshapiro** lmap -- LDAP map information 364264562Sgshapiro** 364364562Sgshapiro** Returns: 364464562Sgshapiro** None. 364564562Sgshapiro** 364664562Sgshapiro*/ 364764562Sgshapiro 364864562Sgshapirostatic void 364964562Sgshapiroldapmap_setopts(ld, lmap) 365064562Sgshapiro LDAP *ld; 365164562Sgshapiro LDAPMAP_STRUCT *lmap; 365264562Sgshapiro{ 365364562Sgshapiro# if USE_LDAP_SET_OPTION 365464562Sgshapiro ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); 365564562Sgshapiro if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) 365664562Sgshapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); 365738032Speter else 365864562Sgshapiro ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 365964562Sgshapiro ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); 366064562Sgshapiro ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); 366164562Sgshapiro# else /* USE_LDAP_SET_OPTION */ 366264562Sgshapiro /* From here on in we can use ldap internal timelimits */ 366364562Sgshapiro ld->ld_deref = lmap->ldap_deref; 366464562Sgshapiro ld->ld_options = lmap->ldap_options; 366564562Sgshapiro ld->ld_sizelimit = lmap->ldap_sizelimit; 366664562Sgshapiro ld->ld_timelimit = lmap->ldap_timelimit; 366764562Sgshapiro# endif /* USE_LDAP_SET_OPTION */ 366838032Speter} 366964562Sgshapiro/* 367064562Sgshapiro** LDAPMAP_GETERRNO -- get ldap errno value 367164562Sgshapiro** 367264562Sgshapiro** Parameters: 367364562Sgshapiro** ld -- LDAP session handle 367464562Sgshapiro** 367564562Sgshapiro** Returns: 367664562Sgshapiro** LDAP errno. 367764562Sgshapiro** 367864562Sgshapiro*/ 367938032Speter 368064562Sgshapirostatic int 368164562Sgshapiroldapmap_geterrno(ld) 368264562Sgshapiro LDAP *ld; 368364562Sgshapiro{ 368464562Sgshapiro int err = LDAP_SUCCESS; 368564562Sgshapiro 368664562Sgshapiro# if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 368764562Sgshapiro (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); 368864562Sgshapiro# else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 368964562Sgshapiro# ifdef LDAP_OPT_SIZELIMIT 369064562Sgshapiro err = ldap_get_lderrno(ld, NULL, NULL); 369164562Sgshapiro# else /* LDAP_OPT_SIZELIMIT */ 369264562Sgshapiro err = ld->ld_errno; 369364562Sgshapiro 369464562Sgshapiro /* 369564562Sgshapiro ** Reset value to prevent lingering LDAP_DECODING_ERROR due to 369664562Sgshapiro ** OpenLDAP 1.X's hack (see above) 369764562Sgshapiro */ 369864562Sgshapiro 369964562Sgshapiro ld->ld_errno = LDAP_SUCCESS; 370064562Sgshapiro# endif /* LDAP_OPT_SIZELIMIT */ 370164562Sgshapiro# endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ 370264562Sgshapiro return err; 370364562Sgshapiro} 370464562Sgshapiro 370538032Speter/* 370664562Sgshapiro** LDAPX_MAP_PARSEARGS -- print warning about use of ldapx map. 370738032Speter*/ 370838032Speter 370938032Speterbool 371064562Sgshapiroldapx_map_parseargs(map, args) 371138032Speter MAP *map; 371238032Speter char *args; 371338032Speter{ 371464562Sgshapiro printf("Warning: The \"ldapx\" map class is deprecated and will be removed in a future\n"); 371564562Sgshapiro printf(" version. Use the \"ldap\" map class instead for map \"%s\".\n", 371664562Sgshapiro map->map_mname); 371764562Sgshapiro return ldapmap_parseargs(map, args); 371864562Sgshapiro} 371938032Speter 372064562Sgshapiro/* 372164562Sgshapiro** LDAPMAP_PARSEARGS -- parse ldap map definition args. 372264562Sgshapiro*/ 372338032Speter 372464562Sgshapirostruct lamvalues LDAPAuthMethods[] = 372564562Sgshapiro{ 372664562Sgshapiro { "none", LDAP_AUTH_NONE }, 372764562Sgshapiro { "simple", LDAP_AUTH_SIMPLE }, 372864562Sgshapiro# ifdef LDAP_AUTH_KRBV4 372964562Sgshapiro { "krbv4", LDAP_AUTH_KRBV4 }, 373064562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 373164562Sgshapiro { NULL, 0 } 373264562Sgshapiro}; 373338032Speter 373464562Sgshapirostruct ladvalues LDAPAliasDereference[] = 373564562Sgshapiro{ 373664562Sgshapiro { "never", LDAP_DEREF_NEVER }, 373764562Sgshapiro { "always", LDAP_DEREF_ALWAYS }, 373864562Sgshapiro { "search", LDAP_DEREF_SEARCHING }, 373964562Sgshapiro { "find", LDAP_DEREF_FINDING }, 374064562Sgshapiro { NULL, 0 } 374164562Sgshapiro}; 374238032Speter 374364562Sgshapirostruct lssvalues LDAPSearchScope[] = 374464562Sgshapiro{ 374564562Sgshapiro { "base", LDAP_SCOPE_BASE }, 374664562Sgshapiro { "one", LDAP_SCOPE_ONELEVEL }, 374764562Sgshapiro { "sub", LDAP_SCOPE_SUBTREE }, 374864562Sgshapiro { NULL, 0 } 374964562Sgshapiro}; 375038032Speter 375164562Sgshapirobool 375264562Sgshapiroldapmap_parseargs(map, args) 375364562Sgshapiro MAP *map; 375464562Sgshapiro char *args; 375564562Sgshapiro{ 375664562Sgshapiro bool secretread = TRUE; 375764562Sgshapiro int i; 375864562Sgshapiro register char *p = args; 375964562Sgshapiro LDAPMAP_STRUCT *lmap; 376064562Sgshapiro struct lamvalues *lam; 376164562Sgshapiro struct ladvalues *lad; 376264562Sgshapiro struct lssvalues *lss; 376364562Sgshapiro char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 376464562Sgshapiro 376564562Sgshapiro /* Get ldap struct pointer from map */ 376664562Sgshapiro lmap = (LDAPMAP_STRUCT *) map->map_db1; 376764562Sgshapiro 376864562Sgshapiro /* Check if setting the initial LDAP defaults */ 376964562Sgshapiro if (lmap == NULL || lmap != LDAPDefaults) 377064562Sgshapiro { 377164562Sgshapiro /* We need to alloc an LDAPMAP_STRUCT struct */ 377264562Sgshapiro lmap = (LDAPMAP_STRUCT *) xalloc(sizeof *lmap); 377364562Sgshapiro if (LDAPDefaults == NULL) 377464562Sgshapiro ldapmap_clear(lmap); 377564562Sgshapiro else 377664562Sgshapiro STRUCTCOPY(*LDAPDefaults, *lmap); 377764562Sgshapiro } 377864562Sgshapiro 377964562Sgshapiro /* there is no check whether there is really an argument */ 378064562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 378164562Sgshapiro map->map_spacesub = SpaceSub; /* default value */ 378238032Speter for (;;) 378338032Speter { 378438032Speter while (isascii(*p) && isspace(*p)) 378538032Speter p++; 378638032Speter if (*p != '-') 378738032Speter break; 378838032Speter switch (*++p) 378938032Speter { 379038032Speter case 'N': 379138032Speter map->map_mflags |= MF_INCLNULL; 379238032Speter map->map_mflags &= ~MF_TRY0NULL; 379338032Speter break; 379438032Speter 379538032Speter case 'O': 379638032Speter map->map_mflags &= ~MF_TRY1NULL; 379738032Speter break; 379838032Speter 379938032Speter case 'o': 380038032Speter map->map_mflags |= MF_OPTIONAL; 380138032Speter break; 380238032Speter 380338032Speter case 'f': 380438032Speter map->map_mflags |= MF_NOFOLDCASE; 380538032Speter break; 380638032Speter 380738032Speter case 'm': 380838032Speter map->map_mflags |= MF_MATCHONLY; 380938032Speter break; 381038032Speter 381138032Speter case 'A': 381238032Speter map->map_mflags |= MF_APPEND; 381338032Speter break; 381438032Speter 381538032Speter case 'q': 381638032Speter map->map_mflags |= MF_KEEPQUOTES; 381738032Speter break; 381838032Speter 381938032Speter case 'a': 382038032Speter map->map_app = ++p; 382138032Speter break; 382238032Speter 382338032Speter case 'T': 382438032Speter map->map_tapp = ++p; 382538032Speter break; 382638032Speter 382764562Sgshapiro case 't': 382864562Sgshapiro map->map_mflags |= MF_NODEFER; 382964562Sgshapiro break; 383064562Sgshapiro 383164562Sgshapiro case 'S': 383264562Sgshapiro map->map_spacesub = *++p; 383364562Sgshapiro break; 383464562Sgshapiro 383564562Sgshapiro case 'D': 383664562Sgshapiro map->map_mflags |= MF_DEFER; 383764562Sgshapiro break; 383864562Sgshapiro 383964562Sgshapiro case 'z': 384064562Sgshapiro if (*++p != '\\') 384164562Sgshapiro map->map_coldelim = *p; 384264562Sgshapiro else 384364562Sgshapiro { 384464562Sgshapiro switch (*++p) 384564562Sgshapiro { 384664562Sgshapiro case 'n': 384764562Sgshapiro map->map_coldelim = '\n'; 384864562Sgshapiro break; 384964562Sgshapiro 385064562Sgshapiro case 't': 385164562Sgshapiro map->map_coldelim = '\t'; 385264562Sgshapiro break; 385364562Sgshapiro 385464562Sgshapiro default: 385564562Sgshapiro map->map_coldelim = '\\'; 385664562Sgshapiro } 385764562Sgshapiro } 385864562Sgshapiro break; 385964562Sgshapiro 386064562Sgshapiro /* Start of ldapmap specific args */ 386138032Speter case 'k': /* search field */ 386238032Speter while (isascii(*++p) && isspace(*p)) 386338032Speter continue; 386464562Sgshapiro lmap->ldap_filter = p; 386538032Speter break; 386638032Speter 386738032Speter case 'v': /* attr to return */ 386838032Speter while (isascii(*++p) && isspace(*p)) 386938032Speter continue; 387064562Sgshapiro lmap->ldap_attr[0] = p; 387164562Sgshapiro lmap->ldap_attr[1] = NULL; 387238032Speter break; 387338032Speter 387464562Sgshapiro case '1': 387564562Sgshapiro map->map_mflags |= MF_SINGLEMATCH; 387664562Sgshapiro break; 387764562Sgshapiro 387838032Speter /* args stolen from ldapsearch.c */ 387938032Speter case 'R': /* don't auto chase referrals */ 388064562Sgshapiro# ifdef LDAP_REFERRALS 388138032Speter lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 388264562Sgshapiro# else /* LDAP_REFERRALS */ 388338032Speter syserr("compile with -DLDAP_REFERRALS for referral support\n"); 388464562Sgshapiro# endif /* LDAP_REFERRALS */ 388538032Speter break; 388638032Speter 388764562Sgshapiro case 'n': /* retrieve attribute names only */ 388864562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_TRUE; 388938032Speter break; 389038032Speter 389164562Sgshapiro case 'r': /* alias dereferencing */ 389264562Sgshapiro while (isascii(*++p) && isspace(*p)) 389364562Sgshapiro continue; 389464562Sgshapiro 389564562Sgshapiro if (strncasecmp(p, "LDAP_DEREF_", 11) == 0) 389664562Sgshapiro p += 11; 389764562Sgshapiro 389864562Sgshapiro for (lad = LDAPAliasDereference; 389964562Sgshapiro lad != NULL && lad->lad_name != NULL; lad++) 390038032Speter { 390164562Sgshapiro if (strncasecmp(p, lad->lad_name, 390264562Sgshapiro strlen(lad->lad_name)) == 0) 390364562Sgshapiro break; 390438032Speter } 390564562Sgshapiro if (lad->lad_name != NULL) 390664562Sgshapiro lmap->ldap_deref = lad->lad_code; 390764562Sgshapiro else 390838032Speter { 390964562Sgshapiro /* bad config line */ 391064562Sgshapiro if (!bitset(MCF_OPTFILE, 391164562Sgshapiro map->map_class->map_cflags)) 391264562Sgshapiro { 391364562Sgshapiro char *ptr; 391464562Sgshapiro 391564562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 391664562Sgshapiro *ptr = '\0'; 391764562Sgshapiro syserr("Deref must be [never|always|search|find] not %s in map %s", 391864562Sgshapiro p, map->map_mname); 391964562Sgshapiro if (ptr != NULL) 392064562Sgshapiro *ptr = ' '; 392164562Sgshapiro return FALSE; 392264562Sgshapiro } 392338032Speter } 392464562Sgshapiro break; 392564562Sgshapiro 392664562Sgshapiro case 's': /* search scope */ 392764562Sgshapiro while (isascii(*++p) && isspace(*p)) 392864562Sgshapiro continue; 392964562Sgshapiro 393064562Sgshapiro if (strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 393164562Sgshapiro p += 11; 393264562Sgshapiro 393364562Sgshapiro for (lss = LDAPSearchScope; 393464562Sgshapiro lss != NULL && lss->lss_name != NULL; lss++) 393538032Speter { 393664562Sgshapiro if (strncasecmp(p, lss->lss_name, 393764562Sgshapiro strlen(lss->lss_name)) == 0) 393864562Sgshapiro break; 393938032Speter } 394064562Sgshapiro if (lss->lss_name != NULL) 394164562Sgshapiro lmap->ldap_scope = lss->lss_code; 394238032Speter else 394364562Sgshapiro { 394464562Sgshapiro /* bad config line */ 394564562Sgshapiro if (!bitset(MCF_OPTFILE, 394664562Sgshapiro map->map_class->map_cflags)) 394738032Speter { 394838032Speter char *ptr; 394938032Speter 395038032Speter if ((ptr = strchr(p, ' ')) != NULL) 395138032Speter *ptr = '\0'; 395238032Speter syserr("Scope must be [base|one|sub] not %s in map %s", 395338032Speter p, map->map_mname); 395438032Speter if (ptr != NULL) 395538032Speter *ptr = ' '; 395638032Speter return FALSE; 395738032Speter } 395838032Speter } 395938032Speter break; 396038032Speter 396138032Speter case 'h': /* ldap host */ 396238032Speter while (isascii(*++p) && isspace(*p)) 396338032Speter continue; 396464562Sgshapiro lmap->ldap_host = p; 396538032Speter break; 396638032Speter 396738032Speter case 'b': /* search base */ 396838032Speter while (isascii(*++p) && isspace(*p)) 396938032Speter continue; 397064562Sgshapiro lmap->ldap_base = p; 397138032Speter break; 397238032Speter 397338032Speter case 'p': /* ldap port */ 397438032Speter while (isascii(*++p) && isspace(*p)) 397538032Speter continue; 397664562Sgshapiro lmap->ldap_port = atoi(p); 397738032Speter break; 397838032Speter 397938032Speter case 'l': /* time limit */ 398038032Speter while (isascii(*++p) && isspace(*p)) 398138032Speter continue; 398264562Sgshapiro lmap->ldap_timelimit = atoi(p); 398364562Sgshapiro lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 398438032Speter break; 398538032Speter 398664562Sgshapiro case 'Z': 398764562Sgshapiro while (isascii(*++p) && isspace(*p)) 398864562Sgshapiro continue; 398964562Sgshapiro lmap->ldap_sizelimit = atoi(p); 399064562Sgshapiro break; 399164562Sgshapiro 399264562Sgshapiro case 'd': /* Dn to bind to server as */ 399364562Sgshapiro while (isascii(*++p) && isspace(*p)) 399464562Sgshapiro continue; 399564562Sgshapiro lmap->ldap_binddn = p; 399664562Sgshapiro break; 399764562Sgshapiro 399864562Sgshapiro case 'M': /* Method for binding */ 399964562Sgshapiro while (isascii(*++p) && isspace(*p)) 400064562Sgshapiro continue; 400164562Sgshapiro 400264562Sgshapiro if (strncasecmp(p, "LDAP_AUTH_", 10) == 0) 400364562Sgshapiro p += 10; 400464562Sgshapiro 400564562Sgshapiro for (lam = LDAPAuthMethods; 400664562Sgshapiro lam != NULL && lam->lam_name != NULL; lam++) 400764562Sgshapiro { 400864562Sgshapiro if (strncasecmp(p, lam->lam_name, 400964562Sgshapiro strlen(lam->lam_name)) == 0) 401064562Sgshapiro break; 401164562Sgshapiro } 401264562Sgshapiro if (lam->lam_name != NULL) 401364562Sgshapiro lmap->ldap_method = lam->lam_code; 401464562Sgshapiro else 401564562Sgshapiro { 401664562Sgshapiro /* bad config line */ 401764562Sgshapiro if (!bitset(MCF_OPTFILE, 401864562Sgshapiro map->map_class->map_cflags)) 401964562Sgshapiro { 402064562Sgshapiro char *ptr; 402164562Sgshapiro 402264562Sgshapiro if ((ptr = strchr(p, ' ')) != NULL) 402364562Sgshapiro *ptr = '\0'; 402464562Sgshapiro syserr("Method for binding must be [none|simple|krbv4] not %s in map %s", 402564562Sgshapiro p, map->map_mname); 402664562Sgshapiro if (ptr != NULL) 402764562Sgshapiro *ptr = ' '; 402864562Sgshapiro return FALSE; 402964562Sgshapiro } 403064562Sgshapiro } 403164562Sgshapiro 403264562Sgshapiro break; 403364562Sgshapiro 403464562Sgshapiro /* 403564562Sgshapiro ** This is a string that is dependent on the 403664562Sgshapiro ** method used defined above. 403764562Sgshapiro */ 403864562Sgshapiro 403964562Sgshapiro case 'P': /* Secret password for binding */ 404064562Sgshapiro while (isascii(*++p) && isspace(*p)) 404164562Sgshapiro continue; 404264562Sgshapiro lmap->ldap_secret = p; 404364562Sgshapiro secretread = FALSE; 404464562Sgshapiro break; 404564562Sgshapiro 404664562Sgshapiro default: 404764562Sgshapiro syserr("Illegal option %c map %s", *p, map->map_mname); 404864562Sgshapiro break; 404938032Speter } 405038032Speter 405164562Sgshapiro /* need to account for quoted strings here */ 405264562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 405338032Speter { 405438032Speter if (*p == '"') 405538032Speter { 405638032Speter while (*++p != '"' && *p != '\0') 405738032Speter continue; 405838032Speter if (*p != '\0') 405938032Speter p++; 406038032Speter } 406138032Speter else 406238032Speter p++; 406338032Speter } 406438032Speter 406538032Speter if (*p != '\0') 406638032Speter *p++ = '\0'; 406738032Speter } 406838032Speter 406938032Speter if (map->map_app != NULL) 407064562Sgshapiro map->map_app = newstr(ldapmap_dequote(map->map_app)); 407138032Speter if (map->map_tapp != NULL) 407264562Sgshapiro map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 407338032Speter 407438032Speter /* 407542575Speter ** We need to swallow up all the stuff into a struct 407642575Speter ** and dump it into map->map_dbptr1 407738032Speter */ 407838032Speter 407964562Sgshapiro if (lmap->ldap_host != NULL && 408064562Sgshapiro (LDAPDefaults == NULL || 408164562Sgshapiro LDAPDefaults == lmap || 408264562Sgshapiro LDAPDefaults->ldap_host != lmap->ldap_host)) 408364562Sgshapiro lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 408464562Sgshapiro map->map_domain = lmap->ldap_host; 408564562Sgshapiro 408664562Sgshapiro if (lmap->ldap_binddn != NULL && 408764562Sgshapiro (LDAPDefaults == NULL || 408864562Sgshapiro LDAPDefaults == lmap || 408964562Sgshapiro LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 409064562Sgshapiro lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 409164562Sgshapiro 409264562Sgshapiro if (lmap->ldap_secret != NULL && 409364562Sgshapiro (LDAPDefaults == NULL || 409464562Sgshapiro LDAPDefaults == lmap || 409564562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 409638032Speter { 409764562Sgshapiro FILE *sfd; 409864562Sgshapiro long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 409938032Speter 410064562Sgshapiro if (DontLockReadFiles) 410164562Sgshapiro sff |= SFF_NOLOCK; 410238032Speter 410364562Sgshapiro /* need to use method to map secret to passwd string */ 410464562Sgshapiro switch (lmap->ldap_method) 410564562Sgshapiro { 410664562Sgshapiro case LDAP_AUTH_NONE: 410764562Sgshapiro /* Do nothing */ 410864562Sgshapiro break; 410938032Speter 411064562Sgshapiro case LDAP_AUTH_SIMPLE: 411138032Speter 411264562Sgshapiro /* 411364562Sgshapiro ** Secret is the name of a file with 411464562Sgshapiro ** the first line as the password. 411564562Sgshapiro */ 411664562Sgshapiro 411764562Sgshapiro /* Already read in the secret? */ 411864562Sgshapiro if (secretread) 411964562Sgshapiro break; 412064562Sgshapiro 412164562Sgshapiro sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 412264562Sgshapiro O_RDONLY, 0, sff); 412364562Sgshapiro if (sfd == NULL) 412464562Sgshapiro { 412564562Sgshapiro syserr("LDAP map: cannot open secret %s", 412664562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 412764562Sgshapiro return FALSE; 412864562Sgshapiro } 412964562Sgshapiro lmap->ldap_secret = sfgets(m_tmp, LDAPMAP_MAX_PASSWD, 413064562Sgshapiro sfd, 0, "ldapmap_parseargs"); 413164562Sgshapiro (void) fclose(sfd); 413264562Sgshapiro if (lmap->ldap_secret != NULL && 413364562Sgshapiro strlen(m_tmp) > 0) 413464562Sgshapiro { 413564562Sgshapiro /* chomp newline */ 413664562Sgshapiro if (m_tmp[strlen(m_tmp) - 1] == '\n') 413764562Sgshapiro m_tmp[strlen(m_tmp) - 1] = '\0'; 413864562Sgshapiro 413964562Sgshapiro lmap->ldap_secret = m_tmp; 414064562Sgshapiro } 414164562Sgshapiro break; 414264562Sgshapiro 414364562Sgshapiro# ifdef LDAP_AUTH_KRBV4 414464562Sgshapiro case LDAP_AUTH_KRBV4: 414564562Sgshapiro 414664562Sgshapiro /* 414764562Sgshapiro ** Secret is where the ticket file is 414864562Sgshapiro ** stashed 414964562Sgshapiro */ 415064562Sgshapiro 415164562Sgshapiro snprintf(m_tmp, MAXPATHLEN + LDAPMAP_MAX_PASSWD, 415264562Sgshapiro "KRBTKFILE=%s", 415364562Sgshapiro ldapmap_dequote(lmap->ldap_secret)); 415464562Sgshapiro lmap->ldap_secret = m_tmp; 415564562Sgshapiro break; 415664562Sgshapiro# endif /* LDAP_AUTH_KRBV4 */ 415764562Sgshapiro 415864562Sgshapiro default: /* Should NEVER get here */ 415964562Sgshapiro syserr("LDAP map: Illegal value in lmap method"); 416064562Sgshapiro return FALSE; 416164562Sgshapiro break; 416264562Sgshapiro } 416338032Speter } 416438032Speter 416564562Sgshapiro if (lmap->ldap_secret != NULL && 416664562Sgshapiro (LDAPDefaults == NULL || 416764562Sgshapiro LDAPDefaults == lmap || 416864562Sgshapiro LDAPDefaults->ldap_secret != lmap->ldap_secret)) 416964562Sgshapiro lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 417038032Speter 417164562Sgshapiro if (lmap->ldap_base != NULL && 417264562Sgshapiro (LDAPDefaults == NULL || 417364562Sgshapiro LDAPDefaults == lmap || 417464562Sgshapiro LDAPDefaults->ldap_base != lmap->ldap_base)) 417564562Sgshapiro lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 417664562Sgshapiro 417764562Sgshapiro /* 417864562Sgshapiro ** Save the server from extra work. If request is for a single 417964562Sgshapiro ** match, tell the server to only return enough records to 418064562Sgshapiro ** determine if there is a single match or not. This can not 418164562Sgshapiro ** be one since the server would only return one and we wouldn't 418264562Sgshapiro ** know if there were others available. 418364562Sgshapiro */ 418464562Sgshapiro 418564562Sgshapiro if (bitset(MF_SINGLEMATCH, map->map_mflags)) 418664562Sgshapiro lmap->ldap_sizelimit = 2; 418764562Sgshapiro 418864562Sgshapiro /* If setting defaults, don't process ldap_filter and ldap_attr */ 418964562Sgshapiro if (lmap == LDAPDefaults) 419064562Sgshapiro return TRUE; 419164562Sgshapiro 419264562Sgshapiro if (lmap->ldap_filter != NULL) 419364562Sgshapiro lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 419438032Speter else 419538032Speter { 419638032Speter if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 419738032Speter { 419838032Speter syserr("No filter given in map %s", map->map_mname); 419938032Speter return FALSE; 420038032Speter } 420138032Speter } 420264562Sgshapiro 420364562Sgshapiro if (lmap->ldap_attr[0] != NULL) 420438032Speter { 420564562Sgshapiro i = 0; 420664562Sgshapiro p = ldapmap_dequote(lmap->ldap_attr[0]); 420764562Sgshapiro lmap->ldap_attr[0] = NULL; 420864562Sgshapiro 420964562Sgshapiro while (p != NULL) 421038032Speter { 421164562Sgshapiro char *v; 421264562Sgshapiro 421364562Sgshapiro while (isascii(*p) && isspace(*p)) 421464562Sgshapiro p++; 421564562Sgshapiro if (*p == '\0') 421664562Sgshapiro break; 421764562Sgshapiro v = p; 421864562Sgshapiro p = strchr(v, ','); 421964562Sgshapiro if (p != NULL) 422064562Sgshapiro *p++ = '\0'; 422164562Sgshapiro 422264562Sgshapiro if (i == LDAPMAP_MAX_ATTR) 422364562Sgshapiro { 422464562Sgshapiro syserr("Too many return attributes in %s (max %d)", 422564562Sgshapiro map->map_mname, LDAPMAP_MAX_ATTR); 422664562Sgshapiro return FALSE; 422764562Sgshapiro } 422864562Sgshapiro if (*v != '\0') 422964562Sgshapiro lmap->ldap_attr[i++] = newstr(v); 423038032Speter } 423164562Sgshapiro lmap->ldap_attr[i] = NULL; 423238032Speter } 423338032Speter 423438032Speter map->map_db1 = (ARBPTR_T) lmap; 423538032Speter return TRUE; 423638032Speter} 423738032Speter 423864562Sgshapiro/* 423964562Sgshapiro** LDAPMAP_CLEAR -- set default values for LDAPMAP_STRUCT 424064562Sgshapiro** 424164562Sgshapiro** Parameters: 424264562Sgshapiro** lmap -- pointer to LDAPMAP_STRUCT to clear 424364562Sgshapiro** 424464562Sgshapiro** Returns: 424564562Sgshapiro** None. 424664562Sgshapiro** 424764562Sgshapiro*/ 424864562Sgshapiro 424964562Sgshapirostatic void 425064562Sgshapiroldapmap_clear(lmap) 425164562Sgshapiro LDAPMAP_STRUCT *lmap; 425264562Sgshapiro{ 425364562Sgshapiro lmap->ldap_host = NULL; 425464562Sgshapiro lmap->ldap_port = LDAP_PORT; 425564562Sgshapiro lmap->ldap_deref = LDAP_DEREF_NEVER; 425664562Sgshapiro lmap->ldap_timelimit = LDAP_NO_LIMIT; 425764562Sgshapiro lmap->ldap_sizelimit = LDAP_NO_LIMIT; 425864562Sgshapiro# ifdef LDAP_REFERRALS 425964562Sgshapiro lmap->ldap_options = LDAP_OPT_REFERRALS; 426064562Sgshapiro# else /* LDAP_REFERRALS */ 426164562Sgshapiro lmap->ldap_options = 0; 426264562Sgshapiro# endif /* LDAP_REFERRALS */ 426364562Sgshapiro lmap->ldap_binddn = NULL; 426464562Sgshapiro lmap->ldap_secret = NULL; 426564562Sgshapiro lmap->ldap_method = LDAP_AUTH_SIMPLE; 426664562Sgshapiro lmap->ldap_base = NULL; 426764562Sgshapiro lmap->ldap_scope = LDAP_SCOPE_SUBTREE; 426864562Sgshapiro lmap->ldap_attrsonly = LDAPMAP_FALSE; 426964562Sgshapiro lmap->ldap_timeout.tv_sec = 0; 427064562Sgshapiro lmap->ldap_timeout.tv_usec = 0; 427164562Sgshapiro lmap->ldap_ld = NULL; 427264562Sgshapiro lmap->ldap_filter = NULL; 427364562Sgshapiro lmap->ldap_attr[0] = NULL; 427464562Sgshapiro lmap->ldap_res = NULL; 427564562Sgshapiro} 427638032Speter/* 427764562Sgshapiro** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 427864562Sgshapiro** 427964562Sgshapiro** Parameters: 428064562Sgshapiro** spec -- map argument string from LDAPDefaults option 428164562Sgshapiro** 428264562Sgshapiro** Returns: 428364562Sgshapiro** None. 428464562Sgshapiro** 428564562Sgshapiro*/ 428664562Sgshapiro 428764562Sgshapirovoid 428864562Sgshapiroldapmap_set_defaults(spec) 428964562Sgshapiro char *spec; 429064562Sgshapiro{ 429164562Sgshapiro MAP map; 429264562Sgshapiro 429364562Sgshapiro /* Allocate and set the default values */ 429464562Sgshapiro if (LDAPDefaults == NULL) 429564562Sgshapiro LDAPDefaults = (LDAPMAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 429664562Sgshapiro ldapmap_clear(LDAPDefaults); 429764562Sgshapiro 429864562Sgshapiro memset(&map, '\0', sizeof map); 429964562Sgshapiro map.map_db1 = (ARBPTR_T) LDAPDefaults; 430064562Sgshapiro 430164562Sgshapiro (void) ldapmap_parseargs(&map, spec); 430264562Sgshapiro 430364562Sgshapiro /* These should never be set in LDAPDefaults */ 430464562Sgshapiro if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 430564562Sgshapiro map.map_spacesub != SpaceSub || 430664562Sgshapiro map.map_app != NULL || 430764562Sgshapiro map.map_tapp != NULL) 430864562Sgshapiro { 430964562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 431064562Sgshapiro if (map.map_app != NULL) 431164562Sgshapiro { 431264562Sgshapiro free(map.map_app); 431364562Sgshapiro map.map_app = NULL; 431464562Sgshapiro } 431564562Sgshapiro if (map.map_tapp != NULL) 431664562Sgshapiro { 431764562Sgshapiro free(map.map_tapp); 431864562Sgshapiro map.map_tapp = NULL; 431964562Sgshapiro } 432064562Sgshapiro } 432164562Sgshapiro 432264562Sgshapiro if (LDAPDefaults->ldap_filter != NULL) 432364562Sgshapiro { 432464562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 432564562Sgshapiro /* don't free, it isn't malloc'ed in parseargs */ 432664562Sgshapiro LDAPDefaults->ldap_filter = NULL; 432764562Sgshapiro } 432864562Sgshapiro 432964562Sgshapiro if (LDAPDefaults->ldap_attr[0] != NULL) 433064562Sgshapiro { 433164562Sgshapiro syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 433264562Sgshapiro /* don't free, they aren't malloc'ed in parseargs */ 433364562Sgshapiro LDAPDefaults->ldap_attr[0] = NULL; 433464562Sgshapiro } 433564562Sgshapiro} 433664562Sgshapiro#endif /* LDAPMAP */ 433764562Sgshapiro/* 433864562Sgshapiro** PH map 433964562Sgshapiro*/ 434064562Sgshapiro 434164562Sgshapiro#ifdef PH_MAP 434264562Sgshapiro 434364562Sgshapiro/* 434464562Sgshapiro** Support for the CCSO Nameserver (ph/qi). 434564562Sgshapiro** This code is intended to replace the so-called "ph mailer". 434664562Sgshapiro** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 434764562Sgshapiro*/ 434864562Sgshapiro 434964562Sgshapiro# include <qiapi.h> 435064562Sgshapiro# include <qicode.h> 435164562Sgshapiro 435264562Sgshapiro/* 435364562Sgshapiro** PH_MAP_PARSEARGS -- parse ph map definition args. 435464562Sgshapiro*/ 435564562Sgshapiro 435664562Sgshapirobool 435764562Sgshapiroph_map_parseargs(map, args) 435864562Sgshapiro MAP *map; 435964562Sgshapiro char *args; 436064562Sgshapiro{ 436164562Sgshapiro int i; 436264562Sgshapiro register int done; 436364562Sgshapiro PH_MAP_STRUCT *pmap = NULL; 436464562Sgshapiro register char *p = args; 436564562Sgshapiro 436664562Sgshapiro pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 436764562Sgshapiro 436864562Sgshapiro /* defaults */ 436964562Sgshapiro pmap->ph_servers = NULL; 437064562Sgshapiro pmap->ph_field_list = NULL; 437164562Sgshapiro pmap->ph_to_server = NULL; 437264562Sgshapiro pmap->ph_from_server = NULL; 437364562Sgshapiro pmap->ph_sockfd = -1; 437464562Sgshapiro pmap->ph_timeout = 0; 437564562Sgshapiro 437664562Sgshapiro map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 437764562Sgshapiro for (;;) 437864562Sgshapiro { 437964562Sgshapiro while (isascii(*p) && isspace(*p)) 438064562Sgshapiro p++; 438164562Sgshapiro if (*p != '-') 438264562Sgshapiro break; 438364562Sgshapiro switch (*++p) 438464562Sgshapiro { 438564562Sgshapiro case 'N': 438664562Sgshapiro map->map_mflags |= MF_INCLNULL; 438764562Sgshapiro map->map_mflags &= ~MF_TRY0NULL; 438864562Sgshapiro break; 438964562Sgshapiro 439064562Sgshapiro case 'O': 439164562Sgshapiro map->map_mflags &= ~MF_TRY1NULL; 439264562Sgshapiro break; 439364562Sgshapiro 439464562Sgshapiro case 'o': 439564562Sgshapiro map->map_mflags |= MF_OPTIONAL; 439664562Sgshapiro break; 439764562Sgshapiro 439864562Sgshapiro case 'f': 439964562Sgshapiro map->map_mflags |= MF_NOFOLDCASE; 440064562Sgshapiro break; 440164562Sgshapiro 440264562Sgshapiro case 'm': 440364562Sgshapiro map->map_mflags |= MF_MATCHONLY; 440464562Sgshapiro break; 440564562Sgshapiro 440664562Sgshapiro case 'A': 440764562Sgshapiro map->map_mflags |= MF_APPEND; 440864562Sgshapiro break; 440964562Sgshapiro 441064562Sgshapiro case 'q': 441164562Sgshapiro map->map_mflags |= MF_KEEPQUOTES; 441264562Sgshapiro break; 441364562Sgshapiro 441464562Sgshapiro case 't': 441564562Sgshapiro map->map_mflags |= MF_NODEFER; 441664562Sgshapiro break; 441764562Sgshapiro 441864562Sgshapiro case 'a': 441964562Sgshapiro map->map_app = ++p; 442064562Sgshapiro break; 442164562Sgshapiro 442264562Sgshapiro case 'T': 442364562Sgshapiro map->map_tapp = ++p; 442464562Sgshapiro break; 442564562Sgshapiro 442664562Sgshapiro#if _FFR_PHMAP_TIMEOUT 442764562Sgshapiro case 'l': 442864562Sgshapiro while (isascii(*++p) && isspace(*p)) 442964562Sgshapiro continue; 443064562Sgshapiro pmap->ph_timeout = atoi(p); 443164562Sgshapiro break; 443264562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 443364562Sgshapiro 443464562Sgshapiro case 'S': 443564562Sgshapiro map->map_spacesub = *++p; 443664562Sgshapiro break; 443764562Sgshapiro 443864562Sgshapiro case 'D': 443964562Sgshapiro map->map_mflags |= MF_DEFER; 444064562Sgshapiro break; 444164562Sgshapiro 444264562Sgshapiro case 'h': /* PH server list */ 444364562Sgshapiro while (isascii(*++p) && isspace(*p)) 444464562Sgshapiro continue; 444564562Sgshapiro pmap->ph_servers = p; 444664562Sgshapiro break; 444764562Sgshapiro 444864562Sgshapiro case 'v': /* fields to search for */ 444964562Sgshapiro while (isascii(*++p) && isspace(*p)) 445064562Sgshapiro continue; 445164562Sgshapiro pmap->ph_field_list = p; 445264562Sgshapiro break; 445364562Sgshapiro 445464562Sgshapiro default: 445564562Sgshapiro syserr("ph_map_parseargs: unknown option -%c\n", *p); 445664562Sgshapiro } 445764562Sgshapiro 445864562Sgshapiro /* try to account for quoted strings */ 445964562Sgshapiro done = isascii(*p) && isspace(*p); 446064562Sgshapiro while (*p != '\0' && !done) 446164562Sgshapiro { 446264562Sgshapiro if (*p == '"') 446364562Sgshapiro { 446464562Sgshapiro while (*++p != '"' && *p != '\0') 446564562Sgshapiro continue; 446664562Sgshapiro if (*p != '\0') 446764562Sgshapiro p++; 446864562Sgshapiro } 446964562Sgshapiro else 447064562Sgshapiro p++; 447164562Sgshapiro done = isascii(*p) && isspace(*p); 447264562Sgshapiro } 447364562Sgshapiro 447464562Sgshapiro if (*p != '\0') 447564562Sgshapiro *p++ = '\0'; 447664562Sgshapiro } 447764562Sgshapiro 447864562Sgshapiro if (map->map_app != NULL) 447964562Sgshapiro map->map_app = newstr(ph_map_dequote(map->map_app)); 448064562Sgshapiro if (map->map_tapp != NULL) 448164562Sgshapiro map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 448264562Sgshapiro 448364562Sgshapiro if (pmap->ph_field_list != NULL) 448464562Sgshapiro pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 448564562Sgshapiro else 448664562Sgshapiro pmap->ph_field_list = DEFAULT_PH_MAP_FIELDS; 448764562Sgshapiro 448864562Sgshapiro if (pmap->ph_servers != NULL) 448964562Sgshapiro pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 449064562Sgshapiro else 449164562Sgshapiro { 449264562Sgshapiro syserr("ph_map_parseargs: -h flag is required"); 449364562Sgshapiro return FALSE; 449464562Sgshapiro } 449564562Sgshapiro 449664562Sgshapiro map->map_db1 = (ARBPTR_T) pmap; 449764562Sgshapiro return TRUE; 449864562Sgshapiro} 449964562Sgshapiro 450064562Sgshapiro#if _FFR_PHMAP_TIMEOUT 450164562Sgshapiro/* 450264562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 450364562Sgshapiro*/ 450464562Sgshapiro 450564562Sgshapirostatic void 450664562Sgshapiroph_map_safeclose(map) 450764562Sgshapiro MAP *map; 450864562Sgshapiro{ 450964562Sgshapiro int save_errno = errno; 451064562Sgshapiro PH_MAP_STRUCT *pmap; 451164562Sgshapiro 451264562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 451364562Sgshapiro 451464562Sgshapiro if (pmap->ph_sockfd != -1) 451564562Sgshapiro { 451664562Sgshapiro (void) close(pmap->ph_sockfd); 451764562Sgshapiro pmap->ph_sockfd = -1; 451864562Sgshapiro } 451964562Sgshapiro if (pmap->ph_from_server != NULL) 452064562Sgshapiro { 452164562Sgshapiro (void) fclose(pmap->ph_from_server); 452264562Sgshapiro pmap->ph_from_server = NULL; 452364562Sgshapiro } 452464562Sgshapiro if (pmap->ph_to_server != NULL) 452564562Sgshapiro { 452664562Sgshapiro (void) fclose(pmap->ph_to_server); 452764562Sgshapiro pmap->ph_to_server = NULL; 452864562Sgshapiro } 452964562Sgshapiro map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 453064562Sgshapiro errno = save_errno; 453164562Sgshapiro} 453264562Sgshapiro 453364562Sgshapirovoid 453464562Sgshapiroph_map_close(map) 453564562Sgshapiro MAP *map; 453664562Sgshapiro{ 453764562Sgshapiro PH_MAP_STRUCT *pmap; 453864562Sgshapiro 453964562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 454064562Sgshapiro (void) fprintf(pmap->ph_to_server, "quit\n"); 454164562Sgshapiro (void) fflush(pmap->ph_to_server); 454264562Sgshapiro ph_map_safeclose(map); 454364562Sgshapiro} 454464562Sgshapiro 454564562Sgshapirostatic jmp_buf PHTimeout; 454664562Sgshapiro 454764562Sgshapiro/* ARGSUSED */ 454864562Sgshapirostatic void 454964562Sgshapiroph_timeout_func(sig_no) 455064562Sgshapiro int sig_no; 455164562Sgshapiro{ 455264562Sgshapiro longjmp(PHTimeout, 1); 455364562Sgshapiro} 455464562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 455564562Sgshapiro/* 455664562Sgshapiro** PH_MAP_CLOSE -- close the connection to the ph server 455764562Sgshapiro*/ 455864562Sgshapiro 455964562Sgshapirovoid 456064562Sgshapiroph_map_close(map) 456164562Sgshapiro MAP *map; 456264562Sgshapiro{ 456364562Sgshapiro PH_MAP_STRUCT *pmap; 456464562Sgshapiro 456564562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 456664562Sgshapiro CloseQi(pmap->ph_to_server, pmap->ph_from_server); 456764562Sgshapiro pmap->ph_to_server = NULL; 456864562Sgshapiro pmap->ph_from_server = NULL; 456964562Sgshapiro} 457064562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 457164562Sgshapiro 457264562Sgshapiro/* 457364562Sgshapiro** PH_MAP_OPEN -- sub for opening PH map 457464562Sgshapiro*/ 457564562Sgshapirobool 457664562Sgshapiroph_map_open(map, mode) 457764562Sgshapiro MAP *map; 457864562Sgshapiro int mode; 457964562Sgshapiro{ 458064562Sgshapiro#if !_FFR_PHMAP_TIMEOUT 458164562Sgshapiro int save_errno = 0; 458264562Sgshapiro#endif /* !_FFR_PHMAP_TIMEOUT */ 458364562Sgshapiro int j; 458464562Sgshapiro char *hostlist, *tmp; 458564562Sgshapiro QIR *server_data = NULL; 458664562Sgshapiro PH_MAP_STRUCT *pmap; 458764562Sgshapiro#if _FFR_PHMAP_TIMEOUT 458864562Sgshapiro register EVENT *ev = NULL; 458964562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 459064562Sgshapiro 459164562Sgshapiro if (tTd(38, 2)) 459264562Sgshapiro dprintf("ph_map_open(%s)\n", map->map_mname); 459364562Sgshapiro 459464562Sgshapiro mode &= O_ACCMODE; 459564562Sgshapiro if (mode != O_RDONLY) 459664562Sgshapiro { 459764562Sgshapiro /* issue a pseudo-error message */ 459864562Sgshapiro# ifdef ENOSYS 459964562Sgshapiro errno = ENOSYS; 460064562Sgshapiro# else /* ENOSYS */ 460164562Sgshapiro# ifdef EFTYPE 460264562Sgshapiro errno = EFTYPE; 460364562Sgshapiro# else /* EFTYPE */ 460464562Sgshapiro errno = ENXIO; 460564562Sgshapiro# endif /* EFTYPE */ 460664562Sgshapiro# endif /* ENOSYS */ 460764562Sgshapiro return FALSE; 460864562Sgshapiro } 460964562Sgshapiro 461064562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 461164562Sgshapiro 461264562Sgshapiro hostlist = newstr(pmap->ph_servers); 461364562Sgshapiro tmp = strtok(hostlist, " "); 461464562Sgshapiro do 461564562Sgshapiro { 461664562Sgshapiro#if _FFR_PHMAP_TIMEOUT 461764562Sgshapiro if (pmap->ph_timeout != 0) 461864562Sgshapiro { 461964562Sgshapiro if (setjmp(PHTimeout) != 0) 462064562Sgshapiro { 462164562Sgshapiro ev = NULL; 462264562Sgshapiro if (LogLevel > 1) 462364562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 462464562Sgshapiro "timeout connecting to PH server %.100s", 462564562Sgshapiro tmp); 462664562Sgshapiro# ifdef ETIMEDOUT 462764562Sgshapiro errno = ETIMEDOUT; 462864562Sgshapiro# else /* ETIMEDOUT */ 462964562Sgshapiro errno = 0; 463064562Sgshapiro# endif /* ETIMEDOUT */ 463164562Sgshapiro goto ph_map_open_abort; 463264562Sgshapiro } 463364562Sgshapiro ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); 463464562Sgshapiro } 463564562Sgshapiro if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) && 463664562Sgshapiro !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server), 463764562Sgshapiro &(pmap->ph_from_server)) && 463864562Sgshapiro fprintf(pmap->ph_to_server, "id sendmail+phmap\n") >= 0 && 463964562Sgshapiro fflush(pmap->ph_to_server) == 0 && 464064562Sgshapiro (server_data = ReadQi(pmap->ph_from_server, &j)) != NULL && 464164562Sgshapiro server_data->code == 200) 464264562Sgshapiro { 464364562Sgshapiro if (ev != NULL) 464464562Sgshapiro clrevent(ev); 464564562Sgshapiro FreeQIR(server_data); 464664562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 464764562Sgshapiro if (OpenQi(tmp, &(pmap->ph_to_server), 464864562Sgshapiro &(pmap->ph_from_server)) >= 0) 464964562Sgshapiro { 465064562Sgshapiro if (fprintf(pmap->ph_to_server, 465164562Sgshapiro "id sendmail+phmap\n") < 0 || 465264562Sgshapiro fflush(pmap->ph_to_server) < 0 || 465364562Sgshapiro (server_data = ReadQi(pmap->ph_from_server, 465464562Sgshapiro &j)) == NULL || 465564562Sgshapiro server_data->code != 200) 465664562Sgshapiro { 465764562Sgshapiro save_errno = errno; 465864562Sgshapiro CloseQi(pmap->ph_to_server, 465964562Sgshapiro pmap->ph_from_server); 466064562Sgshapiro continue; 466164562Sgshapiro } 466264562Sgshapiro if (server_data != NULL) 466364562Sgshapiro FreeQIR(server_data); 466464562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 466564562Sgshapiro free(hostlist); 466664562Sgshapiro return TRUE; 466764562Sgshapiro } 466864562Sgshapiro#if _FFR_PHMAP_TIMEOUT 466964562Sgshapiro ph_map_open_abort: 467064562Sgshapiro if (ev != NULL) 467164562Sgshapiro clrevent(ev); 467264562Sgshapiro ph_map_safeclose(map); 467364562Sgshapiro if (server_data != NULL) 467464562Sgshapiro { 467564562Sgshapiro FreeQIR(server_data); 467664562Sgshapiro server_data = NULL; 467764562Sgshapiro } 467864562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 467964562Sgshapiro save_errno = errno; 468064562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 468164562Sgshapiro } while (tmp = strtok(NULL, " ")); 468264562Sgshapiro 468364562Sgshapiro#if !_FFR_PHMAP_TIMEOUT 468464562Sgshapiro errno = save_errno; 468564562Sgshapiro#endif /* !_FFR_PHMAP_TIMEOUT */ 468664562Sgshapiro if (!bitset(MF_OPTIONAL, map->map_mflags)) 468764562Sgshapiro { 468864562Sgshapiro if (errno == 0 && !bitset(MF_NODEFER,map->map_mflags)) 468964562Sgshapiro errno = EAGAIN; 469064562Sgshapiro syserr("ph_map_open: cannot connect to PH server"); 469164562Sgshapiro } 469264562Sgshapiro else if (LogLevel > 1) 469364562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 469464562Sgshapiro "ph_map_open: cannot connect to PH server"); 469564562Sgshapiro free(hostlist); 469664562Sgshapiro return FALSE; 469764562Sgshapiro} 469864562Sgshapiro 469964562Sgshapiro/* 470064562Sgshapiro** PH_MAP_LOOKUP -- look up key from ph server 470164562Sgshapiro*/ 470264562Sgshapiro 470364562Sgshapiro#if _FFR_PHMAP_TIMEOUT 470464562Sgshapiro# define MAX_PH_FIELDS 20 470564562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 470664562Sgshapiro 470764562Sgshapirochar * 470864562Sgshapiroph_map_lookup(map, key, args, pstat) 470964562Sgshapiro MAP *map; 471064562Sgshapiro char *key; 471164562Sgshapiro char **args; 471264562Sgshapiro int *pstat; 471364562Sgshapiro{ 471464562Sgshapiro int j; 471564562Sgshapiro size_t sz; 471664562Sgshapiro char *tmp, *tmp2; 471764562Sgshapiro char *message = NULL, *field = NULL, *fmtkey; 471864562Sgshapiro QIR *server_data = NULL; 471964562Sgshapiro QIR *qirp; 472064562Sgshapiro char keybuf[MAXKEY + 1], fieldbuf[101]; 472164562Sgshapiro#if _FFR_PHMAP_TIMEOUT 472264562Sgshapiro QIR *hold_data[MAX_PH_FIELDS]; 472364562Sgshapiro int hold_data_idx = 0; 472464562Sgshapiro register EVENT *ev = NULL; 472564562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 472664562Sgshapiro PH_MAP_STRUCT *pmap; 472764562Sgshapiro 472864562Sgshapiro pmap = (PH_MAP_STRUCT *)map->map_db1; 472964562Sgshapiro 473064562Sgshapiro *pstat = EX_OK; 473164562Sgshapiro 473264562Sgshapiro#if _FFR_PHMAP_TIMEOUT 473364562Sgshapiro if (pmap->ph_timeout != 0) 473464562Sgshapiro { 473564562Sgshapiro if (setjmp(PHTimeout) != 0) 473664562Sgshapiro { 473764562Sgshapiro ev = NULL; 473864562Sgshapiro if (LogLevel > 1) 473964562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 474064562Sgshapiro "timeout during PH lookup of %.100s", 474164562Sgshapiro key); 474264562Sgshapiro# ifdef ETIMEDOUT 474364562Sgshapiro errno = ETIMEDOUT; 474464562Sgshapiro# else /* ETIMEDOUT */ 474564562Sgshapiro errno = 0; 474664562Sgshapiro# endif /* ETIMEDOUT */ 474764562Sgshapiro *pstat = EX_TEMPFAIL; 474864562Sgshapiro goto ph_map_lookup_abort; 474964562Sgshapiro } 475064562Sgshapiro ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); 475164562Sgshapiro } 475264562Sgshapiro 475364562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 475464562Sgshapiro /* check all relevant fields */ 475564562Sgshapiro tmp = pmap->ph_field_list; 475664562Sgshapiro do 475764562Sgshapiro { 475864562Sgshapiro#if _FFR_PHMAP_TIMEOUT 475964562Sgshapiro server_data = NULL; 476064562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 476164562Sgshapiro while (isascii(*tmp) && isspace(*tmp)) 476264562Sgshapiro tmp++; 476364562Sgshapiro if (*tmp == '\0') 476464562Sgshapiro break; 476564562Sgshapiro sz = strcspn(tmp, " ") + 1; 476664562Sgshapiro if (sz > sizeof fieldbuf) 476764562Sgshapiro sz = sizeof fieldbuf; 476864562Sgshapiro (void) strlcpy(fieldbuf, tmp, sz); 476964562Sgshapiro field = fieldbuf; 477064562Sgshapiro tmp += sz; 477164562Sgshapiro 477264562Sgshapiro (void) strlcpy(keybuf, key, sizeof keybuf); 477364562Sgshapiro fmtkey = keybuf; 477464562Sgshapiro if (strcmp(field, "alias") == 0) 477564562Sgshapiro { 477664562Sgshapiro /* 477764562Sgshapiro ** for alias lookups, replace any punctuation 477864562Sgshapiro ** characters with '-' 477964562Sgshapiro */ 478064562Sgshapiro 478164562Sgshapiro for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) 478264562Sgshapiro { 478364562Sgshapiro if (isascii(*tmp2) && ispunct(*tmp2)) 478464562Sgshapiro *tmp2 = '-'; 478564562Sgshapiro } 478664562Sgshapiro tmp2 = field; 478764562Sgshapiro } 478864562Sgshapiro else if (strcmp(field,"spacedname") == 0) 478964562Sgshapiro { 479064562Sgshapiro /* 479164562Sgshapiro ** for "spaced" name lookups, replace any 479264562Sgshapiro ** punctuation characters with a space 479364562Sgshapiro */ 479464562Sgshapiro 479564562Sgshapiro for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) 479664562Sgshapiro { 479764562Sgshapiro if (isascii(*tmp2) && ispunct(*tmp2) && 479864562Sgshapiro *tmp2 != '*') 479964562Sgshapiro *tmp2 = ' '; 480064562Sgshapiro } 480164562Sgshapiro tmp2 = &(field[6]); 480264562Sgshapiro } 480364562Sgshapiro else 480464562Sgshapiro tmp2 = field; 480564562Sgshapiro 480664562Sgshapiro if (LogLevel > 9) 480764562Sgshapiro sm_syslog(LOG_NOTICE, CurEnv->e_id, 480864562Sgshapiro "ph_map_lookup: query %s=\"%s\" return email", 480964562Sgshapiro tmp2, fmtkey); 481064562Sgshapiro if (tTd(38, 20)) 481164562Sgshapiro dprintf("ph_map_lookup: query %s=\"%s\" return email\n", 481264562Sgshapiro tmp2, fmtkey); 481364562Sgshapiro 481464562Sgshapiro j = 0; 481564562Sgshapiro 481664562Sgshapiro if (fprintf(pmap->ph_to_server, "query %s=%s return email\n", 481764562Sgshapiro tmp2, fmtkey) < 0) 481864562Sgshapiro message = "qi query command failed"; 481964562Sgshapiro else if (fflush(pmap->ph_to_server) < 0) 482064562Sgshapiro message = "qi fflush failed"; 482164562Sgshapiro else if ((server_data = ReadQi(pmap->ph_from_server, 482264562Sgshapiro &j)) == NULL) 482364562Sgshapiro message = "ReadQi() returned NULL"; 482464562Sgshapiro 482564562Sgshapiro#if _FFR_PHMAP_TIMEOUT 482664562Sgshapiro if ((hold_data[hold_data_idx] = server_data) != NULL) 482764562Sgshapiro { 482864562Sgshapiro /* save pointer for later free() */ 482964562Sgshapiro hold_data_idx++; 483064562Sgshapiro } 483164562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 483264562Sgshapiro 483364562Sgshapiro if (server_data == NULL || 483464562Sgshapiro (server_data->code >= 400 && 483564562Sgshapiro server_data->code < 500)) 483664562Sgshapiro { 483764562Sgshapiro /* temporary failure */ 483864562Sgshapiro *pstat = EX_TEMPFAIL; 483964562Sgshapiro#if _FFR_PHMAP_TIMEOUT 484064562Sgshapiro break; 484164562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 484264562Sgshapiro if (server_data != NULL) 484364562Sgshapiro { 484464562Sgshapiro FreeQIR(server_data); 484564562Sgshapiro server_data = NULL; 484664562Sgshapiro } 484764562Sgshapiro return NULL; 484864562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 484964562Sgshapiro } 485064562Sgshapiro 485164562Sgshapiro /* 485264562Sgshapiro ** if we found a single match, break out. 485364562Sgshapiro ** otherwise, try the next field. 485464562Sgshapiro */ 485564562Sgshapiro 485664562Sgshapiro if (j == 1) 485764562Sgshapiro break; 485864562Sgshapiro 485964562Sgshapiro /* 486064562Sgshapiro ** check for a single response which is an error: 486164562Sgshapiro ** ReadQi() doesn't set j on error responses, 486264562Sgshapiro ** but we should stop here instead of moving on if 486364562Sgshapiro ** it happens (e.g., alias found but email field empty) 486464562Sgshapiro */ 486564562Sgshapiro 486664562Sgshapiro for (qirp = server_data; 486764562Sgshapiro qirp != NULL && qirp->code < 0; 486864562Sgshapiro qirp++) 486964562Sgshapiro { 487064562Sgshapiro if (tTd(38, 20)) 487164562Sgshapiro dprintf("ph_map_lookup: QIR: %d:%d:%d:%s\n", 487264562Sgshapiro qirp->code, qirp->subcode, qirp->field, 487364562Sgshapiro (qirp->message ? qirp->message 487464562Sgshapiro : "[NULL]")); 487564562Sgshapiro if (qirp->code <= -500) 487664562Sgshapiro { 487764562Sgshapiro j = 0; 487864562Sgshapiro goto ph_map_lookup_abort; 487964562Sgshapiro } 488064562Sgshapiro } 488164562Sgshapiro 488264562Sgshapiro#if _FFR_PHMAP_TIMEOUT 488364562Sgshapiro } while (*tmp != '\0' && hold_data_idx < MAX_PH_FIELDS); 488464562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 488564562Sgshapiro } while (*tmp != '\0'); 488664562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 488764562Sgshapiro 488864562Sgshapiro ph_map_lookup_abort: 488964562Sgshapiro#if _FFR_PHMAP_TIMEOUT 489064562Sgshapiro if (ev != NULL) 489164562Sgshapiro clrevent(ev); 489264562Sgshapiro 489364562Sgshapiro /* 489464562Sgshapiro ** Return EX_TEMPFAIL if the timer popped 489564562Sgshapiro ** or we got a temporary PH error 489664562Sgshapiro */ 489764562Sgshapiro 489864562Sgshapiro if (*pstat == EX_TEMPFAIL) 489964562Sgshapiro ph_map_safeclose(map); 490064562Sgshapiro 490164562Sgshapiro /* if we didn't find a single match, bail out */ 490264562Sgshapiro if (*pstat == EX_OK && j != 1) 490364562Sgshapiro *pstat = EX_UNAVAILABLE; 490464562Sgshapiro 490564562Sgshapiro if (*pstat == EX_OK) 490664562Sgshapiro { 490764562Sgshapiro /* 490864562Sgshapiro ** skip leading whitespace and chop at first address 490964562Sgshapiro */ 491064562Sgshapiro 491164562Sgshapiro for (tmp = server_data->message; 491264562Sgshapiro isascii(*tmp) && isspace(*tmp); 491364562Sgshapiro tmp++) 491464562Sgshapiro continue; 491564562Sgshapiro 491664562Sgshapiro for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) 491764562Sgshapiro { 491864562Sgshapiro if (isascii(*tmp2) && isspace(*tmp2)) 491964562Sgshapiro { 492064562Sgshapiro *tmp2 = '\0'; 492164562Sgshapiro break; 492264562Sgshapiro } 492364562Sgshapiro } 492464562Sgshapiro 492564562Sgshapiro if (tTd(38,20)) 492664562Sgshapiro dprintf("ph_map_lookup: %s => %s\n", key, tmp); 492764562Sgshapiro 492864562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 492964562Sgshapiro message = map_rewrite(map, key, strlen(key), NULL); 493064562Sgshapiro else 493164562Sgshapiro message = map_rewrite(map, tmp, strlen(tmp), args); 493264562Sgshapiro } 493364562Sgshapiro 493464562Sgshapiro /* 493564562Sgshapiro ** Deferred free() of returned server_data values 493664562Sgshapiro ** the deferral is to avoid the risk of a free() being 493764562Sgshapiro ** interrupted by the event timer. By now the timeout event 493864562Sgshapiro ** has been cleared and none of the data is still in use. 493964562Sgshapiro */ 494064562Sgshapiro 494164562Sgshapiro while (--hold_data_idx >= 0) 494264562Sgshapiro { 494364562Sgshapiro if (hold_data[hold_data_idx] != NULL) 494464562Sgshapiro FreeQIR(hold_data[hold_data_idx]); 494564562Sgshapiro } 494664562Sgshapiro 494764562Sgshapiro if (*pstat == EX_OK) 494864562Sgshapiro return message; 494964562Sgshapiro 495064562Sgshapiro return NULL; 495164562Sgshapiro#else /* _FFR_PHMAP_TIMEOUT */ 495264562Sgshapiro /* if we didn't find a single match, bail out */ 495364562Sgshapiro if (j != 1) 495464562Sgshapiro { 495564562Sgshapiro *pstat = EX_UNAVAILABLE; 495664562Sgshapiro if (server_data != NULL) 495764562Sgshapiro { 495864562Sgshapiro FreeQIR(server_data); 495964562Sgshapiro server_data = NULL; 496064562Sgshapiro } 496164562Sgshapiro return NULL; 496264562Sgshapiro } 496364562Sgshapiro 496464562Sgshapiro /* 496564562Sgshapiro ** skip leading whitespace and chop at first address 496664562Sgshapiro */ 496764562Sgshapiro 496864562Sgshapiro for (tmp = server_data->message; 496964562Sgshapiro isascii(*tmp) && isspace(*tmp); 497064562Sgshapiro tmp++) 497164562Sgshapiro continue; 497264562Sgshapiro 497364562Sgshapiro for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) 497464562Sgshapiro { 497564562Sgshapiro if (isascii(*tmp2) && isspace(*tmp2)) 497664562Sgshapiro { 497764562Sgshapiro *tmp2 = '\0'; 497864562Sgshapiro break; 497964562Sgshapiro } 498064562Sgshapiro } 498164562Sgshapiro 498264562Sgshapiro if (tTd(38,20)) 498364562Sgshapiro dprintf("ph_map_lookup: %s => %s\n", key, tmp); 498464562Sgshapiro 498564562Sgshapiro if (bitset(MF_MATCHONLY, map->map_mflags)) 498664562Sgshapiro message = map_rewrite(map, key, strlen(key), NULL); 498764562Sgshapiro else 498864562Sgshapiro message = map_rewrite(map, tmp, strlen(tmp), args); 498964562Sgshapiro if (server_data != NULL) 499064562Sgshapiro { 499164562Sgshapiro FreeQIR(server_data); 499264562Sgshapiro server_data = NULL; 499364562Sgshapiro } 499464562Sgshapiro return message; 499564562Sgshapiro#endif /* _FFR_PHMAP_TIMEOUT */ 499664562Sgshapiro} 499764562Sgshapiro#endif /* PH_MAP */ 499864562Sgshapiro/* 499942575Speter** syslog map 500038032Speter*/ 500138032Speter 500238032Speter#define map_prio map_lockfd /* overload field */ 500338032Speter 500438032Speter/* 500542575Speter** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 500638032Speter*/ 500738032Speter 500838032Speterbool 500938032Spetersyslog_map_parseargs(map, args) 501038032Speter MAP *map; 501138032Speter char *args; 501238032Speter{ 501338032Speter char *p = args; 501438032Speter char *priority = NULL; 501538032Speter 501664562Sgshapiro /* there is no check whether there is really an argument */ 501764562Sgshapiro while (*p != '\0') 501838032Speter { 501938032Speter while (isascii(*p) && isspace(*p)) 502038032Speter p++; 502138032Speter if (*p != '-') 502238032Speter break; 502364562Sgshapiro ++p; 502464562Sgshapiro if (*p == 'D') 502564562Sgshapiro { 502664562Sgshapiro map->map_mflags |= MF_DEFER; 502764562Sgshapiro ++p; 502864562Sgshapiro } 502964562Sgshapiro else if (*p == 'S') 503064562Sgshapiro { 503164562Sgshapiro map->map_spacesub = *++p; 503264562Sgshapiro if (*p != '\0') 503364562Sgshapiro p++; 503464562Sgshapiro } 503564562Sgshapiro else if (*p == 'L') 503664562Sgshapiro { 503764562Sgshapiro while (*++p != '\0' && isascii(*p) && isspace(*p)) 503864562Sgshapiro continue; 503964562Sgshapiro if (*p == '\0') 504064562Sgshapiro break; 504164562Sgshapiro priority = p; 504264562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 504364562Sgshapiro p++; 504464562Sgshapiro if (*p != '\0') 504564562Sgshapiro *p++ = '\0'; 504664562Sgshapiro } 504764562Sgshapiro else 504864562Sgshapiro { 504964562Sgshapiro syserr("Illegal option %c map syslog", *p); 505064562Sgshapiro ++p; 505164562Sgshapiro } 505238032Speter } 505338032Speter 505438032Speter if (priority == NULL) 505538032Speter map->map_prio = LOG_INFO; 505638032Speter else 505738032Speter { 505838032Speter if (strncasecmp("LOG_", priority, 4) == 0) 505938032Speter priority += 4; 506038032Speter 506138032Speter#ifdef LOG_EMERG 506238032Speter if (strcasecmp("EMERG", priority) == 0) 506338032Speter map->map_prio = LOG_EMERG; 506438032Speter else 506564562Sgshapiro#endif /* LOG_EMERG */ 506638032Speter#ifdef LOG_ALERT 506738032Speter if (strcasecmp("ALERT", priority) == 0) 506838032Speter map->map_prio = LOG_ALERT; 506938032Speter else 507064562Sgshapiro#endif /* LOG_ALERT */ 507138032Speter#ifdef LOG_CRIT 507238032Speter if (strcasecmp("CRIT", priority) == 0) 507338032Speter map->map_prio = LOG_CRIT; 507438032Speter else 507564562Sgshapiro#endif /* LOG_CRIT */ 507638032Speter#ifdef LOG_ERR 507738032Speter if (strcasecmp("ERR", priority) == 0) 507838032Speter map->map_prio = LOG_ERR; 507938032Speter else 508064562Sgshapiro#endif /* LOG_ERR */ 508138032Speter#ifdef LOG_WARNING 508238032Speter if (strcasecmp("WARNING", priority) == 0) 508338032Speter map->map_prio = LOG_WARNING; 508438032Speter else 508564562Sgshapiro#endif /* LOG_WARNING */ 508638032Speter#ifdef LOG_NOTICE 508738032Speter if (strcasecmp("NOTICE", priority) == 0) 508838032Speter map->map_prio = LOG_NOTICE; 508938032Speter else 509064562Sgshapiro#endif /* LOG_NOTICE */ 509138032Speter#ifdef LOG_INFO 509238032Speter if (strcasecmp("INFO", priority) == 0) 509338032Speter map->map_prio = LOG_INFO; 509438032Speter else 509564562Sgshapiro#endif /* LOG_INFO */ 509638032Speter#ifdef LOG_DEBUG 509738032Speter if (strcasecmp("DEBUG", priority) == 0) 509838032Speter map->map_prio = LOG_DEBUG; 509938032Speter else 510064562Sgshapiro#endif /* LOG_DEBUG */ 510138032Speter { 510238032Speter syserr("syslog_map_parseargs: Unknown priority %s\n", 510338032Speter priority); 510438032Speter return FALSE; 510538032Speter } 510638032Speter } 510738032Speter return TRUE; 510838032Speter} 510938032Speter 511038032Speter/* 511142575Speter** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 511238032Speter*/ 511338032Speter 511438032Speterchar * 511538032Spetersyslog_map_lookup(map, string, args, statp) 511638032Speter MAP *map; 511738032Speter char *string; 511838032Speter char **args; 511938032Speter int *statp; 512038032Speter{ 512138032Speter char *ptr = map_rewrite(map, string, strlen(string), args); 512238032Speter 512338032Speter if (ptr != NULL) 512438032Speter { 512538032Speter if (tTd(38, 20)) 512664562Sgshapiro dprintf("syslog_map_lookup(%s (priority %d): %s\n", 512764562Sgshapiro map->map_mname, map->map_prio, ptr); 512838032Speter 512938032Speter sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 513038032Speter } 513138032Speter 513238032Speter *statp = EX_OK; 513338032Speter return ""; 513438032Speter} 513538032Speter 513638032Speter/* 513738032Speter** HESIOD Modules 513838032Speter*/ 513938032Speter 514038032Speter#ifdef HESIOD 514138032Speter 514238032Speterbool 514338032Speterhes_map_open(map, mode) 514438032Speter MAP *map; 514538032Speter int mode; 514638032Speter{ 514738032Speter if (tTd(38, 2)) 514864562Sgshapiro dprintf("hes_map_open(%s, %s, %d)\n", 514938032Speter map->map_mname, map->map_file, mode); 515038032Speter 515138032Speter if (mode != O_RDONLY) 515238032Speter { 515338032Speter /* issue a pseudo-error message */ 515464562Sgshapiro# ifdef ENOSYS 515538032Speter errno = ENOSYS; 515664562Sgshapiro# else /* ENOSYS */ 515764562Sgshapiro# ifdef EFTYPE 515838032Speter errno = EFTYPE; 515964562Sgshapiro# else /* EFTYPE */ 516038032Speter errno = ENXIO; 516164562Sgshapiro# endif /* EFTYPE */ 516264562Sgshapiro# endif /* ENOSYS */ 516338032Speter return FALSE; 516438032Speter } 516538032Speter 516664562Sgshapiro# ifdef HESIOD_INIT 516738032Speter if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 516838032Speter return TRUE; 516938032Speter 517038032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 517164562Sgshapiro syserr("421 4.0.0 cannot initialize Hesiod map (%s)", 517238032Speter errstring(errno)); 517338032Speter return FALSE; 517464562Sgshapiro# else /* HESIOD_INIT */ 517538032Speter if (hes_error() == HES_ER_UNINIT) 517638032Speter hes_init(); 517738032Speter switch (hes_error()) 517838032Speter { 517938032Speter case HES_ER_OK: 518038032Speter case HES_ER_NOTFOUND: 518138032Speter return TRUE; 518238032Speter } 518338032Speter 518438032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 518564562Sgshapiro syserr("421 4.0.0 cannot initialize Hesiod map (%d)", hes_error()); 518638032Speter 518738032Speter return FALSE; 518864562Sgshapiro# endif /* HESIOD_INIT */ 518938032Speter} 519038032Speter 519138032Speterchar * 519238032Speterhes_map_lookup(map, name, av, statp) 519338032Speter MAP *map; 519438032Speter char *name; 519538032Speter char **av; 519638032Speter int *statp; 519738032Speter{ 519838032Speter char **hp; 519938032Speter 520038032Speter if (tTd(38, 20)) 520164562Sgshapiro dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 520238032Speter 520338032Speter if (name[0] == '\\') 520438032Speter { 520538032Speter char *np; 520638032Speter int nl; 520738032Speter char nbuf[MAXNAME]; 520838032Speter 520938032Speter nl = strlen(name); 521038032Speter if (nl < sizeof nbuf - 1) 521138032Speter np = nbuf; 521238032Speter else 521338032Speter np = xalloc(strlen(name) + 2); 521438032Speter np[0] = '\\'; 521564562Sgshapiro (void) strlcpy(&np[1], name, (sizeof nbuf) - 1); 521664562Sgshapiro# ifdef HESIOD_INIT 521738032Speter hp = hesiod_resolve(HesiodContext, np, map->map_file); 521864562Sgshapiro# else /* HESIOD_INIT */ 521938032Speter hp = hes_resolve(np, map->map_file); 522064562Sgshapiro# endif /* HESIOD_INIT */ 522138032Speter if (np != nbuf) 522238032Speter free(np); 522338032Speter } 522438032Speter else 522538032Speter { 522664562Sgshapiro# ifdef HESIOD_INIT 522738032Speter hp = hesiod_resolve(HesiodContext, name, map->map_file); 522864562Sgshapiro# else /* HESIOD_INIT */ 522938032Speter hp = hes_resolve(name, map->map_file); 523064562Sgshapiro# endif /* HESIOD_INIT */ 523138032Speter } 523264562Sgshapiro# ifdef HESIOD_INIT 523338032Speter if (hp == NULL) 523438032Speter return NULL; 523538032Speter if (*hp == NULL) 523638032Speter { 523738032Speter hesiod_free_list(HesiodContext, hp); 523838032Speter switch (errno) 523938032Speter { 524038032Speter case ENOENT: 524138032Speter *statp = EX_NOTFOUND; 524238032Speter break; 524338032Speter case ECONNREFUSED: 524438032Speter case EMSGSIZE: 524538032Speter *statp = EX_TEMPFAIL; 524638032Speter break; 524738032Speter case ENOMEM: 524838032Speter default: 524938032Speter *statp = EX_UNAVAILABLE; 525038032Speter break; 525138032Speter } 525238032Speter return NULL; 525338032Speter } 525464562Sgshapiro# else /* HESIOD_INIT */ 525538032Speter if (hp == NULL || hp[0] == NULL) 525638032Speter { 525738032Speter switch (hes_error()) 525838032Speter { 525938032Speter case HES_ER_OK: 526038032Speter *statp = EX_OK; 526138032Speter break; 526238032Speter 526338032Speter case HES_ER_NOTFOUND: 526438032Speter *statp = EX_NOTFOUND; 526538032Speter break; 526638032Speter 526738032Speter case HES_ER_CONFIG: 526838032Speter *statp = EX_UNAVAILABLE; 526938032Speter break; 527038032Speter 527138032Speter case HES_ER_NET: 527238032Speter *statp = EX_TEMPFAIL; 527338032Speter break; 527438032Speter } 527538032Speter return NULL; 527638032Speter } 527764562Sgshapiro# endif /* HESIOD_INIT */ 527838032Speter 527938032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 528038032Speter return map_rewrite(map, name, strlen(name), NULL); 528138032Speter else 528238032Speter return map_rewrite(map, hp[0], strlen(hp[0]), av); 528338032Speter} 528438032Speter 528564562Sgshapiro#endif /* HESIOD */ 528638032Speter/* 528738032Speter** NeXT NETINFO Modules 528838032Speter*/ 528938032Speter 529038032Speter#if NETINFO 529138032Speter 529238032Speter# define NETINFO_DEFAULT_DIR "/aliases" 529338032Speter# define NETINFO_DEFAULT_PROPERTY "members" 529438032Speter 529538032Speter/* 529638032Speter** NI_MAP_OPEN -- open NetInfo Aliases 529738032Speter*/ 529838032Speter 529938032Speterbool 530038032Speterni_map_open(map, mode) 530138032Speter MAP *map; 530238032Speter int mode; 530338032Speter{ 530438032Speter if (tTd(38, 2)) 530564562Sgshapiro dprintf("ni_map_open(%s, %s, %d)\n", 530638032Speter map->map_mname, map->map_file, mode); 530738032Speter mode &= O_ACCMODE; 530838032Speter 530938032Speter if (*map->map_file == '\0') 531038032Speter map->map_file = NETINFO_DEFAULT_DIR; 531138032Speter 531238032Speter if (map->map_valcolnm == NULL) 531338032Speter map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 531438032Speter 531538032Speter if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) 531638032Speter map->map_coldelim = ','; 531738032Speter 531838032Speter return TRUE; 531938032Speter} 532038032Speter 532138032Speter 532238032Speter/* 532338032Speter** NI_MAP_LOOKUP -- look up a datum in NetInfo 532438032Speter*/ 532538032Speter 532638032Speterchar * 532738032Speterni_map_lookup(map, name, av, statp) 532838032Speter MAP *map; 532938032Speter char *name; 533038032Speter char **av; 533138032Speter int *statp; 533238032Speter{ 533338032Speter char *res; 533438032Speter char *propval; 533538032Speter 533638032Speter if (tTd(38, 20)) 533764562Sgshapiro dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 533838032Speter 533938032Speter propval = ni_propval(map->map_file, map->map_keycolnm, name, 534038032Speter map->map_valcolnm, map->map_coldelim); 534138032Speter 534238032Speter if (propval == NULL) 534338032Speter return NULL; 534438032Speter 534538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 534638032Speter res = map_rewrite(map, name, strlen(name), NULL); 534738032Speter else 534838032Speter res = map_rewrite(map, propval, strlen(propval), av); 534938032Speter free(propval); 535038032Speter return res; 535138032Speter} 535238032Speter 535338032Speter 535464562Sgshapirostatic bool 535538032Speterni_getcanonname(name, hbsize, statp) 535638032Speter char *name; 535738032Speter int hbsize; 535838032Speter int *statp; 535938032Speter{ 536038032Speter char *vptr; 536138032Speter char *ptr; 536238032Speter char nbuf[MAXNAME + 1]; 536338032Speter 536438032Speter if (tTd(38, 20)) 536564562Sgshapiro dprintf("ni_getcanonname(%s)\n", name); 536638032Speter 536764562Sgshapiro if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 536838032Speter { 536938032Speter *statp = EX_UNAVAILABLE; 537038032Speter return FALSE; 537138032Speter } 537238032Speter shorten_hostname(nbuf); 537338032Speter 537438032Speter /* we only accept single token search key */ 537538032Speter if (strchr(nbuf, '.')) 537638032Speter { 537738032Speter *statp = EX_NOHOST; 537838032Speter return FALSE; 537938032Speter } 538038032Speter 538138032Speter /* Do the search */ 538238032Speter vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 538338032Speter 538438032Speter if (vptr == NULL) 538538032Speter { 538638032Speter *statp = EX_NOHOST; 538738032Speter return FALSE; 538838032Speter } 538938032Speter 539038032Speter /* Only want the first machine name */ 539138032Speter if ((ptr = strchr(vptr, '\n')) != NULL) 539238032Speter *ptr = '\0'; 539338032Speter 539438032Speter if (hbsize >= strlen(vptr)) 539538032Speter { 539664562Sgshapiro (void) strlcpy(name, vptr, hbsize); 539764562Sgshapiro free(vptr); 539838032Speter *statp = EX_OK; 539938032Speter return TRUE; 540038032Speter } 540138032Speter *statp = EX_UNAVAILABLE; 540238032Speter free(vptr); 540338032Speter return FALSE; 540438032Speter} 540538032Speter 540638032Speter 540738032Speter/* 540838032Speter** NI_PROPVAL -- NetInfo property value lookup routine 540938032Speter** 541038032Speter** Parameters: 541138032Speter** keydir -- the NetInfo directory name in which to search 541238032Speter** for the key. 541338032Speter** keyprop -- the name of the property in which to find the 541438032Speter** property we are interested. Defaults to "name". 541538032Speter** keyval -- the value for which we are really searching. 541638032Speter** valprop -- the property name for the value in which we 541738032Speter** are interested. 541838032Speter** sepchar -- if non-nil, this can be multiple-valued, and 541938032Speter** we should return a string separated by this 542038032Speter** character. 542138032Speter** 542238032Speter** Returns: 542338032Speter** NULL -- if: 542438032Speter** 1. the directory is not found 542538032Speter** 2. the property name is not found 542638032Speter** 3. the property contains multiple values 542764562Sgshapiro** 4. some error occurred 542838032Speter** else -- the value of the lookup. 542938032Speter** 543038032Speter** Example: 543138032Speter** To search for an alias value, use: 543238032Speter** ni_propval("/aliases", "name", aliasname, "members", ',') 543338032Speter** 543438032Speter** Notes: 543564562Sgshapiro** Caller should free the return value of ni_proval 543638032Speter*/ 543738032Speter 543838032Speter# include <netinfo/ni.h> 543938032Speter 544064562Sgshapiro# define LOCAL_NETINFO_DOMAIN "." 544164562Sgshapiro# define PARENT_NETINFO_DOMAIN ".." 544264562Sgshapiro# define MAX_NI_LEVELS 256 544338032Speter 544438032Speterchar * 544538032Speterni_propval(keydir, keyprop, keyval, valprop, sepchar) 544638032Speter char *keydir; 544738032Speter char *keyprop; 544838032Speter char *keyval; 544938032Speter char *valprop; 545038032Speter int sepchar; 545138032Speter{ 545238032Speter char *propval = NULL; 545338032Speter int i; 545464562Sgshapiro int j, alen, l; 545538032Speter void *ni = NULL; 545638032Speter void *lastni = NULL; 545738032Speter ni_status nis; 545838032Speter ni_id nid; 545938032Speter ni_namelist ninl; 546038032Speter register char *p; 546138032Speter char keybuf[1024]; 546238032Speter 546338032Speter /* 546438032Speter ** Create the full key from the two parts. 546538032Speter ** 546638032Speter ** Note that directory can end with, e.g., "name=" to specify 546738032Speter ** an alternate search property. 546838032Speter */ 546938032Speter 547038032Speter i = strlen(keydir) + strlen(keyval) + 2; 547138032Speter if (keyprop != NULL) 547238032Speter i += strlen(keyprop) + 1; 547364562Sgshapiro if (i >= sizeof keybuf) 547438032Speter return NULL; 547564562Sgshapiro (void) strlcpy(keybuf, keydir, sizeof keybuf); 547664562Sgshapiro (void) strlcat(keybuf, "/", sizeof keybuf); 547738032Speter if (keyprop != NULL) 547838032Speter { 547964562Sgshapiro (void) strlcat(keybuf, keyprop, sizeof keybuf); 548064562Sgshapiro (void) strlcat(keybuf, "=", sizeof keybuf); 548138032Speter } 548264562Sgshapiro (void) strlcat(keybuf, keyval, sizeof keybuf); 548338032Speter 548438032Speter if (tTd(38, 21)) 548564562Sgshapiro dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", 548638032Speter keydir, keyprop, keyval, valprop, sepchar, keybuf); 548738032Speter /* 548838032Speter ** If the passed directory and property name are found 548938032Speter ** in one of netinfo domains we need to search (starting 549038032Speter ** from the local domain moving all the way back to the 549138032Speter ** root domain) set propval to the property's value 549238032Speter ** and return it. 549338032Speter */ 549438032Speter 549538032Speter for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) 549638032Speter { 549738032Speter if (i == 0) 549838032Speter { 549938032Speter nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 550038032Speter if (tTd(38, 20)) 550164562Sgshapiro dprintf("ni_open(LOCAL) = %d\n", nis); 550238032Speter } 550338032Speter else 550438032Speter { 550538032Speter if (lastni != NULL) 550638032Speter ni_free(lastni); 550738032Speter lastni = ni; 550838032Speter nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 550938032Speter if (tTd(38, 20)) 551064562Sgshapiro dprintf("ni_open(PARENT) = %d\n", nis); 551138032Speter } 551238032Speter 551338032Speter /* 551438032Speter ** Don't bother if we didn't get a handle on a 551538032Speter ** proper domain. This is not necessarily an error. 551638032Speter ** We would get a positive ni_status if, for instance 551738032Speter ** we never found the directory or property and tried 551838032Speter ** to open the parent of the root domain! 551938032Speter */ 552038032Speter 552138032Speter if (nis != 0) 552238032Speter break; 552338032Speter 552438032Speter /* 552538032Speter ** Find the path to the server information. 552638032Speter */ 552738032Speter 552838032Speter if (ni_pathsearch(ni, &nid, keybuf) != 0) 552938032Speter continue; 553038032Speter 553138032Speter /* 553238032Speter ** Find associated value information. 553338032Speter */ 553438032Speter 553538032Speter if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 553638032Speter continue; 553738032Speter 553838032Speter if (tTd(38, 20)) 553964562Sgshapiro dprintf("ni_lookupprop: len=%d\n", 554064562Sgshapiro ninl.ni_namelist_len); 554164562Sgshapiro 554238032Speter /* 554338032Speter ** See if we have an acceptable number of values. 554438032Speter */ 554538032Speter 554638032Speter if (ninl.ni_namelist_len <= 0) 554738032Speter continue; 554838032Speter 554938032Speter if (sepchar == '\0' && ninl.ni_namelist_len > 1) 555038032Speter { 555138032Speter ni_namelist_free(&ninl); 555238032Speter continue; 555338032Speter } 555438032Speter 555538032Speter /* 555638032Speter ** Calculate number of bytes needed and build result 555738032Speter */ 555838032Speter 555938032Speter alen = 1; 556038032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 556138032Speter alen += strlen(ninl.ni_namelist_val[j]) + 1; 556238032Speter propval = p = xalloc(alen); 556338032Speter for (j = 0; j < ninl.ni_namelist_len; j++) 556438032Speter { 556564562Sgshapiro (void) strlcpy(p, ninl.ni_namelist_val[j], alen); 556664562Sgshapiro l = strlen(p); 556764562Sgshapiro p += l; 556838032Speter *p++ = sepchar; 556964562Sgshapiro alen -= l + 1; 557038032Speter } 557138032Speter *--p = '\0'; 557238032Speter 557338032Speter ni_namelist_free(&ninl); 557438032Speter } 557538032Speter 557638032Speter /* 557738032Speter ** Clean up. 557838032Speter */ 557938032Speter 558038032Speter if (ni != NULL) 558138032Speter ni_free(ni); 558238032Speter if (lastni != NULL && ni != lastni) 558338032Speter ni_free(lastni); 558438032Speter if (tTd(38, 20)) 558564562Sgshapiro dprintf("ni_propval returns: '%s'\n", propval); 558638032Speter 558738032Speter return propval; 558838032Speter} 558938032Speter 559042575Speter#endif /* NETINFO */ 559138032Speter/* 559238032Speter** TEXT (unindexed text file) Modules 559338032Speter** 559438032Speter** This code donated by Sun Microsystems. 559538032Speter*/ 559638032Speter 559738032Speter#define map_sff map_lockfd /* overload field */ 559838032Speter 559938032Speter 560038032Speter/* 560138032Speter** TEXT_MAP_OPEN -- open text table 560238032Speter*/ 560338032Speter 560438032Speterbool 560538032Spetertext_map_open(map, mode) 560638032Speter MAP *map; 560738032Speter int mode; 560838032Speter{ 560964562Sgshapiro long sff; 561038032Speter int i; 561138032Speter 561238032Speter if (tTd(38, 2)) 561364562Sgshapiro dprintf("text_map_open(%s, %s, %d)\n", 561438032Speter map->map_mname, map->map_file, mode); 561538032Speter 561638032Speter mode &= O_ACCMODE; 561738032Speter if (mode != O_RDONLY) 561838032Speter { 561938032Speter errno = EPERM; 562038032Speter return FALSE; 562138032Speter } 562238032Speter 562338032Speter if (*map->map_file == '\0') 562438032Speter { 562538032Speter syserr("text map \"%s\": file name required", 562638032Speter map->map_mname); 562738032Speter return FALSE; 562838032Speter } 562938032Speter 563038032Speter if (map->map_file[0] != '/') 563138032Speter { 563238032Speter syserr("text map \"%s\": file name must be fully qualified", 563338032Speter map->map_mname); 563438032Speter return FALSE; 563538032Speter } 563638032Speter 563738032Speter sff = SFF_ROOTOK|SFF_REGONLY; 563864562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 563938032Speter sff |= SFF_NOWLINK; 564064562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 564138032Speter sff |= SFF_SAFEDIRPATH; 564238032Speter if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 564338032Speter sff, S_IRUSR, NULL)) != 0) 564438032Speter { 564564562Sgshapiro int save_errno = errno; 564664562Sgshapiro 564738032Speter /* cannot open this map */ 564838032Speter if (tTd(38, 2)) 564964562Sgshapiro dprintf("\tunsafe map file: %d\n", i); 565064562Sgshapiro errno = save_errno; 565138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 565238032Speter syserr("text map \"%s\": unsafe map file %s", 565338032Speter map->map_mname, map->map_file); 565438032Speter return FALSE; 565538032Speter } 565638032Speter 565738032Speter if (map->map_keycolnm == NULL) 565838032Speter map->map_keycolno = 0; 565938032Speter else 566038032Speter { 566138032Speter if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 566238032Speter { 566338032Speter syserr("text map \"%s\", file %s: -k should specify a number, not %s", 566438032Speter map->map_mname, map->map_file, 566538032Speter map->map_keycolnm); 566638032Speter return FALSE; 566738032Speter } 566838032Speter map->map_keycolno = atoi(map->map_keycolnm); 566938032Speter } 567038032Speter 567138032Speter if (map->map_valcolnm == NULL) 567238032Speter map->map_valcolno = 0; 567338032Speter else 567438032Speter { 567538032Speter if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 567638032Speter { 567738032Speter syserr("text map \"%s\", file %s: -v should specify a number, not %s", 567838032Speter map->map_mname, map->map_file, 567938032Speter map->map_valcolnm); 568038032Speter return FALSE; 568138032Speter } 568238032Speter map->map_valcolno = atoi(map->map_valcolnm); 568338032Speter } 568438032Speter 568538032Speter if (tTd(38, 2)) 568638032Speter { 568764562Sgshapiro dprintf("text_map_open(%s, %s): delimiter = ", 568838032Speter map->map_mname, map->map_file); 568938032Speter if (map->map_coldelim == '\0') 569064562Sgshapiro dprintf("(white space)\n"); 569138032Speter else 569264562Sgshapiro dprintf("%c\n", map->map_coldelim); 569338032Speter } 569438032Speter 569538032Speter map->map_sff = sff; 569638032Speter return TRUE; 569738032Speter} 569838032Speter 569938032Speter 570038032Speter/* 570138032Speter** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 570238032Speter*/ 570338032Speter 570438032Speterchar * 570538032Spetertext_map_lookup(map, name, av, statp) 570638032Speter MAP *map; 570738032Speter char *name; 570838032Speter char **av; 570938032Speter int *statp; 571038032Speter{ 571138032Speter char *vp; 571238032Speter auto int vsize; 571338032Speter int buflen; 571438032Speter FILE *f; 571538032Speter char delim; 571638032Speter int key_idx; 571738032Speter bool found_it; 571864562Sgshapiro long sff = map->map_sff; 571938032Speter char search_key[MAXNAME + 1]; 572038032Speter char linebuf[MAXLINE]; 572138032Speter char buf[MAXNAME + 1]; 572238032Speter 572338032Speter found_it = FALSE; 572438032Speter if (tTd(38, 20)) 572564562Sgshapiro dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 572638032Speter 572738032Speter buflen = strlen(name); 572838032Speter if (buflen > sizeof search_key - 1) 572938032Speter buflen = sizeof search_key - 1; 573064562Sgshapiro memmove(search_key, name, buflen); 573138032Speter search_key[buflen] = '\0'; 573238032Speter if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 573338032Speter makelower(search_key); 573438032Speter 573538032Speter f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 573638032Speter if (f == NULL) 573738032Speter { 573838032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 573938032Speter *statp = EX_UNAVAILABLE; 574038032Speter return NULL; 574138032Speter } 574238032Speter key_idx = map->map_keycolno; 574338032Speter delim = map->map_coldelim; 574438032Speter while (fgets(linebuf, MAXLINE, f) != NULL) 574538032Speter { 574638032Speter char *p; 574738032Speter 574838032Speter /* skip comment line */ 574938032Speter if (linebuf[0] == '#') 575038032Speter continue; 575138032Speter p = strchr(linebuf, '\n'); 575238032Speter if (p != NULL) 575338032Speter *p = '\0'; 575438032Speter p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 575538032Speter if (p != NULL && strcasecmp(search_key, p) == 0) 575638032Speter { 575738032Speter found_it = TRUE; 575838032Speter break; 575938032Speter } 576038032Speter } 576164562Sgshapiro (void) fclose(f); 576238032Speter if (!found_it) 576338032Speter { 576438032Speter *statp = EX_NOTFOUND; 576538032Speter return NULL; 576638032Speter } 576738032Speter vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 576842575Speter if (vp == NULL) 576942575Speter { 577042575Speter *statp = EX_NOTFOUND; 577142575Speter return NULL; 577242575Speter } 577338032Speter vsize = strlen(vp); 577438032Speter *statp = EX_OK; 577538032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 577638032Speter return map_rewrite(map, name, strlen(name), NULL); 577738032Speter else 577838032Speter return map_rewrite(map, vp, vsize, av); 577938032Speter} 578038032Speter 578138032Speter/* 578238032Speter** TEXT_GETCANONNAME -- look up canonical name in hosts file 578338032Speter*/ 578438032Speter 578564562Sgshapirostatic bool 578638032Spetertext_getcanonname(name, hbsize, statp) 578738032Speter char *name; 578838032Speter int hbsize; 578938032Speter int *statp; 579038032Speter{ 579138032Speter bool found; 579238032Speter FILE *f; 579338032Speter char linebuf[MAXLINE]; 579438032Speter char cbuf[MAXNAME + 1]; 579538032Speter char nbuf[MAXNAME + 1]; 579638032Speter 579738032Speter if (tTd(38, 20)) 579864562Sgshapiro dprintf("text_getcanonname(%s)\n", name); 579938032Speter 580038032Speter if (strlen(name) >= (SIZE_T) sizeof nbuf) 580138032Speter { 580238032Speter *statp = EX_UNAVAILABLE; 580338032Speter return FALSE; 580438032Speter } 580564562Sgshapiro (void) strlcpy(nbuf, name, sizeof nbuf); 580638032Speter shorten_hostname(nbuf); 580738032Speter 580838032Speter f = fopen(HostsFile, "r"); 580938032Speter if (f == NULL) 581038032Speter { 581138032Speter *statp = EX_UNAVAILABLE; 581238032Speter return FALSE; 581338032Speter } 581438032Speter found = FALSE; 581538032Speter while (!found && fgets(linebuf, MAXLINE, f) != NULL) 581638032Speter { 581738032Speter char *p = strpbrk(linebuf, "#\n"); 581838032Speter 581938032Speter if (p != NULL) 582038032Speter *p = '\0'; 582138032Speter if (linebuf[0] != '\0') 582238032Speter found = extract_canonname(nbuf, linebuf, cbuf, sizeof cbuf); 582338032Speter } 582464562Sgshapiro (void) fclose(f); 582538032Speter if (!found) 582638032Speter { 582738032Speter *statp = EX_NOHOST; 582838032Speter return FALSE; 582938032Speter } 583038032Speter 583138032Speter if ((SIZE_T) hbsize >= strlen(cbuf)) 583238032Speter { 583364562Sgshapiro (void) strlcpy(name, cbuf, hbsize); 583438032Speter *statp = EX_OK; 583538032Speter return TRUE; 583638032Speter } 583738032Speter *statp = EX_UNAVAILABLE; 583838032Speter return FALSE; 583938032Speter} 584038032Speter/* 584138032Speter** STAB (Symbol Table) Modules 584238032Speter*/ 584338032Speter 584438032Speter 584538032Speter/* 584638032Speter** STAB_MAP_LOOKUP -- look up alias in symbol table 584738032Speter*/ 584838032Speter 584938032Speter/* ARGSUSED2 */ 585038032Speterchar * 585138032Speterstab_map_lookup(map, name, av, pstat) 585238032Speter register MAP *map; 585338032Speter char *name; 585438032Speter char **av; 585538032Speter int *pstat; 585638032Speter{ 585738032Speter register STAB *s; 585838032Speter 585938032Speter if (tTd(38, 20)) 586064562Sgshapiro dprintf("stab_lookup(%s, %s)\n", 586138032Speter map->map_mname, name); 586238032Speter 586338032Speter s = stab(name, ST_ALIAS, ST_FIND); 586438032Speter if (s != NULL) 586564562Sgshapiro return s->s_alias; 586664562Sgshapiro return NULL; 586738032Speter} 586838032Speter 586938032Speter 587038032Speter/* 587138032Speter** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 587238032Speter*/ 587338032Speter 587438032Spetervoid 587538032Speterstab_map_store(map, lhs, rhs) 587638032Speter register MAP *map; 587738032Speter char *lhs; 587838032Speter char *rhs; 587938032Speter{ 588038032Speter register STAB *s; 588138032Speter 588238032Speter s = stab(lhs, ST_ALIAS, ST_ENTER); 588338032Speter s->s_alias = newstr(rhs); 588438032Speter} 588538032Speter 588638032Speter 588738032Speter/* 588838032Speter** STAB_MAP_OPEN -- initialize (reads data file) 588938032Speter** 589038032Speter** This is a wierd case -- it is only intended as a fallback for 589138032Speter** aliases. For this reason, opens for write (only during a 589238032Speter** "newaliases") always fails, and opens for read open the 589338032Speter** actual underlying text file instead of the database. 589438032Speter*/ 589538032Speter 589638032Speterbool 589738032Speterstab_map_open(map, mode) 589838032Speter register MAP *map; 589938032Speter int mode; 590038032Speter{ 590138032Speter FILE *af; 590264562Sgshapiro long sff; 590338032Speter struct stat st; 590438032Speter 590538032Speter if (tTd(38, 2)) 590664562Sgshapiro dprintf("stab_map_open(%s, %s, %d)\n", 590738032Speter map->map_mname, map->map_file, mode); 590838032Speter 590938032Speter mode &= O_ACCMODE; 591038032Speter if (mode != O_RDONLY) 591138032Speter { 591238032Speter errno = EPERM; 591338032Speter return FALSE; 591438032Speter } 591538032Speter 591638032Speter sff = SFF_ROOTOK|SFF_REGONLY; 591764562Sgshapiro if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 591838032Speter sff |= SFF_NOWLINK; 591964562Sgshapiro if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 592038032Speter sff |= SFF_SAFEDIRPATH; 592138032Speter af = safefopen(map->map_file, O_RDONLY, 0444, sff); 592238032Speter if (af == NULL) 592338032Speter return FALSE; 592438032Speter readaliases(map, af, FALSE, FALSE); 592538032Speter 592638032Speter if (fstat(fileno(af), &st) >= 0) 592738032Speter map->map_mtime = st.st_mtime; 592864562Sgshapiro (void) fclose(af); 592938032Speter 593038032Speter return TRUE; 593138032Speter} 593238032Speter/* 593338032Speter** Implicit Modules 593438032Speter** 593538032Speter** Tries several types. For back compatibility of aliases. 593638032Speter*/ 593738032Speter 593838032Speter 593938032Speter/* 594038032Speter** IMPL_MAP_LOOKUP -- lookup in best open database 594138032Speter*/ 594238032Speter 594338032Speterchar * 594438032Speterimpl_map_lookup(map, name, av, pstat) 594538032Speter MAP *map; 594638032Speter char *name; 594738032Speter char **av; 594838032Speter int *pstat; 594938032Speter{ 595038032Speter if (tTd(38, 20)) 595164562Sgshapiro dprintf("impl_map_lookup(%s, %s)\n", 595238032Speter map->map_mname, name); 595338032Speter 595438032Speter#ifdef NEWDB 595538032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 595638032Speter return db_map_lookup(map, name, av, pstat); 595764562Sgshapiro#endif /* NEWDB */ 595838032Speter#ifdef NDBM 595938032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 596038032Speter return ndbm_map_lookup(map, name, av, pstat); 596164562Sgshapiro#endif /* NDBM */ 596238032Speter return stab_map_lookup(map, name, av, pstat); 596338032Speter} 596438032Speter 596538032Speter/* 596638032Speter** IMPL_MAP_STORE -- store in open databases 596738032Speter*/ 596838032Speter 596938032Spetervoid 597038032Speterimpl_map_store(map, lhs, rhs) 597138032Speter MAP *map; 597238032Speter char *lhs; 597338032Speter char *rhs; 597438032Speter{ 597538032Speter if (tTd(38, 12)) 597664562Sgshapiro dprintf("impl_map_store(%s, %s, %s)\n", 597738032Speter map->map_mname, lhs, rhs); 597838032Speter#ifdef NEWDB 597938032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 598038032Speter db_map_store(map, lhs, rhs); 598164562Sgshapiro#endif /* NEWDB */ 598238032Speter#ifdef NDBM 598338032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 598438032Speter ndbm_map_store(map, lhs, rhs); 598564562Sgshapiro#endif /* NDBM */ 598638032Speter stab_map_store(map, lhs, rhs); 598738032Speter} 598838032Speter 598938032Speter/* 599038032Speter** IMPL_MAP_OPEN -- implicit database open 599138032Speter*/ 599238032Speter 599338032Speterbool 599438032Speterimpl_map_open(map, mode) 599538032Speter MAP *map; 599638032Speter int mode; 599738032Speter{ 599838032Speter if (tTd(38, 2)) 599964562Sgshapiro dprintf("impl_map_open(%s, %s, %d)\n", 600038032Speter map->map_mname, map->map_file, mode); 600138032Speter 600238032Speter mode &= O_ACCMODE; 600338032Speter#ifdef NEWDB 600438032Speter map->map_mflags |= MF_IMPL_HASH; 600538032Speter if (hash_map_open(map, mode)) 600638032Speter { 600738032Speter# ifdef NDBM_YP_COMPAT 600838032Speter if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 600964562Sgshapiro# endif /* NDBM_YP_COMPAT */ 601038032Speter return TRUE; 601138032Speter } 601238032Speter else 601338032Speter map->map_mflags &= ~MF_IMPL_HASH; 601464562Sgshapiro#endif /* NEWDB */ 601538032Speter#ifdef NDBM 601638032Speter map->map_mflags |= MF_IMPL_NDBM; 601738032Speter if (ndbm_map_open(map, mode)) 601838032Speter { 601938032Speter return TRUE; 602038032Speter } 602138032Speter else 602238032Speter map->map_mflags &= ~MF_IMPL_NDBM; 602364562Sgshapiro#endif /* NDBM */ 602438032Speter 602538032Speter#if defined(NEWDB) || defined(NDBM) 602638032Speter if (Verbose) 602738032Speter message("WARNING: cannot open alias database %s%s", 602838032Speter map->map_file, 602938032Speter mode == O_RDONLY ? "; reading text version" : ""); 603064562Sgshapiro#else /* defined(NEWDB) || defined(NDBM) */ 603138032Speter if (mode != O_RDONLY) 603238032Speter usrerr("Cannot rebuild aliases: no database format defined"); 603364562Sgshapiro#endif /* defined(NEWDB) || defined(NDBM) */ 603438032Speter 603538032Speter if (mode == O_RDONLY) 603638032Speter return stab_map_open(map, mode); 603738032Speter else 603838032Speter return FALSE; 603938032Speter} 604038032Speter 604138032Speter 604238032Speter/* 604338032Speter** IMPL_MAP_CLOSE -- close any open database(s) 604438032Speter*/ 604538032Speter 604638032Spetervoid 604738032Speterimpl_map_close(map) 604838032Speter MAP *map; 604938032Speter{ 605038032Speter if (tTd(38, 9)) 605164562Sgshapiro dprintf("impl_map_close(%s, %s, %lx)\n", 605238032Speter map->map_mname, map->map_file, map->map_mflags); 605338032Speter#ifdef NEWDB 605438032Speter if (bitset(MF_IMPL_HASH, map->map_mflags)) 605538032Speter { 605638032Speter db_map_close(map); 605738032Speter map->map_mflags &= ~MF_IMPL_HASH; 605838032Speter } 605964562Sgshapiro#endif /* NEWDB */ 606038032Speter 606138032Speter#ifdef NDBM 606238032Speter if (bitset(MF_IMPL_NDBM, map->map_mflags)) 606338032Speter { 606438032Speter ndbm_map_close(map); 606538032Speter map->map_mflags &= ~MF_IMPL_NDBM; 606638032Speter } 606764562Sgshapiro#endif /* NDBM */ 606838032Speter} 606938032Speter/* 607038032Speter** User map class. 607138032Speter** 607238032Speter** Provides access to the system password file. 607338032Speter*/ 607438032Speter 607538032Speter/* 607638032Speter** USER_MAP_OPEN -- open user map 607738032Speter** 607838032Speter** Really just binds field names to field numbers. 607938032Speter*/ 608038032Speter 608138032Speterbool 608238032Speteruser_map_open(map, mode) 608338032Speter MAP *map; 608438032Speter int mode; 608538032Speter{ 608638032Speter if (tTd(38, 2)) 608764562Sgshapiro dprintf("user_map_open(%s, %d)\n", 608838032Speter map->map_mname, mode); 608938032Speter 609038032Speter mode &= O_ACCMODE; 609138032Speter if (mode != O_RDONLY) 609238032Speter { 609338032Speter /* issue a pseudo-error message */ 609438032Speter#ifdef ENOSYS 609538032Speter errno = ENOSYS; 609664562Sgshapiro#else /* ENOSYS */ 609738032Speter# ifdef EFTYPE 609838032Speter errno = EFTYPE; 609964562Sgshapiro# else /* EFTYPE */ 610038032Speter errno = ENXIO; 610164562Sgshapiro# endif /* EFTYPE */ 610264562Sgshapiro#endif /* ENOSYS */ 610338032Speter return FALSE; 610438032Speter } 610538032Speter if (map->map_valcolnm == NULL) 610664562Sgshapiro /* EMPTY */ 610738032Speter /* nothing */ ; 610838032Speter else if (strcasecmp(map->map_valcolnm, "name") == 0) 610938032Speter map->map_valcolno = 1; 611038032Speter else if (strcasecmp(map->map_valcolnm, "passwd") == 0) 611138032Speter map->map_valcolno = 2; 611238032Speter else if (strcasecmp(map->map_valcolnm, "uid") == 0) 611338032Speter map->map_valcolno = 3; 611438032Speter else if (strcasecmp(map->map_valcolnm, "gid") == 0) 611538032Speter map->map_valcolno = 4; 611638032Speter else if (strcasecmp(map->map_valcolnm, "gecos") == 0) 611738032Speter map->map_valcolno = 5; 611838032Speter else if (strcasecmp(map->map_valcolnm, "dir") == 0) 611938032Speter map->map_valcolno = 6; 612038032Speter else if (strcasecmp(map->map_valcolnm, "shell") == 0) 612138032Speter map->map_valcolno = 7; 612238032Speter else 612338032Speter { 612438032Speter syserr("User map %s: unknown column name %s", 612538032Speter map->map_mname, map->map_valcolnm); 612638032Speter return FALSE; 612738032Speter } 612838032Speter return TRUE; 612938032Speter} 613038032Speter 613138032Speter 613238032Speter/* 613338032Speter** USER_MAP_LOOKUP -- look up a user in the passwd file. 613438032Speter*/ 613538032Speter 613638032Speter/* ARGSUSED3 */ 613738032Speterchar * 613838032Speteruser_map_lookup(map, key, av, statp) 613938032Speter MAP *map; 614038032Speter char *key; 614138032Speter char **av; 614238032Speter int *statp; 614338032Speter{ 614438032Speter struct passwd *pw; 614538032Speter auto bool fuzzy; 614638032Speter 614738032Speter if (tTd(38, 20)) 614864562Sgshapiro dprintf("user_map_lookup(%s, %s)\n", 614938032Speter map->map_mname, key); 615038032Speter 615138032Speter pw = finduser(key, &fuzzy); 615238032Speter if (pw == NULL) 615338032Speter return NULL; 615438032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 615538032Speter return map_rewrite(map, key, strlen(key), NULL); 615638032Speter else 615738032Speter { 615838032Speter char *rwval = NULL; 615938032Speter char buf[30]; 616038032Speter 616138032Speter switch (map->map_valcolno) 616238032Speter { 616338032Speter case 0: 616438032Speter case 1: 616538032Speter rwval = pw->pw_name; 616638032Speter break; 616738032Speter 616838032Speter case 2: 616938032Speter rwval = pw->pw_passwd; 617038032Speter break; 617138032Speter 617238032Speter case 3: 617364562Sgshapiro snprintf(buf, sizeof buf, "%d", (int) pw->pw_uid); 617438032Speter rwval = buf; 617538032Speter break; 617638032Speter 617738032Speter case 4: 617864562Sgshapiro snprintf(buf, sizeof buf, "%d", (int) pw->pw_gid); 617938032Speter rwval = buf; 618038032Speter break; 618138032Speter 618238032Speter case 5: 618338032Speter rwval = pw->pw_gecos; 618438032Speter break; 618538032Speter 618638032Speter case 6: 618738032Speter rwval = pw->pw_dir; 618838032Speter break; 618938032Speter 619038032Speter case 7: 619138032Speter rwval = pw->pw_shell; 619238032Speter break; 619338032Speter } 619438032Speter return map_rewrite(map, rwval, strlen(rwval), av); 619538032Speter } 619638032Speter} 619738032Speter/* 619838032Speter** Program map type. 619938032Speter** 620038032Speter** This provides access to arbitrary programs. It should be used 620138032Speter** only very sparingly, since there is no way to bound the cost 620238032Speter** of invoking an arbitrary program. 620338032Speter*/ 620438032Speter 620538032Speterchar * 620638032Speterprog_map_lookup(map, name, av, statp) 620738032Speter MAP *map; 620838032Speter char *name; 620938032Speter char **av; 621038032Speter int *statp; 621138032Speter{ 621238032Speter int i; 621364562Sgshapiro int save_errno; 621438032Speter int fd; 621564562Sgshapiro int status; 621638032Speter auto pid_t pid; 621764562Sgshapiro register char *p; 621838032Speter char *rval; 621938032Speter char *argv[MAXPV + 1]; 622038032Speter char buf[MAXLINE]; 622138032Speter 622238032Speter if (tTd(38, 20)) 622364562Sgshapiro dprintf("prog_map_lookup(%s, %s) %s\n", 622438032Speter map->map_mname, name, map->map_file); 622538032Speter 622638032Speter i = 0; 622738032Speter argv[i++] = map->map_file; 622838032Speter if (map->map_rebuild != NULL) 622938032Speter { 623038032Speter snprintf(buf, sizeof buf, "%s", map->map_rebuild); 623138032Speter for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 623238032Speter { 623338032Speter if (i >= MAXPV - 1) 623438032Speter break; 623538032Speter argv[i++] = p; 623638032Speter } 623738032Speter } 623838032Speter argv[i++] = name; 623938032Speter argv[i] = NULL; 624038032Speter if (tTd(38, 21)) 624138032Speter { 624264562Sgshapiro dprintf("prog_open:"); 624338032Speter for (i = 0; argv[i] != NULL; i++) 624464562Sgshapiro dprintf(" %s", argv[i]); 624564562Sgshapiro dprintf("\n"); 624638032Speter } 624738032Speter (void) blocksignal(SIGCHLD); 624838032Speter pid = prog_open(argv, &fd, CurEnv); 624938032Speter if (pid < 0) 625038032Speter { 625138032Speter if (!bitset(MF_OPTIONAL, map->map_mflags)) 625238032Speter syserr("prog_map_lookup(%s) failed (%s) -- closing", 625338032Speter map->map_mname, errstring(errno)); 625438032Speter else if (tTd(38, 9)) 625564562Sgshapiro dprintf("prog_map_lookup(%s) failed (%s) -- closing", 625638032Speter map->map_mname, errstring(errno)); 625738032Speter map->map_mflags &= ~(MF_VALID|MF_OPEN); 625838032Speter *statp = EX_OSFILE; 625938032Speter return NULL; 626038032Speter } 626138032Speter i = read(fd, buf, sizeof buf - 1); 626238032Speter if (i < 0) 626338032Speter { 626438032Speter syserr("prog_map_lookup(%s): read error %s\n", 626538032Speter map->map_mname, errstring(errno)); 626638032Speter rval = NULL; 626738032Speter } 626838032Speter else if (i == 0) 626938032Speter { 627038032Speter if (tTd(38, 20)) 627164562Sgshapiro dprintf("prog_map_lookup(%s): empty answer\n", 627238032Speter map->map_mname); 627338032Speter rval = NULL; 627438032Speter } 627538032Speter else 627638032Speter { 627738032Speter buf[i] = '\0'; 627838032Speter p = strchr(buf, '\n'); 627938032Speter if (p != NULL) 628038032Speter *p = '\0'; 628138032Speter 628238032Speter /* collect the return value */ 628338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 628438032Speter rval = map_rewrite(map, name, strlen(name), NULL); 628538032Speter else 628638032Speter rval = map_rewrite(map, buf, strlen(buf), NULL); 628738032Speter 628838032Speter /* now flush any additional output */ 628938032Speter while ((i = read(fd, buf, sizeof buf)) > 0) 629038032Speter continue; 629138032Speter } 629238032Speter 629338032Speter /* wait for the process to terminate */ 629464562Sgshapiro (void) close(fd); 629564562Sgshapiro status = waitfor(pid); 629664562Sgshapiro save_errno = errno; 629738032Speter (void) releasesignal(SIGCHLD); 629864562Sgshapiro errno = save_errno; 629938032Speter 630064562Sgshapiro if (status == -1) 630138032Speter { 630238032Speter syserr("prog_map_lookup(%s): wait error %s\n", 630338032Speter map->map_mname, errstring(errno)); 630438032Speter *statp = EX_SOFTWARE; 630538032Speter rval = NULL; 630638032Speter } 630764562Sgshapiro else if (WIFEXITED(status)) 630838032Speter { 630964562Sgshapiro if ((*statp = WEXITSTATUS(status)) != EX_OK) 631038032Speter rval = NULL; 631138032Speter } 631238032Speter else 631338032Speter { 631438032Speter syserr("prog_map_lookup(%s): child died on signal %d", 631564562Sgshapiro map->map_mname, status); 631638032Speter *statp = EX_UNAVAILABLE; 631738032Speter rval = NULL; 631838032Speter } 631938032Speter return rval; 632038032Speter} 632138032Speter/* 632238032Speter** Sequenced map type. 632338032Speter** 632438032Speter** Tries each map in order until something matches, much like 632538032Speter** implicit. Stores go to the first map in the list that can 632638032Speter** support storing. 632738032Speter** 632838032Speter** This is slightly unusual in that there are two interfaces. 632938032Speter** The "sequence" interface lets you stack maps arbitrarily. 633038032Speter** The "switch" interface builds a sequence map by looking 633138032Speter** at a system-dependent configuration file such as 633238032Speter** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 633338032Speter** 633438032Speter** We don't need an explicit open, since all maps are 633538032Speter** opened during startup, including underlying maps. 633638032Speter*/ 633738032Speter 633838032Speter/* 633938032Speter** SEQ_MAP_PARSE -- Sequenced map parsing 634038032Speter*/ 634138032Speter 634238032Speterbool 634338032Speterseq_map_parse(map, ap) 634438032Speter MAP *map; 634538032Speter char *ap; 634638032Speter{ 634738032Speter int maxmap; 634838032Speter 634938032Speter if (tTd(38, 2)) 635064562Sgshapiro dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 635138032Speter maxmap = 0; 635238032Speter while (*ap != '\0') 635338032Speter { 635438032Speter register char *p; 635538032Speter STAB *s; 635638032Speter 635738032Speter /* find beginning of map name */ 635838032Speter while (isascii(*ap) && isspace(*ap)) 635938032Speter ap++; 636064562Sgshapiro for (p = ap; 636164562Sgshapiro (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 636264562Sgshapiro p++) 636338032Speter continue; 636438032Speter if (*p != '\0') 636538032Speter *p++ = '\0'; 636638032Speter while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 636738032Speter p++; 636838032Speter if (*ap == '\0') 636938032Speter { 637038032Speter ap = p; 637138032Speter continue; 637238032Speter } 637338032Speter s = stab(ap, ST_MAP, ST_FIND); 637438032Speter if (s == NULL) 637538032Speter { 637638032Speter syserr("Sequence map %s: unknown member map %s", 637738032Speter map->map_mname, ap); 637838032Speter } 637938032Speter else if (maxmap == MAXMAPSTACK) 638038032Speter { 638138032Speter syserr("Sequence map %s: too many member maps (%d max)", 638238032Speter map->map_mname, MAXMAPSTACK); 638338032Speter maxmap++; 638438032Speter } 638538032Speter else if (maxmap < MAXMAPSTACK) 638638032Speter { 638738032Speter map->map_stack[maxmap++] = &s->s_map; 638838032Speter } 638938032Speter ap = p; 639038032Speter } 639138032Speter return TRUE; 639238032Speter} 639338032Speter 639438032Speter 639538032Speter/* 639638032Speter** SWITCH_MAP_OPEN -- open a switched map 639738032Speter** 639838032Speter** This looks at the system-dependent configuration and builds 639938032Speter** a sequence map that does the same thing. 640038032Speter** 640138032Speter** Every system must define a switch_map_find routine in conf.c 640238032Speter** that will return the list of service types associated with a 640338032Speter** given service class. 640438032Speter*/ 640538032Speter 640638032Speterbool 640738032Speterswitch_map_open(map, mode) 640838032Speter MAP *map; 640938032Speter int mode; 641038032Speter{ 641138032Speter int mapno; 641238032Speter int nmaps; 641338032Speter char *maptype[MAXMAPSTACK]; 641438032Speter 641538032Speter if (tTd(38, 2)) 641664562Sgshapiro dprintf("switch_map_open(%s, %s, %d)\n", 641738032Speter map->map_mname, map->map_file, mode); 641838032Speter 641938032Speter mode &= O_ACCMODE; 642038032Speter nmaps = switch_map_find(map->map_file, maptype, map->map_return); 642138032Speter if (tTd(38, 19)) 642238032Speter { 642364562Sgshapiro dprintf("\tswitch_map_find => %d\n", nmaps); 642438032Speter for (mapno = 0; mapno < nmaps; mapno++) 642564562Sgshapiro dprintf("\t\t%s\n", maptype[mapno]); 642638032Speter } 642738032Speter if (nmaps <= 0 || nmaps > MAXMAPSTACK) 642838032Speter return FALSE; 642938032Speter 643038032Speter for (mapno = 0; mapno < nmaps; mapno++) 643138032Speter { 643238032Speter register STAB *s; 643338032Speter char nbuf[MAXNAME + 1]; 643438032Speter 643538032Speter if (maptype[mapno] == NULL) 643638032Speter continue; 643738032Speter (void) snprintf(nbuf, sizeof nbuf, "%s.%s", 643838032Speter map->map_mname, maptype[mapno]); 643938032Speter s = stab(nbuf, ST_MAP, ST_FIND); 644038032Speter if (s == NULL) 644138032Speter { 644238032Speter syserr("Switch map %s: unknown member map %s", 644338032Speter map->map_mname, nbuf); 644438032Speter } 644538032Speter else 644638032Speter { 644738032Speter map->map_stack[mapno] = &s->s_map; 644838032Speter if (tTd(38, 4)) 644964562Sgshapiro dprintf("\tmap_stack[%d] = %s:%s\n", 645038032Speter mapno, s->s_map.map_class->map_cname, 645138032Speter nbuf); 645238032Speter } 645338032Speter } 645438032Speter return TRUE; 645538032Speter} 645638032Speter 645738032Speter 645838032Speter/* 645938032Speter** SEQ_MAP_CLOSE -- close all underlying maps 646038032Speter*/ 646138032Speter 646238032Spetervoid 646338032Speterseq_map_close(map) 646438032Speter MAP *map; 646538032Speter{ 646638032Speter int mapno; 646738032Speter 646838032Speter if (tTd(38, 9)) 646964562Sgshapiro dprintf("seq_map_close(%s)\n", map->map_mname); 647038032Speter 647138032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 647238032Speter { 647338032Speter MAP *mm = map->map_stack[mapno]; 647438032Speter 647538032Speter if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 647638032Speter continue; 647738032Speter mm->map_class->map_close(mm); 647838032Speter mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 647938032Speter } 648038032Speter} 648138032Speter 648238032Speter 648338032Speter/* 648438032Speter** SEQ_MAP_LOOKUP -- sequenced map lookup 648538032Speter*/ 648638032Speter 648738032Speterchar * 648838032Speterseq_map_lookup(map, key, args, pstat) 648938032Speter MAP *map; 649038032Speter char *key; 649138032Speter char **args; 649238032Speter int *pstat; 649338032Speter{ 649438032Speter int mapno; 649538032Speter int mapbit = 0x01; 649638032Speter bool tempfail = FALSE; 649738032Speter 649838032Speter if (tTd(38, 20)) 649964562Sgshapiro dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 650038032Speter 650138032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 650238032Speter { 650338032Speter MAP *mm = map->map_stack[mapno]; 650438032Speter char *rv; 650538032Speter 650638032Speter if (mm == NULL) 650738032Speter continue; 650864562Sgshapiro if (!bitset(MF_OPEN, mm->map_mflags) && 650964562Sgshapiro !openmap(mm)) 651038032Speter { 651138032Speter if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 651238032Speter { 651338032Speter *pstat = EX_UNAVAILABLE; 651438032Speter return NULL; 651538032Speter } 651638032Speter continue; 651738032Speter } 651838032Speter *pstat = EX_OK; 651938032Speter rv = mm->map_class->map_lookup(mm, key, args, pstat); 652038032Speter if (rv != NULL) 652138032Speter return rv; 652238032Speter if (*pstat == EX_TEMPFAIL) 652338032Speter { 652438032Speter if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 652538032Speter return NULL; 652638032Speter tempfail = TRUE; 652738032Speter } 652838032Speter else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 652938032Speter break; 653038032Speter } 653138032Speter if (tempfail) 653238032Speter *pstat = EX_TEMPFAIL; 653338032Speter else if (*pstat == EX_OK) 653438032Speter *pstat = EX_NOTFOUND; 653538032Speter return NULL; 653638032Speter} 653738032Speter 653838032Speter 653938032Speter/* 654038032Speter** SEQ_MAP_STORE -- sequenced map store 654138032Speter*/ 654238032Speter 654338032Spetervoid 654438032Speterseq_map_store(map, key, val) 654538032Speter MAP *map; 654638032Speter char *key; 654738032Speter char *val; 654838032Speter{ 654938032Speter int mapno; 655038032Speter 655138032Speter if (tTd(38, 12)) 655264562Sgshapiro dprintf("seq_map_store(%s, %s, %s)\n", 655338032Speter map->map_mname, key, val); 655438032Speter 655538032Speter for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 655638032Speter { 655738032Speter MAP *mm = map->map_stack[mapno]; 655838032Speter 655938032Speter if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 656038032Speter continue; 656138032Speter 656238032Speter mm->map_class->map_store(mm, key, val); 656338032Speter return; 656438032Speter } 656538032Speter syserr("seq_map_store(%s, %s, %s): no writable map", 656638032Speter map->map_mname, key, val); 656738032Speter} 656838032Speter/* 656938032Speter** NULL stubs 657038032Speter*/ 657138032Speter 657238032Speter/* ARGSUSED */ 657338032Speterbool 657438032Speternull_map_open(map, mode) 657538032Speter MAP *map; 657638032Speter int mode; 657738032Speter{ 657838032Speter return TRUE; 657938032Speter} 658038032Speter 658138032Speter/* ARGSUSED */ 658238032Spetervoid 658338032Speternull_map_close(map) 658438032Speter MAP *map; 658538032Speter{ 658638032Speter return; 658738032Speter} 658838032Speter 658938032Speterchar * 659038032Speternull_map_lookup(map, key, args, pstat) 659138032Speter MAP *map; 659238032Speter char *key; 659338032Speter char **args; 659438032Speter int *pstat; 659538032Speter{ 659638032Speter *pstat = EX_NOTFOUND; 659738032Speter return NULL; 659838032Speter} 659938032Speter 660038032Speter/* ARGSUSED */ 660138032Spetervoid 660238032Speternull_map_store(map, key, val) 660338032Speter MAP *map; 660438032Speter char *key; 660538032Speter char *val; 660638032Speter{ 660738032Speter return; 660838032Speter} 660938032Speter 661038032Speter 661138032Speter/* 661238032Speter** BOGUS stubs 661338032Speter*/ 661438032Speter 661538032Speterchar * 661638032Speterbogus_map_lookup(map, key, args, pstat) 661738032Speter MAP *map; 661838032Speter char *key; 661938032Speter char **args; 662038032Speter int *pstat; 662138032Speter{ 662238032Speter *pstat = EX_TEMPFAIL; 662338032Speter return NULL; 662438032Speter} 662538032Speter 662638032SpeterMAPCLASS BogusMapClass = 662738032Speter{ 662838032Speter "bogus-map", NULL, 0, 662938032Speter NULL, bogus_map_lookup, null_map_store, 663038032Speter null_map_open, null_map_close, 663138032Speter}; 663238032Speter/* 663364562Sgshapiro** MACRO modules 663464562Sgshapiro*/ 663564562Sgshapiro 663664562Sgshapirochar * 663764562Sgshapiromacro_map_lookup(map, name, av, statp) 663864562Sgshapiro MAP *map; 663964562Sgshapiro char *name; 664064562Sgshapiro char **av; 664164562Sgshapiro int *statp; 664264562Sgshapiro{ 664364562Sgshapiro int mid; 664464562Sgshapiro 664564562Sgshapiro if (tTd(38, 20)) 664664562Sgshapiro dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 664764562Sgshapiro name == NULL ? "NULL" : name); 664864562Sgshapiro 664964562Sgshapiro if (name == NULL || 665064562Sgshapiro *name == '\0' || 665164562Sgshapiro (mid = macid(name, NULL)) == '\0') 665264562Sgshapiro { 665364562Sgshapiro *statp = EX_CONFIG; 665464562Sgshapiro return NULL; 665564562Sgshapiro } 665664562Sgshapiro 665764562Sgshapiro if (av[1] == NULL) 665864562Sgshapiro define(mid, NULL, CurEnv); 665964562Sgshapiro else 666064562Sgshapiro define(mid, newstr(av[1]), CurEnv); 666164562Sgshapiro 666264562Sgshapiro *statp = EX_OK; 666364562Sgshapiro return ""; 666464562Sgshapiro} 666564562Sgshapiro/* 666638032Speter** REGEX modules 666738032Speter*/ 666838032Speter 666938032Speter#ifdef MAP_REGEX 667038032Speter 667138032Speter# include <regex.h> 667238032Speter 667338032Speter# define DEFAULT_DELIM CONDELSE 667438032Speter 667538032Speter# define END_OF_FIELDS -1 667638032Speter 667738032Speter# define ERRBUF_SIZE 80 667838032Speter# define MAX_MATCH 32 667938032Speter 668064562Sgshapiro# define xnalloc(s) memset(xalloc(s), '\0', s); 668138032Speter 668238032Speterstruct regex_map 668338032Speter{ 668464562Sgshapiro regex_t regex_pattern_buf; /* xalloc it */ 668538032Speter int *regex_subfields; /* move to type MAP */ 668664562Sgshapiro char *regex_delim; /* move to type MAP */ 668738032Speter}; 668838032Speter 668938032Speterstatic int 669038032Speterparse_fields(s, ibuf, blen, nr_substrings) 669138032Speter char *s; 669238032Speter int *ibuf; /* array */ 669338032Speter int blen; /* number of elements in ibuf */ 669438032Speter int nr_substrings; /* number of substrings in the pattern */ 669538032Speter{ 669638032Speter register char *cp; 669738032Speter int i = 0; 669838032Speter bool lastone = FALSE; 669938032Speter 670038032Speter blen--; /* for terminating END_OF_FIELDS */ 670138032Speter cp = s; 670238032Speter do 670338032Speter { 670438032Speter for (;; cp++) 670538032Speter { 670638032Speter if (*cp == ',') 670738032Speter { 670838032Speter *cp = '\0'; 670938032Speter break; 671038032Speter } 671138032Speter if (*cp == '\0') 671238032Speter { 671338032Speter lastone = TRUE; 671438032Speter break; 671538032Speter } 671638032Speter } 671738032Speter if (i < blen) 671838032Speter { 671938032Speter int val = atoi(s); 672038032Speter 672138032Speter if (val < 0 || val >= nr_substrings) 672238032Speter { 672338032Speter syserr("field (%d) out of range, only %d substrings in pattern", 672438032Speter val, nr_substrings); 672538032Speter return -1; 672638032Speter } 672738032Speter ibuf[i++] = val; 672838032Speter } 672938032Speter else 673038032Speter { 673138032Speter syserr("too many fields, %d max\n", blen); 673238032Speter return -1; 673338032Speter } 673438032Speter s = ++cp; 673538032Speter } while (!lastone); 673638032Speter ibuf[i] = END_OF_FIELDS; 673738032Speter return i; 673838032Speter} 673938032Speter 674038032Speterbool 674138032Speterregex_map_init(map, ap) 674238032Speter MAP *map; 674338032Speter char *ap; 674438032Speter{ 674538032Speter int regerr; 674638032Speter struct regex_map *map_p; 674738032Speter register char *p; 674838032Speter char *sub_param = NULL; 674938032Speter int pflags; 675038032Speter static char defdstr[] = { (char)DEFAULT_DELIM, '\0' }; 675138032Speter 675238032Speter if (tTd(38, 2)) 675364562Sgshapiro dprintf("regex_map_init: mapname '%s', args '%s'\n", 675464562Sgshapiro map->map_mname, ap); 675538032Speter 675638032Speter pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 675738032Speter 675838032Speter p = ap; 675938032Speter 676064562Sgshapiro map_p = (struct regex_map *) xnalloc(sizeof *map_p); 676138032Speter 676238032Speter for (;;) 676364562Sgshapiro { 676438032Speter while (isascii(*p) && isspace(*p)) 676538032Speter p++; 676638032Speter if (*p != '-') 676738032Speter break; 676838032Speter switch (*++p) 676938032Speter { 677038032Speter case 'n': /* not */ 677138032Speter map->map_mflags |= MF_REGEX_NOT; 677238032Speter break; 677338032Speter 677438032Speter case 'f': /* case sensitive */ 677538032Speter map->map_mflags |= MF_NOFOLDCASE; 677638032Speter pflags &= ~REG_ICASE; 677738032Speter break; 677838032Speter 677938032Speter case 'b': /* basic regular expressions */ 678038032Speter pflags &= ~REG_EXTENDED; 678138032Speter break; 678238032Speter 678338032Speter case 's': /* substring match () syntax */ 678438032Speter sub_param = ++p; 678538032Speter pflags &= ~REG_NOSUB; 678638032Speter break; 678738032Speter 678838032Speter case 'd': /* delimiter */ 678964562Sgshapiro map_p->regex_delim = ++p; 679038032Speter break; 679138032Speter 679238032Speter case 'a': /* map append */ 679338032Speter map->map_app = ++p; 679438032Speter break; 679538032Speter 679638032Speter case 'm': /* matchonly */ 679738032Speter map->map_mflags |= MF_MATCHONLY; 679838032Speter break; 679938032Speter 680064562Sgshapiro case 'S': 680164562Sgshapiro map->map_spacesub = *++p; 680264562Sgshapiro break; 680364562Sgshapiro 680464562Sgshapiro case 'D': 680564562Sgshapiro map->map_mflags |= MF_DEFER; 680664562Sgshapiro break; 680764562Sgshapiro 680838032Speter } 680964562Sgshapiro while (*p != '\0' && !(isascii(*p) && isspace(*p))) 681064562Sgshapiro p++; 681164562Sgshapiro if (*p != '\0') 681264562Sgshapiro *p++ = '\0'; 681338032Speter } 681438032Speter if (tTd(38, 3)) 681564562Sgshapiro dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 681638032Speter 681764562Sgshapiro if ((regerr = regcomp(&(map_p->regex_pattern_buf), p, pflags)) != 0) 681838032Speter { 681938032Speter /* Errorhandling */ 682038032Speter char errbuf[ERRBUF_SIZE]; 682138032Speter 682264562Sgshapiro (void) regerror(regerr, &(map_p->regex_pattern_buf), 682364562Sgshapiro errbuf, ERRBUF_SIZE); 682438032Speter syserr("pattern-compile-error: %s\n", errbuf); 682538032Speter free(map_p); 682638032Speter return FALSE; 682738032Speter } 682838032Speter 682938032Speter if (map->map_app != NULL) 683038032Speter map->map_app = newstr(map->map_app); 683164562Sgshapiro if (map_p->regex_delim != NULL) 683264562Sgshapiro map_p->regex_delim = newstr(map_p->regex_delim); 683338032Speter else 683464562Sgshapiro map_p->regex_delim = defdstr; 683538032Speter 683638032Speter if (!bitset(REG_NOSUB, pflags)) 683738032Speter { 683838032Speter /* substring matching */ 683938032Speter int substrings; 684064562Sgshapiro int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 684138032Speter 684264562Sgshapiro substrings = map_p->regex_pattern_buf.re_nsub + 1; 684338032Speter 684438032Speter if (tTd(38, 3)) 684564562Sgshapiro dprintf("regex_map_init: nr of substrings %d\n", 684664562Sgshapiro substrings); 684738032Speter 684838032Speter if (substrings >= MAX_MATCH) 684938032Speter { 685038032Speter syserr("too many substrings, %d max\n", MAX_MATCH); 685138032Speter free(map_p); 685238032Speter return FALSE; 685338032Speter } 685438032Speter if (sub_param != NULL && sub_param[0] != '\0') 685538032Speter { 685638032Speter /* optional parameter -sfields */ 685738032Speter if (parse_fields(sub_param, fields, 685838032Speter MAX_MATCH + 1, substrings) == -1) 685938032Speter return FALSE; 686038032Speter } 686138032Speter else 686238032Speter { 686364562Sgshapiro /* set default fields */ 686438032Speter int i; 686538032Speter 686638032Speter for (i = 0; i < substrings; i++) 686738032Speter fields[i] = i; 686838032Speter fields[i] = END_OF_FIELDS; 686938032Speter } 687038032Speter map_p->regex_subfields = fields; 687138032Speter if (tTd(38, 3)) 687238032Speter { 687338032Speter int *ip; 687438032Speter 687564562Sgshapiro dprintf("regex_map_init: subfields"); 687638032Speter for (ip = fields; *ip != END_OF_FIELDS; ip++) 687764562Sgshapiro dprintf(" %d", *ip); 687864562Sgshapiro dprintf("\n"); 687938032Speter } 688038032Speter } 688138032Speter map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */ 688238032Speter 688338032Speter return TRUE; 688438032Speter} 688538032Speter 688638032Speterstatic char * 688738032Speterregex_map_rewrite(map, s, slen, av) 688838032Speter MAP *map; 688938032Speter const char *s; 689038032Speter size_t slen; 689138032Speter char **av; 689238032Speter{ 689338032Speter if (bitset(MF_MATCHONLY, map->map_mflags)) 689438032Speter return map_rewrite(map, av[0], strlen(av[0]), NULL); 689538032Speter else 689638032Speter return map_rewrite(map, s, slen, NULL); 689738032Speter} 689838032Speter 689938032Speterchar * 690038032Speterregex_map_lookup(map, name, av, statp) 690138032Speter MAP *map; 690238032Speter char *name; 690338032Speter char **av; 690438032Speter int *statp; 690538032Speter{ 690638032Speter int reg_res; 690738032Speter struct regex_map *map_p; 690838032Speter regmatch_t pmatch[MAX_MATCH]; 690938032Speter 691038032Speter if (tTd(38, 20)) 691138032Speter { 691238032Speter char **cpp; 691338032Speter 691464562Sgshapiro dprintf("regex_map_lookup: key '%s'\n", name); 691564562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 691664562Sgshapiro dprintf("regex_map_lookup: arg '%s'\n", *cpp); 691738032Speter } 691838032Speter 691938032Speter map_p = (struct regex_map *)(map->map_db1); 692064562Sgshapiro reg_res = regexec(&(map_p->regex_pattern_buf), 692164562Sgshapiro name, MAX_MATCH, pmatch, 0); 692238032Speter 692338032Speter if (bitset(MF_REGEX_NOT, map->map_mflags)) 692438032Speter { 692538032Speter /* option -n */ 692638032Speter if (reg_res == REG_NOMATCH) 692738032Speter return regex_map_rewrite(map, "", (size_t)0, av); 692838032Speter else 692938032Speter return NULL; 693038032Speter } 693138032Speter if (reg_res == REG_NOMATCH) 693238032Speter return NULL; 693338032Speter 693438032Speter if (map_p->regex_subfields != NULL) 693538032Speter { 693638032Speter /* option -s */ 693738032Speter static char retbuf[MAXNAME]; 693838032Speter int fields[MAX_MATCH + 1]; 693938032Speter bool first = TRUE; 694038032Speter int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 694138032Speter bool quotemode = FALSE, bslashmode = FALSE; 694238032Speter register char *dp, *sp; 694338032Speter char *endp, *ldp; 694438032Speter int *ip; 694538032Speter 694638032Speter dp = retbuf; 694738032Speter ldp = retbuf + sizeof(retbuf) - 1; 694838032Speter 694938032Speter if (av[1] != NULL) 695038032Speter { 695138032Speter if (parse_fields(av[1], fields, MAX_MATCH + 1, 695264562Sgshapiro (int) map_p->regex_pattern_buf.re_nsub + 1) == -1) 695338032Speter { 695438032Speter *statp = EX_CONFIG; 695538032Speter return NULL; 695638032Speter } 695738032Speter ip = fields; 695838032Speter } 695938032Speter else 696038032Speter ip = map_p->regex_subfields; 696138032Speter 696238032Speter for ( ; *ip != END_OF_FIELDS; ip++) 696338032Speter { 696438032Speter if (!first) 696538032Speter { 696664562Sgshapiro for (sp = map_p->regex_delim; *sp; sp++) 696738032Speter { 696838032Speter if (dp < ldp) 696938032Speter *dp++ = *sp; 697038032Speter } 697138032Speter } 697238032Speter else 697338032Speter first = FALSE; 697438032Speter 697538032Speter 697638032Speter if (pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 697738032Speter continue; 697838032Speter 697938032Speter sp = name + pmatch[*ip].rm_so; 698038032Speter endp = name + pmatch[*ip].rm_eo; 698138032Speter for (; endp > sp; sp++) 698238032Speter { 698338032Speter if (dp < ldp) 698438032Speter { 698564562Sgshapiro if (bslashmode) 698664562Sgshapiro { 698738032Speter *dp++ = *sp; 698838032Speter bslashmode = FALSE; 698938032Speter } 699064562Sgshapiro else if (quotemode && *sp != '"' && 699138032Speter *sp != '\\') 699238032Speter { 699338032Speter *dp++ = *sp; 699438032Speter } 699538032Speter else switch(*dp++ = *sp) 699638032Speter { 699738032Speter case '\\': 699838032Speter bslashmode = TRUE; 699938032Speter break; 700038032Speter 700138032Speter case '(': 700238032Speter cmntcnt++; 700338032Speter break; 700438032Speter 700538032Speter case ')': 700638032Speter cmntcnt--; 700738032Speter break; 700838032Speter 700938032Speter case '<': 701038032Speter anglecnt++; 701138032Speter break; 701238032Speter 701338032Speter case '>': 701438032Speter anglecnt--; 701538032Speter break; 701638032Speter 701738032Speter case ' ': 701838032Speter spacecnt++; 701938032Speter break; 702038032Speter 702138032Speter case '"': 702238032Speter quotemode = !quotemode; 702338032Speter break; 702438032Speter } 702538032Speter } 702638032Speter } 702738032Speter } 702838032Speter if (anglecnt != 0 || cmntcnt != 0 || quotemode || 702938032Speter bslashmode || spacecnt != 0) 703038032Speter { 703164562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 703264562Sgshapiro "Warning: regex may cause prescan() failure map=%s lookup=%s", 703364562Sgshapiro map->map_mname, name); 703438032Speter return NULL; 703538032Speter } 703638032Speter 703738032Speter *dp = '\0'; 703838032Speter 703938032Speter return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 704038032Speter } 704138032Speter return regex_map_rewrite(map, "", (size_t)0, av); 704238032Speter} 704338032Speter#endif /* MAP_REGEX */ 704464562Sgshapiro/* 704564562Sgshapiro** NSD modules 704664562Sgshapiro*/ 704764562Sgshapiro#ifdef MAP_NSD 704864562Sgshapiro 704964562Sgshapiro# include <ndbm.h> 705064562Sgshapiro# define _DATUM_DEFINED 705164562Sgshapiro# include <ns_api.h> 705264562Sgshapiro 705364562Sgshapirotypedef struct ns_map_list 705464562Sgshapiro{ 705564562Sgshapiro ns_map_t *map; 705664562Sgshapiro char *mapname; 705764562Sgshapiro struct ns_map_list *next; 705864562Sgshapiro} ns_map_list_t; 705964562Sgshapiro 706064562Sgshapirostatic ns_map_t * 706164562Sgshapirons_map_t_find(mapname) 706264562Sgshapiro char *mapname; 706364562Sgshapiro{ 706464562Sgshapiro static ns_map_list_t *ns_maps = NULL; 706564562Sgshapiro ns_map_list_t *ns_map; 706664562Sgshapiro 706764562Sgshapiro /* walk the list of maps looking for the correctly named map */ 706864562Sgshapiro for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 706964562Sgshapiro { 707064562Sgshapiro if (strcmp(ns_map->mapname, mapname) == 0) 707164562Sgshapiro break; 707264562Sgshapiro } 707364562Sgshapiro 707464562Sgshapiro /* if we are looking at a NULL ns_map_list_t, then create a new one */ 707564562Sgshapiro if (ns_map == NULL) 707664562Sgshapiro { 707764562Sgshapiro ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 707864562Sgshapiro ns_map->mapname = newstr(mapname); 707964562Sgshapiro ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 708064562Sgshapiro ns_map->next = ns_maps; 708164562Sgshapiro ns_maps = ns_map; 708264562Sgshapiro } 708364562Sgshapiro return ns_map->map; 708464562Sgshapiro} 708564562Sgshapiro 708664562Sgshapirochar * 708764562Sgshapironsd_map_lookup(map, name, av, statp) 708864562Sgshapiro MAP *map; 708964562Sgshapiro char *name; 709064562Sgshapiro char **av; 709164562Sgshapiro int *statp; 709264562Sgshapiro{ 709364562Sgshapiro int buflen; 709464562Sgshapiro char *p; 709564562Sgshapiro ns_map_t *ns_map; 709664562Sgshapiro char keybuf[MAXNAME + 1]; 709764562Sgshapiro char buf[MAXLINE]; 709864562Sgshapiro 709964562Sgshapiro if (tTd(38, 20)) 710064562Sgshapiro dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 710164562Sgshapiro 710264562Sgshapiro buflen = strlen(name); 710364562Sgshapiro if (buflen > sizeof keybuf - 1) 710464562Sgshapiro buflen = sizeof keybuf - 1; 710564562Sgshapiro memmove(keybuf, name, buflen); 710664562Sgshapiro keybuf[buflen] = '\0'; 710764562Sgshapiro if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 710864562Sgshapiro makelower(keybuf); 710964562Sgshapiro 711064562Sgshapiro ns_map = ns_map_t_find(map->map_file); 711164562Sgshapiro if (ns_map == NULL) 711264562Sgshapiro { 711364562Sgshapiro if (tTd(38, 20)) 711464562Sgshapiro dprintf("nsd_map_t_find failed\n"); 711564562Sgshapiro return NULL; 711664562Sgshapiro } 711764562Sgshapiro 711864562Sgshapiro if (ns_lookup(ns_map, NULL, map->map_file, 711964562Sgshapiro keybuf, NULL, buf, MAXLINE) == NULL) 712064562Sgshapiro return NULL; 712164562Sgshapiro 712264562Sgshapiro /* Null out trailing \n */ 712364562Sgshapiro if ((p = strchr(buf, '\n')) != NULL) 712464562Sgshapiro *p = '\0'; 712564562Sgshapiro 712664562Sgshapiro return map_rewrite(map, buf, strlen(buf), av); 712764562Sgshapiro} 712864562Sgshapiro#endif /* MAP_NSD */ 712964562Sgshapiro 713064562Sgshapirochar * 713164562Sgshapiroarith_map_lookup(map, name, av, statp) 713264562Sgshapiro MAP *map; 713364562Sgshapiro char *name; 713464562Sgshapiro char **av; 713564562Sgshapiro int *statp; 713664562Sgshapiro{ 713764562Sgshapiro long r; 713864562Sgshapiro long v[2]; 713964562Sgshapiro bool res = FALSE; 714064562Sgshapiro bool boolres; 714164562Sgshapiro static char result[16]; 714264562Sgshapiro char **cpp; 714364562Sgshapiro 714464562Sgshapiro if (tTd(38, 2)) 714564562Sgshapiro { 714664562Sgshapiro dprintf("arith_map_lookup: key '%s'\n", name); 714764562Sgshapiro for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 714864562Sgshapiro dprintf("arith_map_lookup: arg '%s'\n", *cpp); 714964562Sgshapiro } 715064562Sgshapiro r = 0; 715164562Sgshapiro boolres = FALSE; 715264562Sgshapiro cpp = av; 715364562Sgshapiro *statp = EX_OK; 715464562Sgshapiro 715564562Sgshapiro /* 715664562Sgshapiro ** read arguments for arith map 715764562Sgshapiro ** - no check is made whether they are really numbers 715864562Sgshapiro ** - just ignores args after the second 715964562Sgshapiro */ 716064562Sgshapiro for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 716164562Sgshapiro v[r++] = strtol(*cpp, NULL, 0); 716264562Sgshapiro 716364562Sgshapiro /* operator and (at least) two operands given? */ 716464562Sgshapiro if (name != NULL && r == 2) 716564562Sgshapiro { 716664562Sgshapiro switch(*name) 716764562Sgshapiro { 716864562Sgshapiro#if _FFR_ARITH 716964562Sgshapiro case '|': 717064562Sgshapiro r = v[0] | v[1]; 717164562Sgshapiro break; 717264562Sgshapiro 717364562Sgshapiro case '&': 717464562Sgshapiro r = v[0] & v[1]; 717564562Sgshapiro break; 717664562Sgshapiro 717764562Sgshapiro case '%': 717864562Sgshapiro if (v[1] == 0) 717964562Sgshapiro return NULL; 718064562Sgshapiro r = v[0] % v[1]; 718164562Sgshapiro break; 718264562Sgshapiro#endif /* _FFR_ARITH */ 718364562Sgshapiro 718464562Sgshapiro case '+': 718564562Sgshapiro r = v[0] + v[1]; 718664562Sgshapiro break; 718764562Sgshapiro 718864562Sgshapiro case '-': 718964562Sgshapiro r = v[0] - v[1]; 719064562Sgshapiro break; 719164562Sgshapiro 719264562Sgshapiro case '*': 719364562Sgshapiro r = v[0] * v[1]; 719464562Sgshapiro break; 719564562Sgshapiro 719664562Sgshapiro case '/': 719764562Sgshapiro if (v[1] == 0) 719864562Sgshapiro return NULL; 719964562Sgshapiro r = v[0] / v[1]; 720064562Sgshapiro break; 720164562Sgshapiro 720264562Sgshapiro case 'l': 720364562Sgshapiro res = v[0] < v[1]; 720464562Sgshapiro boolres = TRUE; 720564562Sgshapiro break; 720664562Sgshapiro 720764562Sgshapiro case '=': 720864562Sgshapiro res = v[0] == v[1]; 720964562Sgshapiro boolres = TRUE; 721064562Sgshapiro break; 721164562Sgshapiro 721264562Sgshapiro default: 721364562Sgshapiro /* XXX */ 721464562Sgshapiro *statp = EX_CONFIG; 721564562Sgshapiro if (LogLevel > 10) 721664562Sgshapiro sm_syslog(LOG_WARNING, NOQID, 721764562Sgshapiro "arith_map: unknown operator %c", 721864562Sgshapiro isprint(*name) ? *name : '?'); 721964562Sgshapiro return NULL; 722064562Sgshapiro } 722164562Sgshapiro if (boolres) 722264562Sgshapiro snprintf(result, sizeof result, res ? "TRUE" : "FALSE"); 722364562Sgshapiro else 722464562Sgshapiro snprintf(result, sizeof result, "%ld", r); 722564562Sgshapiro return result; 722664562Sgshapiro } 722764562Sgshapiro *statp = EX_CONFIG; 722864562Sgshapiro return NULL; 722964562Sgshapiro} 7230