2007-12-01 03:13:35 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-25 18:04:06 +04:00
client RAP calls
2005-02-23 20:29:28 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Gerald ( Jerry ) Carter 2004
2007-12-10 01:18:54 +03:00
Copyright ( C ) James Peach 2007
2007-12-01 03:13:35 +03:00
2000-04-25 18:04:06 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-04-25 18:04:06 +04:00
( at your option ) any later version .
2007-12-01 03:13:35 +03:00
2000-04-25 18:04:06 +04:00
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 .
2007-12-01 03:13:35 +03:00
2000-04-25 18:04:06 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-04-25 18:04:06 +04:00
*/
# include "includes.h"
2009-03-17 12:08:31 +03:00
# include "../libcli/auth/libcli_auth.h"
2010-04-26 17:42:47 +04:00
# include "../librpc/gen_ndr/rap.h"
2011-04-28 19:38:09 +04:00
# include "../lib/util/tevent_ntstatus.h"
2010-08-26 11:58:09 +04:00
# include "async_smb.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2011-02-24 12:46:55 +03:00
# include "libsmb/clirap.h"
2011-02-25 02:03:01 +03:00
# include "trans2.h"
2012-05-26 13:45:09 +04:00
# include "../libcli/smb/smbXcli_base.h"
2023-08-23 16:07:29 +03:00
# include "libcli/smb/reparse.h"
2017-07-21 22:41:11 +03:00
# include "cli_smb2_fnum.h"
2020-08-07 21:17:34 +03:00
# include "lib/util/string_wrappers.h"
2000-04-25 18:04:06 +04:00
2019-01-15 20:14:17 +03:00
# include <gnutls/gnutls.h>
# include <gnutls/crypto.h>
2000-04-25 18:04:06 +04:00
/****************************************************************************
2007-03-17 03:15:18 +03:00
Call a NetShareEnum - try and browse available connections on a host .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-17 03:15:18 +03:00
2024-08-18 21:48:48 +03:00
NTSTATUS cli_RNetShareEnum (
struct cli_state * cli ,
void ( * fn ) ( const char * , uint32_t , const char * , void * ) ,
void * state )
2000-04-25 18:04:06 +04:00
{
2024-08-18 21:36:45 +03:00
uint8_t * rparam = NULL ;
uint8_t * rdata = NULL ;
2024-08-18 21:19:56 +03:00
char * rdata_end = NULL ;
2024-08-18 21:36:45 +03:00
char * p = NULL ;
2003-08-15 05:42:30 +04:00
unsigned int rdrcnt , rprcnt ;
2007-12-01 03:13:35 +03:00
char param [ 1024 ] ;
2000-04-30 19:13:15 +04:00
int count = - 1 ;
2024-08-18 21:19:56 +03:00
int i , converter ;
2020-05-02 15:54:01 +03:00
int res ;
2024-08-18 21:36:45 +03:00
NTSTATUS status ;
2000-04-25 18:04:06 +04:00
2000-04-30 19:13:15 +04:00
/* now send a SMBtrans command with api RNetShareEnum */
p = param ;
SSVAL ( p , 0 , 0 ) ; /* api number */
p + = 2 ;
2007-12-01 03:13:35 +03:00
strlcpy ( p , " WrLeh " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , sizeof ( param ) , p ) ;
2007-12-01 03:13:35 +03:00
strlcpy ( p , " B13BWz " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , sizeof ( param ) , p ) ;
2000-04-30 19:13:15 +04:00
SSVAL ( p , 0 , 1 ) ;
/*
* Win2k needs a * smaller * buffer than 0xFFFF here -
* it returns " out of server memory " with 0xFFFF ! ! ! JRA .
*/
SSVAL ( p , 2 , 0xFFE0 ) ;
p + = 4 ;
2007-12-01 03:13:35 +03:00
2024-08-18 21:36:45 +03:00
status = cli_trans ( talloc_tos ( ) , /* mem_ctx */
cli , /* cli */
SMBtrans , /* cmd */
2024-08-18 22:45:58 +03:00
" \\ PIPE \\ LANMAN " , /* name */
2024-08-18 21:36:45 +03:00
0 , /* fid */
0 , /* function */
0 , /* flags */
NULL , /* setup */
0 , /* num_setup */
0 , /* max_setup */
( uint8_t * ) param , /* param */
PTR_DIFF ( p , param ) , /* num_param */
1024 , /* max_param */
NULL , /* data */
0 , /* num_data */
0xFFE0 , /* max_data, for W2K */
NULL , /* recv_flags2 */
NULL , /* rsetup */
0 , /* min_rsetup */
NULL , /* num_rsetup */
& rparam , /* rparam */
6 , /* min_rparam */
& rprcnt , /* num_rparam */
& rdata , /* rdata */
0 , /* min_rdata */
& rdrcnt ) ; /* num_rdata */
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-05-02 15:54:01 +03:00
DEBUG ( 4 , ( " NetShareEnum failed \n " ) ) ;
goto done ;
}
2024-08-18 21:36:45 +03:00
res = PULL_LE_U16 ( rparam , 0 ) ;
2020-05-02 15:54:01 +03:00
2024-08-18 21:19:56 +03:00
if ( ! ( res = = 0 | | res = = ERRmoredata ) ) {
DEBUG ( 4 , ( " NetShareEnum res=%d \n " , res ) ) ;
2024-08-18 21:48:48 +03:00
status = werror_to_ntstatus ( W_ERROR ( res ) ) ;
2024-08-18 21:19:56 +03:00
goto done ;
}
converter = SVAL ( rparam , 2 ) ;
2024-08-18 21:36:45 +03:00
rdata_end = ( char * ) rdata + rdrcnt ;
2024-08-18 21:19:56 +03:00
count = SVAL ( rparam , 4 ) ;
2024-08-18 21:36:45 +03:00
p = ( char * ) rdata ;
2020-05-02 15:54:01 +03:00
2024-08-18 21:19:56 +03:00
for ( i = 0 ; i < count ; i + + , p + = 20 ) {
char * sname ;
int type ;
int comment_offset ;
const char * cmnt ;
const char * p1 ;
char * s1 , * s2 ;
size_t len ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
if ( p + 20 > rdata_end ) {
2020-05-02 15:54:01 +03:00
TALLOC_FREE ( frame ) ;
2024-08-18 21:19:56 +03:00
break ;
2000-04-30 19:13:15 +04:00
}
2024-08-18 21:19:56 +03:00
sname = p ;
type = SVAL ( p , 14 ) ;
comment_offset = ( IVAL ( p , 16 ) & 0xFFFF ) - converter ;
if ( comment_offset < 0 | |
comment_offset > ( int ) rdrcnt ) {
TALLOC_FREE ( frame ) ;
break ;
}
2024-08-18 21:36:45 +03:00
cmnt = comment_offset ? ( ( char * ) rdata + comment_offset ) : " " ;
2024-08-18 21:19:56 +03:00
/* Work out the comment length. */
for ( p1 = cmnt , len = 0 ; * p1 & &
p1 < rdata_end ; len + + )
p1 + + ;
if ( ! * p1 ) {
len + + ;
}
pull_string_talloc ( frame , rdata , 0 ,
& s1 , sname , 14 , STR_ASCII ) ;
pull_string_talloc ( frame , rdata , 0 ,
& s2 , cmnt , len , STR_ASCII ) ;
if ( ! s1 | | ! s2 ) {
TALLOC_FREE ( frame ) ;
continue ;
}
fn ( s1 , type , s2 , state ) ;
TALLOC_FREE ( frame ) ;
2020-05-02 15:54:01 +03:00
}
2007-12-01 03:13:35 +03:00
2020-05-02 15:54:01 +03:00
done :
2024-08-18 21:36:45 +03:00
TALLOC_FREE ( rparam ) ;
TALLOC_FREE ( rdata ) ;
2007-12-01 03:13:35 +03:00
2024-08-18 21:48:48 +03:00
return status ;
2000-04-25 18:04:06 +04:00
}
/****************************************************************************
2007-03-17 03:15:18 +03:00
Call a NetServerEnum for the specified workgroup and servertype mask . This
function then calls the specified callback function for each name returned .
2000-04-25 18:04:06 +04:00
2007-03-17 03:15:18 +03:00
The callback function takes 4 arguments : the machine name , the server type ,
the comment and a state pointer .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-17 03:15:18 +03:00
2024-08-19 10:26:51 +03:00
NTSTATUS cli_NetServerEnum (
struct cli_state * cli ,
char * workgroup ,
uint32_t stype ,
void ( * fn ) ( const char * , uint32_t , const char * , void * ) ,
void * state )
2000-04-25 18:04:06 +04:00
{
2024-08-18 22:30:24 +03:00
uint8_t * rparam = NULL ;
uint8_t * rdata = NULL ;
2007-12-10 01:18:54 +03:00
char * rdata_end = NULL ;
2024-08-18 22:30:24 +03:00
uint32_t rdrcnt , rprcnt ;
2000-04-25 18:04:06 +04:00
char * p ;
2007-12-01 03:13:35 +03:00
char param [ 1024 ] ;
2000-04-25 18:04:06 +04:00
int uLevel = 1 ;
2007-11-20 04:43:28 +03:00
size_t len ;
2015-05-10 02:59:45 +03:00
uint32_t func = RAP_NetServerEnum2 ;
2007-12-10 01:18:54 +03:00
char * last_entry = NULL ;
int total_cnt = 0 ;
int return_cnt = 0 ;
int res ;
2024-08-18 22:30:24 +03:00
NTSTATUS status ;
2001-01-04 14:35:55 +03:00
2007-12-10 01:18:54 +03:00
/*
* This may take more than one transaction , so we should loop until
* we no longer get a more data to process or we have all of the
* items .
*/
do {
/* send a SMBtrans command with api NetServerEnum */
p = param ;
SIVAL ( p , 0 , func ) ; /* api number */
p + = 2 ;
2010-02-08 20:38:03 +03:00
if ( func = = RAP_NetServerEnum3 ) {
strlcpy ( p , " WrLehDzz " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
2007-12-10 01:18:54 +03:00
} else {
strlcpy ( p , " WrLehDz " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
}
2007-12-01 03:13:35 +03:00
2007-12-10 01:18:54 +03:00
p = skip_string ( param , sizeof ( param ) , p ) ;
strlcpy ( p , " B16BBDz " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
p = skip_string ( param , sizeof ( param ) , p ) ;
SSVAL ( p , 0 , uLevel ) ;
SSVAL ( p , 2 , CLI_BUFFER_SIZE ) ;
p + = 4 ;
SIVAL ( p , 0 , stype ) ;
p + = 4 ;
/* If we have more data, tell the server where
* to continue from .
*/
len = push_ascii ( p ,
2010-02-08 20:38:03 +03:00
workgroup ,
2007-12-10 01:18:54 +03:00
sizeof ( param ) - PTR_DIFF ( p , param ) - 1 ,
STR_TERMINATE | STR_UPPER ) ;
2014-06-08 08:51:44 +04:00
if ( len = = 0 ) {
2008-01-10 00:25:52 +03:00
SAFE_FREE ( last_entry ) ;
2024-08-19 10:26:51 +03:00
return NT_STATUS_INTERNAL_ERROR ;
2007-12-10 01:18:54 +03:00
}
p + = len ;
2001-01-04 14:35:55 +03:00
2010-02-08 20:38:03 +03:00
if ( func = = RAP_NetServerEnum3 ) {
len = push_ascii ( p ,
last_entry ? last_entry : " " ,
sizeof ( param ) - PTR_DIFF ( p , param ) - 1 ,
STR_TERMINATE ) ;
2014-06-08 08:51:44 +04:00
if ( len = = 0 ) {
2010-02-08 20:38:03 +03:00
SAFE_FREE ( last_entry ) ;
2024-08-19 10:26:51 +03:00
return NT_STATUS_INTERNAL_ERROR ;
2010-02-08 20:38:03 +03:00
}
p + = len ;
}
/* Next time through we need to use the continue api */
func = RAP_NetServerEnum3 ;
2024-08-18 22:30:24 +03:00
status = cli_trans ( talloc_tos ( ) , /* mem_ctx */
cli , /* cli */
SMBtrans , /* cmd */
2024-08-18 22:45:58 +03:00
" \\ PIPE \\ LANMAN " , /* name */
2024-08-18 22:30:24 +03:00
0 , /* fid */
0 , /* function */
0 , /* flags */
NULL , /* setup */
0 , /* num_setup */
0 , /* max_setup */
( uint8_t * ) param , /* param */
PTR_DIFF ( p , param ) , /* num_param */
8 , /* max_param */
NULL , /* data */
0 , /* num_data */
CLI_BUFFER_SIZE , /* max_data */
NULL , /* recv_flags2 */
NULL , /* rsetup */
0 , /* min_rsetup */
NULL , /* num_rsetup */
& rparam , /* rparam */
6 , /* min_rparam */
& rprcnt , /* num_rparam */
& rdata , /* rdata */
0 , /* min_rdata */
& rdrcnt ) ; /* num_rdata */
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-12-10 01:18:54 +03:00
/* break out of the loop on error */
res = - 1 ;
break ;
}
2007-12-01 03:13:35 +03:00
2024-08-18 22:30:24 +03:00
rdata_end = ( char * ) rdata + rdrcnt ;
2020-05-02 16:10:14 +03:00
2024-08-18 22:30:24 +03:00
res = PULL_LE_U16 ( rparam , 0 ) ;
2007-12-01 03:13:35 +03:00
2024-08-19 10:10:03 +03:00
if ( res = = 0 | | res = = ERRmoredata ) {
2007-12-10 01:18:54 +03:00
char * sname = NULL ;
int i , count ;
2000-04-30 19:13:15 +04:00
int converter = SVAL ( rparam , 2 ) ;
2007-12-10 01:18:54 +03:00
/* Get the number of items returned in this buffer */
count = SVAL ( rparam , 4 ) ;
/* The next field contains the number of items left,
* including those returned in this buffer . So the
* first time through this should contain all of the
* entries .
*/
if ( total_cnt = = 0 ) {
total_cnt = SVAL ( rparam , 6 ) ;
}
/* Keep track of how many we have read */
return_cnt + = count ;
2024-08-18 22:30:24 +03:00
p = ( char * ) rdata ;
2007-12-01 03:13:35 +03:00
2007-12-10 01:18:54 +03:00
/* The last name in the previous NetServerEnum reply is
* sent back to server in the NetServerEnum3 request
* ( last_entry ) . The next reply should repeat this entry
* as the first element . We have no proof that this is
* always true , but from traces that seems to be the
* behavior from Window Servers . So first lets do a lot
* of checking , just being paranoid . If the string
* matches then we already saw this entry so skip it .
*
* NOTE : sv1_name field must be null terminated and has
* a max size of 16 ( NetBIOS Name ) .
*/
if ( last_entry & & count & & p & &
( strncmp ( last_entry , p , 16 ) = = 0 ) ) {
count - = 1 ; /* Skip this entry */
return_cnt = - 1 ; /* Not part of total, so don't count. */
2024-08-18 22:30:24 +03:00
p = ( char * ) rdata + 26 ; /* Skip the whole record */
2007-12-10 01:18:54 +03:00
}
for ( i = 0 ; i < count ; i + + , p + = 26 ) {
2007-12-01 03:13:35 +03:00
int comment_offset ;
const char * cmnt ;
const char * p1 ;
char * s1 , * s2 ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2010-02-04 16:03:20 +03:00
uint32_t entry_stype ;
2007-12-01 03:13:35 +03:00
if ( p + 26 > rdata_end ) {
TALLOC_FREE ( frame ) ;
break ;
}
sname = p ;
comment_offset = ( IVAL ( p , 22 ) & 0xFFFF ) - converter ;
2024-08-18 22:30:24 +03:00
cmnt = comment_offset ? ( ( char * ) rdata +
comment_offset )
: " " ;
2001-06-21 05:01:15 +04:00
2010-02-09 23:17:08 +03:00
if ( comment_offset < 0 | | comment_offset > = ( int ) rdrcnt ) {
2007-12-01 03:13:35 +03:00
TALLOC_FREE ( frame ) ;
continue ;
}
/* Work out the comment length. */
for ( p1 = cmnt , len = 0 ; * p1 & &
p1 < rdata_end ; len + + )
p1 + + ;
if ( ! * p1 ) {
len + + ;
}
2001-01-04 14:35:55 +03:00
2010-02-04 16:03:20 +03:00
entry_stype = IVAL ( p , 18 ) & ~ SV_TYPE_LOCAL_LIST_ONLY ;
2001-01-04 14:35:55 +03:00
2007-12-01 03:13:35 +03:00
pull_string_talloc ( frame , rdata , 0 ,
& s1 , sname , 16 , STR_ASCII ) ;
pull_string_talloc ( frame , rdata , 0 ,
& s2 , cmnt , len , STR_ASCII ) ;
if ( ! s1 | | ! s2 ) {
TALLOC_FREE ( frame ) ;
continue ;
}
2010-02-04 16:03:20 +03:00
fn ( s1 , entry_stype , s2 , state ) ;
2007-12-01 03:13:35 +03:00
TALLOC_FREE ( frame ) ;
2000-04-25 18:04:06 +04:00
}
2007-12-10 01:18:54 +03:00
/* We are done with the old last entry, so now we can free it */
if ( last_entry ) {
SAFE_FREE ( last_entry ) ; /* This will set it to null */
}
/* We always make a copy of the last entry if we have one */
if ( sname ) {
last_entry = smb_xstrdup ( sname ) ;
}
/* If we have more data, but no last entry then error out */
if ( ! last_entry & & ( res = = ERRmoredata ) ) {
res = 0 ;
}
2000-04-25 18:04:06 +04:00
}
2007-12-10 01:18:54 +03:00
2024-08-18 22:30:24 +03:00
TALLOC_FREE ( rparam ) ;
TALLOC_FREE ( rdata ) ;
2007-12-10 01:18:54 +03:00
} while ( ( res = = ERRmoredata ) & & ( total_cnt > return_cnt ) ) ;
2007-12-01 03:13:35 +03:00
2024-08-18 22:30:24 +03:00
TALLOC_FREE ( rparam ) ;
TALLOC_FREE ( rdata ) ;
2007-12-10 01:18:54 +03:00
SAFE_FREE ( last_entry ) ;
2004-05-09 00:15:52 +04:00
2024-08-19 10:26:51 +03:00
if ( return_cnt = = 0 ) {
return NT_STATUS_NO_MORE_ENTRIES ;
}
return NT_STATUS_OK ;
2000-04-25 18:04:06 +04:00
}
/****************************************************************************
2007-03-17 03:15:18 +03:00
Send a SamOEMChangePassword command .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-17 03:15:18 +03:00
2024-08-18 13:55:34 +03:00
NTSTATUS cli_oem_change_password ( struct cli_state * cli ,
const char * user ,
const char * new_password ,
const char * old_password )
2000-04-25 18:04:06 +04:00
{
2007-12-01 03:13:35 +03:00
char param [ 1024 ] ;
2024-08-18 10:37:13 +03:00
uint8_t data [ 532 ] ;
2007-03-17 03:15:18 +03:00
char * p = param ;
unsigned char old_pw_hash [ 16 ] ;
unsigned char new_pw_hash [ 16 ] ;
unsigned int param_len = 0 ;
2024-08-18 10:37:13 +03:00
uint8_t * rparam = NULL ;
2024-08-18 13:37:13 +03:00
uint32_t rprcnt ;
2019-01-15 20:14:17 +03:00
gnutls_cipher_hd_t cipher_hnd = NULL ;
gnutls_datum_t old_pw_key = {
. data = old_pw_hash ,
. size = sizeof ( old_pw_hash ) ,
} ;
2024-08-20 16:13:52 +03:00
int rc , res ;
2024-08-18 10:37:13 +03:00
NTSTATUS status ;
2007-03-17 03:15:18 +03:00
if ( strlen ( user ) > = sizeof ( fstring ) - 1 ) {
2024-08-05 18:11:43 +03:00
DBG_ERR ( " user name %s is too long. \n " , user ) ;
2024-08-18 13:55:34 +03:00
return NT_STATUS_NAME_TOO_LONG ;
2007-03-17 03:15:18 +03:00
}
SSVAL ( p , 0 , 214 ) ; /* SamOEMChangePassword command. */
p + = 2 ;
2007-12-01 03:13:35 +03:00
strlcpy ( p , " zsT " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , sizeof ( param ) , p ) ;
2007-12-01 03:13:35 +03:00
strlcpy ( p , " B516B16 " , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , sizeof ( param ) , p ) ;
2007-12-01 03:13:35 +03:00
strlcpy ( p , user , sizeof ( param ) - PTR_DIFF ( p , param ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , sizeof ( param ) , p ) ;
2007-03-17 03:15:18 +03:00
SSVAL ( p , 0 , 532 ) ;
p + = 2 ;
param_len = PTR_DIFF ( p , param ) ;
/*
* Get the Lanman hash of the old password , we
* use this as the key to make_oem_passwd_hash ( ) .
*/
E_deshash ( old_password , old_pw_hash ) ;
encode_pw_buffer ( data , new_password , STR_ASCII ) ;
2007-12-01 03:13:35 +03:00
2004-01-26 11:45:02 +03:00
# ifdef DEBUG_PASSWORD
2007-03-17 03:15:18 +03:00
DEBUG ( 100 , ( " make_oem_passwd_hash \n " ) ) ;
2007-03-28 17:34:59 +04:00
dump_data ( 100 , data , 516 ) ;
2004-01-26 11:45:02 +03:00
# endif
2019-01-15 20:14:17 +03:00
rc = gnutls_cipher_init ( & cipher_hnd ,
GNUTLS_CIPHER_ARCFOUR_128 ,
& old_pw_key ,
NULL ) ;
if ( rc < 0 ) {
DBG_ERR ( " gnutls_cipher_init failed: %s \n " ,
gnutls_strerror ( rc ) ) ;
2024-08-18 13:55:34 +03:00
status = gnutls_error_to_ntstatus (
rc , NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
return status ;
2019-01-15 20:14:17 +03:00
}
rc = gnutls_cipher_encrypt ( cipher_hnd ,
data ,
516 ) ;
gnutls_cipher_deinit ( cipher_hnd ) ;
if ( rc < 0 ) {
2024-08-18 13:55:34 +03:00
status = gnutls_error_to_ntstatus (
rc , NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
return status ;
2019-01-15 20:14:17 +03:00
}
2000-04-25 18:04:06 +04:00
2007-12-01 03:13:35 +03:00
/*
2007-03-17 03:15:18 +03:00
* Now place the old password hash in the data .
*/
E_deshash ( new_password , new_pw_hash ) ;
2000-04-25 18:04:06 +04:00
2019-11-20 17:28:39 +03:00
rc = E_old_pw_hash ( new_pw_hash , old_pw_hash , ( uchar * ) & data [ 516 ] ) ;
if ( rc ! = 0 ) {
DBG_ERR ( " E_old_pw_hash failed: %s \n " , gnutls_strerror ( rc ) ) ;
2024-08-18 13:55:34 +03:00
status = gnutls_error_to_ntstatus (
rc , NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
return status ;
2019-11-20 17:28:39 +03:00
}
2000-04-25 18:04:06 +04:00
2024-08-18 10:37:13 +03:00
status = cli_trans ( talloc_tos ( ) , /* mem_ctx */
cli , /* cli */
SMBtrans , /* cmd */
2024-08-18 22:45:58 +03:00
" \\ PIPE \\ LANMAN " , /* name */
2024-08-18 10:37:13 +03:00
0 , /* fid */
0 , /* function */
0 , /* flags */
NULL , /* setup */
0 , /* num_setup */
0 , /* max_setup */
( uint8_t * ) param , /* param */
param_len , /* num_param */
4 , /* max_param */
data , /* data */
2024-08-18 12:22:13 +03:00
sizeof ( data ) , /* num_data */
2024-08-18 10:37:13 +03:00
0 , /* max_data */
NULL , /* recv_flags2 */
NULL , /* rsetup */
0 , /* min_rsetup */
NULL , /* num_rsetup */
& rparam , /* rparam */
2024-08-18 13:37:13 +03:00
2 , /* min_rparam */
2024-08-18 10:37:13 +03:00
& rprcnt , /* num_rparam */
2024-08-18 13:37:13 +03:00
NULL , /* rdata */
2024-08-18 10:37:13 +03:00
0 , /* min_rdata */
2024-08-18 13:37:13 +03:00
NULL ) ; /* num_rdata */
2024-08-18 10:37:13 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2024-08-18 13:55:34 +03:00
return status ;
2007-03-17 03:15:18 +03:00
}
2024-08-20 16:13:52 +03:00
res = PULL_LE_U16 ( rparam , 0 ) ;
2000-04-25 18:04:06 +04:00
2024-08-20 16:13:52 +03:00
status = werror_to_ntstatus ( W_ERROR ( res ) ) ;
2024-08-18 13:55:34 +03:00
2024-08-18 10:37:13 +03:00
TALLOC_FREE ( rparam ) ;
2000-04-25 18:04:06 +04:00
2024-08-18 13:55:34 +03:00
return status ;
2000-04-25 18:04:06 +04:00
}
2020-03-30 17:47:52 +03:00
static void prep_basic_information_buf (
uint8_t buf [ 40 ] ,
struct timespec create_time ,
struct timespec access_time ,
struct timespec write_time ,
struct timespec change_time ,
2020-06-04 06:48:23 +03:00
uint32_t attr )
2019-12-01 11:01:13 +03:00
{
2020-03-30 17:47:52 +03:00
char * p = ( char * ) buf ;
2019-12-01 11:01:13 +03:00
/*
* Add the create , last access , modification , and status change times
*/
2020-03-26 16:33:58 +03:00
put_long_date_full_timespec (
TIMESTAMP_SET_NT_OR_BETTER , p , & create_time ) ;
2019-12-01 11:01:13 +03:00
p + = 8 ;
2020-03-26 16:33:58 +03:00
put_long_date_full_timespec (
TIMESTAMP_SET_NT_OR_BETTER , p , & access_time ) ;
2019-12-01 11:01:13 +03:00
p + = 8 ;
2020-03-26 16:33:58 +03:00
put_long_date_full_timespec (
TIMESTAMP_SET_NT_OR_BETTER , p , & write_time ) ;
2019-12-01 11:01:13 +03:00
p + = 8 ;
2020-03-26 16:33:58 +03:00
put_long_date_full_timespec (
TIMESTAMP_SET_NT_OR_BETTER , p , & change_time ) ;
2019-12-01 11:01:13 +03:00
p + = 8 ;
2020-06-04 06:48:23 +03:00
if ( attr = = ( uint32_t ) - 1 | | attr = = FILE_ATTRIBUTE_NORMAL ) {
2019-12-01 11:01:13 +03:00
/* No change. */
2020-06-03 21:01:36 +03:00
attr = 0 ;
} else if ( attr = = 0 ) {
2019-12-01 11:01:13 +03:00
/* Clear all existing attributes. */
2020-06-03 21:01:36 +03:00
attr = FILE_ATTRIBUTE_NORMAL ;
2019-12-01 11:01:13 +03:00
}
/* Add attributes */
2020-06-03 21:01:36 +03:00
SIVAL ( p , 0 , attr ) ;
2019-12-01 11:01:13 +03:00
p + = 4 ;
/* Add padding */
SIVAL ( p , 0 , 0 ) ;
p + = 4 ;
2020-03-30 17:47:52 +03:00
SMB_ASSERT ( PTR_DIFF ( p , buf ) = = 40 ) ;
}
NTSTATUS cli_setpathinfo_ext ( struct cli_state * cli , const char * fname ,
struct timespec create_time ,
struct timespec access_time ,
struct timespec write_time ,
struct timespec change_time ,
2020-06-04 06:48:23 +03:00
uint32_t attr )
2020-03-30 17:47:52 +03:00
{
uint8_t buf [ 40 ] ;
prep_basic_information_buf (
buf ,
create_time ,
access_time ,
write_time ,
change_time ,
2020-06-03 21:01:36 +03:00
attr ) ;
2019-12-01 11:01:13 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2020-03-30 17:47:52 +03:00
DATA_BLOB in_data = data_blob_const ( buf , sizeof ( buf ) ) ;
2019-12-01 11:01:13 +03:00
/*
* Split out SMB2 here as we need to select
* the correct info type and level .
*/
return cli_smb2_setpathinfo ( cli ,
2024-05-17 13:23:19 +03:00
fname ,
2024-05-17 13:32:20 +03:00
SMB2_0_INFO_FILE ,
2024-05-17 13:23:19 +03:00
FSCC_FILE_BASIC_INFORMATION ,
& in_data ) ;
2019-12-01 11:01:13 +03:00
}
2020-03-30 17:47:52 +03:00
return cli_setpathinfo (
cli , SMB_FILE_BASIC_INFORMATION , fname , buf , sizeof ( buf ) ) ;
2019-12-01 11:01:13 +03:00
}
2020-03-30 18:54:28 +03:00
struct cli_setfileinfo_ext_state {
uint8_t data [ 40 ] ;
DATA_BLOB in_data ;
} ;
static void cli_setfileinfo_ext_done ( struct tevent_req * subreq ) ;
static void cli_setfileinfo_ext_done2 ( struct tevent_req * subreq ) ;
struct tevent_req * cli_setfileinfo_ext_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t fnum ,
struct timespec create_time ,
struct timespec access_time ,
struct timespec write_time ,
struct timespec change_time ,
2020-06-04 06:58:06 +03:00
uint32_t attr )
2020-03-30 18:54:28 +03:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_setfileinfo_ext_state * state = NULL ;
req = tevent_req_create (
mem_ctx , & state , struct cli_setfileinfo_ext_state ) ;
if ( req = = NULL ) {
return NULL ;
}
prep_basic_information_buf (
state - > data ,
create_time ,
access_time ,
write_time ,
change_time ,
2020-06-04 06:58:06 +03:00
attr ) ;
2020-03-30 18:54:28 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
state - > in_data = ( DATA_BLOB ) {
. data = state - > data , . length = sizeof ( state - > data ) ,
} ;
subreq = cli_smb2_set_info_fnum_send (
state ,
ev ,
cli ,
fnum ,
SMB2_0_INFO_FILE ,
2024-05-17 13:23:19 +03:00
FSCC_FILE_BASIC_INFORMATION ,
2020-03-30 18:54:28 +03:00
& state - > in_data ,
2024-05-17 13:23:19 +03:00
0 ) ; /* in_additional_info */
2020-03-30 18:54:28 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback (
subreq , cli_setfileinfo_ext_done2 , req ) ;
return req ;
}
subreq = cli_setfileinfo_send (
state ,
ev ,
cli ,
fnum ,
SMB_FILE_BASIC_INFORMATION ,
state - > data ,
sizeof ( state - > data ) ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_setfileinfo_ext_done , req ) ;
return req ;
}
static void cli_setfileinfo_ext_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_setfileinfo_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static void cli_setfileinfo_ext_done2 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_set_info_fnum_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
NTSTATUS cli_setfileinfo_ext_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_setfileinfo_ext (
struct cli_state * cli ,
uint16_t fnum ,
struct timespec create_time ,
struct timespec access_time ,
struct timespec write_time ,
struct timespec change_time ,
2020-06-04 06:58:06 +03:00
uint32_t attr )
2020-03-30 18:54:28 +03:00
{
TALLOC_CTX * frame = NULL ;
struct tevent_context * ev = NULL ;
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
/*
* Can ' t use sync call while an async call is in flight
*/
return NT_STATUS_INVALID_PARAMETER ;
}
frame = talloc_stackframe ( ) ;
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
goto fail ;
}
req = cli_setfileinfo_ext_send (
ev ,
ev ,
cli ,
fnum ,
create_time ,
access_time ,
write_time ,
change_time ,
2020-06-03 21:01:36 +03:00
attr ) ;
2020-03-30 18:54:28 +03:00
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_setfileinfo_ext_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2007-03-17 03:15:18 +03:00
Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-08-24 02:33:50 +04:00
2010-07-26 11:27:11 +04:00
struct cli_qpathinfo2_state {
2023-08-23 16:07:29 +03:00
struct tevent_context * ev ;
struct cli_state * cli ;
const char * fname ;
2023-04-03 19:31:01 +03:00
struct timespec create_time ;
struct timespec access_time ;
struct timespec write_time ;
struct timespec change_time ;
off_t size ;
uint32_t attr ;
SMB_INO_T ino ;
2023-08-23 16:07:29 +03:00
mode_t mode ;
2010-07-26 11:27:11 +04:00
} ;
2023-04-04 10:36:08 +03:00
static void cli_qpathinfo2_done2 ( struct tevent_req * subreq ) ;
2010-07-26 11:27:11 +04:00
static void cli_qpathinfo2_done ( struct tevent_req * subreq ) ;
2023-08-23 16:07:29 +03:00
static void cli_qpathinfo2_got_reparse ( struct tevent_req * subreq ) ;
2010-07-26 11:27:11 +04:00
struct tevent_req * cli_qpathinfo2_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2010-07-26 11:27:11 +04:00
struct cli_state * cli ,
const char * fname )
2000-04-25 18:04:06 +04:00
{
2010-07-26 11:27:11 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_qpathinfo2_state * state = NULL ;
2000-04-25 18:04:06 +04:00
2010-07-26 11:27:11 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_qpathinfo2_state ) ;
if ( req = = NULL ) {
return NULL ;
2007-12-06 00:31:24 +03:00
}
2023-08-23 16:07:29 +03:00
state - > ev = ev ;
state - > cli = cli ;
state - > fname = fname ;
state - > mode = S_IFREG ;
2023-04-04 10:36:08 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2023-08-18 17:07:56 +03:00
subreq = cli_smb2_qpathinfo_send ( state ,
ev ,
cli ,
fname ,
FSCC_FILE_ALL_INFORMATION ,
0x60 ,
UINT16_MAX ) ;
2023-04-04 10:36:08 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_qpathinfo2_done2 , req ) ;
return req ;
}
2010-07-26 11:27:11 +04:00
subreq = cli_qpathinfo_send ( state , ev , cli , fname ,
SMB_QUERY_FILE_ALL_INFO ,
2011-08-03 01:05:31 +04:00
68 , CLI_BUFFER_SIZE ) ;
2010-07-26 11:27:11 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_qpathinfo2_done , req ) ;
return req ;
}
2000-04-25 18:04:06 +04:00
2023-04-04 10:36:08 +03:00
static void cli_qpathinfo2_done2 ( struct tevent_req * subreq )
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
struct cli_qpathinfo2_state * state =
tevent_req_data ( req , struct cli_qpathinfo2_state ) ;
2023-08-18 17:07:56 +03:00
uint8_t * rdata = NULL ;
uint32_t num_rdata ;
2023-04-04 10:36:08 +03:00
NTSTATUS status ;
2023-08-18 17:07:56 +03:00
status = cli_smb2_qpathinfo_recv ( subreq , state , & rdata , & num_rdata ) ;
2023-04-04 10:36:08 +03:00
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2023-10-04 14:25:21 +03:00
state - > create_time = interpret_long_date ( BVAL ( rdata , 0x0 ) ) ;
state - > access_time = interpret_long_date ( BVAL ( rdata , 0x8 ) ) ;
state - > write_time = interpret_long_date ( BVAL ( rdata , 0x10 ) ) ;
state - > change_time = interpret_long_date ( BVAL ( rdata , 0x18 ) ) ;
2023-08-18 17:07:56 +03:00
state - > attr = PULL_LE_U32 ( rdata , 0x20 ) ;
state - > size = PULL_LE_U64 ( rdata , 0x30 ) ;
state - > ino = PULL_LE_U64 ( rdata , 0x40 ) ;
2023-08-23 16:07:29 +03:00
if ( state - > attr & FILE_ATTRIBUTE_REPARSE_POINT ) {
subreq = cli_get_reparse_data_send ( state ,
state - > ev ,
state - > cli ,
state - > fname ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq ,
cli_qpathinfo2_got_reparse ,
req ) ;
return ;
}
2023-04-04 10:36:08 +03:00
tevent_req_done ( req ) ;
}
2010-07-26 11:27:11 +04:00
static void cli_qpathinfo2_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qpathinfo2_state * state = tevent_req_data (
req , struct cli_qpathinfo2_state ) ;
2023-04-03 19:31:01 +03:00
uint8_t * data = NULL ;
uint32_t num_data ;
2010-07-26 11:27:11 +04:00
NTSTATUS status ;
2000-04-25 18:04:06 +04:00
2023-04-03 19:31:01 +03:00
status = cli_qpathinfo_recv ( subreq , state , & data , & num_data ) ;
2010-07-26 11:27:11 +04:00
TALLOC_FREE ( subreq ) ;
2023-08-16 12:59:03 +03:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-26 11:27:11 +04:00
return ;
2000-04-25 18:04:06 +04:00
}
2023-04-03 19:31:01 +03:00
2023-10-04 14:25:21 +03:00
state - > create_time = interpret_long_date ( BVAL ( data , 0 ) ) ;
state - > access_time = interpret_long_date ( BVAL ( data , 8 ) ) ;
state - > write_time = interpret_long_date ( BVAL ( data , 16 ) ) ;
state - > change_time = interpret_long_date ( BVAL ( data , 24 ) ) ;
2023-04-03 19:31:01 +03:00
state - > attr = PULL_LE_U32 ( data , 32 ) ;
state - > size = PULL_LE_U64 ( data , 48 ) ;
/*
* SMB1 qpathinfo2 uses SMB_QUERY_FILE_ALL_INFO which doesn ' t
* return an inode number ( fileid ) . We can ' t change this to
* one of the FILE_ID info levels as only Win2003 and above
* support these [ MS - SMB : 2.2 .2 .3 .1 ] and the SMB1 code needs
* to support older servers .
*/
state - > ino = 0 ;
TALLOC_FREE ( data ) ;
2023-08-23 16:07:29 +03:00
if ( state - > attr & FILE_ATTRIBUTE_REPARSE_POINT ) {
subreq = cli_get_reparse_data_send ( state ,
state - > ev ,
state - > cli ,
state - > fname ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq ,
cli_qpathinfo2_got_reparse ,
req ) ;
return ;
}
tevent_req_done ( req ) ;
}
static void cli_qpathinfo2_got_reparse ( struct tevent_req * subreq )
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
struct cli_qpathinfo2_state * state =
tevent_req_data ( req , struct cli_qpathinfo2_state ) ;
uint8_t * data = NULL ;
uint32_t num_data ;
struct reparse_data_buffer reparse = {
. tag = 0 ,
} ;
NTSTATUS status ;
status = cli_get_reparse_data_recv ( subreq , state , & data , & num_data ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
status = reparse_data_buffer_parse ( state , & reparse , data , num_data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " Ignoring unknown reparse data \n " ) ;
goto done ;
}
switch ( reparse . tag ) {
case IO_REPARSE_TAG_SYMLINK :
state - > mode = S_IFLNK ;
break ;
case IO_REPARSE_TAG_NFS :
switch ( reparse . parsed . nfs . type ) {
case NFS_SPECFILE_LNK :
state - > mode = S_IFLNK ;
break ;
case NFS_SPECFILE_CHR :
state - > mode = S_IFCHR ;
break ;
case NFS_SPECFILE_BLK :
state - > mode = S_IFBLK ;
break ;
case NFS_SPECFILE_FIFO :
state - > mode = S_IFIFO ;
break ;
case NFS_SPECFILE_SOCK :
state - > mode = S_IFSOCK ;
break ;
}
break ;
}
done :
2010-07-26 11:27:11 +04:00
tevent_req_done ( req ) ;
}
2000-04-25 18:04:06 +04:00
2010-07-26 11:27:11 +04:00
NTSTATUS cli_qpathinfo2_recv ( struct tevent_req * req ,
struct timespec * create_time ,
struct timespec * access_time ,
struct timespec * write_time ,
struct timespec * change_time ,
2023-08-23 14:47:20 +03:00
off_t * size ,
uint32_t * pattr ,
SMB_INO_T * ino ,
mode_t * mode )
2010-07-26 11:27:11 +04:00
{
struct cli_qpathinfo2_state * state = tevent_req_data (
req , struct cli_qpathinfo2_state ) ;
NTSTATUS status ;
2000-04-25 18:04:06 +04:00
2010-07-26 11:27:11 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
2000-04-25 18:04:06 +04:00
}
2007-12-01 03:13:35 +03:00
2006-08-24 02:33:50 +04:00
if ( create_time ) {
2023-04-03 19:31:01 +03:00
* create_time = state - > create_time ;
2000-04-25 18:04:06 +04:00
}
2006-08-24 02:33:50 +04:00
if ( access_time ) {
2023-04-03 19:31:01 +03:00
* access_time = state - > access_time ;
2000-04-25 18:04:06 +04:00
}
2006-08-24 02:33:50 +04:00
if ( write_time ) {
2023-04-03 19:31:01 +03:00
* write_time = state - > write_time ;
2005-12-25 05:00:21 +03:00
}
2006-08-24 02:33:50 +04:00
if ( change_time ) {
2023-04-03 19:31:01 +03:00
* change_time = state - > change_time ;
2000-04-25 18:04:06 +04:00
}
2020-06-03 21:01:36 +03:00
if ( pattr ) {
2023-04-03 19:31:01 +03:00
* pattr = state - > attr ;
2000-04-25 18:04:06 +04:00
}
if ( size ) {
2023-04-03 19:31:01 +03:00
* size = state - > size ;
2000-04-25 18:04:06 +04:00
}
if ( ino ) {
2023-04-03 19:31:01 +03:00
* ino = state - > ino ;
2000-04-25 18:04:06 +04:00
}
2023-08-23 14:47:20 +03:00
if ( mode ! = NULL ) {
2023-08-23 16:07:29 +03:00
* mode = state - > mode ;
2023-08-23 14:47:20 +03:00
}
2010-07-26 11:27:11 +04:00
return NT_STATUS_OK ;
}
2000-04-25 18:04:06 +04:00
2023-08-23 14:47:20 +03:00
NTSTATUS cli_qpathinfo2 ( struct cli_state * cli ,
const char * fname ,
2010-07-26 11:27:11 +04:00
struct timespec * create_time ,
struct timespec * access_time ,
struct timespec * write_time ,
struct timespec * change_time ,
2023-08-23 14:47:20 +03:00
off_t * size ,
uint32_t * pattr ,
SMB_INO_T * ino ,
mode_t * mode )
2010-07-26 11:27:11 +04:00
{
2023-07-05 12:58:39 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_context * ev = NULL ;
struct tevent_req * req = NULL ;
2010-07-26 11:27:11 +04:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-07-26 11:27:11 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-07-26 11:27:11 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_qpathinfo2_send ( frame , ev , cli , fname ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
2023-08-23 14:47:20 +03:00
status = cli_qpathinfo2_recv ( req ,
create_time ,
access_time ,
write_time ,
change_time ,
size ,
pattr ,
ino ,
mode ) ;
2010-07-26 11:27:11 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2000-04-25 18:04:06 +04:00
}
2008-01-18 13:08:17 +03:00
/****************************************************************************
Get the stream info
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-07-26 12:35:15 +04:00
struct cli_qpathinfo_streams_state {
uint32_t num_data ;
uint8_t * data ;
} ;
static void cli_qpathinfo_streams_done ( struct tevent_req * subreq ) ;
2023-08-18 16:47:20 +03:00
static void cli_qpathinfo_streams_done2 ( struct tevent_req * subreq ) ;
2010-07-26 12:35:15 +04:00
struct tevent_req * cli_qpathinfo_streams_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname )
2008-01-18 13:08:17 +03:00
{
2010-07-26 12:35:15 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_qpathinfo_streams_state * state = NULL ;
2008-01-18 13:08:17 +03:00
2010-07-26 12:35:15 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_qpathinfo_streams_state ) ;
if ( req = = NULL ) {
return NULL ;
2008-01-18 13:08:17 +03:00
}
2023-08-18 16:47:20 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_qpathinfo_send ( state ,
ev ,
cli ,
fname ,
FSCC_FILE_STREAM_INFORMATION ,
0 ,
CLI_BUFFER_SIZE ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq ,
cli_qpathinfo_streams_done2 ,
req ) ;
return req ;
}
2010-07-26 12:35:15 +04:00
subreq = cli_qpathinfo_send ( state , ev , cli , fname ,
SMB_FILE_STREAM_INFORMATION ,
2011-08-03 01:05:31 +04:00
0 , CLI_BUFFER_SIZE ) ;
2010-07-26 12:35:15 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_qpathinfo_streams_done , req ) ;
return req ;
}
2008-01-18 13:08:17 +03:00
2010-07-26 12:35:15 +04:00
static void cli_qpathinfo_streams_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qpathinfo_streams_state * state = tevent_req_data (
req , struct cli_qpathinfo_streams_state ) ;
NTSTATUS status ;
2008-01-18 13:08:17 +03:00
2010-07-26 12:35:15 +04:00
status = cli_qpathinfo_recv ( subreq , state , & state - > data ,
& state - > num_data ) ;
2023-08-18 16:47:20 +03:00
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static void cli_qpathinfo_streams_done2 ( struct tevent_req * subreq )
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
struct cli_qpathinfo_streams_state * state =
tevent_req_data ( req , struct cli_qpathinfo_streams_state ) ;
NTSTATUS status ;
status = cli_smb2_qpathinfo_recv ( subreq ,
state ,
& state - > data ,
& state - > num_data ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2010-07-26 12:35:15 +04:00
}
2008-01-18 13:08:17 +03:00
2010-07-26 12:35:15 +04:00
NTSTATUS cli_qpathinfo_streams_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
unsigned int * pnum_streams ,
struct stream_struct * * pstreams )
{
struct cli_qpathinfo_streams_state * state = tevent_req_data (
req , struct cli_qpathinfo_streams_state ) ;
NTSTATUS status ;
2008-01-18 13:08:17 +03:00
2010-07-26 12:35:15 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
if ( ! parse_streams_blob ( mem_ctx , state - > data , state - > num_data ,
pnum_streams , pstreams ) ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
2008-01-18 13:08:17 +03:00
}
2010-07-26 12:35:15 +04:00
return NT_STATUS_OK ;
}
2008-01-18 13:08:17 +03:00
2010-07-26 12:35:15 +04:00
NTSTATUS cli_qpathinfo_streams ( struct cli_state * cli , const char * fname ,
TALLOC_CTX * mem_ctx ,
unsigned int * pnum_streams ,
struct stream_struct * * pstreams )
{
2013-08-08 03:46:05 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2010-07-26 12:35:15 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2013-08-08 03:46:05 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-07-26 12:35:15 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-07-26 12:35:15 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_qpathinfo_streams_send ( frame , ev , cli , fname ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_qpathinfo_streams_recv ( req , mem_ctx , pnum_streams ,
pstreams ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2010-07-26 12:08:38 +04:00
}
2013-08-08 02:54:05 +04:00
bool parse_streams_blob ( TALLOC_CTX * mem_ctx , const uint8_t * rdata ,
2010-07-26 12:08:38 +04:00
size_t data_len ,
unsigned int * pnum_streams ,
struct stream_struct * * pstreams )
{
unsigned int num_streams ;
struct stream_struct * streams ;
unsigned int ofs ;
2008-01-18 13:08:17 +03:00
num_streams = 0 ;
streams = NULL ;
ofs = 0 ;
while ( ( data_len > ofs ) & & ( data_len - ofs > = 24 ) ) {
uint32_t nlen , len ;
2008-05-21 01:06:38 +04:00
size_t size ;
2008-01-18 13:08:17 +03:00
void * vstr ;
struct stream_struct * tmp ;
uint8_t * tmp_buf ;
2011-06-07 05:10:15 +04:00
tmp = talloc_realloc ( mem_ctx , streams ,
2008-01-18 13:08:17 +03:00
struct stream_struct ,
num_streams + 1 ) ;
if ( tmp = = NULL ) {
goto fail ;
}
streams = tmp ;
nlen = IVAL ( rdata , ofs + 0x04 ) ;
streams [ num_streams ] . size = IVAL_TO_SMB_OFF_T (
rdata , ofs + 0x08 ) ;
streams [ num_streams ] . alloc_size = IVAL_TO_SMB_OFF_T (
rdata , ofs + 0x10 ) ;
if ( nlen > data_len - ( ofs + 24 ) ) {
goto fail ;
}
/*
* We need to null - terminate src , how do I do this with
* convert_string_talloc ? ?
*/
2011-06-07 05:30:12 +04:00
tmp_buf = talloc_array ( streams , uint8_t , nlen + 2 ) ;
2008-01-18 13:08:17 +03:00
if ( tmp_buf = = NULL ) {
goto fail ;
}
memcpy ( tmp_buf , rdata + ofs + 24 , nlen ) ;
tmp_buf [ nlen ] = 0 ;
tmp_buf [ nlen + 1 ] = 0 ;
2008-04-30 01:36:24 +04:00
if ( ! convert_string_talloc ( streams , CH_UTF16 , CH_UNIX , tmp_buf ,
2011-03-24 02:59:41 +03:00
nlen + 2 , & vstr , & size ) )
2008-04-30 01:36:24 +04:00
{
TALLOC_FREE ( tmp_buf ) ;
2008-01-18 13:08:17 +03:00
goto fail ;
}
2008-04-30 01:36:24 +04:00
TALLOC_FREE ( tmp_buf ) ;
2008-01-18 13:08:17 +03:00
streams [ num_streams ] . name = ( char * ) vstr ;
num_streams + + ;
len = IVAL ( rdata , ofs ) ;
if ( len > data_len - ofs ) {
goto fail ;
}
if ( len = = 0 ) break ;
ofs + = len ;
}
* pnum_streams = num_streams ;
* pstreams = streams ;
return true ;
fail :
TALLOC_FREE ( streams ) ;
return false ;
}
2002-02-21 07:25:17 +03:00
/****************************************************************************
2007-03-17 03:15:18 +03:00
Send a qfileinfo QUERY_FILE_NAME_INFO call .
2002-02-21 07:25:17 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-17 03:15:18 +03:00
2020-05-28 19:24:17 +03:00
struct cli_qfileinfo_basic_state {
uint32_t attr ;
off_t size ;
struct timespec create_time ;
struct timespec access_time ;
struct timespec write_time ;
struct timespec change_time ;
SMB_INO_T ino ;
} ;
2007-03-17 03:15:18 +03:00
2020-05-28 19:24:17 +03:00
static void cli_qfileinfo_basic_done ( struct tevent_req * subreq ) ;
2020-06-04 09:38:31 +03:00
static void cli_qfileinfo_basic_doneE ( struct tevent_req * subreq ) ;
2020-05-28 19:24:17 +03:00
struct tevent_req * cli_qfileinfo_basic_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t fnum )
2000-04-25 18:04:06 +04:00
{
2020-05-28 19:24:17 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_qfileinfo_basic_state * state = NULL ;
2000-04-25 18:04:06 +04:00
2020-05-28 19:24:17 +03:00
req = tevent_req_create (
mem_ctx , & state , struct cli_qfileinfo_basic_state ) ;
if ( req = = NULL ) {
return NULL ;
2013-08-08 03:47:21 +04:00
}
2020-06-04 09:38:31 +03:00
if ( ( smbXcli_conn_protocol ( cli - > conn ) < PROTOCOL_LANMAN2 ) | |
cli - > win95 ) {
/*
* According to
* https : //docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3d9d8f3e-dc70-410d-a3fc-6f4a881e8cab
* SMB_COM_TRANSACTION2 used in cli_qfileinfo_send ( )
* further down was introduced with the LAN Manager
* 1.2 dialect , which we encode as PROTOCOL_LANMAN2 .
*
* The " win95 " check was introduced with commit
* 27e5850 fd3e1c8 in 1998. Hard to check these days ,
* but leave it in .
*
* Use a lowerlevel fallback in both cases .
*/
subreq = cli_getattrE_send ( state , ev , cli , fnum ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback (
subreq , cli_qfileinfo_basic_doneE , req ) ;
return req ;
2010-10-24 00:37:16 +04:00
}
2000-04-25 18:04:06 +04:00
2024-05-09 11:12:14 +03:00
subreq = cli_qfileinfo_send ( state ,
ev ,
cli ,
fnum ,
FSCC_FILE_ALL_INFORMATION , /* level */
68 , /* min_rdata */
CLI_BUFFER_SIZE ) ; /* max_rdata */
2020-05-28 19:24:17 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_qfileinfo_basic_done , req ) ;
return req ;
}
static void cli_qfileinfo_basic_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qfileinfo_basic_state * state = tevent_req_data (
req , struct cli_qfileinfo_basic_state ) ;
uint8_t * rdata ;
uint32_t num_rdata ;
NTSTATUS status ;
status = cli_qfileinfo_recv (
subreq , state , NULL , & rdata , & num_rdata ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2023-10-04 14:25:21 +03:00
state - > create_time = interpret_long_date ( BVAL ( rdata , 0 ) ) ;
state - > access_time = interpret_long_date ( BVAL ( rdata , 8 ) ) ;
state - > write_time = interpret_long_date ( BVAL ( rdata , 16 ) ) ;
state - > change_time = interpret_long_date ( BVAL ( rdata , 24 ) ) ;
2020-05-28 19:24:17 +03:00
state - > attr = PULL_LE_U32 ( rdata , 32 ) ;
state - > size = PULL_LE_U64 ( rdata , 48 ) ;
state - > ino = PULL_LE_U32 ( rdata , 64 ) ;
TALLOC_FREE ( rdata ) ;
tevent_req_done ( req ) ;
}
2020-06-04 09:38:31 +03:00
static void cli_qfileinfo_basic_doneE ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qfileinfo_basic_state * state = tevent_req_data (
req , struct cli_qfileinfo_basic_state ) ;
NTSTATUS status ;
status = cli_getattrE_recv (
subreq ,
& state - > attr ,
& state - > size ,
& state - > change_time . tv_sec ,
& state - > access_time . tv_sec ,
& state - > write_time . tv_sec ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
2020-05-28 19:24:17 +03:00
NTSTATUS cli_qfileinfo_basic_recv (
struct tevent_req * req ,
uint32_t * attr ,
off_t * size ,
struct timespec * create_time ,
struct timespec * access_time ,
struct timespec * write_time ,
struct timespec * change_time ,
SMB_INO_T * ino )
{
struct cli_qfileinfo_basic_state * state = tevent_req_data (
req , struct cli_qfileinfo_basic_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
2010-10-24 00:37:16 +04:00
return status ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
if ( create_time ! = NULL ) {
* create_time = state - > create_time ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
if ( access_time ! = NULL ) {
* access_time = state - > access_time ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
if ( write_time ! = NULL ) {
* write_time = state - > write_time ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
if ( change_time ! = NULL ) {
* change_time = state - > change_time ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
if ( attr ! = NULL ) {
* attr = state - > attr ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
if ( size ! = NULL ) {
* size = state - > size ;
2000-04-25 18:04:06 +04:00
}
if ( ino ) {
2020-05-28 19:24:17 +03:00
* ino = state - > ino ;
2000-04-25 18:04:06 +04:00
}
2010-10-24 00:37:16 +04:00
return NT_STATUS_OK ;
2000-04-25 18:04:06 +04:00
}
2020-05-28 19:24:17 +03:00
/****************************************************************************
Send a qfileinfo call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS cli_qfileinfo_basic (
struct cli_state * cli ,
uint16_t fnum ,
uint32_t * attr ,
off_t * size ,
struct timespec * create_time ,
struct timespec * access_time ,
struct timespec * write_time ,
struct timespec * change_time ,
SMB_INO_T * ino )
{
TALLOC_CTX * frame = NULL ;
struct tevent_context * ev = NULL ;
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
frame = talloc_stackframe ( ) ;
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
goto fail ;
}
req = cli_qfileinfo_basic_send ( frame , ev , cli , fnum ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_qfileinfo_basic_recv (
req ,
attr ,
size ,
create_time ,
access_time ,
write_time ,
change_time ,
ino ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
2005-02-23 20:29:28 +03:00
/****************************************************************************
2007-03-09 02:54:57 +03:00
Send a qpathinfo BASIC_INFO call .
2005-02-23 20:29:28 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-09 02:54:57 +03:00
2010-07-26 11:41:25 +04:00
struct cli_qpathinfo_basic_state {
uint32_t num_data ;
uint8_t * data ;
} ;
static void cli_qpathinfo_basic_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_qpathinfo_basic_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2010-07-26 11:41:25 +04:00
struct cli_state * cli ,
const char * fname )
2005-02-23 20:29:28 +03:00
{
2010-07-26 11:41:25 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_qpathinfo_basic_state * state = NULL ;
2007-12-01 03:13:35 +03:00
2010-07-26 11:41:25 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_qpathinfo_basic_state ) ;
if ( req = = NULL ) {
return NULL ;
2007-12-01 03:13:35 +03:00
}
2010-07-26 11:41:25 +04:00
subreq = cli_qpathinfo_send ( state , ev , cli , fname ,
SMB_QUERY_FILE_BASIC_INFO ,
2011-08-03 01:05:31 +04:00
36 , CLI_BUFFER_SIZE ) ;
2010-07-26 11:41:25 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2007-12-01 03:13:35 +03:00
}
2010-07-26 11:41:25 +04:00
tevent_req_set_callback ( subreq , cli_qpathinfo_basic_done , req ) ;
return req ;
}
2005-02-23 20:29:28 +03:00
2010-07-26 11:41:25 +04:00
static void cli_qpathinfo_basic_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qpathinfo_basic_state * state = tevent_req_data (
req , struct cli_qpathinfo_basic_state ) ;
NTSTATUS status ;
status = cli_qpathinfo_recv ( subreq , state , & state - > data ,
& state - > num_data ) ;
TALLOC_FREE ( subreq ) ;
2023-08-16 12:59:03 +03:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-26 11:41:25 +04:00
return ;
2007-12-06 00:31:24 +03:00
}
2010-07-26 11:41:25 +04:00
tevent_req_done ( req ) ;
}
2007-12-06 00:31:24 +03:00
2010-07-26 11:41:25 +04:00
NTSTATUS cli_qpathinfo_basic_recv ( struct tevent_req * req ,
2015-05-10 02:59:45 +03:00
SMB_STRUCT_STAT * sbuf , uint32_t * attributes )
2010-07-26 11:41:25 +04:00
{
struct cli_qpathinfo_basic_state * state = tevent_req_data (
req , struct cli_qpathinfo_basic_state ) ;
NTSTATUS status ;
2005-02-23 20:29:28 +03:00
2010-07-26 11:41:25 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
2010-02-07 16:07:17 +03:00
return status ;
2005-02-23 20:29:28 +03:00
}
2023-10-04 14:25:21 +03:00
sbuf - > st_ex_btime = interpret_long_date ( BVAL ( state - > data , 0 ) ) ;
sbuf - > st_ex_atime = interpret_long_date ( BVAL ( state - > data , 8 ) ) ;
sbuf - > st_ex_mtime = interpret_long_date ( BVAL ( state - > data , 16 ) ) ;
sbuf - > st_ex_ctime = interpret_long_date ( BVAL ( state - > data , 24 ) ) ;
2010-07-26 11:41:25 +04:00
* attributes = IVAL ( state - > data , 32 ) ;
return NT_STATUS_OK ;
}
2007-12-01 03:13:35 +03:00
2010-07-26 11:41:25 +04:00
NTSTATUS cli_qpathinfo_basic ( struct cli_state * cli , const char * name ,
2015-05-10 02:59:45 +03:00
SMB_STRUCT_STAT * sbuf , uint32_t * attributes )
2010-07-26 11:41:25 +04:00
{
2013-08-08 21:52:02 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2010-07-26 11:41:25 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2007-12-01 03:13:35 +03:00
2013-08-08 21:52:02 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_qpathinfo_basic ( cli ,
name ,
sbuf ,
attributes ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-07-26 11:41:25 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-07-26 11:41:25 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_qpathinfo_basic_send ( frame , ev , cli , name ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_qpathinfo_basic_recv ( req , sbuf , attributes ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2005-02-23 20:29:28 +03:00
}
2001-09-25 08:25:49 +04:00
/****************************************************************************
2007-03-17 03:15:18 +03:00
Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call .
2001-09-25 08:25:49 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-17 03:15:18 +03:00
2001-09-25 08:25:49 +04:00
NTSTATUS cli_qpathinfo_alt_name ( struct cli_state * cli , const char * fname , fstring alt_name )
{
2011-01-09 21:44:13 +03:00
uint8_t * rdata ;
uint32_t num_rdata ;
2003-03-18 01:40:37 +03:00
unsigned int len ;
2011-01-09 21:44:13 +03:00
char * converted = NULL ;
size_t converted_size = 0 ;
NTSTATUS status ;
2007-12-06 00:31:24 +03:00
2011-01-09 21:44:13 +03:00
status = cli_qpathinfo ( talloc_tos ( ) , cli , fname ,
SMB_QUERY_FILE_ALT_NAME_INFO ,
2011-08-03 01:05:31 +04:00
4 , CLI_BUFFER_SIZE , & rdata , & num_rdata ) ;
2011-01-09 21:44:13 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2001-09-25 08:25:49 +04:00
}
len = IVAL ( rdata , 0 ) ;
2011-01-09 21:44:13 +03:00
if ( len > num_rdata - 4 ) {
2001-09-25 08:25:49 +04:00
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2011-01-09 21:44:13 +03:00
/* The returned data is a pushed string, not raw data. */
if ( ! convert_string_talloc ( talloc_tos ( ) ,
2012-05-26 14:14:51 +04:00
smbXcli_conn_use_unicode ( cli - > conn ) ? CH_UTF16LE : CH_DOS ,
2011-01-09 21:44:13 +03:00
CH_UNIX ,
rdata + 4 ,
len ,
& converted ,
2011-03-24 02:59:41 +03:00
& converted_size ) ) {
2011-01-09 21:44:13 +03:00
return NT_STATUS_NO_MEMORY ;
}
fstrcpy ( alt_name , converted ) ;
2001-09-25 08:25:49 +04:00
2011-01-09 21:44:13 +03:00
TALLOC_FREE ( converted ) ;
TALLOC_FREE ( rdata ) ;
2001-09-25 08:25:49 +04:00
return NT_STATUS_OK ;
}
2013-10-11 12:52:21 +04:00
/****************************************************************************
2020-06-04 17:15:56 +03:00
Send a qpathinfo SMB_QUERY_FILE_STANDARD_INFO call .
2013-10-11 12:52:21 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2024-08-05 16:10:00 +03:00
static NTSTATUS cli_qpathinfo_standard ( struct cli_state * cli ,
const char * fname ,
uint64_t * allocated ,
uint64_t * size ,
uint32_t * nlinks ,
bool * is_del_pending ,
bool * is_dir )
2013-10-11 12:52:21 +04:00
{
uint8_t * rdata ;
uint32_t num_rdata ;
NTSTATUS status ;
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
status = cli_qpathinfo ( talloc_tos ( ) , cli , fname ,
SMB_QUERY_FILE_STANDARD_INFO ,
24 , CLI_BUFFER_SIZE , & rdata , & num_rdata ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( allocated ) {
* allocated = BVAL ( rdata , 0 ) ;
}
if ( size ) {
* size = BVAL ( rdata , 8 ) ;
}
if ( nlinks ) {
* nlinks = IVAL ( rdata , 16 ) ;
}
if ( is_del_pending ) {
* is_del_pending = CVAL ( rdata , 20 ) ;
}
if ( is_dir ) {
* is_dir = CVAL ( rdata , 20 ) ;
}
TALLOC_FREE ( rdata ) ;
return NT_STATUS_OK ;
}
2013-10-11 12:53:45 +04:00
2013-10-14 13:43:45 +04:00
/* like cli_qpathinfo2 but do not use SMB_QUERY_FILE_ALL_INFO with smb1 */
2013-10-11 12:53:45 +04:00
NTSTATUS cli_qpathinfo3 ( struct cli_state * cli , const char * fname ,
struct timespec * create_time ,
struct timespec * access_time ,
struct timespec * write_time ,
struct timespec * change_time ,
2020-06-03 23:36:05 +03:00
off_t * size , uint32_t * pattr ,
2013-10-11 12:53:45 +04:00
SMB_INO_T * ino )
{
NTSTATUS status = NT_STATUS_OK ;
2014-10-30 18:12:17 +03:00
SMB_STRUCT_STAT st = { 0 } ;
2019-08-13 17:55:13 +03:00
uint32_t attr = 0 ;
2013-10-11 12:53:45 +04:00
uint64_t pos ;
2013-10-14 13:43:45 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2020-06-03 23:36:05 +03:00
/*
* NB . cli_qpathinfo2 ( ) checks pattr is valid before
* storing a value into it , so we don ' t need to use
* an intermediate attr variable as below but can
* pass pattr directly .
*/
2023-08-23 14:47:20 +03:00
return cli_qpathinfo2 ( cli ,
fname ,
create_time ,
access_time ,
write_time ,
change_time ,
size ,
pattr ,
ino ,
NULL ) ;
2013-10-14 13:43:45 +04:00
}
2020-06-03 21:01:36 +03:00
if ( create_time | | access_time | | write_time | | change_time | | pattr ) {
2020-06-03 23:36:05 +03:00
/*
* cli_qpathinfo_basic ( ) always indirects the passed
* in pointers so we use intermediate variables to
* collect all of them before assigning any requested
* below .
*/
2013-10-11 12:53:45 +04:00
status = cli_qpathinfo_basic ( cli , fname , & st , & attr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
if ( size ) {
status = cli_qpathinfo_standard ( cli , fname ,
NULL , & pos , NULL , NULL , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
* size = pos ;
}
if ( create_time ) {
* create_time = st . st_ex_btime ;
}
if ( access_time ) {
* access_time = st . st_ex_atime ;
}
if ( write_time ) {
* write_time = st . st_ex_mtime ;
}
if ( change_time ) {
* change_time = st . st_ex_ctime ;
}
2020-06-03 21:01:36 +03:00
if ( pattr ) {
* pattr = attr ;
2013-10-11 12:53:45 +04:00
}
if ( ino ) {
* ino = 0 ;
}
return NT_STATUS_OK ;
}