summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/ldap_server/config.mk3
-rw-r--r--source4/ldap_server/ldap_rootdse.c249
-rw-r--r--source4/ldap_server/ldap_server.c162
-rw-r--r--source4/ldap_server/ldap_server.h34
4 files changed, 371 insertions, 77 deletions
diff --git a/source4/ldap_server/config.mk b/source4/ldap_server/config.mk
index 4e51906ed4..f99e6f54ef 100644
--- a/source4/ldap_server/config.mk
+++ b/source4/ldap_server/config.mk
@@ -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
index 0000000000..75e641648b
--- /dev/null
+++ b/source4/ldap_server/ldap_rootdse.c
@@ -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);
+}
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 529af3fe2a..f4ebd0d74c 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -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)
diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h
index 65b355514c..960ab519bc 100644
--- a/source4/ldap_server/ldap_server.h
+++ b/source4/ldap_server/ldap_server.h
@@ -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;
};