1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

r2523: - readd rootDSE reply

- add infrastructure start for having multiple directory partitions (backends)

metze
This commit is contained in:
Stefan Metzmacher 2004-09-22 13:01:00 +00:00 committed by Gerald (Jerry) Carter
parent 04f68f481c
commit 5103e7fe78
4 changed files with 371 additions and 77 deletions

View File

@ -4,7 +4,8 @@
# Start SUBSYSTEM LDAP
[SUBSYSTEM::LDAP]
INIT_OBJ_FILES = \
ldap_server/ldap_server.o
ldap_server/ldap_server.o \
ldap_server/ldap_rootdse.o
REQUIRED_SUBSYSTEMS = \
LIBCLI_LDAP
# End SUBSYSTEM SMB

View File

@ -0,0 +1,249 @@
/*
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"
#define ATTR_BLOB_CONST(val) data_blob_talloc(attrs, val, sizeof(val)-1)
#define ATTR_SINGLE_NOVAL(attr, blob, num, nam) do { \
attr.name = talloc_strdup(attrs, nam);\
attr.num_values = num; \
attr.values = blob;\
} while(0)
void ldapsrv_RootDSE_Search(struct ldapsrv_call *call,
struct ldap_SearchRequest *r)
{
struct ldap_SearchResEntry *ent;
struct ldap_Result *done;
struct ldapsrv_reply *ent_r, *done_r;
int num_attrs = 3;
struct ldap_attribute *attrs;
DEBUG(10, ("Root DSE: %s\n", r->filter));
attrs = talloc_array_p(call, struct ldap_attribute, num_attrs);
if (!attrs) {
ldapsrv_terminate_connection(call->conn, "no memory");
return;
}
/*
* currentTime
* 20040918090350.0Z
*/
{
int num_currentTime = 1;
DATA_BLOB *currentTime = talloc_array_p(attrs, DATA_BLOB, num_currentTime);
char *str = ldap_timestring(call, time(NULL));
if (!str) {
ldapsrv_terminate_connection(call->conn, "no memory");
return;
}
currentTime[0].data = str;
currentTime[0].length = strlen(str);
ATTR_SINGLE_NOVAL(attrs[0], currentTime, num_currentTime, "currentTime");
}
/*
* subschemaSubentry
* CN=Aggregate,CN=Schema,CN=Configuration,DC=DOM,DC=TLD
*/
/*
* dsServiceName
* CN=NTDS Settings,CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,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
*/
{
int num_supportedLDAPVersion = 1;
DATA_BLOB *supportedLDAPVersion = talloc_array_p(attrs, DATA_BLOB, num_supportedLDAPVersion);
supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
ATTR_SINGLE_NOVAL(attrs[1], supportedLDAPVersion, num_supportedLDAPVersion, "supportedLDAPVersion");
}
/*
* 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
*/
{
int num_dnsHostName = 1;
DATA_BLOB *dnsHostName = talloc_array_p(attrs, DATA_BLOB, num_dnsHostName);
dnsHostName[0] = data_blob_talloc(attrs, lp_netbios_name(),strlen(lp_netbios_name()));
ATTR_SINGLE_NOVAL(attrs[2], dnsHostName, num_dnsHostName, "dnsHostName");
}
/*
* 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
*/
ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
if (!ent_r) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
return;
}
ent = &ent_r->msg.r.SearchResultEntry;
ent->dn = "";
ent->num_attributes = num_attrs;
ent->attributes = attrs;
ldapsrv_queue_reply(call, ent_r);
done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
if (!done_r) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
return;
}
done = &done_r->msg.r.SearchResultDone;
done->resultcode = 0;
done->dn = NULL;
done->errormessage = NULL;
done->referral = NULL;
ldapsrv_queue_reply(call, done_r);
}

View File

