[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Thu Nov 5 04:43:26 MST 2009


The branch, master has been updated
       via  1685ee3... s4:torture/rpc/samr - Add a comment for "ValidatePassword" test
       via  3372e2a... s4:dcesrv_samr - Implement "dcesrv_samr_ValidatePassword" using my new check password call
       via  85f61e5... s4:dsdb/common/util - Add a new utility function "samdb_check_password"
       via  3a6bde7... s4:samdb_set_password/samdb_set_password_sid - Better comments and cosmetics
      from  d415d4d... s3: Add parameter "ctdb timeout"

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 1685ee3ee7b40ee8e36ab799c447ffacdc5d93ea
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Thu Nov 5 12:37:16 2009 +0100

    s4:torture/rpc/samr - Add a comment for "ValidatePassword" test

commit 3372e2a0cc479bf17f04481b172087fbef711ea3
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Wed Nov 4 12:02:02 2009 +0100

    s4:dcesrv_samr - Implement "dcesrv_samr_ValidatePassword" using my new check password call
    
    This implements a very basic method for password validation using my new
    "samdb_check_password" call.

commit 85f61e5342bd3b57983045d54de3d824c81079b2
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Oct 24 20:21:04 2009 +0200

    s4:dsdb/common/util - Add a new utility function "samdb_check_password"
    
    This function performs basic password checks and will be used by the
    "samrValidatePassword" call and the "password_hash" module.

commit 3a6bde799d7fd7dffddbde885abe991407233c07
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Oct 24 19:31:01 2009 +0200

    s4:samdb_set_password/samdb_set_password_sid - Better comments and cosmetics

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/common/util.c            |  116 ++++++++++++++++++++++-----------
 source4/rpc_server/samr/dcesrv_samr.c |   56 ++++++++++++++--
 source4/torture/rpc/samr.c            |    2 +
 3 files changed, 130 insertions(+), 44 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index ace8e18..d953e63 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -1574,20 +1574,55 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 
 
 /*
-  set the user password using plaintext, obeying any user or domain
-  password restrictions
+ * Performs checks on a user password (plaintext UTF 16 format - attribute
+ * "password"). The remaining parameters have to be extracted from the domain
+ * object in the AD.
+ *
+ * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
+ */
+enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
+						struct loadparm_context *lp_ctx,
+						const DATA_BLOB *password,
+						const uint32_t pwdProperties,
+						const uint32_t minPwdLength)
+{
+	char *utf8_password;
+	size_t utf8_password_len;
 
-  note that this function doesn't actually store the result in the
-  database, it just fills in the "mod" structure with ldb modify
-  elements to setup the correct change when samdb_replace() is
-  called. This allows the caller to combine the change with other
-  changes (as is needed by some of the set user info levels)
+	/* checks if the "minPwdLength" property is satisfied */
+	if (minPwdLength > utf16_len_n(password->data, password->length) / 2)
+		return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
 
-  The caller should probably have a transaction wrapping this
-*/
+	/* Try to convert the password to UTF8 and perform other checks */
+	if (convert_string_talloc_convenience(mem_ctx,
+					      lp_iconv_convenience(lp_ctx),
+					      CH_UTF16MUNGED, CH_UTF8,
+					      password->data, password->length,
+					      (void **)&utf8_password,
+					      &utf8_password_len, false)) {
+		/* checks the password complexity */
+		if (((pwdProperties & DOMAIN_PASSWORD_COMPLEX) != 0)
+				&& (!check_password_quality(utf8_password)))
+			return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
+	}
+
+	return SAMR_VALIDATION_STATUS_SUCCESS;
+}
+
+/*
+ * Sets the user password using plaintext UTF16 (attribute "new_password") or
+ * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
+ * as parameter if it's a user change or not ("userChange"). The "rejectReason"
+ * gives some more informations if the changed failed.
+ *
+ * The caller should have a LDB transaction wrapping this.
+ *
+ * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
+ *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
+ *   NT_STATUS_PASSWORD_RESTRICTION
+ */
 NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
-			    struct ldb_dn *user_dn,
-			    struct ldb_dn *domain_dn,
+			    struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
 			    struct ldb_message *mod,
 			    const DATA_BLOB *new_password,
 			    struct samr_Password *param_lmNewHash,
@@ -1851,16 +1886,24 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
 
 
 /*
-  set the user password using plaintext, obeying any user or domain
-  password restrictions
-
-  This wrapper function takes a SID as input, rather than a user DN,
-  and actually performs the password change
-
-*/
-NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
+ * Sets the user password using plaintext UTF16 (attribute "new_password") or
+ * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
+ * as parameter if it's a user change or not ("userChange"). The "rejectReason"
+ * gives some more informations if the changed failed.
+ *
+ * This wrapper function for "samdb_set_password" takes a SID as input rather
+ * than a user DN.
+ *
+ * This call encapsulates a new LDB transaction for changing the password;
+ * therefore the user hasn't to start a new one.
+ *
+ * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
+ *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
+ *   NT_STATUS_PASSWORD_RESTRICTION
+ */
+NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 				const struct dom_sid *user_sid,
-				const DATA_BLOB *new_pass,
+				const DATA_BLOB *new_password,
 				struct samr_Password *lmNewHash, 
 				struct samr_Password *ntNewHash,
 				bool user_change,
@@ -1872,17 +1915,17 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
 	struct ldb_message *msg;
 	int ret;
 
-	ret = ldb_transaction_start(ctx);
-	if (ret) {
-		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ctx)));
+	ret = ldb_transaction_start(ldb);
+	if (ret != LDB_SUCCESS) {
+		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ldb)));
 		return NT_STATUS_TRANSACTION_ABORTED;
 	}
 
