summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/mangle.c137
1 files changed, 83 insertions, 54 deletions
diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c
index 587e9cc906..386b948899 100644
--- a/source3/smbd/mangle.c
+++ b/source3/smbd/mangle.c
@@ -1008,11 +1008,11 @@ BOOL init_mangle_tdb(void)
return True;
}
-/* see push_ucs2 */
-int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, int flags)
+/* trasform a dos charset string in a terminated unicode string */
+static int dos_to_ucs2(void *dest, const char *src, int dest_len)
{
int len=0;
- int src_len = strlen(src);
+ int src_len = strlen(src) + 1;
pstring tmpbuf;
/* treat a pstring as "unlimited" length */
@@ -1020,55 +1020,62 @@ int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len,
dest_len = sizeof(pstring);
}
- if (flags & STR_UPPER) {
- pstrcpy(tmpbuf, src);
- strupper(tmpbuf);
- src = tmpbuf;
- }
-
- if (flags & STR_TERMINATE) {
- src_len++;
- }
-
- if (ucs2_align(base_ptr, dest, flags)) {
- *(char *)dest = 0;
- dest = (void *)((char *)dest + 1);
- if (dest_len) dest_len--;
- len++;
- }
-
/* ucs2 is always a multiple of 2 bytes */
dest_len &= ~1;
- len += convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len);
+ len = convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len);
return len;
}
-/* see pull_ucs2 */
-int ucs2_to_dos(const void *base_ptr, char *dest, const void *src, int dest_len, int src_len, int flags)
+/* trasform a unicode string into a dos charset string */
+static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len)
{
- int ret;
+ int src_len, ret;
if (dest_len == -1) {
dest_len = sizeof(pstring);
}
- if (ucs2_align(base_ptr, src, flags)) {
- src = (const void *)((char *)src + 1);
- if (src_len > 0) src_len--;
- }
-
- if (flags & STR_TERMINATE) src_len = strlen_w(src)*2+2;
-
- /* ucs2 is always a multiple of 2 bytes */
- src_len &= ~1;
+ src_len = strlen_w(src) * sizeof(smb_ucs2_t);
ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len);
if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
- return src_len;
+ return ret;
+}
+
+/* trasform a ucs2 string in a dos charset string that contain only valid chars for 8.3 filenames */
+static int ucs2_to_dos83(char *dest, const smb_ucs2_t *src, int dest_len)
+{
+ int src_len, u2s_len, ret;
+ smb_ucs2_t *u2s;
+
+ u2s = (smb_ucs2_t *)malloc((strlen_w(src) + 1) * sizeof(smb_ucs2_t));
+ if (!u2s) {
+ DEBUG(0, ("ucs2_to_dos83: out of memory!\n"));
+ return 0;
+ }
+
+ src_len = strlen_w(src);
+
+ u2s[src_len] = 0;
+ while (src_len--)
+ {
+ smb_ucs2_t c;
+
+ c = src[src_len];
+ if (isvalid83_w(c)) u2s[src_len] = c;
+ else u2s[src_len] = UCS2_CHAR('_');
+ }
+
+ ret = ucs2_to_dos(dest, u2s, dest_len);
+
+ SAFE_FREE(u2s);
+
+ return ret;
}
+
/* return False if something fail and
* return 2 alloced unicode strings that contain prefix and extension
*/
@@ -1076,6 +1083,7 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix
{
size_t str_len;
smb_ucs2_t *p;
+ fstring ext;
*extension = 0;
*prefix = strdup_w(ucs2_string);
@@ -1084,14 +1092,13 @@ static BOOL mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix
DEBUG(0,("mangle_get_prefix: out of memory!\n"));
return False;
}
- str_len = strlen_w(*prefix);
if (p = strrchr_wa(*prefix, '.'))
{
- /* TODO: check it is <4 in dos charset */
- if ((str_len - ((p - *prefix) / sizeof(smb_ucs2_t))) < 4) /* check extension */
+ p++;
+ str_len = ucs2_to_dos83(ext, p, sizeof(ext));
+ if (str_len > 0 && str_len < 4) /* check extension */
{
- *p = 0;
- p++;
+ *(p - 1) = 0;
*extension = strdup_w(p);
if (!*extension)
{
@@ -1114,7 +1121,7 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
fstring keystr;
fstring mufname;
smb_ucs2_t *pref, *ext, *retstr;
- size_t long_len, ext_len;
+ size_t long_len, ext_len, muf_len;
BOOL ret;
if (strlen_w(mangled) > 12) return NULL;
@@ -1126,8 +1133,10 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
/* TODO: get out extension */
strlower_w(pref);
/* set search key */
- ucs2_to_dos(NULL, mufname, pref, sizeof(mufname), 0, STR_TERMINATE);
+ muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname));
SAFE_FREE(pref);
+ if (!muf_len) return NULL;
+
slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
@@ -1144,9 +1153,9 @@ smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
if (ext)
{
- long_len = data.dsize / 2; /* terminator counted on purpose, will contain '.' */
+ long_len = (data.dsize / 2) - 1;
ext_len = strlen_w(ext);
- retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 1)*sizeof(smb_ucs2_t));
+ retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t));
if (!retstr)
{
DEBUG(0, ("unamngle: out of memory!\n"));
@@ -1190,8 +1199,8 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled)
char suffix[7];
smb_ucs2_t *mangled = NULL;
smb_ucs2_t *um, *ext, *p = NULL;
- smb_ucs2_t temp[8];
- size_t pref_len, ext_len;
+ smb_ucs2_t temp[9];
+ size_t pref_len, ext_len, ud83_len;
size_t um_len;
uint32 n, c, pos;
@@ -1233,9 +1242,10 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled)
temp[pos] = 0;
strlower_w(temp);
- ucs2_to_dos(NULL, prefix, temp, sizeof(prefix), 0, STR_TERMINATE);
+ ud83_len = ucs2_to_dos83(prefix, temp, sizeof(prefix));
+ if (!ud83_len) goto done;
}
- while (strlen(prefix) > 8 - (MANGLE_SUFFIX_SIZE + 1));
+ while (ud83_len > 8 - (MANGLE_SUFFIX_SIZE + 1));
slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix);
klock.dptr = keylock;
@@ -1285,11 +1295,11 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled)
temp[pos] = UCS2_CHAR('~');
temp[pos+1] = 0;
snprintf(suffix, 7, "%.6d", c);
- printf("[%s]\n", suffix);
strncat_wa(temp, &suffix[6 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE + 1);
- ucs2_to_dos(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE);
- if (strlen(mufname) > 8)
+ ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname));
+ if (!ud83_len) goto done;
+ if (ud83_len > 8)
{
DEBUG(0, ("mangle: darn, logic error aborting!\n"));
goto done;
@@ -1314,7 +1324,7 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled)
slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
- data.dsize = strlen(mufname +1);
+ data.dsize = strlen(mufname) + 1;
data.dptr = mufname;
if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
{
@@ -1375,14 +1385,14 @@ smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled)
DEBUG(0,("mangle: out of memory!\n"));
goto done;
}
- dos_to_ucs2(NULL, p, data.dptr, data.dsize*sizeof(smb_ucs2_t), STR_TERMINATE);
+ dos_to_ucs2(p, data.dptr, data.dsize*sizeof(smb_ucs2_t));
}
if (ext)
{
- pref_len = strlen_w(p) + 1; /* terminator counted on purpose, will contain '.' */
+ pref_len = strlen_w(p);
ext_len = strlen_w(ext);
- mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 1)*sizeof(smb_ucs2_t));
+ mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t));
if (!mangled)
{
DEBUG(0,("mangle: out of memory!\n"));
@@ -1424,6 +1434,7 @@ done:
#define EXT2 "e2"
#define EXT3 "3"
#define EXTFAIL "longext"
+#define EXTNULL ""
static void unmangle_test (char *name, char *ext)
{
@@ -1470,79 +1481,97 @@ void mangle_test_code(void)
init_mangle_tdb();
/* unmangle every */
+ printf("Unmangle test 1:\n");
+
unmangle_test (LONG, NULL);
unmangle_test (LONG, EXT1);
unmangle_test (LONG, EXT2);
unmangle_test (LONG, EXT3);
unmangle_test (LONG, EXTFAIL);
+ unmangle_test (LONG, EXTNULL);
unmangle_test (LONGM, NULL);
unmangle_test (LONGM, EXT1);
unmangle_test (LONGM, EXT2);
unmangle_test (LONGM, EXT3);
unmangle_test (LONGM, EXTFAIL);
+ unmangle_test (LONGM, EXTNULL);
unmangle_test (SHORT, NULL);
unmangle_test (SHORT, EXT1);
unmangle_test (SHORT, EXT2);
unmangle_test (SHORT, EXT3);
unmangle_test (SHORT, EXTFAIL);
+ unmangle_test (SHORT, EXTNULL);
unmangle_test (SHORTM, NULL);
unmangle_test (SHORTM, EXT1);
unmangle_test (SHORTM, EXT2);
unmangle_test (SHORTM, EXT3);
unmangle_test (SHORTM, EXTFAIL);
+ unmangle_test (SHORTM, EXTNULL);
/* mangle every */
+ printf("Mangle test\n");
+
mangle_test (LONG, NULL);
mangle_test (LONG, EXT1);
mangle_test (LONG, EXT2);
mangle_test (LONG, EXT3);
mangle_test (LONG, EXTFAIL);
+ mangle_test (LONG, EXTNULL);
mangle_test (LONGM, NULL);
mangle_test (LONGM, EXT1);
mangle_test (LONGM, EXT2);
mangle_test (LONGM, EXT3);
mangle_test (LONGM, EXTFAIL);
+ mangle_test (LONGM, EXTNULL);
mangle_test (SHORT, NULL);
mangle_test (SHORT, EXT1);
mangle_test (SHORT, EXT2);
mangle_test (SHORT, EXT3);
mangle_test (SHORT, EXTFAIL);
+ mangle_test (SHORT, EXTNULL);
mangle_test (SHORTM, NULL);
mangle_test (SHORTM, EXT1);
mangle_test (SHORTM, EXT2);
mangle_test (SHORTM, EXT3);
mangle_test (SHORTM, EXTFAIL);
+ mangle_test (SHORTM, EXTNULL);
/* unmangle again every */
+ printf("Unmangle test 2:\n");
+
unmangle_test (LONG, NULL);
unmangle_test (LONG, EXT1);
unmangle_test (LONG, EXT2);
unmangle_test (LONG, EXT3);
unmangle_test (LONG, EXTFAIL);
+ unmangle_test (LONG, EXTNULL);
unmangle_test (LONGM, NULL);
unmangle_test (LONGM, EXT1);
unmangle_test (LONGM, EXT2);
unmangle_test (LONGM, EXT3);
unmangle_test (LONGM, EXTFAIL);
+ unmangle_test (LONGM, EXTNULL);
unmangle_test (SHORT, NULL);
unmangle_test (SHORT, EXT1);
unmangle_test (SHORT, EXT2);
unmangle_test (SHORT, EXT3);
unmangle_test (SHORT, EXTFAIL);
+ unmangle_test (SHORT, EXTNULL);
unmangle_test (SHORTM, NULL);
unmangle_test (SHORTM, EXT1);
unmangle_test (SHORTM, EXT2);
unmangle_test (SHORTM, EXT3);
unmangle_test (SHORTM, EXTFAIL);
+ unmangle_test (SHORTM, EXTNULL);
}
#endif /* TEST_MANGLE_CODE */