smbd/chgpasswd.c

ソースコードを見る。

関数

static NTSTATUS check_oem_password (const char *user, uchar password_encrypted_with_lm_hash[516], const uchar old_lm_hash_encrypted[16], uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], struct samu **hnd, char *new_passwd, int new_passwd_size)
static int findpty (char **slave)
static int dochild (int master, const char *slavedev, const struct passwd *pass, const char *passwordprogram, BOOL as_root)
static int expect (int master, char *issue, char *expected)
static void pwd_sub (char *buf)
static int talktochild (int master, const char *seq)
static BOOL chat_with_program (char *passwordprogram, const struct passwd *pass, char *chatsequence, BOOL as_root)
BOOL chgpasswd (const char *name, const struct passwd *pass, const char *oldpass, const char *newpass, BOOL as_root)
BOOL check_lanman_password (char *user, uchar *pass1, uchar *pass2, struct samu **hnd)
BOOL change_lanman_password (struct samu *sampass, uchar *pass2)
NTSTATUS pass_oem_change (char *user, uchar password_encrypted_with_lm_hash[516], const uchar old_lm_hash_encrypted[16], uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], uint32 *reject_reason)
static BOOL check_passwd_history (struct samu *sampass, const char *plaintext)
NTSTATUS change_oem_password (struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason)

変数

passdb_ops pdb_ops


関数

static NTSTATUS check_oem_password ( const char *  user,
uchar  password_encrypted_with_lm_hash[516],
const uchar  old_lm_hash_encrypted[16],
uchar  password_encrypted_with_nt_hash[516],
const uchar  old_nt_hash_encrypted[16],
struct samu **  hnd,
char *  new_passwd,
int  new_passwd_size 
) [static]

chgpasswd.c763 行で定義されています。

参照先 samu::acct_ctrlbecome_root()decode_pw_buffer()E_deshash()E_md4hash()E_old_pw_hash()nt_lm_owf_gen()samu::nt_pwpdb_get_acct_ctrl()pdb_get_lanman_passwd()pdb_get_nt_passwd()pdb_getsampwnam()SamOEMhash()samu_new()unbecome_root().

参照元 pass_oem_change().

