示例#1
0
DICT *
dict_erlang_open(const char *key, int open_flags, int dict_flags)
{
    DICT_ERLANG *dict_erlang;

    if (open_flags != O_RDONLY)
        msg_fatal("%s:%s map requires O_RDONLY access mode",
                  DICT_TYPE_ERLANG, key);

    erl_init(NULL, 0);

    dict_erlang = (DICT_ERLANG *)dict_alloc(DICT_TYPE_ERLANG, key,
                                            sizeof(DICT_ERLANG));
    dict_erlang->dict.lookup = dict_erlang_lookup;
    dict_erlang->dict.close = dict_erlang_close;
    dict_erlang->dict.flags = dict_flags;

    erlang_parse_config(dict_erlang, key);
    if (dict_erlang->nodes->argc == 0)
        msg_fatal("no erlang nodes specified");
    dict_erlang->active_node = 0;

    if (dict_erlang->cookie == NULL)
        msg_fatal("no erlang cookie specified");
    if (dict_erlang->mod == NULL)
        msg_fatal("no erlang module specified");
    if (dict_erlang->fun == NULL)
        msg_fatal("no erlang function specified");

    return (DICT_DEBUG(&dict_erlang->dict));
}
示例#2
0
DICT   *dict_tcp_open(const char *map, int open_flags, int dict_flags)
{
    DICT_TCP *dict_tcp;

    dict_errno = 0;

    /*
     * Sanity checks.
     */
    if (dict_flags & DICT_FLAG_NO_UNAUTH)
	msg_fatal("%s:%s map is not allowed for security sensitive data",
		  DICT_TYPE_TCP, map);
    if (open_flags != O_RDONLY)
	msg_fatal("%s:%s map requires O_RDONLY access mode",
		  DICT_TYPE_TCP, map);

    /*
     * Create the dictionary handle. Do not open the connection until the
     * first request is made.
     */
    dict_tcp = (DICT_TCP *) dict_alloc(DICT_TYPE_TCP, map, sizeof(*dict_tcp));
    dict_tcp->fp = 0;
    dict_tcp->raw_buf = dict_tcp->hex_buf = 0;
    dict_tcp->dict.lookup = dict_tcp_lookup;
    dict_tcp->dict.close = dict_tcp_close;
    dict_tcp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
    if (dict_flags & DICT_FLAG_FOLD_MUL)
	dict_tcp->dict.fold_buf = vstring_alloc(10);

    return (DICT_DEBUG (&dict_tcp->dict));
}
示例#3
0
DICT   *dict_pgsql_open(const char *name, int open_flags, int dict_flags)
{
    DICT_PGSQL *dict_pgsql;
    CFG_PARSER *parser;

    /*
     * Sanity check.
     */
    if (open_flags != O_RDONLY)
	return (dict_surrogate(DICT_TYPE_PGSQL, name, open_flags, dict_flags,
			       "%s:%s map requires O_RDONLY access mode",
			       DICT_TYPE_PGSQL, name));

    /*
     * Open the configuration file.
     */
    if ((parser = cfg_parser_alloc(name)) == 0)
	return (dict_surrogate(DICT_TYPE_PGSQL, name, open_flags, dict_flags,
			       "open %s: %m", name));

    dict_pgsql = (DICT_PGSQL *) dict_alloc(DICT_TYPE_PGSQL, name,
					   sizeof(DICT_PGSQL));
    dict_pgsql->dict.lookup = dict_pgsql_lookup;
    dict_pgsql->dict.close = dict_pgsql_close;
    dict_pgsql->dict.flags = dict_flags;
    dict_pgsql->parser = parser;
    pgsql_parse_config(dict_pgsql, name);
    dict_pgsql->active_host = 0;
    dict_pgsql->pldb = plpgsql_init(dict_pgsql->hosts);
    if (dict_pgsql->pldb == NULL)
	msg_fatal("couldn't intialize pldb!\n");
    dict_pgsql->dict.owner = cfg_get_owner(dict_pgsql->parser);
    return (DICT_DEBUG (&dict_pgsql->dict));
}
示例#4
0
DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
{
    DICT_CIDR *dict_cidr;
    VSTREAM *map_fp;
    VSTRING *line_buffer = vstring_alloc(100);
    VSTRING *why = vstring_alloc(100);
    DICT_CIDR_ENTRY *rule;
    DICT_CIDR_ENTRY *last_rule = 0;
    int     lineno = 0;

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	msg_fatal("%s:%s map requires O_RDONLY access mode",
		  DICT_TYPE_CIDR, mapname);

    /*
     * XXX Eliminate unnecessary queries by setting a flag that says "this
     * map matches network addresses only".
     */
    dict_cidr = (DICT_CIDR *) dict_alloc(DICT_TYPE_CIDR, mapname,
					 sizeof(*dict_cidr));
    dict_cidr->dict.lookup = dict_cidr_lookup;
    dict_cidr->dict.close = dict_cidr_close;
    dict_cidr->dict.flags = dict_flags | DICT_FLAG_PATTERN;
    dict_cidr->head = 0;

    if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
	msg_fatal("open %s: %m", mapname);

    while (readlline(line_buffer, map_fp, &lineno)) {
	rule = dict_cidr_parse_rule(vstring_str(line_buffer), why);
	if (rule == 0) {
	    msg_warn("cidr map %s, line %d: %s: skipping this rule",
		     mapname, lineno, vstring_str(why));
	    continue;
	}
	if (last_rule == 0)
	    dict_cidr->head = rule;
	else
	    last_rule->cidr_info.next = &(rule->cidr_info);
	last_rule = rule;
    }

    /*
     * Clean up.
     */
    if (vstream_fclose(map_fp))
	msg_fatal("cidr map %s: read error: %m", mapname);
    vstring_free(line_buffer);
    vstring_free(why);

    return (DICT_DEBUG (&dict_cidr->dict));
}
示例#5
0
DICT   *dict_static_open(const char *name, int unused_flags, int dict_flags)
{
    DICT   *dict;

    dict = dict_alloc(DICT_TYPE_STATIC, name, sizeof(*dict));
    dict->lookup = dict_static_lookup;
    dict->close = dict_static_close;
    dict->flags = dict_flags | DICT_FLAG_FIXED;
    dict->owner.status = DICT_OWNER_TRUSTED;
    return (DICT_DEBUG (dict));
}
示例#6
0
DICT   *dict_random_open(const char *name, int open_flags, int dict_flags)
{
    DICT_RANDOM *dict_random;
    char   *saved_name = 0;
    size_t  len;

    /*
     * Clarity first. Let the optimizer worry about redundant code.
     */
#define DICT_RANDOM_RETURN(x) do { \
	if (saved_name != 0) \
	    myfree(saved_name); \
	return (x); \
    } while (0)

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
					  open_flags, dict_flags,
				  "%s:%s map requires O_RDONLY access mode",
					  DICT_TYPE_RANDOM, name));

    /*
     * Split the name name into its constituent parts.
     */
    if ((len = balpar(name, "{}")) == 0 || name[len] != 0
	|| *(saved_name = mystrndup(name + 1, len - 2)) == 0)
	DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
					  open_flags, dict_flags,
					  "bad syntax: \"%s:%s\"; "
					  "need \"%s:{type:name...}\"",
					  DICT_TYPE_RANDOM, name,
					  DICT_TYPE_RANDOM));

    /*
     * Bundle up the result.
     */
    dict_random =
	(DICT_RANDOM *) dict_alloc(DICT_TYPE_RANDOM, name, sizeof(*dict_random));
    dict_random->dict.lookup = dict_random_lookup;
    dict_random->dict.close = dict_random_close;
    dict_random->dict.flags = dict_flags | DICT_FLAG_PATTERN;
    dict_random->replies = argv_splitq(saved_name, ", \t\r\n", "{}");
    dict_random->dict.owner.status = DICT_OWNER_TRUSTED;
    dict_random->dict.owner.uid = 0;

    DICT_RANDOM_RETURN(DICT_DEBUG (&dict_random->dict));
}
示例#7
0
DICT   *dict_env_open(const char *name, int unused_flags, int dict_flags)
{
    DICT   *dict;

    dict = dict_alloc(DICT_TYPE_ENVIRON, name, sizeof(*dict));
    dict->lookup = dict_env_lookup;
    dict->update = dict_env_update;
    dict->close = dict_env_close;
    dict->flags = dict_flags | DICT_FLAG_FIXED;
    if (dict_flags & DICT_FLAG_FOLD_FIX)
	dict->fold_buf = vstring_alloc(10);
    dict->owner.status = DICT_OWNER_TRUSTED;
    return (DICT_DEBUG (dict));
}
示例#8
0
DICT   *dict_nis_open(const char *map, int open_flags, int dict_flags)
{
    DICT_NIS *dict_nis;

    if (open_flags != O_RDONLY)
	msg_fatal("%s:%s map requires O_RDONLY access mode",
		  DICT_TYPE_NIS, map);

    dict_nis = (DICT_NIS *) dict_alloc(DICT_TYPE_NIS, map, sizeof(*dict_nis));
    dict_nis->dict.lookup = dict_nis_lookup;
    dict_nis->dict.close = dict_nis_close;
    dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED;
    if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
	dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
    if (dict_flags & DICT_FLAG_FOLD_FIX)
	dict_nis->dict.fold_buf = vstring_alloc(10);
    if (dict_nis_domain == 0)
	dict_nis_init();
    return (DICT_DEBUG (&dict_nis->dict));
}
示例#9
0
/**********************************************************************
 * public interface dict_mysql_open
 *    create association with database with appropriate values
 *    parse the map's config file
 *    allocate memory
 **********************************************************************/
