summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/docbook/manpages/smb.conf.5.sgml19
-rw-r--r--source3/param/loadparm.c6
-rw-r--r--source3/smbd/mangle_hash2.c57
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();