17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers. 37c478bd9Sstevel@tonic-gate * All rights reserved. 47c478bd9Sstevel@tonic-gate * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved. 57c478bd9Sstevel@tonic-gate * Copyright (c) 1992, 1993 67c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 97c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 107c478bd9Sstevel@tonic-gate * the sendmail distribution. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate */ 137c478bd9Sstevel@tonic-gate 147c478bd9Sstevel@tonic-gate /* 157c478bd9Sstevel@tonic-gate * Copyright 1996-2004 Sun Microsystems, Inc. All rights reserved. 167c478bd9Sstevel@tonic-gate * Use is subject to license terms. 177c478bd9Sstevel@tonic-gate */ 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 207c478bd9Sstevel@tonic-gate 217c478bd9Sstevel@tonic-gate #include <sendmail.h> 227c478bd9Sstevel@tonic-gate 23*3ee0e492Sjbeck SM_RCSID("@(#)$Id: map.c,v 8.672 2006/04/18 01:26:41 ca Exp $") 247c478bd9Sstevel@tonic-gate SM_IDSTR(i2, "%W% (Sun) %G%") 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #if LDAPMAP 277c478bd9Sstevel@tonic-gate # include <sm/ldap.h> 287c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #if NDBM 317c478bd9Sstevel@tonic-gate # include <ndbm.h> 327c478bd9Sstevel@tonic-gate # ifdef R_FIRST 337c478bd9Sstevel@tonic-gate ERROR README: You are running the Berkeley DB version of ndbm.h. See 347c478bd9Sstevel@tonic-gate ERROR README: the README file about tweaking Berkeley DB so it can 357c478bd9Sstevel@tonic-gate ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile 367c478bd9Sstevel@tonic-gate ERROR README: and use -DNEWDB instead. 377c478bd9Sstevel@tonic-gate # endif /* R_FIRST */ 387c478bd9Sstevel@tonic-gate #endif /* NDBM */ 397c478bd9Sstevel@tonic-gate #if NEWDB 407c478bd9Sstevel@tonic-gate # include "sm/bdb.h" 417c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 427c478bd9Sstevel@tonic-gate #if NIS 437c478bd9Sstevel@tonic-gate struct dom_binding; /* forward reference needed on IRIX */ 447c478bd9Sstevel@tonic-gate # include <rpcsvc/ypclnt.h> 457c478bd9Sstevel@tonic-gate # if NDBM 467c478bd9Sstevel@tonic-gate # define NDBM_YP_COMPAT /* create YP-compatible NDBM files */ 477c478bd9Sstevel@tonic-gate # endif /* NDBM */ 487c478bd9Sstevel@tonic-gate #endif /* NIS */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #if NEWDB 517c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 527c478bd9Sstevel@tonic-gate static bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); 537c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 547c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2 557c478bd9Sstevel@tonic-gate static bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); 567c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */ 577c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 587c478bd9Sstevel@tonic-gate static bool db_map_open __P((MAP *, int, char *, DBTYPE, void **)); 597c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */ 607c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 617c478bd9Sstevel@tonic-gate static bool extract_canonname __P((char *, char *, char *, char[], int)); 627c478bd9Sstevel@tonic-gate static void map_close __P((STAB *, int)); 637c478bd9Sstevel@tonic-gate static void map_init __P((STAB *, int)); 647c478bd9Sstevel@tonic-gate #ifdef LDAPMAP 657c478bd9Sstevel@tonic-gate static STAB * ldapmap_findconn __P((SM_LDAP_STRUCT *)); 667c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 677c478bd9Sstevel@tonic-gate #if NISPLUS 687c478bd9Sstevel@tonic-gate static bool nisplus_getcanonname __P((char *, int, int *)); 697c478bd9Sstevel@tonic-gate #endif /* NISPLUS */ 707c478bd9Sstevel@tonic-gate #if NIS 717c478bd9Sstevel@tonic-gate static bool nis_getcanonname __P((char *, int, int *)); 727c478bd9Sstevel@tonic-gate #endif /* NIS */ 737c478bd9Sstevel@tonic-gate #if NETINFO 747c478bd9Sstevel@tonic-gate static bool ni_getcanonname __P((char *, int, int *)); 757c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 767c478bd9Sstevel@tonic-gate static bool text_getcanonname __P((char *, int, int *)); 777c478bd9Sstevel@tonic-gate #if SOCKETMAP 787c478bd9Sstevel@tonic-gate static STAB *socket_map_findconn __P((const char*)); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* XXX arbitrary limit for sanity */ 817c478bd9Sstevel@tonic-gate # define SOCKETMAP_MAXL 1000000 827c478bd9Sstevel@tonic-gate #endif /* SOCKETMAP */ 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* default error message for trying to open a map in write mode */ 857c478bd9Sstevel@tonic-gate #ifdef ENOSYS 867c478bd9Sstevel@tonic-gate # define SM_EMAPCANTWRITE ENOSYS 877c478bd9Sstevel@tonic-gate #else /* ENOSYS */ 887c478bd9Sstevel@tonic-gate # ifdef EFTYPE 897c478bd9Sstevel@tonic-gate # define SM_EMAPCANTWRITE EFTYPE 907c478bd9Sstevel@tonic-gate # else /* EFTYPE */ 917c478bd9Sstevel@tonic-gate # define SM_EMAPCANTWRITE ENXIO 927c478bd9Sstevel@tonic-gate # endif /* EFTYPE */ 937c478bd9Sstevel@tonic-gate #endif /* ENOSYS */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate ** MAP.C -- implementations for various map classes. 977c478bd9Sstevel@tonic-gate ** 987c478bd9Sstevel@tonic-gate ** Each map class implements a series of functions: 997c478bd9Sstevel@tonic-gate ** 1007c478bd9Sstevel@tonic-gate ** bool map_parse(MAP *map, char *args) 1017c478bd9Sstevel@tonic-gate ** Parse the arguments from the config file. Return true 1027c478bd9Sstevel@tonic-gate ** if they were ok, false otherwise. Fill in map with the 1037c478bd9Sstevel@tonic-gate ** values. 1047c478bd9Sstevel@tonic-gate ** 1057c478bd9Sstevel@tonic-gate ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) 1067c478bd9Sstevel@tonic-gate ** Look up the key in the given map. If found, do any 1077c478bd9Sstevel@tonic-gate ** rewriting the map wants (including "args" if desired) 1087c478bd9Sstevel@tonic-gate ** and return the value. Set *pstat to the appropriate status 1097c478bd9Sstevel@tonic-gate ** on error and return NULL. Args will be NULL if called 1107c478bd9Sstevel@tonic-gate ** from the alias routines, although this should probably 1117c478bd9Sstevel@tonic-gate ** not be relied upon. It is suggested you call map_rewrite 1127c478bd9Sstevel@tonic-gate ** to return the results -- it takes care of null termination 1137c478bd9Sstevel@tonic-gate ** and uses a dynamically expanded buffer as needed. 1147c478bd9Sstevel@tonic-gate ** 1157c478bd9Sstevel@tonic-gate ** void map_store(MAP *map, char *key, char *value) 1167c478bd9Sstevel@tonic-gate ** Store the key:value pair in the map. 1177c478bd9Sstevel@tonic-gate ** 1187c478bd9Sstevel@tonic-gate ** bool map_open(MAP *map, int mode) 1197c478bd9Sstevel@tonic-gate ** Open the map for the indicated mode. Mode should 1207c478bd9Sstevel@tonic-gate ** be either O_RDONLY or O_RDWR. Return true if it 1217c478bd9Sstevel@tonic-gate ** was opened successfully, false otherwise. If the open 1227c478bd9Sstevel@tonic-gate ** failed and the MF_OPTIONAL flag is not set, it should 1237c478bd9Sstevel@tonic-gate ** also print an error. If the MF_ALIAS bit is set 1247c478bd9Sstevel@tonic-gate ** and this map class understands the @:@ convention, it 1257c478bd9Sstevel@tonic-gate ** should call aliaswait() before returning. 1267c478bd9Sstevel@tonic-gate ** 1277c478bd9Sstevel@tonic-gate ** void map_close(MAP *map) 1287c478bd9Sstevel@tonic-gate ** Close the map. 1297c478bd9Sstevel@tonic-gate ** 1307c478bd9Sstevel@tonic-gate ** This file also includes the implementation for getcanonname. 1317c478bd9Sstevel@tonic-gate ** It is currently implemented in a pretty ad-hoc manner; it ought 1327c478bd9Sstevel@tonic-gate ** to be more properly integrated into the map structure. 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 1367c478bd9Sstevel@tonic-gate # define LOCK_ON_OPEN 1 /* we can open/create a locked file */ 1377c478bd9Sstevel@tonic-gate #else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 1387c478bd9Sstevel@tonic-gate # define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ 1397c478bd9Sstevel@tonic-gate #endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate ** MAP_PARSEARGS -- parse config line arguments for database lookup 1437c478bd9Sstevel@tonic-gate ** 1447c478bd9Sstevel@tonic-gate ** This is a generic version of the map_parse method. 1457c478bd9Sstevel@tonic-gate ** 1467c478bd9Sstevel@tonic-gate ** Parameters: 1477c478bd9Sstevel@tonic-gate ** map -- the map being initialized. 1487c478bd9Sstevel@tonic-gate ** ap -- a pointer to the args on the config line. 1497c478bd9Sstevel@tonic-gate ** 1507c478bd9Sstevel@tonic-gate ** Returns: 1517c478bd9Sstevel@tonic-gate ** true -- if everything parsed OK. 1527c478bd9Sstevel@tonic-gate ** false -- otherwise. 1537c478bd9Sstevel@tonic-gate ** 1547c478bd9Sstevel@tonic-gate ** Side Effects: 1557c478bd9Sstevel@tonic-gate ** null terminates the filename; stores it in map 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate bool 1597c478bd9Sstevel@tonic-gate map_parseargs(map, ap) 1607c478bd9Sstevel@tonic-gate MAP *map; 1617c478bd9Sstevel@tonic-gate char *ap; 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate register char *p = ap; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate ** There is no check whether there is really an argument, 1677c478bd9Sstevel@tonic-gate ** but that's not important enough to warrant extra code. 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 1717c478bd9Sstevel@tonic-gate map->map_spacesub = SpaceSub; /* default value */ 1727c478bd9Sstevel@tonic-gate for (;;) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 1757c478bd9Sstevel@tonic-gate p++; 1767c478bd9Sstevel@tonic-gate if (*p != '-') 1777c478bd9Sstevel@tonic-gate break; 1787c478bd9Sstevel@tonic-gate switch (*++p) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate case 'N': 1817c478bd9Sstevel@tonic-gate map->map_mflags |= MF_INCLNULL; 1827c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate case 'O': 1867c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 1877c478bd9Sstevel@tonic-gate break; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate case 'o': 1907c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPTIONAL; 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate case 'f': 1947c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NOFOLDCASE; 1957c478bd9Sstevel@tonic-gate break; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate case 'm': 1987c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 1997c478bd9Sstevel@tonic-gate break; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate case 'A': 2027c478bd9Sstevel@tonic-gate map->map_mflags |= MF_APPEND; 2037c478bd9Sstevel@tonic-gate break; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate case 'q': 2067c478bd9Sstevel@tonic-gate map->map_mflags |= MF_KEEPQUOTES; 2077c478bd9Sstevel@tonic-gate break; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate case 'a': 2107c478bd9Sstevel@tonic-gate map->map_app = ++p; 2117c478bd9Sstevel@tonic-gate break; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate case 'T': 2147c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 2157c478bd9Sstevel@tonic-gate break; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate case 'k': 2187c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 2197c478bd9Sstevel@tonic-gate continue; 2207c478bd9Sstevel@tonic-gate map->map_keycolnm = p; 2217c478bd9Sstevel@tonic-gate break; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate case 'v': 2247c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 2257c478bd9Sstevel@tonic-gate continue; 2267c478bd9Sstevel@tonic-gate map->map_valcolnm = p; 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate case 'z': 2307c478bd9Sstevel@tonic-gate if (*++p != '\\') 2317c478bd9Sstevel@tonic-gate map->map_coldelim = *p; 2327c478bd9Sstevel@tonic-gate else 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate switch (*++p) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate case 'n': 2377c478bd9Sstevel@tonic-gate map->map_coldelim = '\n'; 2387c478bd9Sstevel@tonic-gate break; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate case 't': 2417c478bd9Sstevel@tonic-gate map->map_coldelim = '\t'; 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate default: 2457c478bd9Sstevel@tonic-gate map->map_coldelim = '\\'; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate case 't': 2517c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 2527c478bd9Sstevel@tonic-gate break; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate case 'S': 2567c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate case 'D': 2607c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 2617c478bd9Sstevel@tonic-gate break; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate default: 2647c478bd9Sstevel@tonic-gate syserr("Illegal option %c map %s", *p, map->map_mname); 2657c478bd9Sstevel@tonic-gate break; 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 2687c478bd9Sstevel@tonic-gate p++; 2697c478bd9Sstevel@tonic-gate if (*p != '\0') 2707c478bd9Sstevel@tonic-gate *p++ = '\0'; 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 2737c478bd9Sstevel@tonic-gate map->map_app = newstr(map->map_app); 2747c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 2757c478bd9Sstevel@tonic-gate map->map_tapp = newstr(map->map_tapp); 2767c478bd9Sstevel@tonic-gate if (map->map_keycolnm != NULL) 2777c478bd9Sstevel@tonic-gate map->map_keycolnm = newstr(map->map_keycolnm); 2787c478bd9Sstevel@tonic-gate if (map->map_valcolnm != NULL) 2797c478bd9Sstevel@tonic-gate map->map_valcolnm = newstr(map->map_valcolnm); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate if (*p != '\0') 2827c478bd9Sstevel@tonic-gate { 2837c478bd9Sstevel@tonic-gate map->map_file = p; 2847c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 2857c478bd9Sstevel@tonic-gate p++; 2867c478bd9Sstevel@tonic-gate if (*p != '\0') 2877c478bd9Sstevel@tonic-gate *p++ = '\0'; 2887c478bd9Sstevel@tonic-gate map->map_file = newstr(map->map_file); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate while (*p != '\0' && isascii(*p) && isspace(*p)) 2927c478bd9Sstevel@tonic-gate p++; 2937c478bd9Sstevel@tonic-gate if (*p != '\0') 2947c478bd9Sstevel@tonic-gate map->map_rebuild = newstr(p); 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate if (map->map_file == NULL && 2977c478bd9Sstevel@tonic-gate !bitset(MCF_OPTFILE, map->map_class->map_cflags)) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate syserr("No file name for %s map %s", 3007c478bd9Sstevel@tonic-gate map->map_class->map_cname, map->map_mname); 3017c478bd9Sstevel@tonic-gate return false; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate return true; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 3077c478bd9Sstevel@tonic-gate ** 3087c478bd9Sstevel@tonic-gate ** It also adds the map_app string. It can be used as a utility 3097c478bd9Sstevel@tonic-gate ** in the map_lookup method. 3107c478bd9Sstevel@tonic-gate ** 3117c478bd9Sstevel@tonic-gate ** Parameters: 3127c478bd9Sstevel@tonic-gate ** map -- the map that causes this. 3137c478bd9Sstevel@tonic-gate ** s -- the string to rewrite, NOT necessarily null terminated. 3147c478bd9Sstevel@tonic-gate ** slen -- the length of s. 3157c478bd9Sstevel@tonic-gate ** av -- arguments to interpolate into buf. 3167c478bd9Sstevel@tonic-gate ** 3177c478bd9Sstevel@tonic-gate ** Returns: 3187c478bd9Sstevel@tonic-gate ** Pointer to rewritten result. This is static data that 3197c478bd9Sstevel@tonic-gate ** should be copied if it is to be saved! 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate char * 3237c478bd9Sstevel@tonic-gate map_rewrite(map, s, slen, av) 3247c478bd9Sstevel@tonic-gate register MAP *map; 3257c478bd9Sstevel@tonic-gate register const char *s; 3267c478bd9Sstevel@tonic-gate size_t slen; 3277c478bd9Sstevel@tonic-gate char **av; 3287c478bd9Sstevel@tonic-gate { 3297c478bd9Sstevel@tonic-gate register char *bp; 3307c478bd9Sstevel@tonic-gate register char c; 3317c478bd9Sstevel@tonic-gate char **avp; 3327c478bd9Sstevel@tonic-gate register char *ap; 3337c478bd9Sstevel@tonic-gate size_t l; 3347c478bd9Sstevel@tonic-gate size_t len; 3357c478bd9Sstevel@tonic-gate static size_t buflen = 0; 3367c478bd9Sstevel@tonic-gate static char *buf = NULL; 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate if (tTd(39, 1)) 3397c478bd9Sstevel@tonic-gate { 3407c478bd9Sstevel@tonic-gate sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s); 3417c478bd9Sstevel@tonic-gate if (av == NULL) 3427c478bd9Sstevel@tonic-gate sm_dprintf(" (nullv)"); 3437c478bd9Sstevel@tonic-gate else 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate for (avp = av; *avp != NULL; avp++) 3467c478bd9Sstevel@tonic-gate sm_dprintf("\n\t%s", *avp); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* count expected size of output (can safely overestimate) */ 3527c478bd9Sstevel@tonic-gate l = len = slen; 3537c478bd9Sstevel@tonic-gate if (av != NULL) 3547c478bd9Sstevel@tonic-gate { 3557c478bd9Sstevel@tonic-gate const char *sp = s; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate while (l-- > 0 && (c = *sp++) != '\0') 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate if (c != '%') 3607c478bd9Sstevel@tonic-gate continue; 3617c478bd9Sstevel@tonic-gate if (l-- <= 0) 3627c478bd9Sstevel@tonic-gate break; 3637c478bd9Sstevel@tonic-gate c = *sp++; 3647c478bd9Sstevel@tonic-gate if (!(isascii(c) && isdigit(c))) 3657c478bd9Sstevel@tonic-gate continue; 3667c478bd9Sstevel@tonic-gate for (avp = av; --c >= '0' && *avp != NULL; avp++) 3677c478bd9Sstevel@tonic-gate continue; 3687c478bd9Sstevel@tonic-gate if (*avp == NULL) 3697c478bd9Sstevel@tonic-gate continue; 3707c478bd9Sstevel@tonic-gate len += strlen(*avp); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 3747c478bd9Sstevel@tonic-gate len += strlen(map->map_app); 3757c478bd9Sstevel@tonic-gate if (buflen < ++len) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate /* need to malloc additional space */ 3787c478bd9Sstevel@tonic-gate buflen = len; 3797c478bd9Sstevel@tonic-gate if (buf != NULL) 3807c478bd9Sstevel@tonic-gate sm_free(buf); 3817c478bd9Sstevel@tonic-gate buf = sm_pmalloc_x(buflen); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate bp = buf; 3857c478bd9Sstevel@tonic-gate if (av == NULL) 3867c478bd9Sstevel@tonic-gate { 3877c478bd9Sstevel@tonic-gate memmove(bp, s, slen); 3887c478bd9Sstevel@tonic-gate bp += slen; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* assert(len > slen); */ 3917c478bd9Sstevel@tonic-gate len -= slen; 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate else 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate while (slen-- > 0 && (c = *s++) != '\0') 3967c478bd9Sstevel@tonic-gate { 3977c478bd9Sstevel@tonic-gate if (c != '%') 3987c478bd9Sstevel@tonic-gate { 3997c478bd9Sstevel@tonic-gate pushc: 4007c478bd9Sstevel@tonic-gate if (len-- <= 1) 4017c478bd9Sstevel@tonic-gate break; 4027c478bd9Sstevel@tonic-gate *bp++ = c; 4037c478bd9Sstevel@tonic-gate continue; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate if (slen-- <= 0 || (c = *s++) == '\0') 4067c478bd9Sstevel@tonic-gate c = '%'; 4077c478bd9Sstevel@tonic-gate if (c == '%') 4087c478bd9Sstevel@tonic-gate goto pushc; 4097c478bd9Sstevel@tonic-gate if (!(isascii(c) && isdigit(c))) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate if (len-- <= 1) 4127c478bd9Sstevel@tonic-gate break; 4137c478bd9Sstevel@tonic-gate *bp++ = '%'; 4147c478bd9Sstevel@tonic-gate goto pushc; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate for (avp = av; --c >= '0' && *avp != NULL; avp++) 4177c478bd9Sstevel@tonic-gate continue; 4187c478bd9Sstevel@tonic-gate if (*avp == NULL) 4197c478bd9Sstevel@tonic-gate continue; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* transliterate argument into output string */ 4227c478bd9Sstevel@tonic-gate for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len) 4237c478bd9Sstevel@tonic-gate *bp++ = c; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate if (map->map_app != NULL && len > 0) 4277c478bd9Sstevel@tonic-gate (void) sm_strlcpy(bp, map->map_app, len); 4287c478bd9Sstevel@tonic-gate else 4297c478bd9Sstevel@tonic-gate *bp = '\0'; 4307c478bd9Sstevel@tonic-gate if (tTd(39, 1)) 4317c478bd9Sstevel@tonic-gate sm_dprintf("map_rewrite => %s\n", buf); 4327c478bd9Sstevel@tonic-gate return buf; 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate ** INITMAPS -- rebuild alias maps 4367c478bd9Sstevel@tonic-gate ** 4377c478bd9Sstevel@tonic-gate ** Parameters: 4387c478bd9Sstevel@tonic-gate ** none. 4397c478bd9Sstevel@tonic-gate ** 4407c478bd9Sstevel@tonic-gate ** Returns: 4417c478bd9Sstevel@tonic-gate ** none. 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate void 4457c478bd9Sstevel@tonic-gate initmaps() 4467c478bd9Sstevel@tonic-gate { 4477c478bd9Sstevel@tonic-gate #if XDEBUG 4487c478bd9Sstevel@tonic-gate checkfd012("entering initmaps"); 4497c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 4507c478bd9Sstevel@tonic-gate stabapply(map_init, 0); 4517c478bd9Sstevel@tonic-gate #if XDEBUG 4527c478bd9Sstevel@tonic-gate checkfd012("exiting initmaps"); 4537c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate ** MAP_INIT -- rebuild a map 4577c478bd9Sstevel@tonic-gate ** 4587c478bd9Sstevel@tonic-gate ** Parameters: 4597c478bd9Sstevel@tonic-gate ** s -- STAB entry: if map: try to rebuild 4607c478bd9Sstevel@tonic-gate ** unused -- unused variable 4617c478bd9Sstevel@tonic-gate ** 4627c478bd9Sstevel@tonic-gate ** Returns: 4637c478bd9Sstevel@tonic-gate ** none. 4647c478bd9Sstevel@tonic-gate ** 4657c478bd9Sstevel@tonic-gate ** Side Effects: 4667c478bd9Sstevel@tonic-gate ** will close already open rebuildable map. 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 4707c478bd9Sstevel@tonic-gate static void 4717c478bd9Sstevel@tonic-gate map_init(s, unused) 4727c478bd9Sstevel@tonic-gate register STAB *s; 4737c478bd9Sstevel@tonic-gate int unused; 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate register MAP *map; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* has to be a map */ 4787c478bd9Sstevel@tonic-gate if (s->s_symtype != ST_MAP) 4797c478bd9Sstevel@tonic-gate return; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate map = &s->s_map; 4827c478bd9Sstevel@tonic-gate if (!bitset(MF_VALID, map->map_mflags)) 4837c478bd9Sstevel@tonic-gate return; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 4867c478bd9Sstevel@tonic-gate sm_dprintf("map_init(%s:%s, %s)\n", 4877c478bd9Sstevel@tonic-gate map->map_class->map_cname == NULL ? "NULL" : 4887c478bd9Sstevel@tonic-gate map->map_class->map_cname, 4897c478bd9Sstevel@tonic-gate map->map_mname == NULL ? "NULL" : map->map_mname, 4907c478bd9Sstevel@tonic-gate map->map_file == NULL ? "NULL" : map->map_file); 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate if (!bitset(MF_ALIAS, map->map_mflags) || 4937c478bd9Sstevel@tonic-gate !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate if (tTd(38, 3)) 4967c478bd9Sstevel@tonic-gate sm_dprintf("\tnot rebuildable\n"); 4977c478bd9Sstevel@tonic-gate return; 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* if already open, close it (for nested open) */ 5017c478bd9Sstevel@tonic-gate if (bitset(MF_OPEN, map->map_mflags)) 5027c478bd9Sstevel@tonic-gate { 5037c478bd9Sstevel@tonic-gate map->map_mflags |= MF_CLOSING; 5047c478bd9Sstevel@tonic-gate map->map_class->map_close(map); 5057c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate (void) rebuildaliases(map, false); 5097c478bd9Sstevel@tonic-gate return; 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate ** OPENMAP -- open a map 5137c478bd9Sstevel@tonic-gate ** 5147c478bd9Sstevel@tonic-gate ** Parameters: 5157c478bd9Sstevel@tonic-gate ** map -- map to open (it must not be open). 5167c478bd9Sstevel@tonic-gate ** 5177c478bd9Sstevel@tonic-gate ** Returns: 5187c478bd9Sstevel@tonic-gate ** whether open succeeded. 5197c478bd9Sstevel@tonic-gate */ 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate bool 5227c478bd9Sstevel@tonic-gate openmap(map) 5237c478bd9Sstevel@tonic-gate MAP *map; 5247c478bd9Sstevel@tonic-gate { 5257c478bd9Sstevel@tonic-gate bool restore = false; 5267c478bd9Sstevel@tonic-gate bool savehold = HoldErrs; 5277c478bd9Sstevel@tonic-gate bool savequick = QuickAbort; 5287c478bd9Sstevel@tonic-gate int saveerrors = Errors; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if (!bitset(MF_VALID, map->map_mflags)) 5317c478bd9Sstevel@tonic-gate return false; 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* better safe than sorry... */ 5347c478bd9Sstevel@tonic-gate if (bitset(MF_OPEN, map->map_mflags)) 5357c478bd9Sstevel@tonic-gate return true; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* Don't send a map open error out via SMTP */ 5387c478bd9Sstevel@tonic-gate if ((OnlyOneError || QuickAbort) && 5397c478bd9Sstevel@tonic-gate (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate restore = true; 5427c478bd9Sstevel@tonic-gate HoldErrs = true; 5437c478bd9Sstevel@tonic-gate QuickAbort = false; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate errno = 0; 5477c478bd9Sstevel@tonic-gate if (map->map_class->map_open(map, O_RDONLY)) 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate if (tTd(38, 4)) 5507c478bd9Sstevel@tonic-gate sm_dprintf("openmap()\t%s:%s %s: valid\n", 5517c478bd9Sstevel@tonic-gate map->map_class->map_cname == NULL ? "NULL" : 5527c478bd9Sstevel@tonic-gate map->map_class->map_cname, 5537c478bd9Sstevel@tonic-gate map->map_mname == NULL ? "NULL" : 5547c478bd9Sstevel@tonic-gate map->map_mname, 5557c478bd9Sstevel@tonic-gate map->map_file == NULL ? "NULL" : 5567c478bd9Sstevel@tonic-gate map->map_file); 5577c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN; 5587c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate else 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate if (tTd(38, 4)) 5637c478bd9Sstevel@tonic-gate sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n", 5647c478bd9Sstevel@tonic-gate map->map_class->map_cname == NULL ? "NULL" : 5657c478bd9Sstevel@tonic-gate map->map_class->map_cname, 5667c478bd9Sstevel@tonic-gate map->map_mname == NULL ? "NULL" : 5677c478bd9Sstevel@tonic-gate map->map_mname, 5687c478bd9Sstevel@tonic-gate map->map_file == NULL ? "NULL" : 5697c478bd9Sstevel@tonic-gate map->map_file, 5707c478bd9Sstevel@tonic-gate errno == 0 ? "" : ": ", 5717c478bd9Sstevel@tonic-gate errno == 0 ? "" : sm_errstring(errno)); 5727c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 5737c478bd9Sstevel@tonic-gate { 5747c478bd9Sstevel@tonic-gate extern MAPCLASS BogusMapClass; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate map->map_orgclass = map->map_class; 5777c478bd9Sstevel@tonic-gate map->map_class = &BogusMapClass; 5787c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN|MF_OPENBOGUS; 5797c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate else 5827c478bd9Sstevel@tonic-gate { 5837c478bd9Sstevel@tonic-gate /* don't try again */ 5847c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_VALID; 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate if (restore) 5897c478bd9Sstevel@tonic-gate { 5907c478bd9Sstevel@tonic-gate Errors = saveerrors; 5917c478bd9Sstevel@tonic-gate HoldErrs = savehold; 5927c478bd9Sstevel@tonic-gate QuickAbort = savequick; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate return bitset(MF_OPEN, map->map_mflags); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate ** CLOSEMAPS -- close all open maps opened by the current pid. 5997c478bd9Sstevel@tonic-gate ** 6007c478bd9Sstevel@tonic-gate ** Parameters: 6017c478bd9Sstevel@tonic-gate ** bogus -- only close bogus maps. 6027c478bd9Sstevel@tonic-gate ** 6037c478bd9Sstevel@tonic-gate ** Returns: 6047c478bd9Sstevel@tonic-gate ** none. 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate void 6087c478bd9Sstevel@tonic-gate closemaps(bogus) 6097c478bd9Sstevel@tonic-gate bool bogus; 6107c478bd9Sstevel@tonic-gate { 6117c478bd9Sstevel@tonic-gate stabapply(map_close, bogus); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate ** MAP_CLOSE -- close a map opened by the current pid. 6157c478bd9Sstevel@tonic-gate ** 6167c478bd9Sstevel@tonic-gate ** Parameters: 6177c478bd9Sstevel@tonic-gate ** s -- STAB entry: if map: try to close 6187c478bd9Sstevel@tonic-gate ** bogus -- only close bogus maps or MCF_NOTPERSIST maps. 6197c478bd9Sstevel@tonic-gate ** 6207c478bd9Sstevel@tonic-gate ** Returns: 6217c478bd9Sstevel@tonic-gate ** none. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 6257c478bd9Sstevel@tonic-gate static void 6267c478bd9Sstevel@tonic-gate map_close(s, bogus) 6277c478bd9Sstevel@tonic-gate register STAB *s; 6287c478bd9Sstevel@tonic-gate int bogus; /* int because of stabapply(), used as bool */ 6297c478bd9Sstevel@tonic-gate { 6307c478bd9Sstevel@tonic-gate MAP *map; 6317c478bd9Sstevel@tonic-gate extern MAPCLASS BogusMapClass; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (s->s_symtype != ST_MAP) 6347c478bd9Sstevel@tonic-gate return; 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate map = &s->s_map; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate ** close the map iff: 6407c478bd9Sstevel@tonic-gate ** it is valid and open and opened by this process 6417c478bd9Sstevel@tonic-gate ** and (!bogus or it's a bogus map or it is not persistent) 6427c478bd9Sstevel@tonic-gate ** negate this: return iff 6437c478bd9Sstevel@tonic-gate ** it is not valid or it is not open or not opened by this process 6447c478bd9Sstevel@tonic-gate ** or (bogus and it's not a bogus map and it's not not-persistent) 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate if (!bitset(MF_VALID, map->map_mflags) || 6487c478bd9Sstevel@tonic-gate !bitset(MF_OPEN, map->map_mflags) || 6497c478bd9Sstevel@tonic-gate bitset(MF_CLOSING, map->map_mflags) || 6507c478bd9Sstevel@tonic-gate map->map_pid != CurrentPid || 6517c478bd9Sstevel@tonic-gate (bogus && map->map_class != &BogusMapClass && 6527c478bd9Sstevel@tonic-gate !bitset(MCF_NOTPERSIST, map->map_class->map_cflags))) 6537c478bd9Sstevel@tonic-gate return; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate if (map->map_class == &BogusMapClass && map->map_orgclass != NULL && 6567c478bd9Sstevel@tonic-gate map->map_orgclass != &BogusMapClass) 6577c478bd9Sstevel@tonic-gate map->map_class = map->map_orgclass; 6587c478bd9Sstevel@tonic-gate if (tTd(38, 5)) 6597c478bd9Sstevel@tonic-gate sm_dprintf("closemaps: closing %s (%s)\n", 6607c478bd9Sstevel@tonic-gate map->map_mname == NULL ? "NULL" : map->map_mname, 6617c478bd9Sstevel@tonic-gate map->map_file == NULL ? "NULL" : map->map_file); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (!bitset(MF_OPENBOGUS, map->map_mflags)) 6647c478bd9Sstevel@tonic-gate { 6657c478bd9Sstevel@tonic-gate map->map_mflags |= MF_CLOSING; 6667c478bd9Sstevel@tonic-gate map->map_class->map_close(map); 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate ** GETCANONNAME -- look up name using service switch 6727c478bd9Sstevel@tonic-gate ** 6737c478bd9Sstevel@tonic-gate ** Parameters: 6747c478bd9Sstevel@tonic-gate ** host -- the host name to look up. 6757c478bd9Sstevel@tonic-gate ** hbsize -- the size of the host buffer. 6767c478bd9Sstevel@tonic-gate ** trymx -- if set, try MX records. 6777c478bd9Sstevel@tonic-gate ** pttl -- pointer to return TTL (can be NULL). 6787c478bd9Sstevel@tonic-gate ** 6797c478bd9Sstevel@tonic-gate ** Returns: 6807c478bd9Sstevel@tonic-gate ** true -- if the host was found. 6817c478bd9Sstevel@tonic-gate ** false -- otherwise. 6827c478bd9Sstevel@tonic-gate */ 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate bool 6857c478bd9Sstevel@tonic-gate getcanonname(host, hbsize, trymx, pttl) 6867c478bd9Sstevel@tonic-gate char *host; 6877c478bd9Sstevel@tonic-gate int hbsize; 6887c478bd9Sstevel@tonic-gate bool trymx; 6897c478bd9Sstevel@tonic-gate int *pttl; 6907c478bd9Sstevel@tonic-gate { 6917c478bd9Sstevel@tonic-gate int nmaps; 6927c478bd9Sstevel@tonic-gate int mapno; 6937c478bd9Sstevel@tonic-gate bool found = false; 6947c478bd9Sstevel@tonic-gate bool got_tempfail = false; 6957c478bd9Sstevel@tonic-gate auto int status; 6967c478bd9Sstevel@tonic-gate char *maptype[MAXMAPSTACK]; 6977c478bd9Sstevel@tonic-gate short mapreturn[MAXMAPACTIONS]; 6987c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 6997c478bd9Sstevel@tonic-gate bool should_try_nis_domain = false; 7007c478bd9Sstevel@tonic-gate static char *nis_domain = NULL; 7017c478bd9Sstevel@tonic-gate extern char *sun_init_domain(); 7027c478bd9Sstevel@tonic-gate #endif 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate nmaps = switch_map_find("hosts", maptype, mapreturn); 7057c478bd9Sstevel@tonic-gate if (pttl != 0) 7067c478bd9Sstevel@tonic-gate *pttl = SM_DEFAULT_TTL; 7077c478bd9Sstevel@tonic-gate for (mapno = 0; mapno < nmaps; mapno++) 7087c478bd9Sstevel@tonic-gate { 7097c478bd9Sstevel@tonic-gate int i; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 7127c478bd9Sstevel@tonic-gate sm_dprintf("getcanonname(%s), trying %s\n", 7137c478bd9Sstevel@tonic-gate host, maptype[mapno]); 7147c478bd9Sstevel@tonic-gate if (strcmp("files", maptype[mapno]) == 0) 7157c478bd9Sstevel@tonic-gate { 7167c478bd9Sstevel@tonic-gate found = text_getcanonname(host, hbsize, &status); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate #if NIS 7197c478bd9Sstevel@tonic-gate else if (strcmp("nis", maptype[mapno]) == 0) 7207c478bd9Sstevel@tonic-gate { 7217c478bd9Sstevel@tonic-gate found = nis_getcanonname(host, hbsize, &status); 7227c478bd9Sstevel@tonic-gate # if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 7237c478bd9Sstevel@tonic-gate if (nis_domain == NULL) 7247c478bd9Sstevel@tonic-gate nis_domain = sun_init_domain(); 7257c478bd9Sstevel@tonic-gate # endif 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate #endif /* NIS */ 7287c478bd9Sstevel@tonic-gate #if NISPLUS 7297c478bd9Sstevel@tonic-gate else if (strcmp("nisplus", maptype[mapno]) == 0) 7307c478bd9Sstevel@tonic-gate { 7317c478bd9Sstevel@tonic-gate found = nisplus_getcanonname(host, hbsize, &status); 7327c478bd9Sstevel@tonic-gate # if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 7337c478bd9Sstevel@tonic-gate if (nis_domain == NULL) 7347c478bd9Sstevel@tonic-gate nis_domain = sun_init_domain(); 7357c478bd9Sstevel@tonic-gate # endif 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate #endif /* NISPLUS */ 7387c478bd9Sstevel@tonic-gate #if NAMED_BIND 7397c478bd9Sstevel@tonic-gate else if (strcmp("dns", maptype[mapno]) == 0) 7407c478bd9Sstevel@tonic-gate { 7417c478bd9Sstevel@tonic-gate found = dns_getcanonname(host, hbsize, trymx, &status, pttl); 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 7447c478bd9Sstevel@tonic-gate #if NETINFO 7457c478bd9Sstevel@tonic-gate else if (strcmp("netinfo", maptype[mapno]) == 0) 7467c478bd9Sstevel@tonic-gate { 7477c478bd9Sstevel@tonic-gate found = ni_getcanonname(host, hbsize, &status); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 7507c478bd9Sstevel@tonic-gate else 7517c478bd9Sstevel@tonic-gate { 7527c478bd9Sstevel@tonic-gate found = false; 7537c478bd9Sstevel@tonic-gate status = EX_UNAVAILABLE; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate /* 7577c478bd9Sstevel@tonic-gate ** Heuristic: if $m is not set, we are running during system 7587c478bd9Sstevel@tonic-gate ** startup. In this case, when a name is apparently found 7597c478bd9Sstevel@tonic-gate ** but has no dot, treat is as not found. This avoids 7607c478bd9Sstevel@tonic-gate ** problems if /etc/hosts has no FQDN but is listed first 7617c478bd9Sstevel@tonic-gate ** in the service switch. 7627c478bd9Sstevel@tonic-gate */ 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate if (found && 7657c478bd9Sstevel@tonic-gate (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL)) 7667c478bd9Sstevel@tonic-gate break; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 7697c478bd9Sstevel@tonic-gate if (found) 7707c478bd9Sstevel@tonic-gate should_try_nis_domain = true; 7717c478bd9Sstevel@tonic-gate /* but don't break, as we need to try all methods first */ 7727c478bd9Sstevel@tonic-gate #endif 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* see if we should continue */ 7757c478bd9Sstevel@tonic-gate if (status == EX_TEMPFAIL) 7767c478bd9Sstevel@tonic-gate { 7777c478bd9Sstevel@tonic-gate i = MA_TRYAGAIN; 7787c478bd9Sstevel@tonic-gate got_tempfail = true; 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate else if (status == EX_NOTFOUND) 7817c478bd9Sstevel@tonic-gate i = MA_NOTFOUND; 7827c478bd9Sstevel@tonic-gate else 7837c478bd9Sstevel@tonic-gate i = MA_UNAVAIL; 7847c478bd9Sstevel@tonic-gate if (bitset(1 << mapno, mapreturn[i])) 7857c478bd9Sstevel@tonic-gate break; 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate if (found) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate char *d; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 7937c478bd9Sstevel@tonic-gate sm_dprintf("getcanonname(%s), found\n", host); 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate ** If returned name is still single token, compensate 7977c478bd9Sstevel@tonic-gate ** by tagging on $m. This is because some sites set 7987c478bd9Sstevel@tonic-gate ** up their DNS or NIS databases wrong. 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if ((d = strchr(host, '.')) == NULL || d[1] == '\0') 8027c478bd9Sstevel@tonic-gate { 8037c478bd9Sstevel@tonic-gate d = macvalue('m', CurEnv); 8047c478bd9Sstevel@tonic-gate if (d != NULL && 8057c478bd9Sstevel@tonic-gate hbsize > (int) (strlen(host) + strlen(d) + 1)) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate if (host[strlen(host) - 1] != '.') 8087c478bd9Sstevel@tonic-gate (void) sm_strlcat2(host, ".", d, 8097c478bd9Sstevel@tonic-gate hbsize); 8107c478bd9Sstevel@tonic-gate else 8117c478bd9Sstevel@tonic-gate (void) sm_strlcat(host, d, hbsize); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate else 8147c478bd9Sstevel@tonic-gate { 8157c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 8167c478bd9Sstevel@tonic-gate if (VendorCode == VENDOR_SUN && 8177c478bd9Sstevel@tonic-gate should_try_nis_domain) 8187c478bd9Sstevel@tonic-gate { 8197c478bd9Sstevel@tonic-gate goto try_nis_domain; 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate #endif 8227c478bd9Sstevel@tonic-gate return false; 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate return true; 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) 8297c478bd9Sstevel@tonic-gate if (VendorCode == VENDOR_SUN && should_try_nis_domain) 8307c478bd9Sstevel@tonic-gate { 8317c478bd9Sstevel@tonic-gate try_nis_domain: 8327c478bd9Sstevel@tonic-gate if (nis_domain != NULL && 8337c478bd9Sstevel@tonic-gate strlen(nis_domain) + strlen(host) + 1 < hbsize) 8347c478bd9Sstevel@tonic-gate { 8357c478bd9Sstevel@tonic-gate (void) sm_strlcat2(host, ".", nis_domain, hbsize); 8367c478bd9Sstevel@tonic-gate return true; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate #endif 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 8427c478bd9Sstevel@tonic-gate sm_dprintf("getcanonname(%s), failed, status=%d\n", host, 8437c478bd9Sstevel@tonic-gate status); 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate if (got_tempfail) 8467c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(TRY_AGAIN); 8477c478bd9Sstevel@tonic-gate else 8487c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(HOST_NOT_FOUND); 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate return false; 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate /* 8537c478bd9Sstevel@tonic-gate ** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry 8547c478bd9Sstevel@tonic-gate ** 8557c478bd9Sstevel@tonic-gate ** Parameters: 8567c478bd9Sstevel@tonic-gate ** name -- the name against which to match. 8577c478bd9Sstevel@tonic-gate ** dot -- where to reinsert '.' to get FQDN 8587c478bd9Sstevel@tonic-gate ** line -- the /etc/hosts line. 8597c478bd9Sstevel@tonic-gate ** cbuf -- the location to store the result. 8607c478bd9Sstevel@tonic-gate ** cbuflen -- the size of cbuf. 8617c478bd9Sstevel@tonic-gate ** 8627c478bd9Sstevel@tonic-gate ** Returns: 8637c478bd9Sstevel@tonic-gate ** true -- if the line matched the desired name. 8647c478bd9Sstevel@tonic-gate ** false -- otherwise. 8657c478bd9Sstevel@tonic-gate */ 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate static bool 8687c478bd9Sstevel@tonic-gate extract_canonname(name, dot, line, cbuf, cbuflen) 8697c478bd9Sstevel@tonic-gate char *name; 8707c478bd9Sstevel@tonic-gate char *dot; 8717c478bd9Sstevel@tonic-gate char *line; 8727c478bd9Sstevel@tonic-gate char cbuf[]; 8737c478bd9Sstevel@tonic-gate int cbuflen; 8747c478bd9Sstevel@tonic-gate { 8757c478bd9Sstevel@tonic-gate int i; 8767c478bd9Sstevel@tonic-gate char *p; 8777c478bd9Sstevel@tonic-gate bool found = false; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate cbuf[0] = '\0'; 8807c478bd9Sstevel@tonic-gate if (line[0] == '#') 8817c478bd9Sstevel@tonic-gate return false; 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate for (i = 1; ; i++) 8847c478bd9Sstevel@tonic-gate { 8857c478bd9Sstevel@tonic-gate char nbuf[MAXNAME + 1]; 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate p = get_column(line, i, '\0', nbuf, sizeof nbuf); 8887c478bd9Sstevel@tonic-gate if (p == NULL) 8897c478bd9Sstevel@tonic-gate break; 8907c478bd9Sstevel@tonic-gate if (*p == '\0') 8917c478bd9Sstevel@tonic-gate continue; 8927c478bd9Sstevel@tonic-gate if (cbuf[0] == '\0' || 8937c478bd9Sstevel@tonic-gate (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) 8947c478bd9Sstevel@tonic-gate { 8957c478bd9Sstevel@tonic-gate (void) sm_strlcpy(cbuf, p, cbuflen); 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate if (sm_strcasecmp(name, p) == 0) 8987c478bd9Sstevel@tonic-gate found = true; 8997c478bd9Sstevel@tonic-gate else if (dot != NULL) 9007c478bd9Sstevel@tonic-gate { 9017c478bd9Sstevel@tonic-gate /* try looking for the FQDN as well */ 9027c478bd9Sstevel@tonic-gate *dot = '.'; 9037c478bd9Sstevel@tonic-gate if (sm_strcasecmp(name, p) == 0) 9047c478bd9Sstevel@tonic-gate found = true; 9057c478bd9Sstevel@tonic-gate *dot = '\0'; 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate if (found && strchr(cbuf, '.') == NULL) 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate /* try to add a domain on the end of the name */ 9117c478bd9Sstevel@tonic-gate char *domain = macvalue('m', CurEnv); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if (domain != NULL && 9147c478bd9Sstevel@tonic-gate strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen) 9157c478bd9Sstevel@tonic-gate { 9167c478bd9Sstevel@tonic-gate p = &cbuf[i]; 9177c478bd9Sstevel@tonic-gate *p++ = '.'; 9187c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p, domain, cbuflen - i - 1); 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate return found; 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate ** DNS modules 9267c478bd9Sstevel@tonic-gate */ 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate #if NAMED_BIND 9297c478bd9Sstevel@tonic-gate # if DNSMAP 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate # include "sm_resolve.h" 9327c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 9337c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 9347c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate ** DNS_MAP_OPEN -- stub to check proper value for dns map type 9387c478bd9Sstevel@tonic-gate */ 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate bool 9417c478bd9Sstevel@tonic-gate dns_map_open(map, mode) 9427c478bd9Sstevel@tonic-gate MAP *map; 9437c478bd9Sstevel@tonic-gate int mode; 9447c478bd9Sstevel@tonic-gate { 9457c478bd9Sstevel@tonic-gate if (tTd(38,2)) 9467c478bd9Sstevel@tonic-gate sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 9497c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 9507c478bd9Sstevel@tonic-gate { 9517c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 9527c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 9537c478bd9Sstevel@tonic-gate return false; 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate return true; 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 9597c478bd9Sstevel@tonic-gate ** DNS_MAP_PARSEARGS -- parse dns map definition args. 9607c478bd9Sstevel@tonic-gate ** 9617c478bd9Sstevel@tonic-gate ** Parameters: 9627c478bd9Sstevel@tonic-gate ** map -- pointer to MAP 9637c478bd9Sstevel@tonic-gate ** args -- pointer to the args on the config line. 9647c478bd9Sstevel@tonic-gate ** 9657c478bd9Sstevel@tonic-gate ** Returns: 9667c478bd9Sstevel@tonic-gate ** true -- if everything parsed OK. 9677c478bd9Sstevel@tonic-gate ** false -- otherwise. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTILIMIT 9717c478bd9Sstevel@tonic-gate # if !_FFR_DNSMAP_MULTI 9727c478bd9Sstevel@tonic-gate ERROR README: You must define _FFR_DNSMAP_MULTI to use _FFR_DNSMAP_MULTILIMIT 9737c478bd9Sstevel@tonic-gate # endif /* ! _FFR_DNSMAP_MULTI */ 9747c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTILIMIT */ 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTI 9777c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTILIMIT 9787c478bd9Sstevel@tonic-gate # define map_sizelimit map_lockfd /* overload field */ 9797c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTILIMIT */ 9807c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTI */ 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate struct dns_map 9837c478bd9Sstevel@tonic-gate { 9847c478bd9Sstevel@tonic-gate int dns_m_type; 9857c478bd9Sstevel@tonic-gate }; 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate bool 9887c478bd9Sstevel@tonic-gate dns_map_parseargs(map,args) 9897c478bd9Sstevel@tonic-gate MAP *map; 9907c478bd9Sstevel@tonic-gate char *args; 9917c478bd9Sstevel@tonic-gate { 9927c478bd9Sstevel@tonic-gate register char *p = args; 9937c478bd9Sstevel@tonic-gate struct dns_map *map_p; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate map_p = (struct dns_map *) xalloc(sizeof *map_p); 9967c478bd9Sstevel@tonic-gate map_p->dns_m_type = -1; 9977c478bd9Sstevel@tonic-gate map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate for (;;) 10007c478bd9Sstevel@tonic-gate { 10017c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 10027c478bd9Sstevel@tonic-gate p++; 10037c478bd9Sstevel@tonic-gate if (*p != '-') 10047c478bd9Sstevel@tonic-gate break; 10057c478bd9Sstevel@tonic-gate switch (*++p) 10067c478bd9Sstevel@tonic-gate { 10077c478bd9Sstevel@tonic-gate case 'N': 10087c478bd9Sstevel@tonic-gate map->map_mflags |= MF_INCLNULL; 10097c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 10107c478bd9Sstevel@tonic-gate break; 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate case 'O': 10137c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 10147c478bd9Sstevel@tonic-gate break; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate case 'o': 10177c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPTIONAL; 10187c478bd9Sstevel@tonic-gate break; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate case 'f': 10217c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NOFOLDCASE; 10227c478bd9Sstevel@tonic-gate break; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate case 'm': 10257c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 10267c478bd9Sstevel@tonic-gate break; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate case 'A': 10297c478bd9Sstevel@tonic-gate map->map_mflags |= MF_APPEND; 10307c478bd9Sstevel@tonic-gate break; 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate case 'q': 10337c478bd9Sstevel@tonic-gate map->map_mflags |= MF_KEEPQUOTES; 10347c478bd9Sstevel@tonic-gate break; 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate case 't': 10377c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 10387c478bd9Sstevel@tonic-gate break; 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate case 'a': 10417c478bd9Sstevel@tonic-gate map->map_app = ++p; 10427c478bd9Sstevel@tonic-gate break; 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate case 'T': 10457c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 10467c478bd9Sstevel@tonic-gate break; 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate case 'd': 10497c478bd9Sstevel@tonic-gate { 10507c478bd9Sstevel@tonic-gate char *h; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate ++p; 10537c478bd9Sstevel@tonic-gate h = strchr(p, ' '); 10547c478bd9Sstevel@tonic-gate if (h != NULL) 10557c478bd9Sstevel@tonic-gate *h = '\0'; 10567c478bd9Sstevel@tonic-gate map->map_timeout = convtime(p, 's'); 10577c478bd9Sstevel@tonic-gate if (h != NULL) 10587c478bd9Sstevel@tonic-gate *h = ' '; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate break; 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate case 'r': 10637c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 10647c478bd9Sstevel@tonic-gate continue; 10657c478bd9Sstevel@tonic-gate map->map_retry = atoi(p); 10667c478bd9Sstevel@tonic-gate break; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTI 10697c478bd9Sstevel@tonic-gate case 'z': 10707c478bd9Sstevel@tonic-gate if (*++p != '\\') 10717c478bd9Sstevel@tonic-gate map->map_coldelim = *p; 10727c478bd9Sstevel@tonic-gate else 10737c478bd9Sstevel@tonic-gate { 10747c478bd9Sstevel@tonic-gate switch (*++p) 10757c478bd9Sstevel@tonic-gate { 10767c478bd9Sstevel@tonic-gate case 'n': 10777c478bd9Sstevel@tonic-gate map->map_coldelim = '\n'; 10787c478bd9Sstevel@tonic-gate break; 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate case 't': 10817c478bd9Sstevel@tonic-gate map->map_coldelim = '\t'; 10827c478bd9Sstevel@tonic-gate break; 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate default: 10857c478bd9Sstevel@tonic-gate map->map_coldelim = '\\'; 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate break; 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTILIMIT 10917c478bd9Sstevel@tonic-gate case 'Z': 10927c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 10937c478bd9Sstevel@tonic-gate continue; 10947c478bd9Sstevel@tonic-gate map->map_sizelimit = atoi(p); 10957c478bd9Sstevel@tonic-gate break; 10967c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTILIMIT */ 10977c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTI */ 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate /* Start of dns_map specific args */ 11007c478bd9Sstevel@tonic-gate case 'R': /* search field */ 11017c478bd9Sstevel@tonic-gate { 11027c478bd9Sstevel@tonic-gate char *h; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 11057c478bd9Sstevel@tonic-gate continue; 11067c478bd9Sstevel@tonic-gate h = strchr(p, ' '); 11077c478bd9Sstevel@tonic-gate if (h != NULL) 11087c478bd9Sstevel@tonic-gate *h = '\0'; 11097c478bd9Sstevel@tonic-gate map_p->dns_m_type = dns_string_to_type(p); 11107c478bd9Sstevel@tonic-gate if (h != NULL) 11117c478bd9Sstevel@tonic-gate *h = ' '; 11127c478bd9Sstevel@tonic-gate if (map_p->dns_m_type < 0) 11137c478bd9Sstevel@tonic-gate syserr("dns map %s: wrong type %s", 11147c478bd9Sstevel@tonic-gate map->map_mname, p); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate break; 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_BASE 11197c478bd9Sstevel@tonic-gate case 'B': /* base domain */ 11207c478bd9Sstevel@tonic-gate { 11217c478bd9Sstevel@tonic-gate char *h; 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 11247c478bd9Sstevel@tonic-gate continue; 11257c478bd9Sstevel@tonic-gate h = strchr(p, ' '); 11267c478bd9Sstevel@tonic-gate if (h != NULL) 11277c478bd9Sstevel@tonic-gate *h = '\0'; 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate /* 11307c478bd9Sstevel@tonic-gate ** slight abuse of map->map_file; it isn't 11317c478bd9Sstevel@tonic-gate ** used otherwise in this map type. 11327c478bd9Sstevel@tonic-gate */ 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate map->map_file = newstr(p); 11357c478bd9Sstevel@tonic-gate if (h != NULL) 11367c478bd9Sstevel@tonic-gate *h = ' '; 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate break; 11397c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_BASE */ 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate } 11427c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 11437c478bd9Sstevel@tonic-gate p++; 11447c478bd9Sstevel@tonic-gate if (*p != '\0') 11457c478bd9Sstevel@tonic-gate *p++ = '\0'; 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate if (map_p->dns_m_type < 0) 11487c478bd9Sstevel@tonic-gate syserr("dns map %s: missing -R type", map->map_mname); 11497c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 11507c478bd9Sstevel@tonic-gate map->map_app = newstr(map->map_app); 11517c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 11527c478bd9Sstevel@tonic-gate map->map_tapp = newstr(map->map_tapp); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate ** Assumption: assert(sizeof int <= sizeof(ARBPTR_T)); 11567c478bd9Sstevel@tonic-gate ** Even if this assumption is wrong, we use only one byte, 11577c478bd9Sstevel@tonic-gate ** so it doesn't really matter. 11587c478bd9Sstevel@tonic-gate */ 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate map->map_db1 = (ARBPTR_T) map_p; 11617c478bd9Sstevel@tonic-gate return true; 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate ** DNS_MAP_LOOKUP -- perform dns map lookup. 11667c478bd9Sstevel@tonic-gate ** 11677c478bd9Sstevel@tonic-gate ** Parameters: 11687c478bd9Sstevel@tonic-gate ** map -- pointer to MAP 11697c478bd9Sstevel@tonic-gate ** name -- name to lookup 11707c478bd9Sstevel@tonic-gate ** av -- arguments to interpolate into buf. 11717c478bd9Sstevel@tonic-gate ** statp -- pointer to status (EX_) 11727c478bd9Sstevel@tonic-gate ** 11737c478bd9Sstevel@tonic-gate ** Returns: 11747c478bd9Sstevel@tonic-gate ** result of lookup if succeeded. 11757c478bd9Sstevel@tonic-gate ** NULL -- otherwise. 11767c478bd9Sstevel@tonic-gate */ 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate char * 11797c478bd9Sstevel@tonic-gate dns_map_lookup(map, name, av, statp) 11807c478bd9Sstevel@tonic-gate MAP *map; 11817c478bd9Sstevel@tonic-gate char *name; 11827c478bd9Sstevel@tonic-gate char **av; 11837c478bd9Sstevel@tonic-gate int *statp; 11847c478bd9Sstevel@tonic-gate { 11857c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTI 11867c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTILIMIT 11877c478bd9Sstevel@tonic-gate int resnum = 0; 11887c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTILIMIT */ 11897c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTI */ 11907c478bd9Sstevel@tonic-gate char *vp = NULL, *result = NULL; 11917c478bd9Sstevel@tonic-gate size_t vsize; 11927c478bd9Sstevel@tonic-gate struct dns_map *map_p; 11937c478bd9Sstevel@tonic-gate RESOURCE_RECORD_T *rr = NULL; 11947c478bd9Sstevel@tonic-gate DNS_REPLY_T *r = NULL; 11957c478bd9Sstevel@tonic-gate # if NETINET6 11967c478bd9Sstevel@tonic-gate static char buf6[INET6_ADDRSTRLEN]; 11977c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 12007c478bd9Sstevel@tonic-gate sm_dprintf("dns_map_lookup(%s, %s)\n", 12017c478bd9Sstevel@tonic-gate map->map_mname, name); 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate map_p = (struct dns_map *)(map->map_db1); 12047c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_BASE 12057c478bd9Sstevel@tonic-gate if (map->map_file != NULL && *map->map_file != '\0') 12067c478bd9Sstevel@tonic-gate { 12077c478bd9Sstevel@tonic-gate size_t len; 12087c478bd9Sstevel@tonic-gate char *appdomain; 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate len = strlen(map->map_file) + strlen(name) + 2; 12117c478bd9Sstevel@tonic-gate appdomain = (char *) sm_malloc(len); 12127c478bd9Sstevel@tonic-gate if (appdomain == NULL) 12137c478bd9Sstevel@tonic-gate { 12147c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 12157c478bd9Sstevel@tonic-gate return NULL; 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file); 12187c478bd9Sstevel@tonic-gate r = dns_lookup_int(appdomain, C_IN, map_p->dns_m_type, 12197c478bd9Sstevel@tonic-gate map->map_timeout, map->map_retry); 12207c478bd9Sstevel@tonic-gate sm_free(appdomain); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate else 12237c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_BASE */ 12247c478bd9Sstevel@tonic-gate { 12257c478bd9Sstevel@tonic-gate r = dns_lookup_int(name, C_IN, map_p->dns_m_type, 12267c478bd9Sstevel@tonic-gate map->map_timeout, map->map_retry); 12277c478bd9Sstevel@tonic-gate } 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate if (r == NULL) 12307c478bd9Sstevel@tonic-gate { 12317c478bd9Sstevel@tonic-gate result = NULL; 12327c478bd9Sstevel@tonic-gate if (h_errno == TRY_AGAIN || transienterror(errno)) 12337c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 12347c478bd9Sstevel@tonic-gate else 12357c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 12367c478bd9Sstevel@tonic-gate goto cleanup; 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate *statp = EX_OK; 12397c478bd9Sstevel@tonic-gate for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next) 12407c478bd9Sstevel@tonic-gate { 12417c478bd9Sstevel@tonic-gate char *type = NULL; 12427c478bd9Sstevel@tonic-gate char *value = NULL; 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate switch (rr->rr_type) 12457c478bd9Sstevel@tonic-gate { 12467c478bd9Sstevel@tonic-gate case T_NS: 12477c478bd9Sstevel@tonic-gate type = "T_NS"; 12487c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_txt; 12497c478bd9Sstevel@tonic-gate break; 12507c478bd9Sstevel@tonic-gate case T_CNAME: 12517c478bd9Sstevel@tonic-gate type = "T_CNAME"; 12527c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_txt; 12537c478bd9Sstevel@tonic-gate break; 12547c478bd9Sstevel@tonic-gate case T_AFSDB: 12557c478bd9Sstevel@tonic-gate type = "T_AFSDB"; 12567c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_mx->mx_r_domain; 12577c478bd9Sstevel@tonic-gate break; 12587c478bd9Sstevel@tonic-gate case T_SRV: 12597c478bd9Sstevel@tonic-gate type = "T_SRV"; 12607c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_srv->srv_r_target; 12617c478bd9Sstevel@tonic-gate break; 12627c478bd9Sstevel@tonic-gate case T_PTR: 12637c478bd9Sstevel@tonic-gate type = "T_PTR"; 12647c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_txt; 12657c478bd9Sstevel@tonic-gate break; 12667c478bd9Sstevel@tonic-gate case T_TXT: 12677c478bd9Sstevel@tonic-gate type = "T_TXT"; 12687c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_txt; 12697c478bd9Sstevel@tonic-gate break; 12707c478bd9Sstevel@tonic-gate case T_MX: 12717c478bd9Sstevel@tonic-gate type = "T_MX"; 12727c478bd9Sstevel@tonic-gate value = rr->rr_u.rr_mx->mx_r_domain; 12737c478bd9Sstevel@tonic-gate break; 12747c478bd9Sstevel@tonic-gate # if NETINET 12757c478bd9Sstevel@tonic-gate case T_A: 12767c478bd9Sstevel@tonic-gate type = "T_A"; 12777c478bd9Sstevel@tonic-gate value = inet_ntoa(*(rr->rr_u.rr_a)); 12787c478bd9Sstevel@tonic-gate break; 12797c478bd9Sstevel@tonic-gate # endif /* NETINET */ 12807c478bd9Sstevel@tonic-gate # if NETINET6 12817c478bd9Sstevel@tonic-gate case T_AAAA: 12827c478bd9Sstevel@tonic-gate type = "T_AAAA"; 12837c478bd9Sstevel@tonic-gate value = anynet_ntop(rr->rr_u.rr_aaaa, buf6, 12847c478bd9Sstevel@tonic-gate sizeof buf6); 12857c478bd9Sstevel@tonic-gate break; 12867c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate (void) strreplnonprt(value, 'X'); 12907c478bd9Sstevel@tonic-gate if (map_p->dns_m_type != rr->rr_type) 12917c478bd9Sstevel@tonic-gate { 12927c478bd9Sstevel@tonic-gate if (tTd(38, 40)) 12937c478bd9Sstevel@tonic-gate sm_dprintf("\tskipping type %s (%d) value %s\n", 12947c478bd9Sstevel@tonic-gate type != NULL ? type : "<UNKNOWN>", 12957c478bd9Sstevel@tonic-gate rr->rr_type, 12967c478bd9Sstevel@tonic-gate value != NULL ? value : "<NO VALUE>"); 12977c478bd9Sstevel@tonic-gate continue; 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate # if NETINET6 13017c478bd9Sstevel@tonic-gate if (rr->rr_type == T_AAAA && value == NULL) 13027c478bd9Sstevel@tonic-gate { 13037c478bd9Sstevel@tonic-gate result = NULL; 13047c478bd9Sstevel@tonic-gate *statp = EX_DATAERR; 13057c478bd9Sstevel@tonic-gate if (tTd(38, 40)) 13067c478bd9Sstevel@tonic-gate sm_dprintf("\tbad T_AAAA conversion\n"); 13077c478bd9Sstevel@tonic-gate goto cleanup; 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 13107c478bd9Sstevel@tonic-gate if (tTd(38, 40)) 13117c478bd9Sstevel@tonic-gate sm_dprintf("\tfound type %s (%d) value %s\n", 13127c478bd9Sstevel@tonic-gate type != NULL ? type : "<UNKNOWN>", 13137c478bd9Sstevel@tonic-gate rr->rr_type, 13147c478bd9Sstevel@tonic-gate value != NULL ? value : "<NO VALUE>"); 13157c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTI 13167c478bd9Sstevel@tonic-gate if (value != NULL && 13177c478bd9Sstevel@tonic-gate (map->map_coldelim == '\0' || 13187c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTILIMIT 13197c478bd9Sstevel@tonic-gate map->map_sizelimit == 1 || 13207c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTILIMIT */ 13217c478bd9Sstevel@tonic-gate bitset(MF_MATCHONLY, map->map_mflags))) 13227c478bd9Sstevel@tonic-gate { 13237c478bd9Sstevel@tonic-gate /* Only care about the first match */ 13247c478bd9Sstevel@tonic-gate vp = newstr(value); 13257c478bd9Sstevel@tonic-gate break; 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate else if (vp == NULL) 13287c478bd9Sstevel@tonic-gate { 13297c478bd9Sstevel@tonic-gate /* First result */ 13307c478bd9Sstevel@tonic-gate vp = newstr(value); 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate else 13337c478bd9Sstevel@tonic-gate { 13347c478bd9Sstevel@tonic-gate /* concatenate the results */ 13357c478bd9Sstevel@tonic-gate int sz; 13367c478bd9Sstevel@tonic-gate char *new; 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate sz = strlen(vp) + strlen(value) + 2; 13397c478bd9Sstevel@tonic-gate new = xalloc(sz); 13407c478bd9Sstevel@tonic-gate (void) sm_snprintf(new, sz, "%s%c%s", 13417c478bd9Sstevel@tonic-gate vp, map->map_coldelim, value); 13427c478bd9Sstevel@tonic-gate sm_free(vp); 13437c478bd9Sstevel@tonic-gate vp = new; 13447c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTILIMIT 13457c478bd9Sstevel@tonic-gate if (map->map_sizelimit > 0 && 13467c478bd9Sstevel@tonic-gate ++resnum >= map->map_sizelimit) 13477c478bd9Sstevel@tonic-gate break; 13487c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTILIMIT */ 13497c478bd9Sstevel@tonic-gate } 13507c478bd9Sstevel@tonic-gate # else /* _FFR_DNSMAP_MULTI */ 13517c478bd9Sstevel@tonic-gate vp = value; 13527c478bd9Sstevel@tonic-gate break; 13537c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTI */ 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate if (vp == NULL) 13567c478bd9Sstevel@tonic-gate { 13577c478bd9Sstevel@tonic-gate result = NULL; 13587c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 13597c478bd9Sstevel@tonic-gate if (tTd(38, 40)) 13607c478bd9Sstevel@tonic-gate sm_dprintf("\tno match found\n"); 13617c478bd9Sstevel@tonic-gate goto cleanup; 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTI 13657c478bd9Sstevel@tonic-gate /* Cleanly truncate for rulesets */ 13667c478bd9Sstevel@tonic-gate truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim); 13677c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTI */ 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate vsize = strlen(vp); 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if (LogLevel > 9) 13727c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s", 13737c478bd9Sstevel@tonic-gate name, vp); 13747c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 13757c478bd9Sstevel@tonic-gate result = map_rewrite(map, name, strlen(name), NULL); 13767c478bd9Sstevel@tonic-gate else 13777c478bd9Sstevel@tonic-gate result = map_rewrite(map, vp, vsize, av); 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate cleanup: 13807c478bd9Sstevel@tonic-gate # if _FFR_DNSMAP_MULTI 13817c478bd9Sstevel@tonic-gate if (vp != NULL) 13827c478bd9Sstevel@tonic-gate sm_free(vp); 13837c478bd9Sstevel@tonic-gate # endif /* _FFR_DNSMAP_MULTI */ 13847c478bd9Sstevel@tonic-gate if (r != NULL) 13857c478bd9Sstevel@tonic-gate dns_free_data(r); 13867c478bd9Sstevel@tonic-gate return result; 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate # endif /* DNSMAP */ 13897c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate /* 13927c478bd9Sstevel@tonic-gate ** NDBM modules 13937c478bd9Sstevel@tonic-gate */ 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate #if NDBM 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate /* 13987c478bd9Sstevel@tonic-gate ** NDBM_MAP_OPEN -- DBM-style map open 13997c478bd9Sstevel@tonic-gate */ 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate bool 14027c478bd9Sstevel@tonic-gate ndbm_map_open(map, mode) 14037c478bd9Sstevel@tonic-gate MAP *map; 14047c478bd9Sstevel@tonic-gate int mode; 14057c478bd9Sstevel@tonic-gate { 14067c478bd9Sstevel@tonic-gate register DBM *dbm; 14077c478bd9Sstevel@tonic-gate int save_errno; 14087c478bd9Sstevel@tonic-gate int dfd; 14097c478bd9Sstevel@tonic-gate int pfd; 14107c478bd9Sstevel@tonic-gate long sff; 14117c478bd9Sstevel@tonic-gate int ret; 14127c478bd9Sstevel@tonic-gate int smode = S_IREAD; 14137c478bd9Sstevel@tonic-gate char dirfile[MAXPATHLEN]; 14147c478bd9Sstevel@tonic-gate char pagfile[MAXPATHLEN]; 14157c478bd9Sstevel@tonic-gate struct stat st; 14167c478bd9Sstevel@tonic-gate struct stat std, stp; 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 14197c478bd9Sstevel@tonic-gate sm_dprintf("ndbm_map_open(%s, %s, %d)\n", 14207c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 14217c478bd9Sstevel@tonic-gate map->map_lockfd = -1; 14227c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate /* do initial file and directory checks */ 14257c478bd9Sstevel@tonic-gate if (sm_strlcpyn(dirfile, sizeof dirfile, 2, 14267c478bd9Sstevel@tonic-gate map->map_file, ".dir") >= sizeof dirfile || 14277c478bd9Sstevel@tonic-gate sm_strlcpyn(pagfile, sizeof pagfile, 2, 14287c478bd9Sstevel@tonic-gate map->map_file, ".pag") >= sizeof pagfile) 14297c478bd9Sstevel@tonic-gate { 14307c478bd9Sstevel@tonic-gate errno = 0; 14317c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 14327c478bd9Sstevel@tonic-gate syserr("dbm map \"%s\": map file %s name too long", 14337c478bd9Sstevel@tonic-gate map->map_mname, map->map_file); 14347c478bd9Sstevel@tonic-gate return false; 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate sff = SFF_ROOTOK|SFF_REGONLY; 14377c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 14387c478bd9Sstevel@tonic-gate { 14397c478bd9Sstevel@tonic-gate sff |= SFF_CREAT; 14407c478bd9Sstevel@tonic-gate if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 14417c478bd9Sstevel@tonic-gate sff |= SFF_NOSLINK; 14427c478bd9Sstevel@tonic-gate if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 14437c478bd9Sstevel@tonic-gate sff |= SFF_NOHLINK; 14447c478bd9Sstevel@tonic-gate smode = S_IWRITE; 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate else 14477c478bd9Sstevel@tonic-gate { 14487c478bd9Sstevel@tonic-gate if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 14497c478bd9Sstevel@tonic-gate sff |= SFF_NOWLINK; 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 14527c478bd9Sstevel@tonic-gate sff |= SFF_SAFEDIRPATH; 14537c478bd9Sstevel@tonic-gate ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, 14547c478bd9Sstevel@tonic-gate sff, smode, &std); 14557c478bd9Sstevel@tonic-gate if (ret == 0) 14567c478bd9Sstevel@tonic-gate ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, 14577c478bd9Sstevel@tonic-gate sff, smode, &stp); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate if (ret != 0) 14607c478bd9Sstevel@tonic-gate { 14617c478bd9Sstevel@tonic-gate char *prob = "unsafe"; 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate /* cannot open this map */ 14647c478bd9Sstevel@tonic-gate if (ret == ENOENT) 14657c478bd9Sstevel@tonic-gate prob = "missing"; 14667c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 14677c478bd9Sstevel@tonic-gate sm_dprintf("\t%s map file: %d\n", prob, ret); 14687c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 14697c478bd9Sstevel@tonic-gate syserr("dbm map \"%s\": %s map file %s", 14707c478bd9Sstevel@tonic-gate map->map_mname, prob, map->map_file); 14717c478bd9Sstevel@tonic-gate return false; 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate if (std.st_mode == ST_MODE_NOFILE) 14747c478bd9Sstevel@tonic-gate mode |= O_CREAT|O_EXCL; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN 14777c478bd9Sstevel@tonic-gate if (mode == O_RDONLY) 14787c478bd9Sstevel@tonic-gate mode |= O_SHLOCK; 14797c478bd9Sstevel@tonic-gate else 14807c478bd9Sstevel@tonic-gate mode |= O_TRUNC|O_EXLOCK; 14817c478bd9Sstevel@tonic-gate # else /* LOCK_ON_OPEN */ 14827c478bd9Sstevel@tonic-gate if ((mode & O_ACCMODE) == O_RDWR) 14837c478bd9Sstevel@tonic-gate { 14847c478bd9Sstevel@tonic-gate # if NOFTRUNCATE 14857c478bd9Sstevel@tonic-gate /* 14867c478bd9Sstevel@tonic-gate ** Warning: race condition. Try to lock the file as 14877c478bd9Sstevel@tonic-gate ** quickly as possible after opening it. 14887c478bd9Sstevel@tonic-gate ** This may also have security problems on some systems, 14897c478bd9Sstevel@tonic-gate ** but there isn't anything we can do about it. 14907c478bd9Sstevel@tonic-gate */ 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate mode |= O_TRUNC; 14937c478bd9Sstevel@tonic-gate # else /* NOFTRUNCATE */ 14947c478bd9Sstevel@tonic-gate /* 14957c478bd9Sstevel@tonic-gate ** This ugly code opens the map without truncating it, 14967c478bd9Sstevel@tonic-gate ** locks the file, then truncates it. Necessary to 14977c478bd9Sstevel@tonic-gate ** avoid race conditions. 14987c478bd9Sstevel@tonic-gate */ 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate int dirfd; 15017c478bd9Sstevel@tonic-gate int pagfd; 15027c478bd9Sstevel@tonic-gate long sff = SFF_CREAT|SFF_OPENASROOT; 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 15057c478bd9Sstevel@tonic-gate sff |= SFF_NOSLINK; 15067c478bd9Sstevel@tonic-gate if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 15077c478bd9Sstevel@tonic-gate sff |= SFF_NOHLINK; 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate dirfd = safeopen(dirfile, mode, DBMMODE, sff); 15107c478bd9Sstevel@tonic-gate pagfd = safeopen(pagfile, mode, DBMMODE, sff); 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate if (dirfd < 0 || pagfd < 0) 15137c478bd9Sstevel@tonic-gate { 15147c478bd9Sstevel@tonic-gate save_errno = errno; 15157c478bd9Sstevel@tonic-gate if (dirfd >= 0) 15167c478bd9Sstevel@tonic-gate (void) close(dirfd); 15177c478bd9Sstevel@tonic-gate if (pagfd >= 0) 15187c478bd9Sstevel@tonic-gate (void) close(pagfd); 15197c478bd9Sstevel@tonic-gate errno = save_errno; 15207c478bd9Sstevel@tonic-gate syserr("ndbm_map_open: cannot create database %s", 15217c478bd9Sstevel@tonic-gate map->map_file); 15227c478bd9Sstevel@tonic-gate return false; 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate if (ftruncate(dirfd, (off_t) 0) < 0 || 15257c478bd9Sstevel@tonic-gate ftruncate(pagfd, (off_t) 0) < 0) 15267c478bd9Sstevel@tonic-gate { 15277c478bd9Sstevel@tonic-gate save_errno = errno; 15287c478bd9Sstevel@tonic-gate (void) close(dirfd); 15297c478bd9Sstevel@tonic-gate (void) close(pagfd); 15307c478bd9Sstevel@tonic-gate errno = save_errno; 15317c478bd9Sstevel@tonic-gate syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", 15327c478bd9Sstevel@tonic-gate map->map_file); 15337c478bd9Sstevel@tonic-gate return false; 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate /* if new file, get "before" bits for later filechanged check */ 15377c478bd9Sstevel@tonic-gate if (std.st_mode == ST_MODE_NOFILE && 15387c478bd9Sstevel@tonic-gate (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) 15397c478bd9Sstevel@tonic-gate { 15407c478bd9Sstevel@tonic-gate save_errno = errno; 15417c478bd9Sstevel@tonic-gate (void) close(dirfd); 15427c478bd9Sstevel@tonic-gate (void) close(pagfd); 15437c478bd9Sstevel@tonic-gate errno = save_errno; 15447c478bd9Sstevel@tonic-gate syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", 15457c478bd9Sstevel@tonic-gate map->map_file); 15467c478bd9Sstevel@tonic-gate return false; 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate /* have to save the lock for the duration (bletch) */ 15507c478bd9Sstevel@tonic-gate map->map_lockfd = dirfd; 15517c478bd9Sstevel@tonic-gate (void) close(pagfd); 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate /* twiddle bits for dbm_open */ 15547c478bd9Sstevel@tonic-gate mode &= ~(O_CREAT|O_EXCL); 15557c478bd9Sstevel@tonic-gate # endif /* NOFTRUNCATE */ 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */ 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate /* open the database */ 15607c478bd9Sstevel@tonic-gate dbm = dbm_open(map->map_file, mode, DBMMODE); 15617c478bd9Sstevel@tonic-gate if (dbm == NULL) 15627c478bd9Sstevel@tonic-gate { 15637c478bd9Sstevel@tonic-gate save_errno = errno; 15647c478bd9Sstevel@tonic-gate if (bitset(MF_ALIAS, map->map_mflags) && 15657c478bd9Sstevel@tonic-gate aliaswait(map, ".pag", false)) 15667c478bd9Sstevel@tonic-gate return true; 15677c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN && !NOFTRUNCATE 15687c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 15697c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 15707c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 15717c478bd9Sstevel@tonic-gate errno = save_errno; 15727c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 15737c478bd9Sstevel@tonic-gate syserr("Cannot open DBM database %s", map->map_file); 15747c478bd9Sstevel@tonic-gate return false; 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate dfd = dbm_dirfno(dbm); 15777c478bd9Sstevel@tonic-gate pfd = dbm_pagfno(dbm); 15787c478bd9Sstevel@tonic-gate if (dfd == pfd) 15797c478bd9Sstevel@tonic-gate { 15807c478bd9Sstevel@tonic-gate /* heuristic: if files are linked, this is actually gdbm */ 15817c478bd9Sstevel@tonic-gate dbm_close(dbm); 15827c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN && !NOFTRUNCATE 15837c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 15847c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 15857c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 15867c478bd9Sstevel@tonic-gate errno = 0; 15877c478bd9Sstevel@tonic-gate syserr("dbm map \"%s\": cannot support GDBM", 15887c478bd9Sstevel@tonic-gate map->map_mname); 15897c478bd9Sstevel@tonic-gate return false; 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if (filechanged(dirfile, dfd, &std) || 15937c478bd9Sstevel@tonic-gate filechanged(pagfile, pfd, &stp)) 15947c478bd9Sstevel@tonic-gate { 15957c478bd9Sstevel@tonic-gate save_errno = errno; 15967c478bd9Sstevel@tonic-gate dbm_close(dbm); 15977c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN && !NOFTRUNCATE 15987c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 15997c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 16007c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ 16017c478bd9Sstevel@tonic-gate errno = save_errno; 16027c478bd9Sstevel@tonic-gate syserr("ndbm_map_open(%s): file changed after open", 16037c478bd9Sstevel@tonic-gate map->map_file); 16047c478bd9Sstevel@tonic-gate return false; 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate map->map_db1 = (ARBPTR_T) dbm; 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate /* 16107c478bd9Sstevel@tonic-gate ** Need to set map_mtime before the call to aliaswait() 16117c478bd9Sstevel@tonic-gate ** as aliaswait() will call map_lookup() which requires 16127c478bd9Sstevel@tonic-gate ** map_mtime to be set 16137c478bd9Sstevel@tonic-gate */ 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate if (fstat(pfd, &st) >= 0) 16167c478bd9Sstevel@tonic-gate map->map_mtime = st.st_mtime; 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate if (mode == O_RDONLY) 16197c478bd9Sstevel@tonic-gate { 16207c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN 16217c478bd9Sstevel@tonic-gate if (dfd >= 0) 16227c478bd9Sstevel@tonic-gate (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 16237c478bd9Sstevel@tonic-gate if (pfd >= 0) 16247c478bd9Sstevel@tonic-gate (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); 16257c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */ 16267c478bd9Sstevel@tonic-gate if (bitset(MF_ALIAS, map->map_mflags) && 16277c478bd9Sstevel@tonic-gate !aliaswait(map, ".pag", true)) 16287c478bd9Sstevel@tonic-gate return false; 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate else 16317c478bd9Sstevel@tonic-gate { 16327c478bd9Sstevel@tonic-gate map->map_mflags |= MF_LOCKED; 16337c478bd9Sstevel@tonic-gate if (geteuid() == 0 && TrustedUid != 0) 16347c478bd9Sstevel@tonic-gate { 16357c478bd9Sstevel@tonic-gate # if HASFCHOWN 16367c478bd9Sstevel@tonic-gate if (fchown(dfd, TrustedUid, -1) < 0 || 16377c478bd9Sstevel@tonic-gate fchown(pfd, TrustedUid, -1) < 0) 16387c478bd9Sstevel@tonic-gate { 16397c478bd9Sstevel@tonic-gate int err = errno; 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 16427c478bd9Sstevel@tonic-gate "ownership change on %s failed: %s", 16437c478bd9Sstevel@tonic-gate map->map_file, sm_errstring(err)); 16447c478bd9Sstevel@tonic-gate message("050 ownership change on %s failed: %s", 16457c478bd9Sstevel@tonic-gate map->map_file, sm_errstring(err)); 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate # else /* HASFCHOWN */ 16487c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 16497c478bd9Sstevel@tonic-gate "no fchown(): cannot change ownership on %s", 16507c478bd9Sstevel@tonic-gate map->map_file); 16517c478bd9Sstevel@tonic-gate message("050 no fchown(): cannot change ownership on %s", 16527c478bd9Sstevel@tonic-gate map->map_file); 16537c478bd9Sstevel@tonic-gate # endif /* HASFCHOWN */ 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate return true; 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate /* 16617c478bd9Sstevel@tonic-gate ** NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map 16627c478bd9Sstevel@tonic-gate */ 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate char * 16657c478bd9Sstevel@tonic-gate ndbm_map_lookup(map, name, av, statp) 16667c478bd9Sstevel@tonic-gate MAP *map; 16677c478bd9Sstevel@tonic-gate char *name; 16687c478bd9Sstevel@tonic-gate char **av; 16697c478bd9Sstevel@tonic-gate int *statp; 16707c478bd9Sstevel@tonic-gate { 16717c478bd9Sstevel@tonic-gate datum key, val; 16727c478bd9Sstevel@tonic-gate int dfd, pfd; 16737c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 16747c478bd9Sstevel@tonic-gate struct stat stbuf; 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 16777c478bd9Sstevel@tonic-gate sm_dprintf("ndbm_map_lookup(%s, %s)\n", 16787c478bd9Sstevel@tonic-gate map->map_mname, name); 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate key.dptr = name; 16817c478bd9Sstevel@tonic-gate key.dsize = strlen(name); 16827c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 16837c478bd9Sstevel@tonic-gate { 16847c478bd9Sstevel@tonic-gate if (key.dsize > sizeof keybuf - 1) 16857c478bd9Sstevel@tonic-gate key.dsize = sizeof keybuf - 1; 16867c478bd9Sstevel@tonic-gate memmove(keybuf, key.dptr, key.dsize); 16877c478bd9Sstevel@tonic-gate keybuf[key.dsize] = '\0'; 16887c478bd9Sstevel@tonic-gate makelower(keybuf); 16897c478bd9Sstevel@tonic-gate key.dptr = keybuf; 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate lockdbm: 16927c478bd9Sstevel@tonic-gate dfd = dbm_dirfno((DBM *) map->map_db1); 16937c478bd9Sstevel@tonic-gate if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 16947c478bd9Sstevel@tonic-gate (void) lockfile(dfd, map->map_file, ".dir", LOCK_SH); 16957c478bd9Sstevel@tonic-gate pfd = dbm_pagfno((DBM *) map->map_db1); 16967c478bd9Sstevel@tonic-gate if (pfd < 0 || fstat(pfd, &stbuf) < 0 || 16977c478bd9Sstevel@tonic-gate stbuf.st_mtime > map->map_mtime) 16987c478bd9Sstevel@tonic-gate { 16997c478bd9Sstevel@tonic-gate /* Reopen the database to sync the cache */ 17007c478bd9Sstevel@tonic-gate int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 17017c478bd9Sstevel@tonic-gate : O_RDONLY; 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 17047c478bd9Sstevel@tonic-gate (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 17057c478bd9Sstevel@tonic-gate map->map_mflags |= MF_CLOSING; 17067c478bd9Sstevel@tonic-gate map->map_class->map_close(map); 17077c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 17087c478bd9Sstevel@tonic-gate if (map->map_class->map_open(map, omode)) 17097c478bd9Sstevel@tonic-gate { 17107c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN; 17117c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 17127c478bd9Sstevel@tonic-gate if ((omode && O_ACCMODE) == O_RDWR) 17137c478bd9Sstevel@tonic-gate map->map_mflags |= MF_WRITABLE; 17147c478bd9Sstevel@tonic-gate goto lockdbm; 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate else 17177c478bd9Sstevel@tonic-gate { 17187c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate extern MAPCLASS BogusMapClass; 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 17237c478bd9Sstevel@tonic-gate map->map_orgclass = map->map_class; 17247c478bd9Sstevel@tonic-gate map->map_class = &BogusMapClass; 17257c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN; 17267c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 17277c478bd9Sstevel@tonic-gate syserr("Cannot reopen NDBM database %s", 17287c478bd9Sstevel@tonic-gate map->map_file); 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate return NULL; 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate val.dptr = NULL; 17347c478bd9Sstevel@tonic-gate if (bitset(MF_TRY0NULL, map->map_mflags)) 17357c478bd9Sstevel@tonic-gate { 17367c478bd9Sstevel@tonic-gate val = dbm_fetch((DBM *) map->map_db1, key); 17377c478bd9Sstevel@tonic-gate if (val.dptr != NULL) 17387c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) 17417c478bd9Sstevel@tonic-gate { 17427c478bd9Sstevel@tonic-gate key.dsize++; 17437c478bd9Sstevel@tonic-gate val = dbm_fetch((DBM *) map->map_db1, key); 17447c478bd9Sstevel@tonic-gate if (val.dptr != NULL) 17457c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 17487c478bd9Sstevel@tonic-gate (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); 17497c478bd9Sstevel@tonic-gate if (val.dptr == NULL) 17507c478bd9Sstevel@tonic-gate return NULL; 17517c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 17527c478bd9Sstevel@tonic-gate return map_rewrite(map, name, strlen(name), NULL); 17537c478bd9Sstevel@tonic-gate else 17547c478bd9Sstevel@tonic-gate return map_rewrite(map, val.dptr, val.dsize, av); 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate /* 17597c478bd9Sstevel@tonic-gate ** NDBM_MAP_STORE -- store a datum in the database 17607c478bd9Sstevel@tonic-gate */ 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate void 17637c478bd9Sstevel@tonic-gate ndbm_map_store(map, lhs, rhs) 17647c478bd9Sstevel@tonic-gate register MAP *map; 17657c478bd9Sstevel@tonic-gate char *lhs; 17667c478bd9Sstevel@tonic-gate char *rhs; 17677c478bd9Sstevel@tonic-gate { 17687c478bd9Sstevel@tonic-gate datum key; 17697c478bd9Sstevel@tonic-gate datum data; 17707c478bd9Sstevel@tonic-gate int status; 17717c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate if (tTd(38, 12)) 17747c478bd9Sstevel@tonic-gate sm_dprintf("ndbm_map_store(%s, %s, %s)\n", 17757c478bd9Sstevel@tonic-gate map->map_mname, lhs, rhs); 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate key.dsize = strlen(lhs); 17787c478bd9Sstevel@tonic-gate key.dptr = lhs; 17797c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 17807c478bd9Sstevel@tonic-gate { 17817c478bd9Sstevel@tonic-gate if (key.dsize > sizeof keybuf - 1) 17827c478bd9Sstevel@tonic-gate key.dsize = sizeof keybuf - 1; 17837c478bd9Sstevel@tonic-gate memmove(keybuf, key.dptr, key.dsize); 17847c478bd9Sstevel@tonic-gate keybuf[key.dsize] = '\0'; 17857c478bd9Sstevel@tonic-gate makelower(keybuf); 17867c478bd9Sstevel@tonic-gate key.dptr = keybuf; 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate data.dsize = strlen(rhs); 17907c478bd9Sstevel@tonic-gate data.dptr = rhs; 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate if (bitset(MF_INCLNULL, map->map_mflags)) 17937c478bd9Sstevel@tonic-gate { 17947c478bd9Sstevel@tonic-gate key.dsize++; 17957c478bd9Sstevel@tonic-gate data.dsize++; 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 17997c478bd9Sstevel@tonic-gate if (status > 0) 18007c478bd9Sstevel@tonic-gate { 18017c478bd9Sstevel@tonic-gate if (!bitset(MF_APPEND, map->map_mflags)) 18027c478bd9Sstevel@tonic-gate message("050 Warning: duplicate alias name %s", lhs); 18037c478bd9Sstevel@tonic-gate else 18047c478bd9Sstevel@tonic-gate { 18057c478bd9Sstevel@tonic-gate static char *buf = NULL; 18067c478bd9Sstevel@tonic-gate static int bufsiz = 0; 18077c478bd9Sstevel@tonic-gate auto int xstat; 18087c478bd9Sstevel@tonic-gate datum old; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate old.dptr = ndbm_map_lookup(map, key.dptr, 18117c478bd9Sstevel@tonic-gate (char **) NULL, &xstat); 18127c478bd9Sstevel@tonic-gate if (old.dptr != NULL && *(char *) old.dptr != '\0') 18137c478bd9Sstevel@tonic-gate { 18147c478bd9Sstevel@tonic-gate old.dsize = strlen(old.dptr); 18157c478bd9Sstevel@tonic-gate if (data.dsize + old.dsize + 2 > bufsiz) 18167c478bd9Sstevel@tonic-gate { 18177c478bd9Sstevel@tonic-gate if (buf != NULL) 18187c478bd9Sstevel@tonic-gate (void) sm_free(buf); 18197c478bd9Sstevel@tonic-gate bufsiz = data.dsize + old.dsize + 2; 18207c478bd9Sstevel@tonic-gate buf = sm_pmalloc_x(bufsiz); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(buf, bufsiz, 3, 18237c478bd9Sstevel@tonic-gate data.dptr, ",", old.dptr); 18247c478bd9Sstevel@tonic-gate data.dsize = data.dsize + old.dsize + 1; 18257c478bd9Sstevel@tonic-gate data.dptr = buf; 18267c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 18277c478bd9Sstevel@tonic-gate sm_dprintf("ndbm_map_store append=%s\n", 18287c478bd9Sstevel@tonic-gate data.dptr); 18297c478bd9Sstevel@tonic-gate } 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate status = dbm_store((DBM *) map->map_db1, 18327c478bd9Sstevel@tonic-gate key, data, DBM_REPLACE); 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate if (status != 0) 18357c478bd9Sstevel@tonic-gate syserr("readaliases: dbm put (%s): %d", lhs, status); 18367c478bd9Sstevel@tonic-gate } 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate /* 18407c478bd9Sstevel@tonic-gate ** NDBM_MAP_CLOSE -- close the database 18417c478bd9Sstevel@tonic-gate */ 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate void 18447c478bd9Sstevel@tonic-gate ndbm_map_close(map) 18457c478bd9Sstevel@tonic-gate register MAP *map; 18467c478bd9Sstevel@tonic-gate { 18477c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 18487c478bd9Sstevel@tonic-gate sm_dprintf("ndbm_map_close(%s, %s, %lx)\n", 18497c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, map->map_mflags); 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate if (bitset(MF_WRITABLE, map->map_mflags)) 18527c478bd9Sstevel@tonic-gate { 18537c478bd9Sstevel@tonic-gate # ifdef NDBM_YP_COMPAT 18547c478bd9Sstevel@tonic-gate bool inclnull; 18557c478bd9Sstevel@tonic-gate char buf[MAXHOSTNAMELEN]; 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate inclnull = bitset(MF_INCLNULL, map->map_mflags); 18587c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_INCLNULL; 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate if (strstr(map->map_file, "/yp/") != NULL) 18617c478bd9Sstevel@tonic-gate { 18627c478bd9Sstevel@tonic-gate long save_mflags = map->map_mflags; 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NOFOLDCASE; 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "%010ld", curtime()); 18677c478bd9Sstevel@tonic-gate ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate (void) gethostname(buf, sizeof buf); 18707c478bd9Sstevel@tonic-gate ndbm_map_store(map, "YP_MASTER_NAME", buf); 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate map->map_mflags = save_mflags; 18737c478bd9Sstevel@tonic-gate } 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate if (inclnull) 18767c478bd9Sstevel@tonic-gate map->map_mflags |= MF_INCLNULL; 18777c478bd9Sstevel@tonic-gate # endif /* NDBM_YP_COMPAT */ 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate /* write out the distinguished alias */ 18807c478bd9Sstevel@tonic-gate ndbm_map_store(map, "@", "@"); 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate dbm_close((DBM *) map->map_db1); 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate /* release lock (if needed) */ 18857c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN 18867c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 18877c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 18887c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */ 18897c478bd9Sstevel@tonic-gate } 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate #endif /* NDBM */ 18927c478bd9Sstevel@tonic-gate /* 18937c478bd9Sstevel@tonic-gate ** NEWDB (Hash and BTree) Modules 18947c478bd9Sstevel@tonic-gate */ 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate #if NEWDB 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate /* 18997c478bd9Sstevel@tonic-gate ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 19007c478bd9Sstevel@tonic-gate ** 19017c478bd9Sstevel@tonic-gate ** These do rather bizarre locking. If you can lock on open, 19027c478bd9Sstevel@tonic-gate ** do that to avoid the condition of opening a database that 19037c478bd9Sstevel@tonic-gate ** is being rebuilt. If you don't, we'll try to fake it, but 19047c478bd9Sstevel@tonic-gate ** there will be a race condition. If opening for read-only, 19057c478bd9Sstevel@tonic-gate ** we immediately release the lock to avoid freezing things up. 19067c478bd9Sstevel@tonic-gate ** We really ought to hold the lock, but guarantee that we won't 19077c478bd9Sstevel@tonic-gate ** be pokey about it. That's hard to do. 19087c478bd9Sstevel@tonic-gate */ 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate /* these should be K line arguments */ 19117c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 19127c478bd9Sstevel@tonic-gate # define db_cachesize cachesize 19137c478bd9Sstevel@tonic-gate # define h_nelem nelem 19147c478bd9Sstevel@tonic-gate # ifndef DB_CACHE_SIZE 19157c478bd9Sstevel@tonic-gate # define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ 19167c478bd9Sstevel@tonic-gate # endif /* ! DB_CACHE_SIZE */ 19177c478bd9Sstevel@tonic-gate # ifndef DB_HASH_NELEM 19187c478bd9Sstevel@tonic-gate # define DB_HASH_NELEM 4096 /* (starting) size of hash table */ 19197c478bd9Sstevel@tonic-gate # endif /* ! DB_HASH_NELEM */ 19207c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate bool 19237c478bd9Sstevel@tonic-gate bt_map_open(map, mode) 19247c478bd9Sstevel@tonic-gate MAP *map; 19257c478bd9Sstevel@tonic-gate int mode; 19267c478bd9Sstevel@tonic-gate { 19277c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 19287c478bd9Sstevel@tonic-gate BTREEINFO btinfo; 19297c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 19307c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2 19317c478bd9Sstevel@tonic-gate DB_INFO btinfo; 19327c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */ 19337c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 19347c478bd9Sstevel@tonic-gate void *btinfo = NULL; 19357c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */ 19367c478bd9Sstevel@tonic-gate 19377c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 19387c478bd9Sstevel@tonic-gate sm_dprintf("bt_map_open(%s, %s, %d)\n", 19397c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 3 19427c478bd9Sstevel@tonic-gate memset(&btinfo, '\0', sizeof btinfo); 19437c478bd9Sstevel@tonic-gate # ifdef DB_CACHE_SIZE 19447c478bd9Sstevel@tonic-gate btinfo.db_cachesize = DB_CACHE_SIZE; 19457c478bd9Sstevel@tonic-gate # endif /* DB_CACHE_SIZE */ 19467c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 3 */ 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate bool 19527c478bd9Sstevel@tonic-gate hash_map_open(map, mode) 19537c478bd9Sstevel@tonic-gate MAP *map; 19547c478bd9Sstevel@tonic-gate int mode; 19557c478bd9Sstevel@tonic-gate { 19567c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 19577c478bd9Sstevel@tonic-gate HASHINFO hinfo; 19587c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 19597c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2 19607c478bd9Sstevel@tonic-gate DB_INFO hinfo; 19617c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */ 19627c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 19637c478bd9Sstevel@tonic-gate void *hinfo = NULL; 19647c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */ 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 19677c478bd9Sstevel@tonic-gate sm_dprintf("hash_map_open(%s, %s, %d)\n", 19687c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 3 19717c478bd9Sstevel@tonic-gate memset(&hinfo, '\0', sizeof hinfo); 19727c478bd9Sstevel@tonic-gate # ifdef DB_HASH_NELEM 19737c478bd9Sstevel@tonic-gate hinfo.h_nelem = DB_HASH_NELEM; 19747c478bd9Sstevel@tonic-gate # endif /* DB_HASH_NELEM */ 19757c478bd9Sstevel@tonic-gate # ifdef DB_CACHE_SIZE 19767c478bd9Sstevel@tonic-gate hinfo.db_cachesize = DB_CACHE_SIZE; 19777c478bd9Sstevel@tonic-gate # endif /* DB_CACHE_SIZE */ 19787c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 3 */ 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate return db_map_open(map, mode, "hash", DB_HASH, &hinfo); 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate static bool 19847c478bd9Sstevel@tonic-gate db_map_open(map, mode, mapclassname, dbtype, openinfo) 19857c478bd9Sstevel@tonic-gate MAP *map; 19867c478bd9Sstevel@tonic-gate int mode; 19877c478bd9Sstevel@tonic-gate char *mapclassname; 19887c478bd9Sstevel@tonic-gate DBTYPE dbtype; 19897c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 19907c478bd9Sstevel@tonic-gate const void *openinfo; 19917c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 19927c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2 19937c478bd9Sstevel@tonic-gate DB_INFO *openinfo; 19947c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */ 19957c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 19967c478bd9Sstevel@tonic-gate void **openinfo; 19977c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */ 19987c478bd9Sstevel@tonic-gate { 19997c478bd9Sstevel@tonic-gate DB *db = NULL; 20007c478bd9Sstevel@tonic-gate int i; 20017c478bd9Sstevel@tonic-gate int omode; 20027c478bd9Sstevel@tonic-gate int smode = S_IREAD; 20037c478bd9Sstevel@tonic-gate int fd; 20047c478bd9Sstevel@tonic-gate long sff; 20057c478bd9Sstevel@tonic-gate int save_errno; 20067c478bd9Sstevel@tonic-gate struct stat st; 20077c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate /* do initial file and directory checks */ 20107c478bd9Sstevel@tonic-gate if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf) 20117c478bd9Sstevel@tonic-gate { 20127c478bd9Sstevel@tonic-gate errno = 0; 20137c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 20147c478bd9Sstevel@tonic-gate syserr("map \"%s\": map file %s name too long", 20157c478bd9Sstevel@tonic-gate map->map_mname, map->map_file); 20167c478bd9Sstevel@tonic-gate return false; 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate i = strlen(buf); 20197c478bd9Sstevel@tonic-gate if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 20207c478bd9Sstevel@tonic-gate { 20217c478bd9Sstevel@tonic-gate if (sm_strlcat(buf, ".db", sizeof buf) >= sizeof buf) 20227c478bd9Sstevel@tonic-gate { 20237c478bd9Sstevel@tonic-gate errno = 0; 20247c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 20257c478bd9Sstevel@tonic-gate syserr("map \"%s\": map file %s name too long", 20267c478bd9Sstevel@tonic-gate map->map_mname, map->map_file); 20277c478bd9Sstevel@tonic-gate return false; 20287c478bd9Sstevel@tonic-gate } 20297c478bd9Sstevel@tonic-gate } 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 20327c478bd9Sstevel@tonic-gate omode = mode; 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate sff = SFF_ROOTOK|SFF_REGONLY; 20357c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 20367c478bd9Sstevel@tonic-gate { 20377c478bd9Sstevel@tonic-gate sff |= SFF_CREAT; 20387c478bd9Sstevel@tonic-gate if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) 20397c478bd9Sstevel@tonic-gate sff |= SFF_NOSLINK; 20407c478bd9Sstevel@tonic-gate if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) 20417c478bd9Sstevel@tonic-gate sff |= SFF_NOHLINK; 20427c478bd9Sstevel@tonic-gate smode = S_IWRITE; 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate else 20457c478bd9Sstevel@tonic-gate { 20467c478bd9Sstevel@tonic-gate if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 20477c478bd9Sstevel@tonic-gate sff |= SFF_NOWLINK; 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 20507c478bd9Sstevel@tonic-gate sff |= SFF_SAFEDIRPATH; 20517c478bd9Sstevel@tonic-gate i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate if (i != 0) 20547c478bd9Sstevel@tonic-gate { 20557c478bd9Sstevel@tonic-gate char *prob = "unsafe"; 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate /* cannot open this map */ 20587c478bd9Sstevel@tonic-gate if (i == ENOENT) 20597c478bd9Sstevel@tonic-gate prob = "missing"; 20607c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 20617c478bd9Sstevel@tonic-gate sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i)); 20627c478bd9Sstevel@tonic-gate errno = i; 20637c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 20647c478bd9Sstevel@tonic-gate syserr("%s map \"%s\": %s map file %s", 20657c478bd9Sstevel@tonic-gate mapclassname, map->map_mname, prob, buf); 20667c478bd9Sstevel@tonic-gate return false; 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate if (st.st_mode == ST_MODE_NOFILE) 20697c478bd9Sstevel@tonic-gate omode |= O_CREAT|O_EXCL; 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate map->map_lockfd = -1; 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN 20747c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 20757c478bd9Sstevel@tonic-gate omode |= O_TRUNC|O_EXLOCK; 20767c478bd9Sstevel@tonic-gate else 20777c478bd9Sstevel@tonic-gate omode |= O_SHLOCK; 20787c478bd9Sstevel@tonic-gate # else /* LOCK_ON_OPEN */ 20797c478bd9Sstevel@tonic-gate /* 20807c478bd9Sstevel@tonic-gate ** Pre-lock the file to avoid race conditions. In particular, 20817c478bd9Sstevel@tonic-gate ** since dbopen returns NULL if the file is zero length, we 20827c478bd9Sstevel@tonic-gate ** must have a locked instance around the dbopen. 20837c478bd9Sstevel@tonic-gate */ 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate fd = open(buf, omode, DBMMODE); 20867c478bd9Sstevel@tonic-gate if (fd < 0) 20877c478bd9Sstevel@tonic-gate { 20887c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 20897c478bd9Sstevel@tonic-gate syserr("db_map_open: cannot pre-open database %s", buf); 20907c478bd9Sstevel@tonic-gate return false; 20917c478bd9Sstevel@tonic-gate } 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate /* make sure no baddies slipped in just before the open... */ 20947c478bd9Sstevel@tonic-gate if (filechanged(buf, fd, &st)) 20957c478bd9Sstevel@tonic-gate { 20967c478bd9Sstevel@tonic-gate save_errno = errno; 20977c478bd9Sstevel@tonic-gate (void) close(fd); 20987c478bd9Sstevel@tonic-gate errno = save_errno; 20997c478bd9Sstevel@tonic-gate syserr("db_map_open(%s): file changed after pre-open", buf); 21007c478bd9Sstevel@tonic-gate return false; 21017c478bd9Sstevel@tonic-gate } 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate /* if new file, get the "before" bits for later filechanged check */ 21047c478bd9Sstevel@tonic-gate if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) 21057c478bd9Sstevel@tonic-gate { 21067c478bd9Sstevel@tonic-gate save_errno = errno; 21077c478bd9Sstevel@tonic-gate (void) close(fd); 21087c478bd9Sstevel@tonic-gate errno = save_errno; 21097c478bd9Sstevel@tonic-gate syserr("db_map_open(%s): cannot fstat pre-opened file", 21107c478bd9Sstevel@tonic-gate buf); 21117c478bd9Sstevel@tonic-gate return false; 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate /* actually lock the pre-opened file */ 21157c478bd9Sstevel@tonic-gate if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) 21167c478bd9Sstevel@tonic-gate syserr("db_map_open: cannot lock %s", buf); 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate /* set up mode bits for dbopen */ 21197c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 21207c478bd9Sstevel@tonic-gate omode |= O_TRUNC; 21217c478bd9Sstevel@tonic-gate omode &= ~(O_EXCL|O_CREAT); 21227c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */ 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 21257c478bd9Sstevel@tonic-gate db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); 21267c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 21277c478bd9Sstevel@tonic-gate { 21287c478bd9Sstevel@tonic-gate int flags = 0; 21297c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 21307c478bd9Sstevel@tonic-gate int ret; 21317c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */ 21327c478bd9Sstevel@tonic-gate 21337c478bd9Sstevel@tonic-gate if (mode == O_RDONLY) 21347c478bd9Sstevel@tonic-gate flags |= DB_RDONLY; 21357c478bd9Sstevel@tonic-gate if (bitset(O_CREAT, omode)) 21367c478bd9Sstevel@tonic-gate flags |= DB_CREATE; 21377c478bd9Sstevel@tonic-gate if (bitset(O_TRUNC, omode)) 21387c478bd9Sstevel@tonic-gate flags |= DB_TRUNCATE; 21397c478bd9Sstevel@tonic-gate SM_DB_FLAG_ADD(flags); 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 21427c478bd9Sstevel@tonic-gate ret = db_create(&db, NULL, 0); 21437c478bd9Sstevel@tonic-gate # ifdef DB_CACHE_SIZE 21447c478bd9Sstevel@tonic-gate if (ret == 0 && db != NULL) 21457c478bd9Sstevel@tonic-gate { 21467c478bd9Sstevel@tonic-gate ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); 21477c478bd9Sstevel@tonic-gate if (ret != 0) 21487c478bd9Sstevel@tonic-gate { 21497c478bd9Sstevel@tonic-gate (void) db->close(db, 0); 21507c478bd9Sstevel@tonic-gate db = NULL; 21517c478bd9Sstevel@tonic-gate } 21527c478bd9Sstevel@tonic-gate } 21537c478bd9Sstevel@tonic-gate # endif /* DB_CACHE_SIZE */ 21547c478bd9Sstevel@tonic-gate # ifdef DB_HASH_NELEM 21557c478bd9Sstevel@tonic-gate if (dbtype == DB_HASH && ret == 0 && db != NULL) 21567c478bd9Sstevel@tonic-gate { 21577c478bd9Sstevel@tonic-gate ret = db->set_h_nelem(db, DB_HASH_NELEM); 21587c478bd9Sstevel@tonic-gate if (ret != 0) 21597c478bd9Sstevel@tonic-gate { 21607c478bd9Sstevel@tonic-gate (void) db->close(db, 0); 21617c478bd9Sstevel@tonic-gate db = NULL; 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate } 21647c478bd9Sstevel@tonic-gate # endif /* DB_HASH_NELEM */ 21657c478bd9Sstevel@tonic-gate if (ret == 0 && db != NULL) 21667c478bd9Sstevel@tonic-gate { 21677c478bd9Sstevel@tonic-gate ret = db->open(db, 21687c478bd9Sstevel@tonic-gate DBTXN /* transaction for DB 4.1 */ 21697c478bd9Sstevel@tonic-gate buf, NULL, dbtype, flags, DBMMODE); 21707c478bd9Sstevel@tonic-gate if (ret != 0) 21717c478bd9Sstevel@tonic-gate { 21727c478bd9Sstevel@tonic-gate #ifdef DB_OLD_VERSION 21737c478bd9Sstevel@tonic-gate if (ret == DB_OLD_VERSION) 21747c478bd9Sstevel@tonic-gate ret = EINVAL; 21757c478bd9Sstevel@tonic-gate #endif /* DB_OLD_VERSION */ 21767c478bd9Sstevel@tonic-gate (void) db->close(db, 0); 21777c478bd9Sstevel@tonic-gate db = NULL; 21787c478bd9Sstevel@tonic-gate } 21797c478bd9Sstevel@tonic-gate } 21807c478bd9Sstevel@tonic-gate errno = ret; 21817c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR > 2 */ 21827c478bd9Sstevel@tonic-gate errno = db_open(buf, dbtype, flags, DBMMODE, 21837c478bd9Sstevel@tonic-gate NULL, openinfo, &db); 21847c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */ 21857c478bd9Sstevel@tonic-gate } 21867c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 21877c478bd9Sstevel@tonic-gate save_errno = errno; 21887c478bd9Sstevel@tonic-gate 21897c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN 21907c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 21917c478bd9Sstevel@tonic-gate map->map_lockfd = fd; 21927c478bd9Sstevel@tonic-gate else 21937c478bd9Sstevel@tonic-gate (void) close(fd); 21947c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */ 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate if (db == NULL) 21977c478bd9Sstevel@tonic-gate { 21987c478bd9Sstevel@tonic-gate if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 21997c478bd9Sstevel@tonic-gate aliaswait(map, ".db", false)) 22007c478bd9Sstevel@tonic-gate return true; 22017c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN 22027c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 22037c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 22047c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */ 22057c478bd9Sstevel@tonic-gate errno = save_errno; 22067c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 22077c478bd9Sstevel@tonic-gate syserr("Cannot open %s database %s", 22087c478bd9Sstevel@tonic-gate mapclassname, buf); 22097c478bd9Sstevel@tonic-gate return false; 22107c478bd9Sstevel@tonic-gate } 22117c478bd9Sstevel@tonic-gate 22127c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 22137c478bd9Sstevel@tonic-gate fd = db->fd(db); 22147c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 22157c478bd9Sstevel@tonic-gate fd = -1; 22167c478bd9Sstevel@tonic-gate errno = db->fd(db, &fd); 22177c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 22187c478bd9Sstevel@tonic-gate if (filechanged(buf, fd, &st)) 22197c478bd9Sstevel@tonic-gate { 22207c478bd9Sstevel@tonic-gate save_errno = errno; 22217c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 22227c478bd9Sstevel@tonic-gate (void) db->close(db); 22237c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 22247c478bd9Sstevel@tonic-gate errno = db->close(db, 0); 22257c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 22267c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN 22277c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 22287c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 22297c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */ 22307c478bd9Sstevel@tonic-gate errno = save_errno; 22317c478bd9Sstevel@tonic-gate syserr("db_map_open(%s): file changed after open", buf); 22327c478bd9Sstevel@tonic-gate return false; 22337c478bd9Sstevel@tonic-gate } 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 22367c478bd9Sstevel@tonic-gate map->map_mflags |= MF_LOCKED; 22377c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN 22387c478bd9Sstevel@tonic-gate if (fd >= 0 && mode == O_RDONLY) 22397c478bd9Sstevel@tonic-gate { 22407c478bd9Sstevel@tonic-gate (void) lockfile(fd, buf, NULL, LOCK_UN); 22417c478bd9Sstevel@tonic-gate } 22427c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */ 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate /* try to make sure that at least the database header is on disk */ 22457c478bd9Sstevel@tonic-gate if (mode == O_RDWR) 22467c478bd9Sstevel@tonic-gate { 22477c478bd9Sstevel@tonic-gate (void) db->sync(db, 0); 22487c478bd9Sstevel@tonic-gate if (geteuid() == 0 && TrustedUid != 0) 22497c478bd9Sstevel@tonic-gate { 22507c478bd9Sstevel@tonic-gate # if HASFCHOWN 22517c478bd9Sstevel@tonic-gate if (fchown(fd, TrustedUid, -1) < 0) 22527c478bd9Sstevel@tonic-gate { 22537c478bd9Sstevel@tonic-gate int err = errno; 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 22567c478bd9Sstevel@tonic-gate "ownership change on %s failed: %s", 22577c478bd9Sstevel@tonic-gate buf, sm_errstring(err)); 22587c478bd9Sstevel@tonic-gate message("050 ownership change on %s failed: %s", 22597c478bd9Sstevel@tonic-gate buf, sm_errstring(err)); 22607c478bd9Sstevel@tonic-gate } 22617c478bd9Sstevel@tonic-gate # else /* HASFCHOWN */ 22627c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 22637c478bd9Sstevel@tonic-gate "no fchown(): cannot change ownership on %s", 22647c478bd9Sstevel@tonic-gate map->map_file); 22657c478bd9Sstevel@tonic-gate message("050 no fchown(): cannot change ownership on %s", 22667c478bd9Sstevel@tonic-gate map->map_file); 22677c478bd9Sstevel@tonic-gate # endif /* HASFCHOWN */ 22687c478bd9Sstevel@tonic-gate } 22697c478bd9Sstevel@tonic-gate } 22707c478bd9Sstevel@tonic-gate 22717c478bd9Sstevel@tonic-gate map->map_db2 = (ARBPTR_T) db; 22727c478bd9Sstevel@tonic-gate 22737c478bd9Sstevel@tonic-gate /* 22747c478bd9Sstevel@tonic-gate ** Need to set map_mtime before the call to aliaswait() 22757c478bd9Sstevel@tonic-gate ** as aliaswait() will call map_lookup() which requires 22767c478bd9Sstevel@tonic-gate ** map_mtime to be set 22777c478bd9Sstevel@tonic-gate */ 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate if (fd >= 0 && fstat(fd, &st) >= 0) 22807c478bd9Sstevel@tonic-gate map->map_mtime = st.st_mtime; 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && 22837c478bd9Sstevel@tonic-gate !aliaswait(map, ".db", true)) 22847c478bd9Sstevel@tonic-gate return false; 22857c478bd9Sstevel@tonic-gate return true; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate /* 22907c478bd9Sstevel@tonic-gate ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 22917c478bd9Sstevel@tonic-gate */ 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate char * 22947c478bd9Sstevel@tonic-gate db_map_lookup(map, name, av, statp) 22957c478bd9Sstevel@tonic-gate MAP *map; 22967c478bd9Sstevel@tonic-gate char *name; 22977c478bd9Sstevel@tonic-gate char **av; 22987c478bd9Sstevel@tonic-gate int *statp; 22997c478bd9Sstevel@tonic-gate { 23007c478bd9Sstevel@tonic-gate DBT key, val; 23017c478bd9Sstevel@tonic-gate register DB *db = (DB *) map->map_db2; 23027c478bd9Sstevel@tonic-gate int i; 23037c478bd9Sstevel@tonic-gate int st; 23047c478bd9Sstevel@tonic-gate int save_errno; 23057c478bd9Sstevel@tonic-gate int fd; 23067c478bd9Sstevel@tonic-gate struct stat stbuf; 23077c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 23087c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate memset(&key, '\0', sizeof key); 23117c478bd9Sstevel@tonic-gate memset(&val, '\0', sizeof val); 23127c478bd9Sstevel@tonic-gate 23137c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 23147c478bd9Sstevel@tonic-gate sm_dprintf("db_map_lookup(%s, %s)\n", 23157c478bd9Sstevel@tonic-gate map->map_mname, name); 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf) 23187c478bd9Sstevel@tonic-gate { 23197c478bd9Sstevel@tonic-gate errno = 0; 23207c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 23217c478bd9Sstevel@tonic-gate syserr("map \"%s\": map file %s name too long", 23227c478bd9Sstevel@tonic-gate map->map_mname, map->map_file); 23237c478bd9Sstevel@tonic-gate return NULL; 23247c478bd9Sstevel@tonic-gate } 23257c478bd9Sstevel@tonic-gate i = strlen(buf); 23267c478bd9Sstevel@tonic-gate if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) 23277c478bd9Sstevel@tonic-gate buf[i - 3] = '\0'; 23287c478bd9Sstevel@tonic-gate 23297c478bd9Sstevel@tonic-gate key.size = strlen(name); 23307c478bd9Sstevel@tonic-gate if (key.size > sizeof keybuf - 1) 23317c478bd9Sstevel@tonic-gate key.size = sizeof keybuf - 1; 23327c478bd9Sstevel@tonic-gate key.data = keybuf; 23337c478bd9Sstevel@tonic-gate memmove(keybuf, name, key.size); 23347c478bd9Sstevel@tonic-gate keybuf[key.size] = '\0'; 23357c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 23367c478bd9Sstevel@tonic-gate makelower(keybuf); 23377c478bd9Sstevel@tonic-gate lockdb: 23387c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 23397c478bd9Sstevel@tonic-gate fd = db->fd(db); 23407c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 23417c478bd9Sstevel@tonic-gate fd = -1; 23427c478bd9Sstevel@tonic-gate errno = db->fd(db, &fd); 23437c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 23447c478bd9Sstevel@tonic-gate if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 23457c478bd9Sstevel@tonic-gate (void) lockfile(fd, buf, ".db", LOCK_SH); 23467c478bd9Sstevel@tonic-gate if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) 23477c478bd9Sstevel@tonic-gate { 23487c478bd9Sstevel@tonic-gate /* Reopen the database to sync the cache */ 23497c478bd9Sstevel@tonic-gate int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR 23507c478bd9Sstevel@tonic-gate : O_RDONLY; 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 23537c478bd9Sstevel@tonic-gate (void) lockfile(fd, buf, ".db", LOCK_UN); 23547c478bd9Sstevel@tonic-gate map->map_mflags |= MF_CLOSING; 23557c478bd9Sstevel@tonic-gate map->map_class->map_close(map); 23567c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 23577c478bd9Sstevel@tonic-gate if (map->map_class->map_open(map, omode)) 23587c478bd9Sstevel@tonic-gate { 23597c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN; 23607c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 23617c478bd9Sstevel@tonic-gate if ((omode && O_ACCMODE) == O_RDWR) 23627c478bd9Sstevel@tonic-gate map->map_mflags |= MF_WRITABLE; 23637c478bd9Sstevel@tonic-gate db = (DB *) map->map_db2; 23647c478bd9Sstevel@tonic-gate goto lockdb; 23657c478bd9Sstevel@tonic-gate } 23667c478bd9Sstevel@tonic-gate else 23677c478bd9Sstevel@tonic-gate { 23687c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 23697c478bd9Sstevel@tonic-gate { 23707c478bd9Sstevel@tonic-gate extern MAPCLASS BogusMapClass; 23717c478bd9Sstevel@tonic-gate 23727c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 23737c478bd9Sstevel@tonic-gate map->map_orgclass = map->map_class; 23747c478bd9Sstevel@tonic-gate map->map_class = &BogusMapClass; 23757c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN; 23767c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 23777c478bd9Sstevel@tonic-gate syserr("Cannot reopen DB database %s", 23787c478bd9Sstevel@tonic-gate map->map_file); 23797c478bd9Sstevel@tonic-gate } 23807c478bd9Sstevel@tonic-gate return NULL; 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate st = 1; 23857c478bd9Sstevel@tonic-gate if (bitset(MF_TRY0NULL, map->map_mflags)) 23867c478bd9Sstevel@tonic-gate { 23877c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 23887c478bd9Sstevel@tonic-gate st = db->get(db, &key, &val, 0); 23897c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 23907c478bd9Sstevel@tonic-gate errno = db->get(db, NULL, &key, &val, 0); 23917c478bd9Sstevel@tonic-gate switch (errno) 23927c478bd9Sstevel@tonic-gate { 23937c478bd9Sstevel@tonic-gate case DB_NOTFOUND: 23947c478bd9Sstevel@tonic-gate case DB_KEYEMPTY: 23957c478bd9Sstevel@tonic-gate st = 1; 23967c478bd9Sstevel@tonic-gate break; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate case 0: 23997c478bd9Sstevel@tonic-gate st = 0; 24007c478bd9Sstevel@tonic-gate break; 24017c478bd9Sstevel@tonic-gate 24027c478bd9Sstevel@tonic-gate default: 24037c478bd9Sstevel@tonic-gate st = -1; 24047c478bd9Sstevel@tonic-gate break; 24057c478bd9Sstevel@tonic-gate } 24067c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 24077c478bd9Sstevel@tonic-gate if (st == 0) 24087c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 24097c478bd9Sstevel@tonic-gate } 24107c478bd9Sstevel@tonic-gate if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 24117c478bd9Sstevel@tonic-gate { 24127c478bd9Sstevel@tonic-gate key.size++; 24137c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 24147c478bd9Sstevel@tonic-gate st = db->get(db, &key, &val, 0); 24157c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 24167c478bd9Sstevel@tonic-gate errno = db->get(db, NULL, &key, &val, 0); 24177c478bd9Sstevel@tonic-gate switch (errno) 24187c478bd9Sstevel@tonic-gate { 24197c478bd9Sstevel@tonic-gate case DB_NOTFOUND: 24207c478bd9Sstevel@tonic-gate case DB_KEYEMPTY: 24217c478bd9Sstevel@tonic-gate st = 1; 24227c478bd9Sstevel@tonic-gate break; 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate case 0: 24257c478bd9Sstevel@tonic-gate st = 0; 24267c478bd9Sstevel@tonic-gate break; 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate default: 24297c478bd9Sstevel@tonic-gate st = -1; 24307c478bd9Sstevel@tonic-gate break; 24317c478bd9Sstevel@tonic-gate } 24327c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 24337c478bd9Sstevel@tonic-gate if (st == 0) 24347c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 24357c478bd9Sstevel@tonic-gate } 24367c478bd9Sstevel@tonic-gate save_errno = errno; 24377c478bd9Sstevel@tonic-gate if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) 24387c478bd9Sstevel@tonic-gate (void) lockfile(fd, buf, ".db", LOCK_UN); 24397c478bd9Sstevel@tonic-gate if (st != 0) 24407c478bd9Sstevel@tonic-gate { 24417c478bd9Sstevel@tonic-gate errno = save_errno; 24427c478bd9Sstevel@tonic-gate if (st < 0) 24437c478bd9Sstevel@tonic-gate syserr("db_map_lookup: get (%s)", name); 24447c478bd9Sstevel@tonic-gate return NULL; 24457c478bd9Sstevel@tonic-gate } 24467c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 24477c478bd9Sstevel@tonic-gate return map_rewrite(map, name, strlen(name), NULL); 24487c478bd9Sstevel@tonic-gate else 24497c478bd9Sstevel@tonic-gate return map_rewrite(map, val.data, val.size, av); 24507c478bd9Sstevel@tonic-gate } 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate 24537c478bd9Sstevel@tonic-gate /* 24547c478bd9Sstevel@tonic-gate ** DB_MAP_STORE -- store a datum in the NEWDB database 24557c478bd9Sstevel@tonic-gate */ 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate void 24587c478bd9Sstevel@tonic-gate db_map_store(map, lhs, rhs) 24597c478bd9Sstevel@tonic-gate register MAP *map; 24607c478bd9Sstevel@tonic-gate char *lhs; 24617c478bd9Sstevel@tonic-gate char *rhs; 24627c478bd9Sstevel@tonic-gate { 24637c478bd9Sstevel@tonic-gate int status; 24647c478bd9Sstevel@tonic-gate DBT key; 24657c478bd9Sstevel@tonic-gate DBT data; 24667c478bd9Sstevel@tonic-gate register DB *db = map->map_db2; 24677c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate memset(&key, '\0', sizeof key); 24707c478bd9Sstevel@tonic-gate memset(&data, '\0', sizeof data); 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate if (tTd(38, 12)) 24737c478bd9Sstevel@tonic-gate sm_dprintf("db_map_store(%s, %s, %s)\n", 24747c478bd9Sstevel@tonic-gate map->map_mname, lhs, rhs); 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate key.size = strlen(lhs); 24777c478bd9Sstevel@tonic-gate key.data = lhs; 24787c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 24797c478bd9Sstevel@tonic-gate { 24807c478bd9Sstevel@tonic-gate if (key.size > sizeof keybuf - 1) 24817c478bd9Sstevel@tonic-gate key.size = sizeof keybuf - 1; 24827c478bd9Sstevel@tonic-gate memmove(keybuf, key.data, key.size); 24837c478bd9Sstevel@tonic-gate keybuf[key.size] = '\0'; 24847c478bd9Sstevel@tonic-gate makelower(keybuf); 24857c478bd9Sstevel@tonic-gate key.data = keybuf; 24867c478bd9Sstevel@tonic-gate } 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate data.size = strlen(rhs); 24897c478bd9Sstevel@tonic-gate data.data = rhs; 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate if (bitset(MF_INCLNULL, map->map_mflags)) 24927c478bd9Sstevel@tonic-gate { 24937c478bd9Sstevel@tonic-gate key.size++; 24947c478bd9Sstevel@tonic-gate data.size++; 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 24987c478bd9Sstevel@tonic-gate status = db->put(db, &key, &data, R_NOOVERWRITE); 24997c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 25007c478bd9Sstevel@tonic-gate errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); 25017c478bd9Sstevel@tonic-gate switch (errno) 25027c478bd9Sstevel@tonic-gate { 25037c478bd9Sstevel@tonic-gate case DB_KEYEXIST: 25047c478bd9Sstevel@tonic-gate status = 1; 25057c478bd9Sstevel@tonic-gate break; 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate case 0: 25087c478bd9Sstevel@tonic-gate status = 0; 25097c478bd9Sstevel@tonic-gate break; 25107c478bd9Sstevel@tonic-gate 25117c478bd9Sstevel@tonic-gate default: 25127c478bd9Sstevel@tonic-gate status = -1; 25137c478bd9Sstevel@tonic-gate break; 25147c478bd9Sstevel@tonic-gate } 25157c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 25167c478bd9Sstevel@tonic-gate if (status > 0) 25177c478bd9Sstevel@tonic-gate { 25187c478bd9Sstevel@tonic-gate if (!bitset(MF_APPEND, map->map_mflags)) 25197c478bd9Sstevel@tonic-gate message("050 Warning: duplicate alias name %s", lhs); 25207c478bd9Sstevel@tonic-gate else 25217c478bd9Sstevel@tonic-gate { 25227c478bd9Sstevel@tonic-gate static char *buf = NULL; 25237c478bd9Sstevel@tonic-gate static int bufsiz = 0; 25247c478bd9Sstevel@tonic-gate DBT old; 25257c478bd9Sstevel@tonic-gate 25267c478bd9Sstevel@tonic-gate memset(&old, '\0', sizeof old); 25277c478bd9Sstevel@tonic-gate 25287c478bd9Sstevel@tonic-gate old.data = db_map_lookup(map, key.data, 25297c478bd9Sstevel@tonic-gate (char **) NULL, &status); 25307c478bd9Sstevel@tonic-gate if (old.data != NULL) 25317c478bd9Sstevel@tonic-gate { 25327c478bd9Sstevel@tonic-gate old.size = strlen(old.data); 25337c478bd9Sstevel@tonic-gate if (data.size + old.size + 2 > (size_t) bufsiz) 25347c478bd9Sstevel@tonic-gate { 25357c478bd9Sstevel@tonic-gate if (buf != NULL) 25367c478bd9Sstevel@tonic-gate sm_free(buf); 25377c478bd9Sstevel@tonic-gate bufsiz = data.size + old.size + 2; 25387c478bd9Sstevel@tonic-gate buf = sm_pmalloc_x(bufsiz); 25397c478bd9Sstevel@tonic-gate } 25407c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(buf, bufsiz, 3, 25417c478bd9Sstevel@tonic-gate (char *) data.data, ",", 25427c478bd9Sstevel@tonic-gate (char *) old.data); 25437c478bd9Sstevel@tonic-gate data.size = data.size + old.size + 1; 25447c478bd9Sstevel@tonic-gate data.data = buf; 25457c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 25467c478bd9Sstevel@tonic-gate sm_dprintf("db_map_store append=%s\n", 25477c478bd9Sstevel@tonic-gate (char *) data.data); 25487c478bd9Sstevel@tonic-gate } 25497c478bd9Sstevel@tonic-gate } 25507c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 25517c478bd9Sstevel@tonic-gate status = db->put(db, &key, &data, 0); 25527c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 25537c478bd9Sstevel@tonic-gate status = errno = db->put(db, NULL, &key, &data, 0); 25547c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 25557c478bd9Sstevel@tonic-gate } 25567c478bd9Sstevel@tonic-gate if (status != 0) 25577c478bd9Sstevel@tonic-gate syserr("readaliases: db put (%s)", lhs); 25587c478bd9Sstevel@tonic-gate } 25597c478bd9Sstevel@tonic-gate 25607c478bd9Sstevel@tonic-gate 25617c478bd9Sstevel@tonic-gate /* 25627c478bd9Sstevel@tonic-gate ** DB_MAP_CLOSE -- add distinguished entries and close the database 25637c478bd9Sstevel@tonic-gate */ 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate void 25667c478bd9Sstevel@tonic-gate db_map_close(map) 25677c478bd9Sstevel@tonic-gate MAP *map; 25687c478bd9Sstevel@tonic-gate { 25697c478bd9Sstevel@tonic-gate register DB *db = map->map_db2; 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 25727c478bd9Sstevel@tonic-gate sm_dprintf("db_map_close(%s, %s, %lx)\n", 25737c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, map->map_mflags); 25747c478bd9Sstevel@tonic-gate 25757c478bd9Sstevel@tonic-gate if (bitset(MF_WRITABLE, map->map_mflags)) 25767c478bd9Sstevel@tonic-gate { 25777c478bd9Sstevel@tonic-gate /* write out the distinguished alias */ 25787c478bd9Sstevel@tonic-gate db_map_store(map, "@", "@"); 25797c478bd9Sstevel@tonic-gate } 25807c478bd9Sstevel@tonic-gate 25817c478bd9Sstevel@tonic-gate (void) db->sync(db, 0); 25827c478bd9Sstevel@tonic-gate 25837c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN 25847c478bd9Sstevel@tonic-gate if (map->map_lockfd >= 0) 25857c478bd9Sstevel@tonic-gate (void) close(map->map_lockfd); 25867c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */ 25877c478bd9Sstevel@tonic-gate 25887c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2 25897c478bd9Sstevel@tonic-gate if (db->close(db) != 0) 25907c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */ 25917c478bd9Sstevel@tonic-gate /* 25927c478bd9Sstevel@tonic-gate ** Berkeley DB can use internal shared memory 25937c478bd9Sstevel@tonic-gate ** locking for its memory pool. Closing a map 25947c478bd9Sstevel@tonic-gate ** opened by another process will interfere 25957c478bd9Sstevel@tonic-gate ** with the shared memory and locks of the parent 25967c478bd9Sstevel@tonic-gate ** process leaving things in a bad state. 25977c478bd9Sstevel@tonic-gate */ 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate /* 26007c478bd9Sstevel@tonic-gate ** If this map was not opened by the current 26017c478bd9Sstevel@tonic-gate ** process, do not close the map but recover 26027c478bd9Sstevel@tonic-gate ** the file descriptor. 26037c478bd9Sstevel@tonic-gate */ 26047c478bd9Sstevel@tonic-gate 26057c478bd9Sstevel@tonic-gate if (map->map_pid != CurrentPid) 26067c478bd9Sstevel@tonic-gate { 26077c478bd9Sstevel@tonic-gate int fd = -1; 26087c478bd9Sstevel@tonic-gate 26097c478bd9Sstevel@tonic-gate errno = db->fd(db, &fd); 26107c478bd9Sstevel@tonic-gate if (fd >= 0) 26117c478bd9Sstevel@tonic-gate (void) close(fd); 26127c478bd9Sstevel@tonic-gate return; 26137c478bd9Sstevel@tonic-gate } 26147c478bd9Sstevel@tonic-gate 26157c478bd9Sstevel@tonic-gate if ((errno = db->close(db, 0)) != 0) 26167c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */ 26177c478bd9Sstevel@tonic-gate syserr("db_map_close(%s, %s, %lx): db close failure", 26187c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, map->map_mflags); 26197c478bd9Sstevel@tonic-gate } 26207c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 26217c478bd9Sstevel@tonic-gate /* 26227c478bd9Sstevel@tonic-gate ** NIS Modules 26237c478bd9Sstevel@tonic-gate */ 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate #if NIS 26267c478bd9Sstevel@tonic-gate 26277c478bd9Sstevel@tonic-gate # ifndef YPERR_BUSY 26287c478bd9Sstevel@tonic-gate # define YPERR_BUSY 16 26297c478bd9Sstevel@tonic-gate # endif /* ! YPERR_BUSY */ 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate /* 26327c478bd9Sstevel@tonic-gate ** NIS_MAP_OPEN -- open DBM map 26337c478bd9Sstevel@tonic-gate */ 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate bool 26367c478bd9Sstevel@tonic-gate nis_map_open(map, mode) 26377c478bd9Sstevel@tonic-gate MAP *map; 26387c478bd9Sstevel@tonic-gate int mode; 26397c478bd9Sstevel@tonic-gate { 26407c478bd9Sstevel@tonic-gate int yperr; 26417c478bd9Sstevel@tonic-gate register char *p; 26427c478bd9Sstevel@tonic-gate auto char *vp; 26437c478bd9Sstevel@tonic-gate auto int vsize; 26447c478bd9Sstevel@tonic-gate 26457c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 26467c478bd9Sstevel@tonic-gate sm_dprintf("nis_map_open(%s, %s, %d)\n", 26477c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 26487c478bd9Sstevel@tonic-gate 26497c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 26507c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 26517c478bd9Sstevel@tonic-gate { 26527c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 26537c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 26547c478bd9Sstevel@tonic-gate return false; 26557c478bd9Sstevel@tonic-gate } 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate p = strchr(map->map_file, '@'); 26587c478bd9Sstevel@tonic-gate if (p != NULL) 26597c478bd9Sstevel@tonic-gate { 26607c478bd9Sstevel@tonic-gate *p++ = '\0'; 26617c478bd9Sstevel@tonic-gate if (*p != '\0') 26627c478bd9Sstevel@tonic-gate map->map_domain = p; 26637c478bd9Sstevel@tonic-gate } 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate if (*map->map_file == '\0') 26667c478bd9Sstevel@tonic-gate map->map_file = "mail.aliases"; 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate if (map->map_domain == NULL) 26697c478bd9Sstevel@tonic-gate { 26707c478bd9Sstevel@tonic-gate yperr = yp_get_default_domain(&map->map_domain); 26717c478bd9Sstevel@tonic-gate if (yperr != 0) 26727c478bd9Sstevel@tonic-gate { 26737c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 26747c478bd9Sstevel@tonic-gate syserr("451 4.3.5 NIS map %s specified, but NIS not running", 26757c478bd9Sstevel@tonic-gate map->map_file); 26767c478bd9Sstevel@tonic-gate return false; 26777c478bd9Sstevel@tonic-gate } 26787c478bd9Sstevel@tonic-gate } 26797c478bd9Sstevel@tonic-gate 26807c478bd9Sstevel@tonic-gate /* check to see if this map actually exists */ 26817c478bd9Sstevel@tonic-gate vp = NULL; 26827c478bd9Sstevel@tonic-gate yperr = yp_match(map->map_domain, map->map_file, "@", 1, 26837c478bd9Sstevel@tonic-gate &vp, &vsize); 26847c478bd9Sstevel@tonic-gate if (tTd(38, 10)) 26857c478bd9Sstevel@tonic-gate sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", 26867c478bd9Sstevel@tonic-gate map->map_domain, map->map_file, yperr_string(yperr)); 26877c478bd9Sstevel@tonic-gate if (vp != NULL) 26887c478bd9Sstevel@tonic-gate sm_free(vp); 26897c478bd9Sstevel@tonic-gate 26907c478bd9Sstevel@tonic-gate if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 26917c478bd9Sstevel@tonic-gate { 26927c478bd9Sstevel@tonic-gate /* 26937c478bd9Sstevel@tonic-gate ** We ought to be calling aliaswait() here if this is an 26947c478bd9Sstevel@tonic-gate ** alias file, but powerful HP-UX NIS servers apparently 26957c478bd9Sstevel@tonic-gate ** don't insert the @:@ token into the alias map when it 26967c478bd9Sstevel@tonic-gate ** is rebuilt, so aliaswait() just hangs. I hate HP-UX. 26977c478bd9Sstevel@tonic-gate */ 26987c478bd9Sstevel@tonic-gate 26997c478bd9Sstevel@tonic-gate # if 0 27007c478bd9Sstevel@tonic-gate if (!bitset(MF_ALIAS, map->map_mflags) || 27017c478bd9Sstevel@tonic-gate aliaswait(map, NULL, true)) 27027c478bd9Sstevel@tonic-gate # endif /* 0 */ 27037c478bd9Sstevel@tonic-gate return true; 27047c478bd9Sstevel@tonic-gate } 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 27077c478bd9Sstevel@tonic-gate { 27087c478bd9Sstevel@tonic-gate syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s", 27097c478bd9Sstevel@tonic-gate map->map_file, map->map_domain, yperr_string(yperr)); 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate return false; 27137c478bd9Sstevel@tonic-gate } 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate /* 27177c478bd9Sstevel@tonic-gate ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 27187c478bd9Sstevel@tonic-gate */ 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 27217c478bd9Sstevel@tonic-gate char * 27227c478bd9Sstevel@tonic-gate nis_map_lookup(map, name, av, statp) 27237c478bd9Sstevel@tonic-gate MAP *map; 27247c478bd9Sstevel@tonic-gate char *name; 27257c478bd9Sstevel@tonic-gate char **av; 27267c478bd9Sstevel@tonic-gate int *statp; 27277c478bd9Sstevel@tonic-gate { 27287c478bd9Sstevel@tonic-gate char *vp; 27297c478bd9Sstevel@tonic-gate auto int vsize; 27307c478bd9Sstevel@tonic-gate int buflen; 27317c478bd9Sstevel@tonic-gate int yperr; 27327c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 27337c478bd9Sstevel@tonic-gate char *SM_NONVOLATILE result = NULL; 27347c478bd9Sstevel@tonic-gate 27357c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 27367c478bd9Sstevel@tonic-gate sm_dprintf("nis_map_lookup(%s, %s)\n", 27377c478bd9Sstevel@tonic-gate map->map_mname, name); 27387c478bd9Sstevel@tonic-gate 27397c478bd9Sstevel@tonic-gate buflen = strlen(name); 27407c478bd9Sstevel@tonic-gate if (buflen > sizeof keybuf - 1) 27417c478bd9Sstevel@tonic-gate buflen = sizeof keybuf - 1; 27427c478bd9Sstevel@tonic-gate memmove(keybuf, name, buflen); 27437c478bd9Sstevel@tonic-gate keybuf[buflen] = '\0'; 27447c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 27457c478bd9Sstevel@tonic-gate makelower(keybuf); 27467c478bd9Sstevel@tonic-gate yperr = YPERR_KEY; 27477c478bd9Sstevel@tonic-gate vp = NULL; 27487c478bd9Sstevel@tonic-gate if (bitset(MF_TRY0NULL, map->map_mflags)) 27497c478bd9Sstevel@tonic-gate { 27507c478bd9Sstevel@tonic-gate yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 27517c478bd9Sstevel@tonic-gate &vp, &vsize); 27527c478bd9Sstevel@tonic-gate if (yperr == 0) 27537c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 27547c478bd9Sstevel@tonic-gate } 27557c478bd9Sstevel@tonic-gate if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 27567c478bd9Sstevel@tonic-gate { 27577c478bd9Sstevel@tonic-gate SM_FREE_CLR(vp); 27587c478bd9Sstevel@tonic-gate buflen++; 27597c478bd9Sstevel@tonic-gate yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 27607c478bd9Sstevel@tonic-gate &vp, &vsize); 27617c478bd9Sstevel@tonic-gate if (yperr == 0) 27627c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate if (yperr != 0) 27657c478bd9Sstevel@tonic-gate { 27667c478bd9Sstevel@tonic-gate if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 27677c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_VALID|MF_OPEN); 27687c478bd9Sstevel@tonic-gate if (vp != NULL) 27697c478bd9Sstevel@tonic-gate sm_free(vp); 27707c478bd9Sstevel@tonic-gate return NULL; 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate SM_TRY 27737c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 27747c478bd9Sstevel@tonic-gate result = map_rewrite(map, name, strlen(name), NULL); 27757c478bd9Sstevel@tonic-gate else 27767c478bd9Sstevel@tonic-gate result = map_rewrite(map, vp, vsize, av); 27777c478bd9Sstevel@tonic-gate SM_FINALLY 27787c478bd9Sstevel@tonic-gate if (vp != NULL) 27797c478bd9Sstevel@tonic-gate sm_free(vp); 27807c478bd9Sstevel@tonic-gate SM_END_TRY 27817c478bd9Sstevel@tonic-gate return result; 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate 27857c478bd9Sstevel@tonic-gate /* 27867c478bd9Sstevel@tonic-gate ** NIS_GETCANONNAME -- look up canonical name in NIS 27877c478bd9Sstevel@tonic-gate */ 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate static bool 27907c478bd9Sstevel@tonic-gate nis_getcanonname(name, hbsize, statp) 27917c478bd9Sstevel@tonic-gate char *name; 27927c478bd9Sstevel@tonic-gate int hbsize; 27937c478bd9Sstevel@tonic-gate int *statp; 27947c478bd9Sstevel@tonic-gate { 27957c478bd9Sstevel@tonic-gate char *vp; 27967c478bd9Sstevel@tonic-gate auto int vsize; 27977c478bd9Sstevel@tonic-gate int keylen; 27987c478bd9Sstevel@tonic-gate int yperr; 27997c478bd9Sstevel@tonic-gate static bool try0null = true; 28007c478bd9Sstevel@tonic-gate static bool try1null = true; 28017c478bd9Sstevel@tonic-gate static char *yp_domain = NULL; 28027c478bd9Sstevel@tonic-gate char host_record[MAXLINE]; 28037c478bd9Sstevel@tonic-gate char cbuf[MAXNAME]; 28047c478bd9Sstevel@tonic-gate char nbuf[MAXNAME + 1]; 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 28077c478bd9Sstevel@tonic-gate sm_dprintf("nis_getcanonname(%s)\n", name); 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 28107c478bd9Sstevel@tonic-gate { 28117c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 28127c478bd9Sstevel@tonic-gate return false; 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate (void) shorten_hostname(nbuf); 28157c478bd9Sstevel@tonic-gate keylen = strlen(nbuf); 28167c478bd9Sstevel@tonic-gate 28177c478bd9Sstevel@tonic-gate if (yp_domain == NULL) 28187c478bd9Sstevel@tonic-gate (void) yp_get_default_domain(&yp_domain); 28197c478bd9Sstevel@tonic-gate makelower(nbuf); 28207c478bd9Sstevel@tonic-gate yperr = YPERR_KEY; 28217c478bd9Sstevel@tonic-gate vp = NULL; 28227c478bd9Sstevel@tonic-gate if (try0null) 28237c478bd9Sstevel@tonic-gate { 28247c478bd9Sstevel@tonic-gate yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 28257c478bd9Sstevel@tonic-gate &vp, &vsize); 28267c478bd9Sstevel@tonic-gate if (yperr == 0) 28277c478bd9Sstevel@tonic-gate try1null = false; 28287c478bd9Sstevel@tonic-gate } 28297c478bd9Sstevel@tonic-gate if (yperr == YPERR_KEY && try1null) 28307c478bd9Sstevel@tonic-gate { 28317c478bd9Sstevel@tonic-gate SM_FREE_CLR(vp); 28327c478bd9Sstevel@tonic-gate keylen++; 28337c478bd9Sstevel@tonic-gate yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen, 28347c478bd9Sstevel@tonic-gate &vp, &vsize); 28357c478bd9Sstevel@tonic-gate if (yperr == 0) 28367c478bd9Sstevel@tonic-gate try0null = false; 28377c478bd9Sstevel@tonic-gate } 28387c478bd9Sstevel@tonic-gate if (yperr != 0) 28397c478bd9Sstevel@tonic-gate { 28407c478bd9Sstevel@tonic-gate if (yperr == YPERR_KEY) 28417c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 28427c478bd9Sstevel@tonic-gate else if (yperr == YPERR_BUSY) 28437c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 28447c478bd9Sstevel@tonic-gate else 28457c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 28467c478bd9Sstevel@tonic-gate if (vp != NULL) 28477c478bd9Sstevel@tonic-gate sm_free(vp); 28487c478bd9Sstevel@tonic-gate return false; 28497c478bd9Sstevel@tonic-gate } 28507c478bd9Sstevel@tonic-gate (void) sm_strlcpy(host_record, vp, sizeof host_record); 28517c478bd9Sstevel@tonic-gate sm_free(vp); 28527c478bd9Sstevel@tonic-gate if (tTd(38, 44)) 28537c478bd9Sstevel@tonic-gate sm_dprintf("got record `%s'\n", host_record); 28547c478bd9Sstevel@tonic-gate vp = strpbrk(host_record, "#\n"); 28557c478bd9Sstevel@tonic-gate if (vp != NULL) 28567c478bd9Sstevel@tonic-gate *vp = '\0'; 28577c478bd9Sstevel@tonic-gate if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf)) 28587c478bd9Sstevel@tonic-gate { 28597c478bd9Sstevel@tonic-gate /* this should not happen, but.... */ 28607c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 28617c478bd9Sstevel@tonic-gate return false; 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 28647c478bd9Sstevel@tonic-gate { 28657c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 28667c478bd9Sstevel@tonic-gate return false; 28677c478bd9Sstevel@tonic-gate } 28687c478bd9Sstevel@tonic-gate *statp = EX_OK; 28697c478bd9Sstevel@tonic-gate return true; 28707c478bd9Sstevel@tonic-gate } 28717c478bd9Sstevel@tonic-gate 28727c478bd9Sstevel@tonic-gate #endif /* NIS */ 28737c478bd9Sstevel@tonic-gate /* 28747c478bd9Sstevel@tonic-gate ** NISPLUS Modules 28757c478bd9Sstevel@tonic-gate ** 28767c478bd9Sstevel@tonic-gate ** This code donated by Sun Microsystems. 28777c478bd9Sstevel@tonic-gate */ 28787c478bd9Sstevel@tonic-gate 28797c478bd9Sstevel@tonic-gate #if NISPLUS 28807c478bd9Sstevel@tonic-gate 28817c478bd9Sstevel@tonic-gate # undef NIS /* symbol conflict in nis.h */ 28827c478bd9Sstevel@tonic-gate # undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ 28837c478bd9Sstevel@tonic-gate # include <rpcsvc/nis.h> 28847c478bd9Sstevel@tonic-gate # include <rpcsvc/nislib.h> 28857c478bd9Sstevel@tonic-gate 28867c478bd9Sstevel@tonic-gate # define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val 28877c478bd9Sstevel@tonic-gate # define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name 28887c478bd9Sstevel@tonic-gate # define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len) 28897c478bd9Sstevel@tonic-gate # define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.') 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate /* 28927c478bd9Sstevel@tonic-gate ** NISPLUS_MAP_OPEN -- open nisplus table 28937c478bd9Sstevel@tonic-gate */ 28947c478bd9Sstevel@tonic-gate 28957c478bd9Sstevel@tonic-gate bool 28967c478bd9Sstevel@tonic-gate nisplus_map_open(map, mode) 28977c478bd9Sstevel@tonic-gate MAP *map; 28987c478bd9Sstevel@tonic-gate int mode; 28997c478bd9Sstevel@tonic-gate { 29007c478bd9Sstevel@tonic-gate nis_result *res = NULL; 29017c478bd9Sstevel@tonic-gate int retry_cnt, max_col, i; 29027c478bd9Sstevel@tonic-gate char qbuf[MAXLINE + NIS_MAXNAMELEN]; 29037c478bd9Sstevel@tonic-gate 29047c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 29057c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_open(%s, %s, %d)\n", 29067c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 29077c478bd9Sstevel@tonic-gate 29087c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 29097c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 29107c478bd9Sstevel@tonic-gate { 29117c478bd9Sstevel@tonic-gate errno = EPERM; 29127c478bd9Sstevel@tonic-gate return false; 29137c478bd9Sstevel@tonic-gate } 29147c478bd9Sstevel@tonic-gate 29157c478bd9Sstevel@tonic-gate if (*map->map_file == '\0') 29167c478bd9Sstevel@tonic-gate map->map_file = "mail_aliases.org_dir"; 29177c478bd9Sstevel@tonic-gate 29187c478bd9Sstevel@tonic-gate if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL) 29197c478bd9Sstevel@tonic-gate { 29207c478bd9Sstevel@tonic-gate /* set default NISPLUS Domain to $m */ 29217c478bd9Sstevel@tonic-gate map->map_domain = newstr(nisplus_default_domain()); 29227c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 29237c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_open(%s): using domain %s\n", 29247c478bd9Sstevel@tonic-gate map->map_file, map->map_domain); 29257c478bd9Sstevel@tonic-gate } 29267c478bd9Sstevel@tonic-gate if (!PARTIAL_NAME(map->map_file)) 29277c478bd9Sstevel@tonic-gate { 29287c478bd9Sstevel@tonic-gate map->map_domain = newstr(""); 29297c478bd9Sstevel@tonic-gate (void) sm_strlcpy(qbuf, map->map_file, sizeof qbuf); 29307c478bd9Sstevel@tonic-gate } 29317c478bd9Sstevel@tonic-gate else 29327c478bd9Sstevel@tonic-gate { 29337c478bd9Sstevel@tonic-gate /* check to see if this map actually exists */ 29347c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(qbuf, sizeof qbuf, 3, 29357c478bd9Sstevel@tonic-gate map->map_file, ".", map->map_domain); 29367c478bd9Sstevel@tonic-gate } 29377c478bd9Sstevel@tonic-gate 29387c478bd9Sstevel@tonic-gate retry_cnt = 0; 29397c478bd9Sstevel@tonic-gate while (res == NULL || res->status != NIS_SUCCESS) 29407c478bd9Sstevel@tonic-gate { 29417c478bd9Sstevel@tonic-gate res = nis_lookup(qbuf, FOLLOW_LINKS); 29427c478bd9Sstevel@tonic-gate switch (res->status) 29437c478bd9Sstevel@tonic-gate { 29447c478bd9Sstevel@tonic-gate case NIS_SUCCESS: 29457c478bd9Sstevel@tonic-gate break; 29467c478bd9Sstevel@tonic-gate 29477c478bd9Sstevel@tonic-gate case NIS_TRYAGAIN: 29487c478bd9Sstevel@tonic-gate case NIS_RPCERROR: 29497c478bd9Sstevel@tonic-gate case NIS_NAMEUNREACHABLE: 29507c478bd9Sstevel@tonic-gate if (retry_cnt++ > 4) 29517c478bd9Sstevel@tonic-gate { 29527c478bd9Sstevel@tonic-gate errno = EAGAIN; 29537c478bd9Sstevel@tonic-gate return false; 29547c478bd9Sstevel@tonic-gate } 29557c478bd9Sstevel@tonic-gate /* try not to overwhelm hosed server */ 29567c478bd9Sstevel@tonic-gate sleep(2); 29577c478bd9Sstevel@tonic-gate break; 29587c478bd9Sstevel@tonic-gate 29597c478bd9Sstevel@tonic-gate default: /* all other nisplus errors */ 29607c478bd9Sstevel@tonic-gate # if 0 29617c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 29627c478bd9Sstevel@tonic-gate syserr("451 4.3.5 Cannot find table %s.%s: %s", 29637c478bd9Sstevel@tonic-gate map->map_file, map->map_domain, 29647c478bd9Sstevel@tonic-gate nis_sperrno(res->status)); 29657c478bd9Sstevel@tonic-gate # endif /* 0 */ 29667c478bd9Sstevel@tonic-gate errno = EAGAIN; 29677c478bd9Sstevel@tonic-gate return false; 29687c478bd9Sstevel@tonic-gate } 29697c478bd9Sstevel@tonic-gate } 29707c478bd9Sstevel@tonic-gate 29717c478bd9Sstevel@tonic-gate if (NIS_RES_NUMOBJ(res) != 1 || 29727c478bd9Sstevel@tonic-gate (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) 29737c478bd9Sstevel@tonic-gate { 29747c478bd9Sstevel@tonic-gate if (tTd(38, 10)) 29757c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf); 29767c478bd9Sstevel@tonic-gate # if 0 29777c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 29787c478bd9Sstevel@tonic-gate syserr("451 4.3.5 %s.%s: %s is not a table", 29797c478bd9Sstevel@tonic-gate map->map_file, map->map_domain, 29807c478bd9Sstevel@tonic-gate nis_sperrno(res->status)); 29817c478bd9Sstevel@tonic-gate # endif /* 0 */ 29827c478bd9Sstevel@tonic-gate errno = EBADF; 29837c478bd9Sstevel@tonic-gate return false; 29847c478bd9Sstevel@tonic-gate } 29857c478bd9Sstevel@tonic-gate /* default key column is column 0 */ 29867c478bd9Sstevel@tonic-gate if (map->map_keycolnm == NULL) 29877c478bd9Sstevel@tonic-gate map->map_keycolnm = newstr(COL_NAME(res,0)); 29887c478bd9Sstevel@tonic-gate 29897c478bd9Sstevel@tonic-gate max_col = COL_MAX(res); 29907c478bd9Sstevel@tonic-gate 29917c478bd9Sstevel@tonic-gate /* verify the key column exist */ 29927c478bd9Sstevel@tonic-gate for (i = 0; i < max_col; i++) 29937c478bd9Sstevel@tonic-gate { 29947c478bd9Sstevel@tonic-gate if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0) 29957c478bd9Sstevel@tonic-gate break; 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate if (i == max_col) 29987c478bd9Sstevel@tonic-gate { 29997c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 30007c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_open(%s): can not find key column %s\n", 30017c478bd9Sstevel@tonic-gate map->map_file, map->map_keycolnm); 30027c478bd9Sstevel@tonic-gate errno = ENOENT; 30037c478bd9Sstevel@tonic-gate return false; 30047c478bd9Sstevel@tonic-gate } 30057c478bd9Sstevel@tonic-gate 30067c478bd9Sstevel@tonic-gate /* default value column is the last column */ 30077c478bd9Sstevel@tonic-gate if (map->map_valcolnm == NULL) 30087c478bd9Sstevel@tonic-gate { 30097c478bd9Sstevel@tonic-gate map->map_valcolno = max_col - 1; 30107c478bd9Sstevel@tonic-gate return true; 30117c478bd9Sstevel@tonic-gate } 30127c478bd9Sstevel@tonic-gate 30137c478bd9Sstevel@tonic-gate for (i = 0; i< max_col; i++) 30147c478bd9Sstevel@tonic-gate { 30157c478bd9Sstevel@tonic-gate if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0) 30167c478bd9Sstevel@tonic-gate { 30177c478bd9Sstevel@tonic-gate map->map_valcolno = i; 30187c478bd9Sstevel@tonic-gate return true; 30197c478bd9Sstevel@tonic-gate } 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 30237c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_open(%s): can not find column %s\n", 30247c478bd9Sstevel@tonic-gate map->map_file, map->map_keycolnm); 30257c478bd9Sstevel@tonic-gate errno = ENOENT; 30267c478bd9Sstevel@tonic-gate return false; 30277c478bd9Sstevel@tonic-gate } 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate 30307c478bd9Sstevel@tonic-gate /* 30317c478bd9Sstevel@tonic-gate ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table 30327c478bd9Sstevel@tonic-gate */ 30337c478bd9Sstevel@tonic-gate 30347c478bd9Sstevel@tonic-gate char * 30357c478bd9Sstevel@tonic-gate nisplus_map_lookup(map, name, av, statp) 30367c478bd9Sstevel@tonic-gate MAP *map; 30377c478bd9Sstevel@tonic-gate char *name; 30387c478bd9Sstevel@tonic-gate char **av; 30397c478bd9Sstevel@tonic-gate int *statp; 30407c478bd9Sstevel@tonic-gate { 30417c478bd9Sstevel@tonic-gate char *p; 30427c478bd9Sstevel@tonic-gate auto int vsize; 30437c478bd9Sstevel@tonic-gate char *skp; 30447c478bd9Sstevel@tonic-gate int skleft; 30457c478bd9Sstevel@tonic-gate char search_key[MAXNAME + 4]; 30467c478bd9Sstevel@tonic-gate char qbuf[MAXLINE + NIS_MAXNAMELEN]; 30477c478bd9Sstevel@tonic-gate nis_result *result; 30487c478bd9Sstevel@tonic-gate 30497c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 30507c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_lookup(%s, %s)\n", 30517c478bd9Sstevel@tonic-gate map->map_mname, name); 30527c478bd9Sstevel@tonic-gate 30537c478bd9Sstevel@tonic-gate if (!bitset(MF_OPEN, map->map_mflags)) 30547c478bd9Sstevel@tonic-gate { 30557c478bd9Sstevel@tonic-gate if (nisplus_map_open(map, O_RDONLY)) 30567c478bd9Sstevel@tonic-gate { 30577c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPEN; 30587c478bd9Sstevel@tonic-gate map->map_pid = CurrentPid; 30597c478bd9Sstevel@tonic-gate } 30607c478bd9Sstevel@tonic-gate else 30617c478bd9Sstevel@tonic-gate { 30627c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 30637c478bd9Sstevel@tonic-gate return NULL; 30647c478bd9Sstevel@tonic-gate } 30657c478bd9Sstevel@tonic-gate } 30667c478bd9Sstevel@tonic-gate 30677c478bd9Sstevel@tonic-gate /* 30687c478bd9Sstevel@tonic-gate ** Copy the name to the key buffer, escaping double quote characters 30697c478bd9Sstevel@tonic-gate ** by doubling them and quoting "]" and "," to avoid having the 30707c478bd9Sstevel@tonic-gate ** NIS+ parser choke on them. 30717c478bd9Sstevel@tonic-gate */ 30727c478bd9Sstevel@tonic-gate 30737c478bd9Sstevel@tonic-gate skleft = sizeof search_key - 4; 30747c478bd9Sstevel@tonic-gate skp = search_key; 30757c478bd9Sstevel@tonic-gate for (p = name; *p != '\0' && skleft > 0; p++) 30767c478bd9Sstevel@tonic-gate { 30777c478bd9Sstevel@tonic-gate switch (*p) 30787c478bd9Sstevel@tonic-gate { 30797c478bd9Sstevel@tonic-gate case ']': 30807c478bd9Sstevel@tonic-gate case ',': 30817c478bd9Sstevel@tonic-gate /* quote the character */ 30827c478bd9Sstevel@tonic-gate *skp++ = '"'; 30837c478bd9Sstevel@tonic-gate *skp++ = *p; 30847c478bd9Sstevel@tonic-gate *skp++ = '"'; 30857c478bd9Sstevel@tonic-gate skleft -= 3; 30867c478bd9Sstevel@tonic-gate break; 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate case '"': 30897c478bd9Sstevel@tonic-gate /* double the quote */ 30907c478bd9Sstevel@tonic-gate *skp++ = '"'; 30917c478bd9Sstevel@tonic-gate skleft--; 30927c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 30937c478bd9Sstevel@tonic-gate 30947c478bd9Sstevel@tonic-gate default: 30957c478bd9Sstevel@tonic-gate *skp++ = *p; 30967c478bd9Sstevel@tonic-gate skleft--; 30977c478bd9Sstevel@tonic-gate break; 30987c478bd9Sstevel@tonic-gate } 30997c478bd9Sstevel@tonic-gate } 31007c478bd9Sstevel@tonic-gate *skp = '\0'; 31017c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 31027c478bd9Sstevel@tonic-gate makelower(search_key); 31037c478bd9Sstevel@tonic-gate 31047c478bd9Sstevel@tonic-gate /* construct the query */ 31057c478bd9Sstevel@tonic-gate if (PARTIAL_NAME(map->map_file)) 31067c478bd9Sstevel@tonic-gate (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", 31077c478bd9Sstevel@tonic-gate map->map_keycolnm, search_key, map->map_file, 31087c478bd9Sstevel@tonic-gate map->map_domain); 31097c478bd9Sstevel@tonic-gate else 31107c478bd9Sstevel@tonic-gate (void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", 31117c478bd9Sstevel@tonic-gate map->map_keycolnm, search_key, map->map_file); 31127c478bd9Sstevel@tonic-gate 31137c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 31147c478bd9Sstevel@tonic-gate sm_dprintf("qbuf=%s\n", qbuf); 31157c478bd9Sstevel@tonic-gate result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL); 31167c478bd9Sstevel@tonic-gate if (result->status == NIS_SUCCESS) 31177c478bd9Sstevel@tonic-gate { 31187c478bd9Sstevel@tonic-gate int count; 31197c478bd9Sstevel@tonic-gate char *str; 31207c478bd9Sstevel@tonic-gate 31217c478bd9Sstevel@tonic-gate if ((count = NIS_RES_NUMOBJ(result)) != 1) 31227c478bd9Sstevel@tonic-gate { 31237c478bd9Sstevel@tonic-gate if (LogLevel > 10) 31247c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, CurEnv->e_id, 31257c478bd9Sstevel@tonic-gate "%s: lookup error, expected 1 entry, got %d", 31267c478bd9Sstevel@tonic-gate map->map_file, count); 31277c478bd9Sstevel@tonic-gate 31287c478bd9Sstevel@tonic-gate /* ignore second entry */ 31297c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 31307c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", 31317c478bd9Sstevel@tonic-gate name, count); 31327c478bd9Sstevel@tonic-gate } 31337c478bd9Sstevel@tonic-gate 31347c478bd9Sstevel@tonic-gate p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); 31357c478bd9Sstevel@tonic-gate /* set the length of the result */ 31367c478bd9Sstevel@tonic-gate if (p == NULL) 31377c478bd9Sstevel@tonic-gate p = ""; 31387c478bd9Sstevel@tonic-gate vsize = strlen(p); 31397c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 31407c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_lookup(%s), found %s\n", 31417c478bd9Sstevel@tonic-gate name, p); 31427c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 31437c478bd9Sstevel@tonic-gate str = map_rewrite(map, name, strlen(name), NULL); 31447c478bd9Sstevel@tonic-gate else 31457c478bd9Sstevel@tonic-gate str = map_rewrite(map, p, vsize, av); 31467c478bd9Sstevel@tonic-gate nis_freeresult(result); 31477c478bd9Sstevel@tonic-gate *statp = EX_OK; 31487c478bd9Sstevel@tonic-gate return str; 31497c478bd9Sstevel@tonic-gate } 31507c478bd9Sstevel@tonic-gate else 31517c478bd9Sstevel@tonic-gate { 31527c478bd9Sstevel@tonic-gate if (result->status == NIS_NOTFOUND) 31537c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 31547c478bd9Sstevel@tonic-gate else if (result->status == NIS_TRYAGAIN) 31557c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 31567c478bd9Sstevel@tonic-gate else 31577c478bd9Sstevel@tonic-gate { 31587c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 31597c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_VALID|MF_OPEN); 31607c478bd9Sstevel@tonic-gate } 31617c478bd9Sstevel@tonic-gate } 31627c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 31637c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_map_lookup(%s), failed\n", name); 31647c478bd9Sstevel@tonic-gate nis_freeresult(result); 31657c478bd9Sstevel@tonic-gate return NULL; 31667c478bd9Sstevel@tonic-gate } 31677c478bd9Sstevel@tonic-gate 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate 31707c478bd9Sstevel@tonic-gate /* 31717c478bd9Sstevel@tonic-gate ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ 31727c478bd9Sstevel@tonic-gate */ 31737c478bd9Sstevel@tonic-gate 31747c478bd9Sstevel@tonic-gate static bool 31757c478bd9Sstevel@tonic-gate nisplus_getcanonname(name, hbsize, statp) 31767c478bd9Sstevel@tonic-gate char *name; 31777c478bd9Sstevel@tonic-gate int hbsize; 31787c478bd9Sstevel@tonic-gate int *statp; 31797c478bd9Sstevel@tonic-gate { 31807c478bd9Sstevel@tonic-gate char *vp; 31817c478bd9Sstevel@tonic-gate auto int vsize; 31827c478bd9Sstevel@tonic-gate nis_result *result; 31837c478bd9Sstevel@tonic-gate char *p; 31847c478bd9Sstevel@tonic-gate char nbuf[MAXNAME + 1]; 31857c478bd9Sstevel@tonic-gate char qbuf[MAXLINE + NIS_MAXNAMELEN]; 31867c478bd9Sstevel@tonic-gate 31877c478bd9Sstevel@tonic-gate if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 31887c478bd9Sstevel@tonic-gate { 31897c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 31907c478bd9Sstevel@tonic-gate return false; 31917c478bd9Sstevel@tonic-gate } 31927c478bd9Sstevel@tonic-gate (void) shorten_hostname(nbuf); 31937c478bd9Sstevel@tonic-gate 31947c478bd9Sstevel@tonic-gate p = strchr(nbuf, '.'); 31957c478bd9Sstevel@tonic-gate if (p == NULL) 31967c478bd9Sstevel@tonic-gate { 31977c478bd9Sstevel@tonic-gate /* single token */ 31987c478bd9Sstevel@tonic-gate (void) sm_snprintf(qbuf, sizeof qbuf, 31997c478bd9Sstevel@tonic-gate "[name=%s],hosts.org_dir", nbuf); 32007c478bd9Sstevel@tonic-gate } 32017c478bd9Sstevel@tonic-gate else if (p[1] != '\0') 32027c478bd9Sstevel@tonic-gate { 32037c478bd9Sstevel@tonic-gate /* multi token -- take only first token in nbuf */ 32047c478bd9Sstevel@tonic-gate *p = '\0'; 32057c478bd9Sstevel@tonic-gate (void) sm_snprintf(qbuf, sizeof qbuf, 32067c478bd9Sstevel@tonic-gate "[name=%s],hosts.org_dir.%s", nbuf, &p[1]); 32077c478bd9Sstevel@tonic-gate } 32087c478bd9Sstevel@tonic-gate else 32097c478bd9Sstevel@tonic-gate { 32107c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 32117c478bd9Sstevel@tonic-gate return false; 32127c478bd9Sstevel@tonic-gate } 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 32157c478bd9Sstevel@tonic-gate sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n", 32167c478bd9Sstevel@tonic-gate name, qbuf); 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH, 32197c478bd9Sstevel@tonic-gate NULL, NULL); 32207c478bd9Sstevel@tonic-gate 32217c478bd9Sstevel@tonic-gate if (result->status == NIS_SUCCESS) 32227c478bd9Sstevel@tonic-gate { 32237c478bd9Sstevel@tonic-gate int count; 32247c478bd9Sstevel@tonic-gate char *domain; 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate if ((count = NIS_RES_NUMOBJ(result)) != 1) 32277c478bd9Sstevel@tonic-gate { 32287c478bd9Sstevel@tonic-gate if (LogLevel > 10) 32297c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, CurEnv->e_id, 32307c478bd9Sstevel@tonic-gate "nisplus_getcanonname: lookup error, expected 1 entry, got %d", 32317c478bd9Sstevel@tonic-gate count); 32327c478bd9Sstevel@tonic-gate 32337c478bd9Sstevel@tonic-gate /* ignore second entry */ 32347c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 32357c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n", 32367c478bd9Sstevel@tonic-gate name, count); 32377c478bd9Sstevel@tonic-gate } 32387c478bd9Sstevel@tonic-gate 32397c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 32407c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n", 32417c478bd9Sstevel@tonic-gate name, (NIS_RES_OBJECT(result))->zo_domain); 32427c478bd9Sstevel@tonic-gate 32437c478bd9Sstevel@tonic-gate 32447c478bd9Sstevel@tonic-gate vp = ((NIS_RES_OBJECT(result))->EN_col(0)); 32457c478bd9Sstevel@tonic-gate vsize = strlen(vp); 32467c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 32477c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_getcanonname(%s), found %s\n", 32487c478bd9Sstevel@tonic-gate name, vp); 32497c478bd9Sstevel@tonic-gate if (strchr(vp, '.') != NULL) 32507c478bd9Sstevel@tonic-gate { 32517c478bd9Sstevel@tonic-gate domain = ""; 32527c478bd9Sstevel@tonic-gate } 32537c478bd9Sstevel@tonic-gate else 32547c478bd9Sstevel@tonic-gate { 32557c478bd9Sstevel@tonic-gate domain = macvalue('m', CurEnv); 32567c478bd9Sstevel@tonic-gate if (domain == NULL) 32577c478bd9Sstevel@tonic-gate domain = ""; 32587c478bd9Sstevel@tonic-gate } 32597c478bd9Sstevel@tonic-gate if (hbsize > vsize + (int) strlen(domain) + 1) 32607c478bd9Sstevel@tonic-gate { 32617c478bd9Sstevel@tonic-gate if (domain[0] == '\0') 32627c478bd9Sstevel@tonic-gate (void) sm_strlcpy(name, vp, hbsize); 32637c478bd9Sstevel@tonic-gate else 32647c478bd9Sstevel@tonic-gate (void) sm_snprintf(name, hbsize, 32657c478bd9Sstevel@tonic-gate "%s.%s", vp, domain); 32667c478bd9Sstevel@tonic-gate *statp = EX_OK; 32677c478bd9Sstevel@tonic-gate } 32687c478bd9Sstevel@tonic-gate else 32697c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 32707c478bd9Sstevel@tonic-gate nis_freeresult(result); 32717c478bd9Sstevel@tonic-gate return true; 32727c478bd9Sstevel@tonic-gate } 32737c478bd9Sstevel@tonic-gate else 32747c478bd9Sstevel@tonic-gate { 32757c478bd9Sstevel@tonic-gate if (result->status == NIS_NOTFOUND) 32767c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 32777c478bd9Sstevel@tonic-gate else if (result->status == NIS_TRYAGAIN) 32787c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 32797c478bd9Sstevel@tonic-gate else 32807c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 32817c478bd9Sstevel@tonic-gate } 32827c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 32837c478bd9Sstevel@tonic-gate sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n", 32847c478bd9Sstevel@tonic-gate name, result->status, *statp); 32857c478bd9Sstevel@tonic-gate nis_freeresult(result); 32867c478bd9Sstevel@tonic-gate return false; 32877c478bd9Sstevel@tonic-gate } 32887c478bd9Sstevel@tonic-gate 32897c478bd9Sstevel@tonic-gate char * 32907c478bd9Sstevel@tonic-gate nisplus_default_domain() 32917c478bd9Sstevel@tonic-gate { 32927c478bd9Sstevel@tonic-gate static char default_domain[MAXNAME + 1] = ""; 32937c478bd9Sstevel@tonic-gate char *p; 32947c478bd9Sstevel@tonic-gate 32957c478bd9Sstevel@tonic-gate if (default_domain[0] != '\0') 32967c478bd9Sstevel@tonic-gate return default_domain; 32977c478bd9Sstevel@tonic-gate 32987c478bd9Sstevel@tonic-gate p = nis_local_directory(); 32997c478bd9Sstevel@tonic-gate (void) sm_strlcpy(default_domain, p, sizeof default_domain); 33007c478bd9Sstevel@tonic-gate return default_domain; 33017c478bd9Sstevel@tonic-gate } 33027c478bd9Sstevel@tonic-gate 33037c478bd9Sstevel@tonic-gate #endif /* NISPLUS */ 33047c478bd9Sstevel@tonic-gate /* 33057c478bd9Sstevel@tonic-gate ** LDAP Modules 33067c478bd9Sstevel@tonic-gate */ 33077c478bd9Sstevel@tonic-gate 33087c478bd9Sstevel@tonic-gate /* 33097c478bd9Sstevel@tonic-gate ** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs 33107c478bd9Sstevel@tonic-gate */ 33117c478bd9Sstevel@tonic-gate 33127c478bd9Sstevel@tonic-gate #if defined(LDAPMAP) || defined(PH_MAP) 33137c478bd9Sstevel@tonic-gate 33147c478bd9Sstevel@tonic-gate # if PH_MAP 33157c478bd9Sstevel@tonic-gate # define ph_map_dequote ldapmap_dequote 33167c478bd9Sstevel@tonic-gate # endif /* PH_MAP */ 33177c478bd9Sstevel@tonic-gate 33187c478bd9Sstevel@tonic-gate static char *ldapmap_dequote __P((char *)); 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate static char * 33217c478bd9Sstevel@tonic-gate ldapmap_dequote(str) 33227c478bd9Sstevel@tonic-gate char *str; 33237c478bd9Sstevel@tonic-gate { 33247c478bd9Sstevel@tonic-gate char *p; 33257c478bd9Sstevel@tonic-gate char *start; 33267c478bd9Sstevel@tonic-gate 33277c478bd9Sstevel@tonic-gate if (str == NULL) 33287c478bd9Sstevel@tonic-gate return NULL; 33297c478bd9Sstevel@tonic-gate 33307c478bd9Sstevel@tonic-gate p = str; 33317c478bd9Sstevel@tonic-gate if (*p == '"') 33327c478bd9Sstevel@tonic-gate { 33337c478bd9Sstevel@tonic-gate /* Should probably swallow initial whitespace here */ 33347c478bd9Sstevel@tonic-gate start = ++p; 33357c478bd9Sstevel@tonic-gate } 33367c478bd9Sstevel@tonic-gate else 33377c478bd9Sstevel@tonic-gate return str; 33387c478bd9Sstevel@tonic-gate while (*p != '"' && *p != '\0') 33397c478bd9Sstevel@tonic-gate p++; 33407c478bd9Sstevel@tonic-gate if (*p != '\0') 33417c478bd9Sstevel@tonic-gate *p = '\0'; 33427c478bd9Sstevel@tonic-gate return start; 33437c478bd9Sstevel@tonic-gate } 33447c478bd9Sstevel@tonic-gate #endif /* defined(LDAPMAP) || defined(PH_MAP) */ 33457c478bd9Sstevel@tonic-gate 33467c478bd9Sstevel@tonic-gate #if LDAPMAP 33477c478bd9Sstevel@tonic-gate 33487c478bd9Sstevel@tonic-gate static SM_LDAP_STRUCT *LDAPDefaults = NULL; 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate /* 33517c478bd9Sstevel@tonic-gate ** LDAPMAP_OPEN -- open LDAP map 33527c478bd9Sstevel@tonic-gate ** 33537c478bd9Sstevel@tonic-gate ** Connect to the LDAP server. Re-use existing connections since a 33547c478bd9Sstevel@tonic-gate ** single server connection to a host (with the same host, port, 33557c478bd9Sstevel@tonic-gate ** bind DN, and secret) can answer queries for multiple maps. 33567c478bd9Sstevel@tonic-gate */ 33577c478bd9Sstevel@tonic-gate 33587c478bd9Sstevel@tonic-gate bool 33597c478bd9Sstevel@tonic-gate ldapmap_open(map, mode) 33607c478bd9Sstevel@tonic-gate MAP *map; 33617c478bd9Sstevel@tonic-gate int mode; 33627c478bd9Sstevel@tonic-gate { 33637c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 33647c478bd9Sstevel@tonic-gate STAB *s; 33657c478bd9Sstevel@tonic-gate char *id; 33667c478bd9Sstevel@tonic-gate 33677c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 33687c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode); 33697c478bd9Sstevel@tonic-gate 33707c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 33717c478bd9Sstevel@tonic-gate defined(HASLDAPGETALIASBYNAME) 33727c478bd9Sstevel@tonic-gate if (VendorCode == VENDOR_SUN && 33737c478bd9Sstevel@tonic-gate strcmp(map->map_mname, "aliases.ldap") == 0) 33747c478bd9Sstevel@tonic-gate { 33757c478bd9Sstevel@tonic-gate return true; 33767c478bd9Sstevel@tonic-gate } 33777c478bd9Sstevel@tonic-gate #endif 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 33807c478bd9Sstevel@tonic-gate 33817c478bd9Sstevel@tonic-gate /* sendmail doesn't have the ability to write to LDAP (yet) */ 33827c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 33837c478bd9Sstevel@tonic-gate { 33847c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 33857c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 33867c478bd9Sstevel@tonic-gate return false; 33877c478bd9Sstevel@tonic-gate } 33887c478bd9Sstevel@tonic-gate 33897c478bd9Sstevel@tonic-gate lmap = (SM_LDAP_STRUCT *) map->map_db1; 33907c478bd9Sstevel@tonic-gate 33917c478bd9Sstevel@tonic-gate s = ldapmap_findconn(lmap); 33927c478bd9Sstevel@tonic-gate if (s->s_lmap != NULL) 33937c478bd9Sstevel@tonic-gate { 33947c478bd9Sstevel@tonic-gate /* Already have a connection open to this LDAP server */ 33957c478bd9Sstevel@tonic-gate lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; 33967c478bd9Sstevel@tonic-gate lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid; 33977c478bd9Sstevel@tonic-gate 33987c478bd9Sstevel@tonic-gate /* Add this map as head of linked list */ 33997c478bd9Sstevel@tonic-gate lmap->ldap_next = s->s_lmap; 34007c478bd9Sstevel@tonic-gate s->s_lmap = map; 34017c478bd9Sstevel@tonic-gate 34027c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 34037c478bd9Sstevel@tonic-gate sm_dprintf("using cached connection\n"); 34047c478bd9Sstevel@tonic-gate return true; 34057c478bd9Sstevel@tonic-gate } 34067c478bd9Sstevel@tonic-gate 34077c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 34087c478bd9Sstevel@tonic-gate sm_dprintf("opening new connection\n"); 34097c478bd9Sstevel@tonic-gate 34107c478bd9Sstevel@tonic-gate if (lmap->ldap_host != NULL) 34117c478bd9Sstevel@tonic-gate id = lmap->ldap_host; 34127c478bd9Sstevel@tonic-gate else if (lmap->ldap_uri != NULL) 34137c478bd9Sstevel@tonic-gate id = lmap->ldap_uri; 34147c478bd9Sstevel@tonic-gate else 34157c478bd9Sstevel@tonic-gate id = "localhost"; 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate /* No connection yet, connect */ 34187c478bd9Sstevel@tonic-gate if (!sm_ldap_start(map->map_mname, lmap)) 34197c478bd9Sstevel@tonic-gate { 34207c478bd9Sstevel@tonic-gate if (errno == ETIMEDOUT) 34217c478bd9Sstevel@tonic-gate { 34227c478bd9Sstevel@tonic-gate if (LogLevel > 1) 34237c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 34247c478bd9Sstevel@tonic-gate "timeout conning to LDAP server %.100s", 34257c478bd9Sstevel@tonic-gate id); 34267c478bd9Sstevel@tonic-gate } 34277c478bd9Sstevel@tonic-gate 34287c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 34297c478bd9Sstevel@tonic-gate { 34307c478bd9Sstevel@tonic-gate if (bitset(MF_NODEFER, map->map_mflags)) 34317c478bd9Sstevel@tonic-gate { 34327c478bd9Sstevel@tonic-gate syserr("%s failed to %s in map %s", 34337c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 34347c478bd9Sstevel@tonic-gate "ldap_init/ldap_bind", 34357c478bd9Sstevel@tonic-gate # else /* USE_LDAP_INIT */ 34367c478bd9Sstevel@tonic-gate "ldap_open", 34377c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 34387c478bd9Sstevel@tonic-gate id, map->map_mname); 34397c478bd9Sstevel@tonic-gate } 34407c478bd9Sstevel@tonic-gate else 34417c478bd9Sstevel@tonic-gate { 34427c478bd9Sstevel@tonic-gate syserr("451 4.3.5 %s failed to %s in map %s", 34437c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT 34447c478bd9Sstevel@tonic-gate "ldap_init/ldap_bind", 34457c478bd9Sstevel@tonic-gate # else /* USE_LDAP_INIT */ 34467c478bd9Sstevel@tonic-gate "ldap_open", 34477c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */ 34487c478bd9Sstevel@tonic-gate id, map->map_mname); 34497c478bd9Sstevel@tonic-gate } 34507c478bd9Sstevel@tonic-gate } 34517c478bd9Sstevel@tonic-gate return false; 34527c478bd9Sstevel@tonic-gate } 34537c478bd9Sstevel@tonic-gate 34547c478bd9Sstevel@tonic-gate /* Save connection for reuse */ 34557c478bd9Sstevel@tonic-gate s->s_lmap = map; 34567c478bd9Sstevel@tonic-gate return true; 34577c478bd9Sstevel@tonic-gate } 34587c478bd9Sstevel@tonic-gate 34597c478bd9Sstevel@tonic-gate /* 34607c478bd9Sstevel@tonic-gate ** LDAPMAP_CLOSE -- close ldap map 34617c478bd9Sstevel@tonic-gate */ 34627c478bd9Sstevel@tonic-gate 34637c478bd9Sstevel@tonic-gate void 34647c478bd9Sstevel@tonic-gate ldapmap_close(map) 34657c478bd9Sstevel@tonic-gate MAP *map; 34667c478bd9Sstevel@tonic-gate { 34677c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 34687c478bd9Sstevel@tonic-gate STAB *s; 34697c478bd9Sstevel@tonic-gate 34707c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 34717c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_close(%s)\n", map->map_mname); 34727c478bd9Sstevel@tonic-gate 34737c478bd9Sstevel@tonic-gate lmap = (SM_LDAP_STRUCT *) map->map_db1; 34747c478bd9Sstevel@tonic-gate 34757c478bd9Sstevel@tonic-gate /* Check if already closed */ 34767c478bd9Sstevel@tonic-gate if (lmap->ldap_ld == NULL) 34777c478bd9Sstevel@tonic-gate return; 34787c478bd9Sstevel@tonic-gate 34797c478bd9Sstevel@tonic-gate /* Close the LDAP connection */ 34807c478bd9Sstevel@tonic-gate sm_ldap_close(lmap); 34817c478bd9Sstevel@tonic-gate 34827c478bd9Sstevel@tonic-gate /* Mark all the maps that share the connection as closed */ 34837c478bd9Sstevel@tonic-gate s = ldapmap_findconn(lmap); 34847c478bd9Sstevel@tonic-gate 34857c478bd9Sstevel@tonic-gate while (s->s_lmap != NULL) 34867c478bd9Sstevel@tonic-gate { 34877c478bd9Sstevel@tonic-gate MAP *smap = s->s_lmap; 34887c478bd9Sstevel@tonic-gate 34897c478bd9Sstevel@tonic-gate if (tTd(38, 2) && smap != map) 34907c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", 34917c478bd9Sstevel@tonic-gate map->map_mname, smap->map_mname); 34927c478bd9Sstevel@tonic-gate smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 34937c478bd9Sstevel@tonic-gate lmap = (SM_LDAP_STRUCT *) smap->map_db1; 34947c478bd9Sstevel@tonic-gate lmap->ldap_ld = NULL; 34957c478bd9Sstevel@tonic-gate s->s_lmap = lmap->ldap_next; 34967c478bd9Sstevel@tonic-gate lmap->ldap_next = NULL; 34977c478bd9Sstevel@tonic-gate } 34987c478bd9Sstevel@tonic-gate } 34997c478bd9Sstevel@tonic-gate 35007c478bd9Sstevel@tonic-gate # ifdef SUNET_ID 35017c478bd9Sstevel@tonic-gate /* 35027c478bd9Sstevel@tonic-gate ** SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form 35037c478bd9Sstevel@tonic-gate ** This only makes sense at Stanford University. 35047c478bd9Sstevel@tonic-gate */ 35057c478bd9Sstevel@tonic-gate 35067c478bd9Sstevel@tonic-gate static char * 35077c478bd9Sstevel@tonic-gate sunet_id_hash(str) 35087c478bd9Sstevel@tonic-gate char *str; 35097c478bd9Sstevel@tonic-gate { 35107c478bd9Sstevel@tonic-gate char *p, *p_last; 35117c478bd9Sstevel@tonic-gate 35127c478bd9Sstevel@tonic-gate p = str; 35137c478bd9Sstevel@tonic-gate p_last = p; 35147c478bd9Sstevel@tonic-gate while (*p != '\0') 35157c478bd9Sstevel@tonic-gate { 35167c478bd9Sstevel@tonic-gate if (islower(*p) || isdigit(*p)) 35177c478bd9Sstevel@tonic-gate { 35187c478bd9Sstevel@tonic-gate *p_last = *p; 35197c478bd9Sstevel@tonic-gate p_last++; 35207c478bd9Sstevel@tonic-gate } 35217c478bd9Sstevel@tonic-gate else if (isupper(*p)) 35227c478bd9Sstevel@tonic-gate { 35237c478bd9Sstevel@tonic-gate *p_last = tolower(*p); 35247c478bd9Sstevel@tonic-gate p_last++; 35257c478bd9Sstevel@tonic-gate } 35267c478bd9Sstevel@tonic-gate ++p; 35277c478bd9Sstevel@tonic-gate } 35287c478bd9Sstevel@tonic-gate if (*p_last != '\0') 35297c478bd9Sstevel@tonic-gate *p_last = '\0'; 35307c478bd9Sstevel@tonic-gate return str; 35317c478bd9Sstevel@tonic-gate } 35327c478bd9Sstevel@tonic-gate # endif /* SUNET_ID */ 35337c478bd9Sstevel@tonic-gate 35347c478bd9Sstevel@tonic-gate /* 35357c478bd9Sstevel@tonic-gate ** LDAPMAP_LOOKUP -- look up a datum in a LDAP map 35367c478bd9Sstevel@tonic-gate */ 35377c478bd9Sstevel@tonic-gate 35387c478bd9Sstevel@tonic-gate char * 35397c478bd9Sstevel@tonic-gate ldapmap_lookup(map, name, av, statp) 35407c478bd9Sstevel@tonic-gate MAP *map; 35417c478bd9Sstevel@tonic-gate char *name; 35427c478bd9Sstevel@tonic-gate char **av; 35437c478bd9Sstevel@tonic-gate int *statp; 35447c478bd9Sstevel@tonic-gate { 35457c478bd9Sstevel@tonic-gate int flags; 35467c478bd9Sstevel@tonic-gate int plen = 0; 35477c478bd9Sstevel@tonic-gate int psize = 0; 35487c478bd9Sstevel@tonic-gate int msgid; 35497c478bd9Sstevel@tonic-gate int save_errno; 35507c478bd9Sstevel@tonic-gate char *vp, *p; 35517c478bd9Sstevel@tonic-gate char *result = NULL; 35527c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 35537c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap = NULL; 3554445f2479Sjbeck char keybuf[MAXKEY]; 35557c478bd9Sstevel@tonic-gate 35567c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 35577c478bd9Sstevel@tonic-gate sm_dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); 35587c478bd9Sstevel@tonic-gate 35597c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \ 35607c478bd9Sstevel@tonic-gate defined(HASLDAPGETALIASBYNAME) 35617c478bd9Sstevel@tonic-gate if (VendorCode == VENDOR_SUN && 35627c478bd9Sstevel@tonic-gate strcmp(map->map_mname, "aliases.ldap") == 0) 35637c478bd9Sstevel@tonic-gate { 35647c478bd9Sstevel@tonic-gate char answer[MAXNAME + 1]; 35657c478bd9Sstevel@tonic-gate int rc; 35667c478bd9Sstevel@tonic-gate 35677c478bd9Sstevel@tonic-gate rc = __getldapaliasbyname(name, answer, sizeof(answer)); 35687c478bd9Sstevel@tonic-gate if (rc != 0) 35697c478bd9Sstevel@tonic-gate { 35707c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 35717c478bd9Sstevel@tonic-gate sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n", 35727c478bd9Sstevel@tonic-gate name, errno); 35737c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 35747c478bd9Sstevel@tonic-gate return NULL; 35757c478bd9Sstevel@tonic-gate } 35767c478bd9Sstevel@tonic-gate *statp = EX_OK; 35777c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 35787c478bd9Sstevel@tonic-gate sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name, 35797c478bd9Sstevel@tonic-gate answer); 35807c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 35817c478bd9Sstevel@tonic-gate result = map_rewrite(map, name, strlen(name), NULL); 35827c478bd9Sstevel@tonic-gate else 35837c478bd9Sstevel@tonic-gate result = map_rewrite(map, answer, strlen(answer), av); 35847c478bd9Sstevel@tonic-gate return result; 35857c478bd9Sstevel@tonic-gate } 35867c478bd9Sstevel@tonic-gate #endif 35877c478bd9Sstevel@tonic-gate 35887c478bd9Sstevel@tonic-gate /* Get ldap struct pointer from map */ 35897c478bd9Sstevel@tonic-gate lmap = (SM_LDAP_STRUCT *) map->map_db1; 35907c478bd9Sstevel@tonic-gate sm_ldap_setopts(lmap->ldap_ld, lmap); 35917c478bd9Sstevel@tonic-gate 35927c478bd9Sstevel@tonic-gate (void) sm_strlcpy(keybuf, name, sizeof keybuf); 35937c478bd9Sstevel@tonic-gate 35947c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 35957c478bd9Sstevel@tonic-gate { 35967c478bd9Sstevel@tonic-gate # ifdef SUNET_ID 35977c478bd9Sstevel@tonic-gate sunet_id_hash(keybuf); 35987c478bd9Sstevel@tonic-gate # else /* SUNET_ID */ 35997c478bd9Sstevel@tonic-gate makelower(keybuf); 36007c478bd9Sstevel@tonic-gate # endif /* SUNET_ID */ 36017c478bd9Sstevel@tonic-gate } 36027c478bd9Sstevel@tonic-gate 36037c478bd9Sstevel@tonic-gate msgid = sm_ldap_search(lmap, keybuf); 36047c478bd9Sstevel@tonic-gate if (msgid == -1) 36057c478bd9Sstevel@tonic-gate { 36067c478bd9Sstevel@tonic-gate errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE; 36077c478bd9Sstevel@tonic-gate save_errno = errno; 36087c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 36097c478bd9Sstevel@tonic-gate { 36107c478bd9Sstevel@tonic-gate if (bitset(MF_NODEFER, map->map_mflags)) 36117c478bd9Sstevel@tonic-gate syserr("Error in ldap_search using %s in map %s", 36127c478bd9Sstevel@tonic-gate keybuf, map->map_mname); 36137c478bd9Sstevel@tonic-gate else 36147c478bd9Sstevel@tonic-gate syserr("451 4.3.5 Error in ldap_search using %s in map %s", 36157c478bd9Sstevel@tonic-gate keybuf, map->map_mname); 36167c478bd9Sstevel@tonic-gate } 36177c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 36187c478bd9Sstevel@tonic-gate switch (save_errno - E_LDAPBASE) 36197c478bd9Sstevel@tonic-gate { 36207c478bd9Sstevel@tonic-gate # ifdef LDAP_SERVER_DOWN 36217c478bd9Sstevel@tonic-gate case LDAP_SERVER_DOWN: 36227c478bd9Sstevel@tonic-gate # endif /* LDAP_SERVER_DOWN */ 36237c478bd9Sstevel@tonic-gate case LDAP_TIMEOUT: 36247c478bd9Sstevel@tonic-gate case LDAP_UNAVAILABLE: 36257c478bd9Sstevel@tonic-gate /* server disappeared, try reopen on next search */ 36267c478bd9Sstevel@tonic-gate ldapmap_close(map); 36277c478bd9Sstevel@tonic-gate break; 36287c478bd9Sstevel@tonic-gate } 36297c478bd9Sstevel@tonic-gate errno = save_errno; 36307c478bd9Sstevel@tonic-gate return NULL; 36317c478bd9Sstevel@tonic-gate } 36327c478bd9Sstevel@tonic-gate 36337c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 36347c478bd9Sstevel@tonic-gate vp = NULL; 36357c478bd9Sstevel@tonic-gate 36367c478bd9Sstevel@tonic-gate flags = 0; 36377c478bd9Sstevel@tonic-gate if (bitset(MF_SINGLEMATCH, map->map_mflags)) 36387c478bd9Sstevel@tonic-gate flags |= SM_LDAP_SINGLEMATCH; 36397c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 36407c478bd9Sstevel@tonic-gate flags |= SM_LDAP_MATCHONLY; 364149218d4fSjbeck # if _FFR_LDAP_SINGLEDN 364249218d4fSjbeck if (bitset(MF_SINGLEDN, map->map_mflags)) 364349218d4fSjbeck flags |= SM_LDAP_SINGLEDN; 364449218d4fSjbeck # endif /* _FFR_LDAP_SINGLEDN */ 36457c478bd9Sstevel@tonic-gate 36467c478bd9Sstevel@tonic-gate /* Create an rpool for search related memory usage */ 36477c478bd9Sstevel@tonic-gate rpool = sm_rpool_new_x(NULL); 36487c478bd9Sstevel@tonic-gate 36497c478bd9Sstevel@tonic-gate p = NULL; 36507c478bd9Sstevel@tonic-gate *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim, 36517c478bd9Sstevel@tonic-gate rpool, &p, &plen, &psize, NULL); 36527c478bd9Sstevel@tonic-gate save_errno = errno; 36537c478bd9Sstevel@tonic-gate 36547c478bd9Sstevel@tonic-gate /* Copy result so rpool can be freed */ 36557c478bd9Sstevel@tonic-gate if (*statp == EX_OK && p != NULL) 36567c478bd9Sstevel@tonic-gate vp = newstr(p); 36577c478bd9Sstevel@tonic-gate sm_rpool_free(rpool); 36587c478bd9Sstevel@tonic-gate 36597c478bd9Sstevel@tonic-gate /* need to restart LDAP connection? */ 36607c478bd9Sstevel@tonic-gate if (*statp == EX_RESTART) 36617c478bd9Sstevel@tonic-gate { 36627c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 36637c478bd9Sstevel@tonic-gate ldapmap_close(map); 36647c478bd9Sstevel@tonic-gate } 36657c478bd9Sstevel@tonic-gate 36667c478bd9Sstevel@tonic-gate errno = save_errno; 36677c478bd9Sstevel@tonic-gate if (*statp != EX_OK && *statp != EX_NOTFOUND) 36687c478bd9Sstevel@tonic-gate { 36697c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 36707c478bd9Sstevel@tonic-gate { 36717c478bd9Sstevel@tonic-gate if (bitset(MF_NODEFER, map->map_mflags)) 36727c478bd9Sstevel@tonic-gate syserr("Error getting LDAP results in map %s", 36737c478bd9Sstevel@tonic-gate map->map_mname); 36747c478bd9Sstevel@tonic-gate else 36757c478bd9Sstevel@tonic-gate syserr("451 4.3.5 Error getting LDAP results in map %s", 36767c478bd9Sstevel@tonic-gate map->map_mname); 36777c478bd9Sstevel@tonic-gate } 36787c478bd9Sstevel@tonic-gate errno = save_errno; 36797c478bd9Sstevel@tonic-gate return NULL; 36807c478bd9Sstevel@tonic-gate } 36817c478bd9Sstevel@tonic-gate 36827c478bd9Sstevel@tonic-gate /* Did we match anything? */ 36837c478bd9Sstevel@tonic-gate if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags)) 36847c478bd9Sstevel@tonic-gate return NULL; 36857c478bd9Sstevel@tonic-gate 36867c478bd9Sstevel@tonic-gate if (*statp == EX_OK) 36877c478bd9Sstevel@tonic-gate { 36887c478bd9Sstevel@tonic-gate if (LogLevel > 9) 36897c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, CurEnv->e_id, 36907c478bd9Sstevel@tonic-gate "ldap %.100s => %s", name, 36917c478bd9Sstevel@tonic-gate vp == NULL ? "<NULL>" : vp); 36927c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 36937c478bd9Sstevel@tonic-gate result = map_rewrite(map, name, strlen(name), NULL); 36947c478bd9Sstevel@tonic-gate else 36957c478bd9Sstevel@tonic-gate { 36967c478bd9Sstevel@tonic-gate /* vp != NULL according to test above */ 36977c478bd9Sstevel@tonic-gate result = map_rewrite(map, vp, strlen(vp), av); 36987c478bd9Sstevel@tonic-gate } 36997c478bd9Sstevel@tonic-gate if (vp != NULL) 37007c478bd9Sstevel@tonic-gate sm_free(vp); /* XXX */ 37017c478bd9Sstevel@tonic-gate } 37027c478bd9Sstevel@tonic-gate return result; 37037c478bd9Sstevel@tonic-gate } 37047c478bd9Sstevel@tonic-gate 37057c478bd9Sstevel@tonic-gate /* 37067c478bd9Sstevel@tonic-gate ** LDAPMAP_FINDCONN -- find an LDAP connection to the server 37077c478bd9Sstevel@tonic-gate ** 37087c478bd9Sstevel@tonic-gate ** Cache LDAP connections based on the host, port, bind DN, 37097c478bd9Sstevel@tonic-gate ** secret, and PID so we don't have multiple connections open to 37107c478bd9Sstevel@tonic-gate ** the same server for different maps. Need a separate connection 37117c478bd9Sstevel@tonic-gate ** per PID since a parent process may close the map before the 37127c478bd9Sstevel@tonic-gate ** child is done with it. 37137c478bd9Sstevel@tonic-gate ** 37147c478bd9Sstevel@tonic-gate ** Parameters: 37157c478bd9Sstevel@tonic-gate ** lmap -- LDAP map information 37167c478bd9Sstevel@tonic-gate ** 37177c478bd9Sstevel@tonic-gate ** Returns: 37187c478bd9Sstevel@tonic-gate ** Symbol table entry for the LDAP connection. 37197c478bd9Sstevel@tonic-gate */ 37207c478bd9Sstevel@tonic-gate 37217c478bd9Sstevel@tonic-gate static STAB * 37227c478bd9Sstevel@tonic-gate ldapmap_findconn(lmap) 37237c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 37247c478bd9Sstevel@tonic-gate { 37257c478bd9Sstevel@tonic-gate char *format; 37267c478bd9Sstevel@tonic-gate char *nbuf; 37277c478bd9Sstevel@tonic-gate char *id; 37287c478bd9Sstevel@tonic-gate STAB *SM_NONVOLATILE s = NULL; 37297c478bd9Sstevel@tonic-gate 37307c478bd9Sstevel@tonic-gate if (lmap->ldap_host != NULL) 37317c478bd9Sstevel@tonic-gate id = lmap->ldap_host; 37327c478bd9Sstevel@tonic-gate else if (lmap->ldap_uri != NULL) 37337c478bd9Sstevel@tonic-gate id = lmap->ldap_uri; 37347c478bd9Sstevel@tonic-gate else 37357c478bd9Sstevel@tonic-gate id = "localhost"; 37367c478bd9Sstevel@tonic-gate 37377c478bd9Sstevel@tonic-gate format = "%s%c%d%c%d%c%s%c%s%d"; 37387c478bd9Sstevel@tonic-gate nbuf = sm_stringf_x(format, 37397c478bd9Sstevel@tonic-gate id, 37407c478bd9Sstevel@tonic-gate CONDELSE, 37417c478bd9Sstevel@tonic-gate lmap->ldap_port, 37427c478bd9Sstevel@tonic-gate CONDELSE, 37437c478bd9Sstevel@tonic-gate lmap->ldap_version, 37447c478bd9Sstevel@tonic-gate CONDELSE, 37457c478bd9Sstevel@tonic-gate (lmap->ldap_binddn == NULL ? "" 37467c478bd9Sstevel@tonic-gate : lmap->ldap_binddn), 37477c478bd9Sstevel@tonic-gate CONDELSE, 37487c478bd9Sstevel@tonic-gate (lmap->ldap_secret == NULL ? "" 37497c478bd9Sstevel@tonic-gate : lmap->ldap_secret), 37507c478bd9Sstevel@tonic-gate (int) CurrentPid); 37517c478bd9Sstevel@tonic-gate SM_TRY 37527c478bd9Sstevel@tonic-gate s = stab(nbuf, ST_LMAP, ST_ENTER); 37537c478bd9Sstevel@tonic-gate SM_FINALLY 37547c478bd9Sstevel@tonic-gate sm_free(nbuf); 37557c478bd9Sstevel@tonic-gate SM_END_TRY 37567c478bd9Sstevel@tonic-gate return s; 37577c478bd9Sstevel@tonic-gate } 37587c478bd9Sstevel@tonic-gate /* 37597c478bd9Sstevel@tonic-gate ** LDAPMAP_PARSEARGS -- parse ldap map definition args. 37607c478bd9Sstevel@tonic-gate */ 37617c478bd9Sstevel@tonic-gate 37627c478bd9Sstevel@tonic-gate static struct lamvalues LDAPAuthMethods[] = 37637c478bd9Sstevel@tonic-gate { 37647c478bd9Sstevel@tonic-gate { "none", LDAP_AUTH_NONE }, 37657c478bd9Sstevel@tonic-gate { "simple", LDAP_AUTH_SIMPLE }, 37667c478bd9Sstevel@tonic-gate # ifdef LDAP_AUTH_KRBV4 37677c478bd9Sstevel@tonic-gate { "krbv4", LDAP_AUTH_KRBV4 }, 37687c478bd9Sstevel@tonic-gate # endif /* LDAP_AUTH_KRBV4 */ 37697c478bd9Sstevel@tonic-gate { NULL, 0 } 37707c478bd9Sstevel@tonic-gate }; 37717c478bd9Sstevel@tonic-gate 37727c478bd9Sstevel@tonic-gate static struct ladvalues LDAPAliasDereference[] = 37737c478bd9Sstevel@tonic-gate { 37747c478bd9Sstevel@tonic-gate { "never", LDAP_DEREF_NEVER }, 37757c478bd9Sstevel@tonic-gate { "always", LDAP_DEREF_ALWAYS }, 37767c478bd9Sstevel@tonic-gate { "search", LDAP_DEREF_SEARCHING }, 37777c478bd9Sstevel@tonic-gate { "find", LDAP_DEREF_FINDING }, 37787c478bd9Sstevel@tonic-gate { NULL, 0 } 37797c478bd9Sstevel@tonic-gate }; 37807c478bd9Sstevel@tonic-gate 37817c478bd9Sstevel@tonic-gate static struct lssvalues LDAPSearchScope[] = 37827c478bd9Sstevel@tonic-gate { 37837c478bd9Sstevel@tonic-gate { "base", LDAP_SCOPE_BASE }, 37847c478bd9Sstevel@tonic-gate { "one", LDAP_SCOPE_ONELEVEL }, 37857c478bd9Sstevel@tonic-gate { "sub", LDAP_SCOPE_SUBTREE }, 37867c478bd9Sstevel@tonic-gate { NULL, 0 } 37877c478bd9Sstevel@tonic-gate }; 37887c478bd9Sstevel@tonic-gate 37897c478bd9Sstevel@tonic-gate bool 37907c478bd9Sstevel@tonic-gate ldapmap_parseargs(map, args) 37917c478bd9Sstevel@tonic-gate MAP *map; 37927c478bd9Sstevel@tonic-gate char *args; 37937c478bd9Sstevel@tonic-gate { 37947c478bd9Sstevel@tonic-gate bool secretread = true; 37957c478bd9Sstevel@tonic-gate bool attrssetup = false; 37967c478bd9Sstevel@tonic-gate int i; 37977c478bd9Sstevel@tonic-gate register char *p = args; 37987c478bd9Sstevel@tonic-gate SM_LDAP_STRUCT *lmap; 37997c478bd9Sstevel@tonic-gate struct lamvalues *lam; 38007c478bd9Sstevel@tonic-gate struct ladvalues *lad; 38017c478bd9Sstevel@tonic-gate struct lssvalues *lss; 38027c478bd9Sstevel@tonic-gate char ldapfilt[MAXLINE]; 38037c478bd9Sstevel@tonic-gate char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; 38047c478bd9Sstevel@tonic-gate 38057c478bd9Sstevel@tonic-gate /* Get ldap struct pointer from map */ 38067c478bd9Sstevel@tonic-gate lmap = (SM_LDAP_STRUCT *) map->map_db1; 38077c478bd9Sstevel@tonic-gate 38087c478bd9Sstevel@tonic-gate /* Check if setting the initial LDAP defaults */ 38097c478bd9Sstevel@tonic-gate if (lmap == NULL || lmap != LDAPDefaults) 38107c478bd9Sstevel@tonic-gate { 38117c478bd9Sstevel@tonic-gate /* We need to alloc an SM_LDAP_STRUCT struct */ 38127c478bd9Sstevel@tonic-gate lmap = (SM_LDAP_STRUCT *) xalloc(sizeof *lmap); 38137c478bd9Sstevel@tonic-gate if (LDAPDefaults == NULL) 38147c478bd9Sstevel@tonic-gate sm_ldap_clear(lmap); 38157c478bd9Sstevel@tonic-gate else 38167c478bd9Sstevel@tonic-gate STRUCTCOPY(*LDAPDefaults, *lmap); 38177c478bd9Sstevel@tonic-gate } 38187c478bd9Sstevel@tonic-gate 38197c478bd9Sstevel@tonic-gate /* there is no check whether there is really an argument */ 38207c478bd9Sstevel@tonic-gate map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 38217c478bd9Sstevel@tonic-gate map->map_spacesub = SpaceSub; /* default value */ 38227c478bd9Sstevel@tonic-gate 38237c478bd9Sstevel@tonic-gate /* Check if setting up an alias or file class LDAP map */ 38247c478bd9Sstevel@tonic-gate if (bitset(MF_ALIAS, map->map_mflags)) 38257c478bd9Sstevel@tonic-gate { 38267c478bd9Sstevel@tonic-gate /* Comma separate if used as an alias file */ 38277c478bd9Sstevel@tonic-gate map->map_coldelim = ','; 38287c478bd9Sstevel@tonic-gate if (*args == '\0') 38297c478bd9Sstevel@tonic-gate { 38307c478bd9Sstevel@tonic-gate int n; 38317c478bd9Sstevel@tonic-gate char *lc; 38327c478bd9Sstevel@tonic-gate char jbuf[MAXHOSTNAMELEN]; 38337c478bd9Sstevel@tonic-gate char lcbuf[MAXLINE]; 38347c478bd9Sstevel@tonic-gate 38357c478bd9Sstevel@tonic-gate /* Get $j */ 38367c478bd9Sstevel@tonic-gate expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 38377c478bd9Sstevel@tonic-gate if (jbuf[0] == '\0') 38387c478bd9Sstevel@tonic-gate { 38397c478bd9Sstevel@tonic-gate (void) sm_strlcpy(jbuf, "localhost", 38407c478bd9Sstevel@tonic-gate sizeof jbuf); 38417c478bd9Sstevel@tonic-gate } 38427c478bd9Sstevel@tonic-gate 38437c478bd9Sstevel@tonic-gate lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 38447c478bd9Sstevel@tonic-gate if (lc == NULL) 38457c478bd9Sstevel@tonic-gate lc = ""; 38467c478bd9Sstevel@tonic-gate else 38477c478bd9Sstevel@tonic-gate { 38487c478bd9Sstevel@tonic-gate expand(lc, lcbuf, sizeof lcbuf, CurEnv); 38497c478bd9Sstevel@tonic-gate lc = lcbuf; 38507c478bd9Sstevel@tonic-gate } 38517c478bd9Sstevel@tonic-gate 38527c478bd9Sstevel@tonic-gate n = sm_snprintf(ldapfilt, sizeof ldapfilt, 38537c478bd9Sstevel@tonic-gate "(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))", 38547c478bd9Sstevel@tonic-gate lc, jbuf); 38557c478bd9Sstevel@tonic-gate if (n >= sizeof ldapfilt) 38567c478bd9Sstevel@tonic-gate { 38577c478bd9Sstevel@tonic-gate syserr("%s: Default LDAP string too long", 38587c478bd9Sstevel@tonic-gate map->map_mname); 38597c478bd9Sstevel@tonic-gate return false; 38607c478bd9Sstevel@tonic-gate } 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate /* default args for an alias LDAP entry */ 38637c478bd9Sstevel@tonic-gate lmap->ldap_filter = ldapfilt; 38647c478bd9Sstevel@tonic-gate lmap->ldap_attr[0] = "objectClass"; 38657c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS; 38667c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[0] = NULL; 38677c478bd9Sstevel@tonic-gate lmap->ldap_attr[1] = "sendmailMTAAliasValue"; 38687c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL; 38697c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[1] = NULL; 38707c478bd9Sstevel@tonic-gate lmap->ldap_attr[2] = "sendmailMTAAliasSearch"; 38717c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER; 38727c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject"; 38737c478bd9Sstevel@tonic-gate lmap->ldap_attr[3] = "sendmailMTAAliasURL"; 38747c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL; 38757c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject"; 38767c478bd9Sstevel@tonic-gate lmap->ldap_attr[4] = NULL; 38777c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE; 38787c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[4] = NULL; 38797c478bd9Sstevel@tonic-gate attrssetup = true; 38807c478bd9Sstevel@tonic-gate } 38817c478bd9Sstevel@tonic-gate } 38827c478bd9Sstevel@tonic-gate else if (bitset(MF_FILECLASS, map->map_mflags)) 38837c478bd9Sstevel@tonic-gate { 38847c478bd9Sstevel@tonic-gate /* Space separate if used as a file class file */ 38857c478bd9Sstevel@tonic-gate map->map_coldelim = ' '; 38867c478bd9Sstevel@tonic-gate } 38877c478bd9Sstevel@tonic-gate 38887c478bd9Sstevel@tonic-gate for (;;) 38897c478bd9Sstevel@tonic-gate { 38907c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 38917c478bd9Sstevel@tonic-gate p++; 38927c478bd9Sstevel@tonic-gate if (*p != '-') 38937c478bd9Sstevel@tonic-gate break; 38947c478bd9Sstevel@tonic-gate switch (*++p) 38957c478bd9Sstevel@tonic-gate { 38967c478bd9Sstevel@tonic-gate case 'N': 38977c478bd9Sstevel@tonic-gate map->map_mflags |= MF_INCLNULL; 38987c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 38997c478bd9Sstevel@tonic-gate break; 39007c478bd9Sstevel@tonic-gate 39017c478bd9Sstevel@tonic-gate case 'O': 39027c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 39037c478bd9Sstevel@tonic-gate break; 39047c478bd9Sstevel@tonic-gate 39057c478bd9Sstevel@tonic-gate case 'o': 39067c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPTIONAL; 39077c478bd9Sstevel@tonic-gate break; 39087c478bd9Sstevel@tonic-gate 39097c478bd9Sstevel@tonic-gate case 'f': 39107c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NOFOLDCASE; 39117c478bd9Sstevel@tonic-gate break; 39127c478bd9Sstevel@tonic-gate 39137c478bd9Sstevel@tonic-gate case 'm': 39147c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 39157c478bd9Sstevel@tonic-gate break; 39167c478bd9Sstevel@tonic-gate 39177c478bd9Sstevel@tonic-gate case 'A': 39187c478bd9Sstevel@tonic-gate map->map_mflags |= MF_APPEND; 39197c478bd9Sstevel@tonic-gate break; 39207c478bd9Sstevel@tonic-gate 39217c478bd9Sstevel@tonic-gate case 'q': 39227c478bd9Sstevel@tonic-gate map->map_mflags |= MF_KEEPQUOTES; 39237c478bd9Sstevel@tonic-gate break; 39247c478bd9Sstevel@tonic-gate 39257c478bd9Sstevel@tonic-gate case 'a': 39267c478bd9Sstevel@tonic-gate map->map_app = ++p; 39277c478bd9Sstevel@tonic-gate break; 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate case 'T': 39307c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 39317c478bd9Sstevel@tonic-gate break; 39327c478bd9Sstevel@tonic-gate 39337c478bd9Sstevel@tonic-gate case 't': 39347c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 39357c478bd9Sstevel@tonic-gate break; 39367c478bd9Sstevel@tonic-gate 39377c478bd9Sstevel@tonic-gate case 'S': 39387c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 39397c478bd9Sstevel@tonic-gate break; 39407c478bd9Sstevel@tonic-gate 39417c478bd9Sstevel@tonic-gate case 'D': 39427c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 39437c478bd9Sstevel@tonic-gate break; 39447c478bd9Sstevel@tonic-gate 39457c478bd9Sstevel@tonic-gate case 'z': 39467c478bd9Sstevel@tonic-gate if (*++p != '\\') 39477c478bd9Sstevel@tonic-gate map->map_coldelim = *p; 39487c478bd9Sstevel@tonic-gate else 39497c478bd9Sstevel@tonic-gate { 39507c478bd9Sstevel@tonic-gate switch (*++p) 39517c478bd9Sstevel@tonic-gate { 39527c478bd9Sstevel@tonic-gate case 'n': 39537c478bd9Sstevel@tonic-gate map->map_coldelim = '\n'; 39547c478bd9Sstevel@tonic-gate break; 39557c478bd9Sstevel@tonic-gate 39567c478bd9Sstevel@tonic-gate case 't': 39577c478bd9Sstevel@tonic-gate map->map_coldelim = '\t'; 39587c478bd9Sstevel@tonic-gate break; 39597c478bd9Sstevel@tonic-gate 39607c478bd9Sstevel@tonic-gate default: 39617c478bd9Sstevel@tonic-gate map->map_coldelim = '\\'; 39627c478bd9Sstevel@tonic-gate } 39637c478bd9Sstevel@tonic-gate } 39647c478bd9Sstevel@tonic-gate break; 39657c478bd9Sstevel@tonic-gate 39667c478bd9Sstevel@tonic-gate /* Start of ldapmap specific args */ 39677c478bd9Sstevel@tonic-gate case 'V': 39687c478bd9Sstevel@tonic-gate if (*++p != '\\') 39697c478bd9Sstevel@tonic-gate lmap->ldap_attrsep = *p; 39707c478bd9Sstevel@tonic-gate else 39717c478bd9Sstevel@tonic-gate { 39727c478bd9Sstevel@tonic-gate switch (*++p) 39737c478bd9Sstevel@tonic-gate { 39747c478bd9Sstevel@tonic-gate case 'n': 39757c478bd9Sstevel@tonic-gate lmap->ldap_attrsep = '\n'; 39767c478bd9Sstevel@tonic-gate break; 39777c478bd9Sstevel@tonic-gate 39787c478bd9Sstevel@tonic-gate case 't': 39797c478bd9Sstevel@tonic-gate lmap->ldap_attrsep = '\t'; 39807c478bd9Sstevel@tonic-gate break; 39817c478bd9Sstevel@tonic-gate 39827c478bd9Sstevel@tonic-gate default: 39837c478bd9Sstevel@tonic-gate lmap->ldap_attrsep = '\\'; 39847c478bd9Sstevel@tonic-gate } 39857c478bd9Sstevel@tonic-gate } 39867c478bd9Sstevel@tonic-gate break; 39877c478bd9Sstevel@tonic-gate 39887c478bd9Sstevel@tonic-gate case 'k': /* search field */ 39897c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 39907c478bd9Sstevel@tonic-gate continue; 39917c478bd9Sstevel@tonic-gate lmap->ldap_filter = p; 39927c478bd9Sstevel@tonic-gate break; 39937c478bd9Sstevel@tonic-gate 39947c478bd9Sstevel@tonic-gate case 'v': /* attr to return */ 39957c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 39967c478bd9Sstevel@tonic-gate continue; 39977c478bd9Sstevel@tonic-gate lmap->ldap_attr[0] = p; 39987c478bd9Sstevel@tonic-gate lmap->ldap_attr[1] = NULL; 39997c478bd9Sstevel@tonic-gate break; 40007c478bd9Sstevel@tonic-gate 40017c478bd9Sstevel@tonic-gate case '1': 40027c478bd9Sstevel@tonic-gate map->map_mflags |= MF_SINGLEMATCH; 40037c478bd9Sstevel@tonic-gate break; 40047c478bd9Sstevel@tonic-gate 400549218d4fSjbeck # if _FFR_LDAP_SINGLEDN 400649218d4fSjbeck case '2': 400749218d4fSjbeck map->map_mflags |= MF_SINGLEDN; 400849218d4fSjbeck break; 400949218d4fSjbeck # endif /* _FFR_LDAP_SINGLEDN */ 401049218d4fSjbeck 40117c478bd9Sstevel@tonic-gate /* args stolen from ldapsearch.c */ 40127c478bd9Sstevel@tonic-gate case 'R': /* don't auto chase referrals */ 40137c478bd9Sstevel@tonic-gate # ifdef LDAP_REFERRALS 40147c478bd9Sstevel@tonic-gate lmap->ldap_options &= ~LDAP_OPT_REFERRALS; 40157c478bd9Sstevel@tonic-gate # else /* LDAP_REFERRALS */ 40167c478bd9Sstevel@tonic-gate syserr("compile with -DLDAP_REFERRALS for referral support"); 40177c478bd9Sstevel@tonic-gate # endif /* LDAP_REFERRALS */ 40187c478bd9Sstevel@tonic-gate break; 40197c478bd9Sstevel@tonic-gate 40207c478bd9Sstevel@tonic-gate case 'n': /* retrieve attribute names only */ 40217c478bd9Sstevel@tonic-gate lmap->ldap_attrsonly = LDAPMAP_TRUE; 40227c478bd9Sstevel@tonic-gate break; 40237c478bd9Sstevel@tonic-gate 40247c478bd9Sstevel@tonic-gate case 'r': /* alias dereferencing */ 40257c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 40267c478bd9Sstevel@tonic-gate continue; 40277c478bd9Sstevel@tonic-gate 40287c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0) 40297c478bd9Sstevel@tonic-gate p += 11; 40307c478bd9Sstevel@tonic-gate 40317c478bd9Sstevel@tonic-gate for (lad = LDAPAliasDereference; 40327c478bd9Sstevel@tonic-gate lad != NULL && lad->lad_name != NULL; lad++) 40337c478bd9Sstevel@tonic-gate { 40347c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, lad->lad_name, 40357c478bd9Sstevel@tonic-gate strlen(lad->lad_name)) == 0) 40367c478bd9Sstevel@tonic-gate break; 40377c478bd9Sstevel@tonic-gate } 40387c478bd9Sstevel@tonic-gate if (lad->lad_name != NULL) 40397c478bd9Sstevel@tonic-gate lmap->ldap_deref = lad->lad_code; 40407c478bd9Sstevel@tonic-gate else 40417c478bd9Sstevel@tonic-gate { 40427c478bd9Sstevel@tonic-gate /* bad config line */ 40437c478bd9Sstevel@tonic-gate if (!bitset(MCF_OPTFILE, 40447c478bd9Sstevel@tonic-gate map->map_class->map_cflags)) 40457c478bd9Sstevel@tonic-gate { 40467c478bd9Sstevel@tonic-gate char *ptr; 40477c478bd9Sstevel@tonic-gate 40487c478bd9Sstevel@tonic-gate if ((ptr = strchr(p, ' ')) != NULL) 40497c478bd9Sstevel@tonic-gate *ptr = '\0'; 40507c478bd9Sstevel@tonic-gate syserr("Deref must be [never|always|search|find] (not %s) in map %s", 40517c478bd9Sstevel@tonic-gate p, map->map_mname); 40527c478bd9Sstevel@tonic-gate if (ptr != NULL) 40537c478bd9Sstevel@tonic-gate *ptr = ' '; 40547c478bd9Sstevel@tonic-gate return false; 40557c478bd9Sstevel@tonic-gate } 40567c478bd9Sstevel@tonic-gate } 40577c478bd9Sstevel@tonic-gate break; 40587c478bd9Sstevel@tonic-gate 40597c478bd9Sstevel@tonic-gate case 's': /* search scope */ 40607c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 40617c478bd9Sstevel@tonic-gate continue; 40627c478bd9Sstevel@tonic-gate 40637c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0) 40647c478bd9Sstevel@tonic-gate p += 11; 40657c478bd9Sstevel@tonic-gate 40667c478bd9Sstevel@tonic-gate for (lss = LDAPSearchScope; 40677c478bd9Sstevel@tonic-gate lss != NULL && lss->lss_name != NULL; lss++) 40687c478bd9Sstevel@tonic-gate { 40697c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, lss->lss_name, 40707c478bd9Sstevel@tonic-gate strlen(lss->lss_name)) == 0) 40717c478bd9Sstevel@tonic-gate break; 40727c478bd9Sstevel@tonic-gate } 40737c478bd9Sstevel@tonic-gate if (lss->lss_name != NULL) 40747c478bd9Sstevel@tonic-gate lmap->ldap_scope = lss->lss_code; 40757c478bd9Sstevel@tonic-gate else 40767c478bd9Sstevel@tonic-gate { 40777c478bd9Sstevel@tonic-gate /* bad config line */ 40787c478bd9Sstevel@tonic-gate if (!bitset(MCF_OPTFILE, 40797c478bd9Sstevel@tonic-gate map->map_class->map_cflags)) 40807c478bd9Sstevel@tonic-gate { 40817c478bd9Sstevel@tonic-gate char *ptr; 40827c478bd9Sstevel@tonic-gate 40837c478bd9Sstevel@tonic-gate if ((ptr = strchr(p, ' ')) != NULL) 40847c478bd9Sstevel@tonic-gate *ptr = '\0'; 40857c478bd9Sstevel@tonic-gate syserr("Scope must be [base|one|sub] (not %s) in map %s", 40867c478bd9Sstevel@tonic-gate p, map->map_mname); 40877c478bd9Sstevel@tonic-gate if (ptr != NULL) 40887c478bd9Sstevel@tonic-gate *ptr = ' '; 40897c478bd9Sstevel@tonic-gate return false; 40907c478bd9Sstevel@tonic-gate } 40917c478bd9Sstevel@tonic-gate } 40927c478bd9Sstevel@tonic-gate break; 40937c478bd9Sstevel@tonic-gate 40947c478bd9Sstevel@tonic-gate case 'h': /* ldap host */ 40957c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 40967c478bd9Sstevel@tonic-gate continue; 40977c478bd9Sstevel@tonic-gate if (lmap->ldap_uri != NULL) 40987c478bd9Sstevel@tonic-gate { 40997c478bd9Sstevel@tonic-gate syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 41007c478bd9Sstevel@tonic-gate map->map_mname); 41017c478bd9Sstevel@tonic-gate return false; 41027c478bd9Sstevel@tonic-gate } 41037c478bd9Sstevel@tonic-gate lmap->ldap_host = p; 41047c478bd9Sstevel@tonic-gate break; 41057c478bd9Sstevel@tonic-gate 41067c478bd9Sstevel@tonic-gate case 'b': /* search base */ 41077c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41087c478bd9Sstevel@tonic-gate continue; 41097c478bd9Sstevel@tonic-gate lmap->ldap_base = p; 41107c478bd9Sstevel@tonic-gate break; 41117c478bd9Sstevel@tonic-gate 41127c478bd9Sstevel@tonic-gate case 'p': /* ldap port */ 41137c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41147c478bd9Sstevel@tonic-gate continue; 41157c478bd9Sstevel@tonic-gate lmap->ldap_port = atoi(p); 41167c478bd9Sstevel@tonic-gate break; 41177c478bd9Sstevel@tonic-gate 41187c478bd9Sstevel@tonic-gate case 'l': /* time limit */ 41197c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41207c478bd9Sstevel@tonic-gate continue; 41217c478bd9Sstevel@tonic-gate lmap->ldap_timelimit = atoi(p); 41227c478bd9Sstevel@tonic-gate lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; 41237c478bd9Sstevel@tonic-gate break; 41247c478bd9Sstevel@tonic-gate 41257c478bd9Sstevel@tonic-gate case 'Z': 41267c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41277c478bd9Sstevel@tonic-gate continue; 41287c478bd9Sstevel@tonic-gate lmap->ldap_sizelimit = atoi(p); 41297c478bd9Sstevel@tonic-gate break; 41307c478bd9Sstevel@tonic-gate 41317c478bd9Sstevel@tonic-gate case 'd': /* Dn to bind to server as */ 41327c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41337c478bd9Sstevel@tonic-gate continue; 41347c478bd9Sstevel@tonic-gate lmap->ldap_binddn = p; 41357c478bd9Sstevel@tonic-gate break; 41367c478bd9Sstevel@tonic-gate 41377c478bd9Sstevel@tonic-gate case 'M': /* Method for binding */ 41387c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41397c478bd9Sstevel@tonic-gate continue; 41407c478bd9Sstevel@tonic-gate 41417c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0) 41427c478bd9Sstevel@tonic-gate p += 10; 41437c478bd9Sstevel@tonic-gate 41447c478bd9Sstevel@tonic-gate for (lam = LDAPAuthMethods; 41457c478bd9Sstevel@tonic-gate lam != NULL && lam->lam_name != NULL; lam++) 41467c478bd9Sstevel@tonic-gate { 41477c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, lam->lam_name, 41487c478bd9Sstevel@tonic-gate strlen(lam->lam_name)) == 0) 41497c478bd9Sstevel@tonic-gate break; 41507c478bd9Sstevel@tonic-gate } 41517c478bd9Sstevel@tonic-gate if (lam->lam_name != NULL) 41527c478bd9Sstevel@tonic-gate lmap->ldap_method = lam->lam_code; 41537c478bd9Sstevel@tonic-gate else 41547c478bd9Sstevel@tonic-gate { 41557c478bd9Sstevel@tonic-gate /* bad config line */ 41567c478bd9Sstevel@tonic-gate if (!bitset(MCF_OPTFILE, 41577c478bd9Sstevel@tonic-gate map->map_class->map_cflags)) 41587c478bd9Sstevel@tonic-gate { 41597c478bd9Sstevel@tonic-gate char *ptr; 41607c478bd9Sstevel@tonic-gate 41617c478bd9Sstevel@tonic-gate if ((ptr = strchr(p, ' ')) != NULL) 41627c478bd9Sstevel@tonic-gate *ptr = '\0'; 41637c478bd9Sstevel@tonic-gate syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s", 41647c478bd9Sstevel@tonic-gate p, map->map_mname); 41657c478bd9Sstevel@tonic-gate if (ptr != NULL) 41667c478bd9Sstevel@tonic-gate *ptr = ' '; 41677c478bd9Sstevel@tonic-gate return false; 41687c478bd9Sstevel@tonic-gate } 41697c478bd9Sstevel@tonic-gate } 41707c478bd9Sstevel@tonic-gate 41717c478bd9Sstevel@tonic-gate break; 41727c478bd9Sstevel@tonic-gate 41737c478bd9Sstevel@tonic-gate /* 41747c478bd9Sstevel@tonic-gate ** This is a string that is dependent on the 41757c478bd9Sstevel@tonic-gate ** method used defined above. 41767c478bd9Sstevel@tonic-gate */ 41777c478bd9Sstevel@tonic-gate 41787c478bd9Sstevel@tonic-gate case 'P': /* Secret password for binding */ 41797c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41807c478bd9Sstevel@tonic-gate continue; 41817c478bd9Sstevel@tonic-gate lmap->ldap_secret = p; 41827c478bd9Sstevel@tonic-gate secretread = false; 41837c478bd9Sstevel@tonic-gate break; 41847c478bd9Sstevel@tonic-gate 41857c478bd9Sstevel@tonic-gate case 'H': /* Use LDAP URI */ 41867c478bd9Sstevel@tonic-gate # if !USE_LDAP_INIT 41877c478bd9Sstevel@tonic-gate syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s", 41887c478bd9Sstevel@tonic-gate map->map_mname); 41897c478bd9Sstevel@tonic-gate return false; 41907c478bd9Sstevel@tonic-gate # else /* !USE_LDAP_INIT */ 41917c478bd9Sstevel@tonic-gate if (lmap->ldap_host != NULL) 41927c478bd9Sstevel@tonic-gate { 41937c478bd9Sstevel@tonic-gate syserr("Can not specify both an LDAP host and an LDAP URI in map %s", 41947c478bd9Sstevel@tonic-gate map->map_mname); 41957c478bd9Sstevel@tonic-gate return false; 41967c478bd9Sstevel@tonic-gate } 41977c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41987c478bd9Sstevel@tonic-gate continue; 41997c478bd9Sstevel@tonic-gate lmap->ldap_uri = p; 42007c478bd9Sstevel@tonic-gate break; 42017c478bd9Sstevel@tonic-gate # endif /* !USE_LDAP_INIT */ 42027c478bd9Sstevel@tonic-gate 42037c478bd9Sstevel@tonic-gate case 'w': 42047c478bd9Sstevel@tonic-gate /* -w should be for passwd, -P should be for version */ 42057c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 42067c478bd9Sstevel@tonic-gate continue; 42077c478bd9Sstevel@tonic-gate lmap->ldap_version = atoi(p); 42087c478bd9Sstevel@tonic-gate # ifdef LDAP_VERSION_MAX 42097c478bd9Sstevel@tonic-gate if (lmap->ldap_version > LDAP_VERSION_MAX) 42107c478bd9Sstevel@tonic-gate { 42117c478bd9Sstevel@tonic-gate syserr("LDAP version %d exceeds max of %d in map %s", 42127c478bd9Sstevel@tonic-gate lmap->ldap_version, LDAP_VERSION_MAX, 42137c478bd9Sstevel@tonic-gate map->map_mname); 42147c478bd9Sstevel@tonic-gate return false; 42157c478bd9Sstevel@tonic-gate } 42167c478bd9Sstevel@tonic-gate # endif /* LDAP_VERSION_MAX */ 42177c478bd9Sstevel@tonic-gate # ifdef LDAP_VERSION_MIN 42187c478bd9Sstevel@tonic-gate if (lmap->ldap_version < LDAP_VERSION_MIN) 42197c478bd9Sstevel@tonic-gate { 42207c478bd9Sstevel@tonic-gate syserr("LDAP version %d is lower than min of %d in map %s", 42217c478bd9Sstevel@tonic-gate lmap->ldap_version, LDAP_VERSION_MIN, 42227c478bd9Sstevel@tonic-gate map->map_mname); 42237c478bd9Sstevel@tonic-gate return false; 42247c478bd9Sstevel@tonic-gate } 42257c478bd9Sstevel@tonic-gate # endif /* LDAP_VERSION_MIN */ 42267c478bd9Sstevel@tonic-gate break; 42277c478bd9Sstevel@tonic-gate 42287c478bd9Sstevel@tonic-gate default: 42297c478bd9Sstevel@tonic-gate syserr("Illegal option %c map %s", *p, map->map_mname); 42307c478bd9Sstevel@tonic-gate break; 42317c478bd9Sstevel@tonic-gate } 42327c478bd9Sstevel@tonic-gate 42337c478bd9Sstevel@tonic-gate /* need to account for quoted strings here */ 42347c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 42357c478bd9Sstevel@tonic-gate { 42367c478bd9Sstevel@tonic-gate if (*p == '"') 42377c478bd9Sstevel@tonic-gate { 42387c478bd9Sstevel@tonic-gate while (*++p != '"' && *p != '\0') 42397c478bd9Sstevel@tonic-gate continue; 42407c478bd9Sstevel@tonic-gate if (*p != '\0') 42417c478bd9Sstevel@tonic-gate p++; 42427c478bd9Sstevel@tonic-gate } 42437c478bd9Sstevel@tonic-gate else 42447c478bd9Sstevel@tonic-gate p++; 42457c478bd9Sstevel@tonic-gate } 42467c478bd9Sstevel@tonic-gate 42477c478bd9Sstevel@tonic-gate if (*p != '\0') 42487c478bd9Sstevel@tonic-gate *p++ = '\0'; 42497c478bd9Sstevel@tonic-gate } 42507c478bd9Sstevel@tonic-gate 42517c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 42527c478bd9Sstevel@tonic-gate map->map_app = newstr(ldapmap_dequote(map->map_app)); 42537c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 42547c478bd9Sstevel@tonic-gate map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); 42557c478bd9Sstevel@tonic-gate 42567c478bd9Sstevel@tonic-gate /* 42577c478bd9Sstevel@tonic-gate ** We need to swallow up all the stuff into a struct 42587c478bd9Sstevel@tonic-gate ** and dump it into map->map_dbptr1 42597c478bd9Sstevel@tonic-gate */ 42607c478bd9Sstevel@tonic-gate 42617c478bd9Sstevel@tonic-gate if (lmap->ldap_host != NULL && 42627c478bd9Sstevel@tonic-gate (LDAPDefaults == NULL || 42637c478bd9Sstevel@tonic-gate LDAPDefaults == lmap || 42647c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_host != lmap->ldap_host)) 42657c478bd9Sstevel@tonic-gate lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); 42667c478bd9Sstevel@tonic-gate map->map_domain = lmap->ldap_host; 42677c478bd9Sstevel@tonic-gate 42687c478bd9Sstevel@tonic-gate if (lmap->ldap_uri != NULL && 42697c478bd9Sstevel@tonic-gate (LDAPDefaults == NULL || 42707c478bd9Sstevel@tonic-gate LDAPDefaults == lmap || 42717c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_uri != lmap->ldap_uri)) 42727c478bd9Sstevel@tonic-gate lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri)); 42737c478bd9Sstevel@tonic-gate map->map_domain = lmap->ldap_uri; 42747c478bd9Sstevel@tonic-gate 42757c478bd9Sstevel@tonic-gate if (lmap->ldap_binddn != NULL && 42767c478bd9Sstevel@tonic-gate (LDAPDefaults == NULL || 42777c478bd9Sstevel@tonic-gate LDAPDefaults == lmap || 42787c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) 42797c478bd9Sstevel@tonic-gate lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); 42807c478bd9Sstevel@tonic-gate 42817c478bd9Sstevel@tonic-gate if (lmap->ldap_secret != NULL && 42827c478bd9Sstevel@tonic-gate (LDAPDefaults == NULL || 42837c478bd9Sstevel@tonic-gate LDAPDefaults == lmap || 42847c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_secret != lmap->ldap_secret)) 42857c478bd9Sstevel@tonic-gate { 42867c478bd9Sstevel@tonic-gate SM_FILE_T *sfd; 42877c478bd9Sstevel@tonic-gate long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; 42887c478bd9Sstevel@tonic-gate 42897c478bd9Sstevel@tonic-gate if (DontLockReadFiles) 42907c478bd9Sstevel@tonic-gate sff |= SFF_NOLOCK; 42917c478bd9Sstevel@tonic-gate 42927c478bd9Sstevel@tonic-gate /* need to use method to map secret to passwd string */ 42937c478bd9Sstevel@tonic-gate switch (lmap->ldap_method) 42947c478bd9Sstevel@tonic-gate { 42957c478bd9Sstevel@tonic-gate case LDAP_AUTH_NONE: 42967c478bd9Sstevel@tonic-gate /* Do nothing */ 42977c478bd9Sstevel@tonic-gate break; 42987c478bd9Sstevel@tonic-gate 42997c478bd9Sstevel@tonic-gate case LDAP_AUTH_SIMPLE: 43007c478bd9Sstevel@tonic-gate 43017c478bd9Sstevel@tonic-gate /* 43027c478bd9Sstevel@tonic-gate ** Secret is the name of a file with 43037c478bd9Sstevel@tonic-gate ** the first line as the password. 43047c478bd9Sstevel@tonic-gate */ 43057c478bd9Sstevel@tonic-gate 43067c478bd9Sstevel@tonic-gate /* Already read in the secret? */ 43077c478bd9Sstevel@tonic-gate if (secretread) 43087c478bd9Sstevel@tonic-gate break; 43097c478bd9Sstevel@tonic-gate 43107c478bd9Sstevel@tonic-gate sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), 43117c478bd9Sstevel@tonic-gate O_RDONLY, 0, sff); 43127c478bd9Sstevel@tonic-gate if (sfd == NULL) 43137c478bd9Sstevel@tonic-gate { 43147c478bd9Sstevel@tonic-gate syserr("LDAP map: cannot open secret %s", 43157c478bd9Sstevel@tonic-gate ldapmap_dequote(lmap->ldap_secret)); 43167c478bd9Sstevel@tonic-gate return false; 43177c478bd9Sstevel@tonic-gate } 43187c478bd9Sstevel@tonic-gate lmap->ldap_secret = sfgets(m_tmp, sizeof m_tmp, 43197c478bd9Sstevel@tonic-gate sfd, TimeOuts.to_fileopen, 43207c478bd9Sstevel@tonic-gate "ldapmap_parseargs"); 43217c478bd9Sstevel@tonic-gate (void) sm_io_close(sfd, SM_TIME_DEFAULT); 43227c478bd9Sstevel@tonic-gate if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD) 43237c478bd9Sstevel@tonic-gate { 43247c478bd9Sstevel@tonic-gate syserr("LDAP map: secret in %s too long", 43257c478bd9Sstevel@tonic-gate ldapmap_dequote(lmap->ldap_secret)); 43267c478bd9Sstevel@tonic-gate return false; 43277c478bd9Sstevel@tonic-gate } 43287c478bd9Sstevel@tonic-gate if (lmap->ldap_secret != NULL && 43297c478bd9Sstevel@tonic-gate strlen(m_tmp) > 0) 43307c478bd9Sstevel@tonic-gate { 43317c478bd9Sstevel@tonic-gate /* chomp newline */ 43327c478bd9Sstevel@tonic-gate if (m_tmp[strlen(m_tmp) - 1] == '\n') 43337c478bd9Sstevel@tonic-gate m_tmp[strlen(m_tmp) - 1] = '\0'; 43347c478bd9Sstevel@tonic-gate 43357c478bd9Sstevel@tonic-gate lmap->ldap_secret = m_tmp; 43367c478bd9Sstevel@tonic-gate } 43377c478bd9Sstevel@tonic-gate break; 43387c478bd9Sstevel@tonic-gate 43397c478bd9Sstevel@tonic-gate # ifdef LDAP_AUTH_KRBV4 43407c478bd9Sstevel@tonic-gate case LDAP_AUTH_KRBV4: 43417c478bd9Sstevel@tonic-gate 43427c478bd9Sstevel@tonic-gate /* 43437c478bd9Sstevel@tonic-gate ** Secret is where the ticket file is 43447c478bd9Sstevel@tonic-gate ** stashed 43457c478bd9Sstevel@tonic-gate */ 43467c478bd9Sstevel@tonic-gate 43477c478bd9Sstevel@tonic-gate (void) sm_snprintf(m_tmp, sizeof m_tmp, 43487c478bd9Sstevel@tonic-gate "KRBTKFILE=%s", 43497c478bd9Sstevel@tonic-gate ldapmap_dequote(lmap->ldap_secret)); 43507c478bd9Sstevel@tonic-gate lmap->ldap_secret = m_tmp; 43517c478bd9Sstevel@tonic-gate break; 43527c478bd9Sstevel@tonic-gate # endif /* LDAP_AUTH_KRBV4 */ 43537c478bd9Sstevel@tonic-gate 43547c478bd9Sstevel@tonic-gate default: /* Should NEVER get here */ 43557c478bd9Sstevel@tonic-gate syserr("LDAP map: Illegal value in lmap method"); 43567c478bd9Sstevel@tonic-gate return false; 43577c478bd9Sstevel@tonic-gate /* NOTREACHED */ 43587c478bd9Sstevel@tonic-gate break; 43597c478bd9Sstevel@tonic-gate } 43607c478bd9Sstevel@tonic-gate } 43617c478bd9Sstevel@tonic-gate 43627c478bd9Sstevel@tonic-gate if (lmap->ldap_secret != NULL && 43637c478bd9Sstevel@tonic-gate (LDAPDefaults == NULL || 43647c478bd9Sstevel@tonic-gate LDAPDefaults == lmap || 43657c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_secret != lmap->ldap_secret)) 43667c478bd9Sstevel@tonic-gate lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); 43677c478bd9Sstevel@tonic-gate 43687c478bd9Sstevel@tonic-gate if (lmap->ldap_base != NULL && 43697c478bd9Sstevel@tonic-gate (LDAPDefaults == NULL || 43707c478bd9Sstevel@tonic-gate LDAPDefaults == lmap || 43717c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_base != lmap->ldap_base)) 43727c478bd9Sstevel@tonic-gate lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); 43737c478bd9Sstevel@tonic-gate 43747c478bd9Sstevel@tonic-gate /* 43757c478bd9Sstevel@tonic-gate ** Save the server from extra work. If request is for a single 43767c478bd9Sstevel@tonic-gate ** match, tell the server to only return enough records to 43777c478bd9Sstevel@tonic-gate ** determine if there is a single match or not. This can not 43787c478bd9Sstevel@tonic-gate ** be one since the server would only return one and we wouldn't 43797c478bd9Sstevel@tonic-gate ** know if there were others available. 43807c478bd9Sstevel@tonic-gate */ 43817c478bd9Sstevel@tonic-gate 43827c478bd9Sstevel@tonic-gate if (bitset(MF_SINGLEMATCH, map->map_mflags)) 43837c478bd9Sstevel@tonic-gate lmap->ldap_sizelimit = 2; 43847c478bd9Sstevel@tonic-gate 43857c478bd9Sstevel@tonic-gate /* If setting defaults, don't process ldap_filter and ldap_attr */ 43867c478bd9Sstevel@tonic-gate if (lmap == LDAPDefaults) 43877c478bd9Sstevel@tonic-gate return true; 43887c478bd9Sstevel@tonic-gate 43897c478bd9Sstevel@tonic-gate if (lmap->ldap_filter != NULL) 43907c478bd9Sstevel@tonic-gate lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); 43917c478bd9Sstevel@tonic-gate else 43927c478bd9Sstevel@tonic-gate { 43937c478bd9Sstevel@tonic-gate if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) 43947c478bd9Sstevel@tonic-gate { 43957c478bd9Sstevel@tonic-gate syserr("No filter given in map %s", map->map_mname); 43967c478bd9Sstevel@tonic-gate return false; 43977c478bd9Sstevel@tonic-gate } 43987c478bd9Sstevel@tonic-gate } 43997c478bd9Sstevel@tonic-gate 44007c478bd9Sstevel@tonic-gate if (!attrssetup && lmap->ldap_attr[0] != NULL) 44017c478bd9Sstevel@tonic-gate { 44027c478bd9Sstevel@tonic-gate bool recurse = false; 44037c478bd9Sstevel@tonic-gate bool normalseen = false; 44047c478bd9Sstevel@tonic-gate 44057c478bd9Sstevel@tonic-gate i = 0; 44067c478bd9Sstevel@tonic-gate p = ldapmap_dequote(lmap->ldap_attr[0]); 44077c478bd9Sstevel@tonic-gate lmap->ldap_attr[0] = NULL; 44087c478bd9Sstevel@tonic-gate 44097c478bd9Sstevel@tonic-gate /* Prime the attr list with the objectClass attribute */ 44107c478bd9Sstevel@tonic-gate lmap->ldap_attr[i] = "objectClass"; 44117c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS; 44127c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[i] = NULL; 44137c478bd9Sstevel@tonic-gate i++; 44147c478bd9Sstevel@tonic-gate 44157c478bd9Sstevel@tonic-gate while (p != NULL) 44167c478bd9Sstevel@tonic-gate { 44177c478bd9Sstevel@tonic-gate char *v; 44187c478bd9Sstevel@tonic-gate 44197c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 44207c478bd9Sstevel@tonic-gate p++; 44217c478bd9Sstevel@tonic-gate if (*p == '\0') 44227c478bd9Sstevel@tonic-gate break; 44237c478bd9Sstevel@tonic-gate v = p; 44247c478bd9Sstevel@tonic-gate p = strchr(v, ','); 44257c478bd9Sstevel@tonic-gate if (p != NULL) 44267c478bd9Sstevel@tonic-gate *p++ = '\0'; 44277c478bd9Sstevel@tonic-gate 44287c478bd9Sstevel@tonic-gate if (i >= LDAPMAP_MAX_ATTR) 44297c478bd9Sstevel@tonic-gate { 44307c478bd9Sstevel@tonic-gate syserr("Too many return attributes in %s (max %d)", 44317c478bd9Sstevel@tonic-gate map->map_mname, LDAPMAP_MAX_ATTR); 44327c478bd9Sstevel@tonic-gate return false; 44337c478bd9Sstevel@tonic-gate } 44347c478bd9Sstevel@tonic-gate if (*v != '\0') 44357c478bd9Sstevel@tonic-gate { 44367c478bd9Sstevel@tonic-gate int j; 44377c478bd9Sstevel@tonic-gate int use; 44387c478bd9Sstevel@tonic-gate char *type; 44397c478bd9Sstevel@tonic-gate char *needobjclass; 44407c478bd9Sstevel@tonic-gate 44417c478bd9Sstevel@tonic-gate type = strchr(v, ':'); 44427c478bd9Sstevel@tonic-gate if (type != NULL) 44437c478bd9Sstevel@tonic-gate { 44447c478bd9Sstevel@tonic-gate *type++ = '\0'; 44457c478bd9Sstevel@tonic-gate needobjclass = strchr(type, ':'); 44467c478bd9Sstevel@tonic-gate if (needobjclass != NULL) 44477c478bd9Sstevel@tonic-gate *needobjclass++ = '\0'; 44487c478bd9Sstevel@tonic-gate } 44497c478bd9Sstevel@tonic-gate else 44507c478bd9Sstevel@tonic-gate { 44517c478bd9Sstevel@tonic-gate needobjclass = NULL; 44527c478bd9Sstevel@tonic-gate } 44537c478bd9Sstevel@tonic-gate 44547c478bd9Sstevel@tonic-gate use = i; 44557c478bd9Sstevel@tonic-gate 44567c478bd9Sstevel@tonic-gate /* allow override on "objectClass" type */ 44577c478bd9Sstevel@tonic-gate if (sm_strcasecmp(v, "objectClass") == 0 && 44587c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS) 44597c478bd9Sstevel@tonic-gate { 44607c478bd9Sstevel@tonic-gate use = 0; 44617c478bd9Sstevel@tonic-gate } 44627c478bd9Sstevel@tonic-gate else 44637c478bd9Sstevel@tonic-gate { 44647c478bd9Sstevel@tonic-gate /* 44657c478bd9Sstevel@tonic-gate ** Don't add something to attribute 44667c478bd9Sstevel@tonic-gate ** list twice. 44677c478bd9Sstevel@tonic-gate */ 44687c478bd9Sstevel@tonic-gate 44697c478bd9Sstevel@tonic-gate for (j = 1; j < i; j++) 44707c478bd9Sstevel@tonic-gate { 44717c478bd9Sstevel@tonic-gate if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0) 44727c478bd9Sstevel@tonic-gate { 44737c478bd9Sstevel@tonic-gate syserr("Duplicate attribute (%s) in %s", 44747c478bd9Sstevel@tonic-gate v, map->map_mname); 44757c478bd9Sstevel@tonic-gate return false; 44767c478bd9Sstevel@tonic-gate } 44777c478bd9Sstevel@tonic-gate } 44787c478bd9Sstevel@tonic-gate 44797c478bd9Sstevel@tonic-gate lmap->ldap_attr[use] = newstr(v); 44807c478bd9Sstevel@tonic-gate if (needobjclass != NULL && 44817c478bd9Sstevel@tonic-gate *needobjclass != '\0' && 44827c478bd9Sstevel@tonic-gate *needobjclass != '*') 44837c478bd9Sstevel@tonic-gate { 44847c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[use] = newstr(needobjclass); 44857c478bd9Sstevel@tonic-gate } 44867c478bd9Sstevel@tonic-gate else 44877c478bd9Sstevel@tonic-gate { 44887c478bd9Sstevel@tonic-gate lmap->ldap_attr_needobjclass[use] = NULL; 44897c478bd9Sstevel@tonic-gate } 44907c478bd9Sstevel@tonic-gate 44917c478bd9Sstevel@tonic-gate } 44927c478bd9Sstevel@tonic-gate 44937c478bd9Sstevel@tonic-gate if (type != NULL && *type != '\0') 44947c478bd9Sstevel@tonic-gate { 44957c478bd9Sstevel@tonic-gate if (sm_strcasecmp(type, "dn") == 0) 44967c478bd9Sstevel@tonic-gate { 44977c478bd9Sstevel@tonic-gate recurse = true; 44987c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN; 44997c478bd9Sstevel@tonic-gate } 45007c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(type, "filter") == 0) 45017c478bd9Sstevel@tonic-gate { 45027c478bd9Sstevel@tonic-gate recurse = true; 45037c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER; 45047c478bd9Sstevel@tonic-gate } 45057c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(type, "url") == 0) 45067c478bd9Sstevel@tonic-gate { 45077c478bd9Sstevel@tonic-gate recurse = true; 45087c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL; 45097c478bd9Sstevel@tonic-gate } 45107c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(type, "normal") == 0) 45117c478bd9Sstevel@tonic-gate { 45127c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 45137c478bd9Sstevel@tonic-gate normalseen = true; 45147c478bd9Sstevel@tonic-gate } 45157c478bd9Sstevel@tonic-gate else 45167c478bd9Sstevel@tonic-gate { 45177c478bd9Sstevel@tonic-gate syserr("Unknown attribute type (%s) in %s", 45187c478bd9Sstevel@tonic-gate type, map->map_mname); 45197c478bd9Sstevel@tonic-gate return false; 45207c478bd9Sstevel@tonic-gate } 45217c478bd9Sstevel@tonic-gate } 45227c478bd9Sstevel@tonic-gate else 45237c478bd9Sstevel@tonic-gate { 45247c478bd9Sstevel@tonic-gate lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL; 45257c478bd9Sstevel@tonic-gate normalseen = true; 45267c478bd9Sstevel@tonic-gate } 45277c478bd9Sstevel@tonic-gate i++; 45287c478bd9Sstevel@tonic-gate } 45297c478bd9Sstevel@tonic-gate } 45307c478bd9Sstevel@tonic-gate lmap->ldap_attr[i] = NULL; 45317c478bd9Sstevel@tonic-gate 45327c478bd9Sstevel@tonic-gate /* Set in case needed in future code */ 45337c478bd9Sstevel@tonic-gate attrssetup = true; 45347c478bd9Sstevel@tonic-gate 45357c478bd9Sstevel@tonic-gate if (recurse && !normalseen) 45367c478bd9Sstevel@tonic-gate { 45377c478bd9Sstevel@tonic-gate syserr("LDAP recursion requested in %s but no returnable attribute given", 45387c478bd9Sstevel@tonic-gate map->map_mname); 45397c478bd9Sstevel@tonic-gate return false; 45407c478bd9Sstevel@tonic-gate } 45417c478bd9Sstevel@tonic-gate if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE) 45427c478bd9Sstevel@tonic-gate { 45437c478bd9Sstevel@tonic-gate syserr("LDAP recursion requested in %s can not be used with -n", 45447c478bd9Sstevel@tonic-gate map->map_mname); 45457c478bd9Sstevel@tonic-gate return false; 45467c478bd9Sstevel@tonic-gate } 45477c478bd9Sstevel@tonic-gate } 45487c478bd9Sstevel@tonic-gate map->map_db1 = (ARBPTR_T) lmap; 45497c478bd9Sstevel@tonic-gate return true; 45507c478bd9Sstevel@tonic-gate } 45517c478bd9Sstevel@tonic-gate 45527c478bd9Sstevel@tonic-gate /* 45537c478bd9Sstevel@tonic-gate ** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf 45547c478bd9Sstevel@tonic-gate ** 45557c478bd9Sstevel@tonic-gate ** Parameters: 45567c478bd9Sstevel@tonic-gate ** spec -- map argument string from LDAPDefaults option 45577c478bd9Sstevel@tonic-gate ** 45587c478bd9Sstevel@tonic-gate ** Returns: 45597c478bd9Sstevel@tonic-gate ** None. 45607c478bd9Sstevel@tonic-gate */ 45617c478bd9Sstevel@tonic-gate 45627c478bd9Sstevel@tonic-gate void 45637c478bd9Sstevel@tonic-gate ldapmap_set_defaults(spec) 45647c478bd9Sstevel@tonic-gate char *spec; 45657c478bd9Sstevel@tonic-gate { 45667c478bd9Sstevel@tonic-gate STAB *class; 45677c478bd9Sstevel@tonic-gate MAP map; 45687c478bd9Sstevel@tonic-gate 45697c478bd9Sstevel@tonic-gate /* Allocate and set the default values */ 45707c478bd9Sstevel@tonic-gate if (LDAPDefaults == NULL) 45717c478bd9Sstevel@tonic-gate LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof *LDAPDefaults); 45727c478bd9Sstevel@tonic-gate sm_ldap_clear(LDAPDefaults); 45737c478bd9Sstevel@tonic-gate 45747c478bd9Sstevel@tonic-gate memset(&map, '\0', sizeof map); 45757c478bd9Sstevel@tonic-gate 45767c478bd9Sstevel@tonic-gate /* look up the class */ 45777c478bd9Sstevel@tonic-gate class = stab("ldap", ST_MAPCLASS, ST_FIND); 45787c478bd9Sstevel@tonic-gate if (class == NULL) 45797c478bd9Sstevel@tonic-gate { 45807c478bd9Sstevel@tonic-gate syserr("readcf: LDAPDefaultSpec: class ldap not available"); 45817c478bd9Sstevel@tonic-gate return; 45827c478bd9Sstevel@tonic-gate } 45837c478bd9Sstevel@tonic-gate map.map_class = &class->s_mapclass; 45847c478bd9Sstevel@tonic-gate map.map_db1 = (ARBPTR_T) LDAPDefaults; 45857c478bd9Sstevel@tonic-gate map.map_mname = "O LDAPDefaultSpec"; 45867c478bd9Sstevel@tonic-gate 45877c478bd9Sstevel@tonic-gate (void) ldapmap_parseargs(&map, spec); 45887c478bd9Sstevel@tonic-gate 45897c478bd9Sstevel@tonic-gate /* These should never be set in LDAPDefaults */ 45907c478bd9Sstevel@tonic-gate if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || 45917c478bd9Sstevel@tonic-gate map.map_spacesub != SpaceSub || 45927c478bd9Sstevel@tonic-gate map.map_app != NULL || 45937c478bd9Sstevel@tonic-gate map.map_tapp != NULL) 45947c478bd9Sstevel@tonic-gate { 45957c478bd9Sstevel@tonic-gate syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); 45967c478bd9Sstevel@tonic-gate SM_FREE_CLR(map.map_app); 45977c478bd9Sstevel@tonic-gate SM_FREE_CLR(map.map_tapp); 45987c478bd9Sstevel@tonic-gate } 45997c478bd9Sstevel@tonic-gate 46007c478bd9Sstevel@tonic-gate if (LDAPDefaults->ldap_filter != NULL) 46017c478bd9Sstevel@tonic-gate { 46027c478bd9Sstevel@tonic-gate syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); 46037c478bd9Sstevel@tonic-gate 46047c478bd9Sstevel@tonic-gate /* don't free, it isn't malloc'ed in parseargs */ 46057c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_filter = NULL; 46067c478bd9Sstevel@tonic-gate } 46077c478bd9Sstevel@tonic-gate 46087c478bd9Sstevel@tonic-gate if (LDAPDefaults->ldap_attr[0] != NULL) 46097c478bd9Sstevel@tonic-gate { 46107c478bd9Sstevel@tonic-gate syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); 46117c478bd9Sstevel@tonic-gate /* don't free, they aren't malloc'ed in parseargs */ 46127c478bd9Sstevel@tonic-gate LDAPDefaults->ldap_attr[0] = NULL; 46137c478bd9Sstevel@tonic-gate } 46147c478bd9Sstevel@tonic-gate } 46157c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 46167c478bd9Sstevel@tonic-gate /* 46177c478bd9Sstevel@tonic-gate ** PH map 46187c478bd9Sstevel@tonic-gate */ 46197c478bd9Sstevel@tonic-gate 46207c478bd9Sstevel@tonic-gate #if PH_MAP 46217c478bd9Sstevel@tonic-gate 46227c478bd9Sstevel@tonic-gate /* 46237c478bd9Sstevel@tonic-gate ** Support for the CCSO Nameserver (ph/qi). 46247c478bd9Sstevel@tonic-gate ** This code is intended to replace the so-called "ph mailer". 46257c478bd9Sstevel@tonic-gate ** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support. 46267c478bd9Sstevel@tonic-gate */ 46277c478bd9Sstevel@tonic-gate 46287c478bd9Sstevel@tonic-gate /* what version of the ph map code we're running */ 46297c478bd9Sstevel@tonic-gate static char phmap_id[128]; 46307c478bd9Sstevel@tonic-gate 46317c478bd9Sstevel@tonic-gate /* sendmail version for phmap id string */ 46327c478bd9Sstevel@tonic-gate extern const char Version[]; 46337c478bd9Sstevel@tonic-gate 46347c478bd9Sstevel@tonic-gate /* assume we're using nph-1.2.x if not specified */ 46357c478bd9Sstevel@tonic-gate # ifndef NPH_VERSION 46367c478bd9Sstevel@tonic-gate # define NPH_VERSION 10200 46377c478bd9Sstevel@tonic-gate # endif 46387c478bd9Sstevel@tonic-gate 46397c478bd9Sstevel@tonic-gate /* compatibility for versions older than nph-1.2.0 */ 46407c478bd9Sstevel@tonic-gate # if NPH_VERSION < 10200 46417c478bd9Sstevel@tonic-gate # define PH_OPEN_ROUNDROBIN PH_ROUNDROBIN 46427c478bd9Sstevel@tonic-gate # define PH_OPEN_DONTID PH_DONTID 46437c478bd9Sstevel@tonic-gate # define PH_CLOSE_FAST PH_FASTCLOSE 46447c478bd9Sstevel@tonic-gate # define PH_ERR_DATAERR PH_DATAERR 46457c478bd9Sstevel@tonic-gate # define PH_ERR_NOMATCH PH_NOMATCH 46467c478bd9Sstevel@tonic-gate # endif /* NPH_VERSION < 10200 */ 46477c478bd9Sstevel@tonic-gate 46487c478bd9Sstevel@tonic-gate /* 46497c478bd9Sstevel@tonic-gate ** PH_MAP_PARSEARGS -- parse ph map definition args. 46507c478bd9Sstevel@tonic-gate */ 46517c478bd9Sstevel@tonic-gate 46527c478bd9Sstevel@tonic-gate bool 46537c478bd9Sstevel@tonic-gate ph_map_parseargs(map, args) 46547c478bd9Sstevel@tonic-gate MAP *map; 46557c478bd9Sstevel@tonic-gate char *args; 46567c478bd9Sstevel@tonic-gate { 46577c478bd9Sstevel@tonic-gate register bool done; 46587c478bd9Sstevel@tonic-gate register char *p = args; 46597c478bd9Sstevel@tonic-gate PH_MAP_STRUCT *pmap = NULL; 46607c478bd9Sstevel@tonic-gate 46617c478bd9Sstevel@tonic-gate /* initialize version string */ 46627c478bd9Sstevel@tonic-gate (void) sm_snprintf(phmap_id, sizeof phmap_id, 46637c478bd9Sstevel@tonic-gate "sendmail-%s phmap-20010529 libphclient-%s", 46647c478bd9Sstevel@tonic-gate Version, libphclient_version); 46657c478bd9Sstevel@tonic-gate 46667c478bd9Sstevel@tonic-gate pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); 46677c478bd9Sstevel@tonic-gate 46687c478bd9Sstevel@tonic-gate /* defaults */ 46697c478bd9Sstevel@tonic-gate pmap->ph_servers = NULL; 46707c478bd9Sstevel@tonic-gate pmap->ph_field_list = NULL; 46717c478bd9Sstevel@tonic-gate pmap->ph = NULL; 46727c478bd9Sstevel@tonic-gate pmap->ph_timeout = 0; 46737c478bd9Sstevel@tonic-gate pmap->ph_fastclose = 0; 46747c478bd9Sstevel@tonic-gate 46757c478bd9Sstevel@tonic-gate map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; 46767c478bd9Sstevel@tonic-gate for (;;) 46777c478bd9Sstevel@tonic-gate { 46787c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 46797c478bd9Sstevel@tonic-gate p++; 46807c478bd9Sstevel@tonic-gate if (*p != '-') 46817c478bd9Sstevel@tonic-gate break; 46827c478bd9Sstevel@tonic-gate switch (*++p) 46837c478bd9Sstevel@tonic-gate { 46847c478bd9Sstevel@tonic-gate case 'N': 46857c478bd9Sstevel@tonic-gate map->map_mflags |= MF_INCLNULL; 46867c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY0NULL; 46877c478bd9Sstevel@tonic-gate break; 46887c478bd9Sstevel@tonic-gate 46897c478bd9Sstevel@tonic-gate case 'O': 46907c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_TRY1NULL; 46917c478bd9Sstevel@tonic-gate break; 46927c478bd9Sstevel@tonic-gate 46937c478bd9Sstevel@tonic-gate case 'o': 46947c478bd9Sstevel@tonic-gate map->map_mflags |= MF_OPTIONAL; 46957c478bd9Sstevel@tonic-gate break; 46967c478bd9Sstevel@tonic-gate 46977c478bd9Sstevel@tonic-gate case 'f': 46987c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NOFOLDCASE; 46997c478bd9Sstevel@tonic-gate break; 47007c478bd9Sstevel@tonic-gate 47017c478bd9Sstevel@tonic-gate case 'm': 47027c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 47037c478bd9Sstevel@tonic-gate break; 47047c478bd9Sstevel@tonic-gate 47057c478bd9Sstevel@tonic-gate case 'A': 47067c478bd9Sstevel@tonic-gate map->map_mflags |= MF_APPEND; 47077c478bd9Sstevel@tonic-gate break; 47087c478bd9Sstevel@tonic-gate 47097c478bd9Sstevel@tonic-gate case 'q': 47107c478bd9Sstevel@tonic-gate map->map_mflags |= MF_KEEPQUOTES; 47117c478bd9Sstevel@tonic-gate break; 47127c478bd9Sstevel@tonic-gate 47137c478bd9Sstevel@tonic-gate case 't': 47147c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 47157c478bd9Sstevel@tonic-gate break; 47167c478bd9Sstevel@tonic-gate 47177c478bd9Sstevel@tonic-gate case 'a': 47187c478bd9Sstevel@tonic-gate map->map_app = ++p; 47197c478bd9Sstevel@tonic-gate break; 47207c478bd9Sstevel@tonic-gate 47217c478bd9Sstevel@tonic-gate case 'T': 47227c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 47237c478bd9Sstevel@tonic-gate break; 47247c478bd9Sstevel@tonic-gate 47257c478bd9Sstevel@tonic-gate case 'l': 47267c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 47277c478bd9Sstevel@tonic-gate continue; 47287c478bd9Sstevel@tonic-gate pmap->ph_timeout = atoi(p); 47297c478bd9Sstevel@tonic-gate break; 47307c478bd9Sstevel@tonic-gate 47317c478bd9Sstevel@tonic-gate case 'S': 47327c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 47337c478bd9Sstevel@tonic-gate break; 47347c478bd9Sstevel@tonic-gate 47357c478bd9Sstevel@tonic-gate case 'D': 47367c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 47377c478bd9Sstevel@tonic-gate break; 47387c478bd9Sstevel@tonic-gate 47397c478bd9Sstevel@tonic-gate case 'h': /* PH server list */ 47407c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 47417c478bd9Sstevel@tonic-gate continue; 47427c478bd9Sstevel@tonic-gate pmap->ph_servers = p; 47437c478bd9Sstevel@tonic-gate break; 47447c478bd9Sstevel@tonic-gate 47457c478bd9Sstevel@tonic-gate case 'k': /* fields to search for */ 47467c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 47477c478bd9Sstevel@tonic-gate continue; 47487c478bd9Sstevel@tonic-gate pmap->ph_field_list = p; 47497c478bd9Sstevel@tonic-gate break; 47507c478bd9Sstevel@tonic-gate 47517c478bd9Sstevel@tonic-gate default: 47527c478bd9Sstevel@tonic-gate syserr("ph_map_parseargs: unknown option -%c", *p); 47537c478bd9Sstevel@tonic-gate } 47547c478bd9Sstevel@tonic-gate 47557c478bd9Sstevel@tonic-gate /* try to account for quoted strings */ 47567c478bd9Sstevel@tonic-gate done = isascii(*p) && isspace(*p); 47577c478bd9Sstevel@tonic-gate while (*p != '\0' && !done) 47587c478bd9Sstevel@tonic-gate { 47597c478bd9Sstevel@tonic-gate if (*p == '"') 47607c478bd9Sstevel@tonic-gate { 47617c478bd9Sstevel@tonic-gate while (*++p != '"' && *p != '\0') 47627c478bd9Sstevel@tonic-gate continue; 47637c478bd9Sstevel@tonic-gate if (*p != '\0') 47647c478bd9Sstevel@tonic-gate p++; 47657c478bd9Sstevel@tonic-gate } 47667c478bd9Sstevel@tonic-gate else 47677c478bd9Sstevel@tonic-gate p++; 47687c478bd9Sstevel@tonic-gate done = isascii(*p) && isspace(*p); 47697c478bd9Sstevel@tonic-gate } 47707c478bd9Sstevel@tonic-gate 47717c478bd9Sstevel@tonic-gate if (*p != '\0') 47727c478bd9Sstevel@tonic-gate *p++ = '\0'; 47737c478bd9Sstevel@tonic-gate } 47747c478bd9Sstevel@tonic-gate 47757c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 47767c478bd9Sstevel@tonic-gate map->map_app = newstr(ph_map_dequote(map->map_app)); 47777c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 47787c478bd9Sstevel@tonic-gate map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); 47797c478bd9Sstevel@tonic-gate 47807c478bd9Sstevel@tonic-gate if (pmap->ph_field_list != NULL) 47817c478bd9Sstevel@tonic-gate pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); 47827c478bd9Sstevel@tonic-gate 47837c478bd9Sstevel@tonic-gate if (pmap->ph_servers != NULL) 47847c478bd9Sstevel@tonic-gate pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); 47857c478bd9Sstevel@tonic-gate else 47867c478bd9Sstevel@tonic-gate { 47877c478bd9Sstevel@tonic-gate syserr("ph_map_parseargs: -h flag is required"); 47887c478bd9Sstevel@tonic-gate return false; 47897c478bd9Sstevel@tonic-gate } 47907c478bd9Sstevel@tonic-gate 47917c478bd9Sstevel@tonic-gate map->map_db1 = (ARBPTR_T) pmap; 47927c478bd9Sstevel@tonic-gate return true; 47937c478bd9Sstevel@tonic-gate } 47947c478bd9Sstevel@tonic-gate 47957c478bd9Sstevel@tonic-gate /* 47967c478bd9Sstevel@tonic-gate ** PH_MAP_CLOSE -- close the connection to the ph server 47977c478bd9Sstevel@tonic-gate */ 47987c478bd9Sstevel@tonic-gate 47997c478bd9Sstevel@tonic-gate void 48007c478bd9Sstevel@tonic-gate ph_map_close(map) 48017c478bd9Sstevel@tonic-gate MAP *map; 48027c478bd9Sstevel@tonic-gate { 48037c478bd9Sstevel@tonic-gate PH_MAP_STRUCT *pmap; 48047c478bd9Sstevel@tonic-gate 48057c478bd9Sstevel@tonic-gate pmap = (PH_MAP_STRUCT *)map->map_db1; 48067c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 48077c478bd9Sstevel@tonic-gate sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n", 48087c478bd9Sstevel@tonic-gate map->map_mname, pmap->ph_fastclose); 48097c478bd9Sstevel@tonic-gate 48107c478bd9Sstevel@tonic-gate 48117c478bd9Sstevel@tonic-gate if (pmap->ph != NULL) 48127c478bd9Sstevel@tonic-gate { 48137c478bd9Sstevel@tonic-gate ph_set_sendhook(pmap->ph, NULL); 48147c478bd9Sstevel@tonic-gate ph_set_recvhook(pmap->ph, NULL); 48157c478bd9Sstevel@tonic-gate ph_close(pmap->ph, pmap->ph_fastclose); 48167c478bd9Sstevel@tonic-gate } 48177c478bd9Sstevel@tonic-gate 48187c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 48197c478bd9Sstevel@tonic-gate } 48207c478bd9Sstevel@tonic-gate 48217c478bd9Sstevel@tonic-gate static jmp_buf PHTimeout; 48227c478bd9Sstevel@tonic-gate 48237c478bd9Sstevel@tonic-gate /* ARGSUSED */ 48247c478bd9Sstevel@tonic-gate static void 48257c478bd9Sstevel@tonic-gate ph_timeout(unused) 48267c478bd9Sstevel@tonic-gate int unused; 48277c478bd9Sstevel@tonic-gate { 48287c478bd9Sstevel@tonic-gate /* 48297c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 48307c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 48317c478bd9Sstevel@tonic-gate ** DOING. 48327c478bd9Sstevel@tonic-gate */ 48337c478bd9Sstevel@tonic-gate 48347c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 48357c478bd9Sstevel@tonic-gate longjmp(PHTimeout, 1); 48367c478bd9Sstevel@tonic-gate } 48377c478bd9Sstevel@tonic-gate 48387c478bd9Sstevel@tonic-gate static void 48397c478bd9Sstevel@tonic-gate #if NPH_VERSION >= 10200 48407c478bd9Sstevel@tonic-gate ph_map_send_debug(appdata, text) 48417c478bd9Sstevel@tonic-gate void *appdata; 48427c478bd9Sstevel@tonic-gate #else 48437c478bd9Sstevel@tonic-gate ph_map_send_debug(text) 48447c478bd9Sstevel@tonic-gate #endif 48457c478bd9Sstevel@tonic-gate char *text; 48467c478bd9Sstevel@tonic-gate { 48477c478bd9Sstevel@tonic-gate if (LogLevel > 9) 48487c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 48497c478bd9Sstevel@tonic-gate "ph_map_send_debug: ==> %s", text); 48507c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 48517c478bd9Sstevel@tonic-gate sm_dprintf("ph_map_send_debug: ==> %s\n", text); 48527c478bd9Sstevel@tonic-gate } 48537c478bd9Sstevel@tonic-gate 48547c478bd9Sstevel@tonic-gate static void 48557c478bd9Sstevel@tonic-gate #if NPH_VERSION >= 10200 48567c478bd9Sstevel@tonic-gate ph_map_recv_debug(appdata, text) 48577c478bd9Sstevel@tonic-gate void *appdata; 48587c478bd9Sstevel@tonic-gate #else 48597c478bd9Sstevel@tonic-gate ph_map_recv_debug(text) 48607c478bd9Sstevel@tonic-gate #endif 48617c478bd9Sstevel@tonic-gate char *text; 48627c478bd9Sstevel@tonic-gate { 48637c478bd9Sstevel@tonic-gate if (LogLevel > 10) 48647c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 48657c478bd9Sstevel@tonic-gate "ph_map_recv_debug: <== %s", text); 48667c478bd9Sstevel@tonic-gate if (tTd(38, 21)) 48677c478bd9Sstevel@tonic-gate sm_dprintf("ph_map_recv_debug: <== %s\n", text); 48687c478bd9Sstevel@tonic-gate } 48697c478bd9Sstevel@tonic-gate 48707c478bd9Sstevel@tonic-gate /* 48717c478bd9Sstevel@tonic-gate ** PH_MAP_OPEN -- sub for opening PH map 48727c478bd9Sstevel@tonic-gate */ 48737c478bd9Sstevel@tonic-gate bool 48747c478bd9Sstevel@tonic-gate ph_map_open(map, mode) 48757c478bd9Sstevel@tonic-gate MAP *map; 48767c478bd9Sstevel@tonic-gate int mode; 48777c478bd9Sstevel@tonic-gate { 48787c478bd9Sstevel@tonic-gate PH_MAP_STRUCT *pmap; 48797c478bd9Sstevel@tonic-gate register SM_EVENT *ev = NULL; 48807c478bd9Sstevel@tonic-gate int save_errno = 0; 48817c478bd9Sstevel@tonic-gate char *hostlist, *host; 48827c478bd9Sstevel@tonic-gate 48837c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 48847c478bd9Sstevel@tonic-gate sm_dprintf("ph_map_open(%s)\n", map->map_mname); 48857c478bd9Sstevel@tonic-gate 48867c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 48877c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 48887c478bd9Sstevel@tonic-gate { 48897c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 48907c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 48917c478bd9Sstevel@tonic-gate return false; 48927c478bd9Sstevel@tonic-gate } 48937c478bd9Sstevel@tonic-gate 48947c478bd9Sstevel@tonic-gate if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER && 48957c478bd9Sstevel@tonic-gate bitset(MF_DEFER, map->map_mflags)) 48967c478bd9Sstevel@tonic-gate { 48977c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 48987c478bd9Sstevel@tonic-gate sm_dprintf("ph_map_open(%s) => DEFERRED\n", 48997c478bd9Sstevel@tonic-gate map->map_mname); 49007c478bd9Sstevel@tonic-gate 49017c478bd9Sstevel@tonic-gate /* 49027c478bd9Sstevel@tonic-gate ** Unset MF_DEFER here so that map_lookup() returns 49037c478bd9Sstevel@tonic-gate ** a temporary failure using the bogus map and 49047c478bd9Sstevel@tonic-gate ** map->map_tapp instead of the default permanent error. 49057c478bd9Sstevel@tonic-gate */ 49067c478bd9Sstevel@tonic-gate 49077c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_DEFER; 49087c478bd9Sstevel@tonic-gate return false; 49097c478bd9Sstevel@tonic-gate } 49107c478bd9Sstevel@tonic-gate 49117c478bd9Sstevel@tonic-gate pmap = (PH_MAP_STRUCT *)map->map_db1; 49127c478bd9Sstevel@tonic-gate pmap->ph_fastclose = 0; /* refresh field for reopen */ 49137c478bd9Sstevel@tonic-gate 49147c478bd9Sstevel@tonic-gate /* try each host in the list */ 49157c478bd9Sstevel@tonic-gate hostlist = newstr(pmap->ph_servers); 49167c478bd9Sstevel@tonic-gate for (host = strtok(hostlist, " "); 49177c478bd9Sstevel@tonic-gate host != NULL; 49187c478bd9Sstevel@tonic-gate host = strtok(NULL, " ")) 49197c478bd9Sstevel@tonic-gate { 49207c478bd9Sstevel@tonic-gate /* set timeout */ 49217c478bd9Sstevel@tonic-gate if (pmap->ph_timeout != 0) 49227c478bd9Sstevel@tonic-gate { 49237c478bd9Sstevel@tonic-gate if (setjmp(PHTimeout) != 0) 49247c478bd9Sstevel@tonic-gate { 49257c478bd9Sstevel@tonic-gate ev = NULL; 49267c478bd9Sstevel@tonic-gate if (LogLevel > 1) 49277c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 49287c478bd9Sstevel@tonic-gate "timeout connecting to PH server %.100s", 49297c478bd9Sstevel@tonic-gate host); 49307c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 49317c478bd9Sstevel@tonic-gate goto ph_map_open_abort; 49327c478bd9Sstevel@tonic-gate } 49337c478bd9Sstevel@tonic-gate ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 49347c478bd9Sstevel@tonic-gate } 49357c478bd9Sstevel@tonic-gate 49367c478bd9Sstevel@tonic-gate /* open connection to server */ 49377c478bd9Sstevel@tonic-gate if (ph_open(&(pmap->ph), host, 49387c478bd9Sstevel@tonic-gate PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID, 49397c478bd9Sstevel@tonic-gate ph_map_send_debug, ph_map_recv_debug 49407c478bd9Sstevel@tonic-gate #if NPH_VERSION >= 10200 49417c478bd9Sstevel@tonic-gate , NULL 49427c478bd9Sstevel@tonic-gate #endif 49437c478bd9Sstevel@tonic-gate ) == 0 49447c478bd9Sstevel@tonic-gate && ph_id(pmap->ph, phmap_id) == 0) 49457c478bd9Sstevel@tonic-gate { 49467c478bd9Sstevel@tonic-gate if (ev != NULL) 49477c478bd9Sstevel@tonic-gate sm_clrevent(ev); 49487c478bd9Sstevel@tonic-gate sm_free(hostlist); /* XXX */ 49497c478bd9Sstevel@tonic-gate return true; 49507c478bd9Sstevel@tonic-gate } 49517c478bd9Sstevel@tonic-gate 49527c478bd9Sstevel@tonic-gate ph_map_open_abort: 49537c478bd9Sstevel@tonic-gate save_errno = errno; 49547c478bd9Sstevel@tonic-gate if (ev != NULL) 49557c478bd9Sstevel@tonic-gate sm_clrevent(ev); 49567c478bd9Sstevel@tonic-gate pmap->ph_fastclose = PH_CLOSE_FAST; 49577c478bd9Sstevel@tonic-gate ph_map_close(map); 49587c478bd9Sstevel@tonic-gate errno = save_errno; 49597c478bd9Sstevel@tonic-gate } 49607c478bd9Sstevel@tonic-gate 49617c478bd9Sstevel@tonic-gate if (bitset(MF_NODEFER, map->map_mflags)) 49627c478bd9Sstevel@tonic-gate { 49637c478bd9Sstevel@tonic-gate if (errno == 0) 49647c478bd9Sstevel@tonic-gate errno = EAGAIN; 49657c478bd9Sstevel@tonic-gate syserr("ph_map_open: %s: cannot connect to PH server", 49667c478bd9Sstevel@tonic-gate map->map_mname); 49677c478bd9Sstevel@tonic-gate } 49687c478bd9Sstevel@tonic-gate else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1) 49697c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 49707c478bd9Sstevel@tonic-gate "ph_map_open: %s: cannot connect to PH server", 49717c478bd9Sstevel@tonic-gate map->map_mname); 49727c478bd9Sstevel@tonic-gate sm_free(hostlist); /* XXX */ 49737c478bd9Sstevel@tonic-gate return false; 49747c478bd9Sstevel@tonic-gate } 49757c478bd9Sstevel@tonic-gate 49767c478bd9Sstevel@tonic-gate /* 49777c478bd9Sstevel@tonic-gate ** PH_MAP_LOOKUP -- look up key from ph server 49787c478bd9Sstevel@tonic-gate */ 49797c478bd9Sstevel@tonic-gate 49807c478bd9Sstevel@tonic-gate char * 49817c478bd9Sstevel@tonic-gate ph_map_lookup(map, key, args, pstat) 49827c478bd9Sstevel@tonic-gate MAP *map; 49837c478bd9Sstevel@tonic-gate char *key; 49847c478bd9Sstevel@tonic-gate char **args; 49857c478bd9Sstevel@tonic-gate int *pstat; 49867c478bd9Sstevel@tonic-gate { 49877c478bd9Sstevel@tonic-gate int i, save_errno = 0; 49887c478bd9Sstevel@tonic-gate register SM_EVENT *ev = NULL; 49897c478bd9Sstevel@tonic-gate PH_MAP_STRUCT *pmap; 49907c478bd9Sstevel@tonic-gate char *value = NULL; 49917c478bd9Sstevel@tonic-gate 49927c478bd9Sstevel@tonic-gate pmap = (PH_MAP_STRUCT *)map->map_db1; 49937c478bd9Sstevel@tonic-gate 49947c478bd9Sstevel@tonic-gate *pstat = EX_OK; 49957c478bd9Sstevel@tonic-gate 49967c478bd9Sstevel@tonic-gate /* set timeout */ 49977c478bd9Sstevel@tonic-gate if (pmap->ph_timeout != 0) 49987c478bd9Sstevel@tonic-gate { 49997c478bd9Sstevel@tonic-gate if (setjmp(PHTimeout) != 0) 50007c478bd9Sstevel@tonic-gate { 50017c478bd9Sstevel@tonic-gate ev = NULL; 50027c478bd9Sstevel@tonic-gate if (LogLevel > 1) 50037c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 50047c478bd9Sstevel@tonic-gate "timeout during PH lookup of %.100s", 50057c478bd9Sstevel@tonic-gate key); 50067c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 50077c478bd9Sstevel@tonic-gate *pstat = EX_TEMPFAIL; 50087c478bd9Sstevel@tonic-gate goto ph_map_lookup_abort; 50097c478bd9Sstevel@tonic-gate } 50107c478bd9Sstevel@tonic-gate ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0); 50117c478bd9Sstevel@tonic-gate } 50127c478bd9Sstevel@tonic-gate 50137c478bd9Sstevel@tonic-gate /* perform lookup */ 50147c478bd9Sstevel@tonic-gate i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); 50157c478bd9Sstevel@tonic-gate if (i == -1) 50167c478bd9Sstevel@tonic-gate *pstat = EX_TEMPFAIL; 50177c478bd9Sstevel@tonic-gate else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR) 50187c478bd9Sstevel@tonic-gate *pstat = EX_UNAVAILABLE; 50197c478bd9Sstevel@tonic-gate 50207c478bd9Sstevel@tonic-gate ph_map_lookup_abort: 50217c478bd9Sstevel@tonic-gate if (ev != NULL) 50227c478bd9Sstevel@tonic-gate sm_clrevent(ev); 50237c478bd9Sstevel@tonic-gate 50247c478bd9Sstevel@tonic-gate /* 50257c478bd9Sstevel@tonic-gate ** Close the connection if the timer popped 50267c478bd9Sstevel@tonic-gate ** or we got a temporary PH error 50277c478bd9Sstevel@tonic-gate */ 50287c478bd9Sstevel@tonic-gate 50297c478bd9Sstevel@tonic-gate if (*pstat == EX_TEMPFAIL) 50307c478bd9Sstevel@tonic-gate { 50317c478bd9Sstevel@tonic-gate save_errno = errno; 50327c478bd9Sstevel@tonic-gate pmap->ph_fastclose = PH_CLOSE_FAST; 50337c478bd9Sstevel@tonic-gate ph_map_close(map); 50347c478bd9Sstevel@tonic-gate errno = save_errno; 50357c478bd9Sstevel@tonic-gate } 50367c478bd9Sstevel@tonic-gate 50377c478bd9Sstevel@tonic-gate if (*pstat == EX_OK) 50387c478bd9Sstevel@tonic-gate { 50397c478bd9Sstevel@tonic-gate if (tTd(38,20)) 50407c478bd9Sstevel@tonic-gate sm_dprintf("ph_map_lookup: %s => %s\n", key, value); 50417c478bd9Sstevel@tonic-gate 50427c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 50437c478bd9Sstevel@tonic-gate return map_rewrite(map, key, strlen(key), NULL); 50447c478bd9Sstevel@tonic-gate else 50457c478bd9Sstevel@tonic-gate return map_rewrite(map, value, strlen(value), args); 50467c478bd9Sstevel@tonic-gate } 50477c478bd9Sstevel@tonic-gate 50487c478bd9Sstevel@tonic-gate return NULL; 50497c478bd9Sstevel@tonic-gate } 50507c478bd9Sstevel@tonic-gate #endif /* PH_MAP */ 50517c478bd9Sstevel@tonic-gate /* 50527c478bd9Sstevel@tonic-gate ** syslog map 50537c478bd9Sstevel@tonic-gate */ 50547c478bd9Sstevel@tonic-gate 50557c478bd9Sstevel@tonic-gate #define map_prio map_lockfd /* overload field */ 50567c478bd9Sstevel@tonic-gate 50577c478bd9Sstevel@tonic-gate /* 50587c478bd9Sstevel@tonic-gate ** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. 50597c478bd9Sstevel@tonic-gate */ 50607c478bd9Sstevel@tonic-gate 50617c478bd9Sstevel@tonic-gate bool 50627c478bd9Sstevel@tonic-gate syslog_map_parseargs(map, args) 50637c478bd9Sstevel@tonic-gate MAP *map; 50647c478bd9Sstevel@tonic-gate char *args; 50657c478bd9Sstevel@tonic-gate { 50667c478bd9Sstevel@tonic-gate char *p = args; 50677c478bd9Sstevel@tonic-gate char *priority = NULL; 50687c478bd9Sstevel@tonic-gate 50697c478bd9Sstevel@tonic-gate /* there is no check whether there is really an argument */ 50707c478bd9Sstevel@tonic-gate while (*p != '\0') 50717c478bd9Sstevel@tonic-gate { 50727c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 50737c478bd9Sstevel@tonic-gate p++; 50747c478bd9Sstevel@tonic-gate if (*p != '-') 50757c478bd9Sstevel@tonic-gate break; 50767c478bd9Sstevel@tonic-gate ++p; 50777c478bd9Sstevel@tonic-gate if (*p == 'D') 50787c478bd9Sstevel@tonic-gate { 50797c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 50807c478bd9Sstevel@tonic-gate ++p; 50817c478bd9Sstevel@tonic-gate } 50827c478bd9Sstevel@tonic-gate else if (*p == 'S') 50837c478bd9Sstevel@tonic-gate { 50847c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 50857c478bd9Sstevel@tonic-gate if (*p != '\0') 50867c478bd9Sstevel@tonic-gate p++; 50877c478bd9Sstevel@tonic-gate } 50887c478bd9Sstevel@tonic-gate else if (*p == 'L') 50897c478bd9Sstevel@tonic-gate { 50907c478bd9Sstevel@tonic-gate while (*++p != '\0' && isascii(*p) && isspace(*p)) 50917c478bd9Sstevel@tonic-gate continue; 50927c478bd9Sstevel@tonic-gate if (*p == '\0') 50937c478bd9Sstevel@tonic-gate break; 50947c478bd9Sstevel@tonic-gate priority = p; 50957c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 50967c478bd9Sstevel@tonic-gate p++; 50977c478bd9Sstevel@tonic-gate if (*p != '\0') 50987c478bd9Sstevel@tonic-gate *p++ = '\0'; 50997c478bd9Sstevel@tonic-gate } 51007c478bd9Sstevel@tonic-gate else 51017c478bd9Sstevel@tonic-gate { 51027c478bd9Sstevel@tonic-gate syserr("Illegal option %c map syslog", *p); 51037c478bd9Sstevel@tonic-gate ++p; 51047c478bd9Sstevel@tonic-gate } 51057c478bd9Sstevel@tonic-gate } 51067c478bd9Sstevel@tonic-gate 51077c478bd9Sstevel@tonic-gate if (priority == NULL) 51087c478bd9Sstevel@tonic-gate map->map_prio = LOG_INFO; 51097c478bd9Sstevel@tonic-gate else 51107c478bd9Sstevel@tonic-gate { 51117c478bd9Sstevel@tonic-gate if (sm_strncasecmp("LOG_", priority, 4) == 0) 51127c478bd9Sstevel@tonic-gate priority += 4; 51137c478bd9Sstevel@tonic-gate 51147c478bd9Sstevel@tonic-gate #ifdef LOG_EMERG 51157c478bd9Sstevel@tonic-gate if (sm_strcasecmp("EMERG", priority) == 0) 51167c478bd9Sstevel@tonic-gate map->map_prio = LOG_EMERG; 51177c478bd9Sstevel@tonic-gate else 51187c478bd9Sstevel@tonic-gate #endif /* LOG_EMERG */ 51197c478bd9Sstevel@tonic-gate #ifdef LOG_ALERT 51207c478bd9Sstevel@tonic-gate if (sm_strcasecmp("ALERT", priority) == 0) 51217c478bd9Sstevel@tonic-gate map->map_prio = LOG_ALERT; 51227c478bd9Sstevel@tonic-gate else 51237c478bd9Sstevel@tonic-gate #endif /* LOG_ALERT */ 51247c478bd9Sstevel@tonic-gate #ifdef LOG_CRIT 51257c478bd9Sstevel@tonic-gate if (sm_strcasecmp("CRIT", priority) == 0) 51267c478bd9Sstevel@tonic-gate map->map_prio = LOG_CRIT; 51277c478bd9Sstevel@tonic-gate else 51287c478bd9Sstevel@tonic-gate #endif /* LOG_CRIT */ 51297c478bd9Sstevel@tonic-gate #ifdef LOG_ERR 51307c478bd9Sstevel@tonic-gate if (sm_strcasecmp("ERR", priority) == 0) 51317c478bd9Sstevel@tonic-gate map->map_prio = LOG_ERR; 51327c478bd9Sstevel@tonic-gate else 51337c478bd9Sstevel@tonic-gate #endif /* LOG_ERR */ 51347c478bd9Sstevel@tonic-gate #ifdef LOG_WARNING 51357c478bd9Sstevel@tonic-gate if (sm_strcasecmp("WARNING", priority) == 0) 51367c478bd9Sstevel@tonic-gate map->map_prio = LOG_WARNING; 51377c478bd9Sstevel@tonic-gate else 51387c478bd9Sstevel@tonic-gate #endif /* LOG_WARNING */ 51397c478bd9Sstevel@tonic-gate #ifdef LOG_NOTICE 51407c478bd9Sstevel@tonic-gate if (sm_strcasecmp("NOTICE", priority) == 0) 51417c478bd9Sstevel@tonic-gate map->map_prio = LOG_NOTICE; 51427c478bd9Sstevel@tonic-gate else 51437c478bd9Sstevel@tonic-gate #endif /* LOG_NOTICE */ 51447c478bd9Sstevel@tonic-gate #ifdef LOG_INFO 51457c478bd9Sstevel@tonic-gate if (sm_strcasecmp("INFO", priority) == 0) 51467c478bd9Sstevel@tonic-gate map->map_prio = LOG_INFO; 51477c478bd9Sstevel@tonic-gate else 51487c478bd9Sstevel@tonic-gate #endif /* LOG_INFO */ 51497c478bd9Sstevel@tonic-gate #ifdef LOG_DEBUG 51507c478bd9Sstevel@tonic-gate if (sm_strcasecmp("DEBUG", priority) == 0) 51517c478bd9Sstevel@tonic-gate map->map_prio = LOG_DEBUG; 51527c478bd9Sstevel@tonic-gate else 51537c478bd9Sstevel@tonic-gate #endif /* LOG_DEBUG */ 51547c478bd9Sstevel@tonic-gate { 51557c478bd9Sstevel@tonic-gate syserr("syslog_map_parseargs: Unknown priority %s", 51567c478bd9Sstevel@tonic-gate priority); 51577c478bd9Sstevel@tonic-gate return false; 51587c478bd9Sstevel@tonic-gate } 51597c478bd9Sstevel@tonic-gate } 51607c478bd9Sstevel@tonic-gate return true; 51617c478bd9Sstevel@tonic-gate } 51627c478bd9Sstevel@tonic-gate 51637c478bd9Sstevel@tonic-gate /* 51647c478bd9Sstevel@tonic-gate ** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string 51657c478bd9Sstevel@tonic-gate */ 51667c478bd9Sstevel@tonic-gate 51677c478bd9Sstevel@tonic-gate char * 51687c478bd9Sstevel@tonic-gate syslog_map_lookup(map, string, args, statp) 51697c478bd9Sstevel@tonic-gate MAP *map; 51707c478bd9Sstevel@tonic-gate char *string; 51717c478bd9Sstevel@tonic-gate char **args; 51727c478bd9Sstevel@tonic-gate int *statp; 51737c478bd9Sstevel@tonic-gate { 51747c478bd9Sstevel@tonic-gate char *ptr = map_rewrite(map, string, strlen(string), args); 51757c478bd9Sstevel@tonic-gate 51767c478bd9Sstevel@tonic-gate if (ptr != NULL) 51777c478bd9Sstevel@tonic-gate { 51787c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 51797c478bd9Sstevel@tonic-gate sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n", 51807c478bd9Sstevel@tonic-gate map->map_mname, map->map_prio, ptr); 51817c478bd9Sstevel@tonic-gate 51827c478bd9Sstevel@tonic-gate sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); 51837c478bd9Sstevel@tonic-gate } 51847c478bd9Sstevel@tonic-gate 51857c478bd9Sstevel@tonic-gate *statp = EX_OK; 51867c478bd9Sstevel@tonic-gate return ""; 51877c478bd9Sstevel@tonic-gate } 51887c478bd9Sstevel@tonic-gate 51897c478bd9Sstevel@tonic-gate /* 51907c478bd9Sstevel@tonic-gate ** HESIOD Modules 51917c478bd9Sstevel@tonic-gate */ 51927c478bd9Sstevel@tonic-gate 51937c478bd9Sstevel@tonic-gate #if HESIOD 51947c478bd9Sstevel@tonic-gate 51957c478bd9Sstevel@tonic-gate bool 51967c478bd9Sstevel@tonic-gate hes_map_open(map, mode) 51977c478bd9Sstevel@tonic-gate MAP *map; 51987c478bd9Sstevel@tonic-gate int mode; 51997c478bd9Sstevel@tonic-gate { 52007c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 52017c478bd9Sstevel@tonic-gate sm_dprintf("hes_map_open(%s, %s, %d)\n", 52027c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 52037c478bd9Sstevel@tonic-gate 52047c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 52057c478bd9Sstevel@tonic-gate { 52067c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 52077c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 52087c478bd9Sstevel@tonic-gate return false; 52097c478bd9Sstevel@tonic-gate } 52107c478bd9Sstevel@tonic-gate 52117c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT 52127c478bd9Sstevel@tonic-gate if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) 52137c478bd9Sstevel@tonic-gate return true; 52147c478bd9Sstevel@tonic-gate 52157c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 52167c478bd9Sstevel@tonic-gate syserr("451 4.3.5 cannot initialize Hesiod map (%s)", 52177c478bd9Sstevel@tonic-gate sm_errstring(errno)); 52187c478bd9Sstevel@tonic-gate return false; 52197c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */ 52207c478bd9Sstevel@tonic-gate if (hes_error() == HES_ER_UNINIT) 52217c478bd9Sstevel@tonic-gate hes_init(); 52227c478bd9Sstevel@tonic-gate switch (hes_error()) 52237c478bd9Sstevel@tonic-gate { 52247c478bd9Sstevel@tonic-gate case HES_ER_OK: 52257c478bd9Sstevel@tonic-gate case HES_ER_NOTFOUND: 52267c478bd9Sstevel@tonic-gate return true; 52277c478bd9Sstevel@tonic-gate } 52287c478bd9Sstevel@tonic-gate 52297c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 52307c478bd9Sstevel@tonic-gate syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error()); 52317c478bd9Sstevel@tonic-gate 52327c478bd9Sstevel@tonic-gate return false; 52337c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */ 52347c478bd9Sstevel@tonic-gate } 52357c478bd9Sstevel@tonic-gate 52367c478bd9Sstevel@tonic-gate char * 52377c478bd9Sstevel@tonic-gate hes_map_lookup(map, name, av, statp) 52387c478bd9Sstevel@tonic-gate MAP *map; 52397c478bd9Sstevel@tonic-gate char *name; 52407c478bd9Sstevel@tonic-gate char **av; 52417c478bd9Sstevel@tonic-gate int *statp; 52427c478bd9Sstevel@tonic-gate { 52437c478bd9Sstevel@tonic-gate char **hp; 52447c478bd9Sstevel@tonic-gate 52457c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 52467c478bd9Sstevel@tonic-gate sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name); 52477c478bd9Sstevel@tonic-gate 52487c478bd9Sstevel@tonic-gate if (name[0] == '\\') 52497c478bd9Sstevel@tonic-gate { 52507c478bd9Sstevel@tonic-gate char *np; 52517c478bd9Sstevel@tonic-gate int nl; 52527c478bd9Sstevel@tonic-gate int save_errno; 52537c478bd9Sstevel@tonic-gate char nbuf[MAXNAME]; 52547c478bd9Sstevel@tonic-gate 52557c478bd9Sstevel@tonic-gate nl = strlen(name); 52567c478bd9Sstevel@tonic-gate if (nl < sizeof nbuf - 1) 52577c478bd9Sstevel@tonic-gate np = nbuf; 52587c478bd9Sstevel@tonic-gate else 52597c478bd9Sstevel@tonic-gate np = xalloc(strlen(name) + 2); 52607c478bd9Sstevel@tonic-gate np[0] = '\\'; 52617c478bd9Sstevel@tonic-gate (void) sm_strlcpy(&np[1], name, (sizeof nbuf) - 1); 52627c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT 52637c478bd9Sstevel@tonic-gate hp = hesiod_resolve(HesiodContext, np, map->map_file); 52647c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */ 52657c478bd9Sstevel@tonic-gate hp = hes_resolve(np, map->map_file); 52667c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */ 52677c478bd9Sstevel@tonic-gate save_errno = errno; 52687c478bd9Sstevel@tonic-gate if (np != nbuf) 52697c478bd9Sstevel@tonic-gate sm_free(np); /* XXX */ 52707c478bd9Sstevel@tonic-gate errno = save_errno; 52717c478bd9Sstevel@tonic-gate } 52727c478bd9Sstevel@tonic-gate else 52737c478bd9Sstevel@tonic-gate { 52747c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT 52757c478bd9Sstevel@tonic-gate hp = hesiod_resolve(HesiodContext, name, map->map_file); 52767c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */ 52777c478bd9Sstevel@tonic-gate hp = hes_resolve(name, map->map_file); 52787c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */ 52797c478bd9Sstevel@tonic-gate } 52807c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT 52817c478bd9Sstevel@tonic-gate if (hp == NULL || *hp == NULL) 52827c478bd9Sstevel@tonic-gate { 52837c478bd9Sstevel@tonic-gate switch (errno) 52847c478bd9Sstevel@tonic-gate { 52857c478bd9Sstevel@tonic-gate case ENOENT: 52867c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 52877c478bd9Sstevel@tonic-gate break; 52887c478bd9Sstevel@tonic-gate case ECONNREFUSED: 52897c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 52907c478bd9Sstevel@tonic-gate break; 52917c478bd9Sstevel@tonic-gate case EMSGSIZE: 52927c478bd9Sstevel@tonic-gate case ENOMEM: 52937c478bd9Sstevel@tonic-gate default: 52947c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 52957c478bd9Sstevel@tonic-gate break; 52967c478bd9Sstevel@tonic-gate } 52977c478bd9Sstevel@tonic-gate if (hp != NULL) 52987c478bd9Sstevel@tonic-gate hesiod_free_list(HesiodContext, hp); 52997c478bd9Sstevel@tonic-gate return NULL; 53007c478bd9Sstevel@tonic-gate } 53017c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */ 53027c478bd9Sstevel@tonic-gate if (hp == NULL || hp[0] == NULL) 53037c478bd9Sstevel@tonic-gate { 53047c478bd9Sstevel@tonic-gate switch (hes_error()) 53057c478bd9Sstevel@tonic-gate { 53067c478bd9Sstevel@tonic-gate case HES_ER_OK: 53077c478bd9Sstevel@tonic-gate *statp = EX_OK; 53087c478bd9Sstevel@tonic-gate break; 53097c478bd9Sstevel@tonic-gate 53107c478bd9Sstevel@tonic-gate case HES_ER_NOTFOUND: 53117c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 53127c478bd9Sstevel@tonic-gate break; 53137c478bd9Sstevel@tonic-gate 53147c478bd9Sstevel@tonic-gate case HES_ER_CONFIG: 53157c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 53167c478bd9Sstevel@tonic-gate break; 53177c478bd9Sstevel@tonic-gate 53187c478bd9Sstevel@tonic-gate case HES_ER_NET: 53197c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 53207c478bd9Sstevel@tonic-gate break; 53217c478bd9Sstevel@tonic-gate } 53227c478bd9Sstevel@tonic-gate return NULL; 53237c478bd9Sstevel@tonic-gate } 53247c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */ 53257c478bd9Sstevel@tonic-gate 53267c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 53277c478bd9Sstevel@tonic-gate return map_rewrite(map, name, strlen(name), NULL); 53287c478bd9Sstevel@tonic-gate else 53297c478bd9Sstevel@tonic-gate return map_rewrite(map, hp[0], strlen(hp[0]), av); 53307c478bd9Sstevel@tonic-gate } 53317c478bd9Sstevel@tonic-gate 53327c478bd9Sstevel@tonic-gate /* 53337c478bd9Sstevel@tonic-gate ** HES_MAP_CLOSE -- free the Hesiod context 53347c478bd9Sstevel@tonic-gate */ 53357c478bd9Sstevel@tonic-gate 53367c478bd9Sstevel@tonic-gate void 53377c478bd9Sstevel@tonic-gate hes_map_close(map) 53387c478bd9Sstevel@tonic-gate MAP *map; 53397c478bd9Sstevel@tonic-gate { 53407c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 53417c478bd9Sstevel@tonic-gate sm_dprintf("hes_map_close(%s)\n", map->map_file); 53427c478bd9Sstevel@tonic-gate 53437c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT 53447c478bd9Sstevel@tonic-gate /* Free the hesiod context */ 53457c478bd9Sstevel@tonic-gate if (HesiodContext != NULL) 53467c478bd9Sstevel@tonic-gate { 53477c478bd9Sstevel@tonic-gate hesiod_end(HesiodContext); 53487c478bd9Sstevel@tonic-gate HesiodContext = NULL; 53497c478bd9Sstevel@tonic-gate } 53507c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */ 53517c478bd9Sstevel@tonic-gate } 53527c478bd9Sstevel@tonic-gate 53537c478bd9Sstevel@tonic-gate #endif /* HESIOD */ 53547c478bd9Sstevel@tonic-gate /* 53557c478bd9Sstevel@tonic-gate ** NeXT NETINFO Modules 53567c478bd9Sstevel@tonic-gate */ 53577c478bd9Sstevel@tonic-gate 53587c478bd9Sstevel@tonic-gate #if NETINFO 53597c478bd9Sstevel@tonic-gate 53607c478bd9Sstevel@tonic-gate # define NETINFO_DEFAULT_DIR "/aliases" 53617c478bd9Sstevel@tonic-gate # define NETINFO_DEFAULT_PROPERTY "members" 53627c478bd9Sstevel@tonic-gate 53637c478bd9Sstevel@tonic-gate /* 53647c478bd9Sstevel@tonic-gate ** NI_MAP_OPEN -- open NetInfo Aliases 53657c478bd9Sstevel@tonic-gate */ 53667c478bd9Sstevel@tonic-gate 53677c478bd9Sstevel@tonic-gate bool 53687c478bd9Sstevel@tonic-gate ni_map_open(map, mode) 53697c478bd9Sstevel@tonic-gate MAP *map; 53707c478bd9Sstevel@tonic-gate int mode; 53717c478bd9Sstevel@tonic-gate { 53727c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 53737c478bd9Sstevel@tonic-gate sm_dprintf("ni_map_open(%s, %s, %d)\n", 53747c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 53757c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 53767c478bd9Sstevel@tonic-gate 53777c478bd9Sstevel@tonic-gate if (*map->map_file == '\0') 53787c478bd9Sstevel@tonic-gate map->map_file = NETINFO_DEFAULT_DIR; 53797c478bd9Sstevel@tonic-gate 53807c478bd9Sstevel@tonic-gate if (map->map_valcolnm == NULL) 53817c478bd9Sstevel@tonic-gate map->map_valcolnm = NETINFO_DEFAULT_PROPERTY; 53827c478bd9Sstevel@tonic-gate 53837c478bd9Sstevel@tonic-gate if (map->map_coldelim == '\0') 53847c478bd9Sstevel@tonic-gate { 53857c478bd9Sstevel@tonic-gate if (bitset(MF_ALIAS, map->map_mflags)) 53867c478bd9Sstevel@tonic-gate map->map_coldelim = ','; 53877c478bd9Sstevel@tonic-gate else if (bitset(MF_FILECLASS, map->map_mflags)) 53887c478bd9Sstevel@tonic-gate map->map_coldelim = ' '; 53897c478bd9Sstevel@tonic-gate } 53907c478bd9Sstevel@tonic-gate return true; 53917c478bd9Sstevel@tonic-gate } 53927c478bd9Sstevel@tonic-gate 53937c478bd9Sstevel@tonic-gate 53947c478bd9Sstevel@tonic-gate /* 53957c478bd9Sstevel@tonic-gate ** NI_MAP_LOOKUP -- look up a datum in NetInfo 53967c478bd9Sstevel@tonic-gate */ 53977c478bd9Sstevel@tonic-gate 53987c478bd9Sstevel@tonic-gate char * 53997c478bd9Sstevel@tonic-gate ni_map_lookup(map, name, av, statp) 54007c478bd9Sstevel@tonic-gate MAP *map; 54017c478bd9Sstevel@tonic-gate char *name; 54027c478bd9Sstevel@tonic-gate char **av; 54037c478bd9Sstevel@tonic-gate int *statp; 54047c478bd9Sstevel@tonic-gate { 54057c478bd9Sstevel@tonic-gate char *res; 54067c478bd9Sstevel@tonic-gate char *propval; 54077c478bd9Sstevel@tonic-gate 54087c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 54097c478bd9Sstevel@tonic-gate sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name); 54107c478bd9Sstevel@tonic-gate 54117c478bd9Sstevel@tonic-gate propval = ni_propval(map->map_file, map->map_keycolnm, name, 54127c478bd9Sstevel@tonic-gate map->map_valcolnm, map->map_coldelim); 54137c478bd9Sstevel@tonic-gate 54147c478bd9Sstevel@tonic-gate if (propval == NULL) 54157c478bd9Sstevel@tonic-gate return NULL; 54167c478bd9Sstevel@tonic-gate 54177c478bd9Sstevel@tonic-gate SM_TRY 54187c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 54197c478bd9Sstevel@tonic-gate res = map_rewrite(map, name, strlen(name), NULL); 54207c478bd9Sstevel@tonic-gate else 54217c478bd9Sstevel@tonic-gate res = map_rewrite(map, propval, strlen(propval), av); 54227c478bd9Sstevel@tonic-gate SM_FINALLY 54237c478bd9Sstevel@tonic-gate sm_free(propval); 54247c478bd9Sstevel@tonic-gate SM_END_TRY 54257c478bd9Sstevel@tonic-gate return res; 54267c478bd9Sstevel@tonic-gate } 54277c478bd9Sstevel@tonic-gate 54287c478bd9Sstevel@tonic-gate 54297c478bd9Sstevel@tonic-gate static bool 54307c478bd9Sstevel@tonic-gate ni_getcanonname(name, hbsize, statp) 54317c478bd9Sstevel@tonic-gate char *name; 54327c478bd9Sstevel@tonic-gate int hbsize; 54337c478bd9Sstevel@tonic-gate int *statp; 54347c478bd9Sstevel@tonic-gate { 54357c478bd9Sstevel@tonic-gate char *vptr; 54367c478bd9Sstevel@tonic-gate char *ptr; 54377c478bd9Sstevel@tonic-gate char nbuf[MAXNAME + 1]; 54387c478bd9Sstevel@tonic-gate 54397c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 54407c478bd9Sstevel@tonic-gate sm_dprintf("ni_getcanonname(%s)\n", name); 54417c478bd9Sstevel@tonic-gate 54427c478bd9Sstevel@tonic-gate if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 54437c478bd9Sstevel@tonic-gate { 54447c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 54457c478bd9Sstevel@tonic-gate return false; 54467c478bd9Sstevel@tonic-gate } 54477c478bd9Sstevel@tonic-gate (void) shorten_hostname(nbuf); 54487c478bd9Sstevel@tonic-gate 54497c478bd9Sstevel@tonic-gate /* we only accept single token search key */ 54507c478bd9Sstevel@tonic-gate if (strchr(nbuf, '.')) 54517c478bd9Sstevel@tonic-gate { 54527c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 54537c478bd9Sstevel@tonic-gate return false; 54547c478bd9Sstevel@tonic-gate } 54557c478bd9Sstevel@tonic-gate 54567c478bd9Sstevel@tonic-gate /* Do the search */ 54577c478bd9Sstevel@tonic-gate vptr = ni_propval("/machines", NULL, nbuf, "name", '\n'); 54587c478bd9Sstevel@tonic-gate 54597c478bd9Sstevel@tonic-gate if (vptr == NULL) 54607c478bd9Sstevel@tonic-gate { 54617c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 54627c478bd9Sstevel@tonic-gate return false; 54637c478bd9Sstevel@tonic-gate } 54647c478bd9Sstevel@tonic-gate 54657c478bd9Sstevel@tonic-gate /* Only want the first machine name */ 54667c478bd9Sstevel@tonic-gate if ((ptr = strchr(vptr, '\n')) != NULL) 54677c478bd9Sstevel@tonic-gate *ptr = '\0'; 54687c478bd9Sstevel@tonic-gate 54697c478bd9Sstevel@tonic-gate if (sm_strlcpy(name, vptr, hbsize) >= hbsize) 54707c478bd9Sstevel@tonic-gate { 54717c478bd9Sstevel@tonic-gate sm_free(vptr); 54727c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 54737c478bd9Sstevel@tonic-gate return true; 54747c478bd9Sstevel@tonic-gate } 54757c478bd9Sstevel@tonic-gate sm_free(vptr); 54767c478bd9Sstevel@tonic-gate *statp = EX_OK; 54777c478bd9Sstevel@tonic-gate return false; 54787c478bd9Sstevel@tonic-gate } 54797c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 54807c478bd9Sstevel@tonic-gate /* 54817c478bd9Sstevel@tonic-gate ** TEXT (unindexed text file) Modules 54827c478bd9Sstevel@tonic-gate ** 54837c478bd9Sstevel@tonic-gate ** This code donated by Sun Microsystems. 54847c478bd9Sstevel@tonic-gate */ 54857c478bd9Sstevel@tonic-gate 54867c478bd9Sstevel@tonic-gate #define map_sff map_lockfd /* overload field */ 54877c478bd9Sstevel@tonic-gate 54887c478bd9Sstevel@tonic-gate 54897c478bd9Sstevel@tonic-gate /* 54907c478bd9Sstevel@tonic-gate ** TEXT_MAP_OPEN -- open text table 54917c478bd9Sstevel@tonic-gate */ 54927c478bd9Sstevel@tonic-gate 54937c478bd9Sstevel@tonic-gate bool 54947c478bd9Sstevel@tonic-gate text_map_open(map, mode) 54957c478bd9Sstevel@tonic-gate MAP *map; 54967c478bd9Sstevel@tonic-gate int mode; 54977c478bd9Sstevel@tonic-gate { 54987c478bd9Sstevel@tonic-gate long sff; 54997c478bd9Sstevel@tonic-gate int i; 55007c478bd9Sstevel@tonic-gate 55017c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 55027c478bd9Sstevel@tonic-gate sm_dprintf("text_map_open(%s, %s, %d)\n", 55037c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 55047c478bd9Sstevel@tonic-gate 55057c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 55067c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 55077c478bd9Sstevel@tonic-gate { 55087c478bd9Sstevel@tonic-gate errno = EPERM; 55097c478bd9Sstevel@tonic-gate return false; 55107c478bd9Sstevel@tonic-gate } 55117c478bd9Sstevel@tonic-gate 55127c478bd9Sstevel@tonic-gate if (*map->map_file == '\0') 55137c478bd9Sstevel@tonic-gate { 55147c478bd9Sstevel@tonic-gate syserr("text map \"%s\": file name required", 55157c478bd9Sstevel@tonic-gate map->map_mname); 55167c478bd9Sstevel@tonic-gate return false; 55177c478bd9Sstevel@tonic-gate } 55187c478bd9Sstevel@tonic-gate 55197c478bd9Sstevel@tonic-gate if (map->map_file[0] != '/') 55207c478bd9Sstevel@tonic-gate { 55217c478bd9Sstevel@tonic-gate syserr("text map \"%s\": file name must be fully qualified", 55227c478bd9Sstevel@tonic-gate map->map_mname); 55237c478bd9Sstevel@tonic-gate return false; 55247c478bd9Sstevel@tonic-gate } 55257c478bd9Sstevel@tonic-gate 55267c478bd9Sstevel@tonic-gate sff = SFF_ROOTOK|SFF_REGONLY; 55277c478bd9Sstevel@tonic-gate if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 55287c478bd9Sstevel@tonic-gate sff |= SFF_NOWLINK; 55297c478bd9Sstevel@tonic-gate if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 55307c478bd9Sstevel@tonic-gate sff |= SFF_SAFEDIRPATH; 55317c478bd9Sstevel@tonic-gate if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, 55327c478bd9Sstevel@tonic-gate sff, S_IRUSR, NULL)) != 0) 55337c478bd9Sstevel@tonic-gate { 55347c478bd9Sstevel@tonic-gate int save_errno = errno; 55357c478bd9Sstevel@tonic-gate 55367c478bd9Sstevel@tonic-gate /* cannot open this map */ 55377c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 55387c478bd9Sstevel@tonic-gate sm_dprintf("\tunsafe map file: %d\n", i); 55397c478bd9Sstevel@tonic-gate errno = save_errno; 55407c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 55417c478bd9Sstevel@tonic-gate syserr("text map \"%s\": unsafe map file %s", 55427c478bd9Sstevel@tonic-gate map->map_mname, map->map_file); 55437c478bd9Sstevel@tonic-gate return false; 55447c478bd9Sstevel@tonic-gate } 55457c478bd9Sstevel@tonic-gate 55467c478bd9Sstevel@tonic-gate if (map->map_keycolnm == NULL) 55477c478bd9Sstevel@tonic-gate map->map_keycolno = 0; 55487c478bd9Sstevel@tonic-gate else 55497c478bd9Sstevel@tonic-gate { 55507c478bd9Sstevel@tonic-gate if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) 55517c478bd9Sstevel@tonic-gate { 55527c478bd9Sstevel@tonic-gate syserr("text map \"%s\", file %s: -k should specify a number, not %s", 55537c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, 55547c478bd9Sstevel@tonic-gate map->map_keycolnm); 55557c478bd9Sstevel@tonic-gate return false; 55567c478bd9Sstevel@tonic-gate } 55577c478bd9Sstevel@tonic-gate map->map_keycolno = atoi(map->map_keycolnm); 55587c478bd9Sstevel@tonic-gate } 55597c478bd9Sstevel@tonic-gate 55607c478bd9Sstevel@tonic-gate if (map->map_valcolnm == NULL) 55617c478bd9Sstevel@tonic-gate map->map_valcolno = 0; 55627c478bd9Sstevel@tonic-gate else 55637c478bd9Sstevel@tonic-gate { 55647c478bd9Sstevel@tonic-gate if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) 55657c478bd9Sstevel@tonic-gate { 55667c478bd9Sstevel@tonic-gate syserr("text map \"%s\", file %s: -v should specify a number, not %s", 55677c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, 55687c478bd9Sstevel@tonic-gate map->map_valcolnm); 55697c478bd9Sstevel@tonic-gate return false; 55707c478bd9Sstevel@tonic-gate } 55717c478bd9Sstevel@tonic-gate map->map_valcolno = atoi(map->map_valcolnm); 55727c478bd9Sstevel@tonic-gate } 55737c478bd9Sstevel@tonic-gate 55747c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 55757c478bd9Sstevel@tonic-gate { 55767c478bd9Sstevel@tonic-gate sm_dprintf("text_map_open(%s, %s): delimiter = ", 55777c478bd9Sstevel@tonic-gate map->map_mname, map->map_file); 55787c478bd9Sstevel@tonic-gate if (map->map_coldelim == '\0') 55797c478bd9Sstevel@tonic-gate sm_dprintf("(white space)\n"); 55807c478bd9Sstevel@tonic-gate else 55817c478bd9Sstevel@tonic-gate sm_dprintf("%c\n", map->map_coldelim); 55827c478bd9Sstevel@tonic-gate } 55837c478bd9Sstevel@tonic-gate 55847c478bd9Sstevel@tonic-gate map->map_sff = sff; 55857c478bd9Sstevel@tonic-gate return true; 55867c478bd9Sstevel@tonic-gate } 55877c478bd9Sstevel@tonic-gate 55887c478bd9Sstevel@tonic-gate 55897c478bd9Sstevel@tonic-gate /* 55907c478bd9Sstevel@tonic-gate ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table 55917c478bd9Sstevel@tonic-gate */ 55927c478bd9Sstevel@tonic-gate 55937c478bd9Sstevel@tonic-gate char * 55947c478bd9Sstevel@tonic-gate text_map_lookup(map, name, av, statp) 55957c478bd9Sstevel@tonic-gate MAP *map; 55967c478bd9Sstevel@tonic-gate char *name; 55977c478bd9Sstevel@tonic-gate char **av; 55987c478bd9Sstevel@tonic-gate int *statp; 55997c478bd9Sstevel@tonic-gate { 56007c478bd9Sstevel@tonic-gate char *vp; 56017c478bd9Sstevel@tonic-gate auto int vsize; 56027c478bd9Sstevel@tonic-gate int buflen; 56037c478bd9Sstevel@tonic-gate SM_FILE_T *f; 56047c478bd9Sstevel@tonic-gate char delim; 56057c478bd9Sstevel@tonic-gate int key_idx; 56067c478bd9Sstevel@tonic-gate bool found_it; 56077c478bd9Sstevel@tonic-gate long sff = map->map_sff; 56087c478bd9Sstevel@tonic-gate char search_key[MAXNAME + 1]; 56097c478bd9Sstevel@tonic-gate char linebuf[MAXLINE]; 56107c478bd9Sstevel@tonic-gate char buf[MAXNAME + 1]; 56117c478bd9Sstevel@tonic-gate 56127c478bd9Sstevel@tonic-gate found_it = false; 56137c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 56147c478bd9Sstevel@tonic-gate sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); 56157c478bd9Sstevel@tonic-gate 56167c478bd9Sstevel@tonic-gate buflen = strlen(name); 56177c478bd9Sstevel@tonic-gate if (buflen > sizeof search_key - 1) 56187c478bd9Sstevel@tonic-gate buflen = sizeof search_key - 1; /* XXX just cut if off? */ 56197c478bd9Sstevel@tonic-gate memmove(search_key, name, buflen); 56207c478bd9Sstevel@tonic-gate search_key[buflen] = '\0'; 56217c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 56227c478bd9Sstevel@tonic-gate makelower(search_key); 56237c478bd9Sstevel@tonic-gate 56247c478bd9Sstevel@tonic-gate f = safefopen(map->map_file, O_RDONLY, FileMode, sff); 56257c478bd9Sstevel@tonic-gate if (f == NULL) 56267c478bd9Sstevel@tonic-gate { 56277c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_VALID|MF_OPEN); 56287c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 56297c478bd9Sstevel@tonic-gate return NULL; 56307c478bd9Sstevel@tonic-gate } 56317c478bd9Sstevel@tonic-gate key_idx = map->map_keycolno; 56327c478bd9Sstevel@tonic-gate delim = map->map_coldelim; 56337c478bd9Sstevel@tonic-gate while (sm_io_fgets(f, SM_TIME_DEFAULT, 56347c478bd9Sstevel@tonic-gate linebuf, sizeof linebuf) != NULL) 56357c478bd9Sstevel@tonic-gate { 56367c478bd9Sstevel@tonic-gate char *p; 56377c478bd9Sstevel@tonic-gate 56387c478bd9Sstevel@tonic-gate /* skip comment line */ 56397c478bd9Sstevel@tonic-gate if (linebuf[0] == '#') 56407c478bd9Sstevel@tonic-gate continue; 56417c478bd9Sstevel@tonic-gate p = strchr(linebuf, '\n'); 56427c478bd9Sstevel@tonic-gate if (p != NULL) 56437c478bd9Sstevel@tonic-gate *p = '\0'; 56447c478bd9Sstevel@tonic-gate p = get_column(linebuf, key_idx, delim, buf, sizeof buf); 56457c478bd9Sstevel@tonic-gate if (p != NULL && sm_strcasecmp(search_key, p) == 0) 56467c478bd9Sstevel@tonic-gate { 56477c478bd9Sstevel@tonic-gate found_it = true; 56487c478bd9Sstevel@tonic-gate break; 56497c478bd9Sstevel@tonic-gate } 56507c478bd9Sstevel@tonic-gate } 56517c478bd9Sstevel@tonic-gate (void) sm_io_close(f, SM_TIME_DEFAULT); 56527c478bd9Sstevel@tonic-gate if (!found_it) 56537c478bd9Sstevel@tonic-gate { 56547c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 56557c478bd9Sstevel@tonic-gate return NULL; 56567c478bd9Sstevel@tonic-gate } 56577c478bd9Sstevel@tonic-gate vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); 56587c478bd9Sstevel@tonic-gate if (vp == NULL) 56597c478bd9Sstevel@tonic-gate { 56607c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 56617c478bd9Sstevel@tonic-gate return NULL; 56627c478bd9Sstevel@tonic-gate } 56637c478bd9Sstevel@tonic-gate vsize = strlen(vp); 56647c478bd9Sstevel@tonic-gate *statp = EX_OK; 56657c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 56667c478bd9Sstevel@tonic-gate return map_rewrite(map, name, strlen(name), NULL); 56677c478bd9Sstevel@tonic-gate else 56687c478bd9Sstevel@tonic-gate return map_rewrite(map, vp, vsize, av); 56697c478bd9Sstevel@tonic-gate } 56707c478bd9Sstevel@tonic-gate 56717c478bd9Sstevel@tonic-gate /* 56727c478bd9Sstevel@tonic-gate ** TEXT_GETCANONNAME -- look up canonical name in hosts file 56737c478bd9Sstevel@tonic-gate */ 56747c478bd9Sstevel@tonic-gate 56757c478bd9Sstevel@tonic-gate static bool 56767c478bd9Sstevel@tonic-gate text_getcanonname(name, hbsize, statp) 56777c478bd9Sstevel@tonic-gate char *name; 56787c478bd9Sstevel@tonic-gate int hbsize; 56797c478bd9Sstevel@tonic-gate int *statp; 56807c478bd9Sstevel@tonic-gate { 56817c478bd9Sstevel@tonic-gate bool found; 56827c478bd9Sstevel@tonic-gate char *dot; 56837c478bd9Sstevel@tonic-gate SM_FILE_T *f; 56847c478bd9Sstevel@tonic-gate char linebuf[MAXLINE]; 56857c478bd9Sstevel@tonic-gate char cbuf[MAXNAME + 1]; 56867c478bd9Sstevel@tonic-gate char nbuf[MAXNAME + 1]; 56877c478bd9Sstevel@tonic-gate 56887c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 56897c478bd9Sstevel@tonic-gate sm_dprintf("text_getcanonname(%s)\n", name); 56907c478bd9Sstevel@tonic-gate 56917c478bd9Sstevel@tonic-gate if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) 56927c478bd9Sstevel@tonic-gate { 56937c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 56947c478bd9Sstevel@tonic-gate return false; 56957c478bd9Sstevel@tonic-gate } 56967c478bd9Sstevel@tonic-gate dot = shorten_hostname(nbuf); 56977c478bd9Sstevel@tonic-gate 56987c478bd9Sstevel@tonic-gate f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY, 56997c478bd9Sstevel@tonic-gate NULL); 57007c478bd9Sstevel@tonic-gate if (f == NULL) 57017c478bd9Sstevel@tonic-gate { 57027c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 57037c478bd9Sstevel@tonic-gate return false; 57047c478bd9Sstevel@tonic-gate } 57057c478bd9Sstevel@tonic-gate found = false; 57067c478bd9Sstevel@tonic-gate while (!found && 57077c478bd9Sstevel@tonic-gate sm_io_fgets(f, SM_TIME_DEFAULT, 57087c478bd9Sstevel@tonic-gate linebuf, sizeof linebuf) != NULL) 57097c478bd9Sstevel@tonic-gate { 57107c478bd9Sstevel@tonic-gate char *p = strpbrk(linebuf, "#\n"); 57117c478bd9Sstevel@tonic-gate 57127c478bd9Sstevel@tonic-gate if (p != NULL) 57137c478bd9Sstevel@tonic-gate *p = '\0'; 57147c478bd9Sstevel@tonic-gate if (linebuf[0] != '\0') 57157c478bd9Sstevel@tonic-gate found = extract_canonname(nbuf, dot, linebuf, 57167c478bd9Sstevel@tonic-gate cbuf, sizeof cbuf); 57177c478bd9Sstevel@tonic-gate } 57187c478bd9Sstevel@tonic-gate (void) sm_io_close(f, SM_TIME_DEFAULT); 57197c478bd9Sstevel@tonic-gate if (!found) 57207c478bd9Sstevel@tonic-gate { 57217c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 57227c478bd9Sstevel@tonic-gate return false; 57237c478bd9Sstevel@tonic-gate } 57247c478bd9Sstevel@tonic-gate 57257c478bd9Sstevel@tonic-gate if (sm_strlcpy(name, cbuf, hbsize) >= hbsize) 57267c478bd9Sstevel@tonic-gate { 57277c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 57287c478bd9Sstevel@tonic-gate return false; 57297c478bd9Sstevel@tonic-gate } 57307c478bd9Sstevel@tonic-gate *statp = EX_OK; 57317c478bd9Sstevel@tonic-gate return true; 57327c478bd9Sstevel@tonic-gate } 57337c478bd9Sstevel@tonic-gate /* 57347c478bd9Sstevel@tonic-gate ** STAB (Symbol Table) Modules 57357c478bd9Sstevel@tonic-gate */ 57367c478bd9Sstevel@tonic-gate 57377c478bd9Sstevel@tonic-gate 57387c478bd9Sstevel@tonic-gate /* 57397c478bd9Sstevel@tonic-gate ** STAB_MAP_LOOKUP -- look up alias in symbol table 57407c478bd9Sstevel@tonic-gate */ 57417c478bd9Sstevel@tonic-gate 57427c478bd9Sstevel@tonic-gate /* ARGSUSED2 */ 57437c478bd9Sstevel@tonic-gate char * 57447c478bd9Sstevel@tonic-gate stab_map_lookup(map, name, av, pstat) 57457c478bd9Sstevel@tonic-gate register MAP *map; 57467c478bd9Sstevel@tonic-gate char *name; 57477c478bd9Sstevel@tonic-gate char **av; 57487c478bd9Sstevel@tonic-gate int *pstat; 57497c478bd9Sstevel@tonic-gate { 57507c478bd9Sstevel@tonic-gate register STAB *s; 57517c478bd9Sstevel@tonic-gate 57527c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 57537c478bd9Sstevel@tonic-gate sm_dprintf("stab_lookup(%s, %s)\n", 57547c478bd9Sstevel@tonic-gate map->map_mname, name); 57557c478bd9Sstevel@tonic-gate 57567c478bd9Sstevel@tonic-gate s = stab(name, ST_ALIAS, ST_FIND); 57577c478bd9Sstevel@tonic-gate if (s == NULL) 57587c478bd9Sstevel@tonic-gate return NULL; 57597c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 57607c478bd9Sstevel@tonic-gate return map_rewrite(map, name, strlen(name), NULL); 57617c478bd9Sstevel@tonic-gate else 57627c478bd9Sstevel@tonic-gate return map_rewrite(map, s->s_alias, strlen(s->s_alias), av); 57637c478bd9Sstevel@tonic-gate } 57647c478bd9Sstevel@tonic-gate 57657c478bd9Sstevel@tonic-gate /* 57667c478bd9Sstevel@tonic-gate ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 57677c478bd9Sstevel@tonic-gate */ 57687c478bd9Sstevel@tonic-gate 57697c478bd9Sstevel@tonic-gate void 57707c478bd9Sstevel@tonic-gate stab_map_store(map, lhs, rhs) 57717c478bd9Sstevel@tonic-gate register MAP *map; 57727c478bd9Sstevel@tonic-gate char *lhs; 57737c478bd9Sstevel@tonic-gate char *rhs; 57747c478bd9Sstevel@tonic-gate { 57757c478bd9Sstevel@tonic-gate register STAB *s; 57767c478bd9Sstevel@tonic-gate 57777c478bd9Sstevel@tonic-gate s = stab(lhs, ST_ALIAS, ST_ENTER); 57787c478bd9Sstevel@tonic-gate s->s_alias = newstr(rhs); 57797c478bd9Sstevel@tonic-gate } 57807c478bd9Sstevel@tonic-gate 57817c478bd9Sstevel@tonic-gate 57827c478bd9Sstevel@tonic-gate /* 57837c478bd9Sstevel@tonic-gate ** STAB_MAP_OPEN -- initialize (reads data file) 57847c478bd9Sstevel@tonic-gate ** 57857c478bd9Sstevel@tonic-gate ** This is a wierd case -- it is only intended as a fallback for 57867c478bd9Sstevel@tonic-gate ** aliases. For this reason, opens for write (only during a 57877c478bd9Sstevel@tonic-gate ** "newaliases") always fails, and opens for read open the 57887c478bd9Sstevel@tonic-gate ** actual underlying text file instead of the database. 57897c478bd9Sstevel@tonic-gate */ 57907c478bd9Sstevel@tonic-gate 57917c478bd9Sstevel@tonic-gate bool 57927c478bd9Sstevel@tonic-gate stab_map_open(map, mode) 57937c478bd9Sstevel@tonic-gate register MAP *map; 57947c478bd9Sstevel@tonic-gate int mode; 57957c478bd9Sstevel@tonic-gate { 57967c478bd9Sstevel@tonic-gate SM_FILE_T *af; 57977c478bd9Sstevel@tonic-gate long sff; 57987c478bd9Sstevel@tonic-gate struct stat st; 57997c478bd9Sstevel@tonic-gate 58007c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 58017c478bd9Sstevel@tonic-gate sm_dprintf("stab_map_open(%s, %s, %d)\n", 58027c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 58037c478bd9Sstevel@tonic-gate 58047c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 58057c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 58067c478bd9Sstevel@tonic-gate { 58077c478bd9Sstevel@tonic-gate errno = EPERM; 58087c478bd9Sstevel@tonic-gate return false; 58097c478bd9Sstevel@tonic-gate } 58107c478bd9Sstevel@tonic-gate 58117c478bd9Sstevel@tonic-gate sff = SFF_ROOTOK|SFF_REGONLY; 58127c478bd9Sstevel@tonic-gate if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) 58137c478bd9Sstevel@tonic-gate sff |= SFF_NOWLINK; 58147c478bd9Sstevel@tonic-gate if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) 58157c478bd9Sstevel@tonic-gate sff |= SFF_SAFEDIRPATH; 58167c478bd9Sstevel@tonic-gate af = safefopen(map->map_file, O_RDONLY, 0444, sff); 58177c478bd9Sstevel@tonic-gate if (af == NULL) 58187c478bd9Sstevel@tonic-gate return false; 58197c478bd9Sstevel@tonic-gate readaliases(map, af, false, false); 58207c478bd9Sstevel@tonic-gate 58217c478bd9Sstevel@tonic-gate if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0) 58227c478bd9Sstevel@tonic-gate map->map_mtime = st.st_mtime; 58237c478bd9Sstevel@tonic-gate (void) sm_io_close(af, SM_TIME_DEFAULT); 58247c478bd9Sstevel@tonic-gate 58257c478bd9Sstevel@tonic-gate return true; 58267c478bd9Sstevel@tonic-gate } 58277c478bd9Sstevel@tonic-gate /* 58287c478bd9Sstevel@tonic-gate ** Implicit Modules 58297c478bd9Sstevel@tonic-gate ** 58307c478bd9Sstevel@tonic-gate ** Tries several types. For back compatibility of aliases. 58317c478bd9Sstevel@tonic-gate */ 58327c478bd9Sstevel@tonic-gate 58337c478bd9Sstevel@tonic-gate 58347c478bd9Sstevel@tonic-gate /* 58357c478bd9Sstevel@tonic-gate ** IMPL_MAP_LOOKUP -- lookup in best open database 58367c478bd9Sstevel@tonic-gate */ 58377c478bd9Sstevel@tonic-gate 58387c478bd9Sstevel@tonic-gate char * 58397c478bd9Sstevel@tonic-gate impl_map_lookup(map, name, av, pstat) 58407c478bd9Sstevel@tonic-gate MAP *map; 58417c478bd9Sstevel@tonic-gate char *name; 58427c478bd9Sstevel@tonic-gate char **av; 58437c478bd9Sstevel@tonic-gate int *pstat; 58447c478bd9Sstevel@tonic-gate { 58457c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 58467c478bd9Sstevel@tonic-gate sm_dprintf("impl_map_lookup(%s, %s)\n", 58477c478bd9Sstevel@tonic-gate map->map_mname, name); 58487c478bd9Sstevel@tonic-gate 58497c478bd9Sstevel@tonic-gate #if NEWDB 58507c478bd9Sstevel@tonic-gate if (bitset(MF_IMPL_HASH, map->map_mflags)) 58517c478bd9Sstevel@tonic-gate return db_map_lookup(map, name, av, pstat); 58527c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 58537c478bd9Sstevel@tonic-gate #if NDBM 58547c478bd9Sstevel@tonic-gate if (bitset(MF_IMPL_NDBM, map->map_mflags)) 58557c478bd9Sstevel@tonic-gate return ndbm_map_lookup(map, name, av, pstat); 58567c478bd9Sstevel@tonic-gate #endif /* NDBM */ 58577c478bd9Sstevel@tonic-gate return stab_map_lookup(map, name, av, pstat); 58587c478bd9Sstevel@tonic-gate } 58597c478bd9Sstevel@tonic-gate 58607c478bd9Sstevel@tonic-gate /* 58617c478bd9Sstevel@tonic-gate ** IMPL_MAP_STORE -- store in open databases 58627c478bd9Sstevel@tonic-gate */ 58637c478bd9Sstevel@tonic-gate 58647c478bd9Sstevel@tonic-gate void 58657c478bd9Sstevel@tonic-gate impl_map_store(map, lhs, rhs) 58667c478bd9Sstevel@tonic-gate MAP *map; 58677c478bd9Sstevel@tonic-gate char *lhs; 58687c478bd9Sstevel@tonic-gate char *rhs; 58697c478bd9Sstevel@tonic-gate { 58707c478bd9Sstevel@tonic-gate if (tTd(38, 12)) 58717c478bd9Sstevel@tonic-gate sm_dprintf("impl_map_store(%s, %s, %s)\n", 58727c478bd9Sstevel@tonic-gate map->map_mname, lhs, rhs); 58737c478bd9Sstevel@tonic-gate #if NEWDB 58747c478bd9Sstevel@tonic-gate if (bitset(MF_IMPL_HASH, map->map_mflags)) 58757c478bd9Sstevel@tonic-gate db_map_store(map, lhs, rhs); 58767c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 58777c478bd9Sstevel@tonic-gate #if NDBM 58787c478bd9Sstevel@tonic-gate if (bitset(MF_IMPL_NDBM, map->map_mflags)) 58797c478bd9Sstevel@tonic-gate ndbm_map_store(map, lhs, rhs); 58807c478bd9Sstevel@tonic-gate #endif /* NDBM */ 58817c478bd9Sstevel@tonic-gate stab_map_store(map, lhs, rhs); 58827c478bd9Sstevel@tonic-gate } 58837c478bd9Sstevel@tonic-gate 58847c478bd9Sstevel@tonic-gate /* 58857c478bd9Sstevel@tonic-gate ** IMPL_MAP_OPEN -- implicit database open 58867c478bd9Sstevel@tonic-gate */ 58877c478bd9Sstevel@tonic-gate 58887c478bd9Sstevel@tonic-gate bool 58897c478bd9Sstevel@tonic-gate impl_map_open(map, mode) 58907c478bd9Sstevel@tonic-gate MAP *map; 58917c478bd9Sstevel@tonic-gate int mode; 58927c478bd9Sstevel@tonic-gate { 58937c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 58947c478bd9Sstevel@tonic-gate sm_dprintf("impl_map_open(%s, %s, %d)\n", 58957c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 58967c478bd9Sstevel@tonic-gate 58977c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 58987c478bd9Sstevel@tonic-gate #if NEWDB 58997c478bd9Sstevel@tonic-gate map->map_mflags |= MF_IMPL_HASH; 59007c478bd9Sstevel@tonic-gate if (hash_map_open(map, mode)) 59017c478bd9Sstevel@tonic-gate { 59027c478bd9Sstevel@tonic-gate # ifdef NDBM_YP_COMPAT 59037c478bd9Sstevel@tonic-gate if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) 59047c478bd9Sstevel@tonic-gate # endif /* NDBM_YP_COMPAT */ 59057c478bd9Sstevel@tonic-gate return true; 59067c478bd9Sstevel@tonic-gate } 59077c478bd9Sstevel@tonic-gate else 59087c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_IMPL_HASH; 59097c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 59107c478bd9Sstevel@tonic-gate #if NDBM 59117c478bd9Sstevel@tonic-gate map->map_mflags |= MF_IMPL_NDBM; 59127c478bd9Sstevel@tonic-gate if (ndbm_map_open(map, mode)) 59137c478bd9Sstevel@tonic-gate { 59147c478bd9Sstevel@tonic-gate return true; 59157c478bd9Sstevel@tonic-gate } 59167c478bd9Sstevel@tonic-gate else 59177c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_IMPL_NDBM; 59187c478bd9Sstevel@tonic-gate #endif /* NDBM */ 59197c478bd9Sstevel@tonic-gate 59207c478bd9Sstevel@tonic-gate #if defined(NEWDB) || defined(NDBM) 59217c478bd9Sstevel@tonic-gate if (Verbose) 59227c478bd9Sstevel@tonic-gate message("WARNING: cannot open alias database %s%s", 59237c478bd9Sstevel@tonic-gate map->map_file, 59247c478bd9Sstevel@tonic-gate mode == O_RDONLY ? "; reading text version" : ""); 59257c478bd9Sstevel@tonic-gate #else /* defined(NEWDB) || defined(NDBM) */ 59267c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 59277c478bd9Sstevel@tonic-gate usrerr("Cannot rebuild aliases: no database format defined"); 59287c478bd9Sstevel@tonic-gate #endif /* defined(NEWDB) || defined(NDBM) */ 59297c478bd9Sstevel@tonic-gate 59307c478bd9Sstevel@tonic-gate if (mode == O_RDONLY) 59317c478bd9Sstevel@tonic-gate return stab_map_open(map, mode); 59327c478bd9Sstevel@tonic-gate else 59337c478bd9Sstevel@tonic-gate return false; 59347c478bd9Sstevel@tonic-gate } 59357c478bd9Sstevel@tonic-gate 59367c478bd9Sstevel@tonic-gate 59377c478bd9Sstevel@tonic-gate /* 59387c478bd9Sstevel@tonic-gate ** IMPL_MAP_CLOSE -- close any open database(s) 59397c478bd9Sstevel@tonic-gate */ 59407c478bd9Sstevel@tonic-gate 59417c478bd9Sstevel@tonic-gate void 59427c478bd9Sstevel@tonic-gate impl_map_close(map) 59437c478bd9Sstevel@tonic-gate MAP *map; 59447c478bd9Sstevel@tonic-gate { 59457c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 59467c478bd9Sstevel@tonic-gate sm_dprintf("impl_map_close(%s, %s, %lx)\n", 59477c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, map->map_mflags); 59487c478bd9Sstevel@tonic-gate #if NEWDB 59497c478bd9Sstevel@tonic-gate if (bitset(MF_IMPL_HASH, map->map_mflags)) 59507c478bd9Sstevel@tonic-gate { 59517c478bd9Sstevel@tonic-gate db_map_close(map); 59527c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_IMPL_HASH; 59537c478bd9Sstevel@tonic-gate } 59547c478bd9Sstevel@tonic-gate #endif /* NEWDB */ 59557c478bd9Sstevel@tonic-gate 59567c478bd9Sstevel@tonic-gate #if NDBM 59577c478bd9Sstevel@tonic-gate if (bitset(MF_IMPL_NDBM, map->map_mflags)) 59587c478bd9Sstevel@tonic-gate { 59597c478bd9Sstevel@tonic-gate ndbm_map_close(map); 59607c478bd9Sstevel@tonic-gate map->map_mflags &= ~MF_IMPL_NDBM; 59617c478bd9Sstevel@tonic-gate } 59627c478bd9Sstevel@tonic-gate #endif /* NDBM */ 59637c478bd9Sstevel@tonic-gate } 59647c478bd9Sstevel@tonic-gate /* 59657c478bd9Sstevel@tonic-gate ** User map class. 59667c478bd9Sstevel@tonic-gate ** 59677c478bd9Sstevel@tonic-gate ** Provides access to the system password file. 59687c478bd9Sstevel@tonic-gate */ 59697c478bd9Sstevel@tonic-gate 59707c478bd9Sstevel@tonic-gate /* 59717c478bd9Sstevel@tonic-gate ** USER_MAP_OPEN -- open user map 59727c478bd9Sstevel@tonic-gate ** 59737c478bd9Sstevel@tonic-gate ** Really just binds field names to field numbers. 59747c478bd9Sstevel@tonic-gate */ 59757c478bd9Sstevel@tonic-gate 59767c478bd9Sstevel@tonic-gate bool 59777c478bd9Sstevel@tonic-gate user_map_open(map, mode) 59787c478bd9Sstevel@tonic-gate MAP *map; 59797c478bd9Sstevel@tonic-gate int mode; 59807c478bd9Sstevel@tonic-gate { 59817c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 59827c478bd9Sstevel@tonic-gate sm_dprintf("user_map_open(%s, %d)\n", 59837c478bd9Sstevel@tonic-gate map->map_mname, mode); 59847c478bd9Sstevel@tonic-gate 59857c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 59867c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 59877c478bd9Sstevel@tonic-gate { 59887c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 59897c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 59907c478bd9Sstevel@tonic-gate return false; 59917c478bd9Sstevel@tonic-gate } 59927c478bd9Sstevel@tonic-gate if (map->map_valcolnm == NULL) 59937c478bd9Sstevel@tonic-gate /* EMPTY */ 59947c478bd9Sstevel@tonic-gate /* nothing */ ; 59957c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "name") == 0) 59967c478bd9Sstevel@tonic-gate map->map_valcolno = 1; 59977c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0) 59987c478bd9Sstevel@tonic-gate map->map_valcolno = 2; 59997c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0) 60007c478bd9Sstevel@tonic-gate map->map_valcolno = 3; 60017c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0) 60027c478bd9Sstevel@tonic-gate map->map_valcolno = 4; 60037c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0) 60047c478bd9Sstevel@tonic-gate map->map_valcolno = 5; 60057c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0) 60067c478bd9Sstevel@tonic-gate map->map_valcolno = 6; 60077c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0) 60087c478bd9Sstevel@tonic-gate map->map_valcolno = 7; 60097c478bd9Sstevel@tonic-gate else 60107c478bd9Sstevel@tonic-gate { 60117c478bd9Sstevel@tonic-gate syserr("User map %s: unknown column name %s", 60127c478bd9Sstevel@tonic-gate map->map_mname, map->map_valcolnm); 60137c478bd9Sstevel@tonic-gate return false; 60147c478bd9Sstevel@tonic-gate } 60157c478bd9Sstevel@tonic-gate return true; 60167c478bd9Sstevel@tonic-gate } 60177c478bd9Sstevel@tonic-gate 60187c478bd9Sstevel@tonic-gate 60197c478bd9Sstevel@tonic-gate /* 60207c478bd9Sstevel@tonic-gate ** USER_MAP_LOOKUP -- look up a user in the passwd file. 60217c478bd9Sstevel@tonic-gate */ 60227c478bd9Sstevel@tonic-gate 60237c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 60247c478bd9Sstevel@tonic-gate char * 60257c478bd9Sstevel@tonic-gate user_map_lookup(map, key, av, statp) 60267c478bd9Sstevel@tonic-gate MAP *map; 60277c478bd9Sstevel@tonic-gate char *key; 60287c478bd9Sstevel@tonic-gate char **av; 60297c478bd9Sstevel@tonic-gate int *statp; 60307c478bd9Sstevel@tonic-gate { 60317c478bd9Sstevel@tonic-gate auto bool fuzzy; 60327c478bd9Sstevel@tonic-gate SM_MBDB_T user; 60337c478bd9Sstevel@tonic-gate 60347c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 60357c478bd9Sstevel@tonic-gate sm_dprintf("user_map_lookup(%s, %s)\n", 60367c478bd9Sstevel@tonic-gate map->map_mname, key); 60377c478bd9Sstevel@tonic-gate 60387c478bd9Sstevel@tonic-gate *statp = finduser(key, &fuzzy, &user); 60397c478bd9Sstevel@tonic-gate if (*statp != EX_OK) 60407c478bd9Sstevel@tonic-gate return NULL; 60417c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 60427c478bd9Sstevel@tonic-gate return map_rewrite(map, key, strlen(key), NULL); 60437c478bd9Sstevel@tonic-gate else 60447c478bd9Sstevel@tonic-gate { 60457c478bd9Sstevel@tonic-gate char *rwval = NULL; 60467c478bd9Sstevel@tonic-gate char buf[30]; 60477c478bd9Sstevel@tonic-gate 60487c478bd9Sstevel@tonic-gate switch (map->map_valcolno) 60497c478bd9Sstevel@tonic-gate { 60507c478bd9Sstevel@tonic-gate case 0: 60517c478bd9Sstevel@tonic-gate case 1: 60527c478bd9Sstevel@tonic-gate rwval = user.mbdb_name; 60537c478bd9Sstevel@tonic-gate break; 60547c478bd9Sstevel@tonic-gate 60557c478bd9Sstevel@tonic-gate case 2: 60567c478bd9Sstevel@tonic-gate rwval = "x"; /* passwd no longer supported */ 60577c478bd9Sstevel@tonic-gate break; 60587c478bd9Sstevel@tonic-gate 60597c478bd9Sstevel@tonic-gate case 3: 60607c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "%d", 60617c478bd9Sstevel@tonic-gate (int) user.mbdb_uid); 60627c478bd9Sstevel@tonic-gate rwval = buf; 60637c478bd9Sstevel@tonic-gate break; 60647c478bd9Sstevel@tonic-gate 60657c478bd9Sstevel@tonic-gate case 4: 60667c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "%d", 60677c478bd9Sstevel@tonic-gate (int) user.mbdb_gid); 60687c478bd9Sstevel@tonic-gate rwval = buf; 60697c478bd9Sstevel@tonic-gate break; 60707c478bd9Sstevel@tonic-gate 60717c478bd9Sstevel@tonic-gate case 5: 60727c478bd9Sstevel@tonic-gate rwval = user.mbdb_fullname; 60737c478bd9Sstevel@tonic-gate break; 60747c478bd9Sstevel@tonic-gate 60757c478bd9Sstevel@tonic-gate case 6: 60767c478bd9Sstevel@tonic-gate rwval = user.mbdb_homedir; 60777c478bd9Sstevel@tonic-gate break; 60787c478bd9Sstevel@tonic-gate 60797c478bd9Sstevel@tonic-gate case 7: 60807c478bd9Sstevel@tonic-gate rwval = user.mbdb_shell; 60817c478bd9Sstevel@tonic-gate break; 6082*3ee0e492Sjbeck default: 6083*3ee0e492Sjbeck syserr("user_map %s: bogus field %d", 6084*3ee0e492Sjbeck map->map_mname, map->map_valcolno); 6085*3ee0e492Sjbeck return NULL; 60867c478bd9Sstevel@tonic-gate } 60877c478bd9Sstevel@tonic-gate return map_rewrite(map, rwval, strlen(rwval), av); 60887c478bd9Sstevel@tonic-gate } 60897c478bd9Sstevel@tonic-gate } 60907c478bd9Sstevel@tonic-gate /* 60917c478bd9Sstevel@tonic-gate ** Program map type. 60927c478bd9Sstevel@tonic-gate ** 60937c478bd9Sstevel@tonic-gate ** This provides access to arbitrary programs. It should be used 60947c478bd9Sstevel@tonic-gate ** only very sparingly, since there is no way to bound the cost 60957c478bd9Sstevel@tonic-gate ** of invoking an arbitrary program. 60967c478bd9Sstevel@tonic-gate */ 60977c478bd9Sstevel@tonic-gate 60987c478bd9Sstevel@tonic-gate char * 60997c478bd9Sstevel@tonic-gate prog_map_lookup(map, name, av, statp) 61007c478bd9Sstevel@tonic-gate MAP *map; 61017c478bd9Sstevel@tonic-gate char *name; 61027c478bd9Sstevel@tonic-gate char **av; 61037c478bd9Sstevel@tonic-gate int *statp; 61047c478bd9Sstevel@tonic-gate { 61057c478bd9Sstevel@tonic-gate int i; 61067c478bd9Sstevel@tonic-gate int save_errno; 61077c478bd9Sstevel@tonic-gate int fd; 61087c478bd9Sstevel@tonic-gate int status; 61097c478bd9Sstevel@tonic-gate auto pid_t pid; 61107c478bd9Sstevel@tonic-gate register char *p; 61117c478bd9Sstevel@tonic-gate char *rval; 61127c478bd9Sstevel@tonic-gate char *argv[MAXPV + 1]; 61137c478bd9Sstevel@tonic-gate char buf[MAXLINE]; 61147c478bd9Sstevel@tonic-gate 61157c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 61167c478bd9Sstevel@tonic-gate sm_dprintf("prog_map_lookup(%s, %s) %s\n", 61177c478bd9Sstevel@tonic-gate map->map_mname, name, map->map_file); 61187c478bd9Sstevel@tonic-gate 61197c478bd9Sstevel@tonic-gate i = 0; 61207c478bd9Sstevel@tonic-gate argv[i++] = map->map_file; 61217c478bd9Sstevel@tonic-gate if (map->map_rebuild != NULL) 61227c478bd9Sstevel@tonic-gate { 61237c478bd9Sstevel@tonic-gate (void) sm_strlcpy(buf, map->map_rebuild, sizeof buf); 61247c478bd9Sstevel@tonic-gate for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t")) 61257c478bd9Sstevel@tonic-gate { 61267c478bd9Sstevel@tonic-gate if (i >= MAXPV - 1) 61277c478bd9Sstevel@tonic-gate break; 61287c478bd9Sstevel@tonic-gate argv[i++] = p; 61297c478bd9Sstevel@tonic-gate } 61307c478bd9Sstevel@tonic-gate } 61317c478bd9Sstevel@tonic-gate argv[i++] = name; 61327c478bd9Sstevel@tonic-gate argv[i] = NULL; 61337c478bd9Sstevel@tonic-gate if (tTd(38, 21)) 61347c478bd9Sstevel@tonic-gate { 61357c478bd9Sstevel@tonic-gate sm_dprintf("prog_open:"); 61367c478bd9Sstevel@tonic-gate for (i = 0; argv[i] != NULL; i++) 61377c478bd9Sstevel@tonic-gate sm_dprintf(" %s", argv[i]); 61387c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 61397c478bd9Sstevel@tonic-gate } 61407c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGCHLD); 61417c478bd9Sstevel@tonic-gate pid = prog_open(argv, &fd, CurEnv); 61427c478bd9Sstevel@tonic-gate if (pid < 0) 61437c478bd9Sstevel@tonic-gate { 61447c478bd9Sstevel@tonic-gate if (!bitset(MF_OPTIONAL, map->map_mflags)) 61457c478bd9Sstevel@tonic-gate syserr("prog_map_lookup(%s) failed (%s) -- closing", 61467c478bd9Sstevel@tonic-gate map->map_mname, sm_errstring(errno)); 61477c478bd9Sstevel@tonic-gate else if (tTd(38, 9)) 61487c478bd9Sstevel@tonic-gate sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing", 61497c478bd9Sstevel@tonic-gate map->map_mname, sm_errstring(errno)); 61507c478bd9Sstevel@tonic-gate map->map_mflags &= ~(MF_VALID|MF_OPEN); 61517c478bd9Sstevel@tonic-gate *statp = EX_OSFILE; 61527c478bd9Sstevel@tonic-gate return NULL; 61537c478bd9Sstevel@tonic-gate } 61547c478bd9Sstevel@tonic-gate i = read(fd, buf, sizeof buf - 1); 61557c478bd9Sstevel@tonic-gate if (i < 0) 61567c478bd9Sstevel@tonic-gate { 61577c478bd9Sstevel@tonic-gate syserr("prog_map_lookup(%s): read error %s", 61587c478bd9Sstevel@tonic-gate map->map_mname, sm_errstring(errno)); 61597c478bd9Sstevel@tonic-gate rval = NULL; 61607c478bd9Sstevel@tonic-gate } 61617c478bd9Sstevel@tonic-gate else if (i == 0) 61627c478bd9Sstevel@tonic-gate { 61637c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 61647c478bd9Sstevel@tonic-gate sm_dprintf("prog_map_lookup(%s): empty answer\n", 61657c478bd9Sstevel@tonic-gate map->map_mname); 61667c478bd9Sstevel@tonic-gate rval = NULL; 61677c478bd9Sstevel@tonic-gate } 61687c478bd9Sstevel@tonic-gate else 61697c478bd9Sstevel@tonic-gate { 61707c478bd9Sstevel@tonic-gate buf[i] = '\0'; 61717c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 61727c478bd9Sstevel@tonic-gate if (p != NULL) 61737c478bd9Sstevel@tonic-gate *p = '\0'; 61747c478bd9Sstevel@tonic-gate 61757c478bd9Sstevel@tonic-gate /* collect the return value */ 61767c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 61777c478bd9Sstevel@tonic-gate rval = map_rewrite(map, name, strlen(name), NULL); 61787c478bd9Sstevel@tonic-gate else 61797c478bd9Sstevel@tonic-gate rval = map_rewrite(map, buf, strlen(buf), av); 61807c478bd9Sstevel@tonic-gate 61817c478bd9Sstevel@tonic-gate /* now flush any additional output */ 61827c478bd9Sstevel@tonic-gate while ((i = read(fd, buf, sizeof buf)) > 0) 61837c478bd9Sstevel@tonic-gate continue; 61847c478bd9Sstevel@tonic-gate } 61857c478bd9Sstevel@tonic-gate 61867c478bd9Sstevel@tonic-gate /* wait for the process to terminate */ 61877c478bd9Sstevel@tonic-gate (void) close(fd); 61887c478bd9Sstevel@tonic-gate status = waitfor(pid); 61897c478bd9Sstevel@tonic-gate save_errno = errno; 61907c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 61917c478bd9Sstevel@tonic-gate errno = save_errno; 61927c478bd9Sstevel@tonic-gate 61937c478bd9Sstevel@tonic-gate if (status == -1) 61947c478bd9Sstevel@tonic-gate { 61957c478bd9Sstevel@tonic-gate syserr("prog_map_lookup(%s): wait error %s", 61967c478bd9Sstevel@tonic-gate map->map_mname, sm_errstring(errno)); 61977c478bd9Sstevel@tonic-gate *statp = EX_SOFTWARE; 61987c478bd9Sstevel@tonic-gate rval = NULL; 61997c478bd9Sstevel@tonic-gate } 62007c478bd9Sstevel@tonic-gate else if (WIFEXITED(status)) 62017c478bd9Sstevel@tonic-gate { 62027c478bd9Sstevel@tonic-gate if ((*statp = WEXITSTATUS(status)) != EX_OK) 62037c478bd9Sstevel@tonic-gate rval = NULL; 62047c478bd9Sstevel@tonic-gate } 62057c478bd9Sstevel@tonic-gate else 62067c478bd9Sstevel@tonic-gate { 62077c478bd9Sstevel@tonic-gate syserr("prog_map_lookup(%s): child died on signal %d", 62087c478bd9Sstevel@tonic-gate map->map_mname, status); 62097c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 62107c478bd9Sstevel@tonic-gate rval = NULL; 62117c478bd9Sstevel@tonic-gate } 62127c478bd9Sstevel@tonic-gate return rval; 62137c478bd9Sstevel@tonic-gate } 62147c478bd9Sstevel@tonic-gate /* 62157c478bd9Sstevel@tonic-gate ** Sequenced map type. 62167c478bd9Sstevel@tonic-gate ** 62177c478bd9Sstevel@tonic-gate ** Tries each map in order until something matches, much like 62187c478bd9Sstevel@tonic-gate ** implicit. Stores go to the first map in the list that can 62197c478bd9Sstevel@tonic-gate ** support storing. 62207c478bd9Sstevel@tonic-gate ** 62217c478bd9Sstevel@tonic-gate ** This is slightly unusual in that there are two interfaces. 62227c478bd9Sstevel@tonic-gate ** The "sequence" interface lets you stack maps arbitrarily. 62237c478bd9Sstevel@tonic-gate ** The "switch" interface builds a sequence map by looking 62247c478bd9Sstevel@tonic-gate ** at a system-dependent configuration file such as 62257c478bd9Sstevel@tonic-gate ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix. 62267c478bd9Sstevel@tonic-gate ** 62277c478bd9Sstevel@tonic-gate ** We don't need an explicit open, since all maps are 62287c478bd9Sstevel@tonic-gate ** opened on demand. 62297c478bd9Sstevel@tonic-gate */ 62307c478bd9Sstevel@tonic-gate 62317c478bd9Sstevel@tonic-gate /* 62327c478bd9Sstevel@tonic-gate ** SEQ_MAP_PARSE -- Sequenced map parsing 62337c478bd9Sstevel@tonic-gate */ 62347c478bd9Sstevel@tonic-gate 62357c478bd9Sstevel@tonic-gate bool 62367c478bd9Sstevel@tonic-gate seq_map_parse(map, ap) 62377c478bd9Sstevel@tonic-gate MAP *map; 62387c478bd9Sstevel@tonic-gate char *ap; 62397c478bd9Sstevel@tonic-gate { 62407c478bd9Sstevel@tonic-gate int maxmap; 62417c478bd9Sstevel@tonic-gate 62427c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 62437c478bd9Sstevel@tonic-gate sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap); 62447c478bd9Sstevel@tonic-gate maxmap = 0; 62457c478bd9Sstevel@tonic-gate while (*ap != '\0') 62467c478bd9Sstevel@tonic-gate { 62477c478bd9Sstevel@tonic-gate register char *p; 62487c478bd9Sstevel@tonic-gate STAB *s; 62497c478bd9Sstevel@tonic-gate 62507c478bd9Sstevel@tonic-gate /* find beginning of map name */ 62517c478bd9Sstevel@tonic-gate while (isascii(*ap) && isspace(*ap)) 62527c478bd9Sstevel@tonic-gate ap++; 62537c478bd9Sstevel@tonic-gate for (p = ap; 62547c478bd9Sstevel@tonic-gate (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.'; 62557c478bd9Sstevel@tonic-gate p++) 62567c478bd9Sstevel@tonic-gate continue; 62577c478bd9Sstevel@tonic-gate if (*p != '\0') 62587c478bd9Sstevel@tonic-gate *p++ = '\0'; 62597c478bd9Sstevel@tonic-gate while (*p != '\0' && (!isascii(*p) || !isalnum(*p))) 62607c478bd9Sstevel@tonic-gate p++; 62617c478bd9Sstevel@tonic-gate if (*ap == '\0') 62627c478bd9Sstevel@tonic-gate { 62637c478bd9Sstevel@tonic-gate ap = p; 62647c478bd9Sstevel@tonic-gate continue; 62657c478bd9Sstevel@tonic-gate } 62667c478bd9Sstevel@tonic-gate s = stab(ap, ST_MAP, ST_FIND); 62677c478bd9Sstevel@tonic-gate if (s == NULL) 62687c478bd9Sstevel@tonic-gate { 62697c478bd9Sstevel@tonic-gate syserr("Sequence map %s: unknown member map %s", 62707c478bd9Sstevel@tonic-gate map->map_mname, ap); 62717c478bd9Sstevel@tonic-gate } 62727c478bd9Sstevel@tonic-gate else if (maxmap >= MAXMAPSTACK) 62737c478bd9Sstevel@tonic-gate { 62747c478bd9Sstevel@tonic-gate syserr("Sequence map %s: too many member maps (%d max)", 62757c478bd9Sstevel@tonic-gate map->map_mname, MAXMAPSTACK); 62767c478bd9Sstevel@tonic-gate maxmap++; 62777c478bd9Sstevel@tonic-gate } 62787c478bd9Sstevel@tonic-gate else if (maxmap < MAXMAPSTACK) 62797c478bd9Sstevel@tonic-gate { 62807c478bd9Sstevel@tonic-gate map->map_stack[maxmap++] = &s->s_map; 62817c478bd9Sstevel@tonic-gate } 62827c478bd9Sstevel@tonic-gate ap = p; 62837c478bd9Sstevel@tonic-gate } 62847c478bd9Sstevel@tonic-gate return true; 62857c478bd9Sstevel@tonic-gate } 62867c478bd9Sstevel@tonic-gate 62877c478bd9Sstevel@tonic-gate /* 62887c478bd9Sstevel@tonic-gate ** SWITCH_MAP_OPEN -- open a switched map 62897c478bd9Sstevel@tonic-gate ** 62907c478bd9Sstevel@tonic-gate ** This looks at the system-dependent configuration and builds 62917c478bd9Sstevel@tonic-gate ** a sequence map that does the same thing. 62927c478bd9Sstevel@tonic-gate ** 62937c478bd9Sstevel@tonic-gate ** Every system must define a switch_map_find routine in conf.c 62947c478bd9Sstevel@tonic-gate ** that will return the list of service types associated with a 62957c478bd9Sstevel@tonic-gate ** given service class. 62967c478bd9Sstevel@tonic-gate */ 62977c478bd9Sstevel@tonic-gate 62987c478bd9Sstevel@tonic-gate bool 62997c478bd9Sstevel@tonic-gate switch_map_open(map, mode) 63007c478bd9Sstevel@tonic-gate MAP *map; 63017c478bd9Sstevel@tonic-gate int mode; 63027c478bd9Sstevel@tonic-gate { 63037c478bd9Sstevel@tonic-gate int mapno; 63047c478bd9Sstevel@tonic-gate int nmaps; 63057c478bd9Sstevel@tonic-gate char *maptype[MAXMAPSTACK]; 63067c478bd9Sstevel@tonic-gate 63077c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 63087c478bd9Sstevel@tonic-gate sm_dprintf("switch_map_open(%s, %s, %d)\n", 63097c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 63107c478bd9Sstevel@tonic-gate 63117c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 63127c478bd9Sstevel@tonic-gate nmaps = switch_map_find(map->map_file, maptype, map->map_return); 63137c478bd9Sstevel@tonic-gate if (tTd(38, 19)) 63147c478bd9Sstevel@tonic-gate { 63157c478bd9Sstevel@tonic-gate sm_dprintf("\tswitch_map_find => %d\n", nmaps); 63167c478bd9Sstevel@tonic-gate for (mapno = 0; mapno < nmaps; mapno++) 63177c478bd9Sstevel@tonic-gate sm_dprintf("\t\t%s\n", maptype[mapno]); 63187c478bd9Sstevel@tonic-gate } 63197c478bd9Sstevel@tonic-gate if (nmaps <= 0 || nmaps > MAXMAPSTACK) 63207c478bd9Sstevel@tonic-gate return false; 63217c478bd9Sstevel@tonic-gate 63227c478bd9Sstevel@tonic-gate for (mapno = 0; mapno < nmaps; mapno++) 63237c478bd9Sstevel@tonic-gate { 63247c478bd9Sstevel@tonic-gate register STAB *s; 63257c478bd9Sstevel@tonic-gate char nbuf[MAXNAME + 1]; 63267c478bd9Sstevel@tonic-gate 63277c478bd9Sstevel@tonic-gate if (maptype[mapno] == NULL) 63287c478bd9Sstevel@tonic-gate continue; 63297c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(nbuf, sizeof nbuf, 3, 63307c478bd9Sstevel@tonic-gate map->map_mname, ".", maptype[mapno]); 63317c478bd9Sstevel@tonic-gate s = stab(nbuf, ST_MAP, ST_FIND); 63327c478bd9Sstevel@tonic-gate if (s == NULL) 63337c478bd9Sstevel@tonic-gate { 63347c478bd9Sstevel@tonic-gate syserr("Switch map %s: unknown member map %s", 63357c478bd9Sstevel@tonic-gate map->map_mname, nbuf); 63367c478bd9Sstevel@tonic-gate } 63377c478bd9Sstevel@tonic-gate else 63387c478bd9Sstevel@tonic-gate { 63397c478bd9Sstevel@tonic-gate map->map_stack[mapno] = &s->s_map; 63407c478bd9Sstevel@tonic-gate if (tTd(38, 4)) 63417c478bd9Sstevel@tonic-gate sm_dprintf("\tmap_stack[%d] = %s:%s\n", 63427c478bd9Sstevel@tonic-gate mapno, 63437c478bd9Sstevel@tonic-gate s->s_map.map_class->map_cname, 63447c478bd9Sstevel@tonic-gate nbuf); 63457c478bd9Sstevel@tonic-gate } 63467c478bd9Sstevel@tonic-gate } 63477c478bd9Sstevel@tonic-gate return true; 63487c478bd9Sstevel@tonic-gate } 63497c478bd9Sstevel@tonic-gate 63507c478bd9Sstevel@tonic-gate #if 0 63517c478bd9Sstevel@tonic-gate /* 63527c478bd9Sstevel@tonic-gate ** SEQ_MAP_CLOSE -- close all underlying maps 63537c478bd9Sstevel@tonic-gate */ 63547c478bd9Sstevel@tonic-gate 63557c478bd9Sstevel@tonic-gate void 63567c478bd9Sstevel@tonic-gate seq_map_close(map) 63577c478bd9Sstevel@tonic-gate MAP *map; 63587c478bd9Sstevel@tonic-gate { 63597c478bd9Sstevel@tonic-gate int mapno; 63607c478bd9Sstevel@tonic-gate 63617c478bd9Sstevel@tonic-gate if (tTd(38, 9)) 63627c478bd9Sstevel@tonic-gate sm_dprintf("seq_map_close(%s)\n", map->map_mname); 63637c478bd9Sstevel@tonic-gate 63647c478bd9Sstevel@tonic-gate for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 63657c478bd9Sstevel@tonic-gate { 63667c478bd9Sstevel@tonic-gate MAP *mm = map->map_stack[mapno]; 63677c478bd9Sstevel@tonic-gate 63687c478bd9Sstevel@tonic-gate if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) 63697c478bd9Sstevel@tonic-gate continue; 63707c478bd9Sstevel@tonic-gate mm->map_mflags |= MF_CLOSING; 63717c478bd9Sstevel@tonic-gate mm->map_class->map_close(mm); 63727c478bd9Sstevel@tonic-gate mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 63737c478bd9Sstevel@tonic-gate } 63747c478bd9Sstevel@tonic-gate } 63757c478bd9Sstevel@tonic-gate #endif /* 0 */ 63767c478bd9Sstevel@tonic-gate 63777c478bd9Sstevel@tonic-gate /* 63787c478bd9Sstevel@tonic-gate ** SEQ_MAP_LOOKUP -- sequenced map lookup 63797c478bd9Sstevel@tonic-gate */ 63807c478bd9Sstevel@tonic-gate 63817c478bd9Sstevel@tonic-gate char * 63827c478bd9Sstevel@tonic-gate seq_map_lookup(map, key, args, pstat) 63837c478bd9Sstevel@tonic-gate MAP *map; 63847c478bd9Sstevel@tonic-gate char *key; 63857c478bd9Sstevel@tonic-gate char **args; 63867c478bd9Sstevel@tonic-gate int *pstat; 63877c478bd9Sstevel@tonic-gate { 63887c478bd9Sstevel@tonic-gate int mapno; 63897c478bd9Sstevel@tonic-gate int mapbit = 0x01; 63907c478bd9Sstevel@tonic-gate bool tempfail = false; 63917c478bd9Sstevel@tonic-gate 63927c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 63937c478bd9Sstevel@tonic-gate sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key); 63947c478bd9Sstevel@tonic-gate 63957c478bd9Sstevel@tonic-gate for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++) 63967c478bd9Sstevel@tonic-gate { 63977c478bd9Sstevel@tonic-gate MAP *mm = map->map_stack[mapno]; 63987c478bd9Sstevel@tonic-gate char *rv; 63997c478bd9Sstevel@tonic-gate 64007c478bd9Sstevel@tonic-gate if (mm == NULL) 64017c478bd9Sstevel@tonic-gate continue; 64027c478bd9Sstevel@tonic-gate if (!bitset(MF_OPEN, mm->map_mflags) && 64037c478bd9Sstevel@tonic-gate !openmap(mm)) 64047c478bd9Sstevel@tonic-gate { 64057c478bd9Sstevel@tonic-gate if (bitset(mapbit, map->map_return[MA_UNAVAIL])) 64067c478bd9Sstevel@tonic-gate { 64077c478bd9Sstevel@tonic-gate *pstat = EX_UNAVAILABLE; 64087c478bd9Sstevel@tonic-gate return NULL; 64097c478bd9Sstevel@tonic-gate } 64107c478bd9Sstevel@tonic-gate continue; 64117c478bd9Sstevel@tonic-gate } 64127c478bd9Sstevel@tonic-gate *pstat = EX_OK; 64137c478bd9Sstevel@tonic-gate rv = mm->map_class->map_lookup(mm, key, args, pstat); 64147c478bd9Sstevel@tonic-gate if (rv != NULL) 64157c478bd9Sstevel@tonic-gate return rv; 64167c478bd9Sstevel@tonic-gate if (*pstat == EX_TEMPFAIL) 64177c478bd9Sstevel@tonic-gate { 64187c478bd9Sstevel@tonic-gate if (bitset(mapbit, map->map_return[MA_TRYAGAIN])) 64197c478bd9Sstevel@tonic-gate return NULL; 64207c478bd9Sstevel@tonic-gate tempfail = true; 64217c478bd9Sstevel@tonic-gate } 64227c478bd9Sstevel@tonic-gate else if (bitset(mapbit, map->map_return[MA_NOTFOUND])) 64237c478bd9Sstevel@tonic-gate break; 64247c478bd9Sstevel@tonic-gate } 64257c478bd9Sstevel@tonic-gate if (tempfail) 64267c478bd9Sstevel@tonic-gate *pstat = EX_TEMPFAIL; 64277c478bd9Sstevel@tonic-gate else if (*pstat == EX_OK) 64287c478bd9Sstevel@tonic-gate *pstat = EX_NOTFOUND; 64297c478bd9Sstevel@tonic-gate return NULL; 64307c478bd9Sstevel@tonic-gate } 64317c478bd9Sstevel@tonic-gate 64327c478bd9Sstevel@tonic-gate /* 64337c478bd9Sstevel@tonic-gate ** SEQ_MAP_STORE -- sequenced map store 64347c478bd9Sstevel@tonic-gate */ 64357c478bd9Sstevel@tonic-gate 64367c478bd9Sstevel@tonic-gate void 64377c478bd9Sstevel@tonic-gate seq_map_store(map, key, val) 64387c478bd9Sstevel@tonic-gate MAP *map; 64397c478bd9Sstevel@tonic-gate char *key; 64407c478bd9Sstevel@tonic-gate char *val; 64417c478bd9Sstevel@tonic-gate { 64427c478bd9Sstevel@tonic-gate int mapno; 64437c478bd9Sstevel@tonic-gate 64447c478bd9Sstevel@tonic-gate if (tTd(38, 12)) 64457c478bd9Sstevel@tonic-gate sm_dprintf("seq_map_store(%s, %s, %s)\n", 64467c478bd9Sstevel@tonic-gate map->map_mname, key, val); 64477c478bd9Sstevel@tonic-gate 64487c478bd9Sstevel@tonic-gate for (mapno = 0; mapno < MAXMAPSTACK; mapno++) 64497c478bd9Sstevel@tonic-gate { 64507c478bd9Sstevel@tonic-gate MAP *mm = map->map_stack[mapno]; 64517c478bd9Sstevel@tonic-gate 64527c478bd9Sstevel@tonic-gate if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags)) 64537c478bd9Sstevel@tonic-gate continue; 64547c478bd9Sstevel@tonic-gate 64557c478bd9Sstevel@tonic-gate mm->map_class->map_store(mm, key, val); 64567c478bd9Sstevel@tonic-gate return; 64577c478bd9Sstevel@tonic-gate } 64587c478bd9Sstevel@tonic-gate syserr("seq_map_store(%s, %s, %s): no writable map", 64597c478bd9Sstevel@tonic-gate map->map_mname, key, val); 64607c478bd9Sstevel@tonic-gate } 64617c478bd9Sstevel@tonic-gate /* 64627c478bd9Sstevel@tonic-gate ** NULL stubs 64637c478bd9Sstevel@tonic-gate */ 64647c478bd9Sstevel@tonic-gate 64657c478bd9Sstevel@tonic-gate /* ARGSUSED */ 64667c478bd9Sstevel@tonic-gate bool 64677c478bd9Sstevel@tonic-gate null_map_open(map, mode) 64687c478bd9Sstevel@tonic-gate MAP *map; 64697c478bd9Sstevel@tonic-gate int mode; 64707c478bd9Sstevel@tonic-gate { 64717c478bd9Sstevel@tonic-gate return true; 64727c478bd9Sstevel@tonic-gate } 64737c478bd9Sstevel@tonic-gate 64747c478bd9Sstevel@tonic-gate /* ARGSUSED */ 64757c478bd9Sstevel@tonic-gate void 64767c478bd9Sstevel@tonic-gate null_map_close(map) 64777c478bd9Sstevel@tonic-gate MAP *map; 64787c478bd9Sstevel@tonic-gate { 64797c478bd9Sstevel@tonic-gate return; 64807c478bd9Sstevel@tonic-gate } 64817c478bd9Sstevel@tonic-gate 64827c478bd9Sstevel@tonic-gate char * 64837c478bd9Sstevel@tonic-gate null_map_lookup(map, key, args, pstat) 64847c478bd9Sstevel@tonic-gate MAP *map; 64857c478bd9Sstevel@tonic-gate char *key; 64867c478bd9Sstevel@tonic-gate char **args; 64877c478bd9Sstevel@tonic-gate int *pstat; 64887c478bd9Sstevel@tonic-gate { 64897c478bd9Sstevel@tonic-gate *pstat = EX_NOTFOUND; 64907c478bd9Sstevel@tonic-gate return NULL; 64917c478bd9Sstevel@tonic-gate } 64927c478bd9Sstevel@tonic-gate 64937c478bd9Sstevel@tonic-gate /* ARGSUSED */ 64947c478bd9Sstevel@tonic-gate void 64957c478bd9Sstevel@tonic-gate null_map_store(map, key, val) 64967c478bd9Sstevel@tonic-gate MAP *map; 64977c478bd9Sstevel@tonic-gate char *key; 64987c478bd9Sstevel@tonic-gate char *val; 64997c478bd9Sstevel@tonic-gate { 65007c478bd9Sstevel@tonic-gate return; 65017c478bd9Sstevel@tonic-gate } 65027c478bd9Sstevel@tonic-gate 65037c478bd9Sstevel@tonic-gate /* 65047c478bd9Sstevel@tonic-gate ** BOGUS stubs 65057c478bd9Sstevel@tonic-gate */ 65067c478bd9Sstevel@tonic-gate 65077c478bd9Sstevel@tonic-gate char * 65087c478bd9Sstevel@tonic-gate bogus_map_lookup(map, key, args, pstat) 65097c478bd9Sstevel@tonic-gate MAP *map; 65107c478bd9Sstevel@tonic-gate char *key; 65117c478bd9Sstevel@tonic-gate char **args; 65127c478bd9Sstevel@tonic-gate int *pstat; 65137c478bd9Sstevel@tonic-gate { 65147c478bd9Sstevel@tonic-gate *pstat = EX_TEMPFAIL; 65157c478bd9Sstevel@tonic-gate return NULL; 65167c478bd9Sstevel@tonic-gate } 65177c478bd9Sstevel@tonic-gate 65187c478bd9Sstevel@tonic-gate MAPCLASS BogusMapClass = 65197c478bd9Sstevel@tonic-gate { 65207c478bd9Sstevel@tonic-gate "bogus-map", NULL, 0, 65217c478bd9Sstevel@tonic-gate NULL, bogus_map_lookup, null_map_store, 65227c478bd9Sstevel@tonic-gate null_map_open, null_map_close, 65237c478bd9Sstevel@tonic-gate }; 65247c478bd9Sstevel@tonic-gate /* 65257c478bd9Sstevel@tonic-gate ** MACRO modules 65267c478bd9Sstevel@tonic-gate */ 65277c478bd9Sstevel@tonic-gate 65287c478bd9Sstevel@tonic-gate char * 65297c478bd9Sstevel@tonic-gate macro_map_lookup(map, name, av, statp) 65307c478bd9Sstevel@tonic-gate MAP *map; 65317c478bd9Sstevel@tonic-gate char *name; 65327c478bd9Sstevel@tonic-gate char **av; 65337c478bd9Sstevel@tonic-gate int *statp; 65347c478bd9Sstevel@tonic-gate { 65357c478bd9Sstevel@tonic-gate int mid; 65367c478bd9Sstevel@tonic-gate 65377c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 65387c478bd9Sstevel@tonic-gate sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, 65397c478bd9Sstevel@tonic-gate name == NULL ? "NULL" : name); 65407c478bd9Sstevel@tonic-gate 65417c478bd9Sstevel@tonic-gate if (name == NULL || 65427c478bd9Sstevel@tonic-gate *name == '\0' || 65437c478bd9Sstevel@tonic-gate (mid = macid(name)) == 0) 65447c478bd9Sstevel@tonic-gate { 65457c478bd9Sstevel@tonic-gate *statp = EX_CONFIG; 65467c478bd9Sstevel@tonic-gate return NULL; 65477c478bd9Sstevel@tonic-gate } 65487c478bd9Sstevel@tonic-gate 65497c478bd9Sstevel@tonic-gate if (av[1] == NULL) 65507c478bd9Sstevel@tonic-gate macdefine(&CurEnv->e_macro, A_PERM, mid, NULL); 65517c478bd9Sstevel@tonic-gate else 65527c478bd9Sstevel@tonic-gate macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]); 65537c478bd9Sstevel@tonic-gate 65547c478bd9Sstevel@tonic-gate *statp = EX_OK; 65557c478bd9Sstevel@tonic-gate return ""; 65567c478bd9Sstevel@tonic-gate } 65577c478bd9Sstevel@tonic-gate /* 65587c478bd9Sstevel@tonic-gate ** REGEX modules 65597c478bd9Sstevel@tonic-gate */ 65607c478bd9Sstevel@tonic-gate 65617c478bd9Sstevel@tonic-gate #if MAP_REGEX 65627c478bd9Sstevel@tonic-gate 65637c478bd9Sstevel@tonic-gate # include <regex.h> 65647c478bd9Sstevel@tonic-gate 65657c478bd9Sstevel@tonic-gate # define DEFAULT_DELIM CONDELSE 65667c478bd9Sstevel@tonic-gate # define END_OF_FIELDS -1 65677c478bd9Sstevel@tonic-gate # define ERRBUF_SIZE 80 65687c478bd9Sstevel@tonic-gate # define MAX_MATCH 32 65697c478bd9Sstevel@tonic-gate 65707c478bd9Sstevel@tonic-gate # define xnalloc(s) memset(xalloc(s), '\0', s); 65717c478bd9Sstevel@tonic-gate 65727c478bd9Sstevel@tonic-gate struct regex_map 65737c478bd9Sstevel@tonic-gate { 65747c478bd9Sstevel@tonic-gate regex_t *regex_pattern_buf; /* xalloc it */ 65757c478bd9Sstevel@tonic-gate int *regex_subfields; /* move to type MAP */ 65767c478bd9Sstevel@tonic-gate char *regex_delim; /* move to type MAP */ 65777c478bd9Sstevel@tonic-gate }; 65787c478bd9Sstevel@tonic-gate 65797c478bd9Sstevel@tonic-gate static int parse_fields __P((char *, int *, int, int)); 65807c478bd9Sstevel@tonic-gate static char *regex_map_rewrite __P((MAP *, const char*, size_t, char **)); 65817c478bd9Sstevel@tonic-gate 65827c478bd9Sstevel@tonic-gate static int 65837c478bd9Sstevel@tonic-gate parse_fields(s, ibuf, blen, nr_substrings) 65847c478bd9Sstevel@tonic-gate char *s; 65857c478bd9Sstevel@tonic-gate int *ibuf; /* array */ 65867c478bd9Sstevel@tonic-gate int blen; /* number of elements in ibuf */ 65877c478bd9Sstevel@tonic-gate int nr_substrings; /* number of substrings in the pattern */ 65887c478bd9Sstevel@tonic-gate { 65897c478bd9Sstevel@tonic-gate register char *cp; 65907c478bd9Sstevel@tonic-gate int i = 0; 65917c478bd9Sstevel@tonic-gate bool lastone = false; 65927c478bd9Sstevel@tonic-gate 65937c478bd9Sstevel@tonic-gate blen--; /* for terminating END_OF_FIELDS */ 65947c478bd9Sstevel@tonic-gate cp = s; 65957c478bd9Sstevel@tonic-gate do 65967c478bd9Sstevel@tonic-gate { 65977c478bd9Sstevel@tonic-gate for (;; cp++) 65987c478bd9Sstevel@tonic-gate { 65997c478bd9Sstevel@tonic-gate if (*cp == ',') 66007c478bd9Sstevel@tonic-gate { 66017c478bd9Sstevel@tonic-gate *cp = '\0'; 66027c478bd9Sstevel@tonic-gate break; 66037c478bd9Sstevel@tonic-gate } 66047c478bd9Sstevel@tonic-gate if (*cp == '\0') 66057c478bd9Sstevel@tonic-gate { 66067c478bd9Sstevel@tonic-gate lastone = true; 66077c478bd9Sstevel@tonic-gate break; 66087c478bd9Sstevel@tonic-gate } 66097c478bd9Sstevel@tonic-gate } 66107c478bd9Sstevel@tonic-gate if (i < blen) 66117c478bd9Sstevel@tonic-gate { 66127c478bd9Sstevel@tonic-gate int val = atoi(s); 66137c478bd9Sstevel@tonic-gate 66147c478bd9Sstevel@tonic-gate if (val < 0 || val >= nr_substrings) 66157c478bd9Sstevel@tonic-gate { 66167c478bd9Sstevel@tonic-gate syserr("field (%d) out of range, only %d substrings in pattern", 66177c478bd9Sstevel@tonic-gate val, nr_substrings); 66187c478bd9Sstevel@tonic-gate return -1; 66197c478bd9Sstevel@tonic-gate } 66207c478bd9Sstevel@tonic-gate ibuf[i++] = val; 66217c478bd9Sstevel@tonic-gate } 66227c478bd9Sstevel@tonic-gate else 66237c478bd9Sstevel@tonic-gate { 66247c478bd9Sstevel@tonic-gate syserr("too many fields, %d max", blen); 66257c478bd9Sstevel@tonic-gate return -1; 66267c478bd9Sstevel@tonic-gate } 66277c478bd9Sstevel@tonic-gate s = ++cp; 66287c478bd9Sstevel@tonic-gate } while (!lastone); 66297c478bd9Sstevel@tonic-gate ibuf[i] = END_OF_FIELDS; 66307c478bd9Sstevel@tonic-gate return i; 66317c478bd9Sstevel@tonic-gate } 66327c478bd9Sstevel@tonic-gate 66337c478bd9Sstevel@tonic-gate bool 66347c478bd9Sstevel@tonic-gate regex_map_init(map, ap) 66357c478bd9Sstevel@tonic-gate MAP *map; 66367c478bd9Sstevel@tonic-gate char *ap; 66377c478bd9Sstevel@tonic-gate { 66387c478bd9Sstevel@tonic-gate int regerr; 66397c478bd9Sstevel@tonic-gate struct regex_map *map_p; 66407c478bd9Sstevel@tonic-gate register char *p; 66417c478bd9Sstevel@tonic-gate char *sub_param = NULL; 66427c478bd9Sstevel@tonic-gate int pflags; 66437c478bd9Sstevel@tonic-gate static char defdstr[] = { (char) DEFAULT_DELIM, '\0' }; 66447c478bd9Sstevel@tonic-gate 66457c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 66467c478bd9Sstevel@tonic-gate sm_dprintf("regex_map_init: mapname '%s', args '%s'\n", 66477c478bd9Sstevel@tonic-gate map->map_mname, ap); 66487c478bd9Sstevel@tonic-gate 66497c478bd9Sstevel@tonic-gate pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; 66507c478bd9Sstevel@tonic-gate p = ap; 66517c478bd9Sstevel@tonic-gate map_p = (struct regex_map *) xnalloc(sizeof *map_p); 66527c478bd9Sstevel@tonic-gate map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t)); 66537c478bd9Sstevel@tonic-gate 66547c478bd9Sstevel@tonic-gate for (;;) 66557c478bd9Sstevel@tonic-gate { 66567c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 66577c478bd9Sstevel@tonic-gate p++; 66587c478bd9Sstevel@tonic-gate if (*p != '-') 66597c478bd9Sstevel@tonic-gate break; 66607c478bd9Sstevel@tonic-gate switch (*++p) 66617c478bd9Sstevel@tonic-gate { 66627c478bd9Sstevel@tonic-gate case 'n': /* not */ 66637c478bd9Sstevel@tonic-gate map->map_mflags |= MF_REGEX_NOT; 66647c478bd9Sstevel@tonic-gate break; 66657c478bd9Sstevel@tonic-gate 66667c478bd9Sstevel@tonic-gate case 'f': /* case sensitive */ 66677c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NOFOLDCASE; 66687c478bd9Sstevel@tonic-gate pflags &= ~REG_ICASE; 66697c478bd9Sstevel@tonic-gate break; 66707c478bd9Sstevel@tonic-gate 66717c478bd9Sstevel@tonic-gate case 'b': /* basic regular expressions */ 66727c478bd9Sstevel@tonic-gate pflags &= ~REG_EXTENDED; 66737c478bd9Sstevel@tonic-gate break; 66747c478bd9Sstevel@tonic-gate 66757c478bd9Sstevel@tonic-gate case 's': /* substring match () syntax */ 66767c478bd9Sstevel@tonic-gate sub_param = ++p; 66777c478bd9Sstevel@tonic-gate pflags &= ~REG_NOSUB; 66787c478bd9Sstevel@tonic-gate break; 66797c478bd9Sstevel@tonic-gate 66807c478bd9Sstevel@tonic-gate case 'd': /* delimiter */ 66817c478bd9Sstevel@tonic-gate map_p->regex_delim = ++p; 66827c478bd9Sstevel@tonic-gate break; 66837c478bd9Sstevel@tonic-gate 66847c478bd9Sstevel@tonic-gate case 'a': /* map append */ 66857c478bd9Sstevel@tonic-gate map->map_app = ++p; 66867c478bd9Sstevel@tonic-gate break; 66877c478bd9Sstevel@tonic-gate 66887c478bd9Sstevel@tonic-gate case 'm': /* matchonly */ 66897c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 66907c478bd9Sstevel@tonic-gate break; 66917c478bd9Sstevel@tonic-gate 66927c478bd9Sstevel@tonic-gate case 'q': 66937c478bd9Sstevel@tonic-gate map->map_mflags |= MF_KEEPQUOTES; 66947c478bd9Sstevel@tonic-gate break; 66957c478bd9Sstevel@tonic-gate 66967c478bd9Sstevel@tonic-gate case 'S': 66977c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 66987c478bd9Sstevel@tonic-gate break; 66997c478bd9Sstevel@tonic-gate 67007c478bd9Sstevel@tonic-gate case 'D': 67017c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 67027c478bd9Sstevel@tonic-gate break; 67037c478bd9Sstevel@tonic-gate 67047c478bd9Sstevel@tonic-gate } 67057c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 67067c478bd9Sstevel@tonic-gate p++; 67077c478bd9Sstevel@tonic-gate if (*p != '\0') 67087c478bd9Sstevel@tonic-gate *p++ = '\0'; 67097c478bd9Sstevel@tonic-gate } 67107c478bd9Sstevel@tonic-gate if (tTd(38, 3)) 67117c478bd9Sstevel@tonic-gate sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); 67127c478bd9Sstevel@tonic-gate 67137c478bd9Sstevel@tonic-gate if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0) 67147c478bd9Sstevel@tonic-gate { 67157c478bd9Sstevel@tonic-gate /* Errorhandling */ 67167c478bd9Sstevel@tonic-gate char errbuf[ERRBUF_SIZE]; 67177c478bd9Sstevel@tonic-gate 67187c478bd9Sstevel@tonic-gate (void) regerror(regerr, map_p->regex_pattern_buf, 67197c478bd9Sstevel@tonic-gate errbuf, sizeof errbuf); 67207c478bd9Sstevel@tonic-gate syserr("pattern-compile-error: %s", errbuf); 67217c478bd9Sstevel@tonic-gate sm_free(map_p->regex_pattern_buf); /* XXX */ 67227c478bd9Sstevel@tonic-gate sm_free(map_p); /* XXX */ 67237c478bd9Sstevel@tonic-gate return false; 67247c478bd9Sstevel@tonic-gate } 67257c478bd9Sstevel@tonic-gate 67267c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 67277c478bd9Sstevel@tonic-gate map->map_app = newstr(map->map_app); 67287c478bd9Sstevel@tonic-gate if (map_p->regex_delim != NULL) 67297c478bd9Sstevel@tonic-gate map_p->regex_delim = newstr(map_p->regex_delim); 67307c478bd9Sstevel@tonic-gate else 67317c478bd9Sstevel@tonic-gate map_p->regex_delim = defdstr; 67327c478bd9Sstevel@tonic-gate 67337c478bd9Sstevel@tonic-gate if (!bitset(REG_NOSUB, pflags)) 67347c478bd9Sstevel@tonic-gate { 67357c478bd9Sstevel@tonic-gate /* substring matching */ 67367c478bd9Sstevel@tonic-gate int substrings; 67377c478bd9Sstevel@tonic-gate int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); 67387c478bd9Sstevel@tonic-gate 67397c478bd9Sstevel@tonic-gate substrings = map_p->regex_pattern_buf->re_nsub + 1; 67407c478bd9Sstevel@tonic-gate 67417c478bd9Sstevel@tonic-gate if (tTd(38, 3)) 67427c478bd9Sstevel@tonic-gate sm_dprintf("regex_map_init: nr of substrings %d\n", 67437c478bd9Sstevel@tonic-gate substrings); 67447c478bd9Sstevel@tonic-gate 67457c478bd9Sstevel@tonic-gate if (substrings >= MAX_MATCH) 67467c478bd9Sstevel@tonic-gate { 67477c478bd9Sstevel@tonic-gate syserr("too many substrings, %d max", MAX_MATCH); 67487c478bd9Sstevel@tonic-gate sm_free(map_p->regex_pattern_buf); /* XXX */ 67497c478bd9Sstevel@tonic-gate sm_free(map_p); /* XXX */ 67507c478bd9Sstevel@tonic-gate return false; 67517c478bd9Sstevel@tonic-gate } 67527c478bd9Sstevel@tonic-gate if (sub_param != NULL && sub_param[0] != '\0') 67537c478bd9Sstevel@tonic-gate { 67547c478bd9Sstevel@tonic-gate /* optional parameter -sfields */ 67557c478bd9Sstevel@tonic-gate if (parse_fields(sub_param, fields, 67567c478bd9Sstevel@tonic-gate MAX_MATCH + 1, substrings) == -1) 67577c478bd9Sstevel@tonic-gate return false; 67587c478bd9Sstevel@tonic-gate } 67597c478bd9Sstevel@tonic-gate else 67607c478bd9Sstevel@tonic-gate { 67617c478bd9Sstevel@tonic-gate int i; 67627c478bd9Sstevel@tonic-gate 67637c478bd9Sstevel@tonic-gate /* set default fields */ 67647c478bd9Sstevel@tonic-gate for (i = 0; i < substrings; i++) 67657c478bd9Sstevel@tonic-gate fields[i] = i; 67667c478bd9Sstevel@tonic-gate fields[i] = END_OF_FIELDS; 67677c478bd9Sstevel@tonic-gate } 67687c478bd9Sstevel@tonic-gate map_p->regex_subfields = fields; 67697c478bd9Sstevel@tonic-gate if (tTd(38, 3)) 67707c478bd9Sstevel@tonic-gate { 67717c478bd9Sstevel@tonic-gate int *ip; 67727c478bd9Sstevel@tonic-gate 67737c478bd9Sstevel@tonic-gate sm_dprintf("regex_map_init: subfields"); 67747c478bd9Sstevel@tonic-gate for (ip = fields; *ip != END_OF_FIELDS; ip++) 67757c478bd9Sstevel@tonic-gate sm_dprintf(" %d", *ip); 67767c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 67777c478bd9Sstevel@tonic-gate } 67787c478bd9Sstevel@tonic-gate } 67797c478bd9Sstevel@tonic-gate map->map_db1 = (ARBPTR_T) map_p; /* dirty hack */ 67807c478bd9Sstevel@tonic-gate return true; 67817c478bd9Sstevel@tonic-gate } 67827c478bd9Sstevel@tonic-gate 67837c478bd9Sstevel@tonic-gate static char * 67847c478bd9Sstevel@tonic-gate regex_map_rewrite(map, s, slen, av) 67857c478bd9Sstevel@tonic-gate MAP *map; 67867c478bd9Sstevel@tonic-gate const char *s; 67877c478bd9Sstevel@tonic-gate size_t slen; 67887c478bd9Sstevel@tonic-gate char **av; 67897c478bd9Sstevel@tonic-gate { 67907c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 67917c478bd9Sstevel@tonic-gate return map_rewrite(map, av[0], strlen(av[0]), NULL); 67927c478bd9Sstevel@tonic-gate else 67937c478bd9Sstevel@tonic-gate return map_rewrite(map, s, slen, av); 67947c478bd9Sstevel@tonic-gate } 67957c478bd9Sstevel@tonic-gate 67967c478bd9Sstevel@tonic-gate char * 67977c478bd9Sstevel@tonic-gate regex_map_lookup(map, name, av, statp) 67987c478bd9Sstevel@tonic-gate MAP *map; 67997c478bd9Sstevel@tonic-gate char *name; 68007c478bd9Sstevel@tonic-gate char **av; 68017c478bd9Sstevel@tonic-gate int *statp; 68027c478bd9Sstevel@tonic-gate { 68037c478bd9Sstevel@tonic-gate int reg_res; 68047c478bd9Sstevel@tonic-gate struct regex_map *map_p; 68057c478bd9Sstevel@tonic-gate regmatch_t pmatch[MAX_MATCH]; 68067c478bd9Sstevel@tonic-gate 68077c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 68087c478bd9Sstevel@tonic-gate { 68097c478bd9Sstevel@tonic-gate char **cpp; 68107c478bd9Sstevel@tonic-gate 68117c478bd9Sstevel@tonic-gate sm_dprintf("regex_map_lookup: key '%s'\n", name); 68127c478bd9Sstevel@tonic-gate for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 68137c478bd9Sstevel@tonic-gate sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp); 68147c478bd9Sstevel@tonic-gate } 68157c478bd9Sstevel@tonic-gate 68167c478bd9Sstevel@tonic-gate map_p = (struct regex_map *)(map->map_db1); 68177c478bd9Sstevel@tonic-gate reg_res = regexec(map_p->regex_pattern_buf, 68187c478bd9Sstevel@tonic-gate name, MAX_MATCH, pmatch, 0); 68197c478bd9Sstevel@tonic-gate 68207c478bd9Sstevel@tonic-gate if (bitset(MF_REGEX_NOT, map->map_mflags)) 68217c478bd9Sstevel@tonic-gate { 68227c478bd9Sstevel@tonic-gate /* option -n */ 68237c478bd9Sstevel@tonic-gate if (reg_res == REG_NOMATCH) 68247c478bd9Sstevel@tonic-gate return regex_map_rewrite(map, "", (size_t) 0, av); 68257c478bd9Sstevel@tonic-gate else 68267c478bd9Sstevel@tonic-gate return NULL; 68277c478bd9Sstevel@tonic-gate } 68287c478bd9Sstevel@tonic-gate if (reg_res == REG_NOMATCH) 68297c478bd9Sstevel@tonic-gate return NULL; 68307c478bd9Sstevel@tonic-gate 68317c478bd9Sstevel@tonic-gate if (map_p->regex_subfields != NULL) 68327c478bd9Sstevel@tonic-gate { 68337c478bd9Sstevel@tonic-gate /* option -s */ 68347c478bd9Sstevel@tonic-gate static char retbuf[MAXNAME]; 68357c478bd9Sstevel@tonic-gate int fields[MAX_MATCH + 1]; 68367c478bd9Sstevel@tonic-gate bool first = true; 68377c478bd9Sstevel@tonic-gate int anglecnt = 0, cmntcnt = 0, spacecnt = 0; 68387c478bd9Sstevel@tonic-gate bool quotemode = false, bslashmode = false; 68397c478bd9Sstevel@tonic-gate register char *dp, *sp; 68407c478bd9Sstevel@tonic-gate char *endp, *ldp; 68417c478bd9Sstevel@tonic-gate int *ip; 68427c478bd9Sstevel@tonic-gate 68437c478bd9Sstevel@tonic-gate dp = retbuf; 68447c478bd9Sstevel@tonic-gate ldp = retbuf + sizeof(retbuf) - 1; 68457c478bd9Sstevel@tonic-gate 68467c478bd9Sstevel@tonic-gate if (av[1] != NULL) 68477c478bd9Sstevel@tonic-gate { 68487c478bd9Sstevel@tonic-gate if (parse_fields(av[1], fields, MAX_MATCH + 1, 68497c478bd9Sstevel@tonic-gate (int) map_p->regex_pattern_buf->re_nsub + 1) == -1) 68507c478bd9Sstevel@tonic-gate { 68517c478bd9Sstevel@tonic-gate *statp = EX_CONFIG; 68527c478bd9Sstevel@tonic-gate return NULL; 68537c478bd9Sstevel@tonic-gate } 68547c478bd9Sstevel@tonic-gate ip = fields; 68557c478bd9Sstevel@tonic-gate } 68567c478bd9Sstevel@tonic-gate else 68577c478bd9Sstevel@tonic-gate ip = map_p->regex_subfields; 68587c478bd9Sstevel@tonic-gate 68597c478bd9Sstevel@tonic-gate for ( ; *ip != END_OF_FIELDS; ip++) 68607c478bd9Sstevel@tonic-gate { 68617c478bd9Sstevel@tonic-gate if (!first) 68627c478bd9Sstevel@tonic-gate { 68637c478bd9Sstevel@tonic-gate for (sp = map_p->regex_delim; *sp; sp++) 68647c478bd9Sstevel@tonic-gate { 68657c478bd9Sstevel@tonic-gate if (dp < ldp) 68667c478bd9Sstevel@tonic-gate *dp++ = *sp; 68677c478bd9Sstevel@tonic-gate } 68687c478bd9Sstevel@tonic-gate } 68697c478bd9Sstevel@tonic-gate else 68707c478bd9Sstevel@tonic-gate first = false; 68717c478bd9Sstevel@tonic-gate 68727c478bd9Sstevel@tonic-gate if (*ip >= MAX_MATCH || 68737c478bd9Sstevel@tonic-gate pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) 68747c478bd9Sstevel@tonic-gate continue; 68757c478bd9Sstevel@tonic-gate 68767c478bd9Sstevel@tonic-gate sp = name + pmatch[*ip].rm_so; 68777c478bd9Sstevel@tonic-gate endp = name + pmatch[*ip].rm_eo; 68787c478bd9Sstevel@tonic-gate for (; endp > sp; sp++) 68797c478bd9Sstevel@tonic-gate { 68807c478bd9Sstevel@tonic-gate if (dp < ldp) 68817c478bd9Sstevel@tonic-gate { 68827c478bd9Sstevel@tonic-gate if (bslashmode) 68837c478bd9Sstevel@tonic-gate { 68847c478bd9Sstevel@tonic-gate *dp++ = *sp; 68857c478bd9Sstevel@tonic-gate bslashmode = false; 68867c478bd9Sstevel@tonic-gate } 68877c478bd9Sstevel@tonic-gate else if (quotemode && *sp != '"' && 68887c478bd9Sstevel@tonic-gate *sp != '\\') 68897c478bd9Sstevel@tonic-gate { 68907c478bd9Sstevel@tonic-gate *dp++ = *sp; 68917c478bd9Sstevel@tonic-gate } 68927c478bd9Sstevel@tonic-gate else switch (*dp++ = *sp) 68937c478bd9Sstevel@tonic-gate { 68947c478bd9Sstevel@tonic-gate case '\\': 68957c478bd9Sstevel@tonic-gate bslashmode = true; 68967c478bd9Sstevel@tonic-gate break; 68977c478bd9Sstevel@tonic-gate 68987c478bd9Sstevel@tonic-gate case '(': 68997c478bd9Sstevel@tonic-gate cmntcnt++; 69007c478bd9Sstevel@tonic-gate break; 69017c478bd9Sstevel@tonic-gate 69027c478bd9Sstevel@tonic-gate case ')': 69037c478bd9Sstevel@tonic-gate cmntcnt--; 69047c478bd9Sstevel@tonic-gate break; 69057c478bd9Sstevel@tonic-gate 69067c478bd9Sstevel@tonic-gate case '<': 69077c478bd9Sstevel@tonic-gate anglecnt++; 69087c478bd9Sstevel@tonic-gate break; 69097c478bd9Sstevel@tonic-gate 69107c478bd9Sstevel@tonic-gate case '>': 69117c478bd9Sstevel@tonic-gate anglecnt--; 69127c478bd9Sstevel@tonic-gate break; 69137c478bd9Sstevel@tonic-gate 69147c478bd9Sstevel@tonic-gate case ' ': 69157c478bd9Sstevel@tonic-gate spacecnt++; 69167c478bd9Sstevel@tonic-gate break; 69177c478bd9Sstevel@tonic-gate 69187c478bd9Sstevel@tonic-gate case '"': 69197c478bd9Sstevel@tonic-gate quotemode = !quotemode; 69207c478bd9Sstevel@tonic-gate break; 69217c478bd9Sstevel@tonic-gate } 69227c478bd9Sstevel@tonic-gate } 69237c478bd9Sstevel@tonic-gate } 69247c478bd9Sstevel@tonic-gate } 69257c478bd9Sstevel@tonic-gate if (anglecnt != 0 || cmntcnt != 0 || quotemode || 69267c478bd9Sstevel@tonic-gate bslashmode || spacecnt != 0) 69277c478bd9Sstevel@tonic-gate { 69287c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 69297c478bd9Sstevel@tonic-gate "Warning: regex may cause prescan() failure map=%s lookup=%s", 69307c478bd9Sstevel@tonic-gate map->map_mname, name); 69317c478bd9Sstevel@tonic-gate return NULL; 69327c478bd9Sstevel@tonic-gate } 69337c478bd9Sstevel@tonic-gate 69347c478bd9Sstevel@tonic-gate *dp = '\0'; 69357c478bd9Sstevel@tonic-gate 69367c478bd9Sstevel@tonic-gate return regex_map_rewrite(map, retbuf, strlen(retbuf), av); 69377c478bd9Sstevel@tonic-gate } 69387c478bd9Sstevel@tonic-gate return regex_map_rewrite(map, "", (size_t)0, av); 69397c478bd9Sstevel@tonic-gate } 69407c478bd9Sstevel@tonic-gate #endif /* MAP_REGEX */ 69417c478bd9Sstevel@tonic-gate /* 69427c478bd9Sstevel@tonic-gate ** NSD modules 69437c478bd9Sstevel@tonic-gate */ 69447c478bd9Sstevel@tonic-gate #if MAP_NSD 69457c478bd9Sstevel@tonic-gate 69467c478bd9Sstevel@tonic-gate # include <ndbm.h> 69477c478bd9Sstevel@tonic-gate # define _DATUM_DEFINED 69487c478bd9Sstevel@tonic-gate # include <ns_api.h> 69497c478bd9Sstevel@tonic-gate 69507c478bd9Sstevel@tonic-gate typedef struct ns_map_list 69517c478bd9Sstevel@tonic-gate { 69527c478bd9Sstevel@tonic-gate ns_map_t *map; /* XXX ns_ ? */ 69537c478bd9Sstevel@tonic-gate char *mapname; 69547c478bd9Sstevel@tonic-gate struct ns_map_list *next; 69557c478bd9Sstevel@tonic-gate } ns_map_list_t; 69567c478bd9Sstevel@tonic-gate 69577c478bd9Sstevel@tonic-gate static ns_map_t * 69587c478bd9Sstevel@tonic-gate ns_map_t_find(mapname) 69597c478bd9Sstevel@tonic-gate char *mapname; 69607c478bd9Sstevel@tonic-gate { 69617c478bd9Sstevel@tonic-gate static ns_map_list_t *ns_maps = NULL; 69627c478bd9Sstevel@tonic-gate ns_map_list_t *ns_map; 69637c478bd9Sstevel@tonic-gate 69647c478bd9Sstevel@tonic-gate /* walk the list of maps looking for the correctly named map */ 69657c478bd9Sstevel@tonic-gate for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) 69667c478bd9Sstevel@tonic-gate { 69677c478bd9Sstevel@tonic-gate if (strcmp(ns_map->mapname, mapname) == 0) 69687c478bd9Sstevel@tonic-gate break; 69697c478bd9Sstevel@tonic-gate } 69707c478bd9Sstevel@tonic-gate 69717c478bd9Sstevel@tonic-gate /* if we are looking at a NULL ns_map_list_t, then create a new one */ 69727c478bd9Sstevel@tonic-gate if (ns_map == NULL) 69737c478bd9Sstevel@tonic-gate { 69747c478bd9Sstevel@tonic-gate ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); 69757c478bd9Sstevel@tonic-gate ns_map->mapname = newstr(mapname); 69767c478bd9Sstevel@tonic-gate ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); 69777c478bd9Sstevel@tonic-gate memset(ns_map->map, '\0', sizeof *ns_map->map); 69787c478bd9Sstevel@tonic-gate ns_map->next = ns_maps; 69797c478bd9Sstevel@tonic-gate ns_maps = ns_map; 69807c478bd9Sstevel@tonic-gate } 69817c478bd9Sstevel@tonic-gate return ns_map->map; 69827c478bd9Sstevel@tonic-gate } 69837c478bd9Sstevel@tonic-gate 69847c478bd9Sstevel@tonic-gate char * 69857c478bd9Sstevel@tonic-gate nsd_map_lookup(map, name, av, statp) 69867c478bd9Sstevel@tonic-gate MAP *map; 69877c478bd9Sstevel@tonic-gate char *name; 69887c478bd9Sstevel@tonic-gate char **av; 69897c478bd9Sstevel@tonic-gate int *statp; 69907c478bd9Sstevel@tonic-gate { 69917c478bd9Sstevel@tonic-gate int buflen, r; 69927c478bd9Sstevel@tonic-gate char *p; 69937c478bd9Sstevel@tonic-gate ns_map_t *ns_map; 69947c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 69957c478bd9Sstevel@tonic-gate char buf[MAXLINE]; 69967c478bd9Sstevel@tonic-gate 69977c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 69987c478bd9Sstevel@tonic-gate sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); 69997c478bd9Sstevel@tonic-gate 70007c478bd9Sstevel@tonic-gate buflen = strlen(name); 70017c478bd9Sstevel@tonic-gate if (buflen > sizeof keybuf - 1) 70027c478bd9Sstevel@tonic-gate buflen = sizeof keybuf - 1; /* XXX simply cut off? */ 70037c478bd9Sstevel@tonic-gate memmove(keybuf, name, buflen); 70047c478bd9Sstevel@tonic-gate keybuf[buflen] = '\0'; 70057c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 70067c478bd9Sstevel@tonic-gate makelower(keybuf); 70077c478bd9Sstevel@tonic-gate 70087c478bd9Sstevel@tonic-gate ns_map = ns_map_t_find(map->map_file); 70097c478bd9Sstevel@tonic-gate if (ns_map == NULL) 70107c478bd9Sstevel@tonic-gate { 70117c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 70127c478bd9Sstevel@tonic-gate sm_dprintf("nsd_map_t_find failed\n"); 70137c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 70147c478bd9Sstevel@tonic-gate return NULL; 70157c478bd9Sstevel@tonic-gate } 70167c478bd9Sstevel@tonic-gate r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL, 70177c478bd9Sstevel@tonic-gate buf, sizeof buf); 70187c478bd9Sstevel@tonic-gate if (r == NS_UNAVAIL || r == NS_TRYAGAIN) 70197c478bd9Sstevel@tonic-gate { 70207c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 70217c478bd9Sstevel@tonic-gate return NULL; 70227c478bd9Sstevel@tonic-gate } 70237c478bd9Sstevel@tonic-gate if (r == NS_BADREQ 70247c478bd9Sstevel@tonic-gate # ifdef NS_NOPERM 70257c478bd9Sstevel@tonic-gate || r == NS_NOPERM 70267c478bd9Sstevel@tonic-gate # endif /* NS_NOPERM */ 70277c478bd9Sstevel@tonic-gate ) 70287c478bd9Sstevel@tonic-gate { 70297c478bd9Sstevel@tonic-gate *statp = EX_CONFIG; 70307c478bd9Sstevel@tonic-gate return NULL; 70317c478bd9Sstevel@tonic-gate } 70327c478bd9Sstevel@tonic-gate if (r != NS_SUCCESS) 70337c478bd9Sstevel@tonic-gate { 70347c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 70357c478bd9Sstevel@tonic-gate return NULL; 70367c478bd9Sstevel@tonic-gate } 70377c478bd9Sstevel@tonic-gate 70387c478bd9Sstevel@tonic-gate *statp = EX_OK; 70397c478bd9Sstevel@tonic-gate 70407c478bd9Sstevel@tonic-gate /* Null out trailing \n */ 70417c478bd9Sstevel@tonic-gate if ((p = strchr(buf, '\n')) != NULL) 70427c478bd9Sstevel@tonic-gate *p = '\0'; 70437c478bd9Sstevel@tonic-gate 70447c478bd9Sstevel@tonic-gate return map_rewrite(map, buf, strlen(buf), av); 70457c478bd9Sstevel@tonic-gate } 70467c478bd9Sstevel@tonic-gate #endif /* MAP_NSD */ 70477c478bd9Sstevel@tonic-gate 70487c478bd9Sstevel@tonic-gate char * 70497c478bd9Sstevel@tonic-gate arith_map_lookup(map, name, av, statp) 70507c478bd9Sstevel@tonic-gate MAP *map; 70517c478bd9Sstevel@tonic-gate char *name; 70527c478bd9Sstevel@tonic-gate char **av; 70537c478bd9Sstevel@tonic-gate int *statp; 70547c478bd9Sstevel@tonic-gate { 70557c478bd9Sstevel@tonic-gate long r; 70567c478bd9Sstevel@tonic-gate long v[2]; 70577c478bd9Sstevel@tonic-gate bool res = false; 70587c478bd9Sstevel@tonic-gate bool boolres; 70597c478bd9Sstevel@tonic-gate static char result[16]; 70607c478bd9Sstevel@tonic-gate char **cpp; 70617c478bd9Sstevel@tonic-gate 70627c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 70637c478bd9Sstevel@tonic-gate { 70647c478bd9Sstevel@tonic-gate sm_dprintf("arith_map_lookup: key '%s'\n", name); 70657c478bd9Sstevel@tonic-gate for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) 70667c478bd9Sstevel@tonic-gate sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp); 70677c478bd9Sstevel@tonic-gate } 70687c478bd9Sstevel@tonic-gate r = 0; 70697c478bd9Sstevel@tonic-gate boolres = false; 70707c478bd9Sstevel@tonic-gate cpp = av; 70717c478bd9Sstevel@tonic-gate *statp = EX_OK; 70727c478bd9Sstevel@tonic-gate 70737c478bd9Sstevel@tonic-gate /* 70747c478bd9Sstevel@tonic-gate ** read arguments for arith map 70757c478bd9Sstevel@tonic-gate ** - no check is made whether they are really numbers 70767c478bd9Sstevel@tonic-gate ** - just ignores args after the second 70777c478bd9Sstevel@tonic-gate */ 70787c478bd9Sstevel@tonic-gate 70797c478bd9Sstevel@tonic-gate for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) 70807c478bd9Sstevel@tonic-gate v[r++] = strtol(*cpp, NULL, 0); 70817c478bd9Sstevel@tonic-gate 70827c478bd9Sstevel@tonic-gate /* operator and (at least) two operands given? */ 70837c478bd9Sstevel@tonic-gate if (name != NULL && r == 2) 70847c478bd9Sstevel@tonic-gate { 70857c478bd9Sstevel@tonic-gate switch (*name) 70867c478bd9Sstevel@tonic-gate { 70877c478bd9Sstevel@tonic-gate case '|': 70887c478bd9Sstevel@tonic-gate r = v[0] | v[1]; 70897c478bd9Sstevel@tonic-gate break; 70907c478bd9Sstevel@tonic-gate 70917c478bd9Sstevel@tonic-gate case '&': 70927c478bd9Sstevel@tonic-gate r = v[0] & v[1]; 70937c478bd9Sstevel@tonic-gate break; 70947c478bd9Sstevel@tonic-gate 70957c478bd9Sstevel@tonic-gate case '%': 70967c478bd9Sstevel@tonic-gate if (v[1] == 0) 70977c478bd9Sstevel@tonic-gate return NULL; 70987c478bd9Sstevel@tonic-gate r = v[0] % v[1]; 70997c478bd9Sstevel@tonic-gate break; 71007c478bd9Sstevel@tonic-gate case '+': 71017c478bd9Sstevel@tonic-gate r = v[0] + v[1]; 71027c478bd9Sstevel@tonic-gate break; 71037c478bd9Sstevel@tonic-gate 71047c478bd9Sstevel@tonic-gate case '-': 71057c478bd9Sstevel@tonic-gate r = v[0] - v[1]; 71067c478bd9Sstevel@tonic-gate break; 71077c478bd9Sstevel@tonic-gate 71087c478bd9Sstevel@tonic-gate case '*': 71097c478bd9Sstevel@tonic-gate r = v[0] * v[1]; 71107c478bd9Sstevel@tonic-gate break; 71117c478bd9Sstevel@tonic-gate 71127c478bd9Sstevel@tonic-gate case '/': 71137c478bd9Sstevel@tonic-gate if (v[1] == 0) 71147c478bd9Sstevel@tonic-gate return NULL; 71157c478bd9Sstevel@tonic-gate r = v[0] / v[1]; 71167c478bd9Sstevel@tonic-gate break; 71177c478bd9Sstevel@tonic-gate 71187c478bd9Sstevel@tonic-gate case 'l': 71197c478bd9Sstevel@tonic-gate res = v[0] < v[1]; 71207c478bd9Sstevel@tonic-gate boolres = true; 71217c478bd9Sstevel@tonic-gate break; 71227c478bd9Sstevel@tonic-gate 71237c478bd9Sstevel@tonic-gate case '=': 71247c478bd9Sstevel@tonic-gate res = v[0] == v[1]; 71257c478bd9Sstevel@tonic-gate boolres = true; 71267c478bd9Sstevel@tonic-gate break; 71277c478bd9Sstevel@tonic-gate 71287c478bd9Sstevel@tonic-gate default: 71297c478bd9Sstevel@tonic-gate /* XXX */ 71307c478bd9Sstevel@tonic-gate *statp = EX_CONFIG; 71317c478bd9Sstevel@tonic-gate if (LogLevel > 10) 71327c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 71337c478bd9Sstevel@tonic-gate "arith_map: unknown operator %c", 71347c478bd9Sstevel@tonic-gate isprint(*name) ? *name : '?'); 71357c478bd9Sstevel@tonic-gate return NULL; 71367c478bd9Sstevel@tonic-gate } 71377c478bd9Sstevel@tonic-gate if (boolres) 71387c478bd9Sstevel@tonic-gate (void) sm_snprintf(result, sizeof result, 71397c478bd9Sstevel@tonic-gate res ? "TRUE" : "FALSE"); 71407c478bd9Sstevel@tonic-gate else 71417c478bd9Sstevel@tonic-gate (void) sm_snprintf(result, sizeof result, "%ld", r); 71427c478bd9Sstevel@tonic-gate return result; 71437c478bd9Sstevel@tonic-gate } 71447c478bd9Sstevel@tonic-gate *statp = EX_CONFIG; 71457c478bd9Sstevel@tonic-gate return NULL; 71467c478bd9Sstevel@tonic-gate } 71477c478bd9Sstevel@tonic-gate 71487c478bd9Sstevel@tonic-gate #if SOCKETMAP 71497c478bd9Sstevel@tonic-gate 71507c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 71517c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 71527c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 71537c478bd9Sstevel@tonic-gate 71547c478bd9Sstevel@tonic-gate # define socket_map_next map_stack[0] 71557c478bd9Sstevel@tonic-gate 71567c478bd9Sstevel@tonic-gate /* 71577c478bd9Sstevel@tonic-gate ** SOCKET_MAP_OPEN -- open socket table 71587c478bd9Sstevel@tonic-gate */ 71597c478bd9Sstevel@tonic-gate 71607c478bd9Sstevel@tonic-gate bool 71617c478bd9Sstevel@tonic-gate socket_map_open(map, mode) 71627c478bd9Sstevel@tonic-gate MAP *map; 71637c478bd9Sstevel@tonic-gate int mode; 71647c478bd9Sstevel@tonic-gate { 71657c478bd9Sstevel@tonic-gate STAB *s; 71667c478bd9Sstevel@tonic-gate int sock = 0; 71677c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T addrlen = 0; 71687c478bd9Sstevel@tonic-gate int addrno = 0; 71697c478bd9Sstevel@tonic-gate int save_errno; 71707c478bd9Sstevel@tonic-gate char *p; 71717c478bd9Sstevel@tonic-gate char *colon; 71727c478bd9Sstevel@tonic-gate char *at; 71737c478bd9Sstevel@tonic-gate struct hostent *hp = NULL; 71747c478bd9Sstevel@tonic-gate SOCKADDR addr; 71757c478bd9Sstevel@tonic-gate 71767c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 71777c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_open(%s, %s, %d)\n", 71787c478bd9Sstevel@tonic-gate map->map_mname, map->map_file, mode); 71797c478bd9Sstevel@tonic-gate 71807c478bd9Sstevel@tonic-gate mode &= O_ACCMODE; 71817c478bd9Sstevel@tonic-gate 71827c478bd9Sstevel@tonic-gate /* sendmail doesn't have the ability to write to SOCKET (yet) */ 71837c478bd9Sstevel@tonic-gate if (mode != O_RDONLY) 71847c478bd9Sstevel@tonic-gate { 71857c478bd9Sstevel@tonic-gate /* issue a pseudo-error message */ 71867c478bd9Sstevel@tonic-gate errno = SM_EMAPCANTWRITE; 71877c478bd9Sstevel@tonic-gate return false; 71887c478bd9Sstevel@tonic-gate } 71897c478bd9Sstevel@tonic-gate 71907c478bd9Sstevel@tonic-gate if (*map->map_file == '\0') 71917c478bd9Sstevel@tonic-gate { 71927c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": empty or missing socket information", 71937c478bd9Sstevel@tonic-gate map->map_mname); 71947c478bd9Sstevel@tonic-gate return false; 71957c478bd9Sstevel@tonic-gate } 71967c478bd9Sstevel@tonic-gate 71977c478bd9Sstevel@tonic-gate s = socket_map_findconn(map->map_file); 71987c478bd9Sstevel@tonic-gate if (s->s_socketmap != NULL) 71997c478bd9Sstevel@tonic-gate { 72007c478bd9Sstevel@tonic-gate /* Copy open connection */ 72017c478bd9Sstevel@tonic-gate map->map_db1 = s->s_socketmap->map_db1; 72027c478bd9Sstevel@tonic-gate 72037c478bd9Sstevel@tonic-gate /* Add this map as head of linked list */ 72047c478bd9Sstevel@tonic-gate map->socket_map_next = s->s_socketmap; 72057c478bd9Sstevel@tonic-gate s->s_socketmap = map; 72067c478bd9Sstevel@tonic-gate 72077c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 72087c478bd9Sstevel@tonic-gate sm_dprintf("using cached connection\n"); 72097c478bd9Sstevel@tonic-gate return true; 72107c478bd9Sstevel@tonic-gate } 72117c478bd9Sstevel@tonic-gate 72127c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 72137c478bd9Sstevel@tonic-gate sm_dprintf("opening new connection\n"); 72147c478bd9Sstevel@tonic-gate 72157c478bd9Sstevel@tonic-gate /* following code is ripped from milter.c */ 72167c478bd9Sstevel@tonic-gate /* XXX It should be put in a library... */ 72177c478bd9Sstevel@tonic-gate 72187c478bd9Sstevel@tonic-gate /* protocol:filename or protocol:port@host */ 72197c478bd9Sstevel@tonic-gate memset(&addr, '\0', sizeof addr); 72207c478bd9Sstevel@tonic-gate p = map->map_file; 72217c478bd9Sstevel@tonic-gate colon = strchr(p, ':'); 72227c478bd9Sstevel@tonic-gate if (colon != NULL) 72237c478bd9Sstevel@tonic-gate { 72247c478bd9Sstevel@tonic-gate *colon = '\0'; 72257c478bd9Sstevel@tonic-gate 72267c478bd9Sstevel@tonic-gate if (*p == '\0') 72277c478bd9Sstevel@tonic-gate { 72287c478bd9Sstevel@tonic-gate # if NETUNIX 72297c478bd9Sstevel@tonic-gate /* default to AF_UNIX */ 72307c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_UNIX; 72317c478bd9Sstevel@tonic-gate # else /* NETUNIX */ 72327c478bd9Sstevel@tonic-gate # if NETINET 72337c478bd9Sstevel@tonic-gate /* default to AF_INET */ 72347c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_INET; 72357c478bd9Sstevel@tonic-gate # else /* NETINET */ 72367c478bd9Sstevel@tonic-gate # if NETINET6 72377c478bd9Sstevel@tonic-gate /* default to AF_INET6 */ 72387c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_INET6; 72397c478bd9Sstevel@tonic-gate # else /* NETINET6 */ 72407c478bd9Sstevel@tonic-gate /* no protocols available */ 72417c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": no valid socket protocols available", 72427c478bd9Sstevel@tonic-gate map->map_mname); 72437c478bd9Sstevel@tonic-gate return false; 72447c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 72457c478bd9Sstevel@tonic-gate # endif /* NETINET */ 72467c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 72477c478bd9Sstevel@tonic-gate } 72487c478bd9Sstevel@tonic-gate # if NETUNIX 72497c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(p, "unix") == 0 || 72507c478bd9Sstevel@tonic-gate sm_strcasecmp(p, "local") == 0) 72517c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_UNIX; 72527c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 72537c478bd9Sstevel@tonic-gate # if NETINET 72547c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(p, "inet") == 0) 72557c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_INET; 72567c478bd9Sstevel@tonic-gate # endif /* NETINET */ 72577c478bd9Sstevel@tonic-gate # if NETINET6 72587c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(p, "inet6") == 0) 72597c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_INET6; 72607c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 72617c478bd9Sstevel@tonic-gate else 72627c478bd9Sstevel@tonic-gate { 72637c478bd9Sstevel@tonic-gate # ifdef EPROTONOSUPPORT 72647c478bd9Sstevel@tonic-gate errno = EPROTONOSUPPORT; 72657c478bd9Sstevel@tonic-gate # else /* EPROTONOSUPPORT */ 72667c478bd9Sstevel@tonic-gate errno = EINVAL; 72677c478bd9Sstevel@tonic-gate # endif /* EPROTONOSUPPORT */ 72687c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": unknown socket type %s", 72697c478bd9Sstevel@tonic-gate map->map_mname, p); 72707c478bd9Sstevel@tonic-gate return false; 72717c478bd9Sstevel@tonic-gate } 72727c478bd9Sstevel@tonic-gate *colon++ = ':'; 72737c478bd9Sstevel@tonic-gate } 72747c478bd9Sstevel@tonic-gate else 72757c478bd9Sstevel@tonic-gate { 72767c478bd9Sstevel@tonic-gate colon = p; 72777c478bd9Sstevel@tonic-gate #if NETUNIX 72787c478bd9Sstevel@tonic-gate /* default to AF_UNIX */ 72797c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_UNIX; 72807c478bd9Sstevel@tonic-gate #else /* NETUNIX */ 72817c478bd9Sstevel@tonic-gate # if NETINET 72827c478bd9Sstevel@tonic-gate /* default to AF_INET */ 72837c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_INET; 72847c478bd9Sstevel@tonic-gate # else /* NETINET */ 72857c478bd9Sstevel@tonic-gate # if NETINET6 72867c478bd9Sstevel@tonic-gate /* default to AF_INET6 */ 72877c478bd9Sstevel@tonic-gate addr.sa.sa_family = AF_INET6; 72887c478bd9Sstevel@tonic-gate # else /* NETINET6 */ 72897c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": unknown socket type %s", 72907c478bd9Sstevel@tonic-gate map->map_mname, p); 72917c478bd9Sstevel@tonic-gate return false; 72927c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 72937c478bd9Sstevel@tonic-gate # endif /* NETINET */ 72947c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 72957c478bd9Sstevel@tonic-gate } 72967c478bd9Sstevel@tonic-gate 72977c478bd9Sstevel@tonic-gate # if NETUNIX 72987c478bd9Sstevel@tonic-gate if (addr.sa.sa_family == AF_UNIX) 72997c478bd9Sstevel@tonic-gate { 73007c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK; 73017c478bd9Sstevel@tonic-gate 73027c478bd9Sstevel@tonic-gate at = colon; 73037c478bd9Sstevel@tonic-gate if (strlen(colon) >= sizeof addr.sunix.sun_path) 73047c478bd9Sstevel@tonic-gate { 73057c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": local socket name %s too long", 73067c478bd9Sstevel@tonic-gate map->map_mname, colon); 73077c478bd9Sstevel@tonic-gate return false; 73087c478bd9Sstevel@tonic-gate } 73097c478bd9Sstevel@tonic-gate errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 73107c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR, NULL); 73117c478bd9Sstevel@tonic-gate 73127c478bd9Sstevel@tonic-gate if (errno != 0) 73137c478bd9Sstevel@tonic-gate { 73147c478bd9Sstevel@tonic-gate /* if not safe, don't create */ 73157c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": local socket name %s unsafe", 73167c478bd9Sstevel@tonic-gate map->map_mname, colon); 73177c478bd9Sstevel@tonic-gate return false; 73187c478bd9Sstevel@tonic-gate } 73197c478bd9Sstevel@tonic-gate 73207c478bd9Sstevel@tonic-gate (void) sm_strlcpy(addr.sunix.sun_path, colon, 73217c478bd9Sstevel@tonic-gate sizeof addr.sunix.sun_path); 73227c478bd9Sstevel@tonic-gate addrlen = sizeof (struct sockaddr_un); 73237c478bd9Sstevel@tonic-gate } 73247c478bd9Sstevel@tonic-gate else 73257c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 73267c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 73277c478bd9Sstevel@tonic-gate if (false 73287c478bd9Sstevel@tonic-gate # if NETINET 73297c478bd9Sstevel@tonic-gate || addr.sa.sa_family == AF_INET 73307c478bd9Sstevel@tonic-gate # endif /* NETINET */ 73317c478bd9Sstevel@tonic-gate # if NETINET6 73327c478bd9Sstevel@tonic-gate || addr.sa.sa_family == AF_INET6 73337c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 73347c478bd9Sstevel@tonic-gate ) 73357c478bd9Sstevel@tonic-gate { 73367c478bd9Sstevel@tonic-gate unsigned short port; 73377c478bd9Sstevel@tonic-gate 73387c478bd9Sstevel@tonic-gate /* Parse port@host */ 73397c478bd9Sstevel@tonic-gate at = strchr(colon, '@'); 73407c478bd9Sstevel@tonic-gate if (at == NULL) 73417c478bd9Sstevel@tonic-gate { 73427c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": bad address %s (expected port@host)", 73437c478bd9Sstevel@tonic-gate map->map_mname, colon); 73447c478bd9Sstevel@tonic-gate return false; 73457c478bd9Sstevel@tonic-gate } 73467c478bd9Sstevel@tonic-gate *at = '\0'; 73477c478bd9Sstevel@tonic-gate if (isascii(*colon) && isdigit(*colon)) 73487c478bd9Sstevel@tonic-gate port = htons((unsigned short) atoi(colon)); 73497c478bd9Sstevel@tonic-gate else 73507c478bd9Sstevel@tonic-gate { 73517c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 73527c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": invalid port number %s", 73537c478bd9Sstevel@tonic-gate map->map_mname, colon); 73547c478bd9Sstevel@tonic-gate return false; 73557c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 73567c478bd9Sstevel@tonic-gate register struct servent *sp; 73577c478bd9Sstevel@tonic-gate 73587c478bd9Sstevel@tonic-gate sp = getservbyname(colon, "tcp"); 73597c478bd9Sstevel@tonic-gate if (sp == NULL) 73607c478bd9Sstevel@tonic-gate { 73617c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": unknown port name %s", 73627c478bd9Sstevel@tonic-gate map->map_mname, colon); 73637c478bd9Sstevel@tonic-gate return false; 73647c478bd9Sstevel@tonic-gate } 73657c478bd9Sstevel@tonic-gate port = sp->s_port; 73667c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 73677c478bd9Sstevel@tonic-gate } 73687c478bd9Sstevel@tonic-gate *at++ = '@'; 73697c478bd9Sstevel@tonic-gate if (*at == '[') 73707c478bd9Sstevel@tonic-gate { 73717c478bd9Sstevel@tonic-gate char *end; 73727c478bd9Sstevel@tonic-gate 73737c478bd9Sstevel@tonic-gate end = strchr(at, ']'); 73747c478bd9Sstevel@tonic-gate if (end != NULL) 73757c478bd9Sstevel@tonic-gate { 73767c478bd9Sstevel@tonic-gate bool found = false; 73777c478bd9Sstevel@tonic-gate # if NETINET 73787c478bd9Sstevel@tonic-gate unsigned long hid = INADDR_NONE; 73797c478bd9Sstevel@tonic-gate # endif /* NETINET */ 73807c478bd9Sstevel@tonic-gate # if NETINET6 73817c478bd9Sstevel@tonic-gate struct sockaddr_in6 hid6; 73827c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 73837c478bd9Sstevel@tonic-gate 73847c478bd9Sstevel@tonic-gate *end = '\0'; 73857c478bd9Sstevel@tonic-gate # if NETINET 73867c478bd9Sstevel@tonic-gate if (addr.sa.sa_family == AF_INET && 73877c478bd9Sstevel@tonic-gate (hid = inet_addr(&at[1])) != INADDR_NONE) 73887c478bd9Sstevel@tonic-gate { 73897c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = hid; 73907c478bd9Sstevel@tonic-gate addr.sin.sin_port = port; 73917c478bd9Sstevel@tonic-gate found = true; 73927c478bd9Sstevel@tonic-gate } 73937c478bd9Sstevel@tonic-gate # endif /* NETINET */ 73947c478bd9Sstevel@tonic-gate # if NETINET6 73957c478bd9Sstevel@tonic-gate (void) memset(&hid6, '\0', sizeof hid6); 73967c478bd9Sstevel@tonic-gate if (addr.sa.sa_family == AF_INET6 && 73977c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &at[1], 73987c478bd9Sstevel@tonic-gate &hid6.sin6_addr) == 1) 73997c478bd9Sstevel@tonic-gate { 74007c478bd9Sstevel@tonic-gate addr.sin6.sin6_addr = hid6.sin6_addr; 74017c478bd9Sstevel@tonic-gate addr.sin6.sin6_port = port; 74027c478bd9Sstevel@tonic-gate found = true; 74037c478bd9Sstevel@tonic-gate } 74047c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 74057c478bd9Sstevel@tonic-gate *end = ']'; 74067c478bd9Sstevel@tonic-gate if (!found) 74077c478bd9Sstevel@tonic-gate { 74087c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 74097c478bd9Sstevel@tonic-gate map->map_mname, at); 74107c478bd9Sstevel@tonic-gate return false; 74117c478bd9Sstevel@tonic-gate } 74127c478bd9Sstevel@tonic-gate } 74137c478bd9Sstevel@tonic-gate else 74147c478bd9Sstevel@tonic-gate { 74157c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"", 74167c478bd9Sstevel@tonic-gate map->map_mname, at); 74177c478bd9Sstevel@tonic-gate return false; 74187c478bd9Sstevel@tonic-gate } 74197c478bd9Sstevel@tonic-gate } 74207c478bd9Sstevel@tonic-gate else 74217c478bd9Sstevel@tonic-gate { 74227c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(at, addr.sa.sa_family); 74237c478bd9Sstevel@tonic-gate if (hp == NULL) 74247c478bd9Sstevel@tonic-gate { 74257c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": Unknown host name %s", 74267c478bd9Sstevel@tonic-gate map->map_mname, at); 74277c478bd9Sstevel@tonic-gate return false; 74287c478bd9Sstevel@tonic-gate } 74297c478bd9Sstevel@tonic-gate addr.sa.sa_family = hp->h_addrtype; 74307c478bd9Sstevel@tonic-gate switch (hp->h_addrtype) 74317c478bd9Sstevel@tonic-gate { 74327c478bd9Sstevel@tonic-gate # if NETINET 74337c478bd9Sstevel@tonic-gate case AF_INET: 74347c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 74357c478bd9Sstevel@tonic-gate hp->h_addr, INADDRSZ); 74367c478bd9Sstevel@tonic-gate addr.sin.sin_port = port; 74377c478bd9Sstevel@tonic-gate addrlen = sizeof (struct sockaddr_in); 74387c478bd9Sstevel@tonic-gate addrno = 1; 74397c478bd9Sstevel@tonic-gate break; 74407c478bd9Sstevel@tonic-gate # endif /* NETINET */ 74417c478bd9Sstevel@tonic-gate 74427c478bd9Sstevel@tonic-gate # if NETINET6 74437c478bd9Sstevel@tonic-gate case AF_INET6: 74447c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 74457c478bd9Sstevel@tonic-gate hp->h_addr, IN6ADDRSZ); 74467c478bd9Sstevel@tonic-gate addr.sin6.sin6_port = port; 74477c478bd9Sstevel@tonic-gate addrlen = sizeof (struct sockaddr_in6); 74487c478bd9Sstevel@tonic-gate addrno = 1; 74497c478bd9Sstevel@tonic-gate break; 74507c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 74517c478bd9Sstevel@tonic-gate 74527c478bd9Sstevel@tonic-gate default: 74537c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": Unknown protocol for %s (%d)", 74547c478bd9Sstevel@tonic-gate map->map_mname, at, hp->h_addrtype); 74557c478bd9Sstevel@tonic-gate # if NETINET6 74567c478bd9Sstevel@tonic-gate freehostent(hp); 74577c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 74587c478bd9Sstevel@tonic-gate return false; 74597c478bd9Sstevel@tonic-gate } 74607c478bd9Sstevel@tonic-gate } 74617c478bd9Sstevel@tonic-gate } 74627c478bd9Sstevel@tonic-gate else 74637c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 74647c478bd9Sstevel@tonic-gate { 74657c478bd9Sstevel@tonic-gate syserr("socket map \"%s\": unknown socket protocol", 74667c478bd9Sstevel@tonic-gate map->map_mname); 74677c478bd9Sstevel@tonic-gate return false; 74687c478bd9Sstevel@tonic-gate } 74697c478bd9Sstevel@tonic-gate 74707c478bd9Sstevel@tonic-gate /* nope, actually connecting */ 74717c478bd9Sstevel@tonic-gate for (;;) 74727c478bd9Sstevel@tonic-gate { 74737c478bd9Sstevel@tonic-gate sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 74747c478bd9Sstevel@tonic-gate if (sock < 0) 74757c478bd9Sstevel@tonic-gate { 74767c478bd9Sstevel@tonic-gate save_errno = errno; 74777c478bd9Sstevel@tonic-gate if (tTd(38, 5)) 74787c478bd9Sstevel@tonic-gate sm_dprintf("socket map \"%s\": error creating socket: %s\n", 74797c478bd9Sstevel@tonic-gate map->map_mname, 74807c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 74817c478bd9Sstevel@tonic-gate # if NETINET6 74827c478bd9Sstevel@tonic-gate if (hp != NULL) 74837c478bd9Sstevel@tonic-gate freehostent(hp); 74847c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 74857c478bd9Sstevel@tonic-gate return false; 74867c478bd9Sstevel@tonic-gate } 74877c478bd9Sstevel@tonic-gate 74887c478bd9Sstevel@tonic-gate if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) 74897c478bd9Sstevel@tonic-gate break; 74907c478bd9Sstevel@tonic-gate 74917c478bd9Sstevel@tonic-gate /* couldn't connect.... try next address */ 74927c478bd9Sstevel@tonic-gate save_errno = errno; 74937c478bd9Sstevel@tonic-gate p = CurHostName; 74947c478bd9Sstevel@tonic-gate CurHostName = at; 74957c478bd9Sstevel@tonic-gate if (tTd(38, 5)) 74967c478bd9Sstevel@tonic-gate sm_dprintf("socket_open (%s): open %s failed: %s\n", 74977c478bd9Sstevel@tonic-gate map->map_mname, at, sm_errstring(save_errno)); 74987c478bd9Sstevel@tonic-gate CurHostName = p; 74997c478bd9Sstevel@tonic-gate (void) close(sock); 75007c478bd9Sstevel@tonic-gate 75017c478bd9Sstevel@tonic-gate /* try next address */ 75027c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_addr_list[addrno] != NULL) 75037c478bd9Sstevel@tonic-gate { 75047c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 75057c478bd9Sstevel@tonic-gate { 75067c478bd9Sstevel@tonic-gate # if NETINET 75077c478bd9Sstevel@tonic-gate case AF_INET: 75087c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 75097c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 75107c478bd9Sstevel@tonic-gate INADDRSZ); 75117c478bd9Sstevel@tonic-gate break; 75127c478bd9Sstevel@tonic-gate # endif /* NETINET */ 75137c478bd9Sstevel@tonic-gate 75147c478bd9Sstevel@tonic-gate # if NETINET6 75157c478bd9Sstevel@tonic-gate case AF_INET6: 75167c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 75177c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 75187c478bd9Sstevel@tonic-gate IN6ADDRSZ); 75197c478bd9Sstevel@tonic-gate break; 75207c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 75217c478bd9Sstevel@tonic-gate 75227c478bd9Sstevel@tonic-gate default: 75237c478bd9Sstevel@tonic-gate if (tTd(38, 5)) 75247c478bd9Sstevel@tonic-gate sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n", 75257c478bd9Sstevel@tonic-gate map->map_mname, at, 75267c478bd9Sstevel@tonic-gate hp->h_addrtype); 75277c478bd9Sstevel@tonic-gate # if NETINET6 75287c478bd9Sstevel@tonic-gate freehostent(hp); 75297c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 75307c478bd9Sstevel@tonic-gate return false; 75317c478bd9Sstevel@tonic-gate } 75327c478bd9Sstevel@tonic-gate continue; 75337c478bd9Sstevel@tonic-gate } 75347c478bd9Sstevel@tonic-gate p = CurHostName; 75357c478bd9Sstevel@tonic-gate CurHostName = at; 75367c478bd9Sstevel@tonic-gate if (tTd(38, 5)) 75377c478bd9Sstevel@tonic-gate sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n", 75387c478bd9Sstevel@tonic-gate map->map_mname, sm_errstring(save_errno)); 75397c478bd9Sstevel@tonic-gate CurHostName = p; 75407c478bd9Sstevel@tonic-gate # if NETINET6 75417c478bd9Sstevel@tonic-gate if (hp != NULL) 75427c478bd9Sstevel@tonic-gate freehostent(hp); 75437c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 75447c478bd9Sstevel@tonic-gate return false; 75457c478bd9Sstevel@tonic-gate } 75467c478bd9Sstevel@tonic-gate # if NETINET6 75477c478bd9Sstevel@tonic-gate if (hp != NULL) 75487c478bd9Sstevel@tonic-gate { 75497c478bd9Sstevel@tonic-gate freehostent(hp); 75507c478bd9Sstevel@tonic-gate hp = NULL; 75517c478bd9Sstevel@tonic-gate } 75527c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 75537c478bd9Sstevel@tonic-gate if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd, 75547c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 75557c478bd9Sstevel@tonic-gate (void *) &sock, 75567c478bd9Sstevel@tonic-gate SM_IO_RDWR, 75577c478bd9Sstevel@tonic-gate NULL)) == NULL) 75587c478bd9Sstevel@tonic-gate { 75597c478bd9Sstevel@tonic-gate close(sock); 75607c478bd9Sstevel@tonic-gate if (tTd(38, 2)) 75617c478bd9Sstevel@tonic-gate sm_dprintf("socket_open (%s): failed to create stream: %s\n", 75627c478bd9Sstevel@tonic-gate map->map_mname, sm_errstring(errno)); 75637c478bd9Sstevel@tonic-gate return false; 75647c478bd9Sstevel@tonic-gate } 75657c478bd9Sstevel@tonic-gate 75667c478bd9Sstevel@tonic-gate /* Save connection for reuse */ 75677c478bd9Sstevel@tonic-gate s->s_socketmap = map; 75687c478bd9Sstevel@tonic-gate return true; 75697c478bd9Sstevel@tonic-gate } 75707c478bd9Sstevel@tonic-gate 75717c478bd9Sstevel@tonic-gate /* 75727c478bd9Sstevel@tonic-gate ** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server 75737c478bd9Sstevel@tonic-gate ** 75747c478bd9Sstevel@tonic-gate ** Cache SOCKET connections based on the connection specifier 75757c478bd9Sstevel@tonic-gate ** and PID so we don't have multiple connections open to 75767c478bd9Sstevel@tonic-gate ** the same server for different maps. Need a separate connection 75777c478bd9Sstevel@tonic-gate ** per PID since a parent process may close the map before the 75787c478bd9Sstevel@tonic-gate ** child is done with it. 75797c478bd9Sstevel@tonic-gate ** 75807c478bd9Sstevel@tonic-gate ** Parameters: 75817c478bd9Sstevel@tonic-gate ** conn -- SOCKET map connection specifier 75827c478bd9Sstevel@tonic-gate ** 75837c478bd9Sstevel@tonic-gate ** Returns: 75847c478bd9Sstevel@tonic-gate ** Symbol table entry for the SOCKET connection. 75857c478bd9Sstevel@tonic-gate */ 75867c478bd9Sstevel@tonic-gate 75877c478bd9Sstevel@tonic-gate static STAB * 75887c478bd9Sstevel@tonic-gate socket_map_findconn(conn) 75897c478bd9Sstevel@tonic-gate const char *conn; 75907c478bd9Sstevel@tonic-gate { 75917c478bd9Sstevel@tonic-gate char *nbuf; 75927c478bd9Sstevel@tonic-gate STAB *SM_NONVOLATILE s = NULL; 75937c478bd9Sstevel@tonic-gate 75947c478bd9Sstevel@tonic-gate nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid); 75957c478bd9Sstevel@tonic-gate SM_TRY 75967c478bd9Sstevel@tonic-gate s = stab(nbuf, ST_SOCKETMAP, ST_ENTER); 75977c478bd9Sstevel@tonic-gate SM_FINALLY 75987c478bd9Sstevel@tonic-gate sm_free(nbuf); 75997c478bd9Sstevel@tonic-gate SM_END_TRY 76007c478bd9Sstevel@tonic-gate return s; 76017c478bd9Sstevel@tonic-gate } 76027c478bd9Sstevel@tonic-gate 76037c478bd9Sstevel@tonic-gate /* 76047c478bd9Sstevel@tonic-gate ** SOCKET_MAP_CLOSE -- close the socket 76057c478bd9Sstevel@tonic-gate */ 76067c478bd9Sstevel@tonic-gate 76077c478bd9Sstevel@tonic-gate void 76087c478bd9Sstevel@tonic-gate socket_map_close(map) 76097c478bd9Sstevel@tonic-gate MAP *map; 76107c478bd9Sstevel@tonic-gate { 76117c478bd9Sstevel@tonic-gate STAB *s; 76127c478bd9Sstevel@tonic-gate MAP *smap; 76137c478bd9Sstevel@tonic-gate 76147c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 76157c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file, 76167c478bd9Sstevel@tonic-gate (long) CurrentPid); 76177c478bd9Sstevel@tonic-gate 76187c478bd9Sstevel@tonic-gate /* Check if already closed */ 76197c478bd9Sstevel@tonic-gate if (map->map_db1 == NULL) 76207c478bd9Sstevel@tonic-gate { 76217c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 76227c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_close(%s) already closed\n", 76237c478bd9Sstevel@tonic-gate map->map_file); 76247c478bd9Sstevel@tonic-gate return; 76257c478bd9Sstevel@tonic-gate } 76267c478bd9Sstevel@tonic-gate sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT); 76277c478bd9Sstevel@tonic-gate 76287c478bd9Sstevel@tonic-gate /* Mark all the maps that share the connection as closed */ 76297c478bd9Sstevel@tonic-gate s = socket_map_findconn(map->map_file); 76307c478bd9Sstevel@tonic-gate smap = s->s_socketmap; 76317c478bd9Sstevel@tonic-gate while (smap != NULL) 76327c478bd9Sstevel@tonic-gate { 76337c478bd9Sstevel@tonic-gate MAP *next; 76347c478bd9Sstevel@tonic-gate 76357c478bd9Sstevel@tonic-gate if (tTd(38, 2) && smap != map) 76367c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n", 76377c478bd9Sstevel@tonic-gate map->map_mname, smap->map_mname); 76387c478bd9Sstevel@tonic-gate 76397c478bd9Sstevel@tonic-gate smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 76407c478bd9Sstevel@tonic-gate smap->map_db1 = NULL; 76417c478bd9Sstevel@tonic-gate next = smap->socket_map_next; 76427c478bd9Sstevel@tonic-gate smap->socket_map_next = NULL; 76437c478bd9Sstevel@tonic-gate smap = next; 76447c478bd9Sstevel@tonic-gate } 76457c478bd9Sstevel@tonic-gate s->s_socketmap = NULL; 76467c478bd9Sstevel@tonic-gate } 76477c478bd9Sstevel@tonic-gate 76487c478bd9Sstevel@tonic-gate /* 76497c478bd9Sstevel@tonic-gate ** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table 76507c478bd9Sstevel@tonic-gate */ 76517c478bd9Sstevel@tonic-gate 76527c478bd9Sstevel@tonic-gate char * 76537c478bd9Sstevel@tonic-gate socket_map_lookup(map, name, av, statp) 76547c478bd9Sstevel@tonic-gate MAP *map; 76557c478bd9Sstevel@tonic-gate char *name; 76567c478bd9Sstevel@tonic-gate char **av; 76577c478bd9Sstevel@tonic-gate int *statp; 76587c478bd9Sstevel@tonic-gate { 76597c478bd9Sstevel@tonic-gate unsigned int nettolen, replylen, recvlen; 76607c478bd9Sstevel@tonic-gate char *replybuf, *rval, *value, *status, *key; 76617c478bd9Sstevel@tonic-gate SM_FILE_T *f; 76627c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1]; 76637c478bd9Sstevel@tonic-gate 76647c478bd9Sstevel@tonic-gate replybuf = NULL; 76657c478bd9Sstevel@tonic-gate rval = NULL; 76667c478bd9Sstevel@tonic-gate f = (SM_FILE_T *)map->map_db1; 76677c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 76687c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_lookup(%s, %s) %s\n", 76697c478bd9Sstevel@tonic-gate map->map_mname, name, map->map_file); 76707c478bd9Sstevel@tonic-gate 76717c478bd9Sstevel@tonic-gate if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 76727c478bd9Sstevel@tonic-gate { 76737c478bd9Sstevel@tonic-gate nettolen = strlen(name); 76747c478bd9Sstevel@tonic-gate if (nettolen > sizeof keybuf - 1) 76757c478bd9Sstevel@tonic-gate nettolen = sizeof keybuf - 1; 76767c478bd9Sstevel@tonic-gate memmove(keybuf, name, nettolen); 76777c478bd9Sstevel@tonic-gate keybuf[nettolen] = '\0'; 76787c478bd9Sstevel@tonic-gate makelower(keybuf); 76797c478bd9Sstevel@tonic-gate key = keybuf; 76807c478bd9Sstevel@tonic-gate } 76817c478bd9Sstevel@tonic-gate else 76827c478bd9Sstevel@tonic-gate key = name; 76837c478bd9Sstevel@tonic-gate 76847c478bd9Sstevel@tonic-gate nettolen = strlen(map->map_mname) + 1 + strlen(key); 76857c478bd9Sstevel@tonic-gate SM_ASSERT(nettolen > strlen(map->map_mname)); 76867c478bd9Sstevel@tonic-gate SM_ASSERT(nettolen > strlen(key)); 76877c478bd9Sstevel@tonic-gate if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,", 76887c478bd9Sstevel@tonic-gate nettolen, map->map_mname, key) == SM_IO_EOF) || 76897c478bd9Sstevel@tonic-gate (sm_io_flush(f, SM_TIME_DEFAULT) != 0) || 76907c478bd9Sstevel@tonic-gate (sm_io_error(f))) 76917c478bd9Sstevel@tonic-gate { 76927c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request", 76937c478bd9Sstevel@tonic-gate map->map_mname); 76947c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 76957c478bd9Sstevel@tonic-gate goto errcl; 76967c478bd9Sstevel@tonic-gate } 76977c478bd9Sstevel@tonic-gate 76987c478bd9Sstevel@tonic-gate if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) 76997c478bd9Sstevel@tonic-gate { 77007c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", 77017c478bd9Sstevel@tonic-gate map->map_mname); 77027c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 77037c478bd9Sstevel@tonic-gate goto errcl; 77047c478bd9Sstevel@tonic-gate } 77057c478bd9Sstevel@tonic-gate if (replylen > SOCKETMAP_MAXL) 77067c478bd9Sstevel@tonic-gate { 77077c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u", 77087c478bd9Sstevel@tonic-gate map->map_mname, replylen); 77097c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 77107c478bd9Sstevel@tonic-gate goto errcl; 77117c478bd9Sstevel@tonic-gate } 77127c478bd9Sstevel@tonic-gate if (sm_io_getc(f, SM_TIME_DEFAULT) != ':') 77137c478bd9Sstevel@tonic-gate { 77147c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply", 77157c478bd9Sstevel@tonic-gate map->map_mname); 77167c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 77177c478bd9Sstevel@tonic-gate goto error; 77187c478bd9Sstevel@tonic-gate } 77197c478bd9Sstevel@tonic-gate 77207c478bd9Sstevel@tonic-gate replybuf = (char *) sm_malloc(replylen + 1); 77217c478bd9Sstevel@tonic-gate if (replybuf == NULL) 77227c478bd9Sstevel@tonic-gate { 77237c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes", 77247c478bd9Sstevel@tonic-gate map->map_mname, replylen + 1); 77257c478bd9Sstevel@tonic-gate *statp = EX_OSERR; 77267c478bd9Sstevel@tonic-gate goto error; 77277c478bd9Sstevel@tonic-gate } 77287c478bd9Sstevel@tonic-gate 77297c478bd9Sstevel@tonic-gate recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen); 77307c478bd9Sstevel@tonic-gate if (recvlen < replylen) 77317c478bd9Sstevel@tonic-gate { 77327c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters", 77337c478bd9Sstevel@tonic-gate map->map_mname, recvlen, replylen); 77347c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 77357c478bd9Sstevel@tonic-gate goto errcl; 77367c478bd9Sstevel@tonic-gate } 77377c478bd9Sstevel@tonic-gate if (sm_io_getc(f, SM_TIME_DEFAULT) != ',') 77387c478bd9Sstevel@tonic-gate { 77397c478bd9Sstevel@tonic-gate syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply", 77407c478bd9Sstevel@tonic-gate map->map_mname); 77417c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 77427c478bd9Sstevel@tonic-gate goto errcl; 77437c478bd9Sstevel@tonic-gate } 77447c478bd9Sstevel@tonic-gate status = replybuf; 77457c478bd9Sstevel@tonic-gate replybuf[recvlen] = '\0'; 77467c478bd9Sstevel@tonic-gate value = strchr(replybuf, ' '); 77477c478bd9Sstevel@tonic-gate if (value != NULL) 77487c478bd9Sstevel@tonic-gate { 77497c478bd9Sstevel@tonic-gate *value = '\0'; 77507c478bd9Sstevel@tonic-gate value++; 77517c478bd9Sstevel@tonic-gate } 77527c478bd9Sstevel@tonic-gate if (strcmp(status, "OK") == 0) 77537c478bd9Sstevel@tonic-gate { 77547c478bd9Sstevel@tonic-gate *statp = EX_OK; 77557c478bd9Sstevel@tonic-gate 77567c478bd9Sstevel@tonic-gate /* collect the return value */ 77577c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 77587c478bd9Sstevel@tonic-gate rval = map_rewrite(map, key, strlen(key), NULL); 77597c478bd9Sstevel@tonic-gate else 77607c478bd9Sstevel@tonic-gate rval = map_rewrite(map, value, strlen(value), av); 77617c478bd9Sstevel@tonic-gate } 77627c478bd9Sstevel@tonic-gate else if (strcmp(status, "NOTFOUND") == 0) 77637c478bd9Sstevel@tonic-gate { 77647c478bd9Sstevel@tonic-gate *statp = EX_NOTFOUND; 77657c478bd9Sstevel@tonic-gate if (tTd(38, 20)) 77667c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_lookup(%s): %s not found\n", 77677c478bd9Sstevel@tonic-gate map->map_mname, key); 77687c478bd9Sstevel@tonic-gate } 77697c478bd9Sstevel@tonic-gate else 77707c478bd9Sstevel@tonic-gate { 77717c478bd9Sstevel@tonic-gate if (tTd(38, 5)) 77727c478bd9Sstevel@tonic-gate sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n", 77737c478bd9Sstevel@tonic-gate map->map_mname, key, status, 77747c478bd9Sstevel@tonic-gate value ? value : ""); 77757c478bd9Sstevel@tonic-gate if ((strcmp(status, "TEMP") == 0) || 77767c478bd9Sstevel@tonic-gate (strcmp(status, "TIMEOUT") == 0)) 77777c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 77787c478bd9Sstevel@tonic-gate else if(strcmp(status, "PERM") == 0) 77797c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 77807c478bd9Sstevel@tonic-gate else 77817c478bd9Sstevel@tonic-gate *statp = EX_PROTOCOL; 77827c478bd9Sstevel@tonic-gate } 77837c478bd9Sstevel@tonic-gate 77847c478bd9Sstevel@tonic-gate if (replybuf != NULL) 77857c478bd9Sstevel@tonic-gate sm_free(replybuf); 77867c478bd9Sstevel@tonic-gate return rval; 77877c478bd9Sstevel@tonic-gate 77887c478bd9Sstevel@tonic-gate errcl: 77897c478bd9Sstevel@tonic-gate socket_map_close(map); 77907c478bd9Sstevel@tonic-gate error: 77917c478bd9Sstevel@tonic-gate if (replybuf != NULL) 77927c478bd9Sstevel@tonic-gate sm_free(replybuf); 77937c478bd9Sstevel@tonic-gate return rval; 77947c478bd9Sstevel@tonic-gate } 77957c478bd9Sstevel@tonic-gate #endif /* SOCKETMAP */ 7796