CVE-2019-14833 dsdb: send full password to check password script
[amitay/samba.git] / source4 / dsdb / common / util.c
index 817fce6e17f037ed638203d9f12c06aacc795932..bad2ee7a494c60087928baa640380ba7f410f87d 100644 (file)
@@ -2041,21 +2041,36 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
                                                const uint32_t pwdProperties,
                                                const uint32_t minPwdLength)
 {
-       const char *utf8_pw = (const char *)utf8_blob->data;
-       size_t utf8_len = strlen_m(utf8_pw);
        char *password_script = NULL;
+       const char *utf8_pw = (const char *)utf8_blob->data;
+
+       /*
+        * This looks strange because it is.
+        *
+        * The check for the number of characters in the password
+        * should clearly not be against the byte length, or else a
+        * single UTF8 character would count for more than one.
+        *
+        * We have chosen to use the number of 16-bit units that the
+        * password encodes to as the measure of length.  This is not
+        * the same as the number of codepoints, if a password
+        * contains a character beyond the Basic Multilingual Plane
+        * (above 65535) it will count for more than one "character".
+        */
+
+       size_t password_characters_roughly = strlen_m(utf8_pw);
 
        /* checks if the "minPwdLength" property is satisfied */
-       if (minPwdLength > utf8_len) {
+       if (minPwdLength > password_characters_roughly) {
                return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
        }
 
-       /* checks the password complexity */
+       /* We might not be asked to check the password complexity */
        if (!(pwdProperties & DOMAIN_PASSWORD_COMPLEX)) {
                return SAMR_VALIDATION_STATUS_SUCCESS;
        }
 
-       if (utf8_len == 0) {
+       if (password_characters_roughly == 0) {
                return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
        }
 
@@ -2063,6 +2078,7 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
        if (password_script != NULL && *password_script != '\0') {
                int check_ret = 0;
                int error = 0;
+               ssize_t nwritten = 0;
                struct tevent_context *event_ctx = NULL;
                struct tevent_req *req = NULL;
                int cps_stdin = -1;
@@ -2125,7 +2141,9 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
 
                cps_stdin = samba_runcmd_export_stdin(req);
 
-               if (write(cps_stdin, utf8_pw, utf8_len) != utf8_len) {
+               nwritten = write(cps_stdin, utf8_blob->data,
+                                utf8_blob->length);
+               if (nwritten != utf8_blob->length) {
                        close(cps_stdin);
                        TALLOC_FREE(password_script);
                        TALLOC_FREE(event_ctx);