00770 {
00771         static uchar null_pw[16];
00772         static uchar null_ntpw[16];
00773         struct samu *sampass = NULL;
00774         uint8 *password_encrypted;
00775         const uint8 *encryption_key;
00776         const uint8 *lanman_pw, *nt_pw;
00777         uint32 acct_ctrl;
00778         uint32 new_pw_len;
00779         uchar new_nt_hash[16];
00780         uchar new_lm_hash[16];
00781         uchar verifier[16];
00782         char no_pw[2];
00783         BOOL ret;
00784 
00785         BOOL nt_pass_set = (password_encrypted_with_nt_hash && old_nt_hash_encrypted);
00786         BOOL lm_pass_set = (password_encrypted_with_lm_hash && old_lm_hash_encrypted);
00787 
00788         *hnd = NULL;
00789 
00790         if ( !(sampass = samu_new( NULL )) ) {
00791                 return NT_STATUS_NO_MEMORY;
00792         }
00793 
00794         become_root();
00795         ret = pdb_getsampwnam(sampass, user);
00796         unbecome_root();
00797 
00798         if (ret == False) {
00799                 DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n"));
00800                 TALLOC_FREE(sampass);
00801                 return NT_STATUS_NO_SUCH_USER; 
00802         }
00803 
00804         acct_ctrl = pdb_get_acct_ctrl(sampass);
00805         
00806         if (acct_ctrl & ACB_DISABLED) {
00807                 DEBUG(2,("check_lanman_password: account %s disabled.\n", user));
00808                 TALLOC_FREE(sampass);
00809                 return NT_STATUS_ACCOUNT_DISABLED;
00810         }
00811 
00812         if ((acct_ctrl & ACB_PWNOTREQ) && lp_null_passwords()) {
00813                 /* construct a null password (in case one is needed */
00814                 no_pw[0] = 0;
00815                 no_pw[1] = 0;
00816                 nt_lm_owf_gen(no_pw, null_ntpw, null_pw);
00817                 lanman_pw = null_pw;
00818                 nt_pw = null_pw;
00819 
00820         } else {
00821                 /* save pointers to passwords so we don't have to keep looking them up */
00822                 if (lp_lanman_auth()) {
00823                         lanman_pw = pdb_get_lanman_passwd(sampass);
00824                 } else {
00825                         lanman_pw = NULL;
00826                 }
00827                 nt_pw = pdb_get_nt_passwd(sampass);
00828         }
00829 
00830         if (nt_pw && nt_pass_set) {
00831                 /* IDEAL Case: passwords are in unicode, and we can
00832                  * read use the password encrypted with the NT hash 
00833                  */
00834                 password_encrypted = password_encrypted_with_nt_hash;
00835                 encryption_key = nt_pw;
00836         } else if (lanman_pw && lm_pass_set) {
00837                 /* password may still be in unicode, but use LM hash version */
00838                 password_encrypted = password_encrypted_with_lm_hash;
00839                 encryption_key = lanman_pw;
00840         } else if (nt_pass_set) {
00841                 DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n", 
00842                           user));
00843                 TALLOC_FREE(sampass);
00844                 return NT_STATUS_WRONG_PASSWORD;        
00845         } else if (lm_pass_set) {
00846                 if (lp_lanman_auth()) {
00847                         DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n", 
00848                                   user));
00849                 } else {
00850                         DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n", 
00851                                   user));
00852                 }
00853                 TALLOC_FREE(sampass);
00854                 return NT_STATUS_WRONG_PASSWORD;
00855         } else {
00856                 DEBUG(1, ("password change requested for user %s, but no password supplied!\n", 
00857                           user));
00858                 TALLOC_FREE(sampass);
00859                 return NT_STATUS_WRONG_PASSWORD;
00860         }
00861 
00862         /* 
00863          * Decrypt the password with the key 
00864          */
00865         SamOEMhash( password_encrypted, encryption_key, 516);
00866 
00867         if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len, 
00868                                nt_pass_set ? STR_UNICODE : STR_ASCII)) {
00869                 TALLOC_FREE(sampass);
00870                 return NT_STATUS_WRONG_PASSWORD;
00871         }
00872 
00873         /*
00874          * To ensure we got the correct new password, hash it and
00875          * use it as a key to test the passed old password.
00876          */
00877 
00878         if (nt_pass_set) {
00879                 /* NT passwords, verify the NT hash. */
00880                 
00881                 /* Calculate the MD4 hash (NT compatible) of the password */
00882                 memset(new_nt_hash, '\0', 16);
00883                 E_md4hash(new_passwd, new_nt_hash);
00884 
00885                 if (nt_pw) {
00886                         /*
00887                          * check the NT verifier
00888                          */
00889                         E_old_pw_hash(new_nt_hash, nt_pw, verifier);
00890                         if (memcmp(verifier, old_nt_hash_encrypted, 16)) {
00891                                 DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
00892                                 TALLOC_FREE(sampass);
00893                                 return NT_STATUS_WRONG_PASSWORD;
00894                         }
00895                         
00896                         /* We could check the LM password here, but there is
00897                          * little point, we already know the password is
00898                          * correct, and the LM password might not even be
00899                          * present. */
00900 
00901                         /* Further, LM hash generation algorithms
00902                          * differ with charset, so we could
00903                          * incorrectly fail a perfectly valid password
00904                          * change */
00905 #ifdef DEBUG_PASSWORD
00906                         DEBUG(100,
00907                               ("check_oem_password: password %s ok\n", new_passwd));
00908 #endif
00909                         *hnd = sampass;
00910                         return NT_STATUS_OK;
00911                 }
00912                 
00913                 if (lanman_pw) {
00914                         /*
00915                          * check the lm verifier
00916                          */
00917                         E_old_pw_hash(new_nt_hash, lanman_pw, verifier);
00918                         if (memcmp(verifier, old_lm_hash_encrypted, 16)) {
00919                                 DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
00920                                 TALLOC_FREE(sampass);
00921                                 return NT_STATUS_WRONG_PASSWORD;
00922                         }
00923 #ifdef DEBUG_PASSWORD
00924                         DEBUG(100,
00925                               ("check_oem_password: password %s ok\n", new_passwd));
00926 #endif
00927                         *hnd = sampass;
00928                         return NT_STATUS_OK;
00929                 }
00930         }
00931 
00932         if (lanman_pw && lm_pass_set) {
00933 
00934                 E_deshash(new_passwd, new_lm_hash);
00935 
00936                 /*
00937                  * check the lm verifier
00938                  */
00939                 E_old_pw_hash(new_lm_hash, lanman_pw, verifier);
00940                 if (memcmp(verifier, old_lm_hash_encrypted, 16)) {
00941                         DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
00942                         TALLOC_FREE(sampass);
00943                         return NT_STATUS_WRONG_PASSWORD;
00944                 }
00945                 
00946 #ifdef DEBUG_PASSWORD
00947                 DEBUG(100,
00948                       ("check_oem_password: password %s ok\n", new_passwd));
00949 #endif
00950                 *hnd = sampass;
00951                 return NT_STATUS_OK;
00952         }
00953 
00954         /* should not be reached */
00955         TALLOC_FREE(sampass);
00956         return NT_STATUS_WRONG_PASSWORD;
00957 }

static int findpty ( char **  slave  )  [static]

chgpasswd.c63 行で定義されています。

参照先 linereaddirname()sys_closedir()sys_open()sys_opendir().

参照元 chat_with_program().

00064 {
00065         int master;
00066         static fstring line;
00067         SMB_STRUCT_DIR *dirp;
00068         const char *dpname;
00069 
00070 #if defined(HAVE_GRANTPT)
00071         /* Try to open /dev/ptmx. If that fails, fall through to old method. */
00072         if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0)
00073         {
00074                 grantpt(master);
00075                 unlockpt(master);
00076                 *slave = (char *)ptsname(master);
00077                 if (*slave == NULL)
00078                 {
00079                         DEBUG(0,
00080                               ("findpty: Unable to create master/slave pty pair.\n"));
00081                         /* Stop fd leak on error. */
00082                         close(master);
00083                         return -1;
00084                 }
00085                 else
00086                 {
00087                         DEBUG(10,
00088                               ("findpty: Allocated slave pty %s\n", *slave));
00089                         return (master);
00090                 }
00091         }
00092 #endif /* HAVE_GRANTPT */
00093 
00094         fstrcpy(line, "/dev/ptyXX");
00095 
00096         dirp = sys_opendir("/dev");
00097         if (!dirp)
00098                 return (-1);
00099         while ((dpname = readdirname(dirp)) != NULL)
00100         {
00101                 if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5)
00102                 {
00103                         DEBUG(3,
00104                               ("pty: try to open %s, line was %s\n", dpname,
00105                                line));
00106                         line[8] = dpname[3];
00107                         line[9] = dpname[4];
00108                         if ((master = sys_open(line, O_RDWR, 0)) >= 0)
00109                         {
00110                                 DEBUG(3, ("pty: opened %s\n", line));
00111                                 line[5] = 't';
00112                                 *slave = line;
00113                                 sys_closedir(dirp);
00114                                 return (master);
00115                         }
00116                 }
00117         }
00118         sys_closedir(dirp);
00119         return (-1);
00120 }

