dlz_ldap_driver.c

来自「非常好的dns解析软件」· C语言 代码 · 共 1,340 行 · 第 1/3 页

C
1,340
字号
/* * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE * USE OR PERFORMANCE OF THIS SOFTWARE. * * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was * conceived and contributed by Rob Butler. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE * USE OR PERFORMANCE OF THIS SOFTWARE. *//* * Copyright (C) 1999-2001  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#ifdef DLZ_LDAP#include <config.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <dns/log.h>#include <dns/sdlz.h>#include <dns/result.h>#include <isc/mem.h>#include <isc/platform.h>#include <isc/print.h>#include <isc/result.h>#include <isc/string.h>#include <isc/util.h>#include <named/globals.h>#include <dlz/sdlz_helper.h>#include <dlz/dlz_ldap_driver.h>/* * Need older API functions from ldap.h. */#define LDAP_DEPRECATED 1#include <ldap.h>#define SIMPLE "simple"#define KRB41 "krb41"#define KRB42 "krb42"#define V2 "v2"#define V3 "v3"static dns_sdlzimplementation_t *dlz_ldap = NULL;#define dbc_search_limit 30#define ALLNODES 1#define ALLOWXFR 2#define AUTHORITY 3#define FINDZONE 4#define LOOKUP 5/*% * Structure to hold everthing needed by this "instance" of the LDAP * driver remember, the driver code is only loaded once, but may have * many separate instances. */typedef struct {#ifdef ISC_PLATFORM_USETHREADS	db_list_t    *db; /*%< handle to a list of DB */#else	dbinstance_t *db; /*%< handle to db */#endif	int method;	/*%< security authentication method */	char *user;	/*%< who is authenticating */	char *cred;	/*%< password for simple authentication method */	int protocol;	/*%< LDAP communication protocol version */	char *hosts;	/*%< LDAP server hosts */} ldap_instance_t;/* forward references */static isc_result_tdlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);static voiddlz_ldap_destroy(void *driverarg, void *dbdata);/* * Private methods *//*% checks that the LDAP URL parameters make sense */static isc_result_tdlz_ldap_checkURL(char *URL, int attrCnt, const char *msg) {	isc_result_t result = ISC_R_SUCCESS;	int ldap_result;	LDAPURLDesc *ldap_url = NULL;	if (!ldap_is_ldap_url(URL)) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "%s query is not a valid LDAP URL", msg);		result = ISC_R_FAILURE;		goto cleanup;	}	ldap_result = ldap_url_parse(URL, &ldap_url);	if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "parsing %s query failed", msg);		result = ISC_R_FAILURE;		goto cleanup;	}	if (ldap_count_values(ldap_url->lud_attrs) < attrCnt) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "%s query must specify at least "			      "%d attributes to return",			      msg, attrCnt);		result = ISC_R_FAILURE;		goto cleanup;	}	if (ldap_url->lud_host != NULL) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "%s query must not specify a host", msg);		result = ISC_R_FAILURE;		goto cleanup;	}	if (ldap_url->lud_port != 389) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "%s query must not specify a port", msg);		result = ISC_R_FAILURE;		goto cleanup;	}	if (ldap_url->lud_dn == NULL || strlen (ldap_url->lud_dn) < 1) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "%s query must specify a search base", msg);		result = ISC_R_FAILURE;		goto cleanup;	}	if (ldap_url->lud_exts != NULL || ldap_url->lud_crit_exts != 0) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "%s uses extensions. "			      "The driver does not support LDAP extensions.",			      msg);		result = ISC_R_FAILURE;		goto cleanup;	} cleanup:	if (ldap_url != NULL)		ldap_free_urldesc(ldap_url);	return result;}/*% Connects / reconnects to LDAP server */static isc_result_tdlz_ldap_connect(ldap_instance_t *dbi, dbinstance_t *dbc) {	isc_result_t result;	int ldap_result;	/* if we have a connection, get ride of it. */	if (dbc->dbconn != NULL) {		ldap_unbind_s((LDAP *) dbc->dbconn);		dbc->dbconn = NULL;	}	/* now connect / reconnect. */	/* initialize. */	dbc->dbconn = ldap_init(dbi->hosts, LDAP_PORT);	if (dbc->dbconn == NULL)		return ISC_R_NOMEMORY;	/* set protocol version. */	ldap_result = ldap_set_option((LDAP *) dbc->dbconn,				      LDAP_OPT_PROTOCOL_VERSION,				      &(dbi->protocol));	if (ldap_result != LDAP_SUCCESS) {		result = ISC_R_NOPERM;		goto cleanup;	}	/* "bind" to server.  i.e. send username / pass */	ldap_result = ldap_bind_s((LDAP *) dbc->dbconn, dbi->user,				  dbi->cred, dbi->method);	if (ldap_result != LDAP_SUCCESS) {		result = ISC_R_FAILURE;		goto cleanup;	}	return ISC_R_SUCCESS; cleanup:	/* cleanup if failure. */	if (dbc->dbconn != NULL) {		ldap_unbind_s((LDAP *) dbc->dbconn);		dbc->dbconn = NULL;	}	return result;}#ifdef ISC_PLATFORM_USETHREADS/*% * Properly cleans up a list of database instances. * This function is only used when the driver is compiled for * multithreaded operation. */static voidldap_destroy_dblist(db_list_t *dblist){	dbinstance_t *ndbi = NULL;	dbinstance_t *dbi = NULL;	/* get the first DBI in the list */	ndbi = ISC_LIST_HEAD(*dblist);	/* loop through the list */	while (ndbi != NULL) {		dbi = ndbi;		/* get the next DBI in the list */		ndbi = ISC_LIST_NEXT(dbi, link);		/* release DB connection */		if (dbi->dbconn != NULL)			ldap_unbind_s((LDAP *) dbi->dbconn);		/* release all memory that comprised a DBI */		destroy_sqldbinstance(dbi);	}	/* release memory for the list structure */	isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));}/*% * Loops through the list of DB instances, attempting to lock * on the mutex.  If successful, the DBI is reserved for use * and the thread can perform queries against the database. * If the lock fails, the next one in the list is tried. * looping continues until a lock is obtained, or until * the list has been searched dbc_search_limit times. * This function is only used when the driver is compiled for * multithreaded operation. */static dbinstance_t *ldap_find_avail_conn(db_list_t *dblist){	dbinstance_t *dbi = NULL;	dbinstance_t *head;	int count = 0;	/* get top of list */	head = dbi = ISC_LIST_HEAD(*dblist);	/* loop through list */	while (count < dbc_search_limit) {		/* try to lock on the mutex */		if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)			return dbi; /* success, return the DBI for use. */		/* not successful, keep trying */		dbi = ISC_LIST_NEXT(dbi, link);		/* check to see if we have gone to the top of the list. */		if (dbi == NULL) {			count++;			dbi = head;		}	}	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,		      "LDAP driver unable to find available connection "		      "after searching %d times",		      count);	return NULL;}#endif /* ISC_PLATFORM_USETHREADS */static isc_result_tldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,		     void *ptr, isc_boolean_t allnodes){	isc_result_t result = ISC_R_SUCCESS;	int i = 0;	int j;	int len;	char *attribute = NULL;	LDAPMessage *entry;	char *endp = NULL;	char *host = NULL;	char *type = NULL;	char *data = NULL;	char **vals = NULL;	int ttl;	/* make sure there are at least some attributes to process. */	REQUIRE(attrs != NULL || attrs[0] != NULL);	/* get the first entry to process */	entry = ldap_first_entry(dbc, msg);	if (entry == NULL) {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,			      "LDAP no entries to process.");		return ISC_R_FAILURE;	}	/* loop through all entries returned */	while (entry != NULL) {		/* reset for this loop */		ttl = 0;		len = 0;		i = 0;		attribute = attrs[i];		/* determine how much space we need for data string */		for (j=0; attrs[j] != NULL; j++) {			/* get the list of values for this attribute. */			vals = ldap_get_values(dbc, entry, attrs[j]);			/* skip empty attributes. */			if (vals == NULL || ldap_count_values(vals) < 1)				continue;			/*			 * we only use the first value.  this driver			 * does not support multi-valued attributes.			 */			len = len + strlen(vals[0]) + 1;			/* free vals for next loop */			ldap_value_free(vals);		} /* end for (j=0; attrs[j] != NULL, j++) loop */		/* allocate memory for data string */		data = isc_mem_allocate(ns_g_mctx, len + 1);		if (data == NULL) {			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "LDAP driver unable to allocate memory "				      "while processing results");			result = ISC_R_FAILURE;			goto cleanup;		}		/*		 * Make sure data is null termed at the beginning so		 * we can check if any data was stored to it later.		 */		data[0] = '\0';		/* reset j to re-use below */		j = 0;		/* loop through the attributes in the order specified. */		while (attribute != NULL) {			/* get the list of values for this attribute. */			vals = ldap_get_values(dbc, entry, attribute);			/* skip empty attributes. */			if (vals == NULL || vals[0] == NULL) {				/* increment attibute pointer */				attribute = attrs[++i];				/* start loop over */				continue;			}			/*			 * j initially = 0.  Increment j each time we			 * set a field that way next loop will set			 * next field.			 */			switch(j) {			case 0:				j++;				/*				 * convert text to int, make sure it				 * worked right				 */				ttl = strtol(vals[0], &endp, 10);				if (*endp != '\0' || ttl < 0) {					isc_log_write(dns_lctx,						      DNS_LOGCATEGORY_DATABASE,						      DNS_LOGMODULE_DLZ,						      ISC_LOG_ERROR,						      "LDAP driver ttl must "						      "be a postive number");					goto cleanup;				}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?