⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldapdb.c

📁 bind-3.2.
💻 C
字号:
/* * ldapdb.c version 0.9 * * Copyright (C) 2002 Stig Venaas * * 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. *//* * If you are using an old LDAP API uncomment the define below. Only do this * if you know what you're doing or get compilation errors on ldap_memfree(). *//* #define RFC1823API */#include <config.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/result.h>#include <isc/util.h>#include <isc/thread.h>#include <dns/sdb.h>#include <named/globals.h>#include <named/log.h>#include <ldap.h>#include "ldapdb.h"/* * A simple database driver for LDAP */ /* enough for name with 8 labels of max length */#define MAXNAMELEN 519static dns_sdbimplementation_t *ldapdb = NULL;struct ldapdb_data {	char *hostport;	char *hostname;	int portno;	char *base;	int defaultttl;	char *filterall;	int filteralllen;	char *filterone;	int filteronelen;	char *filtername;};/* used by ldapdb_getconn */struct ldapdb_entry {	void *index;	size_t size;	void *data;	struct ldapdb_entry *next;};static struct ldapdb_entry *ldapdb_find(struct ldapdb_entry *stack,					const void *index, size_t size) {	while (stack != NULL) {		if (stack->size == size && !memcmp(stack->index, index, size))			return stack;		stack = stack->next;	}	return NULL;}static void ldapdb_insert(struct ldapdb_entry **stack,			  struct ldapdb_entry *item) {	item->next = *stack;	*stack = item;}static void ldapdb_lock(int what) {	static isc_mutex_t lock;	switch (what) {	case 0:		isc_mutex_init(&lock);		break;	case 1:		LOCK(&lock);		break;	case -1:		UNLOCK(&lock);		break;	}}/* data == NULL means cleanup */static LDAP **ldapdb_getconn(struct ldapdb_data *data){	static struct ldapdb_entry *allthreadsdata = NULL;	struct ldapdb_entry *threaddata, *conndata;	unsigned long threadid;	if (data == NULL) {		/* cleanup */		/* lock out other threads */		ldapdb_lock(1);		while (allthreadsdata != NULL) {			threaddata = allthreadsdata;			free(threaddata->index);			while (threaddata->data != NULL) {				conndata = threaddata->data;				free(conndata->index);				if (conndata->data != NULL)					ldap_unbind((LDAP *)conndata->data);				threaddata->data = conndata->next;				free(conndata);			}			allthreadsdata = threaddata->next;			free(threaddata);		}		ldapdb_lock(-1);		return (NULL);	}	/* look for connection data for current thread */	threadid = isc_thread_self();	threaddata = ldapdb_find(allthreadsdata, &threadid, sizeof(threadid));	if (threaddata == NULL) {		/* no data for this thread, create empty connection list */		threaddata = malloc(sizeof(*threaddata));		if (threaddata == NULL)			return (NULL);		threaddata->index = malloc(sizeof(threadid));		if (threaddata->index == NULL) {			free(threaddata);			return (NULL);		}		*(unsigned long *)threaddata->index = threadid;		threaddata->size = sizeof(threadid);		threaddata->data = NULL;		/* need to lock out other threads here */		ldapdb_lock(1);		ldapdb_insert(&allthreadsdata, threaddata);		ldapdb_lock(-1);	}	/* threaddata points at the connection list for current thread */	/* look for existing connection to our server */	conndata = ldapdb_find((struct ldapdb_entry *)threaddata->data,			       data->hostport, strlen(data->hostport));	if (conndata == NULL) {		/* no connection data structure for this server, create one */		conndata = malloc(sizeof(*conndata));		if (conndata == NULL)			return (NULL);		(char *)conndata->index = data->hostport;		conndata->size = strlen(data->hostport);		conndata->data = NULL;		ldapdb_insert((struct ldapdb_entry **)&threaddata->data,			      conndata);	}	return (LDAP **)&conndata->data;}static voidldapdb_bind(struct ldapdb_data *data, LDAP **ldp){	if (*ldp != NULL)		ldap_unbind(*ldp);	*ldp = ldap_open(data->hostname, data->portno);	if (*ldp == NULL)		return;	if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) {		ldap_unbind(*ldp);		*ldp = NULL;	}}static isc_result_tldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata){	struct ldapdb_data *data = dbdata;	isc_result_t result = ISC_R_NOTFOUND;	LDAP **ldp;	LDAPMessage *res, *e;	char *fltr, *a, **vals, **names = NULL;	char type[64];#ifdef RFC1823API	void *ptr;#else	BerElement *ptr;#endif	int i, j, errno, msgid;	ldp = ldapdb_getconn(data);	if (ldp == NULL)		return (ISC_R_FAILURE);	if (*ldp == NULL) {		ldapdb_bind(data, ldp);		if (*ldp == NULL) {			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,					      "LDAP sdb zone '%s': bind failed", zone);			return (ISC_R_FAILURE);		}	}	if (name == NULL) {		fltr = data->filterall;	} else {		if (strlen(name) > MAXNAMELEN) {			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,                                      "LDAP sdb zone '%s': name %s too long", zone, name);			return (ISC_R_FAILURE);		}		sprintf(data->filtername, "%s))", name);		fltr = data->filterone;	}	msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);	if (msgid == -1) {		ldapdb_bind(data, ldp);		if (*ldp != NULL)			msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);	}	if (*ldp == NULL || msgid == -1) {		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,				      "LDAP sdb zone '%s': search failed, filter %s", zone, fltr);		return (ISC_R_FAILURE);	}	/* Get the records one by one as they arrive and return them to bind */	while ((errno = ldap_result(*ldp, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) {		LDAP *ld = *ldp;		int ttl = data->defaultttl;		/* not supporting continuation references at present */		if (errno != LDAP_RES_SEARCH_ENTRY) {			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,					      "LDAP sdb zone '%s': ldap_result returned %d", zone, errno);			ldap_msgfree(res);			return (ISC_R_FAILURE);                }		/* only one entry per result message */		e = ldap_first_entry(ld, res);		if (e == NULL) {			ldap_msgfree(res);			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,					      "LDAP sdb zone '%s': ldap_first_entry failed", zone);			return (ISC_R_FAILURE);                }		if (name == NULL) {			names = ldap_get_values(ld, e, "relativeDomainName");			if (names == NULL)				continue;		}		vals = ldap_get_values(ld, e, "dNSTTL");		if (vals != NULL) {			ttl = atoi(vals[0]);			ldap_value_free(vals);		}		for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) {			char *s;			for (s = a; *s; s++)				*s = toupper(*s);			s = strstr(a, "RECORD");			if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) {#ifndef RFC1823API				ldap_memfree(a);#endif				continue;			}			strncpy(type, a, s - a);			type[s - a] = '\0';			vals = ldap_get_values(ld, e, a);			if (vals != NULL) {				for (i = 0; vals[i] != NULL; i++) {					if (name != NULL) {						result = dns_sdb_putrr(retdata, type, ttl, vals[i]);					} else {						for (j = 0; names[j] != NULL; j++) {							result = dns_sdb_putnamedrr(retdata, names[j], type, ttl, vals[i]);							if (result != ISC_R_SUCCESS)								break;						}					};					if (result != ISC_R_SUCCESS) {						isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,								      "LDAP sdb zone '%s': dns_sdb_put... failed for %s", zone, vals[i]);						ldap_value_free(vals);#ifndef RFC1823API						ldap_memfree(a);						if (ptr != NULL)							ber_free(ptr, 0);#endif						if (name == NULL)							ldap_value_free(names);						ldap_msgfree(res);						return (ISC_R_FAILURE);					}				}				ldap_value_free(vals);			}#ifndef RFC1823API			ldap_memfree(a);#endif		}#ifndef RFC1823API		if (ptr != NULL)			ber_free(ptr, 0);#endif		if (name == NULL)			ldap_value_free(names);		/* cleanup this result */		ldap_msgfree(res);	}        return (result);}/* callback routines */static isc_result_tldapdb_lookup(const char *zone, const char *name, void *dbdata,	      dns_sdblookup_t *lookup){	return ldapdb_search(zone, name, dbdata, lookup);}static isc_result_tldapdb_allnodes(const char *zone, void *dbdata,		dns_sdballnodes_t *allnodes){	return ldapdb_search(zone, NULL, dbdata, allnodes);}static char *unhex(char *in){	static const char hexdigits[] = "0123456789abcdef";	char *p, *s = in;	int d1, d2;	while ((s = strchr(s, '%'))) {		if (!(s[1] && s[2]))			return NULL;		if ((p = strchr(hexdigits, tolower(s[1]))) == NULL)			return NULL;		d1 = p - hexdigits;		if ((p = strchr(hexdigits, tolower(s[2]))) == NULL)			return NULL;		d2 = p - hexdigits;		*s++ = d1 << 4 | d2;		memmove(s, s + 2, strlen(s) - 1);	}	return in;}static voidfree_data(struct ldapdb_data *data){	if (data->hostport != NULL)		isc_mem_free(ns_g_mctx, data->hostport);	if (data->hostname != NULL)		isc_mem_free(ns_g_mctx, data->hostname);	if (data->filterall != NULL)		isc_mem_put(ns_g_mctx, data->filterall, data->filteralllen);	if (data->filterone != NULL)		isc_mem_put(ns_g_mctx, data->filterone, data->filteronelen);        isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));}static isc_result_tldapdb_create(const char *zone, int argc, char **argv,	      void *driverdata, void **dbdata){	struct ldapdb_data *data;	char *s, *filter = NULL;	int defaultttl;	UNUSED(driverdata);	/* we assume that only one thread will call create at a time */	/* want to do this only once for all instances */	if ((argc < 2)	    || (argv[0] != strstr( argv[0], "ldap://"))	    || ((defaultttl = atoi(argv[1])) < 1))                return (ISC_R_FAILURE);        data = isc_mem_get(ns_g_mctx, sizeof(struct ldapdb_data));        if (data == NULL)                return (ISC_R_NOMEMORY);	memset(data, 0, sizeof(struct ldapdb_data));	data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));	if (data->hostport == NULL) {		free_data(data);		return (ISC_R_NOMEMORY);	}	data->defaultttl = defaultttl;	s = strchr(data->hostport, '/');	if (s != NULL) {		*s++ = '\0';		data->base = s;		/* attrs, scope, filter etc? */		s = strchr(s, '?');		if (s != NULL) {			*s++ = '\0';			/* ignore attributes */			s = strchr(s, '?');			if (s != NULL) {				*s++ = '\0';				/* ignore scope */				s = strchr(s, '?');				if (s != NULL) {					*s++ = '\0';					/* filter */					filter = s;					s = strchr(s, '?');					if (s != NULL) {						*s++ = '\0';					}					if (*filter == '\0') {						filter = NULL;					}				}			}		}		if (*data->base == '\0') {			data->base = NULL;		}		if ((data->base != NULL && unhex(data->base) == NULL) || (filter != NULL && unhex(filter) == NULL)) {			free_data(data);			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,					      "LDAP sdb zone '%s': bad hex values", zone);			return (ISC_R_FAILURE);		}	}	/* compute filterall and filterone once and for all */	if (filter == NULL) {		data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1;		data->filteronelen = strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;	} else {		data->filteralllen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=))") + 1;		data->filteronelen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;	}	data->filterall = isc_mem_get(ns_g_mctx, data->filteralllen);	if (data->filterall == NULL) {		free_data(data);		return (ISC_R_NOMEMORY);	}	data->filterone = isc_mem_get(ns_g_mctx, data->filteronelen);	if (data->filterone == NULL) {		free_data(data);		return (ISC_R_NOMEMORY);	}	if (filter == NULL) {		sprintf(data->filterall, "(zoneName=%s)", zone);		sprintf(data->filterone, "(&(zoneName=%s)(relativeDomainName=", zone); 	} else {		sprintf(data->filterall, "(&%s(zoneName=%s))", filter, zone);		sprintf(data->filterone, "(&%s(zoneName=%s)(relativeDomainName=", filter, zone);	}	data->filtername = data->filterone + strlen(data->filterone);	/* support URLs with literal IPv6 addresses */	data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport + (*data->hostport == '[' ? 1 : 0));	if (data->hostname == NULL) {		free_data(data);		return (ISC_R_NOMEMORY);	}	if (*data->hostport == '[' &&	    (s = strchr(data->hostname, ']')) != NULL )		*s++ = '\0';	else		s = data->hostname;	s = strchr(s, ':');	if (s != NULL) {		*s++ = '\0';		data->portno = atoi(s);	} else		data->portno = LDAP_PORT;	*dbdata = data;	return (ISC_R_SUCCESS);}static voidldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {	struct ldapdb_data *data = *dbdata;	        UNUSED(zone);        UNUSED(driverdata);	free_data(data);}static dns_sdbmethods_t ldapdb_methods = {	ldapdb_lookup,	NULL, /* authority */	ldapdb_allnodes,	ldapdb_create,	ldapdb_destroy};/* Wrapper around dns_sdb_register() */isc_result_tldapdb_init(void) {	unsigned int flags =		DNS_SDBFLAG_RELATIVEOWNER |		DNS_SDBFLAG_RELATIVERDATA |		DNS_SDBFLAG_THREADSAFE;	ldapdb_lock(0);	return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,				 ns_g_mctx, &ldapdb));}/* Wrapper around dns_sdb_unregister() */voidldapdb_clear(void) {	if (ldapdb != NULL) {		/* clean up thread data */		ldapdb_getconn(NULL);		dns_sdb_unregister(&ldapdb);	}}

⌨️ 快捷键说明

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