-	user_dn = samdb_search_dn(ctx, mem_ctx, NULL, 
+	user_dn = samdb_search_dn(ldb, mem_ctx, NULL,
 				  "(&(objectSid=%s)(objectClass=user))", 
 				  ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
 	if (!user_dn) {
-		ldb_transaction_cancel(ctx);
+		ldb_transaction_cancel(ldb);
 		DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n",
 			  dom_sid_string(mem_ctx, user_sid)));
 		return NT_STATUS_NO_SUCH_USER;
@@ -1890,46 +1933,45 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
 
 	msg = ldb_msg_new(mem_ctx);
 	if (msg == NULL) {
-		ldb_transaction_cancel(ctx);
+		ldb_transaction_cancel(ldb);
 		return NT_STATUS_NO_MEMORY;
 	}
 
 	msg->dn = ldb_dn_copy(msg, user_dn);
 	if (!msg->dn) {
-		ldb_transaction_cancel(ctx);
+		ldb_transaction_cancel(ldb);
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	nt_status = samdb_set_password(ctx, mem_ctx,
+	nt_status = samdb_set_password(ldb, mem_ctx,
 				       user_dn, NULL,
-				       msg, new_pass, 
+				       msg, new_password,
 				       lmNewHash, ntNewHash,
 				       user_change, /* This is a password set, not change */
 				       reject_reason, _dominfo);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		ldb_transaction_cancel(ctx);
+		ldb_transaction_cancel(ldb);
 		return nt_status;
 	}
 
 	/* modify the samdb record */
-	ret = samdb_replace(ctx, mem_ctx, msg);
-	if (ret != 0) {
-		ldb_transaction_cancel(ctx);
+	ret = samdb_replace(ldb, mem_ctx, msg);
+	if (ret != LDB_SUCCESS) {
+		ldb_transaction_cancel(ldb);
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	ret = ldb_transaction_commit(ctx);
-	if (ret != 0) {
+	ret = ldb_transaction_commit(ldb);
+	if (ret != LDB_SUCCESS) {
 		DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
 			 ldb_dn_get_linearized(msg->dn),
-			 ldb_errstring(ctx)));
+			 ldb_errstring(ldb)));
 		return NT_STATUS_TRANSACTION_ABORTED;
 	}
 	return NT_STATUS_OK;
 }
 
 
-
 NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 
 						 struct dom_sid *sid, struct ldb_dn **ret_dn) 
 {
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 7be1cf9..eecc00d 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -4179,7 +4179,9 @@ static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TAL
 
 	ZERO_STRUCTP(r->out.info);
 
-	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 
+	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
+					 dce_call->conn->dce_ctx->lp_ctx,
+					 dce_call->conn->auth_state.session_info);
 	if (sam_ctx == NULL) {
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
@@ -4354,15 +4356,55 @@ static NTSTATUS dcesrv_samr_SetDsrmPassword(struct dcesrv_call_state *dce_call,
 
 
 /* 
-  samr_ValidatePassword 
+  samr_ValidatePassword
+
+  For now the call checks the password complexity (if active) and the minimum
+  password length on level 2 and 3. Level 1 is ignored for now.
 */
-static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-				      struct samr_ValidatePassword *r)
+static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
+					     TALLOC_CTX *mem_ctx,
+					     struct samr_ValidatePassword *r)
 {
-	/* just say it's OK for now - we need to hook this into our
-	   password strength code later */
-	DEBUG(0,(__location__ ": Faking samr_ValidatePassword reply\n"));
+	struct samr_GetDomPwInfo r2;
+	DATA_BLOB password;
+	enum samr_ValidationStatus res;
+	NTSTATUS status;
+
 	(*r->out.rep) = talloc_zero(mem_ctx, union samr_ValidatePasswordRep);
+
+	r2.in.domain_name = NULL;
+	status = dcesrv_samr_GetDomPwInfo(dce_call, mem_ctx, &r2);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	switch (r->in.level) {
+	case NetValidateAuthentication:
+		/* we don't support this yet */
+		return NT_STATUS_NOT_SUPPORTED;
+	break;
+	case NetValidatePasswordChange:
+		password = data_blob_const(r->in.req->req2.password.string,
+					   r->in.req->req2.password.length);
+		res = samdb_check_password(mem_ctx,
+					   dce_call->conn->dce_ctx->lp_ctx,
+					   &password,
+					   r2.out.info->password_properties,
+					   r2.out.info->min_password_length);
+		(*r->out.rep)->ctr2.status = res;
+	break;
+	case NetValidatePasswordReset:
+		password = data_blob_const(r->in.req->req3.password.string,
+					   r->in.req->req3.password.length);
+		res = samdb_check_password(mem_ctx,
+					   dce_call->conn->dce_ctx->lp_ctx,
+					   &password,
+					   r2.out.info->password_properties,
+					   r2.out.info->min_password_length);
+		(*r->out.rep)->ctr3.status = res;
+	break;
+	}
+
 	return NT_STATUS_OK;
 }
 
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 41de9d8..5462e3a 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -6765,6 +6765,8 @@ static bool test_samr_ValidatePassword(struct dcerpc_pipe *p, struct torture_con
 	const char *passwords[] = { "penguin", "p at ssw0rd", "p at ssw0rd123$", NULL };
 	int i;
 
+	torture_comment(tctx, "testing samr_ValidatePassword\n");
+
 	ZERO_STRUCT(r);
 	r.in.level = NetValidatePasswordReset;
 	r.in.req = &req;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list