static int dochild ( int  master,
const char *  slavedev,
const struct passwd *  pass,
const char *  passwordprogram,
BOOL  as_root 
) [static]

chgpasswd.c122 行で定義されています。

参照先 become_user_permanently()gain_root_privilege()sys_dup2()sys_open()tcgetattr()tcsetattr().

参照元 chat_with_program().

00124 {
00125         int slave;
00126         struct termios stermios;
00127         gid_t gid;
00128         uid_t uid;
00129         char * const eptrs[1] = { NULL };
00130 
00131         if (pass == NULL)
00132         {
00133                 DEBUG(0,
00134                       ("dochild: user doesn't exist in the UNIX password database.\n"));
00135                 return False;
00136         }
00137 
00138         gid = pass->pw_gid;
00139         uid = pass->pw_uid;
00140 
00141         gain_root_privilege();
00142 
00143         /* Start new session - gets rid of controlling terminal. */
00144         if (setsid() < 0)
00145         {
00146                 DEBUG(3,
00147                       ("Weirdness, couldn't let go of controlling terminal\n"));
00148                 return (False);
00149         }
00150 
00151         /* Open slave pty and acquire as new controlling terminal. */
00152         if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0)
00153         {
00154                 DEBUG(3, ("More weirdness, could not open %s\n", slavedev));
00155                 return (False);
00156         }
00157 #if defined(TIOCSCTTY) && !defined(SUNOS5)
00158         /*
00159          * On patched Solaris 10 TIOCSCTTY is defined but seems not to work,
00160          * see the discussion under
00161          * https://bugzilla.samba.org/show_bug.cgi?id=5366.
00162          */
00163         if (ioctl(slave, TIOCSCTTY, 0) < 0)
00164         {
00165                 DEBUG(3, ("Error in ioctl call for slave pty\n"));
00166                 /* return(False); */
00167         }
00168 #elif defined(I_PUSH) && defined(I_FIND)
00169         if (ioctl(slave, I_FIND, "ptem") == 0) {
00170                 ioctl(slave, I_PUSH, "ptem");
00171         }
00172         if (ioctl(slave, I_FIND, "ldterm") == 0) {
00173                 ioctl(slave, I_PUSH, "ldterm");
00174         }
00175 #endif
00176 
00177         /* Close master. */
00178         close(master);
00179 
00180         /* Make slave stdin/out/err of child. */
00181 
00182         if (sys_dup2(slave, STDIN_FILENO) != STDIN_FILENO)
00183         {
00184                 DEBUG(3, ("Could not re-direct stdin\n"));
00185                 return (False);
00186         }
00187         if (sys_dup2(slave, STDOUT_FILENO) != STDOUT_FILENO)
00188         {
00189                 DEBUG(3, ("Could not re-direct stdout\n"));
00190                 return (False);
00191         }
00192         if (sys_dup2(slave, STDERR_FILENO) != STDERR_FILENO)
00193         {
00194                 DEBUG(3, ("Could not re-direct stderr\n"));
00195                 return (False);
00196         }
00197         if (slave > 2)
00198                 close(slave);
00199 
00200         /* Set proper terminal attributes - no echo, canonical input processing,
00201            no map NL to CR/NL on output. */
00202 
00203         if (tcgetattr(0, &stermios) < 0)
00204         {
00205                 DEBUG(3,
00206                       ("could not read default terminal attributes on pty\n"));
00207                 return (False);
00208         }
00209         stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
00210         stermios.c_lflag |= ICANON;
00211 #ifdef ONLCR
00212         stermios.c_oflag &= ~(ONLCR);
00213 #endif
00214         if (tcsetattr(0, TCSANOW, &stermios) < 0)
00215         {
00216                 DEBUG(3, ("could not set attributes of pty\n"));
00217                 return (False);
00218         }
00219 
00220         /* make us completely into the right uid */
00221         if (!as_root)
00222         {
00223                 become_user_permanently(uid, gid);
00224         }
00225 
00226         DEBUG(10,
00227               ("Invoking '%s' as password change program.\n",
00228                passwordprogram));
00229 
00230         /* execl() password-change application */
00231         if (execle("/bin/sh", "sh", "-c", passwordprogram, NULL, eptrs) < 0)
00232         {
00233                 DEBUG(3, ("Bad status returned from %s\n", passwordprogram));
00234                 return (False);
00235         }
00236         return (True);
00237 }

