add a 'mangle prefix' option to allow people to tune the number of
authorAndrew Tridgell <tridge@samba.org>
Mon, 21 Oct 2002 04:30:51 +0000 (04:30 +0000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 21 Oct 2002 04:30:51 +0000 (04:30 +0000)
characters used in the prefix for 8.3 names in the hash2
algorithm. The longer the prefix the more readable the 8.3 names will
be, but the weaker the hash.

this was added because of someone complaining that the new hashing
algorithm was unreadable but the old one was broken :)

docs/docbook/manpages/smb.conf.5.sgml
source/param/loadparm.c
source/smbd/mangle_hash2.c

index 0e03eabd037afda17d6c4ea51fccfec772b235c8..a1f767185c789791c872e91e243e0c27e9685280 100644 (file)
                a better algorithm (generates less collisions) in the names.
                However, many Win32 applications store the mangled names and so
                changing to the new algorithm must not be done
-               lightly as these applications may break unless reinstalled.
-               New installations of Samba may set the default to hash2.</para>
-               <para>Default: <command>mangling method = hash</command></para>
-               <para>Example: <command>mangling method = hash2</command></para>
+               lightly as these applications may break unless reinstalled.</para>
+               <para>Default: <command>mangling method = hash2</command></para>
+               <para>Example: <command>mangling method = hash</command></para>
+               </listitem>
+               </varlistentry>
+
+               <varlistentry>
+               <term><anchor id="MANGLEPREFIX">mangle prefix (G)</term>
+               <listitem><para> controls the number of prefix
+               characters from the original name used when generating
+               the mangled names. A larger value will give a weaker
+               hash and therefore more name collisions. The minimum
+               value is 1 and the maximum value is 6.</para>
+               <para>Default: <command>mangle prefix = 1</command></para>
+               <para>Example: <command>mangle prefix = 4</command></para>
                </listitem>
                </varlistentry>
 
index 5d1ef9b91f5a1bfb573d5e83f828f0f9eeed70ae..7bec315631d1284254911eda505fce8e0caeb036 100644 (file)
@@ -167,6 +167,7 @@ typedef struct
        char *szDeleteShareCommand;
        char *szGuestaccount;
        char *szManglingMethod;
+       int mangle_prefix;
        int max_log_size;
        char *szLogLevel;
        int mangled_stack;
@@ -911,6 +912,7 @@ static struct parm_struct parm_table[] = {
        {"Filename Handling", P_SEP, P_SEPARATOR},
        {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
        {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_SHARE},
@@ -1247,8 +1249,9 @@ static void init_globals(void)
        string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
        string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
 
-       /* use the new 'hash2' method by default */
+       /* use the new 'hash2' method by default, with a prefix of 1 */
        string_set(&Globals.szManglingMethod, "hash2");
+       Globals.mangle_prefix = 1;
 
        string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
 
@@ -1535,6 +1538,7 @@ FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
+FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
 #ifdef WITH_UTMP
 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
index 5adde19eea8230995835e2f1dd6771ee5799ba03..bbc9020eabc78b04fa008fa63fecf012a194b82f 100644 (file)
@@ -87,6 +87,13 @@ static unsigned char char_flags[256];
 
 #define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag))
 
+/*
+  this determines how many characters are used from the original filename
+  in the 8.3 mangled name. A larger value leads to a weaker hash and more collisions.
+  The largest possible value is 6.
+*/
+static unsigned mangle_prefix;
+
 /* we will use a very simple direct mapped prefix cache. The big
    advantage of this cache structure is speed and low memory usage 
 
@@ -217,16 +224,18 @@ static BOOL is_mangled_component(const char *name)
                }
        }
        
-       /* check first character */
-       if (! FLAG_CHECK(name[0], FLAG_ASCII)) {
-               return False;
+       /* check lead characters */
+       for (i=0;i<mangle_prefix;i++) {
+               if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
+                       return False;
+               }
        }
        
        /* check rest of hash */
        if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) {
                return False;
        }
-       for (i=1;i<6;i++) {
+       for (i=mangle_prefix;i<6;i++) {
                if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) {
                        return False;
                }
@@ -371,7 +380,7 @@ static BOOL check_cache(char *name)
 
        /* we need to extract the hash from the 8.3 name */
        hash = base_reverse[(unsigned char)name[7]];
-       for (multiplier=36, i=5;i>=1;i--) {
+       for (multiplier=36, i=5;i>=mangle_prefix;i--) {
                u32 v = base_reverse[(unsigned char)name[i]];
                hash += multiplier * v;
                multiplier *= 36;
@@ -478,7 +487,7 @@ static BOOL is_legal_name(const char *name)
 static void name_map(char *name, BOOL need83, BOOL cache83)
 {
        char *dot_p;
-       char lead_char;
+       char lead_chars[7];
        char extension[4];
        int extension_length, i;
        int prefix_len;
@@ -516,15 +525,20 @@ static void name_map(char *name, BOOL need83, BOOL cache83)
                if (i == 0 || i == 4) dot_p = NULL;
        }
 
-       /* the leading character in the mangled name is taken from
-          the first character of the name, if it is ascii 
-          otherwise '_' is used
+       /* the leading characters in the mangled name is taken from
+          the first characters of the name, if they are ascii otherwise
+          '_' is used
        */
-       lead_char = name[0];
-       if (! FLAG_CHECK(lead_char, FLAG_ASCII)) {
-               lead_char = '_';
+       for (i=0;i<mangle_prefix && name[i];i++) {
+               lead_chars[i] = name[i];
+               if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) {
+                       lead_chars[i] = '_';
+               }
+               lead_chars[i] = toupper(lead_chars[i]);
+       }
+       for (;i<mangle_prefix;i++) {
+               lead_chars[i] = '_';
        }
-       lead_char = toupper(lead_char);
 
        /* the prefix is anything up to the first dot */
        if (dot_p) {
@@ -549,10 +563,12 @@ static void name_map(char *name, BOOL need83, BOOL cache83)
        v = hash = mangle_hash(name, prefix_len);
 
        /* now form the mangled name. */
-       new_name[0] = lead_char;
+       for (i=0;i<mangle_prefix;i++) {
+               new_name[i] = lead_chars[i];
+       }
        new_name[7] = base_forward(v % 36);
        new_name[6] = '~';      
-       for (i=5; i>=1; i--) {
+       for (i=5; i>=mangle_prefix; i--) {
                v = v / 36;
                new_name[i] = base_forward(v % 36);
        }
@@ -594,7 +610,7 @@ static void init_tables(void)
 
        memset(char_flags, 0, sizeof(char_flags));
 
-       for (i=0;i<128;i++) {
+       for (i=1;i<128;i++) {
                if ((i >= '0' && i <= '9') || 
                    (i >= 'a' && i <= 'z') || 
                    (i >= 'A' && i <= 'Z')) {
@@ -656,6 +672,15 @@ static struct mangle_fns mangle_fns = {
 /* return the methods for this mangling implementation */
 struct mangle_fns *mangle_hash2_init(void)
 {
+       /* the mangle prefix can only be in the mange 1 to 6 */
+       mangle_prefix = lp_mangle_prefix();
+       if (mangle_prefix > 6) {
+               mangle_prefix = 6;
+       }
+       if (mangle_prefix < 1) {
+               mangle_prefix = 1;
+       }
+
        init_tables();
        mangle_reset();