diff options
-rw-r--r-- | docs/docbook/manpages/smb.conf.5.sgml | 19 | ||||
-rw-r--r-- | source3/param/loadparm.c | 6 | ||||
-rw-r--r-- | source3/smbd/mangle_hash2.c | 57 |
3 files changed, 61 insertions, 21 deletions
diff --git a/docs/docbook/manpages/smb.conf.5.sgml b/docs/docbook/manpages/smb.conf.5.sgml index 0e03eabd03..a1f767185c 100644 --- a/docs/docbook/manpages/smb.conf.5.sgml +++ b/docs/docbook/manpages/smb.conf.5.sgml @@ -4292,10 +4292,21 @@ 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> diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 5d1ef9b91f..7bec315631 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -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) diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 5adde19eea..bbc9020eab 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -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(); |