static int expect ( int  master,
char *  issue,
char *  expected 
) [static]

chgpasswd.c239 行で定義されています。

参照先 errnolenread_socket_with_timeout()strequal()strerror()sys_write()timeouttrim_char()unix_wild_match().

参照元 _cleanup_failures()talktochild().

00240 {
00241         pstring buffer;
00242         int attempts, timeout, nread, len;
00243         BOOL match = False;
00244 
00245         for (attempts = 0; attempts < 2; attempts++) {
00246                 if (!strequal(issue, ".")) {
00247                         if (lp_passwd_chat_debug())
00248                                 DEBUG(100, ("expect: sending [%s]\n", issue));
00249 
00250                         if ((len = sys_write(master, issue, strlen(issue))) != strlen(issue)) {
00251                                 DEBUG(2,("expect: (short) write returned %d\n", len ));
00252                                 return False;
00253                         }
00254                 }
00255 
00256                 if (strequal(expected, "."))
00257                         return True;
00258 
00259                 /* Initial timeout. */
00260                 timeout = lp_passwd_chat_timeout() * 1000;
00261                 nread = 0;
00262                 buffer[nread] = 0;
00263 
00264                 while ((len = read_socket_with_timeout(master, buffer + nread, 1,
00265                                                        sizeof(buffer) - nread - 1,
00266                                                        timeout)) > 0) {
00267                         nread += len;
00268                         buffer[nread] = 0;
00269 
00270                         {
00271                                 /* Eat leading/trailing whitespace before match. */
00272                                 pstring str;
00273                                 pstrcpy( str, buffer);
00274                                 trim_char( str, ' ', ' ');
00275 
00276                                 if ((match = unix_wild_match(expected, str)) == True) {
00277                                         /* Now data has started to return, lower timeout. */
00278                                         timeout = lp_passwd_chat_timeout() * 100;
00279                                 }
00280                         }
00281                 }
00282 
00283                 if (lp_passwd_chat_debug())
00284                         DEBUG(100, ("expect: expected [%s] received [%s] match %s\n",
00285                                     expected, buffer, match ? "yes" : "no" ));
00286 
00287                 if (match)
00288                         break;
00289 
00290                 if (len < 0) {
00291                         DEBUG(2, ("expect: %s\n", strerror(errno)));
00292                         return False;
00293                 }
00294         }
00295 
00296         DEBUG(10,("expect: returning %s\n", match ? "True" : "False" ));
00297         return match;
00298 }

static void pwd_sub ( char *  buf  )  [static]

chgpasswd.c300 行で定義されています。

参照先 all_string_sub().

00301 {
00302         all_string_sub(buf, "\\n", "\n", 0);
00303         all_string_sub(buf, "\\r", "\r", 0);
00304         all_string_sub(buf, "\\s", " ", 0);
00305         all_string_sub(buf, "\\t", "\t", 0);
00306 }

static int talktochild ( int  master,
const char *  seq 
) [static]

chgpasswd.c308 行で定義されています。

参照先 expect()next_token()pwd_sub()strequal().

参照元 chat_with_program().

00309 {
00310         int count = 0;
00311         fstring issue, expected;
00312 
00313         fstrcpy(issue, ".");
00314 
00315         while (next_token(&seq, expected, NULL, sizeof(expected)))
00316         {
00317                 pwd_sub(expected);
00318                 count++;
00319 
00320                 if (!expect(master, issue, expected))
00321                 {
00322                         DEBUG(3, ("Response %d incorrect\n", count));
00323                         return False;
00324                 }
00325 
00326                 if (!next_token(&seq, issue, NULL, sizeof(issue)))
00327                         fstrcpy(issue, ".");
00328 
00329                 pwd_sub(issue);
00330         }
00331         if (!strequal(issue, ".")) {
00332                 /* we have one final issue to send */
00333                 fstrcpy(expected, ".");
00334                 if (!expect(master, issue, expected))
00335                         return False;
00336         }
00337 
00338         return (count > 0);
00339 }

static BOOL chat_with_program ( char *  passwordprogram,
const struct passwd *  pass,
char *  chatsequence,
BOOL  as_root 
) [static]

chgpasswd.c341 行で定義されています。

参照先 become_root()CatchChild()CatchChildLeaveStatus()DMAPI_ACCESS_CAPABILITYdochild()drop_effective_capability()errnofindpty()KERNEL_OPLOCK_CAPABILITYsys_fork()sys_waitpid()talktochild()unbecome_root().

参照元 chgpasswd().

