Change check_path_syntax() to use the new next_mb_char_size() function
[ira/wip.git] / source3 / smbd / reply.c
index c0d5234f472e721f7073b3add26606877ffe0001..0fe73cddc28f6e08a795baef25c643799b82ede3 100644 (file)
@@ -3,6 +3,7 @@
    Main SMB reply routines
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Andrew Bartlett      2001
+   Copyright (C) Jeremy Allison 1992-2004.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -45,7 +46,7 @@ extern BOOL global_encrypted_passwords_negotiated;
  set.
 ****************************************************************************/
 
-static NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
 {
        char *d = destname;
        const char *s = srcname;
@@ -86,6 +87,8 @@ static NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
                                return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        }
                        /* Go back one level... */
+                       /* We know this is safe as '/' cannot be part of a mb sequence. */
+                       /* NOTE - if this assumption is invalid we are not in good shape... */
                        while (d > destname) {
                                if (*d == '/')
                                        break;
@@ -110,22 +113,20 @@ static NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
                        }
                        s++;
                } else {
-                       if ((*s & 0x80) && IS_DIRECTORY_SEP(s[1])) {
-                               /* 
-                                * Potential mb char with second char a directory separator.
-                                * All the encodings we care about are 2 byte only, so do a
-                                * conversion to unicode. If the 2 byte char won't convert then
-                                * it's probably a one byte char with a real directory separator
-                                * following, so only copy one byte. If it will convert then
-                                * copy both bytes.
-                                */
-                               uint16 ucs2_val;
-                               if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) {
+                       switch(next_mb_char_size(s)) {
+                               case 4:
                                        *d++ = *s++;
-                               }
+                               case 3:
+                                       *d++ = *s++;
+                               case 2:
+                                       *d++ = *s++;
+                               case 1:
+                                       *d++ = *s++;
+                                       break;
+                               default:
+                                       DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
+                                       return NT_STATUS_INVALID_PARAMETER;
                        }
-                       /* Just copy the char (or the second byte of the mb char). */
-                       *d++ = *s++;
                }
        }
        *d = '\0';
@@ -140,10 +141,10 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
 {
        pstring tmppath;
        char *tmppath_ptr = tmppath;
+       size_t ret;
 #ifdef DEVELOPER
        SMB_ASSERT(dest_len == sizeof(pstring));
 #endif
-       size_t ret;
 
        if (src_len == 0) {
                ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
@@ -163,7 +164,7 @@ int reply_special(char *inbuf,char *outbuf)
        int outsize = 4;
        int msg_type = CVAL(inbuf,0);
        int msg_flags = CVAL(inbuf,1);
-       pstring name1,name2;
+       fstring name1,name2;
        char name_type = 0;
        
        static BOOL already_got_session = False;
@@ -3353,14 +3354,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,'/');
@@ -3369,21 +3374,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;
@@ -3415,7 +3420,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);
        }