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

📄 ldap.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    Unix SMB/CIFS implementation.   ads (active directory) utility library   Copyright (C) Andrew Tridgell 2001   Copyright (C) Remus Koos 2001   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"#ifdef HAVE_LDAP/** * @file ldap.c * @brief basic ldap client-side routines for ads server communications * * The routines contained here should do the necessary ldap calls for * ads setups. *  * Important note: attribute names passed into ads_ routines must * already be in UTF-8 format.  We do not convert them because in almost * all cases, they are just ascii (which is represented with the same * codepoints in UTF-8).  This may have to change at some point **/#define LDAP_SERVER_TREE_DELETE_OID	"1.2.840.113556.1.4.805"static SIG_ATOMIC_T gotalarm;                                                                                                                   /*************************************************************** Signal function to tell us we timed out.****************************************************************/                                                                                                                   static void gotalarm_sig(void){	gotalarm = 1;}                                                                                                                    LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to){	LDAP *ldp = NULL;                                                                                                                   	/* Setup timeout */	gotalarm = 0;	CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);	alarm(to);	/* End setup timeout. */                                                                                                                   	ldp = ldap_open(server, port);                                                                                                                   	/* Teardown timeout. */	CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);	alarm(0);                                                                                                                   	return ldp;}static int ldap_search_with_timeout(LDAP *ld,				    LDAP_CONST char *base,				    int scope,				    LDAP_CONST char *filter,				    char **attrs,				    int attrsonly,				    LDAPControl **sctrls,				    LDAPControl **cctrls,				    int sizelimit,				    LDAPMessage **res ){	struct timeval timeout;	int result;	/* Setup timeout for the ldap_search_ext_s call - local and remote. */	timeout.tv_sec = lp_ldap_timeout();	timeout.tv_usec = 0;	/* Setup alarm timeout.... Do we need both of these ? JRA. */	gotalarm = 0;	CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);	alarm(lp_ldap_timeout());	/* End setup timeout. */	result = ldap_search_ext_s(ld, base, scope, filter, attrs,				   attrsonly, sctrls, cctrls, &timeout,				   sizelimit, res);	/* Teardown timeout. */	CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);	alarm(0);	if (gotalarm != 0)		return LDAP_TIMELIMIT_EXCEEDED;	return result;}/*  try a connection to a given ldap server, returning True and setting the servers IP  in the ads struct if successful    TODO : add a negative connection cache in here leveraged off of the one  found in the rpc code.  --jerry */BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port){	char *srv;	if (!server || !*server) {		return False;	}	DEBUG(5,("ads_try_connect: trying ldap server '%s' port %u\n", server, port));	/* this copes with inet_ntoa brokenness */	srv = SMB_STRDUP(server);	ads->ld = ldap_open_with_timeout(srv, port, lp_ldap_timeout());	if (!ads->ld) {		free(srv);		return False;	}	ads->ldap_port = port;	ads->ldap_ip = *interpret_addr2(srv);	free(srv);	return True;}/*  try a connection to a given ldap server, based on URL, returning True if successful */static BOOL ads_try_connect_uri(ADS_STRUCT *ads){#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)	DEBUG(5,("ads_try_connect: trying ldap server at URI '%s'\n", 		 ads->server.ldap_uri));		if (ldap_initialize((LDAP**)&(ads->ld), ads->server.ldap_uri) == LDAP_SUCCESS) {		return True;	}	DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));	#else 	DEBUG(1, ("no URL support in LDAP libs!\n"));#endif	return False;}/********************************************************************** Try to find an AD dc using our internal name resolution routines Try the realm first and then then workgroup name if netbios is not  disabled**********************************************************************/static BOOL ads_find_dc(ADS_STRUCT *ads){	const char *c_realm;	int count, i=0;	struct ip_service *ip_list;	pstring realm;	BOOL got_realm = False;	BOOL use_own_domain = False;	/* if the realm and workgroup are both empty, assume they are ours */	/* realm */	c_realm = ads->server.realm;		if ( !c_realm || !*c_realm ) {		/* special case where no realm and no workgroup means our own */		if ( !ads->server.workgroup || !*ads->server.workgroup ) {			use_own_domain = True;			c_realm = lp_realm();		}	}		if (c_realm && *c_realm) 		got_realm = True;		   again:	/* we need to try once with the realm name and fallback to the 	   netbios domain name if we fail (if netbios has not been disabled */	   	if ( !got_realm	&& !lp_disable_netbios() ) {		c_realm = ads->server.workgroup;		if (!c_realm || !*c_realm) {			if ( use_own_domain )				c_realm = lp_workgroup();		}				if ( !c_realm || !*c_realm ) {			DEBUG(0,("ads_find_dc: no realm or workgroup!  Don't know what to do\n"));			return False;		}	}		pstrcpy( realm, c_realm );	DEBUG(6,("ads_find_dc: looking for %s '%s'\n", 		(got_realm ? "realm" : "domain"), realm));	if ( !get_sorted_dc_list(realm, &ip_list, &count, got_realm) ) {		/* fall back to netbios if we can */		if ( got_realm && !lp_disable_netbios() ) {			got_realm = False;			goto again;		}				return False;	}				/* if we fail this loop, then giveup since all the IP addresses returned were dead */	for ( i=0; i<count; i++ ) {		/* since this is an ads conection request, default to LDAP_PORT is not set */		int port = (ip_list[i].port!=PORT_NONE) ? ip_list[i].port : LDAP_PORT;		fstring server;				fstrcpy( server, inet_ntoa(ip_list[i].ip) );				if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) )			continue;					if ( ads_try_connect(ads, server, port) ) {			SAFE_FREE(ip_list);			return True;		}				/* keep track of failures */		add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL );	}	SAFE_FREE(ip_list);		return False;}/** * Connect to the LDAP server * @param ads Pointer to an existing ADS_STRUCT * @return status of connection **/ADS_STATUS ads_connect(ADS_STRUCT *ads){	int version = LDAP_VERSION3;	ADS_STATUS status;	ads->last_attempt = time(NULL);	ads->ld = NULL;	/* try with a URL based server */	if (ads->server.ldap_uri &&	    ads_try_connect_uri(ads)) {		goto got_connection;	}	/* try with a user specified server */	if (ads->server.ldap_server && 	    ads_try_connect(ads, ads->server.ldap_server, LDAP_PORT)) {		goto got_connection;	}	if (ads_find_dc(ads)) {		goto got_connection;	}	return ADS_ERROR_SYSTEM(errno?errno:ENOENT);got_connection:	DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));	status = ads_server_info(ads);	if (!ADS_ERR_OK(status)) {		DEBUG(1,("Failed to get ldap server info\n"));		return status;	}	ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);	status = ADS_ERROR(smb_ldap_start_tls(ads->ld, version));	if (!ADS_ERR_OK(status)) {		return status;	}	if (!ads->auth.user_name) {		/* have to use the userPrincipalName value here and 		   not servicePrincipalName; found by Guenther Deschner @ Sernet */		asprintf(&ads->auth.user_name, "host/%s", global_myname() );	}	if (!ads->auth.realm) {		ads->auth.realm = SMB_STRDUP(ads->config.realm);	}	if (!ads->auth.kdc_server) {		ads->auth.kdc_server = SMB_STRDUP(inet_ntoa(ads->ldap_ip));	}#if KRB5_DNS_HACK	/* this is a really nasty hack to avoid ADS DNS problems. It needs a patch	   to MIT kerberos to work (tridge) */	{		char *env;		asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->config.realm);		setenv(env, ads->auth.kdc_server, 1);		free(env);	}#endif	if (ads->auth.flags & ADS_AUTH_NO_BIND) {		return ADS_SUCCESS;	}	if (ads->auth.flags & ADS_AUTH_ANON_BIND) {		return ADS_ERROR(ldap_simple_bind_s( ads->ld, NULL, NULL));	}	if (ads->auth.flags & ADS_AUTH_SIMPLE_BIND) {		return ADS_ERROR(ldap_simple_bind_s( ads->ld, ads->auth.user_name, ads->auth.password));	}	return ads_sasl_bind(ads);}/*  Duplicate a struct berval into talloc'ed memory */static struct berval *dup_berval(TALLOC_CTX *ctx, const struct berval *in_val){	struct berval *value;	if (!in_val) return NULL;	value = TALLOC_ZERO_P(ctx, struct berval);	if (value == NULL)		return NULL;	if (in_val->bv_len == 0) return value;	value->bv_len = in_val->bv_len;	value->bv_val = TALLOC_MEMDUP(ctx, in_val->bv_val, in_val->bv_len);	return value;}/*  Make a values list out of an array of (struct berval *) */static struct berval **ads_dup_values(TALLOC_CTX *ctx, 				      const struct berval **in_vals){	struct berval **values;	int i;       	if (!in_vals) return NULL;	for (i=0; in_vals[i]; i++)		; /* count values */	values = TALLOC_ZERO_ARRAY(ctx, struct berval *, i+1);	if (!values) return NULL;	for (i=0; in_vals[i]; i++) {		values[i] = dup_berval(ctx, in_vals[i]);	}	return values;}/*  UTF8-encode a values list out of an array of (char *) */static char **ads_push_strvals(TALLOC_CTX *ctx, const char **in_vals){	char **values;	int i;       	if (!in_vals) return NULL;	for (i=0; in_vals[i]; i++)		; /* count values */	values = TALLOC_ZERO_ARRAY(ctx, char *, i+1);	if (!values) return NULL;	for (i=0; in_vals[i]; i++) {		push_utf8_talloc(ctx, &values[i], in_vals[i]);	}	return values;}/*  Pull a (char *) array out of a UTF8-encoded values list */static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals){	char **values;	int i;       	if (!in_vals) return NULL;	for (i=0; in_vals[i]; i++)		; /* count values */	values = TALLOC_ZERO_ARRAY(ctx, char *, i+1);	if (!values) return NULL;	for (i=0; in_vals[i]; i++) {		pull_utf8_talloc(ctx, &values[i], in_vals[i]);	}	return values;}/** * Do a search with paged results.  cookie must be null on the first *  call, and then returned on each subsequent call.  It will be null *  again when the entire search is complete  * @param ads connection to ads server  * @param bind_path Base dn for the search * @param scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE) * @param expr Search expression - specified in local charset * @param attrs Attributes to retrieve - specified in utf8 or ascii * @param res ** which will contain results - free res* with ads_msgfree() * @param count Number of entries retrieved on this page * @param cookie The paged results cookie to be returned on subsequent calls * @return status of search **/ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,			       int scope, const char *expr,			       const char **attrs, void **res, 			       int *count, void **cookie){	int rc, i, version;	char *utf8_expr, *utf8_path, **search_attrs;	LDAPControl PagedResults, NoReferrals, *controls[3], **rcontrols; 	BerElement *cookie_be = NULL;	struct berval *cookie_bv= NULL;	TALLOC_CTX *ctx;	*res = NULL;	if (!(ctx = talloc_init("ads_do_paged_search")))		return ADS_ERROR(LDAP_NO_MEMORY);	/* 0 means the conversion worked but the result was empty 	   so we only fail if it's -1.  In any case, it always 	   at least nulls out the dest */	if ((push_utf8_talloc(ctx, &utf8_expr, expr) == (size_t)-1) ||	    (push_utf8_talloc(ctx, &utf8_path, bind_path) == (size_t)-1)) {		rc = LDAP_NO_MEMORY;		goto done;	}	if (!attrs || !(*attrs))		search_attrs = NULL;	else {		/* This would be the utf8-encoded version...*/		/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */		if (!(str_list_copy(&search_attrs, attrs))) {			rc = LDAP_NO_MEMORY;			goto done;		}	}					/* Paged results only available on ldap v3 or later */	ldap_get_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);	if (version < LDAP_VERSION3) {

⌨️ 快捷键说明

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