00343 {
00344         char *slavedev;
00345         int master;
00346         pid_t pid, wpid;
00347         int wstat;
00348         BOOL chstat = False;
00349 
00350         if (pass == NULL) {
00351                 DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n"));
00352                 return False;
00353         }
00354 
00355         /* allocate a pseudo-terminal device */
00356         if ((master = findpty(&slavedev)) < 0) {
00357                 DEBUG(3, ("chat_with_program: Cannot Allocate pty for password change: %s\n", pass->pw_name));
00358                 return (False);
00359         }
00360 
00361         /*
00362          * We need to temporarily stop CatchChild from eating
00363          * SIGCLD signals as it also eats the exit status code. JRA.
00364          */
00365 
00366         CatchChildLeaveStatus();
00367 
00368         if ((pid = sys_fork()) < 0) {
00369                 DEBUG(3, ("chat_with_program: Cannot fork() child for password change: %s\n", pass->pw_name));
00370                 close(master);
00371                 CatchChild();
00372                 return (False);
00373         }
00374 
00375         /* we now have a pty */
00376         if (pid > 0) {                  /* This is the parent process */
00377                 if ((chstat = talktochild(master, chatsequence)) == False) {
00378                         DEBUG(3, ("chat_with_program: Child failed to change password: %s\n", pass->pw_name));
00379                         kill(pid, SIGKILL);     /* be sure to end this process */
00380                 }
00381 
00382                 while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
00383                         if (errno == EINTR) {
00384                                 errno = 0;
00385                                 continue;
00386                         }
00387                         break;
00388                 }
00389 
00390                 if (wpid < 0) {
00391                         DEBUG(3, ("chat_with_program: The process is no longer waiting!\n\n"));
00392                         close(master);
00393                         CatchChild();
00394                         return (False);
00395                 }
00396 
00397                 /*
00398                  * Go back to ignoring children.
00399                  */
00400                 CatchChild();
00401 
00402                 close(master);
00403 
00404                 if (pid != wpid) {
00405                         DEBUG(3, ("chat_with_program: We were waiting for the wrong process ID\n"));
00406                         return (False);
00407                 }
00408                 if (WIFEXITED(wstat) && (WEXITSTATUS(wstat) != 0)) {
00409                         DEBUG(3, ("chat_with_program: The process exited with status %d \
00410 while we were waiting\n", WEXITSTATUS(wstat)));
00411                         return (False);
00412                 }
00413 #if defined(WIFSIGNALLED) && defined(WTERMSIG)
00414                 else if (WIFSIGNALLED(wstat)) {
00415                         DEBUG(3, ("chat_with_program: The process was killed by signal %d \
00416 while we were waiting\n", WTERMSIG(wstat)));
00417                         return (False);
00418                 }
00419 #endif
00420         } else {
00421                 /* CHILD */
00422 
00423                 /*
00424                  * Lose any elevated privileges.
00425                  */
00426                 drop_effective_capability(KERNEL_OPLOCK_CAPABILITY);
00427                 drop_effective_capability(DMAPI_ACCESS_CAPABILITY);
00428 
00429                 /* make sure it doesn't freeze */
00430                 alarm(20);
00431 
00432                 if (as_root)
00433                         become_root();
00434 
00435                 DEBUG(3, ("chat_with_program: Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name,
00436                        (int)getuid(), (int)getgid(), BOOLSTR(as_root) ));
00437                 chstat = dochild(master, slavedev, pass, passwordprogram, as_root);
00438 
00439                 if (as_root)
00440                         unbecome_root();
00441 
00442                 /*
00443                  * The child should never return from dochild() ....
00444                  */
00445 
00446                 DEBUG(0, ("chat_with_program: Error: dochild() returned %d\n", chstat));
00447                 exit(1);
00448         }
00449 
00450         if (chstat)
00451                 DEBUG(3, ("chat_with_program: Password change %ssuccessful for user %s\n",
00452                        (chstat ? "" : "un"), pass->pw_name));
00453         return (chstat);
00454 }

BOOL chgpasswd ( const char *  name,
const struct passwd *  pass,
const char *  oldpass,
const char *  newpass,
BOOL  as_root 
)

chgpasswd.c456 行で定義されています。

参照先 all_string_sub()become_root()chat_with_program()lenpstring_sub()smb_pam_passchange()strstr_m()unbecome_root().

参照元 change_oem_password()set_user_info_23()set_user_info_pw().

