1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-14 00:58:38 +03:00

r23858: Added srvstr_pull_buf_talloc() and srvstr_pull_talloc()

calls and converted reply_tcon and reply_tconX to use
them - to show the boilerplate usage (valgrind tested).
In conjunction with Volker's srvstr_get_path_talloc()
work this should allow us to start eliminating all
pstrings/fstrings out of the main path processing
code.
I'll watch the build farm tonight...
Jeremy.
This commit is contained in:
Jeremy Allison 2007-07-13 01:22:09 +00:00 committed by Gerald (Jerry) Carter
parent 6ba12b6cb9
commit b4eff3f680
4 changed files with 319 additions and 58 deletions

View File

@ -164,6 +164,7 @@ size_t __unsafe_string_function_usage_here_char__(void);
#define safe_strcat(dest,src,maxlength) safe_strcat_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE,dest,src,maxlength)
#define push_string(base_ptr, dest, src, dest_len, flags) push_string_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, dest, src, dest_len, flags)
#define pull_string(base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) pull_string_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, smb_flags2, dest, src, dest_len, src_len, flags)
#define pull_string_talloc(ctx, base_ptr, smb_flags2, dest, src, src_len, flags) pull_string_talloc_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, ctx, base_ptr, smb_flags2, dest, src, src_len, flags)
#define clistr_push(cli, dest, src, dest_len, flags) clistr_push_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, cli, dest, src, dest_len, flags)
#define clistr_pull(cli, dest, src, dest_len, src_len, flags) clistr_pull_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, cli, dest, src, dest_len, src_len, flags)
#define srvstr_push(base_ptr, dest, src, dest_len, flags) srvstr_push_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, dest, src, dest_len, flags)
@ -197,6 +198,9 @@ size_t __unsafe_string_function_usage_here_char__(void);
? __unsafe_string_function_usage_here_size_t__() \
: pull_string_fn(fn_name, fn_line, base_ptr, smb_flags2, dest, src, dest_len, src_len, flags))
#define pull_string_talloc_fn2(fn_name, fn_line, ctx, base_ptr, smb_flags2, dest, src, src_len, flags) \
pull_string_talloc_fn(fn_name, fn_line, ctx, base_ptr, smb_flags2, dest, src, src_len, flags)
#define clistr_push_fn2(fn_name, fn_line, cli, dest, src, dest_len, flags) \
(CHECK_STRING_SIZE(dest, dest_len) \
? __unsafe_string_function_usage_here_size_t__() \
@ -218,6 +222,7 @@ size_t __unsafe_string_function_usage_here_char__(void);
#define safe_strcat_fn2 safe_strcat_fn
#define push_string_fn2 push_string_fn
#define pull_string_fn2 pull_string_fn
#define pull_string_talloc_fn2 pull_string_talloc_fn
#define clistr_push_fn2 clistr_push_fn
#define clistr_pull_fn2 clistr_pull_fn
#define srvstr_push_fn2 srvstr_push_fn

View File

@ -20,6 +20,10 @@
#define srvstr_pull(base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) \
pull_string(base_ptr, smb_flags2, dest, src, dest_len, src_len, flags)
/* talloc version of above. */
#define srvstr_pull_talloc(ctx, base_ptr, smb_flags2, dest, src, src_len, flags) \
pull_string_talloc(ctx, base_ptr, smb_flags2, dest, src, src_len, flags)
/* pull a string from the smb_buf part of a packet. In this case the
string can either be null terminated or it can be terminated by the
end of the smbbuf area
@ -28,3 +32,6 @@
#define srvstr_pull_buf(inbuf, smb_flags2, dest, src, dest_len, flags) \
pull_string(inbuf, smb_flags2, dest, src, dest_len, smb_bufrem(inbuf, src), flags)
/* talloc version of above. */
#define srvstr_pull_buf_talloc(ctx, inbuf, smb_flags2, dest, src, flags) \
pull_string_talloc(ctx, inbuf, smb_flags2, dest, src, smb_bufrem(inbuf, src), flags)

View File

@ -1,21 +1,21 @@
/*
/*
Unix SMB/CIFS implementation.
Character set conversion Extensions
Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
Copyright (C) Andrew Tridgell 2001
Copyright (C) Simo Sorce 2001
Copyright (C) Martin Pool 2003
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 3 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, see <http://www.gnu.org/licenses/>.
@ -33,7 +33,7 @@ char lp_failed_convert_char(void)
* @file
*
* @brief Character-set conversion routines built on our iconv.
*
*
* @note Samba's internal character set (at least in the 3.0 series)
* is always the same as the one for the Unix filesystem. It is
* <b>not</b> necessarily UTF-8 and may be different on machines that
@ -509,6 +509,7 @@ size_t convert_string(charset_t from, charset_t to,
* Convert between character sets, allocating a new buffer for the result.
*
* @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
* (this is a bad interface and needs fixing. JRA).
* @param srclen length of source buffer.
* @param dest always set at least to NULL
* @note -1 is not accepted for srclen.
@ -516,7 +517,7 @@ size_t convert_string(charset_t from, charset_t to,
* @returns Size in bytes of the converted string; or -1 in case of error.
*
* Ensure the srclen contains the terminating zero.
*
*
* I hate the goto's in this function. It's embarressing.....
* There has to be a cleaner way to do this. JRA.
**/
@ -603,6 +604,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
if (!conv_silent)
DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
/* smb_panic(reason); */
if (ctx) {
TALLOC_FREE(ob);
} else {
SAFE_FREE(ob);
}
return (size_t)-1;
}
@ -711,7 +717,7 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
* Convert between character sets, allocating a new buffer using talloc for the result.
*
* @param srclen length of source buffer.
* @param dest always set at least to NULL
* @param dest always set at least to NULL
* @note -1 is not accepted for srclen.
*
* @returns Size in bytes of the converted string; or -1 in case of error.
@ -736,7 +742,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
{
size_t size;
smb_ucs2_t *buffer;
size = push_ucs2_allocate(&buffer, src);
if (size == (size_t)-1) {
smb_panic("failed to create UCS2 buffer");
@ -745,7 +751,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
free(buffer);
return srclen;
}
size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
free(buffer);
return size;
@ -788,7 +794,7 @@ char *strdup_upper(const char *s)
}
strupper_w(buffer);
size = convert_string(CH_UTF16LE, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
if (size == (size_t)-1) {
return NULL;
@ -802,7 +808,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
{
size_t size;
smb_ucs2_t *buffer = NULL;
size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
(void **)(void *)&buffer, True);
if (size == (size_t)-1 || !buffer) {
@ -826,21 +832,21 @@ char *strdup_lower(const char *s)
size_t size;
smb_ucs2_t *buffer = NULL;
char *out_buffer;
size = push_ucs2_allocate(&buffer, s);
if (size == -1 || !buffer) {
return NULL;
}
strlower_w(buffer);
size = pull_ucs2_allocate(&out_buffer, buffer);
SAFE_FREE(buffer);
if (size == (size_t)-1) {
return NULL;
}
return out_buffer;
}
@ -987,6 +993,84 @@ size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len,
return src_len;
}
/**
* Copy a string from a dos codepage source to a unix char* destination.
Talloc version.
Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
needs fixing. JRA).
*
* The resulting string in "dest" is always null terminated.
*
* @param flags can have:
* <dl>
* <dt>STR_TERMINATE</dt>
* <dd>STR_TERMINATE means the string in @p src
* is null terminated, and src_len is ignored.</dd>
* </dl>
*
* @param src_len is the length of the source area in bytes.
* @returns the number of bytes occupied by the string in @p src.
**/
static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
char **ppdest,
const void *src,
size_t src_len,
int flags)
{
char *dest = NULL;
size_t dest_len = 0;
#ifdef DEVELOPER
/* Ensure we never use the braindead "malloc" varient. */
if (ctx == NULL) {
smb_panic("NULL talloc CTX in pull_ascii_base_talloc\n");
}
#endif
*ppdest = NULL;
if (flags & STR_TERMINATE) {
if (src_len == (size_t)-1) {
src_len = strlen((const char *)src) + 1;
} else {
size_t len = strnlen((const char *)src, src_len);
if (len < src_len)
len++;
src_len = len;
}
/* Ensure we don't use an insane length from the client. */
if (src_len >= 1024*1024) {
smb_panic("Bad src length in pull_ascii_base_talloc\n");
}
}
dest_len = convert_string_allocate(ctx,
CH_DOS,
CH_UNIX,
src,
src_len,
&dest,
True);
if (dest_len == (size_t)-1) {
return 0;
}
if (dest_len && dest) {
/* Did we already process the terminating zero ? */
if (dest[dest_len-1] != 0) {
dest[dest_len-1] = 0;
}
} else if (dest) {
dest[0] = 0;
}
*ppdest = dest;
return src_len;
}
size_t pull_ascii_pstring(char *dest, const void *src)
{
return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
@ -1214,7 +1298,7 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
/* ucs2 is always a multiple of 2 bytes */
if (src_len != (size_t)-1)
src_len &= ~1;
ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
if (ret == (size_t)-1) {
return 0;
@ -1222,7 +1306,7 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
if (src_len == (size_t)-1)
src_len = ret*2;
if (dest_len && ret) {
/* Did we already process the terminating zero ? */
if (dest[MIN(ret-1, dest_len-1)] != 0) {
@ -1235,6 +1319,92 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
return src_len;
}
/**
Copy a string from a ucs2 source to a unix char* destination.
Talloc version with a base pointer.
Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
needs fixing. JRA).
Flags can have:
STR_TERMINATE means the string in src is null terminated.
STR_NOALIGN means don't try to align.
if STR_TERMINATE is set then src_len is ignored if it is -1.
src_len is the length of the source area in bytes
Return the number of bytes occupied by the string in src.
The resulting string in "dest" is always null terminated.
**/
static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
const void *base_ptr,
char **ppdest,
const void *src,
size_t src_len,
int flags)
{
char *dest;
size_t dest_len;
*ppdest = NULL;
#ifdef DEVELOPER
/* Ensure we never use the braindead "malloc" varient. */
if (ctx == NULL) {
smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
}
#endif
if (ucs2_align(base_ptr, src, flags)) {
src = (const void *)((const char *)src + 1);
if (src_len != (size_t)-1)
src_len--;
}
if (flags & STR_TERMINATE) {
/* src_len -1 is the default for null terminated strings. */
if (src_len != (size_t)-1) {
size_t len = strnlen_w((const smb_ucs2_t *)src,
src_len/2);
if (len < src_len/2)
len++;
src_len = len*2;
}
/* Ensure we don't use an insane length from the client. */
if (src_len >= 1024*1024) {
smb_panic("Bad src length in pull_ucs2_base_talloc\n");
}
}
/* ucs2 is always a multiple of 2 bytes */
if (src_len != (size_t)-1) {
src_len &= ~1;
}
dest_len = convert_string_talloc(ctx,
CH_UTF16LE,
CH_UNIX,
src,
src_len,
(void **)&dest,
True);
if (dest_len == (size_t)-1) {
return 0;
}
if (src_len == (size_t)-1)
src_len = dest_len*2;
if (dest_len) {
/* Did we already process the terminating zero ? */
if (dest[dest_len-1] != 0) {
dest[dest_len-1] = 0;
}
} else if (dest) {
dest[0] = 0;
}
*ppdest = dest;
return src_len;
}
size_t pull_ucs2_pstring(char *dest, const void *src)
{
return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
@ -1398,6 +1568,54 @@ size_t pull_string_fn(const char *function, unsigned int line,
return pull_ascii(dest, src, dest_len, src_len, flags);
}
/**
Copy a string from a unicode or ascii source (depending on
the packet flags) to a char* destination.
Variant that uses talloc.
Flags can have:
STR_TERMINATE means the string in src is null terminated.
STR_UNICODE means to force as unicode.
STR_ASCII use ascii even with unicode packet.
STR_NOALIGN means don't do alignment.
if STR_TERMINATE is set then src_len is ignored is it is -1
src_len is the length of the source area in bytes.
Return the number of bytes occupied by the string in src.
The resulting string in "dest" is always null terminated.
**/
size_t pull_string_talloc_fn(const char *function,
unsigned int line,
TALLOC_CTX *ctx,
const void *base_ptr,
uint16 smb_flags2,
char **ppdest,
const void *src,
size_t src_len,
int flags)
{
if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
smb_panic("No base ptr to get flg2 and neither ASCII nor "
"UNICODE defined");
}
if (!(flags & STR_ASCII) && \
((flags & STR_UNICODE || \
(smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
return pull_ucs2_base_talloc(ctx,
base_ptr,
ppdest,
src,
src_len,
flags);
}
return pull_ascii_base_talloc(ctx,
ppdest,
src,
src_len,
flags);
}
size_t align_string(const void *base_ptr, const char *p, int flags)
{
if (!(flags & STR_ASCII) && \

View File

@ -381,30 +381,40 @@ int reply_special(char *inbuf,char *outbuf)
int reply_tcon(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
TALLOC_CTX *ctx;
const char *service;
pstring service_buf;
pstring password;
pstring dev;
char *service_buf = NULL;
char *password = NULL;
char *dev = NULL;
int outsize = 0;
uint16 vuid = SVAL(inbuf,smb_uid);
int pwlen=0;
NTSTATUS nt_status;
char *p;
DATA_BLOB password_blob;
START_PROFILE(SMBtcon);
*service_buf = *password = *dev = 0;
ctx = talloc_init("reply_tcon");
if (!ctx) {
END_PROFILE(SMBtcon);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
p = smb_buf(inbuf)+1;
p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p,
sizeof(service_buf), STR_TERMINATE) + 1;
pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p,
sizeof(password), STR_TERMINATE) + 1;
p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
&service_buf, p, STR_TERMINATE) + 1;
pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
&password, p, STR_TERMINATE) + 1;
p += pwlen;
p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev),
STR_TERMINATE) + 1;
p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
&dev, p, STR_TERMINATE) + 1;
if (service_buf == NULL || password == NULL || dev == NULL) {
TALLOC_FREE(ctx);
END_PROFILE(SMBtcon);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
p = strrchr_m(service_buf,'\\');
if (p) {
service = p+1;
@ -417,21 +427,23 @@ int reply_tcon(connection_struct *conn,
conn = make_connection(service,password_blob,dev,vuid,&nt_status);
data_blob_clear_free(&password_blob);
if (!conn) {
TALLOC_FREE(ctx);
END_PROFILE(SMBtcon);
return ERROR_NT(nt_status);
}
outsize = set_message(inbuf,outbuf,2,0,True);
SSVAL(outbuf,smb_vwv0,max_recv);
SSVAL(outbuf,smb_vwv1,conn->cnum);
SSVAL(outbuf,smb_tid,conn->cnum);
DEBUG(3,("tcon service=%s cnum=%d\n",
service, conn->cnum));
END_PROFILE(SMBtcon);
TALLOC_FREE(ctx);
return(outsize);
}
@ -442,23 +454,22 @@ int reply_tcon(connection_struct *conn,
int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
fstring service;
char *service = NULL;
DATA_BLOB password;
TALLOC_CTX *ctx = NULL;
/* what the cleint thinks the device is */
fstring client_devicetype;
char *client_devicetype = NULL;
/* what the server tells the client the share represents */
const char *server_devicetype;
NTSTATUS nt_status;
uint16 vuid = SVAL(inbuf,smb_uid);
int passlen = SVAL(inbuf,smb_vwv3);
pstring path;
char *path = NULL;
char *p, *q;
uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
START_PROFILE(SMBtconX);
*service = *client_devicetype = 0;
START_PROFILE(SMBtconX);
/* we might have to close an old one */
if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
@ -468,7 +479,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
if (passlen > MAX_PASS_LEN) {
return ERROR_DOS(ERRDOS,ERRbuftoosmall);
}
if (global_encrypted_passwords_negotiated) {
password = data_blob(smb_buf(inbuf),passlen);
if (lp_security() == SEC_SHARE) {
@ -487,34 +498,53 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
p = smb_buf(inbuf) + passlen + 1;
}
p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p,
sizeof(path), STR_TERMINATE);
ctx = talloc_init("reply_tcon_and_X");
if (!ctx) {
END_PROFILE(SMBtconX);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &path, p,
STR_TERMINATE);
if (path == NULL) {
TALLOC_FREE(ctx);
END_PROFILE(SMBtconX);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
/*
* the service name can be either: \\server\share
* or share directly like on the DELL PowerVault 705
*/
if (*path=='\\') {
if (*path=='\\') {
q = strchr_m(path+2,'\\');
if (!q) {
TALLOC_FREE(ctx);
END_PROFILE(SMBtconX);
return(ERROR_DOS(ERRDOS,ERRnosuchshare));
}
fstrcpy(service,q+1);
service = q+1;
} else {
service = path;
}
p += srvstr_pull_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2), &client_devicetype, p,
6, STR_ASCII);
if (client_devicetype == NULL) {
TALLOC_FREE(ctx);
END_PROFILE(SMBtconX);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
else
fstrcpy(service,path);
p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p,
sizeof(client_devicetype), 6, STR_ASCII);
DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
data_blob_clear_free(&password);
if (!conn) {
TALLOC_FREE(ctx);
END_PROFILE(SMBtconX);
return ERROR_NT(nt_status);
}
@ -523,19 +553,19 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
server_devicetype = "IPC";
else if ( IS_PRINT(conn) )
server_devicetype = "LPT1:";
else
else
server_devicetype = "A:";
if (Protocol < PROTOCOL_NT1) {
set_message(inbuf,outbuf,2,0,True);
p = smb_buf(outbuf);
p += srvstr_push(outbuf, p, server_devicetype, -1,
p += srvstr_push(outbuf, p, server_devicetype, -1,
STR_TERMINATE|STR_ASCII);
set_message_end(inbuf,outbuf,p);
} else {
/* NT sets the fstype of IPC$ to the null string */
const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
/* Return permissions. */
uint32 perm1 = 0;
@ -559,29 +589,30 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
p = smb_buf(outbuf);
p += srvstr_push(outbuf, p, server_devicetype, -1,
p += srvstr_push(outbuf, p, server_devicetype, -1,
STR_TERMINATE|STR_ASCII);
p += srvstr_push(outbuf, p, fstype, -1,
p += srvstr_push(outbuf, p, fstype, -1,
STR_TERMINATE);
set_message_end(inbuf,outbuf,p);
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
(lp_csc_policy(SNUM(conn)) << 2));
init_dfsroot(conn, inbuf, outbuf);
}
DEBUG(3,("tconX service=%s \n",
service));
/* set the incoming and outgoing tid to the just created one */
SSVAL(inbuf,smb_tid,conn->cnum);
SSVAL(outbuf,smb_tid,conn->cnum);
TALLOC_FREE(ctx);
END_PROFILE(SMBtconX);
return chain_reply(inbuf,outbuf,length,bufsize);
}