diff options
-rw-r--r-- | source3/auth/pampass.c | 4 | ||||
-rw-r--r-- | source3/lib/util.c | 120 | ||||
-rw-r--r-- | source3/passdb/pampass.c | 4 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 48 |
4 files changed, 152 insertions, 24 deletions
diff --git a/source3/auth/pampass.c b/source3/auth/pampass.c index 6d0dabcd9d..0c7c4f1291 100644 --- a/source3/auth/pampass.c +++ b/source3/auth/pampass.c @@ -306,7 +306,7 @@ static int smb_pam_passchange_conv(int num_msg, DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: trying to match |%s| to |%s|\n", t->prompt, current_prompt )); - if (wild_match(t->prompt, current_prompt) == 0) { + if (unix_wild_match(t->prompt, current_prompt) == 0) { fstrcpy(current_reply, t->reply); DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: We sent: %s\n", current_reply)); pwd_sub(current_reply, udp->PAM_username, udp->PAM_password, udp->PAM_newpassword); @@ -337,7 +337,7 @@ static int smb_pam_passchange_conv(int num_msg, DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: trying to match |%s| to |%s|\n", t->prompt, current_prompt )); - if (wild_match(t->prompt, current_prompt) == 0) { + if (unix_wild_match(t->prompt, current_prompt) == 0) { fstrcpy(current_reply, t->reply); DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: We sent: %s\n", current_reply)); pwd_sub(current_reply, udp->PAM_username, udp->PAM_password, udp->PAM_newpassword); diff --git a/source3/lib/util.c b/source3/lib/util.c index 7fbdb44b4a..ce39bb3b1d 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3,6 +3,7 @@ Version 1.9. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1756,19 +1757,130 @@ BOOL mask_match(char *string, char *pattern, BOOL is_case_sensitive) return ms_fnmatch(p2, s2, Protocol) == 0; } +/********************************************************* + Recursive routine that is called by unix_wild_match. +*********************************************************/ + +static BOOL unix_do_match(char *regexp, char *str) +{ + char *p; + + for( p = regexp; *p && *str; ) { + + switch(*p) { + case '?': + str++; + p++; + break; + + case '*': + + /* + * Look for a character matching + * the one after the '*'. + */ + p++; + if(!*p) + return True; /* Automatic match */ + while(*str) { + + while(*str && (*p != *str)) + str++; + + /* + * Patch from weidel@multichart.de. In the case of the regexp + * '*XX*' we want to ensure there are at least 2 'X' characters + * in the string after the '*' for a match to be made. + */ + + { + int matchcount=0; + + /* + * Eat all the characters that match, but count how many there were. + */ + + while(*str && (*p == *str)) { + str++; + matchcount++; + } + + /* + * Now check that if the regexp had n identical characters that + * matchcount had at least that many matches. + */ + + while ( *(p+1) && (*(p+1) == *p)) { + p++; + matchcount--; + } + + if ( matchcount <= 0 ) + return False; + } + + str--; /* We've eaten the match char after the '*' */ + + if(unix_do_match(p, str)) + return True; + + if(!*str) + return False; + else + str++; + } + return False; + + default: + if(*str != *p) + return False; + str++; + p++; + break; + } + } + + if(!*p && !*str) + return True; + + if (!*p && str[0] == '.' && str[1] == 0) + return(True); + + if (!*str && *p == '?') { + while (*p == '?') + p++; + return(!*p); + } + + if(!*str && (*p == '*' && p[1] == '\0')) + return True; + + return False; +} + /******************************************************************* - Simple case insensitive interface to ms_fnmatch. + Simple case insensitive interface to a UNIX wildcard matcher. *******************************************************************/ - -BOOL wild_match(char *string, char *pattern) + +BOOL unix_wild_match(char *pattern, char *string) { pstring p2, s2; + char *p; pstrcpy(p2, pattern); pstrcpy(s2, string); strlower(p2); strlower(s2); - return ms_fnmatch(p2, s2, Protocol) == 0; + + /* Remove any *? and ** from the pattern as they are meaningless */ + for(p = p2; *p; p++) + while( *p == '*' && (p[1] == '?' ||p[1] == '*')) + pstrcpy( &p[1], &p[2]); + + if (strequal(p2,"*")) + return True; + + return unix_do_match(p2, s2) == 0; } #ifdef __INSURE__ diff --git a/source3/passdb/pampass.c b/source3/passdb/pampass.c index 6d0dabcd9d..0c7c4f1291 100644 --- a/source3/passdb/pampass.c +++ b/source3/passdb/pampass.c @@ -306,7 +306,7 @@ static int smb_pam_passchange_conv(int num_msg, DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: trying to match |%s| to |%s|\n", t->prompt, current_prompt )); - if (wild_match(t->prompt, current_prompt) == 0) { + if (unix_wild_match(t->prompt, current_prompt) == 0) { fstrcpy(current_reply, t->reply); DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: We sent: %s\n", current_reply)); pwd_sub(current_reply, udp->PAM_username, udp->PAM_password, udp->PAM_newpassword); @@ -337,7 +337,7 @@ static int smb_pam_passchange_conv(int num_msg, DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: trying to match |%s| to |%s|\n", t->prompt, current_prompt )); - if (wild_match(t->prompt, current_prompt) == 0) { + if (unix_wild_match(t->prompt, current_prompt) == 0) { fstrcpy(current_reply, t->reply); DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: We sent: %s\n", current_reply)); pwd_sub(current_reply, udp->PAM_username, udp->PAM_password, udp->PAM_newpassword); diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fbcefd6128..d2ee2f46fa 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -199,7 +199,7 @@ static int dochild(int master, char *slavedev, char *name, } stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); stermios.c_lflag |= ICANON; - stermios.c_oflag &= ~(ONLCR); + stermios.c_oflag &= ~(ONLCR); if (tcsetattr(0, TCSANOW, &stermios) < 0) { DEBUG(3, ("could not set attributes of pty\n")); @@ -231,14 +231,15 @@ static int expect(int master, char *issue, char *expected) int attempts, timeout, nread, len; BOOL match = False; - for (attempts = 0; attempts < 2; attempts++) - { - if (!strequal(issue, ".")) - { + for (attempts = 0; attempts < 2; attempts++) { + if (!strequal(issue, ".")) { if (lp_passwd_chat_debug()) DEBUG(100, ("expect: sending [%s]\n", issue)); - write(master, issue, strlen(issue)); + if ((len = write(master, issue, strlen(issue))) != strlen(issue)) { + DEBUG(2,("expect: (short) write returned %d\n", len )); + return False; + } } if (strequal(expected, ".")) @@ -250,29 +251,35 @@ static int expect(int master, char *issue, char *expected) while ((len = read_with_timeout(master, buffer + nread, 1, sizeof(buffer) - nread - 1, - timeout)) > 0) - { + timeout)) > 0) { nread += len; buffer[nread] = 0; - if ((match = (wild_match(expected, buffer) == 0))) - timeout = 200; + { + /* Eat leading/trailing whitespace before match. */ + pstring str; + pstrcpy( str, buffer); + trim_string( str, " ", " "); + + if ((match = (unix_wild_match(expected, str) == 0))) + timeout = 200; + } } if (lp_passwd_chat_debug()) - DEBUG(100, ("expect: expected [%s] received [%s]\n", - expected, buffer)); + DEBUG(100, ("expect: expected [%s] received [%s] match %s\n", + expected, buffer, match ? "yes" : "no" )); if (match) break; - if (len < 0) - { + if (len < 0) { DEBUG(2, ("expect: %s\n", strerror(errno))); return False; } } + DEBUG(10,("expect: returning %s\n", match ? "True" : "False" )); return match; } @@ -519,15 +526,24 @@ BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root) pstrcpy(chatsequence, lp_passwd_chat()); if (!*chatsequence) { - DEBUG(2, ("Null chat sequence - no password changing\n")); + DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n")); return (False); } if (!*passwordprogram) { - DEBUG(2, ("Null password program - no password changing\n")); + DEBUG(2, ("chgpasswd: Null password program - no password changing\n")); return (False); } + if (as_root) { + /* The password program *must* contain the user name to work. Fail if not. */ + if (strstr(passwordprogram, "%u") == NULL) { + DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \ +the string %%u, and the given string %s does not.\n", passwordprogram )); + return False; + } + } + pstring_sub(passwordprogram, "%u", name); /* note that we do NOT substitute the %o and %n in the password program as this would open up a security hole where the user could use |