00458 {
00459         pstring passwordprogram;
00460         pstring chatsequence;
00461         size_t i;
00462         size_t len;
00463 
00464         if (!oldpass) {
00465                 oldpass = "";
00466         }
00467 
00468         DEBUG(3, ("chgpasswd: Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name));
00469 
00470 #ifdef DEBUG_PASSWORD
00471         DEBUG(100, ("chgpasswd: Passwords: old=%s new=%s\n", oldpass, newpass));
00472 #endif
00473 
00474         /* Take the passed information and test it for minimum criteria */
00475 
00476         /* Password is same as old password */
00477         if (strcmp(oldpass, newpass) == 0) {
00478                 /* don't allow same password */
00479                 DEBUG(2, ("chgpasswd: Password Change: %s, New password is same as old\n", name));      /* log the attempt */
00480                 return (False); /* inform the user */
00481         }
00482 
00483         /* 
00484          * Check the old and new passwords don't contain any control
00485          * characters.
00486          */
00487 
00488         len = strlen(oldpass);
00489         for (i = 0; i < len; i++) {
00490                 if (iscntrl((int)oldpass[i])) {
00491                         DEBUG(0, ("chgpasswd: oldpass contains control characters (disallowed).\n"));
00492                         return False;
00493                 }
00494         }
00495 
00496         len = strlen(newpass);
00497         for (i = 0; i < len; i++) {
00498                 if (iscntrl((int)newpass[i])) {
00499                         DEBUG(0, ("chgpasswd: newpass contains control characters (disallowed).\n"));
00500                         return False;
00501                 }
00502         }
00503         
00504 #ifdef WITH_PAM
00505         if (lp_pam_password_change()) {
00506                 BOOL ret;
00507 #ifdef HAVE_SETLOCALE
00508                 char *prevlocale = setlocale(LC_ALL, "C");
00509 #endif
00510 
00511                 if (as_root)
00512                         become_root();
00513 
00514                 if (pass) {
00515                         ret = smb_pam_passchange(pass->pw_name, oldpass, newpass);
00516                 } else {
00517                         ret = smb_pam_passchange(name, oldpass, newpass);
00518                 }
00519                         
00520                 if (as_root)
00521                         unbecome_root();
00522 
00523 #ifdef HAVE_SETLOCALE
00524                 setlocale(LC_ALL, prevlocale);
00525 #endif
00526 
00527                 return ret;
00528         }
00529 #endif
00530 
00531         /* A non-PAM password change just doen't make sense without a valid local user */
00532 
00533         if (pass == NULL) {
00534                 DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name));
00535                 return False;
00536         }
00537 
00538         pstrcpy(passwordprogram, lp_passwd_program());
00539         pstrcpy(chatsequence, lp_passwd_chat());
00540 
00541         if (!*chatsequence) {
00542                 DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n"));
00543                 return (False);
00544         }
00545 
00546         if (!*passwordprogram) {
00547                 DEBUG(2, ("chgpasswd: Null password program - no password changing\n"));
00548                 return (False);
00549         }
00550 
00551         if (as_root) {
00552                 /* The password program *must* contain the user name to work. Fail if not. */
00553                 if (strstr_m(passwordprogram, "%u") == NULL) {
00554                         DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \
00555 the string %%u, and the given string %s does not.\n", passwordprogram ));
00556                         return False;
00557                 }
00558         }
00559 
00560         pstring_sub(passwordprogram, "%u", name);
00561         /* note that we do NOT substitute the %o and %n in the password program
00562            as this would open up a security hole where the user could use
00563            a new password containing shell escape characters */
00564 
00565         pstring_sub(chatsequence, "%u", name);
00566         all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring));
00567         all_string_sub(chatsequence, "%n", newpass, sizeof(pstring));
00568         return (chat_with_program
00569                 (passwordprogram, pass, chatsequence, as_root));
00570 }

BOOL check_lanman_password ( char *  user,
uchar *  pass1,
uchar *  pass2,
struct samu **  hnd 
)

chgpasswd.c586 行で定義されています。

参照先 samu::acct_ctrlbecome_root()D_P16()pdb_get_acct_ctrl()pdb_get_lanman_passwd()pdb_getsampwnam()samu_new()unbecome_root().

参照元 api_SetUserPassword().

00588 {
00589         uchar unenc_new_pw[16];
00590         uchar unenc_old_pw[16];
00591         struct samu *sampass = NULL;
00592         uint32 acct_ctrl;
00593         const uint8 *lanman_pw;
00594         BOOL ret;
00595 
00596         if ( !(sampass = samu_new(NULL)) ) {
00597                 DEBUG(0, ("samu_new() failed!\n"));
00598                 return False;
00599         }
00600         
00601         become_root();
00602         ret = pdb_getsampwnam(sampass, user);
00603         unbecome_root();
00604 
00605         if (ret == False) {
00606                 DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n"));
00607                 TALLOC_FREE(sampass);
00608                 return False;
00609         }
00610         
00611         acct_ctrl = pdb_get_acct_ctrl     (sampass);
00612         lanman_pw = pdb_get_lanman_passwd (sampass);
00613 
00614         if (acct_ctrl & ACB_DISABLED) {
00615                 DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
00616                 TALLOC_FREE(sampass);
00617                 return False;
00618         }
00619 
00620         if (lanman_pw == NULL) {
00621                 if (acct_ctrl & ACB_PWNOTREQ) {
00622                         /* this saves the pointer for the caller */
00623                         *hnd = sampass;
00624                         return True;
00625                 } else {
00626                         DEBUG(0, ("check_lanman_password: no lanman password !\n"));
00627                         TALLOC_FREE(sampass);
00628                         return False;
00629                 }
00630         }
00631 
00632         /* Get the new lanman hash. */
00633         D_P16(lanman_pw, pass2, unenc_new_pw);
00634 
00635         /* Use this to get the old lanman hash. */
00636         D_P16(unenc_new_pw, pass1, unenc_old_pw);
00637 
00638         /* Check that the two old passwords match. */
00639         if (memcmp(lanman_pw, unenc_old_pw, 16)) {
00640                 DEBUG(0,("check_lanman_password: old password doesn't match.\n"));
00641                 TALLOC_FREE(sampass);
00642                 return False;
00643         }
00644 
00645         /* this saves the pointer for the caller */
00646         *hnd = sampass;
00647         return True;
00648 }

BOOL change_lanman_password ( struct samu sampass,
uchar *  pass2 
)

chgpasswd.c658 行で定義されています。

参照先 samu::acct_ctrlD_P16()E_P16()PDB_CHANGEDpdb_get_acct_ctrl()pdb_get_lanman_passwd()pdb_get_username()pdb_set_lanman_passwd()pdb_set_nt_passwd()pdb_set_pass_last_set_time()pdb_update_sam_account().

参照元 api_SetUserPassword().

