diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 75 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 18 | ||||
-rw-r--r-- | source3/libsmb/clistr.c | 161 |
3 files changed, 213 insertions, 41 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 8a56a08b1d..74a10ddf8b 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -104,8 +104,7 @@ BOOL cli_session_setup(struct cli_state *cli, /* * Plaintext mode needed, assume plaintext supplied. */ - fstrcpy(pword, pass); - unix_to_dos(pword,True); + passlen = clistr_push(cli, pword, pass, -1, CLISTR_CONVERT|CLISTR_TERMINATE); fstrcpy(ntpword, ""); ntpasslen = 0; } @@ -124,7 +123,10 @@ BOOL cli_session_setup(struct cli_state *cli, if (cli->protocol < PROTOCOL_NT1) { - set_message(cli->outbuf,10,1 + strlen(user) + passlen,True); + set_message(cli->outbuf,10, + clistr_align(cli, 1) + + clistr_push_size(cli, user, -1, CLISTR_TERMINATE|CLISTR_CONVERT) + + passlen,True); CVAL(cli->outbuf,smb_com) = SMBsesssetupX; cli_setup_packet(cli); @@ -135,11 +137,10 @@ BOOL cli_session_setup(struct cli_state *cli, SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); p = smb_buf(cli->outbuf); + p += clistr_align(cli, PTR_DIFF(p,cli->outbuf)); memcpy(p,pword,passlen); p += passlen; - pstrcpy(p,user); - unix_to_dos(p,True); - strupper(p); + clistr_push(cli, p, user, -1, CLISTR_CONVERT|CLISTR_UPPER|CLISTR_TERMINATE); } else { @@ -156,20 +157,15 @@ BOOL cli_session_setup(struct cli_state *cli, SSVAL(cli->outbuf,smb_vwv8,ntpasslen); SSVAL(cli->outbuf,smb_vwv11,CAP_NT_SMBS|(cli->use_level_II_oplocks ? CAP_LEVEL_II_OPLOCKS : 0)); p = smb_buf(cli->outbuf); + p += clistr_align(cli, PTR_DIFF(p,cli->outbuf)); memcpy(p,pword,passlen); p += SVAL(cli->outbuf,smb_vwv7); memcpy(p,ntpword,ntpasslen); p += SVAL(cli->outbuf,smb_vwv8); - pstrcpy(p,user); - unix_to_dos(p,True); - strupper(p); - p = skip_string(p,1); - pstrcpy(p,workgroup); - unix_to_dos(p,True); - strupper(p); - p = skip_string(p,1); - pstrcpy(p,"Unix");p = skip_string(p,1); - pstrcpy(p,"Samba");p = skip_string(p,1); + p += clistr_push(cli, p, user, -1, CLISTR_CONVERT|CLISTR_TERMINATE|CLISTR_UPPER); + p += clistr_push(cli, p, workgroup, -1, CLISTR_CONVERT|CLISTR_TERMINATE|CLISTR_UPPER); + p += clistr_push(cli, p, "Unix", -1, CLISTR_CONVERT|CLISTR_TERMINATE); + p += clistr_push(cli, p, "Samba", -1, CLISTR_CONVERT|CLISTR_TERMINATE); set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False); } @@ -187,24 +183,18 @@ BOOL cli_session_setup(struct cli_state *cli, cli->vuid = SVAL(cli->inbuf,smb_uid); if (cli->protocol >= PROTOCOL_NT1) { - /* - * Save off some of the connected server - * info. - */ - char *server_domain,*server_os,*server_type; - server_os = smb_buf(cli->inbuf); - server_type = skip_string(server_os,1); - server_domain = skip_string(server_type,1); - fstrcpy(cli->server_os, server_os); - dos_to_unix(cli->server_os, True); - fstrcpy(cli->server_type, server_type); - dos_to_unix(cli->server_type, True); - fstrcpy(cli->server_domain, server_domain); - dos_to_unix(cli->server_domain, True); + /* + * Save off some of the connected server + * info. + */ + char *p = smb_buf(cli->inbuf); + p += clistr_align(cli, PTR_DIFF(p,cli->outbuf)); + p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT); + p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT); + p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT); } fstrcpy(cli->user_name, user); - dos_to_unix(cli->user_name, True); return True; } @@ -257,12 +247,11 @@ BOOL cli_send_tconX(struct cli_state *cli, unix_to_dos(dos_pword,True); SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword); } else { - if(!(cli->sec_mode & 2)) { + if((cli->sec_mode & 3) == 0) { /* * Non-encrypted passwords - convert to DOS codepage before using. */ - fstrcpy(pword,pass); - unix_to_dos(pword,True); + passlen = clistr_push(cli, pword, pass, -1, CLISTR_CONVERT|CLISTR_TERMINATE); } else { memcpy(pword, pass, passlen); } @@ -274,7 +263,10 @@ BOOL cli_send_tconX(struct cli_state *cli, strupper(fullshare); set_message(cli->outbuf,4, - 2 + strlen(fullshare) + passlen + strlen(dev),True); + clistr_push_size(cli, fullshare, -1, CLISTR_TERMINATE | CLISTR_CONVERT) + + passlen + + 1+strlen(dev), + True); CVAL(cli->outbuf,smb_com) = SMBtconX; cli_setup_packet(cli); @@ -284,10 +276,10 @@ BOOL cli_send_tconX(struct cli_state *cli, p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; - fstrcpy(p,fullshare); - p = skip_string(p,1); - pstrcpy(p,dev); - unix_to_dos(p,True); + p += clistr_push(cli, p, fullshare, -1, CLISTR_CONVERT | CLISTR_TERMINATE); + fstrcpy(p, dev); p += strlen(dev)+1; + + set_message(cli->outbuf,4,PTR_DIFF(p,smb_buf(cli->outbuf)),False); SCVAL(cli->inbuf,smb_rcls, 1); @@ -302,7 +294,7 @@ BOOL cli_send_tconX(struct cli_state *cli, fstrcpy(cli->dev, "A:"); if (cli->protocol >= PROTOCOL_NT1) { - fstrcpy(cli->dev, smb_buf(cli->inbuf)); + clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, CLISTR_TERMINATE | CLISTR_CONVERT); } if (strcasecmp(share,"IPC$")==0) { @@ -461,6 +453,9 @@ BOOL cli_negprot(struct cli_state *cli) cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE); + /* this ensures cli_use_unicode is setup - delete this call later (tridge) */ + cli_setup_packet(cli); + return True; } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 1938049806..d7649074db 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -95,19 +95,35 @@ BOOL cli_send_smb(struct cli_state *cli) return True; } +int cli_use_unicode = 0; + /**************************************************************************** setup basics in a outgoing packet ****************************************************************************/ void cli_setup_packet(struct cli_state *cli) { + static int initialised; + + /* the USE_UNICODE check will be deleted once our client side unicode + support is complete (tridge) */ + if (!initialised) { + initialised = 1; + if (getenv("USE_UNICODE")) cli_use_unicode = 1; + } + cli->rap_error = 0; cli->nt_error = 0; SSVAL(cli->outbuf,smb_pid,cli->pid); SSVAL(cli->outbuf,smb_uid,cli->vuid); SSVAL(cli->outbuf,smb_mid,cli->mid); if (cli->protocol > PROTOCOL_CORE) { + uint16 flags2; SCVAL(cli->outbuf,smb_flg,0x8); - SSVAL(cli->outbuf,smb_flg2,0x1); + flags2 = FLAGS2_LONG_PATH_COMPONENTS; + if (cli_use_unicode && cli->capabilities & CAP_UNICODE) { + flags2 |= FLAGS2_UNICODE_STRINGS; + } + SSVAL(cli->outbuf,smb_flg2, flags2); } } diff --git a/source3/libsmb/clistr.c b/source3/libsmb/clistr.c new file mode 100644 index 0000000000..839dec7592 --- /dev/null +++ b/source3/libsmb/clistr.c @@ -0,0 +1,161 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + client string routines + Copyright (C) Andrew Tridgell 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. +*/ + +#define NO_SYSLOG + +#include "includes.h" + +/* we will delete this variable once our client side unicode support is complete */ +extern int cli_use_unicode; + +/**************************************************************************** +copy a string from a char* src to a unicode or ascii +dos code page destination choosing unicode or ascii based on the +cli->capabilities flag +return the number of bytes occupied by the string in the destination +flags can have: + CLISTR_TERMINATE means include the null termination + CLISTR_CONVERT means convert from unix to dos codepage + CLISTR_UPPER means uppercase in the destination +dest_len is the maximum length allowed in the destination. If dest_len +is -1 then no maxiumum is used +****************************************************************************/ +int clistr_push(struct cli_state *cli, void *dest, char *src, int dest_len, int flags) +{ + int len; + + /* treat a pstring as "unlimited" length */ + if (dest_len == -1) { + dest_len = sizeof(pstring); + } + + if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) { + /* the server doesn't want unicode */ + safe_strcpy(dest, src, dest_len); + len = strlen(dest); + if (flags & CLISTR_TERMINATE) len++; + if (flags & CLISTR_CONVERT) unix_to_dos(dest,True); + if (flags & CLISTR_UPPER) strupper(dest); + return len; + } + + /* the server likes unicode. give it the works */ + if (flags & CLISTR_CONVERT) { + dos_PutUniCode(dest, src, dest_len, flags & CLISTR_TERMINATE); + } else { + ascii_to_unistr(dest, src, dest_len); + } + if (flags & CLISTR_UPPER) { + strupper_w(dest); + } + len = strlen(src)*2; + if (flags & CLISTR_TERMINATE) len += 2; + return len; +} + + +/**************************************************************************** +return the length that a string would occupy when copied with clistr_push() + CLISTR_TERMINATE means include the null termination + CLISTR_CONVERT means convert from unix to dos codepage + CLISTR_UPPER means uppercase in the destination +****************************************************************************/ +int clistr_push_size(struct cli_state *cli, char *src, int dest_len, int flags) +{ + int len = strlen(src); + if (flags & CLISTR_TERMINATE) len++; + if (cli_use_unicode && (cli->capabilities & CAP_UNICODE)) len *= 2; + return len; +} + +/**************************************************************************** +copy a string from a unicode or ascii source (depending on +cli->capabilities) to a char* destination +flags can have: + CLISTR_CONVERT means convert from dos to unix codepage + CLISTR_TERMINATE means the string in src is null terminated +if CLISTR_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 clistr_pull(struct cli_state *cli, char *dest, void *src, int dest_len, int src_len, int flags) +{ + int len; + + if (dest_len == -1) { + dest_len = sizeof(pstring); + } + + if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) { + /* the server doesn't want unicode */ + if (flags & CLISTR_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 & CLISTR_CONVERT) dos_to_unix(dest,True); + return len; + } + + if (flags & CLISTR_TERMINATE) { + unistr_to_ascii(dest, src, dest_len); + len = strlen(dest)*2 + 2; + } else { + int i, c; + if (dest_len < src_len) src_len = dest_len; + for (i=0; i < src_len; i += 2) { + c = SVAL(src, i); + *dest++ = c; + } + *dest++ = 0; + len = src_len; + } + if (flags & CLISTR_CONVERT) dos_to_unix(dest,True); + return len; +} + +/**************************************************************************** +return the length that a string would occupy (not including the null) +when copied with clistr_pull() +if src_len is -1 then assume the source is null terminated +****************************************************************************/ +int clistr_pull_size(struct cli_state *cli, void *src, int src_len) +{ + if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) { + return strlen(src); + } + return strlen_w(src); +} + +/**************************************************************************** +return an alignment of either 0 or 1 +if unicode is not negotiated then return 0 +otherwise return 1 if offset is off +****************************************************************************/ +int clistr_align(struct cli_state *cli, int offset) +{ + if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) return 0; + return offset & 1; +} |