1N/A * Copyright (c) 1998-2008 Sendmail, Inc. and its suppliers. 1N/A * All rights reserved. 1N/A * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved. 1N/A * Copyright (c) 1992, 1993 1N/A * The Regents of the University of California. All rights reserved. 1N/A * By using this file, you agree to the terms and conditions set 1N/A * forth in the LICENSE file which can be found at the top level of 1N/A * the sendmail distribution. 1N/A#
endif /* R_FIRST */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR == 2 */ 1N/A#
endif /* DB_VERSION_MAJOR > 2 */ 1N/A/* XXX arbitrary limit for sanity */ 1N/A#
endif /* SOCKETMAP */ 1N/A/* default error message for trying to open a map in write mode */ 1N/A** MAP.C -- implementations for various map classes. 1N/A** Each map class implements a series of functions: 1N/A** bool map_parse(MAP *map, char *args) 1N/A** Parse the arguments from the config file. Return true 1N/A** if they were ok, false otherwise. Fill in map with the 1N/A** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 1N/A** Look up the key in the given map. If found, do any 1N/A** rewriting the map wants (including "args" if desired) 1N/A** and return the value. Set *pstat to the appropriate status 1N/A** on error and return NULL. Args will be NULL if called 1N/A** from the alias routines, although this should probably 1N/A** not be relied upon. It is suggested you call map_rewrite 1N/A** to return the results -- it takes care of null termination 1N/A** and uses a dynamically expanded buffer as needed. 1N/A** void map_store(MAP *map, char *key, char *value) 1N/A** Store the key:value pair in the map. 1N/A** bool map_open(MAP *map, int mode) 1N/A** Open the map for the indicated mode. Mode should 1N/A** be either O_RDONLY or O_RDWR. Return true if it 1N/A** was opened successfully, false otherwise. If the open 1N/A** failed and the MF_OPTIONAL flag is not set, it should 1N/A** also print an error. If the MF_ALIAS bit is set 1N/A** and this map class understands the @:@ convention, it 1N/A** should call aliaswait() before returning. 1N/A** void map_close(MAP *map) 1N/A** This file also includes the implementation for getcanonname. 1N/A** It is currently implemented in a pretty ad-hoc manner; it ought 1N/A** to be more properly integrated into the map structure. 1N/A#
else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 1N/A#
endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 1N/A** MAP_PARSEARGS -- parse config line arguments for database lookup 1N/A** This is a generic version of the map_parse method. 1N/A** map -- the map being initialized. 1N/A** ap -- a pointer to the args on the config line. 1N/A** true -- if everything parsed OK. 1N/A** false -- otherwise. 1N/A** null terminates the filename; stores it in map 1N/A ** There is no check whether there is really an argument, 1N/A ** but that's not important enough to warrant extra code. 1N/A** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 1N/A** It also adds the map_app string. It can be used as a utility 1N/A** in the map_lookup method. 1N/A** map -- the map that causes this. 1N/A** s -- the string to rewrite, NOT necessarily null terminated. 1N/A** slen -- the length of s. 1N/A** av -- arguments to interpolate into buf. 1N/A** Pointer to rewritten result. This is static data that 1N/A** should be copied if it is to be saved! 1N/A register const char *s;
1N/A /* count expected size of output (can safely overestimate) */ 1N/A while (l-- > 0 && (c = *
sp++) !=
'\0')
1N/A /* need to malloc additional space */ 1N/A /* assert(len > slen); */ 1N/A while (
slen-- > 0 && (c = *s++) !=
'\0')
1N/A if (
slen-- <= 0 || (c = *s++) ==
'\0')
1N/A /* transliterate argument into output string */ 1N/A** INITMAPS -- rebuild alias maps 1N/A** MAP_INIT -- rebuild a map 1N/A** s -- STAB entry: if map: try to rebuild 1N/A** unused -- unused variable 1N/A** will close already open rebuildable map. 1N/A /* has to be a map */ 1N/A /* if already open, close it (for nested open) */ 1N/A** OPENMAP -- open a map 1N/A** map -- map to open (it must not be open). 1N/A** whether open succeeded. 1N/A /* better safe than sorry... */ 1N/A /* Don't send a map open error out via SMTP */ 1N/A /* don't try again */ 1N/A** CLOSEMAPS -- close all open maps opened by the current pid. 1N/A** bogus -- only close bogus maps. 1N/A** MAP_CLOSE -- close a map opened by the current pid. 1N/A** s -- STAB entry: if map: try to close 1N/A** bogus -- only close bogus maps or MCF_NOTPERSIST maps. 1N/A int bogus;
/* int because of stabapply(), used as bool */ 1N/A ** close the map iff: 1N/A ** it is valid and open and opened by this process 1N/A ** and (!bogus or it's a bogus map or it is not persistent) 1N/A ** negate this: return iff 1N/A ** it is not valid or it is not open or not opened by this process 1N/A ** or (bogus and it's not a bogus map and it's not not-persistent) 1N/A/* this is mainly for backward compatibility in Sun environment */ 1N/A ** Get the domain name from the kernel. 1N/A ** If it does not start with a leading dot, then remove 1N/A ** the first component. Since leading dots are funny Unix 1N/A ** files, we treat a leading "+" the same as a leading dot. 1N/A ** Finally, force there to be at least one dot in the domain name 1N/A ** (i.e. top-level domains are not allowed, like "com", must be 1N/A#
endif /* SUN_EXTENSIONS && SUN_INIT_DOMAIN */ 1N/A** GETCANONNAME -- look up name using service switch 1N/A** host -- the host name to look up. 1N/A** hbsize -- the size of the host buffer. 1N/A** trymx -- if set, try MX records. 1N/A** pttl -- pointer to return TTL (can be NULL). 1N/A** true -- if the host was found. 1N/A** false -- otherwise. 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 1N/A#
endif /* NAMED_BIND */ 1N/A ** Heuristic: if $m is not set, we are running during system 1N/A ** startup. In this case, when a name is apparently found 1N/A ** but has no dot, treat is as not found. This avoids 1N/A ** problems if /etc/hosts has no FQDN but is listed first 1N/A ** in the service switch. 1N/A /* but don't break, as we need to try all methods first */ 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 1N/A /* see if we should continue */ 1N/A ** If returned name is still single token, compensate 1N/A ** by tagging on $m. This is because some sites set 1N/A ** up their DNS or NIS databases wrong. 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */ 1N/A** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 1N/A** name -- the name against which to match. 1N/A** dot -- where to reinsert '.' to get FQDN 1N/A** cbuf -- the location to store the result. 1N/A** cbuflen -- the size of cbuf. 1N/A** true -- if the line matched the desired name. 1N/A** false -- otherwise. 1N/A /* try looking for the FQDN as well */ 1N/A /* try to add a domain on the end of the name */ 1N/A#
endif /* NETINET || NETINET6 */ 1N/A** DNS_MAP_OPEN -- stub to check proper value for dns map type 1N/A /* issue a pseudo-error message */ 1N/A** DNS_MAP_PARSEARGS -- parse dns map definition args. 1N/A** map -- pointer to MAP 1N/A** args -- pointer to the args on the config line. 1N/A** true -- if everything parsed OK. 1N/A** false -- otherwise. 1N/A /* Start of dns_map specific args */ 1N/A case 'R':
/* search field */ 1N/A case 'B':
/* base domain */ 1N/A ** slight abuse of map->map_file; it isn't 1N/A ** used otherwise in this map type. 1N/A ** Assumption: assert(sizeof(int) <= sizeof(ARBPTR_T)); 1N/A ** Even if this assumption is wrong, we use only one byte, 1N/A ** so it doesn't really matter. 1N/A** DNS_MAP_LOOKUP -- perform dns map lookup. 1N/A** map -- pointer to MAP 1N/A** name -- name to lookup 1N/A** av -- arguments to interpolate into buf. 1N/A** statp -- pointer to status (EX_) 1N/A** result of lookup if succeeded. 1N/A** NULL -- otherwise. 1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET6 */ 1N/A /* Only care about the first match */ 1N/A /* concatenate the results */ 1N/A /* Cleanly truncate for rulesets */ 1N/A#
endif /* NAMED_BIND */ 1N/A** NDBM_MAP_OPEN -- DBM-style map open 1N/A /* do initial file and directory checks */ 1N/A syserr(
"dbm map \"%s\": map file %s name too long",
1N/A /* cannot open this map */ 1N/A#
else /* LOCK_ON_OPEN */ 1N/A ** Warning: race condition. Try to lock the file as 1N/A ** quickly as possible after opening it. 1N/A ** This may also have security problems on some systems, 1N/A ** but there isn't anything we can do about it. 1N/A#
else /* NOFTRUNCATE */ 1N/A ** This ugly code opens the map without truncating it, 1N/A ** locks the file, then truncates it. Necessary to 1N/A ** avoid race conditions. 1N/A syserr(
"ndbm_map_open: cannot create database %s",
1N/A syserr(
"ndbm_map_open: cannot truncate %s.{dir,pag}",
1N/A /* if new file, get "before" bits for later filechanged check */ 1N/A syserr(
"ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file",
1N/A /* have to save the lock for the duration (bletch) */ 1N/A /* twiddle bits for dbm_open */ 1N/A#
endif /* NOFTRUNCATE */ 1N/A#
endif /* LOCK_ON_OPEN */ 1N/A /* open the database */ 1N/A#
endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 1N/A /* heuristic: if files are linked, this is actually gdbm */ 1N/A#
endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 1N/A syserr(
"dbm map \"%s\": cannot support GDBM",
1N/A#
endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 1N/A syserr(
"ndbm_map_open(%s): file changed after open",
1N/A ** Need to set map_mtime before the call to aliaswait() 1N/A ** as aliaswait() will call map_lookup() which requires 1N/A ** map_mtime to be set 1N/A#
endif /* LOCK_ON_OPEN */ 1N/A "ownership change on %s failed: %s",
1N/A#
else /* HASFCHOWN */ 1N/A "no fchown(): cannot change ownership on %s",
1N/A message(
"050 no fchown(): cannot change ownership on %s",
1N/A#
endif /* HASFCHOWN */ 1N/A** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 1N/A /* Reopen the database to sync the cache */ 1N/A** NDBM_MAP_STORE -- store a datum in the database 1N/A** NDBM_MAP_CLOSE -- close the database 1N/A#
endif /* NDBM_YP_COMPAT */ 1N/A /* write out the distinguished alias */ 1N/A /* release lock (if needed) */ 1N/A#
endif /* !LOCK_ON_OPEN */ 1N/A** NEWDB (Hash and BTree) Modules 1N/A** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 1N/A** These do rather bizarre locking. If you can lock on open, 1N/A** do that to avoid the condition of opening a database that 1N/A** is being rebuilt. If you don't, we'll try to fake it, but 1N/A** there will be a race condition. If opening for read-only, 1N/A** we immediately release the lock to avoid freezing things up. 1N/A** We really ought to hold the lock, but guarantee that we won't 1N/A** be pokey about it. That's hard to do. 1N/A/* these should be K line arguments */ 1N/A#
endif /* ! DB_CACHE_SIZE */ 1N/A#
endif /* ! DB_HASH_NELEM */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR == 2 */ 1N/A#
endif /* DB_VERSION_MAJOR > 2 */ 1N/A#
endif /* DB_CACHE_SIZE */ 1N/A#
endif /* DB_VERSION_MAJOR < 3 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR == 2 */ 1N/A#
endif /* DB_VERSION_MAJOR > 2 */ 1N/A#
endif /* DB_HASH_NELEM */ 1N/A#
endif /* DB_CACHE_SIZE */ 1N/A#
endif /* DB_VERSION_MAJOR < 3 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR == 2 */ 1N/A#
endif /* DB_VERSION_MAJOR > 2 */ 1N/A /* do initial file and directory checks */ 1N/A syserr(
"map \"%s\": map file %s name too long",
1N/A syserr(
"map \"%s\": map file %s name too long",
1N/A /* cannot open this map */ 1N/A#
else /* LOCK_ON_OPEN */ 1N/A ** Pre-lock the file to avoid race conditions. In particular, 1N/A ** since dbopen returns NULL if the file is zero length, we 1N/A ** must have a locked instance around the dbopen. 1N/A /* make sure no baddies slipped in just before the open... */ 1N/A syserr(
"db_map_open(%s): file changed after pre-open",
buf);
1N/A /* if new file, get the "before" bits for later filechanged check */ 1N/A syserr(
"db_map_open(%s): cannot fstat pre-opened file",
1N/A /* actually lock the pre-opened file */ 1N/A /* set up mode bits for dbopen */ 1N/A#
endif /* LOCK_ON_OPEN */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR > 2 */ 1N/A#
endif /* DB_CACHE_SIZE */ 1N/A#
endif /* DB_HASH_NELEM */ 1N/A#
endif /* DB_OLD_VERSION */ 1N/A#
else /* DB_VERSION_MAJOR > 2 */ 1N/A#
endif /* DB_VERSION_MAJOR > 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* !LOCK_ON_OPEN */ 1N/A#
endif /* !LOCK_ON_OPEN */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* !LOCK_ON_OPEN */ 1N/A#
endif /* LOCK_ON_OPEN */ 1N/A /* try to make sure that at least the database header is on disk */ 1N/A "ownership change on %s failed: %s",
1N/A#
else /* HASFCHOWN */ 1N/A "no fchown(): cannot change ownership on %s",
1N/A message(
"050 no fchown(): cannot change ownership on %s",
1N/A#
endif /* HASFCHOWN */ 1N/A ** Need to set map_mtime before the call to aliaswait() 1N/A ** as aliaswait() will call map_lookup() which requires 1N/A ** map_mtime to be set 1N/A** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 1N/A syserr(
"map \"%s\": map file %s name too long",
1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A /* Reopen the database to sync the cache */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A** DB_MAP_STORE -- store a datum in the NEWDB database 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A** DB_MAP_CLOSE -- add distinguished entries and close the database 1N/A /* write out the distinguished alias */ 1N/A#
endif /* !LOCK_ON_OPEN */ 1N/A#
else /* DB_VERSION_MAJOR < 2 */ 1N/A ** Berkeley DB can use internal shared memory 1N/A ** locking for its memory pool. Closing a map 1N/A ** opened by another process will interfere 1N/A ** with the shared memory and locks of the parent 1N/A ** process leaving things in a bad state. 1N/A ** If this map was not opened by the current 1N/A ** process, do not close the map but recover 1N/A ** the file descriptor. 1N/A#
endif /* DB_VERSION_MAJOR < 2 */ 1N/A syserr(
"db_map_close(%s, %s, %lx): db close failure",
1N/A#
endif /* ! YPERR_BUSY */ 1N/A** NIS_MAP_OPEN -- open DBM map 1N/A /* issue a pseudo-error message */ 1N/A syserr(
"451 4.3.5 NIS map %s specified, but NIS not running",
1N/A /* check to see if this map actually exists */ 1N/A ** We ought to be calling aliaswait() here if this is an 1N/A ** alias file, but powerful HP-UX NIS servers apparently 1N/A ** don't insert the @:@ token into the alias map when it 1N/A ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 1N/A syserr(
"451 4.3.5 Cannot bind to map %s in domain %s: %s",
1N/A** NIS_MAP_LOOKUP -- look up a datum in a NIS map 1N/A** NIS_GETCANONNAME -- look up canonical name in NIS 1N/A /* this should not happen, but.... */ 1N/A** This code donated by Sun Microsystems. 1N/A** NISPLUS_MAP_OPEN -- open nisplus table 1N/A /* set default NISPLUS Domain to $m */ 1N/A /* check to see if this map actually exists */ 1N/A /* try not to overwhelm hosed server */ 1N/A default:
/* all other nisplus errors */ 1N/A syserr(
"451 4.3.5 Cannot find table %s.%s: %s",
1N/A /* default key column is column 0 */ 1N/A /* verify the key column exist */ 1N/A /* default value column is the last column */ 1N/A** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 1N/A ** Copy the name to the key buffer, escaping double quote characters 1N/A ** by doubling them and quoting "]" and "," to avoid having the 1N/A ** NIS+ parser choke on them. 1N/A /* quote the character */ 1N/A /* double the quote */ 1N/A /* construct the query */ 1N/A "%s: lookup error, expected 1 entry, got %d",
1N/A /* ignore second entry */ 1N/A sm_dprintf(
"nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
1N/A /* set the length of the result */ 1N/A** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 1N/A else if (p[
1] !=
'\0')
1N/A /* multi token -- take only first token in nbuf */ 1N/A "[name=%s],hosts.org_dir.%s",
nbuf, &p[
1]);
1N/A "nisplus_getcanonname: lookup error, expected 1 entry, got %d",
1N/A /* ignore second entry */ 1N/A sm_dprintf(
"nisplus_getcanonname(%s), got %d entries, all but first ignored\n",
1N/A sm_dprintf(
"nisplus_getcanonname(%s), found in directory \"%s\"\n",
1N/A sm_dprintf(
"nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
1N/A** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 1N/A /* Should probably swallow initial whitespace here */ 1N/A while (*p !=
'"' && *p !=
'\0')
1N/A#
endif /* defined(LDAPMAP) || defined(PH_MAP) */ 1N/A** LDAPMAP_OPEN -- open LDAP map 1N/A** Connect to the LDAP server. Re-use existing connections since a 1N/A** single server connection to a host (with the same host, port, 1N/A** bind DN, and secret) can answer queries for multiple maps. 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 1N/A /* sendmail doesn't have the ability to write to LDAP (yet) */ 1N/A /* issue a pseudo-error message */ 1N/A /* Already have a connection open to this LDAP server */ 1N/A /* Add this map as head of linked list */ 1N/A /* debug mode: don't actually open an LDAP connection */ 1N/A /* No connection yet, connect */ 1N/A "timeout conning to LDAP server %.100s",
1N/A#
else /* USE_LDAP_INIT */ 1N/A#
endif /* USE_LDAP_INIT */ 1N/A syserr(
"451 4.3.5 %s failed to %s in map %s",
1N/A#
else /* USE_LDAP_INIT */ 1N/A#
endif /* USE_LDAP_INIT */ 1N/A /* Save connection for reuse */ 1N/A** LDAPMAP_CLOSE -- close ldap map 1N/A /* Check if already closed */ 1N/A /* Close the LDAP connection */ 1N/A /* Mark all the maps that share the connection as closed */ 1N/A sm_dprintf(
"ldapmap_close(%s): closed %s (shared LDAP connection)\n",
1N/A** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 1N/A** This only makes sense at Stanford University. 1N/A#
else /* SUNET_ID */ 1N/A#
endif /* SUNET_ID */ 1N/A** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 1N/A#
endif /* SM_LDAP_ARGS != MAX_MAP_ARGS */ 1N/A#
endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */ 1N/A /* Get ldap struct pointer from map */ 1N/A /* free the argv array and its content, no longer needed */ 1N/A ** Do not include keybuf as this error may be shown 1N/A syserr(
"451 4.3.5 Error in ldap_search in map %s",
1N/A#
endif /* LDAP_SERVER_DOWN */ 1N/A /* server disappeared, try reopen on next search */ 1N/A syserr(
"Error in ldap_search in map %s, too few arguments",
1N/A syserr(
"554 5.3.5 Error in ldap_search in map %s, too few arguments",
1N/A#
endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 1N/A#
endif /* _FFR_LDAP_SINGLEDN */ 1N/A /* Create an rpool for search related memory usage */ 1N/A /* Copy result so rpool can be freed */ 1N/A /* need to restart LDAP connection? */ 1N/A syserr(
"Error getting LDAP results in map %s",
1N/A syserr(
"451 4.3.5 Error getting LDAP results in map %s",
1N/A /* Did we match anything? */ 1N/A /* vp != NULL according to test above */ 1N/A** LDAPMAP_FINDCONN -- find an LDAP connection to the server 1N/A** Cache LDAP connections based on the host, port, bind DN, 1N/A** secret, and PID so we don't have multiple connections open to 1N/A** the same server for different maps. Need a separate connection 1N/A** per PID since a parent process may close the map before the 1N/A** child is done with it. 1N/A** lmap -- LDAP map information 1N/A** Symbol table entry for the LDAP connection. 1N/A** LDAPMAP_PARSEARGS -- parse ldap map definition args. 1N/A#
endif /* LDAP_AUTH_KRBV4 */ 1N/A /* Get ldap struct pointer from map */ 1N/A /* Check if setting the initial LDAP defaults */ 1N/A /* We need to alloc an SM_LDAP_STRUCT struct */ 1N/A /* there is no check whether there is really an argument */ 1N/A /* Check if setting up an alias or file class LDAP map */ 1N/A /* Comma separate if used as an alias file */ 1N/A "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))",
1N/A /* default args for an alias LDAP entry */ 1N/A /* Space separate if used as a file class file */ 1N/A#
endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 1N/A /* Start of ldapmap specific args */ 1N/A#
endif /* _FFR_LDAP_SINGLEDN */ 1N/A case 'b':
/* search base */ 1N/A case 'c':
/* network (connect) timeout */ 1N/A#
endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 1N/A case 'd':
/* Dn to bind to server as */ 1N/A case 'H':
/* Use LDAP URI */ 1N/A syserr(
"Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s",
1N/A#
else /* !USE_LDAP_INIT */ 1N/A syserr(
"Can not specify both an LDAP host and an LDAP URI in map %s",
1N/A#
endif /* !USE_LDAP_INIT */ 1N/A case 'h':
/* ldap host */ 1N/A syserr(
"Can not specify both an LDAP host and an LDAP URI in map %s",
1N/A case 'k':
/* search field */ 1N/A case 'l':
/* time limit */ 1N/A case 'M':
/* Method for binding */ 1N/A /* bad config line */ 1N/A syserr(
"Method for binding must be [none|simple|krbv4] (not %s) in map %s",
1N/A case 'n':
/* retrieve attribute names only */ 1N/A ** This is a string that is dependent on the 1N/A ** method used defined by 'M'. 1N/A case 'P':
/* Secret password for binding */ 1N/A case 'p':
/* ldap port */ 1N/A case 'R':
/* don't auto chase referrals */ 1N/A#
else /* LDAP_REFERRALS */ 1N/A syserr(
"compile with -DLDAP_REFERRALS for referral support");
1N/A#
endif /* LDAP_REFERRALS */ 1N/A case 'r':
/* alias dereferencing */ 1N/A /* bad config line */ 1N/A syserr(
"Deref must be [never|always|search|find] (not %s) in map %s",
1N/A case 's':
/* search scope */ 1N/A /* bad config line */ 1N/A syserr(
"Scope must be [base|one|sub] (not %s) in map %s",
1N/A case 'v':
/* attr to return */ 1N/A /* -w should be for passwd, -P should be for version */ 1N/A syserr(
"LDAP version %d exceeds max of %d in map %s",
1N/A#
endif /* LDAP_VERSION_MAX */ 1N/A syserr(
"LDAP version %d is lower than min of %d in map %s",
1N/A#
endif /* LDAP_VERSION_MIN */ 1N/A /* need to account for quoted strings here */ 1N/A while (*++p !=
'"' && *p !=
'\0')
1N/A ** We need to swallow up all the stuff into a struct 1N/A ** and dump it into map->map_dbptr1 1N/A /* need to use method to map secret to passwd string */ 1N/A ** Secret is the name of a file with 1N/A ** the first line as the password. 1N/A /* Already read in the secret? */ 1N/A "ldapmap_parseargs");
1N/A ** Secret is where the ticket file is 1N/A#
endif /* LDAP_AUTH_KRBV4 */ 1N/A default:
/* Should NEVER get here */ 1N/A syserr(
"LDAP map: Illegal value in lmap method");
1N/A ** Save the server from extra work. If request is for a single 1N/A ** match, tell the server to only return enough records to 1N/A ** determine if there is a single match or not. This can not 1N/A ** be one since the server would only return one and we wouldn't 1N/A ** know if there were others available. 1N/A /* If setting defaults, don't process ldap_filter and ldap_attr */ 1N/A /* Prime the attr list with the objectClass attribute */ 1N/A syserr(
"Too many return attributes in %s (max %d)",
1N/A /* allow override on "objectClass" type */ 1N/A ** Don't add something to attribute 1N/A for (j =
1; j < i; j++)
1N/A /* Set in case needed in future code */ 1N/A syserr(
"LDAP recursion requested in %s but no returnable attribute given",
1N/A syserr(
"LDAP recursion requested in %s can not be used with -n",
1N/A** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 1N/A** spec -- map argument string from LDAPDefaults option 1N/A /* Allocate and set the default values */ 1N/A /* look up the class */ 1N/A syserr(
"readcf: LDAPDefaultSpec: class ldap not available");
1N/A /* These should never be set in LDAPDefaults */ 1N/A syserr(
"readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags");
1N/A syserr(
"readcf: option LDAPDefaultSpec: Do not set the LDAP search filter");
1N/A /* don't free, it isn't malloc'ed in parseargs */ 1N/A syserr(
"readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes");
1N/A /* don't free, they aren't malloc'ed in parseargs */ 1N/A** Support for the CCSO Nameserver (ph/qi). 1N/A** This code is intended to replace the so-called "ph mailer". 1N/A** Contributed by Mark D. Roth. Contact him for support. 1N/A/* what version of the ph map code we're running */ 1N/A/* sendmail version for phmap id string */ 1N/A/* assume we're using nph-1.2.x if not specified */ 1N/A/* compatibility for versions older than nph-1.2.0 */ 1N/A#
endif /* NPH_VERSION < 10200 */ 1N/A** PH_MAP_PARSEARGS -- parse ph map definition args. 1N/A /* initialize version string */ 1N/A "sendmail-%s phmap-20010529 libphclient-%s",
1N/A case 'h':
/* PH server list */ 1N/A case 'k':
/* fields to search for */ 1N/A syserr(
"ph_map_parseargs: unknown option -%c", *p);
1N/A /* try to account for quoted strings */ 1N/A while (*++p !=
'"' && *p !=
'\0')
1N/A syserr(
"ph_map_parseargs: -h flag is required");
1N/A** PH_MAP_CLOSE -- close the connection to the ph server 1N/A ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1N/A ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1N/A "ph_map_send_debug: ==> %s",
text);
1N/A "ph_map_recv_debug: <== %s",
text);
1N/A** PH_MAP_OPEN -- sub for opening PH map 1N/A /* issue a pseudo-error message */ 1N/A ** Unset MF_DEFER here so that map_lookup() returns 1N/A ** a temporary failure using the bogus map and 1N/A ** map->map_tapp instead of the default permanent error. 1N/A /* try each host in the list */ 1N/A "timeout connecting to PH server %.100s",
1N/A /* open connection to server */ 1N/A syserr(
"ph_map_open: %s: cannot connect to PH server",
1N/A "ph_map_open: %s: cannot connect to PH server",
1N/A** PH_MAP_LOOKUP -- look up key from ph server 1N/A "timeout during PH lookup of %.100s",
1N/A /* perform lookup */ 1N/A ** Close the connection if the timer popped 1N/A ** or we got a temporary PH error 1N/A** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 1N/A /* there is no check whether there is really an argument */ 1N/A#
endif /* LOG_EMERG */ 1N/A#
endif /* LOG_ALERT */ 1N/A#
endif /* LOG_CRIT */ 1N/A#
endif /* LOG_WARNING */ 1N/A#
endif /* LOG_NOTICE */ 1N/A#
endif /* LOG_INFO */ 1N/A#
endif /* LOG_DEBUG */ 1N/A syserr(
"syslog_map_parseargs: Unknown priority %s",
1N/A** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 1N/A** DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages. 1N/A /* there is no check whether there is really an argument */ 1N/A syserr(
"dprintf map \"%s\", file %s: -d should specify a number, not %s",
1N/A** DPRINTF_MAP_LOOKUP -- rewrite and print message. Always return empty string 1N/A#
endif /* _FFR_DPRINTF_MAP */ 1N/A /* issue a pseudo-error message */ 1N/A syserr(
"451 4.3.5 cannot initialize Hesiod map (%s)",
1N/A#
else /* HESIOD_INIT */ 1N/A#
endif /* HESIOD_INIT */ 1N/A#
else /* HESIOD_INIT */ 1N/A#
endif /* HESIOD_INIT */ 1N/A#
else /* HESIOD_INIT */ 1N/A#
endif /* HESIOD_INIT */ 1N/A#
else /* HESIOD_INIT */ 1N/A#
endif /* HESIOD_INIT */ 1N/A** HES_MAP_CLOSE -- free the Hesiod context 1N/A /* Free the hesiod context */ 1N/A#
endif /* HESIOD_INIT */ 1N/A** NeXT NETINFO Modules 1N/A** NI_MAP_OPEN -- open NetInfo Aliases 1N/A** NI_MAP_LOOKUP -- look up a datum in NetInfo 1N/A /* we only accept single token search key */ 1N/A /* Only want the first machine name */ 1N/A** TEXT (unindexed text file) Modules 1N/A** This code donated by Sun Microsystems. 1N/A** TEXT_MAP_OPEN -- open text table 1N/A syserr(
"text map \"%s\": file name required",
1N/A syserr(
"text map \"%s\": file name must be fully qualified",
1N/A /* cannot open this map */ 1N/A syserr(
"text map \"%s\": unsafe map file %s",
1N/A syserr(
"text map \"%s\", file %s: -k should specify a number, not %s",
1N/A syserr(
"text map \"%s\", file %s: -v should specify a number, not %s",
1N/A** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 1N/A /* skip comment line */ 1N/A** TEXT_GETCANONNAME -- look up canonical name in hosts file 1N/A** STAB (Symbol Table) Modules 1N/A** STAB_MAP_LOOKUP -- look up alias in symbol table 1N/A** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 1N/A** STAB_MAP_OPEN -- initialize (reads data file) 1N/A** This is a weird case -- it is only intended as a fallback for 1N/A** aliases. For this reason, opens for write (only during a 1N/A** "newaliases") always fails, and opens for read open the 1N/A** actual underlying text file instead of the database. 1N/A** Tries several types. For back compatibility of aliases. 1N/A** IMPL_MAP_LOOKUP -- lookup in best open database 1N/A** IMPL_MAP_STORE -- store in open databases 1N/A** IMPL_MAP_OPEN -- implicit database open 1N/A#
endif /* NDBM_YP_COMPAT */ 1N/A message(
"WARNING: cannot open alias database %s%s",
1N/A#
else /* defined(NEWDB) || defined(NDBM) */ 1N/A usrerr(
"Cannot rebuild aliases: no database format defined");
1N/A#
endif /* defined(NEWDB) || defined(NDBM) */ 1N/A** IMPL_MAP_CLOSE -- close any open database(s) 1N/A** Provides access to the system password file. 1N/A** USER_MAP_OPEN -- open user map 1N/A** Really just binds field names to field numbers. 1N/A /* issue a pseudo-error message */ 1N/A syserr(
"User map %s: unknown column name %s",
1N/A** USER_MAP_LOOKUP -- look up a user in the passwd file. 1N/A rwval =
"x";
/* passwd no longer supported */ 1N/A** This provides access to arbitrary programs. It should be used 1N/A** only very sparingly, since there is no way to bound the cost 1N/A** of invoking an arbitrary program. 1N/A syserr(
"prog_map_lookup(%s) failed (%s) -- closing",
1N/A /* collect the return value */ 1N/A /* now flush any additional output */ 1N/A /* wait for the process to terminate */ 1N/A syserr(
"prog_map_lookup(%s): child died on signal %d",
1N/A** Sequenced map type. 1N/A** Tries each map in order until something matches, much like 1N/A** implicit. Stores go to the first map in the list that can 1N/A** This is slightly unusual in that there are two interfaces. 1N/A** The "sequence" interface lets you stack maps arbitrarily. 1N/A** The "switch" interface builds a sequence map by looking 1N/A** at a system-dependent configuration file such as 1N/A** We don't need an explicit open, since all maps are 1N/A** SEQ_MAP_PARSE -- Sequenced map parsing 1N/A /* find beginning of map name */ 1N/A syserr(
"Sequence map %s: unknown member map %s",
1N/A syserr(
"Sequence map %s: too many member maps (%d max)",
1N/A** SWITCH_MAP_OPEN -- open a switched map 1N/A** This looks at the system-dependent configuration and builds 1N/A** a sequence map that does the same thing. 1N/A** Every system must define a switch_map_find routine in conf.c 1N/A** that will return the list of service types associated with a 1N/A** given service class. 1N/A syserr(
"Switch map %s: unknown member map %s",
1N/A** SEQ_MAP_CLOSE -- close all underlying maps 1N/A** SEQ_MAP_LOOKUP -- sequenced map lookup 1N/A** SEQ_MAP_STORE -- sequenced map store 1N/A syserr(
"seq_map_store(%s, %s, %s): no writable map",
1N/A int blen;
/* number of elements in ibuf */ 1N/A blen--;
/* for terminating END_OF_FIELDS */ 1N/A syserr(
"field (%d) out of range, only %d substrings in pattern",
1N/A case 'f':
/* case sensitive */ 1N/A case 'b':
/* basic regular expressions */ 1N/A case 's':
/* substring match () syntax */ 1N/A case 'd':
/* delimiter */ 1N/A case 'a':
/* map append */ 1N/A case 'm':
/* matchonly */ 1N/A /* substring matching */ 1N/A /* optional parameter -sfields */ 1N/A /* set default fields */ 1N/A "Warning: regex may cause prescan() failure map=%s lookup=%s",
1N/A#
endif /* MAP_REGEX */ 1N/A /* walk the list of maps looking for the correctly named map */ 1N/A /* if we are looking at a NULL ns_map_list_t, then create a new one */ 1N/A#
endif /* NS_NOPERM */ 1N/A /* Null out trailing \n */ 1N/A ** read arguments for arith map 1N/A ** - no check is made whether they are really numbers 1N/A ** - just ignores args after the second 1N/A /* operator and (at least) two operands given? */ 1N/A r = v[
1] - v[0] +
1;
1N/A "arith_map: unknown operator %c",
1N/A#
endif /* NETINET || NETINET6 */ 1N/A** SOCKET_MAP_OPEN -- open socket table 1N/A /* sendmail doesn't have the ability to write to SOCKET (yet) */ 1N/A /* issue a pseudo-error message */ 1N/A syserr(
"socket map \"%s\": empty or missing socket information",
1N/A /* Copy open connection */ 1N/A /* Add this map as head of linked list */ 1N/A /* XXX It should be put in a library... */ 1N/A /* protocol:filename or protocol:port@host */ 1N/A /* default to AF_UNIX */ 1N/A /* default to AF_INET */ 1N/A /* default to AF_INET6 */ 1N/A#
else /* NETINET6 */ 1N/A /* no protocols available */ 1N/A syserr(
"socket map \"%s\": no valid socket protocols available",
1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETUNIX */ 1N/A#
endif /* NETUNIX */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A#
else /* EPROTONOSUPPORT */ 1N/A#
endif /* EPROTONOSUPPORT */ 1N/A syserr(
"socket map \"%s\": unknown socket type %s",
1N/A /* default to AF_UNIX */ 1N/A /* default to AF_INET */ 1N/A /* default to AF_INET6 */ 1N/A#
else /* NETINET6 */ 1N/A syserr(
"socket map \"%s\": unknown socket type %s",
1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET */ 1N/A syserr(
"socket map \"%s\": local socket name %s too long",
1N/A /* if not safe, don't create */ 1N/A syserr(
"socket map \"%s\": local socket name %s unsafe",
1N/A#
endif /* NETUNIX */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A /* Parse port@host */ 1N/A syserr(
"socket map \"%s\": bad address %s (expected port@host)",
1N/A syserr(
"socket map \"%s\": invalid port number %s",
1N/A#
else /* NO_GETSERVBYNAME */ 1N/A syserr(
"socket map \"%s\": unknown port name %s",
1N/A#
endif /* NO_GETSERVBYNAME */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A syserr(
"socket map \"%s\": Invalid numeric domain spec \"%s\"",
1N/A syserr(
"socket map \"%s\": Invalid numeric domain spec \"%s\"",
1N/A syserr(
"socket map \"%s\": Unknown host name %s",
1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A syserr(
"socket map \"%s\": Unknown protocol for %s (%d)",
1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET || NETINET6 */ 1N/A syserr(
"socket map \"%s\": unknown socket protocol",
1N/A /* nope, actually connecting */ 1N/A#
endif /* NETINET6 */ 1N/A /* couldn't connect.... try next address */ 1N/A /* try next address */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET6 */ 1N/A sm_dprintf(
"socket map \"%s\": error connecting to socket map: %s\n",
1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET6 */ 1N/A /* Save connection for reuse */ 1N/A** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 1N/A** Cache SOCKET connections based on the connection specifier 1N/A** and PID so we don't have multiple connections open to 1N/A** the same server for different maps. Need a separate connection 1N/A** per PID since a parent process may close the map before the 1N/A** child is done with it. 1N/A** conn -- SOCKET map connection specifier 1N/A** Symbol table entry for the SOCKET connection. 1N/A** SOCKET_MAP_CLOSE -- close the socket 1N/A /* Check if already closed */ 1N/A /* Mark all the maps that share the connection as closed */ 1N/A sm_dprintf(
"socket_map_close(%s): closed %s (shared SOCKET connection)\n",
1N/A** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): failed to send lookup request",
1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply",
1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): reply too long: %u",
1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): missing ':' in reply",
1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes",
1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters",
1N/A syserr(
"451 4.3.0 socket_map_lookup(%s): missing ',' in reply",
1N/A /* collect the return value */ 1N/A sm_dprintf(
"socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n",
1N/A#
endif /* SOCKETMAP */