From cc70a548f3c48a9503fd54d01896cc2499f5bbcd Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Fri, 12 Mar 2004 14:28:14 +0000 Subject: [PATCH] Fix problems with very long filenames in both smbd and smbclient. It appears that we pass filename through resolve_wildcards() as pstring and use fstring temporary buffer there. As result, a long filename in unix charset (UTF-8 by default) can easily expand over 255 bytes while Windows is able to send to us such names (e.g. Japanese name of ~190 mb chars) which we unable to process through this small fstring buffer. Tested with W2K and smbclient, Japanese and Cyrillics. --- source/client/client.c | 74 +++++++++++++++++++++--------------------- source/configure.in | 2 +- source/smbd/reply.c | 28 ++++++++++------ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/source/client/client.c b/source/client/client.c index 2d640a55738..214b7872979 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -47,7 +47,7 @@ static int io_bufsize = 64512; static int name_type = 0x20; static int max_protocol = PROTOCOL_NT1; -static int process_tok(fstring tok); +static int process_tok(pstring tok); static int cmd_help(void); /* 30 second timeout on most commands */ @@ -284,7 +284,7 @@ static int do_cd(char *newdir) static int cmd_cd(void) { - fstring buf; + pstring buf; int rc = 0; if (next_token_nr(NULL,buf,NULL,sizeof(buf))) @@ -572,7 +572,7 @@ static int cmd_dir(void) { uint16 attribute = aDIR | aSYSTEM | aHIDDEN; pstring mask; - fstring buf; + pstring buf; char *p=buf; int rc; @@ -612,7 +612,7 @@ static int cmd_du(void) { uint16 attribute = aDIR | aSYSTEM | aHIDDEN; pstring mask; - fstring buf; + pstring buf; char *p=buf; int rc; @@ -866,13 +866,13 @@ static void do_mget(file_info *finfo) static int cmd_more(void) { - fstring rname,lname,pager_cmd; + pstring rname,lname,pager_cmd; char *pager; int fd; int rc = 0; - fstrcpy(rname,cur_dir); - fstrcat(rname,"\\"); + pstrcpy(rname,cur_dir); + pstrcat(rname,"\\"); slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir()); fd = smb_mkstemp(lname); @@ -909,7 +909,7 @@ static int cmd_mget(void) { uint16 attribute = aSYSTEM | aHIDDEN; pstring mget_mask; - fstring buf; + pstring buf; char *p=buf; *mget_mask = 0; @@ -963,7 +963,7 @@ static BOOL do_mkdir(char *name) static BOOL do_altname(char *name) { - fstring altname; + pstring altname; if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) { d_printf("%s getting alt name for %s\n", cli_errstr(cli),name); @@ -993,7 +993,7 @@ static int cmd_quit(void) static int cmd_mkdir(void) { pstring mask; - fstring buf; + pstring buf; char *p=buf; pstrcpy(mask,cur_dir); @@ -1035,7 +1035,7 @@ static int cmd_mkdir(void) static int cmd_altname(void) { pstring name; - fstring buf; + pstring buf; char *p=buf; pstrcpy(name,cur_dir); @@ -1187,7 +1187,7 @@ static int cmd_put(void) { pstring lname; pstring rname; - fstring buf; + pstring buf; char *p=buf; pstrcpy(rname,cur_dir); @@ -1349,7 +1349,7 @@ static int file_find(struct file_list **list, const char *directory, static int cmd_mput(void) { - fstring buf; + pstring buf; char *p=buf; while (next_token_nr(NULL,p,NULL,sizeof(buf))) { @@ -1447,7 +1447,7 @@ static int do_cancel(int job) static int cmd_cancel(void) { - fstring buf; + pstring buf; int job; if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) { @@ -1536,7 +1536,7 @@ static void do_del(file_info *finfo) static int cmd_del(void) { pstring mask; - fstring buf; + pstring buf; uint16 attribute = aSYSTEM | aHIDDEN; if (recurse) @@ -1561,7 +1561,7 @@ static int cmd_del(void) static int cmd_open(void) { pstring mask; - fstring buf; + pstring buf; pstrcpy(mask,cur_dir); @@ -1584,7 +1584,7 @@ static int cmd_open(void) static int cmd_rmdir(void) { pstring mask; - fstring buf; + pstring buf; pstrcpy(mask,cur_dir); @@ -1609,7 +1609,7 @@ static int cmd_rmdir(void) static int cmd_link(void) { pstring src,dest; - fstring buf,buf2; + pstring buf,buf2; if (!SERVER_HAS_UNIX_CIFS(cli)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); @@ -1643,7 +1643,7 @@ static int cmd_link(void) static int cmd_symlink(void) { pstring src,dest; - fstring buf,buf2; + pstring buf,buf2; if (!SERVER_HAS_UNIX_CIFS(cli)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); @@ -1679,7 +1679,7 @@ static int cmd_chmod(void) { pstring src; mode_t mode; - fstring buf, buf2; + pstring buf, buf2; if (!SERVER_HAS_UNIX_CIFS(cli)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); @@ -1715,7 +1715,7 @@ static int cmd_chown(void) pstring src; uid_t uid; gid_t gid; - fstring buf, buf2, buf3; + pstring buf, buf2, buf3; if (!SERVER_HAS_UNIX_CIFS(cli)) { d_printf("Server doesn't support UNIX CIFS calls.\n"); @@ -1751,7 +1751,7 @@ static int cmd_chown(void) static int cmd_rename(void) { pstring src,dest; - fstring buf,buf2; + pstring buf,buf2; pstrcpy(src,cur_dir); pstrcpy(dest,cur_dir); @@ -1780,7 +1780,7 @@ static int cmd_rename(void) static int cmd_hardlink(void) { pstring src,dest; - fstring buf,buf2; + pstring buf,buf2; pstrcpy(src,cur_dir); pstrcpy(dest,cur_dir); @@ -1820,7 +1820,7 @@ static int cmd_prompt(void) static int cmd_newer(void) { - fstring buf; + pstring buf; BOOL ok; SMB_STRUCT_STAT sbuf; @@ -1847,7 +1847,7 @@ static int cmd_newer(void) static int cmd_archive(void) { - fstring buf; + pstring buf; if (next_token_nr(NULL,buf,NULL,sizeof(buf))) { archive_level = atoi(buf); @@ -1937,7 +1937,7 @@ static int cmd_printmode(void) static int cmd_lcd(void) { - fstring buf; + pstring buf; pstring d; if (next_token_nr(NULL,buf,NULL,sizeof(buf))) @@ -1982,7 +1982,7 @@ static int cmd_reput(void) { pstring local_name; pstring remote_name; - fstring buf; + pstring buf; char *p = buf; SMB_STRUCT_STAT st; @@ -2126,7 +2126,7 @@ static int cmd_vuid(void) static int cmd_logon(void) { pstring l_username, l_password; - fstring buf,buf2; + pstring buf,buf2; if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) { d_printf("logon []\n"); @@ -2236,7 +2236,7 @@ static struct abbreviations. ******************************************************************/ -static int process_tok(fstring tok) +static int process_tok(pstring tok) { int i = 0, matches = 0; int cmd=0; @@ -2269,7 +2269,7 @@ static int process_tok(fstring tok) static int cmd_help(void) { int i=0,j; - fstring buf; + pstring buf; if (next_token_nr(NULL,buf,NULL,sizeof(buf))) { if ((i = process_tok(buf)) >= 0) @@ -2306,7 +2306,7 @@ static int process_command_string(char *cmd) while (cmd[0] != '\0') { char *p; - fstring tok; + pstring tok; int i; if ((p = strchr_m(cmd, ';')) == 0) { @@ -2569,8 +2569,8 @@ static void process_stdin(void) const char *ptr; while (1) { - fstring tok; - fstring the_prompt; + pstring tok; + pstring the_prompt; char *cline; pstring line; int i; @@ -2613,11 +2613,11 @@ static struct cli_state *do_connect(const char *server, const char *share) struct nmb_name called, calling; const char *server_n; struct in_addr ip; - fstring servicename; + pstring servicename; char *sharename; /* make a copy so we don't modify the global string 'service' */ - fstrcpy(servicename, share); + pstrcpy(servicename, share); sharename = servicename; if (*sharename == '\\') { server = sharename+2; @@ -2853,7 +2853,7 @@ static int do_message_op(void) int main(int argc,char *argv[]) { extern BOOL AllowDebugChange; - fstring base_directory; + pstring base_directory; int opt; pstring query_host; BOOL message = False; @@ -2971,7 +2971,7 @@ static int do_message_op(void) } break; case 'D': - fstrcpy(base_directory,poptGetOptArg(pc)); + pstrcpy(base_directory,poptGetOptArg(pc)); break; case 'g': grepable=True; diff --git a/source/configure.in b/source/configure.in index d07baf12102..6cb64e8d87a 100644 --- a/source/configure.in +++ b/source/configure.in @@ -34,7 +34,7 @@ AC_ARG_WITH(fhs, logfilebase="\${VARDIR}/log/samba" privatedir="\${CONFIGDIR}/private" libdir="\${prefix}/lib/samba" - swatdir="\${LIBDIR}/samba/swat" + swatdir="\${prefix}/share/samba/swat" ;; esac]) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 4a0c06f4427..aeac9e4c84f 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -3361,14 +3361,18 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, /******************************************************************* Resolve wildcards in a filename rename. + Note that name is in UNIX charset and thus potentially can be more + than fstring buffer (255 bytes) especially in default UTF-8 case. + Therefore, we use pstring inside and all calls should ensure that + name2 is at least pstring-long (they do already) ********************************************************************/ static BOOL resolve_wildcards(const char *name1, char *name2) { - fstring root1,root2; - fstring ext1,ext2; + pstring root1,root2; + pstring ext1,ext2; char *p,*p2, *pname1, *pname2; - int available_space; + int available_space, actual_space; pname1 = strrchr_m(name1,'/'); @@ -3377,21 +3381,21 @@ static BOOL resolve_wildcards(const char *name1, char *name2) if (!pname1 || !pname2) return(False); - fstrcpy(root1,pname1); - fstrcpy(root2,pname2); + pstrcpy(root1,pname1); + pstrcpy(root2,pname2); p = strrchr_m(root1,'.'); if (p) { *p = 0; - fstrcpy(ext1,p+1); + pstrcpy(ext1,p+1); } else { - fstrcpy(ext1,""); + pstrcpy(ext1,""); } p = strrchr_m(root2,'.'); if (p) { *p = 0; - fstrcpy(ext2,p+1); + pstrcpy(ext2,p+1); } else { - fstrcpy(ext2,""); + pstrcpy(ext2,""); } p = root1; @@ -3423,7 +3427,11 @@ static BOOL resolve_wildcards(const char *name1, char *name2) available_space = sizeof(pstring) - PTR_DIFF(pname2, name2); if (ext2[0]) { - snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); + actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); + if (actual_space >= available_space - 1) { + DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n", + actual_space - available_space)); + } } else { pstrcpy_base(pname2, root2, name2); } -- 2.34.1