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 + -
显示快捷键?