diff -ruN samba-3.5.3.a/source3/smbd/chgpasswd.c samba-3.5.3.b/source3/smbd/chgpasswd.c --- samba-3.5.3.a/source3/smbd/chgpasswd.c 2010-06-16 16:38:29.000000000 +0200 +++ samba-3.5.3.b/source3/smbd/chgpasswd.c 2010-06-17 10:45:16.000000000 +0200 @@ -240,6 +240,59 @@ return (True); } +static char *expand_pass_patterns(TALLOC_CTX *ctx, const char *patstr, + const char *oldpass, const char *newpass) +{ + int i; + ssize_t chat_len, op_len, np_len, pat_len, insert_len, ld; + char *s,*p,*chatstr; + const char *insert; + + chat_len = (ssize_t)strlen(patstr); + op_len = (ssize_t)strlen(oldpass); + np_len = (ssize_t)strlen(newpass); + pat_len = 2; + + chatstr = talloc_strdup(ctx, patstr); + if (chatstr == NULL) { + DEBUG(0, ("expand_pass_patterns: talloc_strdup failed\n")); + return NULL; + } + + for (i = chat_len-1; i>=0; i--) { + p = chatstr+i; + /* All patterns start with '%' */ + if (*p != '%') { + continue; + } + if (p == (s = strstr_m(p, "%n"))) { + ld = np_len - pat_len; + insert = newpass; + insert_len = np_len; + } else if (p == (s = strstr_m(p, "%o"))) { + ld = op_len - pat_len; + insert = oldpass; + insert_len = op_len; + } else { + continue; + } + + if (ld > 0) { + chatstr = TALLOC_REALLOC(ctx, chatstr, chat_len + ld + 1); + if (!chatstr) { + DEBUG(0, ("expand_pass_patterns: out " + "of memory!\n")); + return (NULL); + } + } + if (insert_len != 2) { + memmove(p+insert_len,p+2,strlen(p+2)+1); + } + memcpy(p, insert, insert_len); + } + return (chatstr); +} + static int expect(int master, const char *issue, const char *expected, const char *oldpass, const char *newpass) { @@ -253,25 +306,7 @@ * We know we're safe allowing "unsafe" characters here * as we know there are no embedded control characters. */ - newissue = talloc_string_sub2(talloc_tos(), - issue, - "%o", - oldpass, - false, /* remove_unsafe_characters */ - false, /* replace_once */ - true); /* allow_trailing_dollar */ - if (!newissue) { - DEBUG(1,("expect: talloc fail\n")); - return false; - } - - newissue = talloc_string_sub2(talloc_tos(), - newissue, - "%n", - newpass, - false, /* remove_unsafe_characters */ - false, /* replace_once */ - true); /* allow_trailing_dollar */ + newissue = expand_pass_patterns(talloc_tos(), issue, oldpass, newpass); if (!newissue) { DEBUG(1,("expect: talloc fail\n")); return false;