[PATCH 17/22] passdb: Use sam_get_results_trust() and implement pdb_samba_dsdb_get_trusteddom_pw

abartlet at samba.org abartlet at samba.org
Tue Aug 19 20:06:52 MDT 2014


From: Andrew Bartlett <abartlet at samba.org>

We now return the plaintext passwords for trusted domains so winbindd can use them.

Change-Id: Ifcd59b0be815d25b73bdbc41db7477895461c7b6
Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
Signed-off-by: Garming Sam <garming at catalyst.net.nz>
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/passdb/pdb_ldap.c       |   9 ++-
 source3/passdb/pdb_samba_dsdb.c | 125 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 7dccc03..47e7b4a 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -6031,16 +6031,21 @@ static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
 {
 	int rc;
 	char *filter;
-	int scope = LDAP_SCOPE_SUBTREE;
+	int scope = LDAP_SCOPE_BASE;
 	const char **attrs = NULL; /* NULL: get all attrs */
 	int attrsonly = 0; /* 0: return values too */
 	LDAPMessage *result = NULL;
 	char *trusted_dn;
 	uint32_t num_result;
+	char *escape_domain = escape_ldap_string(talloc_tos(), domain);
+
+	if (!escape_domain) {
+		return LDAP_NO_MEMORY;
+	}
 
 	filter = talloc_asprintf(talloc_tos(),
 				 "(&(objectClass=%s)(sambaDomainName=%s))",
-				 LDAP_OBJ_TRUSTDOM_PASSWORD, domain);
+				 LDAP_OBJ_TRUSTDOM_PASSWORD, escape_domain);
 
 	trusted_dn = trusteddom_dn(ldap_state, domain);
 	if (trusted_dn == NULL) {
diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c
index b04e7b2..62c693b 100644
--- a/source3/passdb/pdb_samba_dsdb.c
+++ b/source3/passdb/pdb_samba_dsdb.c
@@ -28,6 +28,8 @@
 #include "libcli/security/dom_sid.h"
 #include "source4/winbind/idmap.h"
 #include "librpc/gen_ndr/ndr_security.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "librpc/gen_ndr/ndr_lsa.h"
 #include "libds/common/flag_mapping.h"
 #include "source4/lib/events/events.h"
 #include "source4/auth/session.h"
@@ -35,6 +37,7 @@
 #include "lib/param/param.h"
 #include "source4/dsdb/common/util.h"
 #include "source3/include/secrets.h"
+#include "source4/auth/auth_sam.h"
 
 struct pdb_samba_dsdb_state {
 	struct tevent_context *ev;
@@ -2142,7 +2145,127 @@ static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
 				      struct dom_sid *sid,
 				      time_t *pass_last_set_time)
 {
-	return false;
+	struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
+		m->private_data, struct pdb_samba_dsdb_state);
+	TALLOC_CTX *tmp_ctx = talloc_stackframe();
+	const char * const attrs[] = {
+		"securityIdentifier",
+		"trustPartner",
+		"trustAuthOutgoing",
+		"whenCreated",
+		"msDS-SupportedEncryptionTypes",
+		"trustAttributes",
+		"trustDirection",
+		"trustType",
+		NULL
+	};
+	struct ldb_message *msg;
+	const struct ldb_val *password_val;
+	int trust_direction_flags;
+	int trust_type;
+	int i;
+	DATA_BLOB password_utf16;
+	struct trustAuthInOutBlob password_blob;
+	struct AuthenticationInformationArray *auth_array;
+	char *password_talloc;
+	size_t password_len;
+	enum ndr_err_code ndr_err;
+
+	NTSTATUS status = sam_get_results_trust(state->ldb,
+						tmp_ctx, domain, NULL, attrs, &msg);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * This can be called to work out of a domain is
+		 * trusted, rather than just to get the password 
+		 */
+		DEBUG(2, ("Failed to get trusted domain password for %s.  "
+			  "It may not be a trusted domain.\n", domain));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+
+	trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
+	if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
+		DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n", 
+			  domain));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+
+	trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
+	if (trust_type == LSA_TRUST_TYPE_MIT) {
+		DEBUG(1, ("Trusted domain %s is is not an AD trust (trustType == LSA_TRUST_TYPE_MIT).\n", 
+			  domain));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+
+	password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
+	
+	if (password_val == NULL) {
+		DEBUG(2, ("Failed to get trusted domain password for %s, "
+			  "attribute trustAuthOutgoing not returned.\n", domain));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+	
+	ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
+				       (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DEBUG(0, ("Failed to get trusted domain password for %s, "
+			  "attribute trustAuthOutgoing coult not be parsed %s.\n", 
+			  domain,
+			  ndr_map_error2string(ndr_err)));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+
+	auth_array = &password_blob.current;
+
+	for (i=0; i < auth_array->count; i++) {
+		if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
+			break;
+		}
+	}
+
+	if (i == auth_array->count) {
+		DEBUG(0, ("Trusted domain %s does not have a clear-text password stored\n", 
+			  domain));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+	
+	password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
+									 auth_array->array[i].AuthInfo.clear.size);
+	
+	/* 
+	 * In the future, make this function return a
+	 * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
+	 * but for now convert to UTF8 and fail if the string can not be converted.
+	 * 
+	 * We can't safely convert the random strings windows uses into
+	 * utf8.
+	 */
+	
+	if (!convert_string_talloc(tmp_ctx,
+				   CH_UTF16, CH_UTF8,
+				   password_utf16.data, password_utf16.length,
+				   (void *)&password_talloc,
+				   &password_len)) {
+		DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
+			  " to UTF8.  This may be a password set from Windows.  \n",
+			  domain));
+		TALLOC_FREE(tmp_ctx);
+		return false;
+	}
+	*pwd = SMB_STRNDUP(password_talloc, password_len);
+	if (pass_last_set_time) {
+		*pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
+	}
+
+	TALLOC_FREE(tmp_ctx);
+	return true;
 }
 
 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
-- 
2.0.1



More information about the samba-technical mailing list