diff options
| -rw-r--r-- | source3/lib/util_unistr.c | 107 | ||||
| -rw-r--r-- | source3/smbd/mangle.c | 357 | 
2 files changed, 464 insertions, 0 deletions
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index d4c71ae13f..8248ac073c 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -280,6 +280,67 @@ int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)  } +/******************************************************************* +duplicate string +********************************************************************/ +smb_ucs2_t *strdup_w(const smb_ucs2_t *src) +{ +	smb_ucs2_t *dest; +	uint32 len; +	 +	len = strlen_w(src); +	dest = (smb_ucs2_t *)malloc((len+1)*sizeof(smb_ucs2_t)); +	if (!dest) { +		DEBUG(0,("strdup_w: out of memory!\n")); +		return NULL; +	} + +	memcpy(dest, src, (len+1)*sizeof(smb_ucs2_t)); +	 +	return dest; +} + +/******************************************************************* +copy a string with max len +********************************************************************/ + +smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) +{ +	size_t len; +	 +	if (!dest || !src) return NULL; +	 +	for (len = 0; (src[len] != 0) && (len < max); len++) +		dest[len] = src[len]; +	while (len < max) +		dest[len++] = 0; +	 +	return dest; +} + + +/******************************************************************* +append a string of len bytes and add a terminator +********************************************************************/ + +smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) +{	 +	size_t start; +	size_t len;	 +	 +	if (!dest || !src) return NULL; +	 +	start = strlen_w(dest); +	len = strlen_w(src); +	if (len > max) len = max; + +	memcpy(&dest[start], src, len);			 +	dest[start+len+1] = 0; +	 +	return dest; +} + +  /*    The *_wa() functions take a combination of 7 bit ascii    and wide characters They are used so that you can use string @@ -304,6 +365,8 @@ int strcmp_wa(const smb_ucs2_t *a, const char *b)  	return (*a - UCS2_CHAR(*b));  } + +  smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)  {  	while (*s != 0) { @@ -337,3 +400,47 @@ smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)  	return NULL;  } + +/******************************************************************* +copy a string with max len +********************************************************************/ + +smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max) +{ +	smb_ucs2_t *ucs2_src; + +	if (!dest || !src) return NULL; +	ucs2_src = (smb_ucs2_t *)malloc((strlen(src)+1)*sizeof(smb_ucs2_t)); +	if (!ucs2_src) { +		DEBUG(0,("strncpy_wa: out of memory!\n")); +		return NULL; +	} +	push_ucs2(NULL, ucs2_src, src, -1, STR_TERMINATE|STR_NOALIGN); +	 +	strncpy_w(dest, ucs2_src, max); +	SAFE_FREE(ucs2_src); +	return dest; +} + + +/******************************************************************* +append a string of len bytes and add a terminator +********************************************************************/ + +smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max) +{ +	smb_ucs2_t *ucs2_src; + +	if (!dest || !src) return NULL; +	ucs2_src = (smb_ucs2_t *)malloc((strlen(src)+1)*sizeof(smb_ucs2_t)); +	if (!ucs2_src) { +		DEBUG(0,("strncat_wa: out of memory!\n")); +		return NULL; +	} +	push_ucs2(NULL, ucs2_src, src, -1, STR_TERMINATE|STR_NOALIGN); +	 +	strncat_w(dest, ucs2_src, max); +	SAFE_FREE(ucs2_src); +	return dest; +} + diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 0e6689d9d2..0de2188bcf 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -965,3 +965,360 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)  	return(True);  } /* name_map_mangle */ + + + + +#if 0 + +#define MANGLE_TDB_VERSION		"20010830" +#define MANGLE_TDB_FILE_NAME		"mangle.tdb" +#define MANGLE_TDB_STORED_NAME		"B" +#define MANGLED_PREFIX			"MANGLED_" +#define LONG_PREFIX			"LONG_" + +struct mt_enum_info { +	TDB_CONTEXT	*mangle_tdb; +	TDB_DATA	key; +}; + + +static struct mt_enum_info	global_mt_ent = {0, 0}; + +static int POW10(unsigned int exp) +{ +	int result = 1; +	 +	while (exp) { +		result *= 10; +		exp--; +	} +   +	return result; +} + +static BOOL init_mangle_tdb(void) +{ +	pstring tdbfile; +	 +	if (global_mt_ent.mangle_tdb == 0) +	{ +		slprintf(tdbfile, sizeof(tdbfile)-1, "%s/%s", lp_private_dir(), MANGLE_TDB_FILE_NAME); + +		/* Open tdb */ +		if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) +		{ +			DEBUG(0, ("Unable to open Mangle TDB, trying create new!\n")); +			/* create a new one if it does not exist */ +			if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) +			{ +				DEBUG(0, ("Unable to create Mangle TDB (%s) !!!", tdbfile)); +				return False; +			} +		} +	} + +	return True; +} + +/* see push_ucs2 */ +int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, int flags) +{ +	int len=0; +	int src_len = strlen(src); +	pstring tmpbuf; + +	/* treat a pstring as "unlimited" length */ +	if (dest_len == -1) { +		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); +	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) +{ +	int 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; +	 +	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; +} + + + +/* the unicode string will be ZERO terminated */ +static smb_ucs2_t *unicode_from_buffer (uint8 *buf, uint32 size) +{ +	uint32 len = 0; +	uint32 lfn_len; +	smb_ucs2_t *long_file_name; +	 +	len = tdb_unpack (buf, size, MANGLE_TDB_STORED_NAME, +		&lfn_len, &long_file_name); + +	if (len == -1) return NULL; +	else return long_file_name; +} + +/* the unicode string MUST be ZERO terminated */ +static uint32 buffer_from_unicode (uint8 **buf, smb_ucs2_t *long_file_name) +{ +	uint32 buflen; +	uint32 len = 0; +	uint32 lfn_len = strlen_w(long_file_name)*sizeof(smb_ucs2_t)+1; +	 +	/* one time to get the size needed */ +	len = tdb_pack(NULL, 0,  MANGLE_TDB_STORED_NAME, +		lfn_len, long_file_name); + +	/* malloc the space needed */ +	if ((*buf=(uint8*)malloc(len)) == NULL) +	{ +		DEBUG(0,("buffer_from_longname: Unable to malloc() memory for buffer!\n")); +		return (-1); +	} +	 +	/* now for the real call to tdb_pack() */ +	buflen = tdb_pack(*buf, 0,  MANGLE_TDB_STORED_NAME, +		lfn_len, long_file_name); + +	/* check to make sure we got it correct */ +	if (buflen != len) +	{ +		/* error */ +		free (*buf); +		return (-1); +	} + +	return (buflen); +} + +/* 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 *retstr; +	smb_ucs2_t *temp; + +	if (strlen_w(mangled) > 12) return NULL; +	if (!strchr_wa(mangled, '~')) return NULL; +	if (!init_mangle_tdb()) return NULL; +	 +	temp = strdup_w(mangled); +	if (!temp) +	{ +		DEBUG(0,("mangle: out of memory!\n")); +		return NULL; +	} +	strupper_w(temp); +	/* set search key */ +	pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); +	SAFE_FREE(temp); +	slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); +	key.dptr = keystr; +	key.dsize = strlen (keystr) + 1; +	 +	/* get the record */ +	data = tdb_fetch(global_mt_ent.mangle_tdb, key); +	 +	if (!data.dptr) /* not found */ +	{ +		DEBUG(5,("unmangle: %s\n", tdb_errorstr(global_mt_ent.mangle_tdb))); +		return NULL; +	} +	 +	if (!(retstr = unicode_from_buffer (data.dptr, data.dsize))) +	{ +		DEBUG(0,("unmangle: bad buffer returned from database!\n")); +		SAFE_FREE(data.dptr); +		return NULL; +	} + +	SAFE_FREE(data.dptr); +	return retstr; +} + +/* unmangled must contain only the file name, not a path. +   and MUST be ZERO terminated */ +smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled) +{ +	TDB_DATA data, key; +	pstring keystr; +	pstring longname; +	fstring mufname; +	BOOL db_free = False; +	smb_ucs2_t *mangled; +	smb_ucs2_t *um; +	smb_ucs2_t *ext = NULL; +	smb_ucs2_t *p; +	size_t b_len; +	size_t e_len; +	size_t um_len; +	uint32 n, c; +			 + +	/* TODO: if it is a path return a failure */ +			 +	um = strdup_w(unmangled); +	if (!um) +	{ +		DEBUG(0,("mangle: out of memory!\n")); +		goto error; +	} +	um_len = strlen_w(um); +	if (p = strrchr_wa(um, '.')) +	{ +		if ((um_len - ((p - um) / sizeof(smb_ucs2_t))) < 4) /* check extension */ +		{ +			*p = UCS2_CHAR('\0'); +			ext = p++; +		} +	} + +	/* test if the same is yet mangled */ + +	/* set search key */ +	pull_ucs2(NULL, longname, um, 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 (global_mt_ent.mangle_tdb, key); +	if (!data.dptr) /* not found */ +	{ +		if (tdb_error(global_mt_ent.mangle_tdb) != TDB_ERR_NOEXIST) +		{ +			DEBUG(0, ("mangle: database retrieval error: %s\n", +					tdb_errorstr(global_mt_ent.mangle_tdb))); +			goto error; +		} +	 +		/* if not find the first free possibile mangled name */ +		n = c = 1; +		while (!db_free) +		{ +			uint32 pos; +			smb_ucs2_t temp[9]; +			char num[7]; +		 +			while ((int)POW10(n) <= c) n++; +			pos = 7 - n; +			if (pos == 0) goto error; + +			strncpy_w(temp, um, pos); +			strupper_w(temp); +			temp[pos] = UCS2_CHAR('~'); +			temp[pos+1] = 0; +			snprintf(num, 7, "%d", c); +			strncat_wa(temp, num, n); + +			pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE); +			if (strlen(mufname) > 8) +			{ +				n++; +				continue; +			} + +			slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname); +			key.dptr = keystr; +			key.dsize = strlen (keystr) + 1; +			if ((data.dsize=buffer_from_unicode ((uint8 **)(&data.dptr), temp)) == -1) +			{ +				DEBUG(0,("mangle: ERROR - Unable to copy mangled name info buffer!\n")); +				goto error; +			} + +			if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS) +			{ +				SAFE_FREE(data.dptr); +				if (tdb_error(global_mt_ent.mangle_tdb) == TDB_ERR_EXISTS) +				{ +					continue; +				} +				else +				{ +					DEBUG(0, ("mangle: database retrieval error: %s\n", +							tdb_errorstr(global_mt_ent.mangle_tdb))); +					goto error; +				} +			} +			else +			{ +				db_free = True; +				p = strdup_w(temp); +			} +			c++; +		} +	} +	else /* FOUND */ +	{ +		if (!(p = unicode_from_buffer (data.dptr, data.dsize))) +		{ +			DEBUG(0,("mangle: bad buffer returned from database!\n")); +			goto error; +		} +	} +		 +	b_len = strlen_w(p); +	if (ext) e_len = strlen_w(ext); +	else e_len = 0; +	mangled = (smb_ucs2_t *)malloc((b_len+e_len+2)*sizeof(smb_ucs2_t)); +	strncpy_w (mangled, p, b_len+1); +	strncat_w (mangled, ext, e_len); + +	SAFE_FREE(p); +	SAFE_FREE(um); +	SAFE_FREE(data.dptr); + +	return mangled; + +error: +	DEBUG(10, ("mangle: failed to mangle <string from unicode here>!\n")); +	SAFE_FREE(data.dptr); +	SAFE_FREE(um); +	return NULL; +} + +#endif /* 0 */  | 
