r11909: Implement 'reset on zero vc'. This kills other connections when a session
[ira/wip.git] / source3 / smbd / mangle_hash2.c
index 9cd0438d5134425bc7db64cc0656a0ec5f264c3c..335ba8e2ef9315e21e1f4240c7a47d14c85b2e27 100644 (file)
@@ -53,7 +53,7 @@
 
 #include "includes.h"
 
-#if 0
+#if 1
 #define M_DEBUG(level, x) DEBUG(level, x)
 #else
 #define M_DEBUG(level, x)
@@ -119,7 +119,7 @@ static const char *reserved_names[] =
 
    this hash needs to be fast with a low collision rate (what hash doesn't?)
 */
-static u32 mangle_hash(const char *key, unsigned length)
+static u32 mangle_hash(const char *key, unsigned int length)
 {
        u32 value;
        u32   i;
@@ -129,6 +129,7 @@ static u32 mangle_hash(const char *key, unsigned length)
           doesn't depend on the case of the long name. Note that this
           is the only place where we need to use a multi-byte string
           function */
+       length = MIN(length,sizeof(fstring)-1);
        strncpy(str, key, length);
        str[length] = 0;
        strupper_m(str);
@@ -152,13 +153,19 @@ static u32 mangle_hash(const char *key, unsigned length)
  */
 static BOOL cache_init(void)
 {
-       if (prefix_cache) return True;
+       if (prefix_cache) {
+               return True;
+       }
 
-       prefix_cache = calloc(MANGLE_CACHE_SIZE, sizeof(char *));
-       if (!prefix_cache) return False;
+       prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE);
+       if (!prefix_cache) {
+               return False;
+       }
 
-       prefix_cache_hashes = calloc(MANGLE_CACHE_SIZE, sizeof(u32));
-       if (!prefix_cache_hashes) return False;
+       prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE);
+       if (!prefix_cache_hashes) {
+               return False;
+       }
 
        return True;
 }
@@ -174,7 +181,7 @@ static void cache_insert(const char *prefix, int length, u32 hash)
                free(prefix_cache[i]);
        }
 
-       prefix_cache[i] = strndup(prefix, length);
+       prefix_cache[i] = SMB_STRNDUP(prefix, length);
        prefix_cache_hashes[i] = hash;
 }
 
@@ -205,7 +212,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
 {
        unsigned int i;
 
-       M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len));
+       M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len));
 
        /* check the length */
        if (len > 12 || len < 8)
@@ -219,7 +226,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
        if (len > 8) {
                if (name[8] != '.')
                        return False;
-               for (i=9; name[i]; i++) {
+               for (i=9; name[i] && i < len; i++) {
                        if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
                                return False;
                        }
@@ -243,7 +250,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
                }
        }
 
-       M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len));
+       M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len));
 
        return True;
 }
@@ -261,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
    directory separators. It should return true if any component is
    mangled
  */
-static BOOL is_mangled(const char *name)
+static BOOL is_mangled(const char *name, int snum)
 {
        const char *p;
        const char *s;
@@ -286,7 +293,7 @@ static BOOL is_mangled(const char *name)
    simplifies things greatly (it means that we know the string won't
    get larger when converted from UNIX to DOS formats)
 */
-static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
+static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum)
 {
        int len, i;
        char *dot_p;
@@ -325,7 +332,7 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
                prefix_len = PTR_DIFF(dot_p, name);
                suffix_len = len - (prefix_len+1);
 
-               if (prefix_len > 8 || suffix_len > 3) {
+               if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
                        return False;
                }
 
@@ -362,10 +369,8 @@ static void mangle_reset(void)
 /*
   try to find a 8.3 name in the cache, and if found then
   replace the string with the original long name. 
-
-  The filename must be able to hold at least sizeof(fstring) 
 */
-static BOOL check_cache(char *name)
+static BOOL check_cache(char *name, size_t maxlen, int snum)
 {
        u32 hash, multiplier;
        unsigned int i;
@@ -373,7 +378,7 @@ static BOOL check_cache(char *name)
        char extension[4];
 
        /* make sure that this is a mangled name from this cache */
-       if (!is_mangled(name)) {
+       if (!is_mangled(name, snum)) {
                M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
                return False;
        }
@@ -403,10 +408,10 @@ static BOOL check_cache(char *name)
 
        if (extension[0]) {
                M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension));
-               slprintf(name, sizeof(fstring), "%s.%s", prefix, extension);
+               slprintf(name, maxlen, "%s.%s", prefix, extension);
        } else {
                M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix));
