mirror of
				https://github.com/samba-team/samba.git
				synced 2025-10-31 12:23:52 +03:00 
			
		
		
		
	- got rid of the special cases for sasl buffers - added a tls_socket_pending() call to determine how much data is waiting on a tls connection - removed the attempt at async handling of ldap calls. The buffers/sockets are all async, but the calls themselves are sync.
		
			
				
	
	
		
			369 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			369 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 
 | |
|    Unix SMB/CIFS implementation.
 | |
|    LDAP server ROOT DSE
 | |
|    Copyright (C) Stefan Metzmacher 2004
 | |
|    
 | |
|    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"
 | |
| #include "dynconfig.h"
 | |
| #include "ldap_server/ldap_server.h"
 | |
| #include "system/time.h"
 | |
| #include "lib/ldb/include/ldb.h"
 | |
| 
 | |
| #define ATTR_BLOB_CONST(val) data_blob_talloc(mem_ctx, val, sizeof(val)-1)
 | |
| 
 | |
| #define ATTR_SINGLE_NOVAL(ctx, attr, blob, num, nam) do { \
 | |
| 	attr->name = talloc_strdup(ctx, nam);\
 | |
| 	NT_STATUS_HAVE_NO_MEMORY(attr->name);\
 | |
| 	attr->num_values = num; \
 | |
| 	attr->values = blob;\
 | |
| } while(0)
 | |
| 
 | |
| /*
 | |
|   this is used to catch debug messages from ldb
 | |
| */
 | |
| static void rootdse_db_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
 | |
| static void rootdse_db_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
 | |
| {
 | |
| 	char *s = NULL;
 | |
| 	if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) {
 | |
| 		return;
 | |
| 	}
 | |
| 	vasprintf(&s, fmt, ap);
 | |
| 	if (!s) return;
 | |
| 	DEBUG(level, ("rootdse: %s\n", s));
 | |
| 	free(s);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   connect to the SAM database
 | |
|  */
 | |
| static struct ldb_context *rootdse_db_connect(TALLOC_CTX *mem_ctx)
 | |