00659 {
00660         static uchar null_pw[16];
00661         uchar unenc_new_pw[16];
00662         BOOL ret;
00663         uint32 acct_ctrl;
00664         const uint8 *pwd;
00665 
00666         if (sampass == NULL) {
00667                 DEBUG(0,("change_lanman_password: no smb password entry.\n"));
00668                 return False;
00669         }
00670         
00671         acct_ctrl = pdb_get_acct_ctrl(sampass);
00672         pwd = pdb_get_lanman_passwd(sampass);
00673 
00674         if (acct_ctrl & ACB_DISABLED) {
00675                 DEBUG(0,("change_lanman_password: account %s disabled.\n",
00676                        pdb_get_username(sampass)));
00677                 return False;
00678         }
00679 
00680         if (pwd == NULL) { 
00681                 if (acct_ctrl & ACB_PWNOTREQ) {
00682                         uchar no_pw[14];
00683                         memset(no_pw, '\0', 14);
00684                         E_P16(no_pw, null_pw);
00685 
00686                         /* Get the new lanman hash. */
00687                         D_P16(null_pw, pass2, unenc_new_pw);
00688                 } else {
00689                         DEBUG(0,("change_lanman_password: no lanman password !\n"));
00690                         return False;
00691                 }
00692         } else {
00693                 /* Get the new lanman hash. */
00694                 D_P16(pwd, pass2, unenc_new_pw);
00695         }
00696 
00697         if (!pdb_set_lanman_passwd(sampass, unenc_new_pw, PDB_CHANGED)) {
00698                 return False;
00699         }
00700 
00701         if (!pdb_set_nt_passwd    (sampass, NULL, PDB_CHANGED)) {
00702                 return False;   /* We lose the NT hash. Sorry. */
00703         }
00704 
00705         if (!pdb_set_pass_last_set_time  (sampass, time(NULL), PDB_CHANGED)) {
00706                 TALLOC_FREE(sampass);
00707                 /* Not quite sure what this one qualifies as, but this will do */
00708                 return False; 
00709         }
00710  
00711         /* Now flush the sam_passwd struct to persistent storage */
00712         ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
00713 
00714         return ret;
00715 }

NTSTATUS pass_oem_change ( char *  user,
uchar  password_encrypted_with_lm_hash[516],
const uchar  old_lm_hash_encrypted[16],
uchar  password_encrypted_with_nt_hash[516],
const uchar  old_nt_hash_encrypted[16],
uint32 *  reject_reason 
)

chgpasswd.c721 行で定義されています。

参照先 become_root()change_oem_password()check_oem_password()new_passwdunbecome_root().

参照元 _samr_chgpasswd_user()_samr_chgpasswd_user3()api_SamOEMChangePassword().

00727 {
00728         pstring new_passwd;
00729         struct samu *sampass = NULL;
00730         NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash, 
00731                                                 old_lm_hash_encrypted, 
00732                                                 password_encrypted_with_nt_hash, 
00733                                                 old_nt_hash_encrypted,
00734                                                 &sampass, new_passwd, sizeof(new_passwd));
00735         
00736         if (!NT_STATUS_IS_OK(nt_status))
00737                 return nt_status;
00738 
00739         /* We've already checked the old password here.... */
00740         become_root();
00741         nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason);
00742         unbecome_root();
00743 
00744         memset(new_passwd, 0, sizeof(new_passwd));
00745 
00746         TALLOC_FREE(sampass);
00747 
00748         return nt_status;
00749 }

static BOOL check_passwd_history ( struct samu sampass,
const char *  plaintext 
) [static]

chgpasswd.c965 行で定義されています。

参照先 current_saltdump_data()E_md4hash()E_md5hash()samu::nt_pwpdb_get_account_policy()pdb_get_nt_passwd()pdb_get_pw_history()pdb_get_username().

参照元 change_oem_password().

00966 {
00967         uchar new_nt_p16[NT_HASH_LEN];
00968         uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN];
00969         const uint8 *nt_pw;
00970         const uint8 *pwhistory;
00971         BOOL found = False;
00972         int i;
00973         uint32 pwHisLen, curr_pwHisLen;
00974 
00975         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen);
00976         if (pwHisLen == 0) {
00977                 return False;
00978         }
00979 
00980         pwhistory = pdb_get_pw_history(sampass, &curr_pwHisLen);
00981         if (!pwhistory || curr_pwHisLen == 0) {
00982                 return False;
00983         }
00984 
00985         /* Only examine the minimum of the current history len and
00986            the stored history len. Avoids race conditions. */
00987         pwHisLen = MIN(pwHisLen,curr_pwHisLen);
00988 
00989         nt_pw = pdb_get_nt_passwd(sampass);
00990 
00991         E_md4hash(plaintext, new_nt_p16);
00992 
00993         if (!memcmp(nt_pw, new_nt_p16, NT_HASH_LEN)) {
00994                 DEBUG(10,("check_passwd_history: proposed new password for user %s is the same as the current password !\n",
00995                         pdb_get_username(sampass) ));
00996                 return True;
00997         }
00998 
00999         dump_data(100, (const char *)new_nt_p16, NT_HASH_LEN);
01000         dump_data(100, (const char *)pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen);
01001 
01002         memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN);
01003         for (i=0; i<pwHisLen; i++) {
01004                 uchar new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN];
01005                 const uchar *current_salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN];
01006                 const uchar *old_nt_pw_salted_md5_hash = &pwhistory[(i*PW_HISTORY_ENTRY_LEN)+
01007                                                         PW_HISTORY_SALT_LEN];
01008                 if (!memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) {
01009                         /* Ignore zero valued entries. */
01010                         continue;
01011                 }
01012                 /* Create salted versions of new to compare. */
01013                 E_md5hash(current_salt, new_nt_p16, new_nt_pw_salted_md5_hash);
01014 
01015                 if (!memcmp(new_nt_pw_salted_md5_hash, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) {
01016                         DEBUG(1,("check_passwd_history: proposed new password for user %s found in history list !\n",
01017                                 pdb_get_username(sampass) ));
01018                         found = True;
01019                         break;
01020                 }
01021         }
01022         return found;
01023 }

