summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2013-10-30 11:54:21 +0100
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2013-11-01 07:01:39 +0100
commit16b7ba3488c1207d2229b0b51bfa709b80cf7a1f (patch)
tree2715acdd77feef5f134e668fbd7ca92cecda604c
parent1a540680a6550f9b0938dd9c39a7558d8e578511 (diff)
downloadsamba-16b7ba3488c1207d2229b0b51bfa709b80cf7a1f.tar.gz
samba-16b7ba3488c1207d2229b0b51bfa709b80cf7a1f.tar.bz2
samba-16b7ba3488c1207d2229b0b51bfa709b80cf7a1f.zip
s4:dsdb/rootdse: Netlogon maybe requested with other attrs
MS AD allows netlogon requests to request other attributes, as long as the search parameter is correct, e.g: ldapsearch -h 192.168.122.2 -x -b '' -s base \ "(&(NtVer=\06\00\00\00)(AAC=\00\00\00\00))" \ supportedLDAPPolicies netlogon This also removes an old check that for requests having a netlogon attribute returned zero elements. This is not true, if there is a valid netlogon filter. This patch is to be squashed into "s4:dsdb/rootdse: Support netlogon request".
-rw-r--r--source4/cldap_server/cldap_server.h3
-rw-r--r--source4/cldap_server/netlogon.c43
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c101
3 files changed, 81 insertions, 66 deletions
diff --git a/source4/cldap_server/cldap_server.h b/source4/cldap_server/cldap_server.h
index 995ceed3a2..181edbd176 100644
--- a/source4/cldap_server/cldap_server.h
+++ b/source4/cldap_server/cldap_server.h
@@ -56,6 +56,7 @@ NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
const char **domain_guid,
struct dom_sid **domain_sid,
int *acct_control,
- int *version);
+ int *version,
+ bool filter_from_tree);
#include "cldap_server/proto.h"
diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c
index 0894b2bea7..a5c12df1fb 100644
--- a/source4/cldap_server/netlogon.c
+++ b/source4/cldap_server/netlogon.c
@@ -38,6 +38,7 @@
#include "../lib/tsocket/tsocket.h"
#include "libds/common/flag_mapping.h"
#include "lib/util/util_net.h"
+#include "lib/ldb/include/ldb_module.h"
/*
fill in the cldap netlogon union for a given version
@@ -369,6 +370,21 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
return NT_STATUS_OK;
}
+/*
+ create a always matching node from a equality node
+ */
+static void set_parse_tree_true(struct ldb_parse_tree *tree)
+{
+ const char *attr = tree->u.equality.attr;
+ struct ldb_val value = tree->u.equality.value;
+
+ tree->operation = LDB_OP_EXTENDED;
+ tree->u.extended.attr = attr;
+ tree->u.extended.value = value;
+ tree->u.extended.rule_id = SAMBA_LDAP_MATCH_ALWAYS_TRUE;
+ tree->u.extended.dnAttributes = 0;
+}
+
NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
struct loadparm_context *lp_ctx,
TALLOC_CTX *tmp_ctx,
@@ -378,7 +394,8 @@ NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
const char **domain_guid,
struct dom_sid **domain_sid,
int *acct_control,
- int *version)
+ int *version,
+ bool filter_from_tree)
{
unsigned int i;
@@ -400,11 +417,17 @@ NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
*domain = talloc_strndup(tmp_ctx,
(const char *)t->u.equality.value.data,
t->u.equality.value.length);
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
if (strcasecmp(t->u.equality.attr, "Host") == 0) {
*host = talloc_strndup(tmp_ctx,
(const char *)t->u.equality.value.data,
t->u.equality.value.length);
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) {
NTSTATUS enc_status;
@@ -413,6 +436,9 @@ NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
t->u.equality.value, &guid);
if (NT_STATUS_IS_OK(enc_status)) {
*domain_guid = GUID_string(tmp_ctx, &guid);
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
}
if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) {
@@ -429,19 +455,31 @@ NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
talloc_free(*domain_sid);
goto failed;
}
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
if (strcasecmp(t->u.equality.attr, "User") == 0) {
*user = talloc_strndup(tmp_ctx,
(const char *)t->u.equality.value.data,
t->u.equality.value.length);
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
if (strcasecmp(t->u.equality.attr, "NtVer") == 0 &&
t->u.equality.value.length == 4) {
*version = IVAL(t->u.equality.value.data, 0);
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
if (strcasecmp(t->u.equality.attr, "AAC") == 0 &&
t->u.equality.value.length == 4) {
*acct_control = IVAL(t->u.equality.value.data, 0);
+ if (filter_from_tree) {
+ set_parse_tree_true(t);
+ }
}
}
@@ -480,7 +518,8 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
status = parse_netlogon_request(tree, cldapd->task->lp_ctx, tmp_ctx,
&domain, &host, &user, &domain_guid,
- &domain_sid, &acct_control, &version);
+ &domain_sid, &acct_control, &version,
+ false);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index baffd1766c..3ec6248302 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -45,6 +45,12 @@ struct private_data {
bool block_anonymous;
};
+struct rootdse_context {
+ struct ldb_module *module;
+ struct ldb_request *req;
+ struct ldb_val netlogon;
+};
+
/*
return 1 if a specific attribute has been requested
*/
@@ -556,11 +562,6 @@ failed:
handle search requests
*/
-struct rootdse_context {
- struct ldb_module *module;
- struct ldb_request *req;
-};
-
static struct rootdse_context *rootdse_init_context(struct ldb_module *module,
struct ldb_request *req)
{
@@ -599,16 +600,6 @@ static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares)
switch (ares->type) {
case LDB_REPLY_ENTRY:
- /*
- * if the client explicit asks for the 'netlogon' attribute
- * the reply_entry needs to be skipped
- */
- if (ac->req->op.search.attrs &&
- ldb_attr_in_list(ac->req->op.search.attrs, "netlogon")) {
- talloc_free(ares);
- return LDB_SUCCESS;
- }
-
/* for each record returned post-process to add any dynamic
attributes that have been asked for */
ret = rootdse_add_dynamic(ac, ares->message,
@@ -618,6 +609,17 @@ static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares)
return ldb_module_done(ac->req, NULL, NULL, ret);
}
+ /* This should of cause be in rootdse_add_dynamic,
+ * but therefore we need ac there. */
+ if (ac->netlogon.length > 0) {
+ ret = ldb_msg_add_value(ares->message, "netlogon",
+ &ac->netlogon, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+
return ldb_module_send_entry(ac->req, ares->message, ares->controls);
case LDB_REPLY_REFERRAL:
@@ -760,9 +762,7 @@ static int rootdse_handle_netlogon(struct rootdse_context *ac)
int version = -1;
NTSTATUS status;
struct netlogon_samlogon_response netlogon;
- struct ldb_message *msg = NULL;
- int ret, error = LDB_ERR_OPERATIONS_ERROR;
- struct ldb_val blob;
+ int ret = LDB_SUCCESS;
ldb = ldb_module_get_ctx(ac->module);
tree = ac->req->op.search.tree;
@@ -774,9 +774,12 @@ static int rootdse_handle_netlogon(struct rootdse_context *ac)
status = parse_netlogon_request(tree, lp_ctx, tmp_ctx,
&domain, &host, &user, &domain_guid,
- &domain_sid, &acct_control, &version);
+ &domain_sid, &acct_control, &version,
+ true);
if (!NT_STATUS_IS_OK(status)) {
- goto failed;
+ /* We have to return an empty search if the filter
+ * does not match, no an error. */
+ goto done;
}
status = fill_netlogon_samlogon_response(ldb, tmp_ctx,
@@ -787,50 +790,19 @@ static int rootdse_handle_netlogon(struct rootdse_context *ac)
version, lp_ctx,
&netlogon, false);
if (!NT_STATUS_IS_OK(status)) {
- goto failed;
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
}
- status = push_netlogon_samlogon_response(&blob, tmp_ctx, &netlogon);
+ status = push_netlogon_samlogon_response(&ac->netlogon, ac, &netlogon);
if (!NT_STATUS_IS_OK(status)) {
- goto failed;
- }
-
- msg = ldb_msg_new(tmp_ctx);
- if (!msg) {
- error = ldb_oom(ldb);
- goto failed;
- }
-
- msg->dn = ldb_dn_new(msg, ldb, "");
- if (!msg->dn) {
- error = ldb_oom(ldb);
- goto failed;
- }
-
- ret = ldb_msg_add_value(msg, "netlogon", &blob, NULL);
- if (ret != LDB_SUCCESS) {
- error = ret;
- goto failed;
- }
-
- ret = ldb_module_send_entry(ac->req, msg, NULL);
- if (ret != LDB_SUCCESS) {
- error = ret;
- goto failed;
- }
-
- ret = ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
- if (ret != LDB_SUCCESS) {
- error = ret;
- goto failed;
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
}
+done:
talloc_free(tmp_ctx);
- return LDB_SUCCESS;
-
-failed:
- talloc_free(tmp_ctx);
- return ldb_module_done(ac->req, NULL, NULL, error);
+ return ret;
}
static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
@@ -863,11 +835,14 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
return ldb_operr(ldb);
}
- if (req->op.search.attrs &&
- req->op.search.attrs[0] &&
- req->op.search.attrs[1] == NULL &&
- ldb_attr_cmp(req->op.search.attrs[0], "netlogon") == 0) {
- return rootdse_handle_netlogon(ac);
+ if (do_attribute_explicit(req->op.search.attrs, "netlogon")) {
+ ret = rootdse_handle_netlogon(ac);
+ /* Finish with an empty reply here, either if:
+ * - An error was returned, or
+ * - No valid netlogon generated (i.e filter didn't match). */
+ if (ret != LDB_SUCCESS || ac->netlogon.length == 0) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
}
/* in our db we store the rootDSE with a DN of @ROOTDSE */