Ejemplo n.º 1
0
int     db_common_check_domain(void *ctxPtr, const char *addr)
{
    DB_COMMON_CTX *ctx = (DB_COMMON_CTX *) ctxPtr;
    char   *domain;

    if (ctx->domain) {
	if ((domain = strrchr(addr, '@')) != NULL)
	    ++domain;
	if (domain == NULL || domain == addr + 1)
	    return (0);
	if (match_list_match(ctx->domain, domain) == 0)
	    return (0);
    }
    return (1);
}
Ejemplo n.º 2
0
static const char *dict_ldap_lookup(DICT *dict, const char *name)
{
    char   *myname = "dict_ldap_lookup";
    DICT_LDAP *dict_ldap = (DICT_LDAP *) dict;
    LDAPMessage *res = 0;
    static VSTRING *result;
    struct timeval tv;
    VSTRING *escaped_name = 0,
           *filter_buf = 0;
    int     rc = 0;
    int     sizelimit;
    char   *sub,
           *end;

    dict_errno = 0;

    if (msg_verbose)
	msg_info("%s: In dict_ldap_lookup", myname);

    /*
     * If they specified a domain list for this map, then only search for
     * addresses in domains on the list. This can significantly reduce the
     * load on the LDAP server.
     */
    if (dict_ldap->domain) {
	const char *p = strrchr(name, '@');

	if (p == 0 || p == name ||
	    match_list_match(dict_ldap->domain, ++p) == 0) {
	    if (msg_verbose)
		msg_info("%s: domain of %s not found in domain list", myname,
			 name);
	    return (0);
	}
    }

    /*
     * Initialize the result holder.
     */
    if (result == 0)
	result = vstring_alloc(2);
    vstring_strcpy(result, "");

    /*
     * Because the connection may be shared and invalidated via queries for
     * another map, update private copy of "ld" from shared connection
     * container.
     */
    dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld;

    /*
     * Connect to the LDAP server, if necessary.
     */
    if (dict_ldap->ld == NULL) {
	if (msg_verbose)
	    msg_info
		("%s: No existing connection for LDAP source %s, reopening",
		 myname, dict_ldap->ldapsource);

	dict_ldap_connect(dict_ldap);

	/*
	 * if dict_ldap_connect() set dict_errno, abort.
	 */
	if (dict_errno)
	    return (0);
    } else if (msg_verbose)
	msg_info("%s: Using existing connection for LDAP source %s",
		 myname, dict_ldap->ldapsource);

    /*
     * Connection caching, means that the connection handle may have the
     * wrong size limit. Re-adjust before each query. This is cheap, just
     * sets a field in the ldap connection handle. We also do this in the
     * connect code, because we sometimes reconnect (below) in the middle of
     * a query.
     */
    sizelimit = dict_ldap->size_limit ? dict_ldap->size_limit : LDAP_NO_LIMIT;
    if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT, &sizelimit)
	!= LDAP_OPT_SUCCESS)
	msg_warn("%s: %s: Unable to set query result size limit to %ld.",
		 myname, dict_ldap->ldapsource, dict_ldap->size_limit);

    /*
     * Prepare the query.
     */
    tv.tv_sec = dict_ldap->timeout;
    tv.tv_usec = 0;
    escaped_name = vstring_alloc(20);
    filter_buf = vstring_alloc(30);

    /*
     * If any characters in the supplied address should be escaped per RFC
     * 2254, do so. Thanks to Keith Stevenson and Wietse. And thanks to
     * Samuel Tardieu for spotting that wildcard searches were being done in
     * the first place, which prompted the ill-conceived lookup_wildcards
     * parameter and then this more comprehensive mechanism.
     */
    end = (char *) name + strlen((char *) name);
    sub = (char *) strpbrk((char *) name, "*()\\\0");
    if (sub && sub != end) {
	if (msg_verbose)
	    msg_info("%s: Found character(s) in %s that must be escaped",
		     myname, name);
	for (sub = (char *) name; sub != end; sub++) {
	    switch (*sub) {
	    case '*':
		vstring_strcat(escaped_name, "\\2a");
		break;
	    case '(':
		vstring_strcat(escaped_name, "\\28");
		break;
	    case ')':
		vstring_strcat(escaped_name, "\\29");
		break;
	    case '\\':
		vstring_strcat(escaped_name, "\\5c");
		break;
	    case '\0':
		vstring_strcat(escaped_name, "\\00");
		break;
	    default:
		vstring_strncat(escaped_name, sub, 1);
	    }
	}
	if (msg_verbose)
	    msg_info("%s: After escaping, it's %s", myname,
		     vstring_str(escaped_name));
    } else
	vstring_strcpy(escaped_name, (char *) name);

    /*
     * Does the supplied query_filter even include a substitution?
     */
    if ((char *) strchr(dict_ldap->query_filter, '%') == NULL) {

	/*
	 * No, log the fact and continue.
	 */
	msg_warn("%s: %s: Fixed query_filter %s is probably useless",
		 myname, dict_ldap->ldapsource, dict_ldap->query_filter);
	vstring_strcpy(filter_buf, dict_ldap->query_filter);
    } else {
	dict_ldap_expand_filter(dict_ldap->ldapsource, dict_ldap->query_filter,
				vstring_str(escaped_name), filter_buf);
    }

    /*
     * On to the search.
     */
    if (msg_verbose)
	msg_info("%s: Searching with filter %s", myname,
		 vstring_str(filter_buf));

    rc = ldap_search_st(dict_ldap->ld, dict_ldap->search_base,
			dict_ldap->scope,
			vstring_str(filter_buf),
			dict_ldap->result_attributes->argv,
			0, &tv, &res);

    if (rc == LDAP_SERVER_DOWN) {
	if (msg_verbose)
	    msg_info("%s: Lost connection for LDAP source %s, reopening",
		     myname, dict_ldap->ldapsource);

	ldap_unbind(dict_ldap->ld);
	dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0;
	dict_ldap_connect(dict_ldap);

	/*
	 * if dict_ldap_connect() set dict_errno, abort.
	 */
	if (dict_errno)
	    return (0);

	rc = ldap_search_st(dict_ldap->ld, dict_ldap->search_base,
			    dict_ldap->scope,
			    vstring_str(filter_buf),
			    dict_ldap->result_attributes->argv,
			    0, &tv, &res);

    }
    if (rc == LDAP_SUCCESS) {

	/*
	 * Search worked; extract the requested result_attribute.
	 */

	dict_ldap_get_values(dict_ldap, res, result);

	/*
	 * OpenLDAP's ldap_next_attribute returns a bogus
	 * LDAP_DECODING_ERROR; I'm ignoring that for now.
	 */

	rc = dict_ldap_get_errno(dict_ldap->ld);
	if (rc != LDAP_SUCCESS && rc != LDAP_DECODING_ERROR)
	    msg_warn
		("%s: Had some trouble with entries returned by search: %s",
		 myname, ldap_err2string(rc));

	if (msg_verbose)
	    msg_info("%s: Search returned %s", myname,
		     VSTRING_LEN(result) >
		     0 ? vstring_str(result) : "nothing");
    } else {

	/*
	 * Rats. The search didn't work.
	 */
	msg_warn("%s: Search error %d: %s ", myname, rc,
		 ldap_err2string(rc));

	/*
	 * Tear down the connection so it gets set up from scratch on the
	 * next lookup.
	 */
	ldap_unbind(dict_ldap->ld);
	dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0;

	/*
	 * And tell the caller to try again later.
	 */
	dict_errno = DICT_ERR_RETRY;
    }

    /*
     * Cleanup.
     */
    if (res != 0)
	ldap_msgfree(res);
    if (filter_buf != 0)
	vstring_free(filter_buf);
    if (escaped_name != 0)
	vstring_free(escaped_name);

    /*
     * If we had an error, return nothing, Otherwise, return the result, if
     * any.
     */
    return (VSTRING_LEN(result) > 0 && !dict_errno ? vstring_str(result) : 0);
}