NTSTATUS change_oem_password ( struct samu hnd,
char *  old_passwd,
char *  new_passwd,
BOOL  as_root,
uint32 *  samr_reject_reason 
)

chgpasswd.c1032 行で定義されています。

参照先 check_passwd_history()chgpasswd()Get_Pwnam()http_timestring()pdb_get_account_policy()pdb_get_pass_can_change()pdb_get_pass_can_change_time()pdb_get_username()pdb_set_plaintext_passwd()pdb_update_sam_account()smbrunsecret()str_charnum()username.

参照元 api_SetUserPassword()pass_oem_change().

01033 {
01034         uint32 min_len;
01035         struct passwd *pass = NULL;
01036         const char *username = pdb_get_username(hnd);
01037         time_t can_change_time = pdb_get_pass_can_change_time(hnd);
01038 
01039         if (samr_reject_reason) {
01040                 *samr_reject_reason = Undefined;
01041         }
01042 
01043         /* check to see if the secdesc has previously been set to disallow */
01044         if (!pdb_get_pass_can_change(hnd)) {
01045                 DEBUG(1, ("user %s does not have permissions to change password\n", username));
01046                 if (samr_reject_reason) {
01047                         *samr_reject_reason = REJECT_REASON_OTHER;
01048                 }
01049                 return NT_STATUS_ACCOUNT_RESTRICTION;
01050         }
01051 
01052         /* removed calculation here, becuase passdb now calculates
01053            based on policy.  jmcd */
01054         if ((can_change_time != 0) && (time(NULL) < can_change_time)) {
01055                 DEBUG(1, ("user %s cannot change password now, must "
01056                           "wait until %s\n", username,
01057                           http_timestring(can_change_time)));
01058                 if (samr_reject_reason) {
01059                         *samr_reject_reason = REJECT_REASON_OTHER;
01060                 }
01061                 return NT_STATUS_ACCOUNT_RESTRICTION;
01062         }
01063 
01064         if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
01065                 DEBUG(1, ("user %s cannot change password - password too short\n", 
01066                           username));
01067                 DEBUGADD(1, (" account policy min password len = %d\n", min_len));
01068                 if (samr_reject_reason) {
01069                         *samr_reject_reason = REJECT_REASON_TOO_SHORT;
01070                 }
01071                 return NT_STATUS_PASSWORD_RESTRICTION;
01072 /*              return NT_STATUS_PWD_TOO_SHORT; */
01073         }
01074 
01075         if (check_passwd_history(hnd,new_passwd)) {
01076                 if (samr_reject_reason) {
01077                         *samr_reject_reason = REJECT_REASON_IN_HISTORY;
01078                 }
01079                 return NT_STATUS_PASSWORD_RESTRICTION;
01080         }
01081 
01082         pass = Get_Pwnam(username);
01083         if (!pass) {
01084                 DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username));
01085                 return NT_STATUS_ACCESS_DENIED;
01086         }
01087 
01088         /* Use external script to check password complexity */
01089         if (lp_check_password_script() && *(lp_check_password_script())) {
01090                 int check_ret;
01091 
01092                 check_ret = smbrunsecret(lp_check_password_script(), new_passwd);
01093                 DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", lp_check_password_script(), check_ret));
01094 
01095                 if (check_ret != 0) {
01096                         DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
01097                         if (samr_reject_reason) {
01098                                 *samr_reject_reason = REJECT_REASON_NOT_COMPLEX;
01099                         }
01100                         return NT_STATUS_PASSWORD_RESTRICTION;
01101                 }
01102         }
01103 
01104         /*
01105          * If unix password sync was requested, attempt to change
01106          * the /etc/passwd database first. Return failure if this cannot
01107          * be done.
01108          *
01109          * This occurs before the oem change, because we don't want to
01110          * update it if chgpasswd failed.
01111          *
01112          * Conditional on lp_unix_password_sync() because we don't want
01113          * to touch the unix db unless we have admin permission.
01114          */
01115         
01116         if(lp_unix_password_sync() &&
01117                 !chgpasswd(username, pass, old_passwd, new_passwd, as_root)) {
01118                 return NT_STATUS_ACCESS_DENIED;
01119         }
01120 
01121         if (!pdb_set_plaintext_passwd (hnd, new_passwd)) {
01122                 return NT_STATUS_ACCESS_DENIED;
01123         }
01124 
01125         /* Now write it into the file. */
01126         return pdb_update_sam_account (hnd);
01127 }


変数

struct passdb_ops pdb_ops


Sambaに対してSat Aug 29 21:24:25 2009に生成されました。  doxygen 1.4.7