diff options
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rw-r--r-- | source3/lib/charcnv.c | 60 | ||||
-rw-r--r-- | source3/lib/util.c | 1 | ||||
-rw-r--r-- | source3/libsmb/smbdes.c | 6 | ||||
-rw-r--r-- | source3/passdb/smbpass.c | 12 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 83 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 30 | ||||
-rw-r--r-- | source3/smbd/server.c | 7 |
8 files changed, 195 insertions, 8 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index d0376fb9fe..d6027e3716 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -45,6 +45,9 @@ void add_char_string(char *s); BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence); BOOL chgpasswd(char *name,char *oldpass,char *newpass); BOOL chgpasswd(char *name,char *oldpass,char *newpass); +BOOL check_lanman_password(char *user, unsigned char *pass1, + unsigned char *pass2, struct smb_passwd **psmbpw); +BOOL change_lanman_password(struct smb_passwd *smbpw, char *pass1, char *pass2); /*The following definitions come from client.c */ @@ -1268,6 +1271,7 @@ struct shmem_ops *sysv_shm_open(int ronly); void E_P16(unsigned char *p14,unsigned char *p16); void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); +void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out); void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key); void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key); diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index e1a7ac01db..f5d28baee4 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -98,6 +98,62 @@ update_map("\257\275\261\245\346\206\352\251\263\210\361\344\363\242\266\230"); update_map("\274\253\277\276"); } +/* Init for russian language (iso8859-5) */ + +/* Added by Max Khon <max@iclub.nsu.ru> */ + +static void init_iso8859_5() +{ + int i; + if (!mapsinited) initmaps(); + + /* Do not map undefined characters to some accidental code */ + for (i = 128; i < 256; i++) + { + unix2dos[i] = CTRLZ; + dos2unix[i] = CTRLZ; + } + +/* MSDOS Code Page 866 -> ISO8859-5 */ +update_map("\200\260\201\261\202\262\203\263\204\264\205\265\206\266\207\267"); +update_map("\210\270\211\271\212\272\213\273\214\274\215\275\216\276\217\277"); +update_map("\220\300\221\301\222\302\223\303\224\304\225\305\226\306\227\307"); +update_map("\230\310\231\311\232\312\233\313\234\314\235\315\236\316\237\317"); +update_map("\240\320\241\321\242\322\243\323\244\324\245\325\246\326\247\327"); +update_map("\250\330\251\331\252\332\253\333\254\334\255\335\256\336\257\337"); +update_map("\340\340\341\341\342\342\343\343\344\344\345\345\346\346\347\347"); +update_map("\350\350\351\351\352\352\353\353\354\354\355\355\356\356\357\357"); +update_map("\360\241\361\361\362\244\363\364\364\247\365\367\366\256\367\376"); +update_map("\374\360\377\240"); +} + +/* Init for russian language (koi8) */ + +static void init_koi8_r() +{ + if (!mapsinited) initmaps(); + + /* There aren't undefined characters between 128 and 255 */ + +/* MSDOS Code Page 866 -> KOI8-R */ +update_map("\200\304\201\263\202\332\203\277\204\300\205\331\206\303\207\264"); +update_map("\210\302\211\301\212\305\213\337\214\334\215\333\216\335\217\336"); +update_map("\220\260\221\261\222\262\223\364\224\376\225\371\226\373\227\367"); +update_map("\230\363\231\362\232\377\233\365\234\370\235\375\236\372\237\366"); +update_map("\240\315\241\272\242\325\243\361\244\326\245\311\246\270\247\267"); +update_map("\250\273\251\324\252\323\253\310\254\276\255\275\256\274\257\306"); +update_map("\260\307\261\314\262\265\263\360\264\266\265\271\266\321\267\322"); +update_map("\270\313\271\317\272\320\273\312\274\330\275\327\276\316\277\374"); +update_map("\300\356\301\240\302\241\303\346\304\244\305\245\306\344\307\243"); +update_map("\310\345\311\250\312\251\313\252\314\253\315\254\316\255\317\256"); +update_map("\320\257\321\357\322\340\323\341\324\342\325\343\326\246\327\242"); +update_map("\330\354\331\353\332\247\333\350\334\355\335\351\336\347\337\352"); +update_map("\340\236\341\200\342\201\343\226\344\204\345\205\346\224\347\203"); +update_map("\350\225\351\210\352\211\353\212\354\213\355\214\356\215\357\216"); +update_map("\360\217\361\237\362\220\363\221\364\222\365\223\366\206\367\202"); +update_map("\370\234\371\233\372\207\373\230\374\235\375\231\376\227\377\232"); +} + /* * Convert unix to dos */ @@ -156,6 +212,10 @@ void interpret_character_set(char *str) init_iso8859_1(); } else if (strequal (str, "iso8859-2")) { init_iso8859_2(); + } else if (strequal (str, "iso8859-5")) { + init_iso8859_5(); + } else if (strequal (str, "koi8-r")) { + init_koi8_r(); } else { DEBUG(0,("unrecognized character set\n")); } diff --git a/source3/lib/util.c b/source3/lib/util.c index 403ebb73eb..1aa88c0708 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3731,6 +3731,7 @@ char *automount_server(char *user_name) home_server_len = sizeof(pstring); } strncpy(server_name, nis_result, home_server_len); + server_name[home_server_len] = '\0'; } #else /* use the local machine name instead of the auto-map server */ diff --git a/source3/libsmb/smbdes.c b/source3/libsmb/smbdes.c index c3cc2c7133..7446f31e15 100644 --- a/source3/libsmb/smbdes.c +++ b/source3/libsmb/smbdes.c @@ -317,6 +317,12 @@ void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) smbhash(p24+16, c8, p21+14, 1); } +void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) +{ + smbhash(out, in, p14, 0); + smbhash(out+8, in+8, p14+7, 0); +} + void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key) { unsigned char buf[8]; diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index 4109383fb4..188bf1b71d 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -788,12 +788,15 @@ BOOL mod_smbpwd_entry(struct smb_passwd* pwd) return False; } + /* The following check is wrong - the NT hash is optional. */ +#if 0 if (*p == '*' || *p == 'X') { fclose(fp); pw_file_unlock(lockfd); return False; } +#endif /* whew. entry is correctly formed. */ @@ -838,19 +841,20 @@ BOOL mod_smbpwd_entry(struct smb_passwd* pwd) { sprintf(&ascii_p16[i*2], "%02X", (uchar) pwd->smb_passwd[i]); } + /* Add on the NT md4 hash */ + ascii_p16[32] = ':'; + wr_len = 65; if (pwd->smb_nt_passwd != NULL) { - /* Add on the NT md4 hash */ - ascii_p16[32] = ':'; for (i = 0; i < 16; i++) { sprintf(&ascii_p16[(i*2)+33], "%02X", (uchar) pwd->smb_nt_passwd[i]); } - wr_len = 65; } else { - wr_len = 32; + /* No NT hash - write out an 'invalid' string. */ + strcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); } #ifdef DEBUG_PASSWORD diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 17401410ce..1502cd1219 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -398,3 +398,86 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass) return(False); } #endif + +/*********************************************************** + Code to check the lanman hashed password. +************************************************************/ + +BOOL check_lanman_password(char *user, unsigned char *pass1, + unsigned char *pass2, struct smb_passwd **psmbpw) +{ + unsigned char unenc_new_pw[16]; + unsigned char unenc_old_pw[16]; + struct smb_passwd *smbpw; + + *psmbpw = NULL; + + become_root(0); + smbpw = get_smbpwd_entry(user, 0); + unbecome_root(0); + + if(smbpw == NULL) + { + DEBUG(0,("check_lanman_password: get_smbpwd_entry returned NULL\n")); + return False; + } + + if(smbpw->smb_passwd == NULL) + { + DEBUG(0,("check_lanman_password: no lanman password !\n")); + return False; + } + + /* Get the new lanman hash. */ + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + + /* Use this to get the old lanman hash. */ + D_P16(unenc_new_pw, pass1, unenc_old_pw); + + /* Check that the two old passwords match. */ + if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) + { + DEBUG(0,("check_lanman_password: old password doens't match.\n")); + return False; + } + + *psmbpw = smbpw; + return True; +} + +/*********************************************************** + Code to change the lanman hashed password. + It nulls out the NT hashed password as it will + no longer be valid. +************************************************************/ + +BOOL change_lanman_password(struct smb_passwd *smbpw, char *pass1, char *pass2) +{ + char unenc_new_pw[16]; + BOOL ret; + + if(smbpw == NULL) + { + DEBUG(0,("change_lanman_password: get_smbpwd_entry returned NULL\n")); + return False; + } + + if(smbpw->smb_passwd == NULL) + { + DEBUG(0,("change_lanman_password: no lanman password !\n")); + return False; + } + + /* Get the new lanman hash. */ + D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); + + smbpw->smb_passwd = unenc_new_pw; + smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ + + /* Now write it into the file. */ + become_root(0); + ret = mod_smbpwd_entry(smbpw); + unbecome_root(0); + + return ret; +} diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index ee2aec8c22..e3db823a9d 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1141,7 +1141,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, uint32 servertype = IVAL(p,4); char *p2; int data_len, fixed_len, string_len; - int f_len, s_len; + int f_len = 0, s_len = 0; struct srv_info_struct *servers=NULL; int counted=0,total=0; int i,missed; @@ -1421,7 +1421,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, int total=0,counted=0; int i; int data_len, fixed_len, string_len; - int f_len, s_len; + int f_len = 0, s_len = 0; if (!prefix_ok(str1,"WrLeh")) return False; if (!check_share_info(uLevel,str2)) return False; @@ -1532,8 +1532,8 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, p = skip_string(p,1); - StrnCpy(pass1,p,16); - StrnCpy(pass2,p+16,16); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -1545,12 +1545,34 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, DEBUG(3,("Set password for <%s>\n",user)); + /* + * Attempt the plaintext password change first. + * Older versions of Windows seem to do this. + */ + if (password_ok(user,pass1,strlen(pass1),NULL) && chgpasswd(user,pass1,pass2)) { SSVAL(*rparam,0,NERR_Success); } + /* + * If the plaintext change failed, attempt + * the encrypted. NT will generate this + * after trying the samr method. + */ + + if(SVAL(*rparam,0) != NERR_Success) + { + struct smb_passwd *smbpw = NULL; + + if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &smbpw) && + change_lanman_password(smbpw,(unsigned char *)pass1,(unsigned char *)pass2)) + { + SSVAL(*rparam,0,NERR_Success); + } + } + bzero(pass1,sizeof(fstring)); bzero(pass2,sizeof(fstring)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index bf635fc27a..751039070f 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1637,6 +1637,13 @@ BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) { DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); +#if 0 + /* + * This next line is a test that allows the deny-mode + * processing to be skipped. JRA. + */ + continue; +#endif } else { |