diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/dir.c | 96 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 101 |
2 files changed, 130 insertions, 67 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 28faa9a06b..cae6281e91 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -790,38 +790,32 @@ int TellDir(void *p) return(dirp->pos); } +/******************************************************************************* + This section manages a global directory cache. + (It should probably be split into a separate module. crh) +********************************************************************************/ -/* -------------------------------------------------------------------------- ** - * This section manages a global directory cache. - * (It should probably be split into a separate module. crh) - * -------------------------------------------------------------------------- ** - */ - -typedef struct - { +typedef struct { ubi_dlNode node; char *path; char *name; char *dname; int snum; - } dir_cache_entry; +} dir_cache_entry; static ubi_dlNewList( dir_cache ); +/***************************************************************************** + Add an entry to the directory cache. + Input: path - + name - + dname - + snum - + Output: None. +*****************************************************************************/ + void DirCacheAdd( char *path, char *name, char *dname, int snum ) - /* ------------------------------------------------------------------------ ** - * Add an entry to the directory cache. - * - * Input: path - - * name - - * dname - - * snum - - * - * Output: None. - * - * ------------------------------------------------------------------------ ** - */ - { +{ int pathlen; int namelen; dir_cache_entry *entry; @@ -852,27 +846,23 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum ) while( DIRCACHESIZE < dir_cache->count ) free( ubi_dlRemTail( dir_cache ) ); - } /* DirCacheAdd */ +} +/***************************************************************************** + Search for an entry to the directory cache. + Input: path - + name - + snum - + Output: The dname string of the located entry, or NULL if the entry was + not found. + + Notes: This uses a linear search, which is is okay because of + the small size of the cache. Use a splay tree or hash + for large caches. +*****************************************************************************/ char *DirCacheCheck( char *path, char *name, int snum ) - /* ------------------------------------------------------------------------ ** - * Search for an entry to the directory cache. - * - * Input: path - - * name - - * snum - - * - * Output: The dname string of the located entry, or NULL if the entry was - * not found. - * - * Notes: This uses a linear search, which is is okay because of - * the small size of the cache. Use a splay tree or hash - * for large caches. - * - * ------------------------------------------------------------------------ ** - */ - { +{ dir_cache_entry *entry; for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); @@ -889,18 +879,15 @@ char *DirCacheCheck( char *path, char *name, int snum ) } return(NULL); - } /* DirCacheCheck */ +} + +/***************************************************************************** + Remove all cache entries which have an snum that matches the input. + Input: snum - + Output: None. +*****************************************************************************/ void DirCacheFlush(int snum) - /* ------------------------------------------------------------------------ ** - * Remove all cache entries which have an snum that matches the input. - * - * Input: snum - - * - * Output: None. - * - * ------------------------------------------------------------------------ ** - */ { dir_cache_entry *entry; ubi_dlNodePtr next; @@ -912,11 +899,4 @@ void DirCacheFlush(int snum) free( ubi_dlRemThis( dir_cache, entry ) ); entry = (dir_cache_entry *)next; } -} /* DirCacheFlush */ - -/* -------------------------------------------------------------------------- ** - * End of the section that manages the global directory cache. - * -------------------------------------------------------------------------- ** - */ - - +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index cb4127aee4..086a4bfa0b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1660,9 +1660,53 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch return(True); } +/*********************************************************** + Code to check a plaintext password against smbpasswd entries. +***********************************************************/ + +static BOOL check_plaintext_password(char *user,char *old_passwd, + int old_passwd_size, struct smb_passwd **psmbpw) +{ + struct smb_passwd *smbpw = NULL; + uchar old_pw[16],old_ntpw[16]; + + become_root(False); + *psmbpw = smbpw = getsmbpwnam(user); + unbecome_root(False); + + if (smbpw == NULL) { + DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); + return False; + } + + if (smbpw->acct_ctrl & ACB_DISABLED) { + DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); + return(False); + } + + nt_lm_owf_gen(old_passwd,old_ntpw,old_pw); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("check_plaintext_password: smbpw->smb_nt_passwd \n")); + dump_data(100,smbpw->smb_nt_passwd,16); + DEBUG(100,("check_plaintext_password: old_ntpw \n")); + dump_data(100,old_ntpw,16); + DEBUG(100,("check_plaintext_password: smbpw->smb_passwd \n")); + dump_data(100,smbpw->smb_passwd,16); + DEBUG(100,("check_plaintext_password: old_pw\n")); + dump_data(100,old_pw,16); +#endif + + if(memcmp(smbpw->smb_nt_passwd,old_ntpw,16) && memcmp(smbpw->smb_passwd,old_pw,16)) + return(False); + else + return(True); +} + /**************************************************************************** - set the user password - ****************************************************************************/ + Set the user password. +*****************************************************************************/ + static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1704,20 +1748,59 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param (void)Get_Pwnam( user, True); /* - * Attempt the plaintext password change first. - * Older versions of Windows seem to do this. + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. */ - if (password_ok(user, pass1,strlen(pass1),NULL) && - chgpasswd(user,pass1,pass2,False)) { - SSVAL(*rparam,0,NERR_Success); + fstring saved_pass2; + struct smb_passwd *smbpw = NULL; + + /* + * Save the new password as change_oem_password overwrites it + * with zeros. + */ + + fstrcpy(saved_pass2, pass2); + + if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) && + change_oem_password(smbpw,pass2,False)) + { + SSVAL(*rparam,0,NERR_Success); + + /* + * If unix password sync was requested, attempt to change + * the /etc/passwd database also. Return failure if this cannot + * be done. + */ + + if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False)) + SSVAL(*rparam,0,NERR_badpass); + } + } + + /* + * If the above failed, attempt the plaintext password change. + * This tests against the /etc/passwd database only. + */ + + if(SVAL(*rparam,0) != NERR_Success) + { + if (password_ok(user, pass1,strlen(pass1),NULL) && + chgpasswd(user,pass1,pass2,False)) + { + SSVAL(*rparam,0,NERR_Success); + } } /* * If the plaintext change failed, attempt - * the encrypted. NT will generate this - * after trying the samr method. + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. */ if(SVAL(*rparam,0) != NERR_Success) |