diff options
-rw-r--r-- | source3/smbd/globals.c | 6 | ||||
-rw-r--r-- | source3/smbd/globals.h | 3 | ||||
-rw-r--r-- | source3/smbd/mangle_hash2.c | 243 |
3 files changed, 178 insertions, 74 deletions
diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 98e4d51b08..1c7afb948e 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -57,15 +57,12 @@ const struct mangle_fns *mangle_fns = NULL; unsigned char *chartest = NULL; TDB_CONTEXT *tdb_mangled_cache = NULL; -/* these tables are used to provide fast tests for characters */ -unsigned char char_flags[256]; /* 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. */ unsigned mangle_prefix = 0; -unsigned char base_reverse[256]; struct msg_state *smbd_msg_state = NULL; @@ -146,9 +143,6 @@ struct memcache *smbd_memcache(void) void smbd_init_globals(void) { - ZERO_STRUCT(char_flags); - ZERO_STRUCT(base_reverse); - ZERO_STRUCT(conn_ctx_stack); ZERO_STRUCT(sec_ctx_stack); diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 86e2c9b3f9..759fead1c3 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -54,15 +54,12 @@ extern const struct mangle_fns *mangle_fns; extern unsigned char *chartest; extern TDB_CONTEXT *tdb_mangled_cache; -/* these tables are used to provide fast tests for characters */ -extern unsigned char char_flags[256]; /* 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. */ extern unsigned mangle_prefix; -extern unsigned char base_reverse[256]; struct msg_state; extern struct msg_state *smbd_msg_state; diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index b9e7d63872..298f348661 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -49,6 +49,19 @@ =============================================================================== */ +/* + * ============================================================================ + * Whenever you change anything in the FLAG_ or other fields, + * re-initialize the tables char_flags and base_reverse by running the + * init_tables() routine once and dump its results. To do this, a + * single smbd run with + * + * #define DYNAMIC_MANGLE_TABLES 1 + * + * and debug level 10 should be sufficient. + * ============================================================================ + */ + #include "includes.h" #include "smbd/globals.h" @@ -93,6 +106,169 @@ static const char * const reserved_names[] = { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; +#define DYNAMIC_MANGLE_TABLES 0 + +#if DYNAMIC_MANGLE_TABLES + +/* these tables are used to provide fast tests for characters */ +static unsigned char char_flags[256]; +static unsigned char base_reverse[256]; + +/* initialise the flags table + + we allow only a very restricted set of characters as 'ascii' in this + mangling backend. This isn't a significant problem as modern clients + use the 'long' filenames anyway, and those don't have these + restrictions. +*/ +static void init_tables(void) +{ + int i; + + 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')) { + char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); + } + if (strchr("_-$~", i)) { + char_flags[i] |= FLAG_ASCII; + } + + if (strchr("*\\/?<>|\":", i)) { + char_flags[i] |= FLAG_ILLEGAL; + } + + if (strchr("*?\"<>", i)) { + char_flags[i] |= FLAG_WILDCARD; + } + } + + memset(base_reverse, 0, sizeof(base_reverse)); + for (i=0;i<36;i++) { + base_reverse[(unsigned char)base_forward(i)] = i; + } + + /* fill in the reserved names flags. These are used as a very + fast filter for finding possible DOS reserved filenames */ + for (i=0; reserved_names[i]; i++) { + unsigned char c1, c2, c3, c4; + + c1 = (unsigned char)reserved_names[i][0]; + c2 = (unsigned char)reserved_names[i][1]; + c3 = (unsigned char)reserved_names[i][2]; + c4 = (unsigned char)reserved_names[i][3]; + + char_flags[c1] |= FLAG_POSSIBLE1; + char_flags[c2] |= FLAG_POSSIBLE2; + char_flags[c3] |= FLAG_POSSIBLE3; + char_flags[c4] |= FLAG_POSSIBLE4; + char_flags[tolower_ascii(c1)] |= FLAG_POSSIBLE1; + char_flags[tolower_ascii(c2)] |= FLAG_POSSIBLE2; + char_flags[tolower_ascii(c3)] |= FLAG_POSSIBLE3; + char_flags[tolower_ascii(c4)] |= FLAG_POSSIBLE4; + + char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; + } + +#if 0 + DEBUG(10, ("char_flags\n")); + dump_data(10, char_flags, sizeof(char_flags)); + + DEBUG(10, ("base_reverse\n")); + dump_data(10, base_reverse, sizeof(base_reverse)); +#endif +} + +#else + +/* + * These tables were initialized by a single run of the above + * init_tables() routine, dumping the tables and a simple emacs macro. + * + * Technically we could leave out the 0's at the end of the array + * initializers, but I'll leave it in: less surprise. + */ + +static uint8_t char_flags[256] = { + 0x80, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x00, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x80, 0x04, + 0x03, 0x83, 0x83, 0x83, 0x83, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x00, 0x0C, 0x00, 0x0C, 0x0C, + 0x00, 0x13, 0x03, 0x53, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x83, 0x53, 0x43, 0x53, 0x23, + 0x33, 0x03, 0x23, 0x03, 0x43, 0x23, 0x03, 0x03, + 0x43, 0x03, 0x03, 0x00, 0x04, 0x00, 0x00, 0x02, + 0x00, 0x13, 0x03, 0x53, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x83, 0x53, 0x43, 0x53, 0x23, + 0x33, 0x03, 0x23, 0x03, 0x43, 0x23, 0x03, 0x03, + 0x43, 0x03, 0x03, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static uint8_t base_reverse[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#endif + /* hash a string of the specified length. The string does not need to be null terminated @@ -615,71 +791,6 @@ static bool hash2_name_to_8_3(const char *name, return True; } -/* initialise the flags table - - we allow only a very restricted set of characters as 'ascii' in this - mangling backend. This isn't a significant problem as modern clients - use the 'long' filenames anyway, and those don't have these - restrictions. -*/ -static void init_tables(void) -{ - int i; - - 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')) { - char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); - } - if (strchr("_-$~", i)) { - char_flags[i] |= FLAG_ASCII; - } - - if (strchr("*\\/?<>|\":", i)) { - char_flags[i] |= FLAG_ILLEGAL; - } - - if (strchr("*?\"<>", i)) { - char_flags[i] |= FLAG_WILDCARD; - } - } - - memset(base_reverse, 0, sizeof(base_reverse)); - for (i=0;i<36;i++) { - base_reverse[(unsigned char)base_forward(i)] = i; - } - - /* fill in the reserved names flags. These are used as a very - fast filter for finding possible DOS reserved filenames */ - for (i=0; reserved_names[i]; i++) { - unsigned char c1, c2, c3, c4; - - c1 = (unsigned char)reserved_names[i][0]; - c2 = (unsigned char)reserved_names[i][1]; - c3 = (unsigned char)reserved_names[i][2]; - c4 = (unsigned char)reserved_names[i][3]; - - char_flags[c1] |= FLAG_POSSIBLE1; - char_flags[c2] |= FLAG_POSSIBLE2; - char_flags[c3] |= FLAG_POSSIBLE3; - char_flags[c4] |= FLAG_POSSIBLE4; - char_flags[tolower_ascii(c1)] |= FLAG_POSSIBLE1; - char_flags[tolower_ascii(c2)] |= FLAG_POSSIBLE2; - char_flags[tolower_ascii(c3)] |= FLAG_POSSIBLE3; - char_flags[tolower_ascii(c4)] |= FLAG_POSSIBLE4; - - char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; - } -} - /* the following provides the abstraction layer to make it easier to drop in an alternative mangling implementation */ @@ -704,7 +815,9 @@ const struct mangle_fns *mangle_hash2_init(void) mangle_prefix = 1; } +#if DYNAMIC_MANGLE_TABLES init_tables(); +#endif mangle_reset(); return &mangle_hash2_fns; |