X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source%2Fsmbd%2Fsrvstr.c;h=68e61033ae1a30b482073a53ca62fb534a52afef;hb=5c6c8e1fe93;hp=241a74f02f04d24aead46125c7d8e8ad7c84df7d;hpb=d5b39a1d435f7fe79eb556f7e6b55276ac68a73d;p=samba.git diff --git a/source/smbd/srvstr.c b/source/smbd/srvstr.c index 241a74f02f0..68e61033ae1 100644 --- a/source/smbd/srvstr.c +++ b/source/smbd/srvstr.c @@ -1,12 +1,12 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. server specific string routines Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 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 2 of the License, or + 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, @@ -15,132 +15,73 @@ 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. + along with this program. If not, see . */ -#define NO_SYSLOG - #include "includes.h" +extern int max_send; -#define UNICODE_FLAG(buf) (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS) +/* Make sure we can't write a string past the end of the buffer */ -/**************************************************************************** -copy a string from a char* src to a unicode or ascii -dos code page destination choosing unicode or ascii based on the -FLAGS2_UNICODE_STRINGS bit in inbuf -return the number of bytes occupied by the string in the destination -flags can have: - STR_TERMINATE means include the null termination - STR_CONVERT means convert from unix to dos codepage - STR_UPPER means uppercase in the destination - STR_ASCII use ascii even with unicode servers -dest_len is the maximum length allowed in the destination. If dest_len -is -1 then no maxiumum is used -****************************************************************************/ -int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int flags) +size_t srvstr_push_fn(const char *function, unsigned int line, + const char *base_ptr, uint16 smb_flags2, void *dest, + const char *src, int dest_len, int flags) { - int len=0; - - /* treat a pstring as "unlimited" length */ + size_t buf_used = PTR_DIFF(dest, base_ptr); if (dest_len == -1) { - dest_len = sizeof(pstring); - } - - if (!(flags & STR_ASCII) && srvstr_align(outbuf, PTR_DIFF(dest, outbuf))) { - *(char *)dest = 0; - dest++; - dest_len--; - len++; - } - - if ((flags & STR_ASCII) || !UNICODE_FLAG(outbuf)) { - /* the client doesn't want unicode */ - safe_strcpy(dest, src, dest_len); - len = strlen(dest); - if (flags & STR_TERMINATE) len++; - if (flags & STR_CONVERT) unix_to_dos(dest,True); - if (flags & STR_UPPER) strupper(dest); - return len; - } - - /* the server likes unicode. give it the works */ - if (flags & STR_CONVERT) { - dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE); - } else { - ascii_to_unistr(dest, src, dest_len); - } - if (flags & STR_UPPER) { - strupper_w(dest); + if (((ptrdiff_t)dest < (ptrdiff_t)base_ptr) || (buf_used > (size_t)max_send)) { +#if 0 + DEBUG(0, ("Pushing string of 'unlimited' length into non-SMB buffer!\n")); +#endif + return push_string_fn(function, line, base_ptr, + smb_flags2, dest, src, -1, + flags); + } + return push_string_fn(function, line, base_ptr, smb_flags2, + dest, src, max_send - buf_used, flags); } - len += strlen(src)*2; - if (flags & STR_TERMINATE) len += 2; - return len; + + /* 'normal' push into size-specified buffer */ + return push_string_fn(function, line, base_ptr, smb_flags2, dest, src, + dest_len, flags); } -/**************************************************************************** -copy a string from a unicode or ascii source (depending on flg2) -to a char* destination -flags can have: - STR_CONVERT means convert from dos to unix codepage - STR_TERMINATE means the string in src is null terminated - STR_UNICODE means to force as unicode -if STR_TERMINATE is set then src_len is ignored -src_len is the length of the source area in bytes -return the number of bytes occupied by the string in src -****************************************************************************/ -int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags) +/******************************************************************* + Add a string to the end of a smb_buf, adjusting bcc and smb_len. + Return the bytes added +********************************************************************/ + +ssize_t message_push_string(uint8 **outbuf, const char *str, int flags) { - int len; + size_t buf_size = smb_len(*outbuf) + 4; + size_t grow_size; + size_t result; + uint8 *tmp; - if (dest_len == -1) { - dest_len = sizeof(pstring); - } + /* + * We need to over-allocate, now knowing what srvstr_push will + * actually use. This is very generous by incorporating potential + * padding, the terminating 0 and at most 4 chars per UTF-16 code + * point. + */ + grow_size = (strlen(str) + 2) * 4; - if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(src, inbuf))) { - src++; - if (src_len > 0) src_len--; + if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, + buf_size + grow_size))) { + DEBUG(0, ("talloc failed\n")); + return -1; } - if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG(inbuf))) { - /* the server doesn't want unicode */ - if (flags & STR_TERMINATE) { - safe_strcpy(dest, src, dest_len); - len = strlen(src)+1; - } else { - if (src_len > dest_len) src_len = dest_len; - len = src_len; - memcpy(dest, src, len); - dest[len] = 0; - } - if (flags & STR_CONVERT) dos_to_unix(dest,True); - return len; - } + result = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2), + tmp + buf_size, str, grow_size, flags); - if (flags & STR_TERMINATE) { - unistr_to_ascii(dest, src, dest_len); - len = strlen(dest)*2 + 2; - } else { - int i, c; - if (dest_len*2 < src_len) src_len = 2*dest_len; - for (i=0; i < src_len; i += 2) { - c = SVAL(src, i); - *dest++ = c; - } - *dest++ = 0; - len = src_len; + if (result == (size_t)-1) { + DEBUG(0, ("srvstr_push failed\n")); + return -1; } - if (flags & STR_CONVERT) dos_to_unix(dest,True); - return len; -} + set_message_bcc((char *)tmp, smb_buflen(tmp) + result); -/**************************************************************************** -return an alignment of either 0 or 1 -if unicode is not negotiated then return 0 -otherwise return 1 if offset is off -****************************************************************************/ -int srvstr_align(void *inbuf, int offset) -{ - if (!UNICODE_FLAG(inbuf)) return 0; - return offset & 1; + *outbuf = tmp; + + return result; }