-               fstrcpy(name, prefix);
+               safe_strcpy(name, prefix, maxlen);
        }
 
        return True;
@@ -427,7 +432,7 @@ static BOOL is_reserved_name(const char *name)
                for (i=0; reserved_names[i]; i++) {
                        int len = strlen(reserved_names[i]);
                        /* note that we match on COM1 as well as COM1.foo */
-                       if (strncasecmp(name, reserved_names[i], len) == 0 &&
+                       if (strnequal(name, reserved_names[i], len) &&
                            (name[len] == '.' || name[len] == 0)) {
                                return True;
                        }
@@ -440,6 +445,7 @@ static BOOL is_reserved_name(const char *name)
 /*
  See if a filename is a legal long filename.
  A filename ending in a '.' is not legal unless it's "." or "..". JRA.
+ A filename ending in ' ' is not legal either. See bug id #2769.
 */
 
 static BOOL is_legal_name(const char *name)
@@ -453,17 +459,13 @@ static BOOL is_legal_name(const char *name)
                        /* Possible start of mb character. */
                        char mbc[2];
                        /*
-                        * We know the following will return 2 bytes. What
-                        * we need to know was if errno was set.
                         * Note that if CH_UNIX is utf8 a string may be 3
                         * bytes, but this is ok as mb utf8 characters don't
                         * contain embedded ascii bytes. We are really checking
                         * for mb UNIX asian characters like Japanese (SJIS) here.
                         * JRA.
                         */
-                       errno = 0;
-                       convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2);
-                       if (!errno) {
+                       if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) {
                                /* Was a good mb string. */
                                name += 2;
                                continue;
@@ -479,6 +481,10 @@ static BOOL is_legal_name(const char *name)
                } else {
                        alldots = False;
                }
+               if ((name[0] == ' ') && (name[1] == '\0')) {
+                       /* Can't end in ' ' */
+                       return False;
+               }
                name++;
        }
 
@@ -490,7 +496,6 @@ static BOOL is_legal_name(const char *name)
                if (dot_pos[1] == '\0')
                        return False;
        }
-
        return True;
 }
 
@@ -505,7 +510,7 @@ static BOOL is_legal_name(const char *name)
 
   the name parameter must be able to hold 13 bytes
 */
-static void name_map(fstring name, BOOL need83, BOOL cache83)
+static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum)
 {
        char *dot_p;
        char lead_chars[7];
@@ -519,7 +524,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83)
        if (!is_reserved_name(name)) {
                /* if the name is already a valid 8.3 name then we don't need to 
                   do anything */
-               if (is_8_3(name, False, False)) {
+               if (is_8_3(name, False, False, snum)) {
                        return;
                }
 
@@ -632,6 +637,11 @@ static void init_tables(void)
        memset(char_flags, 0, sizeof(char_flags));
 
        for (i=1;i<128;i++) {
+               if (i <= 0x1f) {
+                       /* Control characters. */
+                       char_flags[i] |= FLAG_ILLEGAL;
+               }
+
                if ((i >= '0' && i <= '9') || 
                    (i >= 'a' && i <= 'z') || 
                    (i >= 'A' && i <= 'Z')) {
@@ -678,14 +688,13 @@ static void init_tables(void)
        }
 }
 
-
 /*
   the following provides the abstraction layer to make it easier
   to drop in an alternative mangling implementation */
 static struct mangle_fns mangle_fns = {
+       mangle_reset,
        is_mangled,
        is_8_3,
-       mangle_reset,
        check_cache,
        name_map
 };
@@ -711,3 +720,42 @@ struct mangle_fns *mangle_hash2_init(void)
 
        return &mangle_fns;
 }
+
+static void posix_mangle_reset(void)
+{;}
+
+static BOOL posix_is_mangled(const char *s, int snum)
+{
+       return False;
+}
+
+static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum)
+{
+       return False;
+}
+
+static BOOL posix_check_cache( char *s, size_t maxlen, int snum )
+{
+       return False;
+}
+
+static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum)
+{
+       if (need83) {
+               memset(OutName, '\0', 13);
+       }
+}
+
+/* POSIX paths backend - no mangle. */
+static struct mangle_fns posix_mangle_fns = {
+        posix_mangle_reset,
+        posix_is_mangled,
+        posix_is_8_3,
+        posix_check_cache,
+        posix_name_map
+};
+
+struct mangle_fns *posix_mangle_init(void)
+{
+       return &posix_mangle_fns;
+}