diff options
author | Jeremy Allison <jra@samba.org> | 1997-09-26 18:55:29 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 1997-09-26 18:55:29 +0000 |
commit | cef59090bb2fd3f8a9efd1a453cb90264b891d58 (patch) | |
tree | 694593e9501de3a8aa6966d7e0f9118c29b28447 /source3/smbd/reply.c | |
parent | 5a7b3294dbbe88f0d5da25a74b8112fc6c70af1f (diff) | |
download | samba-cef59090bb2fd3f8a9efd1a453cb90264b891d58.tar.gz samba-cef59090bb2fd3f8a9efd1a453cb90264b891d58.tar.bz2 samba-cef59090bb2fd3f8a9efd1a453cb90264b891d58.zip |
Adding Andrews buffer overflow fixes into the main branch.
Jeremy (jallison@whistle.com)
(This used to be commit e7eb1f044d3101679dc7a118820ea5efe0cd837c)
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r-- | source3/smbd/reply.c | 175 |
1 files changed, 101 insertions, 74 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8117685637..c1422bbcf6 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -49,6 +49,18 @@ a packet to ensure chaining works correctly */ /**************************************************************************** +report a possible attack via the password buffer overflow bug +****************************************************************************/ +static void overflow_attack(int len) +{ + DEBUG(0,("ERROR: Invalid password length %d\n", len)); + DEBUG(0,("you're machine may be under attack by a user exploiting an old bug\n")); + DEBUG(0,("Attack was from IP=%s\n", client_addr())); + exit_server("possible attack"); +} + + +/**************************************************************************** reply to an special message ****************************************************************************/ int reply_special(char *inbuf,char *outbuf) @@ -66,36 +78,36 @@ int reply_special(char *inbuf,char *outbuf) smb_setlen(outbuf,0); switch (msg_type) { - case 0x81: /* session request */ - CVAL(outbuf,0) = 0x82; - CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50) { - DEBUG(0,("Invalid name length in session request\n")); - return(0); - } - name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); + case 0x81: /* session request */ + CVAL(outbuf,0) = 0x82; + CVAL(outbuf,3) = 0; + if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { + DEBUG(0,("Invalid name length in session request\n")); + return(0); + } + name_extract(inbuf,4,name1); + name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - - strcpy(remote_machine,name2); - trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); - strlower(remote_machine); - if (p) *p = 0; - - strcpy(local_machine,name1); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - strlower(local_machine); - if (p) *p = 0; - - add_session_user(remote_machine); - - reload_services(True); - reopen_logs(); - - break; + + fstrcpy(remote_machine,name2); + trim_string(remote_machine," "," "); + p = strchr(remote_machine,' '); + strlower(remote_machine); + if (p) *p = 0; + + fstrcpy(local_machine,name1); + trim_string(local_machine," "," "); + p = strchr(local_machine,' '); + strlower(local_machine); + if (p) *p = 0; + + add_session_user(remote_machine); + + reload_services(True); + reopen_logs(); + + break; case 0x89: /* session keepalive request (some old clients produce this?) */ @@ -160,25 +172,25 @@ static void parse_connect(char *p,char *service,char *user, p2 = strrchr(p,'\\'); if (p2 == NULL) - strcpy(service,p); + fstrcpy(service,p); else - strcpy(service,p2+1); + fstrcpy(service,p2+1); p += strlen(p) + 2; - strcpy(password,p); + fstrcpy(password,p); *pwlen = strlen(password); p += strlen(p) + 2; - strcpy(dev,p); + fstrcpy(dev,p); *user = 0; p = strchr(service,'%'); if (p != NULL) { *p = 0; - strcpy(user,p+1); + fstrcpy(user,p+1); } } @@ -238,6 +250,10 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); + + if (passlen > MAX_PASSWORD_LENGTH) { + overflow_attack(passlen); + } { char *path; @@ -252,18 +268,17 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen = strlen(password); } - DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen)); - strcpy(service,path+2); + fstrcpy(service,path+2); p = strchr(service,'\\'); if (!p) return(ERROR(ERRSRV,ERRinvnetname)); *p = 0; - strcpy(service,p+1); + fstrcpy(service,p+1); p = strchr(service,'%'); if (p) { *p++ = 0; - strcpy(user,p); + fstrcpy(user,p); } StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); @@ -372,11 +387,15 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); + if (smb_apasslen > MAX_PASSWORD_LENGTH) + overflow_attack(smb_apasslen); + memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1); + pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - if (lp_security() != SEC_SERVER && !doencrypt) - smb_apasslen = strlen(smb_apasswd); + if (lp_security() != SEC_SERVER && !doencrypt) { + smb_apasslen = strlen(smb_apasswd); + } } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); @@ -401,6 +420,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; + if (passlen1 > MAX_PASSWORD_LENGTH) { + overflow_attack(passlen1); + } + + passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); + passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; @@ -438,7 +464,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } p += passlen1 + passlen2; - strcpy(user,p); p = skip_string(p,1); + fstrcpy(user,p); p = skip_string(p,1); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", p,skip_string(p,1),skip_string(p,2))); } @@ -591,7 +617,7 @@ int reply_chkpth(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf) + 1); + pstrcpy(name,smb_buf(inbuf) + 1); unix_convert(name,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -639,7 +665,7 @@ int reply_getatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(fname,smb_buf(inbuf) + 1); + pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,cnum,0,&bad_path); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" @@ -714,7 +740,7 @@ int reply_setatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(fname,smb_buf(inbuf) + 1); + pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -825,8 +851,8 @@ int reply_search(char *inbuf,char *outbuf) { pstring dir2; - strcpy(directory,smb_buf(inbuf)+1); - strcpy(dir2,smb_buf(inbuf)+1); + pstrcpy(directory,smb_buf(inbuf)+1); + pstrcpy(dir2,smb_buf(inbuf)+1); unix_convert(directory,cnum,0,&bad_path); unix_format(dir2); @@ -842,7 +868,7 @@ int reply_search(char *inbuf,char *outbuf) else { *p = 0; - strcpy(mask,p+1); + pstrcpy(mask,p+1); } p = strrchr(directory,'/'); @@ -876,7 +902,7 @@ int reply_search(char *inbuf,char *outbuf) if ((p = strrchr(mask,' '))) { fstring ext; - strcpy(ext,p+1); + fstrcpy(ext,p+1); *p = 0; trim_string(mask,NULL," "); strcat(mask,"."); @@ -898,7 +924,7 @@ int reply_search(char *inbuf,char *outbuf) if (!strchr(mask,'.') && strlen(mask)>8) { fstring tmp; - strcpy(tmp,&mask[8]); + fstrcpy(tmp,&mask[8]); mask[8] = '.'; mask[9] = 0; strcat(mask,tmp); @@ -1078,7 +1104,7 @@ int reply_open(char *inbuf,char *outbuf) share_mode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -1168,7 +1194,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* XXXX we need to handle passed times, sattr and flags */ - strcpy(fname,smb_buf(inbuf)); + pstrcpy(fname,smb_buf(inbuf)); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -1281,7 +1307,7 @@ int reply_mknew(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,cnum,0,&bad_path); if (createmode & aVOLID) @@ -1359,7 +1385,8 @@ int reply_ctemp(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); - sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); + strcat(fname,"/TMXXXXXX"); unix_convert(fname,cnum,0,&bad_path); unixmode = unix_mode(cnum,createmode); @@ -1455,7 +1482,7 @@ int reply_unlink(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); dirtype = SVAL(inbuf,smb_vwv0); - strcpy(name,smb_buf(inbuf) + 1); + pstrcpy(name,smb_buf(inbuf) + 1); DEBUG(3,("reply_unlink : %s\n",name)); @@ -1503,7 +1530,7 @@ int reply_unlink(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; @@ -2381,7 +2408,7 @@ int reply_printopen(char *inbuf,char *outbuf) { pstring s; char *p; - StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1); + pstrcpy(s,smb_buf(inbuf)+1); p = s; while (*p) { @@ -2583,7 +2610,7 @@ int reply_mkdir(char *inbuf,char *outbuf) int outsize,ret= -1; BOOL bad_path = False; - strcpy(directory,smb_buf(inbuf) + 1); + pstrcpy(directory,smb_buf(inbuf) + 1); cnum = SVAL(inbuf,smb_tid); unix_convert(directory,cnum,0,&bad_path); @@ -2680,7 +2707,7 @@ int reply_rmdir(char *inbuf,char *outbuf) BOOL bad_path = False; cnum = SVAL(inbuf,smb_tid); - strcpy(directory,smb_buf(inbuf) + 1); + pstrcpy(directory,smb_buf(inbuf) + 1); unix_convert(directory,cnum,0,&bad_path); if (check_name(directory,cnum)) @@ -2728,7 +2755,7 @@ int reply_rmdir(char *inbuf,char *outbuf) errno = ENOMEM; break; } - strcpy(fullname, directory); + pstrcpy(fullname, directory); strcat(fullname, "/"); strcat(fullname, dname); @@ -2795,21 +2822,21 @@ static BOOL resolve_wildcards(char *name1,char *name2) if (!name1 || !name2) return(False); - strcpy(root1,name1); - strcpy(root2,name2); + fstrcpy(root1,name1); + fstrcpy(root2,name2); p = strrchr(root1,'.'); if (p) { *p = 0; - strcpy(ext1,p+1); + fstrcpy(ext1,p+1); } else { - strcpy(ext1,""); + fstrcpy(ext1,""); } p = strrchr(root2,'.'); if (p) { *p = 0; - strcpy(ext2,p+1); + fstrcpy(ext2,p+1); } else { - strcpy(ext2,""); + fstrcpy(ext2,""); } p = root1; @@ -2883,8 +2910,8 @@ int reply_mv(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf) + 1); - strcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); + pstrcpy(name,smb_buf(inbuf) + 1); + pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -2998,14 +3025,14 @@ int reply_mv(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; error = ERRnoaccess; sprintf(fname,"%s/%s",directory,dname); if (!can_rename(fname,cnum)) continue; - strcpy(destname,newname); + pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) continue; @@ -3051,7 +3078,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, int fnum1,fnum2; pstring dest; - strcpy(dest,dest1); + pstrcpy(dest,dest1); if (target_is_directory) { char *p = strrchr(src,'/'); if (p) @@ -3128,8 +3155,8 @@ int reply_copy(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf)); - strcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); + pstrcpy(name,smb_buf(inbuf)); + pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); @@ -3198,7 +3225,7 @@ int reply_copy(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; @@ -3252,7 +3279,7 @@ int reply_setdir(char *inbuf,char *outbuf) if (!CAN_SETDIR(snum)) return(ERROR(ERRDOS,ERRnoaccess)); - strcpy(newdir,smb_buf(inbuf) + 1); + pstrcpy(newdir,smb_buf(inbuf) + 1); strlower(newdir); if (strlen(newdir) == 0) |