summaryrefslogtreecommitdiff
path: root/source3/rpc_server/netlogon
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-09-03 11:56:31 +0200
committerGünther Deschner <gd@samba.org>2011-02-16 11:44:07 +0100
commit77638169681ce5da6a3f7705b16a8f2b5d261671 (patch)
tree9d45399b2b87370cdaf752801a451a1002b649d5 /source3/rpc_server/netlogon
parent9ebbbb7456e501c3b43677cd96d880e7320765b8 (diff)
downloadsamba-77638169681ce5da6a3f7705b16a8f2b5d261671.tar.gz
samba-77638169681ce5da6a3f7705b16a8f2b5d261671.tar.bz2
samba-77638169681ce5da6a3f7705b16a8f2b5d261671.zip
s3-netlogon: Implement NetrServerGetTrustInfo and NetrGetForestTrustInformation
Signed-off-by: Günther Deschner <gd@samba.org>
Diffstat (limited to 'source3/rpc_server/netlogon')
-rw-r--r--source3/rpc_server/netlogon/srv_netlog_nt.c261
1 files changed, 257 insertions, 4 deletions
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index b55c74adfc..f5dace2753 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -37,6 +37,10 @@
#include "rpc_client/init_lsa.h"
#include "rpc_server/rpc_ncacn_np.h"
#include "../libcli/security/security.h"
+#include "../libcli/security/dom_sid.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "lib/crypto/arcfour.h"
+#include "lib/crypto/md4.h"
extern userdom_struct current_user_info;
@@ -2177,21 +2181,270 @@ WERROR _netr_DsRGetForestTrustInformation(struct pipes_struct *p,
/****************************************************************
****************************************************************/
+static NTSTATUS fill_forest_trust_array(TALLOC_CTX *mem_ctx,
+ struct lsa_ForestTrustInformation *info)
+{
+ struct lsa_ForestTrustRecord *e;
+ struct pdb_domain_info *dom_info;
+ struct lsa_ForestTrustDomainInfo *domain_info;
+
+ dom_info = pdb_get_domain_info(mem_ctx);
+ if (dom_info == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ info->count = 2;
+ info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
+ if (info->entries == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ e = talloc(info, struct lsa_ForestTrustRecord);
+ if (e == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ e->flags = 0;
+ e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
+ e->time = 0; /* so far always 0 in trces. */
+ e->forest_trust_data.top_level_name.string = talloc_steal(info,
+ dom_info->dns_forest);
+
+ info->entries[0] = e;
+
+ e = talloc(info, struct lsa_ForestTrustRecord);
+ if (e == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* TODO: check if disabled and set flags accordingly */
+ e->flags = 0;
+ e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
+ e->time = 0; /* so far always 0 in traces. */
+
+ domain_info = &e->forest_trust_data.domain_info;
+ domain_info->domain_sid = dom_sid_dup(info, &dom_info->sid);
+
+ domain_info->dns_domain_name.string = talloc_steal(info,
+ dom_info->dns_domain);
+ domain_info->netbios_domain_name.string = talloc_steal(info,
+ dom_info->name);
+
+ info->entries[1] = e;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ _netr_GetForestTrustInformation
+****************************************************************/
+
NTSTATUS _netr_GetForestTrustInformation(struct pipes_struct *p,
struct netr_GetForestTrustInformation *r)
{
- p->rng_fault_state = true;
- return NT_STATUS_NOT_IMPLEMENTED;
+ NTSTATUS status;
+ struct netlogon_creds_CredentialState *creds;
+ struct lsa_ForestTrustInformation *info, **info_ptr;
+
+ /* TODO: check server name */
+
+ status = schannel_check_creds_state(p->mem_ctx, lp_private_dir(),
+ r->in.computer_name,
+ r->in.credential,
+ r->out.return_authenticator,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
+ (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ info_ptr = talloc(p->mem_ctx, struct lsa_ForestTrustInformation *);
+ if (!info_ptr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
+ if (!info) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = fill_forest_trust_array(p->mem_ctx, info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *info_ptr = info;
+ r->out.forest_trust_info = info_ptr;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS get_password_from_trustAuth(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *trustAuth_blob,
+ const DATA_BLOB *session_key,
+ struct samr_Password *current_pw_enc,
+ struct samr_Password *previous_pw_enc)
+{
+ enum ndr_err_code ndr_err;
+ struct trustAuthInOutBlob trustAuth;
+
+ ndr_err = ndr_pull_struct_blob_all(trustAuth_blob, mem_ctx, &trustAuth,
+ (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+
+ if (trustAuth.count != 0 && trustAuth.current.count != 0 &&
+ trustAuth.current.array[0].AuthType == TRUST_AUTH_TYPE_CLEAR) {
+ mdfour(previous_pw_enc->hash,
+ trustAuth.current.array[0].AuthInfo.clear.password,
+ trustAuth.current.array[0].AuthInfo.clear.size);
+ } else {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ arcfour_crypt_blob(current_pw_enc->hash, sizeof(current_pw_enc->hash),
+ session_key);
+
+ if (trustAuth.previous.count != 0 &&
+ trustAuth.previous.array[0].AuthType == TRUST_AUTH_TYPE_CLEAR) {
+ mdfour(previous_pw_enc->hash,
+ trustAuth.previous.array[0].AuthInfo.clear.password,
+ trustAuth.previous.array[0].AuthInfo.clear.size);
+ } else {
+ mdfour(previous_pw_enc->hash, NULL, 0);
+ }
+ arcfour_crypt_blob(previous_pw_enc->hash, sizeof(previous_pw_enc->hash),
+ session_key);
+
+ return NT_STATUS_OK;
}
/****************************************************************
+ _netr_ServerGetTrustInfo
****************************************************************/
NTSTATUS _netr_ServerGetTrustInfo(struct pipes_struct *p,
struct netr_ServerGetTrustInfo *r)
{
- p->rng_fault_state = true;
- return NT_STATUS_NOT_IMPLEMENTED;
+ NTSTATUS status;
+ struct netlogon_creds_CredentialState *creds;
+ char *account_name;
+ size_t account_name_last;
+ bool trusted;
+ struct netr_TrustInfo *trust_info;
+ struct pdb_trusted_domain *td;
+ DATA_BLOB trustAuth_blob;
+ struct samr_Password *new_owf_enc;
+ struct samr_Password *old_owf_enc;
+ DATA_BLOB session_key;
+
+ /* TODO: check server name */
+
+ status = schannel_check_creds_state(p->mem_ctx, lp_private_dir(),
+ r->in.computer_name,
+ r->in.credential,
+ r->out.return_authenticator,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ account_name = talloc_strdup(p->mem_ctx, r->in.account_name);
+ if (account_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ account_name_last = strlen(account_name);
+ if (account_name_last == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ account_name_last--;
+ if (account_name[account_name_last] == '.') {
+ account_name[account_name_last] = '\0';
+ }
+
+ if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
+ (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
+ trusted = false;
+ } else {
+ trusted = true;
+ }
+
+
+ if (trusted) {
+ account_name_last = strlen(account_name);
+ if (account_name_last == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ account_name_last--;
+ if (account_name[account_name_last] == '$') {
+ account_name[account_name_last] = '\0';
+ }
+
+ status = pdb_get_trusted_domain(p->mem_ctx, account_name, &td);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (r->out.trust_info != NULL) {
+ trust_info = talloc_zero(p->mem_ctx, struct netr_TrustInfo);
+ if (trust_info == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ trust_info->count = 1;
+
+ trust_info->data = talloc_array(trust_info, uint32_t, 1);
+ if (trust_info->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ trust_info->data[0] = td->trust_attributes;
+
+ *r->out.trust_info = trust_info;
+ }
+
+ new_owf_enc = talloc_zero(p->mem_ctx, struct samr_Password);
+ old_owf_enc = talloc_zero(p->mem_ctx, struct samr_Password);
+ if (new_owf_enc == NULL || old_owf_enc == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+/* TODO: which trustAuth shall we use if we have in/out trust or do they have to
+ * be equal ? */
+ if (td->trust_direction & NETR_TRUST_FLAG_INBOUND) {
+ trustAuth_blob = td->trust_auth_incoming;
+ } else if (td->trust_direction & NETR_TRUST_FLAG_OUTBOUND) {
+ trustAuth_blob = td->trust_auth_outgoing;
+ }
+
+ session_key.data = creds->session_key;
+ session_key.length = sizeof(creds->session_key);
+ status = get_password_from_trustAuth(p->mem_ctx, &trustAuth_blob,
+ &session_key,
+ new_owf_enc, old_owf_enc);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ r->out.new_owf_password = new_owf_enc;
+ r->out.old_owf_password = old_owf_enc;
+ } else {
+/* TODO: look for machine password */
+ r->out.new_owf_password = NULL;
+ r->out.old_owf_password = NULL;
+
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ return NT_STATUS_OK;
}
/****************************************************************