diff options
author | Stefan Metzmacher <metze@samba.org> | 2006-11-16 10:47:15 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:28:17 -0500 |
commit | b471ed1a0cec6f978f5aa183e925766faca13f59 (patch) | |
tree | 73f01d448188294f8720dafc81bf966c9c392980 | |
parent | 3826a6027fa3c7247bbb5084942fed1700f73e90 (diff) | |
download | samba-b471ed1a0cec6f978f5aa183e925766faca13f59.tar.gz samba-b471ed1a0cec6f978f5aa183e925766faca13f59.tar.bz2 samba-b471ed1a0cec6f978f5aa183e925766faca13f59.zip |
r19736: handle rootdse call via CLDAP
metze
(This used to be commit 39dc94b219355ba774b309e26f1d93070d9d080b)
-rw-r--r-- | source4/cldap_server/cldap_server.c | 38 | ||||
-rw-r--r-- | source4/cldap_server/config.mk | 3 | ||||
-rw-r--r-- | source4/cldap_server/netlogon.c | 8 | ||||
-rw-r--r-- | source4/cldap_server/rootdse.c | 185 |
4 files changed, 219 insertions, 15 deletions
diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c index 4c1c7b86c5..d36cf8b637 100644 --- a/source4/cldap_server/cldap_server.c +++ b/source4/cldap_server/cldap_server.c @@ -29,6 +29,11 @@ #include "cldap_server/cldap_server.h" #include "system/network.h" #include "lib/socket/netif.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_errors.h" +#include "dsdb/samdb/samdb.h" +#include "db_wrap.h" +#include "auth/auth.h" /* handle incoming cldap requests @@ -41,21 +46,38 @@ static void cldapd_request_handler(struct cldap_socket *cldap, if (ldap_msg->type != LDAP_TAG_SearchRequest) { DEBUG(0,("Invalid CLDAP request type %d from %s:%d\n", ldap_msg->type, src->addr, src->port)); + cldap_error_reply(cldap, ldap_msg->messageid, src, + LDAP_OPERATIONS_ERROR, "Invalid CLDAP request"); return; } search = &ldap_msg->r.SearchRequest; + if (strcmp("", search->basedn) != 0) { + DEBUG(0,("Invalid CLDAP basedn '%s' from %s:%d\n", + search->basedn, src->addr, src->port)); + cldap_error_reply(cldap, ldap_msg->messageid, src, + LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn"); + return; + } + + if (search->scope != LDAP_SEARCH_SCOPE_BASE) { + DEBUG(0,("Invalid CLDAP scope %d from %s:%d\n", + search->scope, src->addr, src->port)); + cldap_error_reply(cldap, ldap_msg->messageid, src, + LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope"); + return; + } + if (search->num_attributes == 1 && strcasecmp(search->attributes[0], "netlogon") == 0) { cldapd_netlogon_request(cldap, ldap_msg->messageid, search->tree, src); - } else { - DEBUG(0,("Unknown CLDAP search for '%s'\n", - ldb_filter_from_tree(ldap_msg, - ldap_msg->r.SearchRequest.tree))); - cldap_empty_reply(cldap, ldap_msg->messageid, src); + return; } + + cldapd_rootdse_request(cldap, ldap_msg->messageid, + search, src); } @@ -146,7 +168,11 @@ static void cldapd_task_init(struct task_server *task) } cldapd->task = task; - cldapd->samctx = NULL; + cldapd->samctx = samdb_connect(cldapd, anonymous_session(cldapd)); + if (cldapd->samctx == NULL) { + task_server_terminate(task, "cldapd failed to open samdb"); + return; + } /* start listening on the configured network interfaces */ status = cldapd_startup_interfaces(cldapd); diff --git a/source4/cldap_server/config.mk b/source4/cldap_server/config.mk index 25b1c220bc..a5e2d52d1c 100644 --- a/source4/cldap_server/config.mk +++ b/source4/cldap_server/config.mk @@ -8,7 +8,8 @@ SUBSYSTEM = service PRIVATE_PROTO_HEADER = proto.h OBJ_FILES = \ cldap_server.o \ - netlogon.o + netlogon.o \ + rootdse.o PUBLIC_DEPENDENCIES = \ LIBCLI_CLDAP LIBNETIF process_model # End SUBSYSTEM CLDAPD diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c index f5090df837..fd00c43cda 100644 --- a/source4/cldap_server/netlogon.c +++ b/source4/cldap_server/netlogon.c @@ -64,14 +64,6 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd, const char *pdc_ip; const struct ldb_dn *partitions_basedn; - if (cldapd->samctx == NULL) { - cldapd->samctx = samdb_connect(cldapd, anonymous_session(cldapd)); - if (cldapd->samctx == NULL) { - DEBUG(2,("Unable to open sam in cldap netlogon reply\n")); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - } - partitions_basedn = samdb_partitions_dn(cldapd->samctx, mem_ctx); /* the domain has an optional trailing . */ diff --git a/source4/cldap_server/rootdse.c b/source4/cldap_server/rootdse.c new file mode 100644 index 0000000000..966b90889c --- /dev/null +++ b/source4/cldap_server/rootdse.c @@ -0,0 +1,185 @@ +/* + Unix SMB/CIFS implementation. + + CLDAP server - rootdse handling + + Copyright (C) Stefan Metzmacher 2006 + + 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 "libcli/ldap/ldap.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_errors.h" +#include "lib/events/events.h" +#include "lib/socket/socket.h" +#include "smbd/service_task.h" +#include "cldap_server/cldap_server.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "dsdb/samdb/samdb.h" +#include "auth/auth.h" +#include "db_wrap.h" +#include "system/network.h" +#include "lib/socket/netif.h" + +static void cldapd_rootdse_fill(struct cldapd_server *cldapd, + TALLOC_CTX *mem_ctx, + struct ldap_SearchRequest *search, + struct ldap_SearchResEntry **response, + struct ldap_Result *result) +{ + struct ldap_SearchResEntry *ent = NULL; + struct ldb_dn *basedn; + struct ldb_result *res = NULL; + struct ldb_request *lreq; + enum ldb_scope scope = LDB_SCOPE_DEFAULT; + const char **attrs = NULL; + const char *errstr = NULL; + int ret = 0; + int ldb_ret = -1; + + basedn = ldb_dn_explode(mem_ctx, ""); + if (basedn == NULL) goto nomem; + scope = LDB_SCOPE_BASE; + + if (search->num_attributes >= 1) { + int i; + + attrs = talloc_array(mem_ctx, const char *, search->num_attributes+1); + if (attrs == NULL) goto nomem; + + for (i=0; i < search->num_attributes; i++) { + attrs[i] = search->attributes[i]; + } + attrs[i] = NULL; + } + + lreq = talloc(mem_ctx, struct ldb_request); + if (lreq == NULL) goto nomem; + + res = talloc_zero(mem_ctx, struct ldb_result); + if (res == NULL) goto nomem; + + lreq->operation = LDB_SEARCH; + lreq->op.search.base = basedn; + lreq->op.search.scope = scope; + lreq->op.search.tree = search->tree; + lreq->op.search.attrs = attrs; + + lreq->controls = NULL; + + lreq->context = res; + lreq->callback = ldb_search_default_callback; + + /* Copy the timeout from the incoming call */ + ldb_set_timeout(cldapd->samctx, lreq, search->timelimit); + + ldb_ret = ldb_request(cldapd->samctx, lreq); + if (ldb_ret != LDB_SUCCESS) { + goto reply; + } + + ldb_ret = ldb_wait(lreq->handle, LDB_WAIT_ALL); + if (ldb_ret != LDB_SUCCESS) { + goto reply; + } + + if (res->count > 1) { + errstr = "Internal error: to much replies"; + ldb_ret = LDB_ERR_OTHER; + goto reply; + } else if (res->count == 1) { + int j; + + ent = talloc(mem_ctx, struct ldap_SearchResEntry); + if (ent == NULL) goto nomem; + + ent->dn = ldb_dn_linearize(ent, res->msgs[0]->dn); + if (ent->dn == NULL) goto nomem; + ent->num_attributes = 0; + ent->attributes = NULL; + if (res->msgs[0]->num_elements == 0) { + goto reply; + } + ent->num_attributes = res->msgs[0]->num_elements; + ent->attributes = talloc_array(ent, struct ldb_message_element, ent->num_attributes); + if (ent->attributes == NULL) goto nomem; + for (j=0; j < ent->num_attributes; j++) { + ent->attributes[j].name = talloc_steal(ent->attributes, res->msgs[0]->elements[j].name); + ent->attributes[j].num_values = 0; + ent->attributes[j].values = NULL; + if (search->attributesonly && (res->msgs[0]->elements[j].num_values == 0)) { + continue; + } + ent->attributes[j].num_values = res->msgs[0]->elements[j].num_values; + ent->attributes[j].values = res->msgs[0]->elements[j].values; + talloc_steal(ent->attributes, res->msgs[0]->elements[j].values); + } + } + +reply: + if (ret) { + /* nothing ... */ + } else if (ldb_ret == LDB_SUCCESS) { + ret = LDAP_SUCCESS; + errstr = NULL; + } else { + ret = ldb_ret; + errstr = ldb_errstring(cldapd->samctx); + } + goto done; +nomem: + talloc_free(ent); + ret = LDAP_OPERATIONS_ERROR; + errstr = "No memory"; +done: + *response = ent; + result->resultcode = ret; + result->errormessage = (errstr?talloc_strdup(mem_ctx, errstr):NULL); +} + +/* + handle incoming cldap requests +*/ +void cldapd_rootdse_request(struct cldap_socket *cldap, + uint32_t message_id, + struct ldap_SearchRequest *search, + struct socket_address *src) +{ + struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private, struct cldapd_server); + NTSTATUS status; + struct cldap_reply reply; + struct ldap_Result result; + TALLOC_CTX *tmp_ctx = talloc_new(cldap); + + ZERO_STRUCT(result); + + reply.messageid = message_id; + reply.dest = src; + reply.response = NULL; + reply.result = &result; + + cldapd_rootdse_fill(cldapd, tmp_ctx, search, &reply.response, reply.result); + + status = cldap_reply_send(cldap, &reply); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("cldap rootdse query failed '%s' - %s\n", + ldb_filter_from_tree(tmp_ctx, search->tree), nt_errstr(status))); + } + + talloc_free(tmp_ctx); + return; +} |