diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 2eb09d1..1998646 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -240,20 +240,50 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, return (True); } -static int expect(int master, char *issue, char *expected) +static int expect(int master, const char *issue, const char *expected, + const char *oldpass, const char *newpass) { char buffer[1024]; int attempts, timeout, nread; size_t len; bool match = False; + const char *newissue; + + /* + * 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 */ + if (!newissue) { + DEBUG(1,("expect: talloc fail\n")); + return false; + } for (attempts = 0; attempts < 2; attempts++) { NTSTATUS status; - if (!strequal(issue, ".")) { + if (!strequal(newissue, ".")) { if (lp_passwd_chat_debug()) - DEBUG(100, ("expect: sending [%s]\n", issue)); + DEBUG(100, ("expect: sending [%s]\n", newissue)); - if ((len = sys_write(master, issue, strlen(issue))) != strlen(issue)) { + if ((len = sys_write(master, newissue, strlen(newissue))) != strlen(newissue)) { DEBUG(2,("expect: (short) write returned %d\n", (int)len )); return False; @@ -322,7 +352,8 @@ static void pwd_sub(char *buf) all_string_sub(buf, "\\t", "\t", 0); } -static int talktochild(int master, const char *seq) +static int talktochild(int master, const char *seq, + const char *oldpass, const char *newpass) { TALLOC_CTX *frame = talloc_stackframe(); int count = 0; @@ -339,7 +370,7 @@ static int talktochild(int master, const char *seq) pwd_sub(expected); count++; - if (!expect(master, issue, expected)) { + if (!expect(master, issue, expected, oldpass, newpass)) { DEBUG(3, ("Response %d incorrect\n", count)); TALLOC_FREE(frame); return false; @@ -362,7 +393,7 @@ static int talktochild(int master, const char *seq) TALLOC_FREE(frame); return false; } - if (!expect(master, issue, expected)) { + if (!expect(master, issue, expected, oldpass, newpass)) { TALLOC_FREE(frame); return False; } @@ -372,7 +403,8 @@ static int talktochild(int master, const char *seq) } static bool chat_with_program(char *passwordprogram, const struct passwd *pass, - char *chatsequence, bool as_root) + char *chatsequence, bool as_root, + const char *oldpass, const char *newpass) { char *slavedev = NULL; int master; @@ -411,7 +443,7 @@ static bool chat_with_program(char *passwordprogram, const struct passwd *pass, /* Don't need this anymore in parent. */ SAFE_FREE(slavedev); - if ((chstat = talktochild(master, chatsequence)) == False) { + if ((chstat = talktochild(master, chatsequence, oldpass, newpass)) == False) { DEBUG(3, ("chat_with_program: Child failed to change password: %s\n", pass->pw_name)); kill(pid, SIGKILL); /* be sure to end this process */ } @@ -606,21 +638,12 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); if (!chatsequence) { return false; } - chatsequence = talloc_all_string_sub(ctx, - chatsequence, - "%o", - oldpass); - if (!chatsequence) { - return false; - } - chatsequence = talloc_all_string_sub(ctx, - chatsequence, - "%n", - newpass); return chat_with_program(passwordprogram, pass, chatsequence, - as_root); + as_root, + oldpass, + newpass); } #else /* ALLOW_CHANGE_PASSWORD */