diff options
-rw-r--r-- | source4/ldap_server/config.mk | 3 | ||||
-rw-r--r-- | source4/ldap_server/ldap_rootdse.c | 249 | ||||
-rw-r--r-- | source4/ldap_server/ldap_server.c | 162 | ||||
-rw-r--r-- | source4/ldap_server/ldap_server.h | 34 |
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; }; |