@ -24,7 +24,7 @@
/*
close the socket and shutdown a server_context
*/
static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, const char *reason)
void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, const char *reason)
{
server_terminate_connection(ldap_conn->connection, reason);
}
@ -173,7 +173,7 @@ static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
return res;
}
static struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, enum ldap_request_tag type)
struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, enum ldap_request_tag type)
{
struct ldapsrv_reply *reply;
@ -191,7 +191,22 @@ static struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, enum
return reply;
}
static void ldapsrv_unwilling(struct ldapsrv_call *call, int error)
void ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
{
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
}
struct ldapsrv_partition *ldapsrv_get_partition(struct ldapsrv_connection *conn, const char *dn)
{
static const struct ldapsrv_partition_ops null_ops;
static struct ldapsrv_partition null_part = {
.ops = &null_ops
};
return &null_part;
}
void ldapsrv_unwilling(struct ldapsrv_call *call, int error)
{
struct ldapsrv_reply *reply;
struct ldap_ExtendedResponse *r;
@ -213,7 +228,7 @@ static void ldapsrv_unwilling(struct ldapsrv_call *call, int error)
r->value.data = NULL;
r->value.length = 0;
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
ldapsrv_queue_reply(call, reply);
}
static void ldapsrv_BindRequest(struct ldapsrv_call *call)
@ -222,8 +237,7 @@ static void ldapsrv_BindRequest(struct ldapsrv_call *call)
struct ldapsrv_reply *reply;
struct ldap_BindResponse *resp;
DEBUG(5, ("Binding as %s with pw %s\n",
req->dn, req->creds.password));
DEBUG(5, ("BindRequest dn: %s\n",req->dn));
reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
if (!reply) {
@ -238,144 +252,140 @@ static void ldapsrv_BindRequest(struct ldapsrv_call *call)
resp->response.referral = NULL;
resp->SASL.secblob = data_blob(NULL, 0);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
ldapsrv_queue_reply(call, reply);
}
static void ldapsrv_UnbindRequest(struct ldapsrv_call *call)
{
// struct ldap_UnbindRequest *req = &call->request->r.UnbindRequest;
DEBUG(10, ("Unbind\n"));
/* struct ldap_UnbindRequest *req = &call->request->r.UnbindRequest;*/
DEBUG(10, ("UnbindRequest\n"));
}
static void ldapsrv_SearchRequest(struct ldapsrv_call *call)
{
struct ldap_SearchRequest *req = &call->request.r.SearchRequest;
struct ldapsrv_reply *reply;
struct ldap_Result *resp;
struct ldapsrv_partition *part;
DEBUG(10, ("Search filter: %s\n", req->filter));
DEBUG(10, ("SearchRequest"));
DEBUGADD(10, (" basedn: %s", req->basedn));
DEBUGADD(10, (" filter: %s\n", req->filter));
/* Is this a rootdse request? */
if ((strlen(req->basedn) == 0) &&
(req->scope == LDAP_SEARCH_SCOPE_BASE) &&
strequal(req->filter, "(objectclass=*)")) {
if ((strcasecmp("", req->basedn) == 0) &&
(req->scope == LDAP_SEARCH_SCOPE_BASE)) {
ldapsrv_RootDSE_Search(call, req);
return;
}
}
part = ldapsrv_get_partition(call->conn, req->basedn);
reply = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
if (!reply) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
if (!part->ops->Search) {
ldapsrv_unwilling(call, 2);
return;
}
resp = &reply->msg.r.SearchResultDone;
resp->resultcode = 0;
resp->dn = NULL;
resp->errormessage = NULL;
resp->referral = NULL;
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
part->ops->Search(part, call, req);
}
static void ldapsrv_ModifyRequest(struct ldapsrv_call *call)
{
// struct ldap_ModifyRequest *req = &call->request.r.ModifyRequest;
struct ldapsrv_reply *reply;
struct ldap_ModifyRequest *req = &call->request.r.ModifyRequest;
struct ldapsrv_partition *part;
DEBUG(10, ("Modify\n"));
DEBUG(10, ("ModifyRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
if (!reply) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Modify) {
ldapsrv_unwilling(call, 2);
return;
}
ZERO_STRUCT(reply->msg.r);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
part->ops->Modify(part, call, req);
}
static void ldapsrv_AddRequest(struct ldapsrv_call *call)
{
// struct ldap_AddRequest *req = &call->request.r.AddRequest;
struct ldapsrv_reply *reply;
struct ldap_AddRequest *req = &call->request.r.AddRequest;
struct ldapsrv_partition *part;
DEBUG(10, ("Add\n"));
DEBUG(10, ("AddRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
if (!reply) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Add) {
ldapsrv_unwilling(call, 2);
return;
}
ZERO_STRUCT(reply->msg.r);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
part->ops->Add(part, call, req);
}
static void ldapsrv_DelRequest(struct ldapsrv_call *call)
{
// struct ldap_DelRequest *req = &call->request.r.DelRequest;
struct ldapsrv_reply *reply;
struct ldap_DelRequest *req = &call->request.r.DelRequest;
struct ldapsrv_partition *part;
DEBUG(10, ("Del\n"));
DEBUG(10, ("DelRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
if (!reply) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Del) {
ldapsrv_unwilling(call, 2);
return;
}
ZERO_STRUCT(reply->msg.r);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
part->ops->Del(part, call, req);
}
static void ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
{
// struct ldap_ModifyDNRequest *req = &call->request.r.ModifyDNRequest;
struct ldapsrv_reply *reply;
struct ldap_ModifyDNRequest *req = &call->request.r.ModifyDNRequest;
struct ldapsrv_partition *part;
DEBUG(10, ("Modify\n"));
DEBUG(10, ("ModifyDNRequrest"));
DEBUGADD(10, (" dn: %s", req->dn));
DEBUGADD(10, (" newrdn: %s", req->newrdn));
reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
if (!reply) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->ModifyDN) {
ldapsrv_unwilling(call, 2);
return;
}
ZERO_STRUCT(reply->msg.r);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
part->ops->ModifyDN(part, call, req);
}
static void ldapsrv_CompareRequest(struct ldapsrv_call *call)
{
// struct ldap_CompareRequest *req = &call->request.r.CompareRequest;
struct ldapsrv_reply *reply;
struct ldap_CompareRequest *req = &call->request.r.CompareRequest;
struct ldapsrv_partition *part;
DEBUG(10, ("Compare\n"));
DEBUG(10, ("CompareRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
reply = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
if (!reply) {
ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Compare) {
ldapsrv_unwilling(call, 2);
return;
}
ZERO_STRUCT(reply->msg.r);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
part->ops->Compare(part, call, req);
}
static void ldapsrv_AbandonRequest(struct ldapsrv_call *call)
{
// struct ldap_AbandonRequest *req = &call->request.r.AbandonRequest;
DEBUG(10, ("Abandon\n"));
/* struct ldap_AbandonRequest *req = &call->request.r.AbandonRequest;*/
DEBUG(10, ("AbandonRequest\n"));
}
static void ldapsrv_ExtendedRequest(struct ldapsrv_call *call)
{
// struct ldap_ExtendedRequest *req = &call->request.r.ExtendedRequest;
/* struct ldap_ExtendedRequest *req = &call->request.r.ExtendedRequest;*/
struct ldapsrv_reply *reply;
DEBUG(10, ("Extended\n"));
@ -388,7 +398,7 @@ static void ldapsrv_ExtendedRequest(struct ldapsrv_call *call)
ZERO_STRUCT(reply->msg.r);
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
ldapsrv_queue_reply(call, reply);
}
static void ldapsrv_do_call(struct ldapsrv_call *call)

View File

@ -54,6 +54,8 @@ struct ldapsrv_call {
} *replies;
};
struct ldapsrv_service;
struct ldapsrv_connection {
struct server_connection *connection;
@ -64,4 +66,36 @@ struct ldapsrv_connection {
struct rw_buffer out_buffer;
struct ldapsrv_call *calls;
struct ldapsrv_service *service;
};
struct ldapsrv_partition;
struct ldapsrv_partition_ops {
NTSTATUS (*Bind)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_BindRequest *r);
NTSTATUS (*Unbind)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_UnbindRequest *r);
NTSTATUS (*Search)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_SearchRequest *r);
NTSTATUS (*Modify)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ModifyRequest *r);
NTSTATUS (*Add)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_AddRequest *r);
NTSTATUS (*Del)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_DelRequest *r);
NTSTATUS (*ModifyDN)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ModifyDNRequest *r);
NTSTATUS (*Compare)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_CompareRequest *r);
NTSTATUS (*Abandon)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_AbandonRequest *r);
NTSTATUS (*Extended)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ExtendedRequest *r);
};
struct ldapsrv_partition {
struct ldapsrv_partition *prev,*next;
void *private_data;
const struct ldapsrv_partition_ops *ops;
const char *base_dn;
};
struct ldapsrv_service {
struct ldapsrv_partition *rootDSE;
struct ldapsrv_partition *default_partition;
struct ldapsrv_partition *partitions;
};