DICT   *dict_mysql_open(const char *name, int open_flags, int dict_flags)
{
    DICT_MYSQL *dict_mysql;

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
        msg_fatal("%s:%s map requires O_RDONLY access mode",
                  DICT_TYPE_MYSQL, name);

    dict_mysql = (DICT_MYSQL *) dict_alloc(DICT_TYPE_MYSQL, name,
                                           sizeof(DICT_MYSQL));
    dict_mysql->dict.lookup = dict_mysql_lookup;
    dict_mysql->dict.close = dict_mysql_close;
    dict_mysql->dict.flags = dict_flags | DICT_FLAG_FIXED;
    dict_mysql->name = mysqlname_parse(name);
    dict_mysql->pldb = plmysql_init(dict_mysql->name->hostnames,
                                    dict_mysql->name->len_hosts);
    if (dict_mysql->pldb == NULL)
        msg_fatal("couldn't intialize pldb!\n");
    return (DICT_DEBUG (&dict_mysql->dict));
}
示例#10
0
DICT   *dict_sqlite_open(const char *name, int open_flags, int dict_flags)
{
    DICT_SQLITE *dict_sqlite;
    CFG_PARSER *parser;

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	return (dict_surrogate(DICT_TYPE_SQLITE, name, open_flags, dict_flags,
			       "%s:%s map requires O_RDONLY access mode",
			       DICT_TYPE_SQLITE, name));

    /*
     * Open the configuration file.
     */
    if ((parser = cfg_parser_alloc(name)) == 0)
	return (dict_surrogate(DICT_TYPE_SQLITE, name, open_flags, dict_flags,
			       "open %s: %m", name));

    dict_sqlite = (DICT_SQLITE *) dict_alloc(DICT_TYPE_SQLITE, name,
					     sizeof(DICT_SQLITE));
    dict_sqlite->dict.lookup = dict_sqlite_lookup;
    dict_sqlite->dict.close = dict_sqlite_close;
    dict_sqlite->dict.flags = dict_flags;

    dict_sqlite->parser = parser;
    sqlite_parse_config(dict_sqlite, name);

    if (sqlite3_open(dict_sqlite->dbpath, &dict_sqlite->db))
	msg_fatal("%s:%s: Can't open database: %s\n",
		  DICT_TYPE_SQLITE, name, sqlite3_errmsg(dict_sqlite->db));

    dict_sqlite->dict.owner = cfg_get_owner(dict_sqlite->parser);

    return (DICT_DEBUG (&dict_sqlite->dict));
}
示例#11
0
DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
{
    DICT_THASH *dict_thash;
    VSTREAM *fp = 0;
    struct stat st;
    time_t  before;
    time_t  after;
    VSTRING *line_buffer = 0;
    int     lineno;
    char   *key;
    char   *value;
    HTABLE *table;
    HTABLE_INFO *ht;

    /*
     * Let the optimizer worry about eliminating redundant code.
     */
#define DICT_THASH_OPEN_RETURN(d) { \
	DICT *__d = (d); \
	if (fp != 0) \
	    vstream_fclose(fp); \
	if (line_buffer != 0) \
	    vstring_free(line_buffer); \
	return (__d); \
    } while (0)

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path,
					      open_flags, dict_flags,
				  "%s:%s map requires O_RDONLY access mode",
					      DICT_TYPE_THASH, path));

    /*
     * Read the flat text file into in-memory hash. Read the file again if it
     * may have changed while we were reading.
     */
    for (before = time((time_t *) 0); /* see below */ ; before = after) {
	if ((fp = vstream_fopen(path, open_flags, 0644)) == 0) {
	    DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path,
						  open_flags, dict_flags,
					     "open database %s: %m", path));
	}
	if (line_buffer == 0)
	    line_buffer = vstring_alloc(100);
	lineno = 0;
	table = htable_create(13);
	while (readlline(line_buffer, fp, &lineno)) {

	    /*
	     * Split on the first whitespace character, then trim leading and
	     * trailing whitespace from key and value.
	     */
	    key = STR(line_buffer);
	    value = key + strcspn(key, " \t\r\n");
	    if (*value)
		*value++ = 0;
	    while (ISSPACE(*value))
		value++;
	    trimblanks(key, 0)[0] = 0;
	    trimblanks(value, 0)[0] = 0;

	    /*
	     * Enforce the "key whitespace value" format. Disallow missing
	     * keys or missing values.
	     */
	    if (*key == 0 || *value == 0) {
		msg_warn("%s, line %d: expected format: key whitespace value"
			 " -- ignoring this line", path, lineno);
		continue;
	    }
	    if (key[strlen(key) - 1] == ':')
		msg_warn("%s, line %d: record is in \"key: value\" format;"
			 " is this an alias file?", path, lineno);

	    /*
	     * Optionally fold the key.
	     */
	    if (dict_flags & DICT_FLAG_FOLD_FIX)
		lowercase(key);

	    /*
	     * Store the value under the key. Handle duplicates
	     * appropriately.
	     */
	    if ((ht = htable_locate(table, key)) != 0) {
		if (dict_flags & DICT_FLAG_DUP_IGNORE) {
		     /* void */ ;
		} else if (dict_flags & DICT_FLAG_DUP_REPLACE) {
		    myfree(ht->value);
		    ht->value = mystrdup(value);
		} else if (dict_flags & DICT_FLAG_DUP_WARN) {
		    msg_warn("%s, line %d: duplicate entry: \"%s\"",
			     path, lineno, key);
		} else {
		    msg_fatal("%s, line %d: duplicate entry: \"%s\"",
			      path, lineno, key);
		}
	    } else {
		htable_enter(table, key, mystrdup(value));
	    }
	}

	/*
	 * See if the source file is hot.
	 */
	if (fstat(vstream_fileno(fp), &st) < 0)
	    msg_fatal("fstat %s: %m", path);
	if (vstream_fclose(fp))
	    msg_fatal("read %s: %m", path);
	fp = 0;					/* DICT_THASH_OPEN_RETURN() */
	after = time((time_t *) 0);
	if (st.st_mtime < before - 1 || st.st_mtime > after)
	    break;

	/*
	 * Yes, it is hot. Discard the result and read the file again.
	 */
	htable_free(table, myfree);
	if (msg_verbose > 1)
	    msg_info("pausing to let file %s cool down", path);
	doze(300000);
    }

    /*
     * Create the in-memory table.
     */
    dict_thash = (DICT_THASH *)
	dict_alloc(DICT_TYPE_THASH, path, sizeof(*dict_thash));
    dict_thash->dict.lookup = dict_thash_lookup;
    dict_thash->dict.sequence = dict_thash_sequence;
    dict_thash->dict.close = dict_thash_close;
    dict_thash->dict.flags = dict_flags | DICT_FLAG_DUP_WARN | DICT_FLAG_FIXED;
    if (dict_flags & DICT_FLAG_FOLD_FIX)
	dict_thash->dict.fold_buf = vstring_alloc(10);
    dict_thash->info = 0;
    dict_thash->table = table;
    dict_thash->dict.owner.uid = st.st_uid;
    dict_thash->dict.owner.status = (st.st_uid != 0);

    DICT_THASH_OPEN_RETURN(DICT_DEBUG (&dict_thash->dict));
}
示例#12
0
DICT   *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags)
{
    DICT_SOCKMAP *dp;
    char   *saved_name = 0;
    char   *sockmap;
    DICT_SOCKMAP_REFC_HANDLE *ref_handle;
    HTABLE_INFO *client_info;

    /*
     * Let the optimizer worry about eliminating redundant code.
     */
#define DICT_SOCKMAP_OPEN_RETURN(d) { \
	DICT *__d = (d); \
	if (saved_name != 0) \
	    myfree(saved_name); \
	return (__d); \
    } while (0)

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
					   open_flags, dict_flags,
				  "%s:%s map requires O_RDONLY access mode",
					   DICT_TYPE_SOCKMAP, mapname));
    if (dict_flags & DICT_FLAG_NO_UNAUTH)
	DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
					   open_flags, dict_flags,
		     "%s:%s map is not allowed for security-sensitive data",
					   DICT_TYPE_SOCKMAP, mapname));

    /*
     * Separate the socketmap name from the socketmap server name.
     */
    saved_name = mystrdup(mapname);
    if ((sockmap = split_at_right(saved_name, ':')) == 0)
	DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
					   open_flags, dict_flags,
				    "%s requires server:socketmap argument",
					   DICT_TYPE_SOCKMAP));

    /*
     * Use one reference-counted client handle for all socketmaps with the
     * same inet:host:port or unix:pathname information.
     * 
     * XXX Todo: graceful degradation after endpoint syntax error.
     */
    if (dict_sockmap_handles == 0)
	dict_sockmap_handles = htable_create(1);
    if ((client_info = htable_locate(dict_sockmap_handles, saved_name)) == 0) {
	ref_handle = (DICT_SOCKMAP_REFC_HANDLE *) mymalloc(sizeof(*ref_handle));
	client_info = htable_enter(dict_sockmap_handles,
				   saved_name, (char *) ref_handle);
	/* XXX Late initialization, so we can reuse macros for consistency. */
	DICT_SOCKMAP_RH_REFCOUNT(client_info) = 1;
	DICT_SOCKMAP_RH_HANDLE(client_info) =
	    auto_clnt_create(saved_name, dict_sockmap_timeout,
			     dict_sockmap_max_idle, dict_sockmap_max_ttl);
    } else
	DICT_SOCKMAP_RH_REFCOUNT(client_info) += 1;

    /*
     * Instantiate a socket map handle.
     */
    dp = (DICT_SOCKMAP *) dict_alloc(DICT_TYPE_SOCKMAP, mapname, sizeof(*dp));
    dp->rdwr_buf = vstring_alloc(100);
    dp->sockmap_name = mystrdup(sockmap);
    dp->client_info = client_info;
    dp->dict.lookup = dict_sockmap_lookup;
    dp->dict.close = dict_sockmap_close;
    /* Don't look up parent domains or network superblocks. */
    dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;

    DICT_SOCKMAP_OPEN_RETURN(DICT_DEBUG (&dp->dict));
}
示例#13
0
DICT   *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
{
    DICT_PCRE *dict_pcre;
    VSTREAM *map_fp;
    struct stat st;
    VSTRING *line_buffer;
    DICT_PCRE_RULE *last_rule = 0;
    DICT_PCRE_RULE *rule;
    int     lineno = 0;
    int     nesting = 0;
    char   *p;

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags,
			       "%s:%s map requires O_RDONLY access mode",
			       DICT_TYPE_PCRE, mapname));

    /*
     * Open the configuration file.
     */
    if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
	return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags,
			       "open %s: %m", mapname));
    if (fstat(vstream_fileno(map_fp), &st) < 0)
	msg_fatal("fstat %s: %m", mapname);

    line_buffer = vstring_alloc(100);

    dict_pcre = (DICT_PCRE *) dict_alloc(DICT_TYPE_PCRE, mapname,
					 sizeof(*dict_pcre));
    dict_pcre->dict.lookup = dict_pcre_lookup;
    dict_pcre->dict.close = dict_pcre_close;
    dict_pcre->dict.flags = dict_flags | DICT_FLAG_PATTERN;
    if (dict_flags & DICT_FLAG_FOLD_MUL)
	dict_pcre->dict.fold_buf = vstring_alloc(10);
    dict_pcre->head = 0;
    dict_pcre->expansion_buf = 0;

    if (dict_pcre_init == 0) {
	pcre_malloc = (void *(*) (size_t)) mymalloc;
	pcre_free = (void (*) (void *)) myfree;
	dict_pcre_init = 1;
    }
    dict_pcre->dict.owner.uid = st.st_uid;
    dict_pcre->dict.owner.status = (st.st_uid != 0);

    /*
     * Parse the pcre table.
     */
    while (readlline(line_buffer, map_fp, &lineno)) {
	p = vstring_str(line_buffer);
	trimblanks(p, 0)[0] = 0;		/* Trim space at end */
	if (*p == 0)
	    continue;
	rule = dict_pcre_parse_rule(mapname, lineno, p, nesting, dict_flags);
	if (rule == 0)
	    continue;
	if (rule->op == DICT_PCRE_OP_IF) {
	    nesting++;
	} else if (rule->op == DICT_PCRE_OP_ENDIF) {
	    nesting--;
	}
	if (last_rule == 0)
	    dict_pcre->head = rule;
	else
	    last_rule->next = rule;
	last_rule = rule;
    }

    if (nesting)
	msg_warn("pcre map %s, line %d: more IFs than ENDIFs",
		 mapname, lineno);

    vstring_free(line_buffer);
    vstream_fclose(map_fp);

    return (DICT_DEBUG (&dict_pcre->dict));
}
示例#14
0
DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
{
    char   *myname = "dict_ldap_open";
    DICT_LDAP *dict_ldap;
    VSTRING *url_list;
    char   *s;
    char   *h;
    char   *server_host;
    char   *domainlist;
    char   *scope;
    char   *attr;
    int     tmp;

    if (msg_verbose)
	msg_info("%s: Using LDAP source %s", myname, ldapsource);

    dict_ldap = (DICT_LDAP *) dict_alloc(DICT_TYPE_LDAP, ldapsource,
					 sizeof(*dict_ldap));
    dict_ldap->dict.lookup = dict_ldap_lookup;
    dict_ldap->dict.close = dict_ldap_close;
    dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED;

    dict_ldap->ld = NULL;
    dict_ldap->parser = cfg_parser_alloc(ldapsource);
    dict_ldap->ldapsource = mystrdup(ldapsource);

    server_host = cfg_get_str(dict_ldap->parser, "server_host",
			      "localhost", 1, 0);

    /*
     * get configured value of "server_port"; default to LDAP_PORT (389)
     */
    dict_ldap->server_port =
	cfg_get_int(dict_ldap->parser, "server_port", LDAP_PORT, 0, 0);

    /*
     * Define LDAP Version.
     */
    dict_ldap->version = cfg_get_int(dict_ldap->parser, "version", 2, 2, 0);
    switch (dict_ldap->version) {
    case 2:
	dict_ldap->version = LDAP_VERSION2;
	break;
    case 3:
	dict_ldap->version = LDAP_VERSION3;
	break;
    default:
	msg_warn("%s: %s Unknown version %d.", myname, ldapsource,
		 dict_ldap->version);
	dict_ldap->version = LDAP_VERSION2;
    }

#if defined(LDAP_API_FEATURE_X_OPENLDAP)
    dict_ldap->ldap_ssl = 0;
#endif

    url_list = vstring_alloc(32);
    s = server_host;
    while ((h = mystrtok(&s, " \t\n\r,")) != NULL) {
#if defined(LDAP_API_FEATURE_X_OPENLDAP)

	/*
	 * Convert (host, port) pairs to LDAP URLs
	 */
	if (ldap_is_ldap_url(h)) {
	    LDAPURLDesc *url_desc;
	    int     rc;

	    if ((rc = ldap_url_parse(h, &url_desc)) != 0) {
		msg_error("%s: error parsing URL %s: %d: %s; skipping", myname,
			  h, rc, ldap_err2string(rc));
		continue;
	    }
	    if (strcasecmp(url_desc->lud_scheme, "ldap") != 0 &&
		dict_ldap->version != LDAP_VERSION3) {
		msg_warn("%s: URL scheme %s requires protocol version 3", myname,
			 url_desc->lud_scheme);
		dict_ldap->version = LDAP_VERSION3;
	    }
	    if (strcasecmp(url_desc->lud_scheme, "ldaps") == 0)
		dict_ldap->ldap_ssl = 1;
	    ldap_free_urldesc(url_desc);
	    vstring_sprintf_append(url_list, " %s", h);
	} else {
	    if (strrchr(h, ':'))
		vstring_sprintf_append(url_list, " ldap://%s", h);
	    else
		vstring_sprintf_append(url_list, " ldap://%s:%d", h,
				       dict_ldap->server_port);
	}
#else
	vstring_sprintf_append(url_list, " %s", h);
#endif
    }
    dict_ldap->server_host =
	mystrdup(VSTRING_LEN(url_list) > 0 ? vstring_str(url_list) + 1 : "");

#if defined(LDAP_API_FEATURE_X_OPENLDAP)

    /*
     * With URL scheme, clear port to normalize connection cache key
     */
    dict_ldap->server_port = LDAP_PORT;
    if (msg_verbose)
	msg_info("%s: %s server_host URL is %s", myname, ldapsource,
		 dict_ldap->server_host);
#endif
    myfree(server_host);
    vstring_free(url_list);

    /*
     * Scope handling thanks to Carsten Hoeger of SuSE.
     */
    scope = cfg_get_str(dict_ldap->parser, "scope", "sub", 1, 0);

    if (strcasecmp(scope, "one") == 0) {
	dict_ldap->scope = LDAP_SCOPE_ONELEVEL;
    } else if (strcasecmp(scope, "base") == 0) {
	dict_ldap->scope = LDAP_SCOPE_BASE;
    } else if (strcasecmp(scope, "sub") == 0) {
	dict_ldap->scope = LDAP_SCOPE_SUBTREE;
    } else {
	msg_warn("%s: %s: Unrecognized value %s specified for scope; using sub",
		 myname, ldapsource, scope);
	dict_ldap->scope = LDAP_SCOPE_SUBTREE;
    }

    myfree(scope);

    dict_ldap->search_base = cfg_get_str(dict_ldap->parser, "search_base",
					 "", 0, 0);

    domainlist = cfg_get_str(dict_ldap->parser, "domain", "", 0, 0);
    if (*domainlist) {
#ifdef MATCH_FLAG_NONE
	dict_ldap->domain = match_list_init(MATCH_FLAG_NONE,
					    domainlist, 1, match_string);
#else
	dict_ldap->domain = match_list_init(domainlist, 1, match_string);
#endif
	if (dict_ldap->domain == NULL)
	    msg_warn("%s: domain match list creation using \"%s\" failed, will continue without it",
		     myname, domainlist);
	if (msg_verbose)
	    msg_info("%s: domain list created using \"%s\"", myname,
		     domainlist);
    } else {
	dict_ldap->domain = NULL;
    }
    myfree(domainlist);

    /*
     * get configured value of "timeout"; default to 10 seconds
     * 
     * Thanks to Manuel Guesdon for spotting that this wasn't really getting
     * set.
     */
    dict_ldap->timeout = cfg_get_int(dict_ldap->parser, "timeout",
				     10, 0, 0);

    dict_ldap->query_filter =
	cfg_get_str(dict_ldap->parser, "query_filter",
		    "(mailacceptinggeneralid=%s)", 0, 0);

    dict_ldap->result_filter =
	cfg_get_str(dict_ldap->parser, "result_filter", "%s", 0, 0);

    if (strcmp(dict_ldap->result_filter, "%s") == 0) {
	myfree(dict_ldap->result_filter);
	dict_ldap->result_filter = NULL;
    }
    attr = cfg_get_str(dict_ldap->parser, "result_attribute",
		       "maildrop", 0, 0);
    dict_ldap->result_attributes = argv_split(attr, " ,\t\r\n");
    dict_ldap->num_attributes = dict_ldap->result_attributes->argc;
    myfree(attr);

    attr = cfg_get_str(dict_ldap->parser, "special_result_attribute",
		       "", 0, 0);
    if (*attr) {
	argv_split_append(dict_ldap->result_attributes, attr, " ,\t\r\n");
    }
    myfree(attr);

    /*
     * get configured value of "bind"; default to true
     */
    dict_ldap->bind = cfg_get_bool(dict_ldap->parser, "bind", 1);

    /*
     * get configured value of "bind_dn"; default to ""
     */
    dict_ldap->bind_dn = cfg_get_str(dict_ldap->parser, "bind_dn", "", 0, 0);

    /*
     * get configured value of "bind_pw"; default to ""
     */
    dict_ldap->bind_pw = cfg_get_str(dict_ldap->parser, "bind_pw", "", 0, 0);

    /*
     * get configured value of "cache"; default to false
     */
    tmp = cfg_get_bool(dict_ldap->parser, "cache", 0);
    if (tmp)
	msg_warn("%s: %s ignoring cache", myname, ldapsource);

    /*
     * get configured value of "cache_expiry"; default to 30 seconds
     */
    tmp = cfg_get_int(dict_ldap->parser, "cache_expiry", -1, 0, 0);
    if (tmp >= 0)
	msg_warn("%s: %s ignoring cache_expiry", myname, ldapsource);

    /*
     * get configured value of "cache_size"; default to 32k
     */
    tmp = cfg_get_int(dict_ldap->parser, "cache_size", -1, 0, 0);
    if (tmp >= 0)
	msg_warn("%s: %s ignoring cache_size", myname, ldapsource);

    /*
     * get configured value of "recursion_limit"; default to 1000
     */
    dict_ldap->recursion_limit = cfg_get_int(dict_ldap->parser,
					     "recursion_limit", 1000, 1, 0);

    /*
     * get configured value of "expansion_limit"; default to 0
     */
    dict_ldap->expansion_limit = cfg_get_int(dict_ldap->parser,
					     "expansion_limit", 0, 0, 0);

    /*
     * get configured value of "size_limit"; default to expansion_limit
     */
    dict_ldap->size_limit = cfg_get_int(dict_ldap->parser, "size_limit",
					dict_ldap->expansion_limit,
					0, 0);

    /*
     * Alias dereferencing suggested by Mike Mattice.
     */
    dict_ldap->dereference = cfg_get_int(dict_ldap->parser, "dereference",
					 0, 0, 0);
    if (dict_ldap->dereference < 0 || dict_ldap->dereference > 3) {
	msg_warn("%s: %s Unrecognized value %d specified for dereference; using 0",
		 myname, ldapsource, dict_ldap->dereference);
	dict_ldap->dereference = 0;
    }
    /* Referral chasing */
    dict_ldap->chase_referrals = cfg_get_bool(dict_ldap->parser,
					      "chase_referrals", 0);

#ifdef LDAP_API_FEATURE_X_OPENLDAP

    /*
     * TLS options
     */
    /* get configured value of "start_tls"; default to no */
    dict_ldap->start_tls = cfg_get_bool(dict_ldap->parser, "start_tls", 0);
    if (dict_ldap->start_tls && dict_ldap->version < LDAP_VERSION3) {
	msg_warn("%s: %s start_tls requires protocol version 3",
		 myname, ldapsource);
	dict_ldap->version = LDAP_VERSION3;
    }
    /* get configured value of "tls_require_cert"; default to no */
    dict_ldap->tls_require_cert = cfg_get_bool(dict_ldap->parser,
					       "tls_require_cert", 0);

    /* get configured value of "tls_ca_cert_file"; default "" */
    dict_ldap->tls_ca_cert_file = cfg_get_str(dict_ldap->parser,
					      "tls_ca_cert_file", "", 0, 0);

    /* get configured value of "tls_ca_cert_dir"; default "" */
    dict_ldap->tls_ca_cert_dir = cfg_get_str(dict_ldap->parser,
					     "tls_ca_cert_dir", "", 0, 0);

    /* get configured value of "tls_cert"; default "" */
    dict_ldap->tls_cert = cfg_get_str(dict_ldap->parser, "tls_cert",
				      "", 0, 0);

    /* get configured value of "tls_key"; default "" */
    dict_ldap->tls_key = cfg_get_str(dict_ldap->parser, "tls_key",
				     "", 0, 0);

    /* get configured value of "tls_random_file"; default "" */
    dict_ldap->tls_random_file = cfg_get_str(dict_ldap->parser,
					     "tls_random_file", "", 0, 0);

    /* get configured value of "tls_cipher_suite"; default "" */
    dict_ldap->tls_cipher_suite = cfg_get_str(dict_ldap->parser,
					      "tls_cipher_suite", "", 0, 0);
#endif

    /*
     * Debug level.
     */
#if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN)
    dict_ldap->debuglevel = cfg_get_int(dict_ldap->parser, "debuglevel",
					0, 0, 0);
#endif

    /*
     * Find or allocate shared LDAP connection container.
     */
    dict_ldap_conn_find(dict_ldap);

    /*
     * Return the new dict_ldap structure.
     */
    return (DICT_DEBUG (&dict_ldap->dict));
}
示例#15
0
DICT   *dict_union_open(const char *name, int open_flags, int dict_flags)
{
    static const char myname[] = "dict_union_open";
    DICT_UNION *dict_union;
    char   *saved_name = 0;
    char   *dict_type_name;
    ARGV   *argv = 0;
    char  **cpp;
    DICT   *dict;
    int     match_flags = 0;
    struct DICT_OWNER aggr_owner;
    size_t  len;

    /*
     * Clarity first. Let the optimizer worry about redundant code.
     */
#define DICT_UNION_RETURN(x) do { \
	      if (saved_name != 0) \
	          myfree(saved_name); \
	      if (argv != 0) \
	          argv_free(argv); \
	      return (x); \
	  } while (0)

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name,
					 open_flags, dict_flags,
				  "%s:%s map requires O_RDONLY access mode",
					 DICT_TYPE_UNION, name));

    /*
     * Split the table name into its constituent parts.
     */
    if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
	|| *(saved_name = mystrndup(name + 1, len - 2)) == 0
	|| ((argv = argv_splitq(saved_name, CHARS_COMMA_SP, CHARS_BRACE)),
	    (argv->argc == 0)))
	DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name,
					 open_flags, dict_flags,
					 "bad syntax: \"%s:%s\"; "
					 "need \"%s:{type:name...}\"",
					 DICT_TYPE_UNION, name,
					 DICT_TYPE_UNION));

    /*
     * The least-trusted table in the set determines the over-all trust
     * level. The first table determines the pattern-matching flags.
     */
    DICT_OWNER_AGGREGATE_INIT(aggr_owner);
    for (cpp = argv->argv; (dict_type_name = *cpp) != 0; cpp++) {
	if (msg_verbose)
	    msg_info("%s: %s", myname, dict_type_name);
	if (strchr(dict_type_name, ':') == 0)
	    DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name,
					     open_flags, dict_flags,
					     "bad syntax: \"%s:%s\"; "
					     "need \"%s:{type:name...}\"",
					     DICT_TYPE_UNION, name,
					     DICT_TYPE_UNION));
	if ((dict = dict_handle(dict_type_name)) == 0)
	    dict = dict_open(dict_type_name, open_flags, dict_flags);
	dict_register(dict_type_name, dict);
	DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
	if (cpp == argv->argv)
	    match_flags = dict->flags & (DICT_FLAG_FIXED | DICT_FLAG_PATTERN);
    }

    /*
     * Bundle up the result.
     */
    dict_union =
	(DICT_UNION *) dict_alloc(DICT_TYPE_UNION, name, sizeof(*dict_union));
    dict_union->dict.lookup = dict_union_lookup;
    dict_union->dict.close = dict_union_close;
    dict_union->dict.flags = dict_flags | match_flags;
    dict_union->dict.owner = aggr_owner;
    dict_union->re_buf = vstring_alloc(100);
    dict_union->map_union = argv;
    argv = 0;
    DICT_UNION_RETURN(DICT_DEBUG (&dict_union->dict));
}
示例#16
0
DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
{
    const char myname[] = "dict_cidr_open";
    DICT_CIDR *dict_cidr;
    VSTREAM *map_fp = 0;
    struct stat st;
    VSTRING *line_buffer = 0;
    VSTRING *why = 0;
    DICT_CIDR_ENTRY *rule;
    DICT_CIDR_ENTRY *last_rule = 0;
    int     last_line = 0;
    int     lineno;
    int     nesting = 0;
    DICT_CIDR_ENTRY **rule_stack = 0;
    MVECT   mvect;

    /*
     * Let the optimizer worry about eliminating redundant code.
     */
#define DICT_CIDR_OPEN_RETURN(d) do { \
	DICT *__d = (d); \
	if (map_fp != 0 && vstream_fclose(map_fp)) \
	    msg_fatal("cidr map %s: read error: %m", mapname); \
	if (line_buffer != 0) \
	    vstring_free(line_buffer); \
	if (why != 0) \
	    vstring_free(why); \
	return (__d); \
    } while (0)

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname,
					     open_flags, dict_flags,
				  "%s:%s map requires O_RDONLY access mode",
					     DICT_TYPE_CIDR, mapname));

    /*
     * Open the configuration file.
     */
    if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
	DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname,
					     open_flags, dict_flags,
					     "open %s: %m", mapname));
    if (fstat(vstream_fileno(map_fp), &st) < 0)
	msg_fatal("fstat %s: %m", mapname);

    line_buffer = vstring_alloc(100);
    why = vstring_alloc(100);

    /*
     * XXX Eliminate unnecessary queries by setting a flag that says "this
     * map matches network addresses only".
     */
    dict_cidr = (DICT_CIDR *) dict_alloc(DICT_TYPE_CIDR, mapname,
					 sizeof(*dict_cidr));
    dict_cidr->dict.lookup = dict_cidr_lookup;
    dict_cidr->dict.close = dict_cidr_close;
    dict_cidr->dict.flags = dict_flags | DICT_FLAG_PATTERN;
    dict_cidr->head = 0;

    dict_cidr->dict.owner.uid = st.st_uid;
    dict_cidr->dict.owner.status = (st.st_uid != 0);

    while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
	rule = dict_cidr_parse_rule(vstring_str(line_buffer), lineno,
				    nesting, why);
	if (rule == 0) {
	    msg_warn("cidr map %s, line %d: %s: skipping this rule",
		     mapname, lineno, vstring_str(why));
	    continue;
	}
	if (rule->cidr_info.op == CIDR_MATCH_OP_IF) {
	    if (rule_stack == 0)
		rule_stack = (DICT_CIDR_ENTRY **) mvect_alloc(&mvect,
					   sizeof(*rule_stack), nesting + 1,
						(MVECT_FN) 0, (MVECT_FN) 0);
	    else
		rule_stack =
		    (DICT_CIDR_ENTRY **) mvect_realloc(&mvect, nesting + 1);
	    rule_stack[nesting] = rule;
	    nesting++;
	} else if (rule->cidr_info.op == CIDR_MATCH_OP_ENDIF) {
	    DICT_CIDR_ENTRY *if_rule;

	    if (nesting-- <= 0)
		/* Already handled in dict_cidr_parse_rule(). */
		msg_panic("%s: ENDIF without IF", myname);
	    if_rule = rule_stack[nesting];
	    if (if_rule->cidr_info.op != CIDR_MATCH_OP_IF)
		msg_panic("%s: unexpected rule stack element type %d",
			  myname, if_rule->cidr_info.op);
	    if_rule->cidr_info.block_end = &(rule->cidr_info);
	}
	if (last_rule == 0)
	    dict_cidr->head = rule;
	else
	    last_rule->cidr_info.next = &(rule->cidr_info);
	last_rule = rule;
    }

    while (nesting-- > 0)
	msg_warn("cidr map %s, line %d: IF has no matching ENDIF",
		 mapname, rule_stack[nesting]->lineno);

    if (rule_stack)
	(void) mvect_free(&mvect);

    DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict));
}