summaryrefslogtreecommitdiff
path: root/source4/rpc_server/netlogon
diff options
context:
space:
mode:
authorMatthias Dieter Wallnöfer <mwallnoefer@yahoo.de>2010-03-05 11:09:57 +0100
committerMatthias Dieter Wallnöfer <mwallnoefer@yahoo.de>2010-03-09 17:18:46 +0100
commit9995a37a8cffb5e20e2b0ef5abfee602673d362d (patch)
tree198c3281d72eabd28a91fc4d3bdde27086ae18c1 /source4/rpc_server/netlogon
parent1deefcaee1f3de97c0377b513a6f9c3d1181e2b0 (diff)
downloadsamba-9995a37a8cffb5e20e2b0ef5abfee602673d362d.tar.gz
samba-9995a37a8cffb5e20e2b0ef5abfee602673d362d.tar.bz2
samba-9995a37a8cffb5e20e2b0ef5abfee602673d362d.zip
s4:netlogon RPC - "LogonGetDomainInfo" - make the call compatible with >= Windows 2008
Add more security checks and other corrections to imitate Windows Server >= 2008.
Diffstat (limited to 'source4/rpc_server/netlogon')
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c85
1 files changed, 62 insertions, 23 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 563ed5eddb..e82158f4a0 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -1148,16 +1148,18 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
"securityIdentifier", "trustPartner", NULL };
const char * const attrs2[] = { "dNSHostName",
"msDS-SupportedEncryptionTypes", NULL };
- const char *temp_str;
+ const char * const attrs3[] = { NULL };
+ const char *temp_str, *temp_str2;
const char *old_dns_hostname;
struct ldb_context *sam_ctx;
- struct ldb_message **res1, **res2, **res3, *new_msg;
+ struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
struct ldb_dn *workstation_dn;
struct netr_DomainInformation *domain_info;
struct netr_LsaPolicyInformation *lsa_policy_info;
struct netr_OsVersionInfoEx *os_version;
uint32_t default_supported_enc_types = 0xFFFFFFFF;
- int ret1, ret2, ret3, i;
+ bool update_dns_hostname = true;
+ int ret, ret3, i;
NTSTATUS status;
status = dcesrv_netr_creds_server_step_check(dce_call,
@@ -1181,27 +1183,59 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
switch (r->in.level) {
case 1: /* Domain information */
- /* TODO: check NTSTATUS results - and fail also on SAMDB
- * errors (needs some testing against Windows Server 2008) */
+ /*
+ * Updates the DNS hostname when the client wishes that the
+ * server should handle this for him
+ * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
+ * See MS-NRPC section 3.5.4.3.9
+ */
+ if ((r->in.query->workstation_info->workstation_flags
+ & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
+ update_dns_hostname = false;
+ }
/*
- * Check that the computer name parameter matches as prefix with
- * the DNS hostname in the workstation info structure.
+ * Checks that the computer name parameter without possible "$"
+ * matches as prefix with the DNS hostname in the workstation
+ * info structure.
*/
- temp_str = strndup(r->in.query->workstation_info->dns_hostname,
- strcspn(r->in.query->workstation_info->dns_hostname,
- "."));
- if (strcasecmp(r->in.computer_name, temp_str) != 0)
- return NT_STATUS_INVALID_PARAMETER;
+ temp_str = talloc_strndup(mem_ctx,
+ r->in.computer_name,
+ strcspn(r->in.computer_name, "$"));
+ NT_STATUS_HAVE_NO_MEMORY(temp_str);
+ temp_str2 = talloc_strndup(mem_ctx,
+ r->in.query->workstation_info->dns_hostname,
+ strcspn(r->in.query->workstation_info->dns_hostname, "."));
+ NT_STATUS_HAVE_NO_MEMORY(temp_str2);
+ if (strcasecmp(temp_str, temp_str2) != 0) {
+ update_dns_hostname = false;
+ }
+
+ /*
+ * Check that the DNS hostname when it should be updated
+ * will be used only by maximum one host.
+ */
+ ret = gendb_search(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
+ &res0, attrs3, "(dNSHostName=%s)",
+ r->in.query->workstation_info->dns_hostname);
+ if (ret < 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (ret >= 1) {
+ update_dns_hostname = false;
+ }
+
+ talloc_free(res0);
+ /* Prepare the workstation DN */
workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
dom_sid_string(mem_ctx, creds->sid));
NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
/* Lookup for attributes in workstation object */
- ret1 = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
+ ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
&res1, attrs2);
- if (ret1 != 1) {
+ if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -1260,13 +1294,10 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
}
/*
- * Updates the "dNSHostname" and the "servicePrincipalName"s
- * since the client wishes that the server should handle this
- * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
- * See MS-NRPC section 3.5.4.3.9
+ * If the boolean "update_dns_hostname" remained true, then we
+ * are fine to start the update.
*/
- if ((r->in.query->workstation_info->workstation_flags
- & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
+ if (update_dns_hostname) {
samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
"dNSHostname",
r->in.query->workstation_info->dns_hostname);
@@ -1297,9 +1328,9 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
primary domain is also a "trusted" domain, so we need to
put the primary domain into the lists of returned trusts as
well. */
- ret2 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
+ ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
&res2, attrs);
- if (ret2 != 1) {
+ if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -1356,7 +1387,15 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
domain_info->lsa_policy = *lsa_policy_info;
- domain_info->dns_hostname.string = old_dns_hostname;
+ /* The DNS hostname is only returned back when there is a chance
+ * for a change. */
+ if ((r->in.query->workstation_info->workstation_flags
+ & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
+ domain_info->dns_hostname.string = old_dns_hostname;
+ } else {
+ domain_info->dns_hostname.string = NULL;
+ }
+
domain_info->workstation_flags =
r->in.query->workstation_info->workstation_flags;