summaryrefslogtreecommitdiff
path: root/source4/rpc_server/netlogon/dcerpc_netlogon.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/rpc_server/netlogon/dcerpc_netlogon.c')
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c121
1 files changed, 97 insertions, 24 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 6f4287f9d8..9d4c897892 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -29,13 +29,14 @@
#include "dsdb/samdb/samdb.h"
#include "dsdb/common/flags.h"
#include "rpc_server/samr/proto.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
#include "libcli/auth/libcli_auth.h"
#include "auth/gensec/schannel_state.h"
#include "libcli/security/security.h"
#include "param/param.h"
#include "lib/messaging/irpc.h"
#include "librpc/gen_ndr/ndr_irpc.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
struct server_pipe_state {
struct netr_Credential client_challenge;
@@ -86,6 +87,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
const char *attrs[] = {"unicodePwd", "userAccountControl",
"objectSid", NULL};
+ const char *trust_dom_attrs[] = {"flatname", NULL};
+ const char *account_name;
+
ZERO_STRUCTP(r->out.credentials);
*r->out.rid = 0;
*r->out.negotiate_flags = *r->in.negotiate_flags;
@@ -100,10 +104,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
+
+ if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
+ char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
+ const char *flatname;
+ if (!encoded_account) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Kill the trailing dot */
+ if (encoded_account[strlen(encoded_account)-1] == '.') {
+ encoded_account[strlen(encoded_account)-1] = '\0';
+ }
+
+ /* pull the user attributes */
+ num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs,
+ "(&(trustPartner=%s)(objectclass=trustedDomain))",
+ encoded_account);
+
+ if (num_records == 0) {
+ DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
+ encoded_account));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (num_records > 1) {
+ DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
+ if (!flatname) {
+ /* No flatname for this trust - we can't proceed */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
+
+ if (!account_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ } else {
+ account_name = r->in.account_name;
+ }
+
/* pull the user attributes */
num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
"(&(sAMAccountName=%s)(objectclass=user))",
- r->in.account_name);
+ ldb_binary_encode_string(mem_ctx, account_name));
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in samdb.\n",
@@ -129,7 +177,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
return NT_STATUS_ACCESS_DENIED;
}
- } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) {
+ } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
+ r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
@@ -321,7 +370,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
creds->sid,
NULL, /* Don't have plaintext */
NULL, &r->in.new_password,
- false, /* This is not considered a password change */
+ true, /* Password change */
NULL, NULL);
return nt_status;
}
@@ -336,16 +385,14 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- char new_pass[512];
- uint32_t new_pass_len;
- bool ret;
+ DATA_BLOB new_password;
struct samr_CryptPassword password_buf;
nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
r->in.computer_name, mem_ctx,
- &r->in.credential, &r->out.return_authenticator,
- &creds);
+ &r->in.credential, &r->out.return_authenticator,
+ &creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
@@ -354,22 +401,20 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
}
memcpy(password_buf.data, r->in.new_password.data, 512);
- SIVAL(password_buf.data,512,r->in.new_password.length);
+ SIVAL(password_buf.data, 512, r->in.new_password.length);
creds_arcfour_crypt(creds, password_buf.data, 516);
- ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass),
- &new_pass_len, STR_UNICODE);
- if (!ret) {
- DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
- return NT_STATUS_ACCESS_DENIED;
+ if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
+ DEBUG(3,("samr: failed to decode password buffer\n"));
+ return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* Using the sid for the account as the key, set the password */
nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
creds->sid,
- new_pass, /* we have plaintext */
+ &new_password, /* we have plaintext */
NULL, NULL,
- false, /* This is not considered a password change */
+ true, /* Password change */
NULL, NULL);
return nt_status;
}
@@ -899,20 +944,37 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
struct ldb_message *res,
struct ldb_message *ref_res,
struct netr_DomainTrustInfo *info,
- bool is_local)
+ bool is_local, bool is_trust_list)
{
ZERO_STRUCTP(info);
+ info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
+ info->trust_extension.length = 16;
+ info->trust_extension.info->flags =
+ NETR_TRUST_FLAG_TREEROOT |
+ NETR_TRUST_FLAG_IN_FOREST |
+ NETR_TRUST_FLAG_PRIMARY;
+ info->trust_extension.info->parent_index = 0; /* should be index into array
+ of parent */
+ info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
+ info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
+
+ if (is_trust_list) {
+ /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
+ info->forest.string = NULL;
+ } else {
+ /* TODO: we need a common function for pulling the forest */
+ info->forest.string = samdb_result_string(ref_res, "dnsRoot", NULL);
+ }
+
if (is_local) {
info->domainname.string = samdb_result_string(ref_res, "nETBIOSName", NULL);
info->fulldomainname.string = samdb_result_string(ref_res, "dnsRoot", NULL);
- info->forest.string = NULL;
info->guid = samdb_result_guid(res, "objectGUID");
info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
} else {
info->domainname.string = samdb_result_string(res, "flatName", NULL);
info->fulldomainname.string = samdb_result_string(res, "trustPartner", NULL);
- info->forest.string = NULL;
info->guid = samdb_result_guid(res, "objectGUID");
info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
}
@@ -948,6 +1010,9 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
r->in.credential,
r->out.return_authenticator,
NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,(__location__ " Bad credentials - error\n"));
+ }
NT_STATUS_NOT_OK_RETURN(status);
sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
@@ -993,17 +1058,25 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
info1->num_trusts);
NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
- status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, true);
+ status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo,
+ true, false);
NT_STATUS_NOT_OK_RETURN(status);
for (i=0;i<ret2;i++) {
- status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], false);
+ status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i],
+ false, true);
NT_STATUS_NOT_OK_RETURN(status);
}
- status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], true);
+ status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i],
+ true, true);
NT_STATUS_NOT_OK_RETURN(status);
+ info1->dns_hostname.string = samdb_result_string(ref_res[0], "dnsRoot", NULL);
+ info1->workstation_flags =
+ NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS | NETR_WS_FLAG_HANDLES_SPN_UPDATE;
+ info1->supported_enc_types = 0; /* w2008 gives this 0 */
+
r->out.info.info1 = info1;
return NT_STATUS_OK;