Fix errrors in new password handling code found by RPC-SAMR.
authorAndrew Bartlett <abartlet@samba.org>
Fri, 17 Oct 2008 01:41:02 +0000 (12:41 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 17 Oct 2008 01:41:02 +0000 (12:41 +1100)
I'm very glad we have such a comprehensive testsuite for the SAMR
password change process, as it makes this a much easier task to get
right.

Andrew Bartlett

source4/dsdb/common/util.c
source4/rpc_server/samr/samr_password.c

index 0a87c5ffe12f946d5b609ad907dc7331cf5df605..6a6f370943e241421e416faed8ac43f816b67540 100644 (file)
@@ -1644,7 +1644,7 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
                char *new_pass;
                
                /* check the various password restrictions */
-               if (restrictions && minPwdLength > utf16_len_n(new_password->data, (new_password->length / 2))) {
+               if (restrictions && minPwdLength > utf16_len_n(new_password->data, new_password->length) / 2) {
                        if (reject_reason) {
                                *reject_reason = SAMR_REJECT_TOO_SHORT;
                        }
index 336720ecc768004b85a972a9ba238814fb955a1b..859fd03801197b9e6e5c315e286bba0b00523f99 100644 (file)
@@ -184,7 +184,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
                                     struct samr_OemChangePasswordUser2 *r)
 {
        NTSTATUS status;
-       DATA_BLOB new_password;
+       DATA_BLOB new_password, new_unicode_password;
        char *new_pass;
        struct samr_CryptPassword *pwbuf = r->in.password;
        struct ldb_context *sam_ctx;
@@ -196,6 +196,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
        DATA_BLOB lm_pwd_blob;
        uint8_t new_lm_hash[16];
        struct samr_Password lm_verifier;
+       ssize_t unicode_pw_len;
 
        if (pwbuf == NULL) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -260,6 +261,18 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
                return NT_STATUS_WRONG_PASSWORD;
        }
 
+       unicode_pw_len = convert_string_talloc(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), 
+                                              CH_DOS, CH_UTF16, 
+                                              (const char *)new_password.data, 
+                                              new_password.length,
+                                              (void **)&new_unicode_password.data);
+       if (unicode_pw_len == -1) {
+               DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
+               ldb_transaction_cancel(sam_ctx);
+               return NT_STATUS_WRONG_PASSWORD;
+       }
+       new_unicode_password.length = unicode_pw_len;
+
        E_deshash(new_pass, new_lm_hash);
        E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
        if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
@@ -283,7 +296,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
         * due to password policies */
        status = samdb_set_password(sam_ctx, mem_ctx,
                                    user_dn, NULL, 
-                                   mod, &new_password, 
+                                   mod, &new_unicode_password, 
                                    NULL, NULL,
                                    true, /* this is a user password change */
                                    NULL,