mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
0ebb29e032
(This used to be commit ad7afbfdea
)
968 lines
22 KiB
C
968 lines
22 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 3.0
|
|
Name mangling with persistent tdb
|
|
Copyright (C) Simo Sorce 2001
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
/****************************************************************************
|
|
Rewritten from scrach in 2001 by Simo Sorce <idra@samba.org>
|
|
****************************************************************************/
|
|
|
|
#include "includes.h"
|
|
|
|
|
|
/* -------------------------------------------------------------------------- **
|
|
* External Variables...
|
|
*/
|
|
|
|
extern int case_default; /* Are conforming 8.3 names all upper or lower? */
|
|
extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
|
|
|
|
char magic_char = '~';
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
#define MANGLE_TDB_VERSION "20010927"
|
|
#define MANGLE_TDB_FILE_NAME "mangle.tdb"
|
|
#define MANGLED_PREFIX "MANGLED_"
|
|
#define LONG_PREFIX "LONG_"
|
|
#define COUNTER_PREFIX "COUNTER_"
|
|
#define MANGLE_COUNTER_MAX 99
|
|
#define MANGLE_SUFFIX_SIZE 3 /* "~XX" */
|
|
|
|
|
|
static TDB_CONTEXT *mangle_tdb;
|
|
|
|
BOOL init_mangle_tdb(void)
|
|
{
|
|
char *tdbfile;
|
|
|
|
tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */
|
|
|
|
/* Open tdb */
|
|
if (!(mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
|
|
{
|
|
DEBUG(0, ("Unable to open Mangle TDB\n"));
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/* 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 src_len, ret;
|
|
|
|
if (dest_len == -1) {
|
|
dest_len = sizeof(pstring);
|
|
}
|
|
|
|
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 ret;
|
|
}
|
|
|
|
/* trasform in a string that contain only valid chars for win filenames */
|
|
static void strvalid(smb_ucs2_t *src)
|
|
{
|
|
if (!src || !*src) return;
|
|
|
|
while (*src) {
|
|
if (!isvalid83_w(*src)) *src = UCS2_CHAR('_');
|
|
src++;
|
|
}
|
|
}
|
|
|
|
|
|
/* return False if something fail and
|
|
* return 2 alloced unicode strings that contain prefix and extension
|
|
*/
|
|
static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension)
|
|
{
|
|
size_t ext_len;
|
|
smb_ucs2_t *p;
|
|
|
|
*extension = 0;
|
|
*prefix = strdup_w(ucs2_string);
|
|
if (!*prefix)
|
|
{
|
|
DEBUG(0,("mangle_get_prefix: out of memory!\n"));
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
if ((p = strrchr_w(*prefix, UCS2_CHAR('.'))))
|
|
{
|
|
p++;
|
|
ext_len = strlen_w(p);
|
|
if ((ext_len > 0) && (ext_len < 4)
|
|
&& (NT_STATUS_IS_OK(has_valid_chars(p)))) /* check extension */
|
|
{
|
|
*(p - 1) = 0;
|
|
*extension = strdup_w(p);
|
|
if (!*extension)
|
|
{
|
|
DEBUG(0,("mangle_get_prefix: out of memory!\n"));
|
|
SAFE_FREE(*prefix);
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
|
|
/* mangled must contain only the file name, not a path.
|
|
and MUST be ZERO terminated */
|
|
smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
|
|
{
|
|
TDB_DATA data, key;
|
|
fstring keystr;
|
|
fstring mufname;
|
|
smb_ucs2_t *pref, *ext, *retstr;
|
|
size_t long_len, ext_len, muf_len;
|
|
|
|
if (strlen_w(mangled) > 12) return NULL;
|
|
if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL;
|
|
|
|
/* if it is a path refuse to proceed */
|
|
if (strchr_w(mangled, UCS2_CHAR('/'))) {
|
|
DEBUG(10, ("unmangle: cannot unmangle a path\n"));
|
|
return NULL;
|
|
}
|
|
|
|
if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext)))
|
|
return NULL;
|
|
|
|
/* mangled names are stored lowercase only */
|
|
strlower_w(pref);
|
|
/* set search key */
|
|
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;
|
|
|
|
/* get the record */
|
|
data = tdb_fetch(mangle_tdb, key);
|
|
|
|
if (!data.dptr) /* not found */
|
|
{
|
|
DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(mangle_tdb)));
|
|
retstr = NULL;
|
|
goto done;
|
|
}
|
|
|
|
if (ext)
|
|
{
|
|
long_len = (data.dsize / 2) - 1;
|
|
ext_len = strlen_w(ext);
|
|
retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t));
|
|
if (!retstr)
|
|
{
|
|
DEBUG(0, ("unamngle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
strncpy_w(retstr, (smb_ucs2_t *)data.dptr, long_len);
|
|
retstr[long_len] = UCS2_CHAR('.');
|
|
retstr[long_len + 1] = 0;
|
|
strncat_w(retstr, ext, ext_len);
|
|
}
|
|
else
|
|
{
|
|
retstr = strdup_w((smb_ucs2_t *)data.dptr);
|
|
if (!retstr)
|
|
{
|
|
DEBUG(0, ("unamngle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
|
|
done:
|
|
SAFE_FREE(data.dptr);
|
|
SAFE_FREE(pref);
|
|
SAFE_FREE(ext);
|
|
|
|
return retstr;
|
|
}
|
|
|
|
/* unmangled must contain only the file name, not a path.
|
|
and MUST be ZERO terminated.
|
|
return a new allocated string if the name is yet valid 8.3
|
|
or is mangled successfully.
|
|
return null on error.
|
|
*/
|
|
|
|
smb_ucs2_t *mangle(const smb_ucs2_t *unmangled)
|
|
{
|
|
TDB_DATA data, key, klock;
|
|
pstring keystr;
|
|
pstring longname;
|
|
fstring keylock;
|
|
fstring mufname;
|
|
fstring prefix;
|
|
BOOL tclock = False;
|
|
char suffix[7];
|
|
smb_ucs2_t *mangled = NULL;
|
|
smb_ucs2_t *umpref, *ext, *p = NULL;
|
|
size_t pref_len, ext_len, ud83_len;
|
|
|
|
/* if it is a path refuse to proceed */
|
|
if (strchr_w(unmangled, UCS2_CHAR('/'))) {
|
|
DEBUG(10, ("mangle: cannot mangle a path\n"));
|
|
return NULL;
|
|
}
|
|
|
|
/* if it is a valid 8_3 do not mangle again */
|
|
if (NT_STATUS_IS_OK(is_8_3_w(unmangled)))
|
|
return NULL;
|
|
|
|
if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext)))
|
|
return NULL;
|
|
|
|
/* test if the same is yet mangled */
|
|
|
|
/* set search key */
|
|
pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
|
|
slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
|
|
key.dptr = keystr;
|
|
key.dsize = strlen(keystr) + 1;
|
|
|
|
/* get the record */
|
|
data = tdb_fetch (mangle_tdb, key);
|
|
if (!data.dptr) /* not found */
|
|
{
|
|
smb_ucs2_t temp[9];
|
|
size_t c, pos;
|
|
|
|
if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST)
|
|
{
|
|
DEBUG(0, ("mangle: database retrieval error: %s\n",
|
|
tdb_errorstr(mangle_tdb)));
|
|
goto done;
|
|
}
|
|
|
|
/* if not find the first free possibile mangled name */
|
|
|
|
pos = strlen_w(umpref);
|
|
if ((8 - MANGLE_SUFFIX_SIZE) < pos)
|
|
pos = 8 - MANGLE_SUFFIX_SIZE;
|
|
pos++;
|
|
do
|
|
{
|
|
pos--;
|
|
if (pos == 0)
|
|
{
|
|
DEBUG(0, ("mangle: unable to mangle file name!\n"));
|
|
goto done;
|
|
}
|
|
strncpy_w(temp, umpref, pos);
|
|
temp[pos] = 0;
|
|
strlower_w(temp);
|
|
|
|
/* convert any invalid char into '_' */
|
|
strvalid(temp);
|
|
ud83_len = ucs2_to_dos(prefix, temp, sizeof(prefix));
|
|
if (!ud83_len) goto done;
|
|
}
|
|
while (ud83_len > 8 - MANGLE_SUFFIX_SIZE);
|
|
|
|
slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix);
|
|
klock.dptr = keylock;
|
|
klock.dsize = strlen(keylock) + 1;
|
|
|
|
c = 0;
|
|
data.dptr = (char *)&c;
|
|
data.dsize = sizeof(uint32);
|
|
/* try to insert a new counter prefix, if it exist the call will
|
|
fail (correct) otherwise it will create a new entry with counter set
|
|
to 0
|
|
*/
|
|
if(tdb_store(mangle_tdb, klock, data, TDB_INSERT) != TDB_SUCCESS)
|
|
{
|
|
if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS)
|
|
{
|
|
DEBUG(0, ("mangle: database store error: %s\n",
|
|
tdb_errorstr(mangle_tdb)));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* lock the mangle counter for this prefix */
|
|
if (tdb_chainlock(mangle_tdb, klock))
|
|
{
|
|
DEBUG(0,("mangle: failed to lock database\n!"));
|
|
goto done;
|
|
}
|
|
tclock = True;
|
|
|
|
data = tdb_fetch(mangle_tdb, klock);
|
|
if (!data.dptr)
|
|
{
|
|
DEBUG(0, ("mangle: database retrieval error: %s\n",
|
|
tdb_errorstr(mangle_tdb)));
|
|
goto done;
|
|
}
|
|
c = *((uint32 *)data.dptr);
|
|
c++;
|
|
|
|
if (c > MANGLE_COUNTER_MAX)
|
|
{
|
|
DEBUG(0, ("mangle: error, counter overflow!\n"));
|
|
goto done;
|
|
}
|
|
|
|
temp[pos] = UCS2_CHAR('~');
|
|
temp[pos+1] = 0;
|
|
snprintf(suffix, 7, "%.6d", c);
|
|
strncat_wa(temp, &suffix[7 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE);
|
|
|
|
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;
|
|
}
|
|
|
|
/* store the long entry with mangled key */
|
|
slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
|
|
key.dptr = keystr;
|
|
key.dsize = strlen (keystr) + 1;
|
|
data.dsize = (strlen_w(umpref) + 1) * sizeof (smb_ucs2_t);
|
|
data.dptr = (void *)umpref;
|
|
|
|
if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
|
|
{
|
|
DEBUG(0, ("mangle: database store error: %s\n",
|
|
tdb_errorstr(mangle_tdb)));
|
|
goto done;
|
|
}
|
|
|
|
/* store the mangled entry with long key*/
|
|
pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
|
|
slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
|
|
key.dptr = keystr;
|
|
key.dsize = strlen (keystr) + 1;
|
|
data.dsize = strlen(mufname) + 1;
|
|
data.dptr = mufname;
|
|
if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
|
|
{
|
|
DEBUG(0, ("mangle: database store failed: %s\n",
|
|
tdb_errorstr(mangle_tdb)));
|
|
|
|
/* try to delete the mangled key entry to avoid later inconsistency */
|
|
slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
|
|
key.dptr = keystr;
|
|
key.dsize = strlen (keystr) + 1;
|
|
if (!tdb_delete(mangle_tdb, key))
|
|
{
|
|
DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
p = strdup_w(temp);
|
|
if (!p)
|
|
{
|
|
DEBUG(0,("mangle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
|
|
data.dptr = (char *)&c;
|
|
data.dsize = sizeof(uint32);
|
|
/* store the counter */
|
|
if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS)
|
|
{
|
|
DEBUG(0, ("mangle: database store failed: %s\n",
|
|
tdb_errorstr(mangle_tdb)));
|
|
/* try to delete the mangled and long key entry to avoid later inconsistency */
|
|
slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
|
|
key.dptr = keystr;
|
|
key.dsize = strlen (keystr) + 1;
|
|
if (!tdb_delete(mangle_tdb, key))
|
|
{
|
|
DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
|
|
}
|
|
slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
|
|
key.dptr = keystr;
|
|
key.dsize = strlen (keystr) + 1;
|
|
if (!tdb_delete(mangle_tdb, key))
|
|
{
|
|
DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
tclock = False;
|
|
tdb_chainunlock(mangle_tdb, klock);
|
|
}
|
|
else /* FOUND */
|
|
{
|
|
p = acnv_dosu2(data.dptr);
|
|
if (!p)
|
|
{
|
|
DEBUG(0,("mangle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (ext)
|
|
{
|
|
pref_len = strlen_w(p);
|
|
ext_len = strlen_w(ext);
|
|
mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t));
|
|
if (!mangled)
|
|
{
|
|
DEBUG(0,("mangle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
strncpy_w (mangled, p, pref_len);
|
|
mangled[pref_len] = UCS2_CHAR('.');
|
|
mangled[pref_len + 1] = 0;
|
|
strncat_w (mangled, ext, ext_len);
|
|
}
|
|
else
|
|
{
|
|
mangled = strdup_w(p);
|
|
if (!mangled)
|
|
{
|
|
DEBUG(0,("mangle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* mangled name are returned in upper or lower case depending on
|
|
case_default value */
|
|
strnorm_w(mangled);
|
|
|
|
done:
|
|
if (tclock) tdb_chainunlock(mangle_tdb, klock);
|
|
SAFE_FREE(p);
|
|
SAFE_FREE(umpref);
|
|
SAFE_FREE(ext);
|
|
|
|
return mangled;
|
|
}
|
|
|
|
|
|
/* non unicode compatibility functions */
|
|
|
|
char *dos_mangle(const char *dos_unmangled)
|
|
{
|
|
smb_ucs2_t *in, *out;
|
|
char *dos_mangled;
|
|
|
|
if (!dos_unmangled || !*dos_unmangled) return NULL;
|
|
|
|
in = acnv_dosu2(dos_unmangled);
|
|
if (!in)
|
|
{
|
|
DEBUG(0,("dos_mangle: out of memory!\n"));
|
|
return NULL;
|
|
}
|
|
|
|
out = mangle(in);
|
|
if (!out)
|
|
{
|
|
SAFE_FREE(in);
|
|
return NULL;
|
|
}
|
|
|
|
dos_mangled = acnv_u2dos(out);
|
|
if (!dos_mangled)
|
|
{
|
|
DEBUG(0,("dos_mangle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
SAFE_FREE(in);
|
|
SAFE_FREE(out);
|
|
return dos_mangled;
|
|
}
|
|
|
|
char *dos_unmangle(const char *dos_mangled)
|
|
{
|
|
smb_ucs2_t *in, *out;
|
|
char *dos_unmangled;
|
|
|
|
if (!dos_mangled || !*dos_mangled) return NULL;
|
|
|
|
in = acnv_dosu2(dos_mangled);
|
|
if (!in)
|
|
{
|
|
DEBUG(0,("dos_unmangle: out of memory!\n"));
|
|
return NULL;
|
|
}
|
|
|
|
out = mangle(in);
|
|
if (!out)
|
|
{
|
|
SAFE_FREE(in);
|
|
return NULL;
|
|
}
|
|
|
|
dos_unmangled = acnv_u2dos(out);
|
|
if (!dos_unmangled)
|
|
{
|
|
DEBUG(0,("dos_unmangle: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
SAFE_FREE(in);
|
|
SAFE_FREE(out);
|
|
return dos_unmangled;
|
|
}
|
|
|
|
BOOL is_8_3(const char *fname, BOOL check_case)
|
|
{
|
|
smb_ucs2_t *ucs2name;
|
|
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
|
|
|
if (!fname || !*fname) return False;
|
|
|
|
DEBUG(10,("is_8_3: testing [%s]\n", fname));
|
|
|
|
if (strlen(fname) > 12) return False;
|
|
|
|
ucs2name = acnv_uxu2(fname);
|
|
if (!ucs2name)
|
|
{
|
|
DEBUG(0,("is_8_3: out of memory!\n"));
|
|
goto done;
|
|
}
|
|
|
|
ret = is_8_3_w(ucs2name);
|
|
|
|
done:
|
|
SAFE_FREE(ucs2name);
|
|
|
|
DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False"));
|
|
|
|
if (NT_STATUS_IS_ERR(ret)) return False;
|
|
else return True;
|
|
}
|
|
|
|
NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
|
|
{
|
|
smb_ucs2_t *pref = 0, *ext = 0;
|
|
size_t plen;
|
|
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
|
|
|
if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
|
|
|
|
DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */
|
|
|
|
if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
|
|
|
|
if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
|
|
return NT_STATUS_OK;
|
|
|
|
if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
|
|
|
|
if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
|
|
plen = strlen_w(pref);
|
|
if (plen < 1 || plen > 8) goto done;
|
|
if (ext) if (strlen_w(ext) > 3) goto done;
|
|
|
|
ret = NT_STATUS_OK;
|
|
|
|
done:
|
|
SAFE_FREE(pref);
|
|
SAFE_FREE(ext);
|
|
return ret;
|
|
}
|
|
|
|
NTSTATUS has_valid_chars(const smb_ucs2_t *s)
|
|
{
|
|
NTSTATUS ret = NT_STATUS_OK;
|
|
|
|
if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
|
|
|
|
DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
|
|
|
|
/* CHECK: this should not be necessary if the ms wild chars
|
|
are not valid in valid.dat --- simo */
|
|
if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
|
|
|
|
while (*s) {
|
|
if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
|
|
s++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
NTSTATUS is_valid_name(const smb_ucs2_t *fname)
|
|
{
|
|
smb_ucs2_t *str, *p;
|
|
NTSTATUS ret = NT_STATUS_OK;
|
|
|
|
if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
|
|
|
|
DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */
|
|
|
|
ret = has_valid_chars(fname);
|
|
if (NT_STATUS_IS_ERR(ret)) return ret;
|
|
|
|
str = strdup_w(fname);
|
|
p = strchr_w(str, UCS2_CHAR('.'));
|
|
if (p) *p = 0;
|
|
strupper_w(str);
|
|
p = &(str[1]);
|
|
|
|
switch(str[0])
|
|
{
|
|
case UCS2_CHAR('A'):
|
|
if(strcmp_wa(p, "UX") == 0)
|
|
ret = NT_STATUS_UNSUCCESSFUL;
|
|
break;
|
|
case UCS2_CHAR('C'):
|
|
if((strcmp_wa(p, "LOCK$") == 0)
|
|
|| (strcmp_wa(p, "ON") == 0)
|
|
|| (strcmp_wa(p, "OM1") == 0)
|
|
|| (strcmp_wa(p, "OM2") == 0)
|
|
|| (strcmp_wa(p, "OM3") == 0)
|
|
|| (strcmp_wa(p, "OM4") == 0)
|
|
)
|
|
ret = NT_STATUS_UNSUCCESSFUL;
|
|
break;
|
|
case UCS2_CHAR('L'):
|
|
if((strcmp_wa(p, "PT1") == 0)
|
|
|| (strcmp_wa(p, "PT2") == 0)
|
|
|| (strcmp_wa(p, "PT3") == 0)
|
|
)
|
|
ret = NT_STATUS_UNSUCCESSFUL;
|
|
break;
|
|
case UCS2_CHAR('N'):
|
|
if(strcmp_wa(p, "UL") == 0)
|
|
ret = NT_STATUS_UNSUCCESSFUL;
|
|
break;
|
|
case UCS2_CHAR('P'):
|
|
if(strcmp_wa(p, "RN") == 0)
|
|
ret = NT_STATUS_UNSUCCESSFUL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
SAFE_FREE(str);
|
|
return ret;
|
|
}
|
|
|
|
BOOL is_mangled(const char *s)
|
|
{
|
|
smb_ucs2_t *u2, *res;
|
|
BOOL ret = False;
|
|
|
|
DEBUG(10,("is_mangled: testing [%s]\n", s));
|
|
|
|
if (!s || !*s) return False;
|
|
if ((strlen(s) > 12) || (!strchr(s, '~'))) return False;
|
|
|
|
u2 = acnv_dosu2(s);
|
|
if (!u2)
|
|
{
|
|
DEBUG(0,("is_mangled: out of memory!\n"));
|
|
return ret;
|
|
}
|
|
|
|
res = unmangle(u2);
|
|
if (res) ret = True;
|
|
SAFE_FREE(res);
|
|
SAFE_FREE(u2);
|
|
DEBUG(10,("is_mangled: returning [%s]\n", ret?"True":"False"));
|
|
return ret;
|
|
}
|
|
|
|
NTSTATUS is_mangled_w(const smb_ucs2_t *s)
|
|
{
|
|
smb_ucs2_t *res;
|
|
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
|
|
|
res = unmangle(s);
|
|
if (res) ret = NT_STATUS_OK;
|
|
SAFE_FREE(res);
|
|
return ret;
|
|
}
|
|
|
|
NTSTATUS path_has_mangled(const smb_ucs2_t *s)
|
|
{
|
|
smb_ucs2_t *p, *f, *b;
|
|
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
|
|
|
if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
|
|
|
|
p = strdup_w(s);
|
|
if (!p) return NT_STATUS_NO_MEMORY;
|
|
trim_string_wa(p, "/", "/");
|
|
f = b = p;
|
|
while (b) {
|
|
b = strchr_w(f, UCS2_CHAR('/'));
|
|
if (b) *b = 0;
|
|
if (NT_STATUS_IS_OK(is_mangled_w(f))) {
|
|
ret = NT_STATUS_OK;
|
|
goto done;
|
|
}
|
|
f = b + 1;
|
|
}
|
|
done:
|
|
SAFE_FREE(p);
|
|
return ret;
|
|
}
|
|
|
|
/* backward compatibility functions */
|
|
|
|
void reset_mangled_cache(void)
|
|
{
|
|
DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n"));
|
|
}
|
|
|
|
BOOL check_mangled_cache(char *s)
|
|
{
|
|
smb_ucs2_t *u2, *res;
|
|
BOOL ret = False;
|
|
|
|
DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n"));
|
|
DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s));
|
|
|
|
if (!s || !*s) return False;
|
|
|
|
u2 = acnv_dosu2(s);
|
|
if (!u2)
|
|
{
|
|
DEBUG(0,("check_mangled_cache: out of memory!\n"));
|
|
return ret;
|
|
}
|
|
|
|
res = unmangle(u2);
|
|
if (res)
|
|
{
|
|
|
|
ucs2_to_dos (s, res, PSTRING_LEN);
|
|
/* We MUST change this brainded interface,
|
|
we do not know how many chars will be used
|
|
in dos so i guess they will be no more than
|
|
double the size of the unicode string
|
|
---simo */
|
|
DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s));
|
|
ret = True;
|
|
}
|
|
SAFE_FREE(res);
|
|
SAFE_FREE(u2);
|
|
DEBUG(10,("check_mangled_cache: returning -> %s\n", ret?"True":"False"));
|
|
return ret;
|
|
}
|
|
|
|
void mangle_name_83(char *s)
|
|
{
|
|
smb_ucs2_t *u2, *res;
|
|
|
|
DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n"));
|
|
DEBUG(10,("mangle_name_83: testing -> [%s]\n", s));
|
|
|
|
if (!s || !*s) return;
|
|
|
|
u2 = acnv_dosu2(s);
|
|
if (!u2)
|
|
{
|
|
DEBUG(0,("mangle_name_83: out of memory!\n"));
|
|
return;
|
|
}
|
|
|
|
res = mangle(u2);
|
|
if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */
|
|
DEBUG(10,("mangle_name_83: returning -> [%s]\n", s));
|
|
SAFE_FREE(res);
|
|
SAFE_FREE(u2);
|
|
}
|
|
|
|
BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
|
|
{
|
|
DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n"));
|
|
|
|
if (!need83) return True;
|
|
/* if (is_8_3(OutName, True)) return True; */
|
|
/* Warning: we should check for invalid chars in file name and mangle
|
|
if invalid chars found --simo*/
|
|
|
|
mangle_name_83(OutName);
|
|
return True;
|
|
}
|
|
|
|
|
|
|
|
#if 0 /* TEST_MANGLE_CODE */
|
|
|
|
#define LONG "this_is_a_long_file_name"
|
|
#define LONGM "this_~01"
|
|
#define SHORT "short"
|
|
#define SHORTM "short~01"
|
|
#define EXT1 "ex1"
|
|
#define EXT2 "e2"
|
|
#define EXT3 "3"
|
|
#define EXTFAIL "longext"
|
|
#define EXTNULL ""
|
|
|
|
static void unmangle_test (char *name, char *ext)
|
|
{
|
|
smb_ucs2_t ucs2_name[2048];
|
|
smb_ucs2_t *retstr;
|
|
pstring unix_name;
|
|
|
|
push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
|
|
if (ext)
|
|
{
|
|
strncat_wa(ucs2_name, ".", 1);
|
|
strncat_wa(ucs2_name, ext, strlen(ext) + 1);
|
|
}
|
|
retstr = unmangle(ucs2_name);
|
|
if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
|
|
else unix_name[0] = 0;
|
|
if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
|
|
else printf ("[%s] ---> [%s]\n", name, unix_name);
|
|
SAFE_FREE(retstr);
|
|
}
|
|
|
|
static void mangle_test (char *name, char *ext)
|
|
{
|
|
smb_ucs2_t ucs2_name[2048];
|
|
smb_ucs2_t *retstr;
|
|
pstring unix_name;
|
|
|
|
push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
|
|
if (ext)
|
|
{
|
|
strncat_wa(ucs2_name, ".", 1);
|
|
strncat_wa(ucs2_name, ext, strlen(ext) + 1);
|
|
}
|
|
retstr = mangle(ucs2_name);
|
|
if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
|
|
else unix_name[0] = 0;
|
|
if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
|
|
else printf ("[%s] ---> [%s]\n", name, unix_name);
|
|
SAFE_FREE(retstr);
|
|
}
|
|
|
|
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 */
|