diff options
Diffstat (limited to 'source/libsmb')
-rw-r--r-- | source/libsmb/cliconnect.c | 12 | ||||
-rw-r--r-- | source/libsmb/clidfs.c | 600 | ||||
-rw-r--r-- | source/libsmb/clientgen.c | 4 | ||||
-rw-r--r-- | source/libsmb/clilist.c | 10 | ||||
-rw-r--r-- | source/libsmb/cliprint.c | 105 | ||||
-rw-r--r-- | source/libsmb/clirap.c | 74 | ||||
-rw-r--r-- | source/libsmb/clisecdesc.c | 9 | ||||
-rw-r--r-- | source/libsmb/ntlmssp.c | 13 | ||||
-rw-r--r-- | source/libsmb/ntlmssp_sign.c | 6 |
9 files changed, 811 insertions, 22 deletions
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index 78cf9028c68..01a92a89ba4 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -151,7 +151,7 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli) if (cli->use_level_II_oplocks) capabilities |= CAP_LEVEL_II_OPLOCKS; - capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX)); + capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS)); return capabilities; } @@ -972,6 +972,9 @@ BOOL cli_send_tconX(struct cli_state *cli, /* almost certainly win95 - enable bug fixes */ cli->win95 = True; } + + if ( cli->protocol >= PROTOCOL_LANMAN2 ) + cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS); cli->cnum = SVAL(cli->inbuf,smb_tid); return True; @@ -993,7 +996,12 @@ BOOL cli_tdis(struct cli_state *cli) if (!cli_receive_smb(cli)) return False; - return !cli_is_error(cli); + if (cli_is_error(cli)) { + return False; + } + + cli->cnum = -1; + return True; } /**************************************************************************** diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c new file mode 100644 index 00000000000..1b0860b675d --- /dev/null +++ b/source/libsmb/clidfs.c @@ -0,0 +1,600 @@ +/* + Unix SMB/CIFS implementation. + client connect/disconnect routines + Copyright (C) Andrew Tridgell 1994-1998 + Copyright (C) Gerald (Jerry) Carter 2004 + + 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" + + +struct client_connection { + struct client_connection *prev, *next; + struct cli_state *cli; +}; + +/* global state....globals reek! */ + +static pstring username; +static pstring password; +static BOOL use_kerberos; +static BOOL got_pass; +static int signing_state; + +static int port; +static int name_type = 0x20; +static int max_protocol = PROTOCOL_NT1; +static BOOL have_ip; +static struct in_addr dest_ip; + +static struct client_connection *connections; + +/******************************************************************** + Return a connection to a server. +********************************************************************/ + +static struct cli_state *do_connect( const char *server, const char *share, + BOOL show_sessetup ) +{ + struct cli_state *c; + struct nmb_name called, calling; + const char *server_n; + struct in_addr ip; + pstring servicename; + char *sharename; + + /* make a copy so we don't modify the global string 'service' */ + pstrcpy(servicename, share); + sharename = servicename; + if (*sharename == '\\') { + server = sharename+2; + sharename = strchr_m(server,'\\'); + if (!sharename) return NULL; + *sharename = 0; + sharename++; + } + + server_n = server; + + zero_ip(&ip); + + make_nmb_name(&calling, global_myname(), 0x0); + make_nmb_name(&called , server, name_type); + + again: + zero_ip(&ip); + if (have_ip) + ip = dest_ip; + + /* have to open a new connection */ + if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) || + !cli_connect(c, server_n, &ip)) { + d_printf("Connection to %s failed\n", server_n); + return NULL; + } + + c->protocol = max_protocol; + c->use_kerberos = use_kerberos; + cli_setup_signing_state(c, signing_state); + + + if (!cli_session_request(c, &calling, &called)) { + char *p; + d_printf("session request to %s failed (%s)\n", + called.name, cli_errstr(c)); + cli_shutdown(c); + if ((p=strchr_m(called.name, '.'))) { + *p = 0; + goto again; + } + if (strcmp(called.name, "*SMBSERVER")) { + make_nmb_name(&called , "*SMBSERVER", 0x20); + goto again; + } + return NULL; + } + + DEBUG(4,(" session request ok\n")); + + if (!cli_negprot(c)) { + d_printf("protocol negotiation failed\n"); + cli_shutdown(c); + return NULL; + } + + if (!got_pass) { + char *pass = getpass("Password: "); + if (pass) { + pstrcpy(password, pass); + got_pass = 1; + } + } + + if (!cli_session_setup(c, username, + password, strlen(password), + password, strlen(password), + lp_workgroup())) { + /* if a password was not supplied then try again with a null username */ + if (password[0] || !username[0] || use_kerberos || + !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) { + d_printf("session setup failed: %s\n", cli_errstr(c)); + if (NT_STATUS_V(cli_nt_error(c)) == + NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)) + d_printf("did you forget to run kinit?\n"); + cli_shutdown(c); + return NULL; + } + d_printf("Anonymous login successful\n"); + } + + if ( show_sessetup ) { + if (*c->server_domain) { + DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", + c->server_domain,c->server_os,c->server_type)); + } else if (*c->server_os || *c->server_type){ + DEBUG(1,("OS=[%s] Server=[%s]\n", + c->server_os,c->server_type)); + } + } + DEBUG(4,(" session setup ok\n")); + + if (!cli_send_tconX(c, sharename, "?????", + password, strlen(password)+1)) { + d_printf("tree connect failed: %s\n", cli_errstr(c)); + cli_shutdown(c); + return NULL; + } + + DEBUG(4,(" tconx ok\n")); + + return c; +} + +/******************************************************************** + Add a new connection to the list +********************************************************************/ + +static struct cli_state* cli_cm_connect( const char *server, const char *share, + BOOL show_hdr ) +{ + struct client_connection *node; + + node = SMB_XMALLOC_P( struct client_connection ); + + node->cli = do_connect( server, share, show_hdr ); + + if ( !node->cli ) { + SAFE_FREE( node ); + return NULL; + } + + DLIST_ADD( connections, node ); + + return node->cli; + +} + +/******************************************************************** + Return a connection to a server. +********************************************************************/ + +static struct cli_state* cli_cm_find( const char *server, const char *share ) +{ + struct client_connection *p; + + for ( p=connections; p; p=p->next ) { + if ( strequal(server, p->cli->desthost) && strequal(share,p->cli->share) ) + return p->cli; + } + + return NULL; +} + +/**************************************************************************** + open a client connection to a \\server\share. Set's the current *cli + global variable as a side-effect (but only if the connection is successful). +****************************************************************************/ + +struct cli_state* cli_cm_open( const char *server, const char *share, BOOL show_hdr ) +{ + struct cli_state *c; + + /* try to reuse an existing connection */ + + c = cli_cm_find( server, share ); + + if ( !c ) + c = cli_cm_connect( server, share, show_hdr ); + + return c; +} + +/**************************************************************************** +****************************************************************************/ + +void cli_cm_shutdown( void ) +{ + + struct client_connection *p, *x; + + for ( p=connections; p; ) { + cli_shutdown( p->cli ); + x = p; + p = p->next; + + SAFE_FREE( x ); + } + + connections = NULL; + + return; +} + +/**************************************************************************** +****************************************************************************/ + +void cli_cm_display(void) +{ + struct client_connection *p; + int i; + + for ( p=connections,i=0; p; p=p->next,i++ ) { + d_printf("%d:\tserver=%s, share=%s\n", + i, p->cli->desthost, p->cli->share ); + } +} + +/**************************************************************************** +****************************************************************************/ + +void cli_cm_set_credentials( struct user_auth_info *user ) +{ + pstrcpy( username, user->username ); + + if ( user->got_pass ) { + pstrcpy( password, user->password ); + got_pass = True; + } + + use_kerberos = user->use_kerberos; + signing_state = user->signing_state; +} + +/**************************************************************************** +****************************************************************************/ + +void cli_cm_set_port( int port_number ) +{ + port = port_number; +} + +/**************************************************************************** +****************************************************************************/ + +void cli_cm_set_dest_name_type( int type ) +{ + name_type = type; +} + +/**************************************************************************** +****************************************************************************/ + +void cli_cm_set_dest_ip(struct in_addr ip ) +{ + dest_ip = ip; + have_ip = True; +} + +/******************************************************************** + split a dfs path into the server and share name components +********************************************************************/ + +static void split_dfs_path( const char *nodepath, fstring server, fstring share ) +{ + char *p; + pstring path; + + pstrcpy( path, nodepath ); + + if ( path[0] != '\\' ) + return; + + p = strrchr_m( path, '\\' ); + + if ( !p ) + return; + + *p = '\0'; + p++; + + fstrcpy( share, p ); + fstrcpy( server, &path[1] ); +} + +/**************************************************************************** + return the original path truncated at the first wildcard character + (also strips trailing \'s). Trust the caller to provide a NULL + terminated string +****************************************************************************/ + +static void clean_path( pstring clean, const char *path ) +{ + int len; + char *p; + pstring newpath; + + pstrcpy( newpath, path ); + p = newpath; + + while ( p ) { + /* first check for '*' */ + + p = strrchr_m( newpath, '*' ); + if ( p ) { + *p = '\0'; + p = newpath; + continue; + } + + /* first check for '?' */ + + p = strrchr_m( newpath, '?' ); + if ( p ) { + *p = '\0'; + p = newpath; + } + } + + /* strip a trailing backslash */ + + len = strlen( newpath ); + if ( newpath[len-1] == '\\' ) + newpath[len-1] = '\0'; + + pstrcpy( clean, newpath ); +} + +/**************************************************************************** +****************************************************************************/ + +static BOOL make_full_path( pstring path, const char *server, const char *share, + const char *dir ) +{ + pstring servicename; + char *sharename; + const char *directory; + + + /* make a copy so we don't modify the global string 'service' */ + + pstrcpy(servicename, share); + sharename = servicename; + + if (*sharename == '\\') { + + server = sharename+2; + sharename = strchr_m(server,'\\'); + + if (!sharename) + return False; + + *sharename = 0; + sharename++; + } + + directory = dir; + if ( *directory == '\\' ) + directory++; + + pstr_sprintf( path, "\\%s\\%s\\%s", server, sharename, directory ); + + return True; +} + +/******************************************************************** + check for dfs referral +********************************************************************/ + +static BOOL cli_dfs_check_error( struct cli_state *cli ) +{ + uint32 flgs2 = SVAL(cli->inbuf,smb_flg2); + + /* only deal with DS when we negotiated NT_STATUS codes and UNICODE */ + + if ( !( (flgs2&FLAGS2_32_BIT_ERROR_CODES) && (flgs2&FLAGS2_UNICODE_STRINGS) ) ) + return False; + + if ( NT_STATUS_EQUAL( NT_STATUS_PATH_NOT_COVERED, NT_STATUS(IVAL(cli->inbuf,smb_rcls)) ) ) + return True; + + return False; +} + +/******************************************************************** + get the dfs referral link +********************************************************************/ + +BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path, + CLIENT_DFS_REFERRAL**refs, size_t *num_refs, + uint16 *consumed) +{ + unsigned int data_len = 0; + unsigned int param_len = 0; + uint16 setup = TRANSACT2_GET_DFS_REFERRAL; + char param[sizeof(pstring)+2]; + pstring data; + char *rparam=NULL, *rdata=NULL; + char *p; + size_t pathlen = 2*(strlen(path)+1); + uint16 num_referrals; + CLIENT_DFS_REFERRAL *referrals; + + memset(param, 0, sizeof(param)); + SSVAL(param, 0, 0x03); /* max referral level */ + p = ¶m[2]; + + p += clistr_push(cli, p, path, MIN(pathlen, sizeof(param)-2), STR_TERMINATE); + param_len = PTR_DIFF(p, param); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + (char *)&data, data_len, cli->max_xmit /* data, length, max */ + )) { + return False; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return False; + } + + *consumed = SVAL( rdata, 0 ); + num_referrals = SVAL( rdata, 2 ); + + if ( num_referrals != 0 ) { + uint16 ref_version; + uint16 ref_size; + int i; + uint16 node_offset; + + + referrals = SMB_XMALLOC_ARRAY( CLIENT_DFS_REFERRAL, num_referrals ); + + /* start at the referrals array */ + + p = rdata+8; + for ( i=0; i<num_referrals; i++ ) { + ref_version = SVAL( p, 0 ); + ref_size = SVAL( p, 2 ); + node_offset = SVAL( p, 16 ); + + if ( ref_version != 3 ) { + p += ref_size; + continue; + } + + referrals[i].proximity = SVAL( p, 8 ); + referrals[i].ttl = SVAL( p, 10 ); + + clistr_pull( cli, referrals[i].dfspath, p+node_offset, + sizeof(referrals[i].dfspath), -1, STR_TERMINATE|STR_UNICODE ); + + p += ref_size; + } + + } + + *num_refs = num_referrals; + *refs = referrals; + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + + return True; +} + +/******************************************************************** +********************************************************************/ + +BOOL cli_resolve_path( struct cli_state *rootcli, const char *path, + struct cli_state **targetcli, pstring targetpath ) +{ + CLIENT_DFS_REFERRAL *refs = NULL; + size_t num_refs; + uint16 consumed; + struct cli_state *cli_ipc; + pstring fullpath, cleanpath; + int pathlen; + fstring server, share; + struct cli_state *newcli; + pstring newpath; + + SMB_STRUCT_STAT sbuf; + uint32 attributes; + + *targetcli = NULL; + + if ( !rootcli || !path || !targetcli ) + return False; + + /* send a trans2_query_path_info to check for a referral */ + + clean_path( cleanpath, path ); + make_full_path( fullpath, rootcli->desthost, rootcli->share, cleanpath ); + + /* don't bother continuing if this is not a dfs root */ + + if ( !rootcli->dfsroot || cli_qpathinfo_basic( rootcli, cleanpath, &sbuf, &attributes ) ) { + *targetcli = rootcli; + pstrcpy( targetpath, path ); + return True; + } + + /* we got an error, check for DFS referral */ + + if ( !cli_dfs_check_error(rootcli) ) + return False; + + /* check for the referral */ + + if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) ) + return False; + + if ( !cli_dfs_get_referral(cli_ipc, fullpath, &refs, &num_refs, &consumed) + || !num_refs ) + { + return False; + } + + /* just store the first referral for now + Make sure to recreate the original string including any wildcards */ + + make_full_path( fullpath, rootcli->desthost, rootcli->share, path ); + pathlen = strlen( fullpath )*2; + consumed = MIN(pathlen, consumed ); + pstrcpy( targetpath, &fullpath[consumed/2] ); + + split_dfs_path( refs[0].dfspath, server, share ); + SAFE_FREE( refs ); + + /* open the connection to the target path */ + + if ( (*targetcli = cli_cm_open(server, share, False)) == NULL ) { + d_printf("Unable to follow dfs referral [//%s/%s]\n", + server, share ); + + return False; + } + + /* check for another dfs refeerrali, note that we are not + checking for loops here */ + + if ( !strequal( targetpath, "\\" ) ) { + if ( cli_resolve_path( *targetcli, targetpath, &newcli, newpath ) ) { + *targetcli = newcli; + pstrcpy( targetpath, newpath ); + } + } + + return True; +} diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index 39fe91172d4..369fba35218 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -185,6 +185,8 @@ void cli_setup_packet(struct cli_state *cli) flags2 = FLAGS2_LONG_PATH_COMPONENTS; if (cli->capabilities & CAP_UNICODE) flags2 |= FLAGS2_UNICODE_STRINGS; + if (cli->capabilities & CAP_DFS) + flags2 |= FLAGS2_DFS_PATHNAMES; if (cli->capabilities & CAP_STATUS32) flags2 |= FLAGS2_32_BIT_ERROR_CODES; if (cli->use_spnego) @@ -283,7 +285,7 @@ struct cli_state *cli_initialise(struct cli_state *cli) cli->use_spnego = lp_client_use_spnego(); - cli->capabilities = CAP_UNICODE | CAP_STATUS32; + cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS; /* Set the CLI_FORCE_DOSERR environment variable to test client routines using DOS errors instead of STATUS32 diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c index 8ab5854c8fb..532fb3a772e 100644 --- a/source/libsmb/clilist.c +++ b/source/libsmb/clilist.c @@ -171,8 +171,14 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, /* NT uses 260, OS/2 uses 2. Both accept 1. */ info_level = (cli->capabilities&CAP_NT_SMBS)?260:1; - - pstrcpy(mask,Mask); + + /* when getting a directory listing from a 2k dfs root share, + we have to include the full path (\server\share\mask) here */ + + if ( cli->dfsroot ) + pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask ); + else + pstrcpy(mask,Mask); while (ff_eos == 0) { loop_count++; diff --git a/source/libsmb/cliprint.c b/source/libsmb/cliprint.c index 2fb0e59acac..732241a758f 100644 --- a/source/libsmb/cliprint.c +++ b/source/libsmb/cliprint.c @@ -156,3 +156,108 @@ int cli_printjob_del(struct cli_state *cli, int job) } +/**************************************************************************** + Open a spool file +****************************************************************************/ + +int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_mode) +{ + char *p; + unsigned openfn=0; + unsigned accessmode=0; + + if (flags & O_CREAT) + openfn |= (1<<4); + if (!(flags & O_EXCL)) { + if (flags & O_TRUNC) + openfn |= (1<<1); + else + openfn |= (1<<0); + } + + accessmode = (share_mode<<4); + + if ((flags & O_ACCMODE) == O_RDWR) { + accessmode |= 2; + } else if ((flags & O_ACCMODE) == O_WRONLY) { + accessmode |= 1; + } + +#if defined(O_SYNC) + if ((flags & O_SYNC) == O_SYNC) { + accessmode |= (1<<14); + } +#endif /* O_SYNC */ + + if (share_mode == DENY_FCB) { + accessmode = 0xFF; + } + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,15,0,True); + + SCVAL(cli->outbuf,smb_com,SMBsplopen); + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,0xFF); + SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */ + SSVAL(cli->outbuf,smb_vwv3,accessmode); + SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN); + SSVAL(cli->outbuf,smb_vwv5,0); + SSVAL(cli->outbuf,smb_vwv8,openfn); + + if (cli->use_oplocks) { + /* if using oplocks then ask for a batch oplock via + core and extended methods */ + SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)| + FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK); + SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6); + } + + p = smb_buf(cli->outbuf); + p += clistr_push(cli, p, fname, -1, STR_TERMINATE); + + cli_setup_bcc(cli, p); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return -1; + } + + if (cli_is_error(cli)) { + return -1; + } + + return SVAL(cli->inbuf,smb_vwv2); +} + +/**************************************************************************** + Close a file. +****************************************************************************/ + +BOOL cli_spl_close(struct cli_state *cli, int fnum) +{ + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,3,0,True); + + SCVAL(cli->outbuf,smb_com,SMBsplclose); + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SIVALS(cli->outbuf,smb_vwv1,-1); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return False; + } + + return !cli_is_error(cli); +} + + diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c index 8cc5d8bf901..8e6742d4380 100644 --- a/source/libsmb/clirap.c +++ b/source/libsmb/clirap.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. client RAP calls - Copyright (C) Andrew Tridgell 1994-1998 + Copyright (C) Andrew Tridgell 1994-1998 + Copyright (C) Gerald (Jerry) Carter 2004 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 @@ -641,9 +642,80 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, return True; } + +/**************************************************************************** +send a qpathinfo BASIC_INFO call +****************************************************************************/ +BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name, + SMB_STRUCT_STAT *sbuf, uint32 *attributes ) +{ + unsigned int param_len = 0; + unsigned int data_len = 0; + uint16 setup = TRANSACT2_QPATHINFO; + char param[sizeof(pstring)+6]; + char *rparam=NULL, *rdata=NULL; + char *p; + pstring path; + int len; + + /* send full paths to dfs root shares */ + + if ( cli->dfsroot ) + pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name ); + else + pstrcpy( path, name ); + + /* cleanup */ + + len = strlen( path ); + if ( path[len] == '\\' ) + path[len] = '\0'; + + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO); + p += 6; + p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE); + param_len = PTR_DIFF(p, param); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + NULL, 0, cli->max_xmit /* data, length, max */ + )) { + return False; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return False; + } + + if (data_len < 36) { + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return False; + } + + sbuf->st_atime = interpret_long_date( rdata+8 ); + sbuf->st_mtime = interpret_long_date( rdata+16 ); + sbuf->st_ctime = interpret_long_date( rdata+24 ); + + *attributes = IVAL( rdata, 32 ); + + SAFE_FREE(rparam); + SAFE_FREE(rdata); + + return True; +} + /**************************************************************************** send a qfileinfo call ****************************************************************************/ + BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen) { unsigned int data_len = 0; diff --git a/source/libsmb/clisecdesc.c b/source/libsmb/clisecdesc.c index b79ea9d14ba..24757434794 100644 --- a/source/libsmb/clisecdesc.c +++ b/source/libsmb/clisecdesc.c @@ -30,6 +30,7 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum, char *rparam=NULL, *rdata=NULL; unsigned int rparam_count=0, rdata_count=0; prs_struct pd; + BOOL pd_initialized = False; SEC_DESC *psd = NULL; SIVAL(param, 0, fnum); @@ -56,7 +57,10 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum, if (cli_is_error(cli)) goto cleanup; - prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL); + if (!prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL)) { + goto cleanup; + } + pd_initialized = True; prs_copy_data_in(&pd, rdata, rdata_count); prs_set_offset(&pd,0); @@ -70,7 +74,8 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum, SAFE_FREE(rparam); SAFE_FREE(rdata); - prs_mem_free(&pd); + if (pd_initialized) + prs_mem_free(&pd); return psd; } diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c index eb1fce54392..4d9aaf989b1 100644 --- a/source/libsmb/ntlmssp.c +++ b/source/libsmb/ntlmssp.c @@ -393,7 +393,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, &neg_flags, &cliname, &domname)) { - DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n")); + DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate:\n")); dump_data(2, (const char *)request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } @@ -442,13 +442,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This creates the 'blob' of names that appears at the end of the packet */ if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { - const char *target_name_dns = ""; - if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) { - target_name_dns = dnsdomname; - } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) { - target_name_dns = dnsname; - } - msrpc_gen(&struct_blob, "aaaaa", NTLMSSP_NAME_TYPE_DOMAIN, target_name, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), @@ -546,8 +539,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &workstation, &encrypted_session_key, &auth_flags)) { - DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); - dump_data(2, (const char *)request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); @@ -570,7 +561,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &domain, &user, &workstation)) { - DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); + DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); dump_data(2, (const char *)request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); diff --git a/source/libsmb/ntlmssp_sign.c b/source/libsmb/ntlmssp_sign.c index ee0f9df0249..b8105970762 100644 --- a/source/libsmb/ntlmssp_sign.c +++ b/source/libsmb/ntlmssp_sign.c @@ -53,7 +53,7 @@ static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len) hash[257] = index_j; } -static void calc_hash(unsigned char hash[258], const char *k2, int k2l) +static void calc_hash(unsigned char hash[258], unsigned char *k2, int k2l) { unsigned char j = 0; int ind; @@ -390,7 +390,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n")); - calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 8); + calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8); dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); } else { @@ -402,7 +402,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n")); - calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 16); + calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16); dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); } |