| {
 | |
| 	char *db_path;
 | |
| 	struct ldb_context *ldb;
 | |
| 
 | |
| 	db_path = talloc_asprintf(mem_ctx, "tdb://%s", 
 | |
| 				  private_path(mem_ctx, "rootdse.ldb"));
 | |
| 	if (db_path == NULL) {
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	ldb = ldb_wrap_connect(mem_ctx, db_path, 0, NULL);
 | |
| 	if (ldb == NULL) {
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	ldb_set_debug(ldb, rootdse_db_debug, NULL);
 | |
| 
 | |
| 	return ldb;
 | |
| }
 | |
| 
 | |
| 
 | |
| static NTSTATUS fill_dynamic_values(void *mem_ctx, struct ldb_message_element *attrs)
 | |
| {
 | |
| 	/* 
 | |
| 	 * currentTime
 | |
| 	 * 20040918090350.0Z
 | |
| 	 */
 | |
| 
 | |
| 	DEBUG(10, ("fill_dynamic_values for %s\n", attrs[0].name));
 | |
| 
 | |
| 	if (strcasecmp(attrs->name, "currentTime") == 0)
 | |
| 	{
 | |
| 		int num_currentTime = 1;
 | |
| 		DATA_BLOB *currentTime = talloc_array(mem_ctx, DATA_BLOB, num_currentTime);
 | |
| 		char *str = ldap_timestring(mem_ctx, time(NULL));
 | |
| 		NT_STATUS_HAVE_NO_MEMORY(str);
 | |
| 		currentTime[0].data = (uint8_t *)str;
 | |
| 		currentTime[0].length = strlen(str);
 | |
| 		ATTR_SINGLE_NOVAL(mem_ctx, attrs, currentTime, num_currentTime, "currentTime");
 | |
| 		return NT_STATUS_OK;
 | |
| 	}
 | |
| 
 | |
| 	/* 
 | |
| 	 * subschemaSubentry 
 | |
| 	 * CN=Aggregate,CN=Schema,CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * dsServiceName
 | |
| 	 * CN=NTDS Settings,CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * namingContexts
 | |
| 	 * DC=DOM,DC=TLD
 | |
| 	 * CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 * DC=DomainDnsZones,DC=DOM,DC=TLD
 | |
| 	 * DC=ForestDnsZones,DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * defaultNamingContext
 | |
| 	 * DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * schemaNamingContext
 | |
| 	 * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * configurationNamingContext
 | |
| 	 * CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * rootDomainNamingContext
 | |
| 	 * DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * supportedControl
 | |
| 	 * 1.2.840.113556.1.4.319
 | |
| 	 * 1.2.840.113556.1.4.801
 | |
| 	 * 1.2.840.113556.1.4.473
 | |
| 	 * 1.2.840.113556.1.4.528
 | |
| 	 * 1.2.840.113556.1.4.417
 | |
| 	 * 1.2.840.113556.1.4.619
 | |
| 	 * 1.2.840.113556.1.4.841
 | |
| 	 * 1.2.840.113556.1.4.529
 | |
| 	 * 1.2.840.113556.1.4.805
 | |
| 	 * 1.2.840.113556.1.4.521
 | |
| 	 * 1.2.840.113556.1.4.970
 | |
| 	 * 1.2.840.113556.1.4.1338
 | |
| 	 * 1.2.840.113556.1.4.474
 | |
| 	 * 1.2.840.113556.1.4.1339
 | |
| 	 * 1.2.840.113556.1.4.1340
 | |
| 	 * 1.2.840.113556.1.4.1413
 | |
| 	 * 2.16.840.1.113730.3.4.9
 | |
| 	 * 2.16.840.1.113730.3.4.10
 | |
| 	 * 1.2.840.113556.1.4.1504
 | |
| 	 * 1.2.840.113556.1.4.1852
 | |
| 	 * 1.2.840.113556.1.4.802
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * supportedLDAPVersion 
 | |
| 	 * 3
 | |
| 	 * 2
 | |
| 	 */
 | |
| 	if (strcasecmp(attrs->name, "supportedLDAPVersion") == 0)
 | |
| 	{
 | |
| 		int num_supportedLDAPVersion = 1;
 | |
| 		DATA_BLOB *supportedLDAPVersion = talloc_array(mem_ctx, DATA_BLOB, num_supportedLDAPVersion);
 | |
| 		supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
 | |
| 		ATTR_SINGLE_NOVAL(mem_ctx, attrs, supportedLDAPVersion, num_supportedLDAPVersion, "supportedLDAPVersion");
 | |
| 		return NT_STATUS_OK;
 | |
| 	}
 | |
| 
 | |
| 	/* 
 | |
| 	 * supportedLDAPPolicies
 | |
| 	 * MaxPoolThreads
 | |
| 	 * MaxDatagramRecv
 | |
| 	 * MaxReceiveBuffer
 | |
| 	 * InitRecvTimeout
 | |
| 	 * MaxConnections
 | |
| 	 * MaxConnIdleTime
 | |
| 	 * MaxPageSize
 | |
| 	 * MaxQueryDuration
 | |
| 	 * MaxTempTableSize
 | |
| 	 * MaxResultSetSize
 | |
| 	 * MaxNotificationPerConn
 | |
| 	 * MaxValRange
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * highestCommittedUSN 
 | |
| 	 * 4555
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * supportedSASLMechanisms
 | |
| 	 * GSSAPI
 | |
| 	 * GSS-SPNEGO
 | |
| 	 * EXTERNAL
 | |
| 	 * DIGEST-MD5
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * dnsHostName
 | |
| 	 * netbiosname.dom.tld
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * ldapServiceName
 | |
| 	 * dom.tld:netbiosname$@DOM.TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * serverName:
 | |
| 	 * CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * supportedCapabilities
 | |
| 	 * 1.2.840.113556.1.4.800
 | |
| 	 * 1.2.840.113556.1.4.1670
 | |
| 	 * 1.2.840.113556.1.4.1791
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * isSynchronized:
 | |
| 	 * TRUE/FALSE
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * isGlobalCatalogReady
 | |
| 	 * TRUE/FALSE
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * domainFunctionality
 | |
| 	 * 0
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * forestFunctionality
 | |
| 	 * 0
 | |
| 	 */
 | |
| 
 | |
| 	/* 
 | |
| 	 * domainControllerFunctionality
 | |
| 	 * 2
 | |
| 	 */
 | |
| 
 | |
| 	{
 | |
| 		DATA_BLOB *x = talloc_array(mem_ctx, DATA_BLOB, 1);
 | |
| 		x[0] = ATTR_BLOB_CONST("0");
 | |
| 		ATTR_SINGLE_NOVAL(mem_ctx, attrs, x, 1, attrs->name);
 | |
| 	}
 | |
| 	return NT_STATUS_OK;
 | |
| }
 | |
| 
 | |
| static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
 | |
| 				     struct ldap_SearchRequest *r)
 | |
| {
 | |
| 	NTSTATUS status;
 | |
| 	void *local_ctx;
 | |
| 	struct ldap_SearchResEntry *ent;
 | |
| 	struct ldap_Result *done;
 | |
| 	struct ldb_message **res = NULL;
 | |
| 	int result = LDAP_SUCCESS;
 | |
| 	struct ldapsrv_reply *ent_r, *done_r;
 | |
| 	struct ldb_context *ldb;
 | |
| 	const char *errstr = NULL;
 | |
| 	int count, j;
 | |
| 	const char **attrs = NULL;
 | |
| 
 | |
| 	if (r->scope != LDAP_SEARCH_SCOPE_BASE) {
 | |
| 		return NT_STATUS_INVALID_PARAMETER;
 | |
| 	}
 | |
| 
 | |
| 	local_ctx = talloc_named(call, 0, "rootdse_Search local memory context");
 | |
| 	NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 | |
| 
 | |
| 	ldb = rootdse_db_connect(local_ctx);
 | |
| 	NT_STATUS_HAVE_NO_MEMORY(ldb);
 | |
| 
 | |
| 	if (r->num_attributes >= 1) {
 | |
| 		attrs = talloc_array(ldb, const char *, r->num_attributes+1);
 | |
| 		NT_STATUS_HAVE_NO_MEMORY(attrs);
 | |
| 
 | |
| 		for (j=0; j < r->num_attributes; j++) {
 | |
| 			DEBUG(10,("rootDSE_Search: attrs: [%s]\n",r->attributes[j]));
 | |
| 			attrs[j] = r->attributes[j];
 | |
| 		}
 | |
| 		attrs[j] = NULL;
 | |
| 	}
 | |
| 
 | |
| 	count = ldb_search(ldb, NULL, 0, "dn=cn=rootDSE", attrs, &res);
 | |
| 	talloc_steal(local_ctx, res);
 | |
| 
 | |
| 	if (count == 1) {
 | |
| 		ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
 | |
| 		NT_STATUS_HAVE_NO_MEMORY(ent_r);
 | |
| 
 | |
| 		ent = &ent_r->msg->r.SearchResultEntry;
 | |
| 		ent->dn = "";
 | |
| 		ent->num_attributes = 0;
 | |
| 		ent->attributes = NULL;
 | |
| 		if (res[0]->num_elements == 0) {
 | |
| 			goto queue_reply;
 | |
| 		}
 | |
| 		ent->num_attributes = res[0]->num_elements;
 | |
| 		ent->attributes = talloc_steal(ent_r, res[0]->elements);
 | |
| 
 | |
| 		for (j=0; j < ent->num_attributes; j++) {
 | |
| 			if (ent->attributes[j].num_values == 1 &&
 | |
| 			    ent->attributes[j].values[0].length >= 9 &&
 | |
| 			    strncmp(ent->attributes[j].values[0].data, "_DYNAMIC_", 9) == 0) {
 | |
| 				status = fill_dynamic_values(ent->attributes, &(ent->attributes[j]));
 | |
| 				if (!NT_STATUS_IS_OK(status)) {
 | |
| 					return status;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| queue_reply:
 | |
| 		ldapsrv_queue_reply(call, ent_r);
 | |
| 	}
 | |
| 
 | |
| 	done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
 | |
| 	NT_STATUS_HAVE_NO_MEMORY(done_r);
 | |
| 
 | |
| 	if (count == 1) {
 | |
| 		DEBUG(10,("rootdse_Search: results: [%d]\n",count));
 | |
| 		result = LDAP_SUCCESS;
 | |
| 		errstr = NULL;
 | |
| 	} else if (count == 0) {
 | |
| 		DEBUG(10,("rootdse_Search: no results\n"));
 | |
| 		result = LDAP_NO_SUCH_OBJECT;
 | |
| 		errstr = ldb_errstring(ldb);
 | |
| 	} else if (count > 1) {
 | |
| 		DEBUG(10,("rootdse_Search: too many results[%d]\n", count));
 | |
| 		result = LDAP_OTHER; 
 | |
| 		errstr = "internal error";	
 | |
| 	} else if (count == -1) {
 | |
| 		DEBUG(10,("rootdse_Search: error\n"));
 | |
| 		result = LDAP_OTHER;
 | |
| 		errstr = ldb_errstring(ldb);
 | |
| 	}
 | |
| 
 | |
| 	done = &done_r->msg->r.SearchResultDone;
 | |
| 	done->dn = NULL;
 | |
| 	done->resultcode = result;
 | |
| 	done->errormessage = (errstr?talloc_strdup(done_r,errstr):NULL);;
 | |
| 	done->referral = NULL;
 | |
| 
 | |
| 	talloc_free(local_ctx);
 | |
| 
 | |
| 	ldapsrv_queue_reply(call, done_r);
 | |
| 	return NT_STATUS_OK;
 | |
| }
 | |
| 
 | |
| static const struct ldapsrv_partition_ops rootdse_ops = {
 | |
| 	.Search		= rootdse_Search
 | |
| };
 | |
| 
 | |
| const struct ldapsrv_partition_ops *ldapsrv_get_rootdse_partition_ops(void)
 | |
| {
 | |
| 	return &rootdse_ops;
 | |
| }
 |