r2523: - readd rootDSE reply
authorStefan Metzmacher <metze@samba.org>
Wed, 22 Sep 2004 13:01:00 +0000 (13:01 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:59:02 +0000 (12:59 -0500)
- add infrastructure start for having multiple directory partitions (backends)

metze
(This used to be commit 5103e7fe7873c0309461ad471f0529223d7c38eb)

source4/ldap_server/config.mk
source4/ldap_server/ldap_rootdse.c [new file with mode: 0644]
source4/ldap_server/ldap_server.c
source4/ldap_server/ldap_server.h

index 4e51906ed4567c33635c5a848f7b18600080a563..f99e6f54ef7791c83b376175c8ac6f322fb62acf 100644 (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
diff --git a/source4/ldap_server/ldap_rootdse.c b/source4/ldap_server/ldap_rootdse.c
new file mode 100644 (file)
index 0000000..75e6416
--- /dev/null
@@ -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);
+}
index 529af3fe2ae147d22da10f6038543d657c8fe795..f4ebd0d74c4b3b42e26a9eb6a8b688e78c84637a 100644 (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)
index 65b355514cad0fa5bf60d2ddfb5dcc3e758cad2c..960ab519bcd752c5cd416817ea5ba16c199ebe12 100644 (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;
 };