diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/chgpasswd.c | 61 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 2 | ||||
-rw-r--r-- | source3/smbd/password.c | 37 | ||||
-rw-r--r-- | source3/smbd/reply.c | 7 |
4 files changed, 66 insertions, 41 deletions
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 852d6aa618..c22f268684 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -604,6 +604,42 @@ BOOL pass_oem_change(char *user, } /*********************************************************** + decode a password buffer +************************************************************/ +BOOL decode_pw_buffer(const char buffer[516], char *new_passwd, + int new_passwd_size, BOOL nt_pass_set) +{ + /* + * The length of the new password is in the last 4 bytes of + * the data buffer. + */ + + uint32 new_pw_len = IVAL(buffer, 512); + if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + { + DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); + return False; + } + + if (nt_pass_set) + { + /* + * nt passwords are in unicode + */ + int uni_pw_len = new_pw_len; + new_pw_len /= 2; + unibuf_to_ascii(new_passwd, &buffer[512-uni_pw_len], new_pw_len); + } + else + { + memcpy(new_passwd, &buffer[512-new_pw_len], new_pw_len); + new_passwd[new_pw_len] = '\0'; + } + + return True; +} + +/*********************************************************** Code to check the OEM hashed password. this function ignores the 516 byte nt OEM hashed password @@ -619,7 +655,6 @@ BOOL check_oem_password(char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; struct smb_passwd *smbpw = NULL; - int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; uchar new_p16[16]; @@ -681,33 +716,11 @@ BOOL check_oem_password(char *user, */ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - new_pw_len = IVAL(lmdata, 512); - if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) + if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, nt_pass_set)) { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } - if (nt_pass_set) - { - /* - * nt passwords are in unicode - */ - int uni_pw_len = new_pw_len; - new_pw_len /= 2; - unibuf_to_ascii(new_passwd, &lmdata[512-uni_pw_len], new_pw_len); - } - else - { - memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); - new_passwd[new_pw_len] = '\0'; - } - /* * To ensure we got the correct new password, hash it and * use it as a key to test the passed old password. diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index a4d452b2a8..5001b16b35 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1680,7 +1680,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param * Older versions of Windows seem to do this. */ - if (password_ok(user, pass1,strlen(pass1),NULL) && + if (password_ok(user, pass1,strlen(pass1),NULL, NULL) && chgpasswd(user,pass1,pass2,False)) { SSVAL(*rparam,0,NERR_Success); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 68d75b933f..11fe69b103 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -156,7 +156,7 @@ register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest) +uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]) { user_struct *vuser; struct passwd *pwfile; /* for getting real name from passwd file */ @@ -205,6 +205,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, vuser->guest = guest; fstrcpy(vuser->name,unix_name); fstrcpy(vuser->requested_name,requested_name); + memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key)); vuser->n_sids = 0; vuser->sids = NULL; @@ -412,7 +413,7 @@ return True if the password is correct, False otherwise BOOL pass_check_smb(char *user, char *domain, uchar *chal, uchar *lm_pwd, uchar *nt_pwd, - struct passwd *pwd) + struct passwd *pwd, uchar user_sess_key[16]) { struct passwd *pass; struct smb_passwd *smb_pass; @@ -467,6 +468,14 @@ BOOL pass_check_smb(char *user, char *domain, if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd)) { + if (user_sess_key != NULL) + { + mdfour(user_sess_key, smb_pass->smb_nt_passwd, 16); +#ifdef DEBUG_PASSWORD + DEBUG(100,("user session key: ")); + dump_data(100, user_sess_key, 16); +#endif + } return(True); } @@ -479,7 +488,8 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) +BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd, + uchar user_sess_key[16]) { if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords())) { @@ -493,7 +503,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd) } return pass_check_smb(user, global_myworkgroup, - challenge, (uchar *)password, (uchar *)password, pwd); + challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key); } return pass_check(user, password, pwlen, pwd, @@ -536,7 +546,8 @@ BOOL user_ok(char *user,int snum) /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum) +static char *validate_group(char *group,char *password,int pwlen,int snum, + uchar user_sess_key[16]) { #if defined(HAVE_NETGROUP) && defined(HAVE_GETNETGRENT) && defined(HAVE_SETNETGRENT) && defined(HAVE_ENDNETGRENT) { @@ -545,7 +556,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL)) { + password_ok(user,password,pwlen,NULL, user_sess_key)) { endnetgrent(); return(user); } @@ -567,7 +578,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; fstrcpy(name,*member); if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL)) + password_ok(name,password,pwlen,NULL, user_sess_key)) return(&name[0]); member++; } @@ -580,7 +591,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (pwd = getpwent ()) { if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd)) { + if (password_ok(NULL, password, pwlen, pwd, user_sess_key)) { fstrcpy(tm, pwd->pw_name); endpwent (); return tm; @@ -633,14 +644,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL); + ok = password_ok(user,password, pwlen, NULL, vuser->dc.user_sess_key); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL)) { + password_ok(vuser->name, password, pwlen, NULL, vuser->dc.user_sess_key)) { fstrcpy(user, vuser->name); vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); @@ -664,7 +675,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstrcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL)) { + if (password_ok(user2,password, pwlen, NULL, vuser->dc.user_sess_key)) { ok = True; fstrcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -703,7 +714,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum); + auser = validate_group(auser+1,password,pwlen,snum, vuser->dc.user_sess_key); if (auser) { ok = True; @@ -716,7 +727,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; fstrcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL)) + password_ok(user2,password,pwlen,NULL, vuser->dc.user_sess_key)) { ok = True; fstrcpy(user,user2); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 694cf3cdd5..57742003ff 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -511,6 +511,7 @@ reply to a session setup command int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 sess_vuid; + uchar user_sess_key[16]; int gid; int uid; int smb_bufsize; @@ -706,13 +707,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if(smb_ntpasslen) { - if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL)) + if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key)) DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); else valid_nt_password = True; } - if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL)) + if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key)) { if (lp_security() >= SEC_USER) { @@ -791,7 +792,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest); + sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); |