o
    àý°jÔÆ  ã                   @   s  d dl Z d dlZd dlmZmZmZmZmZmZ d dl	m
Z
mZ d dlmZ d dlmZmZmZmZ d dlmZmZmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZmZmZmZmZmZm Z m!Z!m"Z" d dlm#Z#m$Z$m%Z% G dd„ dƒZ&G dd„ de'ƒZ(dS )é    N)ÚsmbÚsmb3Úsmb3structsÚnmbÚ	nt_errorsÚLOG)Úcompute_lmhashÚcompute_nthash)ÚSMB_DIALECT)ÚSMB2_DIALECT_002ÚSMB2_DIALECT_21ÚSMB2_DIALECT_30ÚSMB2_DIALECT_311)Ú	FILE_OPENÚFILE_OVERWRITEÚFILE_OVERWRITE_IF)ÚFILE_OPEN_REPARSE_POINT)ÚFILE_NON_DIRECTORY_FILE)ÚFILE_ATTRIBUTE_NORMALÚFILE_SYNCHRONOUS_IO_NONALERT)	ÚFILE_READ_DATAÚFILE_WRITE_DATAÚGENERIC_READÚGENERIC_WRITEÚGENERIC_ALLÚREAD_CONTROLÚFILE_READ_ATTRIBUTESÚFILE_READ_EAÚSYNCHRONIZE)ÚFILE_SHARE_READÚFILE_SHARE_WRITEÚFILE_SHARE_DELETEc                	   @   sœ  e Zd ZdZdddejddddfdd„Zdejj	ejj
B ejjejjB ejjB dfd	d
„Z		d€dd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Z d1d2„ Z!d3d4„ Z"d5d6„ Z#d�d7d8„Z$		d‚d9d:„Z%d;d<„ Z&d=d>„ Z'd?d@„ Z(dAdB„ Z)dCdD„ Z*dƒdEdF„Z+e,e-e.B e/B e0e1e2e3j4de3j5df	dGdH„Z6e7e8B e-e0e9e2e3j4de3j5df	dIdJ„Z:d„dKdL„Z;d…dMdN„Z<dOdP„ Z=dQdR„ Z>e-e9ddfdSdT„Z?e-e1ddfdUdV„Z@dƒdWdX„ZAdYdZ„ ZBd[d\„ ZCd]d^„ ZDd†d`da„ZEd‡dbdc„ZFddde„ ZGd‡dfdg„ZHdƒdhdi„ZIdjdk„ ZJdldm„ ZKdndo„ ZLdpdq„ ZMdrds„ ZNdtdu„ ZOdvdw„ ZPdxdy„ ZQdzd{„ ZRd|d}„ ZSe9ddfd~d„ZTdS )ˆÚSMBConnectionab  
    SMBConnection class

    :param str remoteName: The name of the remote host, can be its NETBIOS name, IP or *\*SMBSERVER*.  
                           If the later, and port is 139, the library will try to get the target's server name.
    :param str remoteHost: Target server's remote address (IPv4, IPv6) or FQDN
    :param optional str myName: The client's NETBIOS name
    :param optional int sess_port: A target port to connect
    :param optional int timeout: Timeout in seconds when receiving packets
    :param optional int/str preferredDialect: The dialect desired to talk with the target server. If not specified the highest
           one available will be used
    :param optional bool manualNegotiate: Lets the user manually perform SMB_COM_NEGOTIATE.

    :return: An SMBConnection instance.
    :raise SessionError: If encountered an error.
    Ú Né<   Fc	           	      C   sº   d| _ d| _d| _|| _|| _|| _|| _|| _|| _|| _	|| _
d| _d | _d| _d| _|d urPt|tjƒs?t|tjƒs?J ‚|| _ | j  ¡ | _| j  ¡ | _d S |du r[|  |¡ d S d S )Nr   r#   FT)Ú_SMBConnectionÚ_dialectÚ_nmbSessionÚ
_sess_portÚ_myNameÚ_remoteHostÚ_remoteNameÚ_timeoutÚ_preferredDialectÚ_existingConnectionÚ_manualNegotiateÚ_doKerberosÚ_kdcHostÚ	_useCacheÚ_ntlmFallbackÚ
isinstancer   ÚSMBr   ÚSMB3Ú
getDialectÚgetKerberosÚnegotiateSession)	ÚselfÚ
remoteNameÚ
remoteHostÚmyNameÚ	sess_portÚtimeoutÚpreferredDialectÚexistingConnectionÚmanualNegotiate© rC   ú‰/root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-packages/impacket/smbconnection.pyÚ__init__?   s0   ÿzSMBConnection.__init__z"NT LM 0.12 SMB 2.002 SMB 2.??? c           	      C   s¼  | j tjkr| jdkr| j| _n | j tjkr0| jdkr0t ¡ }z| | j¡}W n   Y n|| _| j tjkr8d}tj}|du r‡| j	| j
| j| j| j | jd|||d�	}|dd… dkrrtj| j| j| j
|| j | j| jt |¡d	�| _nJtj| j| j| j
|| j | j| j|d
�| _n5|tjkr�t | j| j| j
|| j | j¡| _n|ttttfv r¸tj| j| j| j
|| j | j|d�| _ntdƒ‚t| jtjƒrÜ| j ¡ d tjj@ rÔ|tjjO }| jj||d� dS )a,  
        Perform SMB protocol negotiation.

        :param optional int/str preferredDialect: The dialect desired to talk with the target server. 
                                                  If None is specified the highest one available will be used
        :param optional int flags1: The SMB FLAGS capabilities
        :param optional int flags2: The SMB FLAGS2 capabilities
        :param optional bytes negoData: Data to be sent as part of the nego handshake.

        :return: True
        :raise SessionError: If encountered an error.
        z
*SMBSERVERzNT LM 0.12 SMB 2.002 NT)Úflags1Úflags2Údatar   é   ó   þ)ÚsessionÚnegSessionResponse)rK   Ú	negPacket)r@   zUnknown dialect %s)rF   rG   )r(   r   ÚSMB_SESSION_PORTr+   r*   ÚNETBIOS_SESSION_PORTÚNetBIOSÚgetnetbiosnameÚTYPE_SERVERÚnegotiateSessionWildcardr)   r,   r   r6   r'   r   Ú
SMB2Packetr%   r   r5   r
   r   r   r   r   Ú	Exceptionr4   Ú	get_flagsÚFLAGS2_UNICODEÚ	set_flags)	r:   r@   rF   rG   ÚnegoDataÚnbÚresÚhostTypeÚpacketrC   rC   rD   r9   _   sN   
ÿ
þ
þ
ÿ

ÿzSMBConnection.negotiateSessionTr   c
                 C   s8  |st  ¡ }| d¡}
|
dkr|d |
… }d}t ¡ }||d< |tjjB |d< d }|dk r�t |||tj	||¡| _
t tjj¡}|du rN|d  tjjO  < |	|d< | |¡ | j
 | ¡ ¡ z| j
 |¡}W n( tjy‡   |d  tjjtjjB tjjB O  < g |d< Y nw |d	7 }|dk s-|d u r˜td
ƒ‚| ¡ S )NÚ.éÿÿÿÿr   ÚFlags1ÚFlags2é   TÚDatarI   z
No answer!)ÚsocketÚgethostnameÚfindr   ÚNewSMBPacketr5   rW   r   ÚNetBIOSTCPSessionrR   r'   Ú
SMBCommandÚSMB_COM_NEGOTIATEÚFLAGS2_EXTENDED_SECURITYÚ
addCommandÚsend_packetÚgetDataÚrecv_packetÚNetBIOSErrorÚFLAGS2_NT_STATUSÚFLAGS2_LONG_NAMESrU   Úget_trailer)r:   r=   r;   r<   r>   r?   Úextended_securityrF   rG   rH   ÚiÚtriesÚsmbpÚrespÚ
negSessionrC   rC   rD   rS   ¥   s@   
ÿ
$ýíz&SMBConnection.negotiateSessionWildcardc                 C   ó   | j S ©N)r'   ©r:   rC   rC   rD   ÚgetNMBServerÑ   ó   zSMBConnection.getNMBServerc                 C   rz   )za
        Returns the SMB/SMB3 instance being used. Useful for calling low level methods.
        )r%   r|   rC   rC   rD   ÚgetSMBServerÔ   s   zSMBConnection.getSMBServerc                 C   ó
   | j  ¡ S r{   )r%   r7   r|   rC   rC   rD   r7   Ú   ó   
zSMBConnection.getDialectc                 C   r€   r{   )r%   Úget_server_namer|   rC   rC   rD   ÚgetServerNameÝ   r�   zSMBConnection.getServerNamec                 C   r€   r{   )r%   Úget_client_namer|   rC   rC   rD   ÚgetClientNameà   r�   zSMBConnection.getClientNamec                 C   r€   r{   )r%   Úget_remote_hostr|   rC   rC   rD   ÚgetRemoteHostã   r�   zSMBConnection.getRemoteHostc                 C   r€   r{   )r%   Úget_remote_namer|   rC   rC   rD   ÚgetRemoteNameæ   r�   zSMBConnection.getRemoteNamec                 C   s   | j  |¡S r{   )r%   Úset_remote_name)r:   ÚnamerC   rC   rD   ÚsetRemoteNameé   ó   zSMBConnection.setRemoteNamec                 C   r€   r{   )r%   Úget_server_domainr|   rC   rC   rD   ÚgetServerDomainì   r�   zSMBConnection.getServerDomainc                 C   r€   r{   )r%   Úget_server_dns_domain_namer|   rC   rC   rD   ÚgetServerDNSDomainNameï   r�   z$SMBConnection.getServerDNSDomainNamec                 C   r€   r{   )r%   Úget_server_dns_host_namer|   rC   rC   rD   ÚgetServerDNSHostNameò   r�   z"SMBConnection.getServerDNSHostNamec                 C   r€   r{   )r%   Úget_server_osr|   rC   rC   rD   ÚgetServerOSõ   r�   zSMBConnection.getServerOSc                 C   r€   r{   )r%   Úget_server_os_majorr|   rC   rC   rD   ÚgetServerOSMajorø   r�   zSMBConnection.getServerOSMajorc                 C   r€   r{   )r%   Úget_server_os_minorr|   rC   rC   rD   ÚgetServerOSMinorû   r�   zSMBConnection.getServerOSMinorc                 C   r€   r{   )r%   Úget_server_os_buildr|   rC   rC   rD   ÚgetServerOSBuildþ   r�   zSMBConnection.getServerOSBuildc                 C   r€   r{   )r%   ÚdoesSupportNTLMv2r|   rC   rC   rD   rœ     r�   zSMBConnection.doesSupportNTLMv2c                 C   r€   r{   )r%   Úis_login_requiredr|   rC   rC   rD   ÚisLoginRequired  r�   zSMBConnection.isLoginRequiredc                 C   r€   r{   )r%   Úis_signing_requiredr|   rC   rC   rD   ÚisSigningRequired  r�   zSMBConnection.isSigningRequiredc                 C   r€   r{   )r%   ÚgetCredentialsr|   rC   rC   rD   r¡   
  r�   zSMBConnection.getCredentialsc                 C   r€   r{   )r%   ÚgetIOCapabilitiesr|   rC   rC   rD   r¢     r�   zSMBConnection.getIOCapabilitiesc              
   C   sv   || _ z|  ¡ tjkr| j ||||||¡W S | j |||||¡W S  tjtjfy: } z	t| ¡ | 	¡ ƒ‚d}~ww )aï  
        Authenticates against the target system using NTLM.

        :param str user: Username.
        :param str password: Password for the user.
        :param optional str domain: Domain where the account is valid for.
        :param optional str lmhash: LMHASH used to authenticate using hashes (password is not used).
        :param optional str nthash: NTHASH used to authenticate using hashes (password is not used).
        :param optional bool ntlmFallback: If True it will try NTLMv1 authentication if NTLMv2 fails. 
                                           Only available for SMBv1.

        :return: None
        :raise SessionError: If encountered an error (e.g. authentication failure, or invalid/truncated server response).
        N)
r3   r7   r   r
   r%   ÚloginÚSessionErrorr   Úget_error_codeÚget_error_packet)r:   ÚuserÚpasswordÚdomainÚlmhashÚnthashÚntlmFallbackÚerC   rC   rD   r£     s   €ÿzSMBConnection.loginc                 C   sf  ddl m} ddlm} ddlm} || _|
| _|dus |	dur"d}
|
r3| ||d|  	¡  ¡\}}}}		 z%|  
¡ tjkrK| j |||||||||	¡	W S | j |||||||||	¡	W S  tjtjfyr } z	t| ¡ | ¡ ƒ‚d}~w |y± } z4| ¡ |jjjkr¥|d	kr£|d	kr£|d	ks’|du r£|du r£|	du r£t|ƒ}t|ƒ}n|‚|‚W Y d}~nd}~ww q4)
a±  
        Authenticates against the target system using Kerberos.
        Hashes are used if RC4_HMAC is supported.

        :param str user: Username.
        :param str password: Password for the user.
        :param optional str domain: Domain where the account is valid for (required).
        :param optional str lmhash: LMHASH used to authenticate using hashes (password is not used).
        :param optional str nthash: NTHASH used to authenticate using hashes (password is not used).
        :param optional str aesKey: aes256-cts-hmac-sha1-96 or aes128-cts-hmac-sha1-96 used for Kerberos authentication.
        :param optional str kdcHost: Hostname or IP Address for the KDC. If None, the domain will be used (it needs to resolve tho).
        :param optional struct TGT: If there's a TGT available, send the structure here and it will be used.
        :param optional struct TGS: Same for TGS. See smb3.py for the format.
        :param optional bool useCache: Whether or not we should use the ccache for credentials lookup.
                                       If TGT or TGS are specified this is False

        :return: None
        :raise SessionError: If encountered an error.
        r   )ÚCCache)ÚKerberosError)Ú	constantsNFzcifs/%sTr#   )Úimpacket.krb5.ccacher®   Úimpacket.krb5.kerberosv5r¯   Úimpacket.krb5r°   r1   r2   Ú	parseFiler‰   r7   r   r
   r%   Úkerberos_loginÚkerberosLoginr¤   r   r¥   r¦   ÚgetErrorCodeÚ
ErrorCodesÚKDC_ERR_ETYPE_NOSUPPÚvaluer   r	   )r:   r§   r¨   r©   rª   r«   ÚaesKeyÚkdcHostÚTGTÚTGSÚuseCacher®   r¯   r°   r­   rC   rC   rD   r¶   (  s@   ÿÿ€0
ü€ø÷zSMBConnection.kerberosLoginc              
   C   ó@   z| j  ¡ W S  tjtjfy } z	t| ¡ | ¡ ƒ‚d }~ww r{   )r%   ÚisGuestSessionr   r¤   r   r¥   r¦   ©r:   r­   rC   rC   rD   rÁ   a  ó   €ÿzSMBConnection.isGuestSessionc              
   C   rÀ   r{   )r%   Úlogoffr   r¤   r   r¥   r¦   rÂ   rC   rC   rD   rÄ   g  rÃ   zSMBConnection.logoffc              
   C   s|   |   ¡ tjkrt |¡du rt |¡}d|  ¡  d | }z| j |¡W S  tj	t
j	fy= } z	t	| ¡ | ¡ ƒ‚d}~ww )z†
        Connect to a remote share / resource (tree).
        
        :return int: Tree ID (used later in other operations).
        Fú\\ú\N)r7   r   r
   ÚntpathÚismountÚbasenamer‡   r%   Úconnect_treer¤   r   r¥   r¦   )r:   Úsharer­   rC   rC   rD   ÚconnectTreem  s   
€ÿzSMBConnection.connectTreec              
   C   óB   z| j  |¡W S  tjtjfy  } z	t| ¡ | ¡ ƒ‚d }~ww r{   )r%   Údisconnect_treer   r¤   r   r¥   r¦   )r:   ÚtreeIdr­   rC   rC   rD   ÚdisconnectTree~  ó   €ÿzSMBConnection.disconnectTreec                 C   sr   ddl m}m} |j|  ¡ |  ¡ d| d�}| ¡ }| ¡  | |j	¡ |j
|dd|  ¡  d�}|d d	 d
 d S )z¾
        Get a list of available shares at the connected target.

        :return: List containing dict entries for each share.
        :raise SessionError: If encountered an error.
        r   )Ú	transportÚsrvsz\srvsvc)ÚfilenameÚsmb_connectionrI   rÅ   )Ú
serverNameÚ
InfoStructÚ	ShareInfoÚLevel1ÚBuffer)Úimpacket.dcerpc.v5rÒ   rÓ   ÚSMBTransportr‰   r‡   Úget_dce_rpcÚconnectÚbindÚMSRPC_UUID_SRVSÚhNetrShareEnum)r:   rÒ   rÓ   ÚrpctransportÚdcerx   rC   rC   rD   Ú
listShares„  s   ÿzSMBConnection.listSharesc              
   C   óF   z	| j  |||¡W S  tjtjfy" } z	t| ¡ | ¡ ƒ‚d}~ww )až  
        List the files/directories under shareName/path.

        :param str shareName: A valid name for the share where the files/directories are going to be searched.
        :param str path: A base path relative to shareName.
        :param optional str password: The password for the share.

        :return: List containing smb.SharedFile items.
        :raise SessionError: If encountered an error.
        N)r%   Ú	list_pathr   r¤   r   r¥   r¦   )r:   Ú	shareNameÚpathr¨   r­   rC   rC   rD   ÚlistPath•  ó   €ÿzSMBConnection.listPathc                 C   ó°  |   ¡ tjkr­| j ¡ \}}| dd¡}|tjj@ r| d¡n|}t 	tjj
¡}t ¡ |d< tj|d�|d< t|ƒ|d d< ||d d< ||d d	< ||d d
< ||d d< ||d d< ||d d< |	|d d< d|d d< ||d d< |tjj@ r€d|d d< |dur‰t d¡ z
| jj|||d�W S  tjtjfy¬ } z	t| ¡ | ¡ ƒ‚d}~ww z| j |||||||||	|
|¡W S  tjtjfy× } z	t| ¡ | ¡ ƒ‚d}~ww )a�  
        Creates a remote file, returning a handle to it.

        :param HANDLE treeId: A valid handle for the share where the file is to be created.
        :param str pathName: The path name of the file to create.
        :param optional int desiredAccess: The level of access that is required, as specified in https://msdn.microsoft.com/en-us/library/cc246503.aspx
        :param optional int shareMode: Specifies the sharing mode for the open.
        :param optional int creationOption: Specifies the options to be applied when creating or opening the file.
        :param optional int creationDisposition: Defines the action the server MUST take if the file that is specified in the name
                                                 field already exists.
        :param optional int fileAttributes: This field MUST be a combination of the values specified in [MS-FSCC] section 2.6, 
                                            and MUST NOT include any values other than those specified in that section.
        :param optional int impersonationLevel: This field specifies the impersonation level requested by the application that is issuing 
                                                the create request.
        :param optional int securityFlags: This field MUST NOT be used and MUST be reserved. The client MUST set this to 0, 
                                           and the server MUST ignore it.
        :param optional int oplockLevel: The requested oplock level.
        :param optional createContexts: A variable-length attribute that is sent with an SMB2 CREATE Request or SMB2 CREATE Response 
                                        that either gives extra information about how the create will be processed, or returns extra
                                        information about how the create was processed.

        :return: A valid file descriptor.
        :raise SessionError: If encountered an error.
        ú/rÆ   úutf-16leÚ
Parameters©Úflagsrc   ÚFileNameLengthÚ
AccessMaskÚFileAttributesÚShareAccessÚDispositionÚCreateOptionsÚImpersonationÚSecurityFlagsé   ÚCreateFlagsÚFileNamer   ÚPadNú$CreateContexts not supported in SMB1©Úcmd©r7   r   r
   r%   rV   Úreplacer5   rW   Úencoderi   ÚSMB_COM_NT_CREATE_ANDXÚSMBNtCreateAndX_ParametersÚSMBNtCreateAndX_DataÚlenr   ÚerrorÚnt_create_andxr¤   r   r¥   r¦   Úcreate©r:   rÏ   ÚpathNameÚdesiredAccessÚ	shareModeÚcreationOptionÚcreationDispositionÚfileAttributesÚimpersonationLevelÚsecurityFlagsÚoplockLevelÚcreateContextsÚ_rG   ÚpacketPathNameÚntCreater­   rC   rC   rD   Ú
createFile¦  óH   
€ÿþ€ÿzSMBConnection.createFilec                 C   rë   )a}  
        Opens a handle to a remote file.

        :param HANDLE treeId: A valid handle for the share where the file is to be opened.
        :param str pathName: The path name to open.
        :param optional int desiredAccess: The level of access that is required, as specified in https://msdn.microsoft.com/en-us/library/cc246503.aspx
        :param optional int shareMode: Specifies the sharing mode for the open.
        :param optional int creationOption: Specifies the options to be applied when creating or opening the file.
        :param optional int creationDisposition: Defines the action the server MUST take if the file that is specified in the name
                                                 field already exists.
        :param optional int fileAttributes: This field MUST be a combination of the values specified in [MS-FSCC] section 2.6, 
                                            and MUST NOT include any values other than those specified in that section.
        :param optional int impersonationLevel: This field specifies the impersonation level requested by the application that is issuing 
                                                the create request.
        :param optional int securityFlags: This field MUST NOT be used and MUST be reserved. The client MUST set this to 0, 
                                           and the server MUST ignore it.
        :param optional int oplockLevel: The requested oplock level
        :param optional createContexts: A variable-length attribute that is sent with an SMB2 CREATE Request or SMB2 CREATE Response 
                                        that either gives extra information about how the create will be processed, or returns extra
                                        information about how the create was processed.

        :return: A valid file descriptor.
        :raise SessionError: If encountered an error.
        rì   rÆ   rí   rî   rï   rc   rñ   rò   ró   rô   rõ   rö   r÷   rø   rù   rú   rû   r   rü   Nrý   rþ   r   r
  rC   rC   rD   ÚopenFileé  r  zSMBConnection.openFilec              
   C   sH   z
| j  ||||¡W S  tjtjfy# } z	t| ¡ | ¡ ƒ‚d}~ww )aÂ  
        Writes data to a remote file.

        :param HANDLE treeId: A valid handle for the share where the file is to be written.
        :param HANDLE fileId: A valid handle for the file.
        :param str data: A buffer with the data to write.
        :param optional int offset: An offset where to start writing the data.

        :return: The amount of bytes successfully written.
        :raise SessionError: If encountered an error.
        N)r%   Ú	writeFiler   r¤   r   r¥   r¦   )r:   rÏ   ÚfileIdrH   Úoffsetr­   rC   rC   rD   r  ,  ó   €ÿzSMBConnection.writeFilec              
   C   s   d}d}| j  ¡ d }|du r|}|}	|s~|	|kr|}
n|	}
z| j  ||||
¡}W n) tjtjfyR } z| ¡ tjkrEd}
W Y d}~|S t| ¡ | 	¡ ƒ‚d}~ww ||7 }t
|ƒ|kr`d}nt
|ƒdkrid}n|du rpd}n|t
|ƒ7 }|	t
|ƒ8 }	|r|S )a  
        Reads data from a file.

        :param HANDLE treeId: A valid handle for the share where the file is to be read.
        :param HANDLE fileId: A valid handle for the file to be read.
        :param optional int offset: An offset where to start reading the data.
        :param optional int bytesToRead: The amount of bytes to attempt reading. 
                                         If None, it will attempt to read Dialect['MaxBufferSize'] bytes.
        :param optional bool singleCall: If True it won't attempt to read all bytesToRead. 
                                         It will only make a single read call.

        :return: The data read. Length of data read is not always bytesToRead.
        :raise SessionError: If encountered an error.
        Fó    ÚMaxReadSizeNTr   )r%   r¢   Ú	read_andxr   r¤   r   r¥   r   ÚSTATUS_END_OF_FILEr¦   r  )r:   rÏ   r  r  ÚbytesToReadÚ
singleCallÚfinishedrH   ÚmaxReadSizeÚremainingBytesToReadÚtoReadÚ	bytesReadr­   rC   rC   rD   ÚreadFile=  s>   
ò€ûèzSMBConnection.readFilec              
   C   óD   z| j  ||¡W S  tjtjfy! } z	t| ¡ | ¡ ƒ‚d}~ww )a"  
        Closes a file handle.

        :param HANDLE treeId: A valid handle for the share where the file is to be opened.
        :param HANDLE fileId: A valid handle for the file/directory to be closed.

        :return: None
        :raise SessionError: If encountered an error.
        N)r%   Úcloser   r¤   r   r¥   r¦   )r:   rÏ   r  r­   rC   rC   rD   Ú	closeFilen  ó   
€ÿzSMBConnection.closeFilec              
   C   r+  )zÿ
        Removes a file.

        :param str shareName: A valid name for the share where the file is to be deleted.
        :param str pathName: The path name to remove.

        :return: None
        :raise SessionError: If encountered an error.
        N)r%   Úremover   r¤   r   r¥   r¦   ©r:   rç   r  r­   rC   rC   rD   Ú
deleteFile}  r.  zSMBConnection.deleteFilec           	   
   C   óP   z| j j|||||||d�W S  tjtjfy' } z	t| ¡ | ¡ ƒ‚d}~ww )aÕ  
        Reads a remote file and sends the read data to a callback method.

        :param str shareName: The name for the share where the file is to be retrieved.
        :param str pathName: The path name to retrieve.
        :param callback callback: A function called to write the contents read - the method receives bytes as an argument.
        :param optional int shareAccessMode: Binary flags stating what file access permissions we would like to allow other 
                                             processes to have when accessing our opened file.
        :param optional int mode: Binary flags indicating what file operation we expect to happen when we open our file.
        :param optional int offset: An offset for reading data from the file (used like `seek`).
        :param optional str password: A password for password protected files & shares (Not Implemented in SMBv3).

        :return: None
        :raise SessionError: If encountered an error.
        ©Úmoder  r¨   ÚshareAccessModeN)r%   Ú	retr_filer   r¤   r   r¥   r¦   ©	r:   rç   r  Úcallbackr5  r4  r  r¨   r­   rC   rC   rD   ÚgetFileŒ  s   €ÿzSMBConnection.getFilec           	   
   C   r2  )a/  
        Uploads data read from a callback method to a remote file.

        :param str shareName: The name for the share where the file is to be uploaded.
        :param str pathName: The path name to upload.
        :param callback callback: A function called to read the contents to be written - method should receive 
                                  length of data as a value and return bytes (in the requested amount) to write.
        :param optional int shareAccessMode: Binary flags stating what file access permissions we would like to allow other 
                                             processes to have when accessing our opened file.
        :param optional int mode: Binary flags indicating what file operation we expect to happen when we open our file.
        :param optional int offset: An offset for writing data to the file (used like `seek`).
        :param optional str password: A password for password protected files & shares (Not Implemented in SMBv3).

        :return: None
        :raise SessionError: If encountered an error.
        r3  N)r%   Ú	stor_filer   r¤   r   r¥   r¦   r7  rC   rC   rD   ÚputFile¢  s   €ÿzSMBConnection.putFilec              
   C   s®   z=|   ¡ tjkr#|s| j ||¡}t |¡W S | jj|||d�}|W S |s2| j ||¡}t |¡W S | jj|||d�}|W S  tjtjfyV } z	t| 	¡ | 
¡ ƒ‚d}~ww )ad  
        Queries the desired information class of an opened file/directory.

        :param HANDLE treeId: A valid handle for the share where the file is to be queried.
        :param HANDLE fileId: A valid handle for the file/directory to be queried.
        :param optional int fileInfoClass: The desired file information class to query.

        :return: An smb.SMBQueryFileStandardInfo structure if not given any file info class.
                Otherwise, returns raw bytes - which can be converted into any file information struct by the user.
        :raise SessionError: If encountered an error.
        )ÚfileInfoClassN)r7   r   r
   r%   Úquery_file_infoÚSMBQueryFileStandardInfoÚ	queryInfor¤   r   r¥   r¦   )r:   rÏ   r  r<  r[   r­   rC   rC   rD   r?  ¹  s    û€ÿzSMBConnection.queryInfoc              
   C   sn   z|   ¡ tjkr| jj||||d�W S | jj||||d�W S  tjtjfy6 } z	t| ¡ | 	¡ ƒ‚d}~ww )aG  
        Set the given information data of the desired file information class onto the file/directory.

        :param HANDLE treeId: A valid handle for the share where the file to be modified resides.
        :param HANDLE fileId: A valid handle for the file/directory to be modified.
        :param int fileInfoClass: The desired file information class to modify.
        :param struct infoData: The desired file information data to set onto the file/directory.

        :return: Underlying connection set info result.
        :raise SessionError: If encountered an error.
        )r<  Úfile_info_data)Ú	inputBlobr<  N)
r7   r   r
   r%   Úset_file_infoÚsetInfor¤   r   r¥   r¦   )r:   rÏ   r  r<  ÚinfoDatar­   rC   rC   rD   rC  Ö  s   ü€ÿzSMBConnection.setInfoc              
   C   r+  )a  
        Creates a directory.

        :param str shareName: A valid name for the share where the directory is to be created.
        :param str pathName: The path name or the directory to create.

        :return: None
        :raise SessionError: If encountered an error.
        N)r%   Úmkdirr   r¤   r   r¥   r¦   r0  rC   rC   rD   ÚcreateDirectoryï  r.  zSMBConnection.createDirectoryc              
   C   r+  )a  
        Deletes a directory.

        :param str shareName: A valid name for the share where directory is to be deleted.
        :param str pathName: The path name or the directory to delete.

        :return: None
        :raise SessionError: If encountered an error.
        N)r%   Úrmdirr   r¤   r   r¥   r¦   r0  rC   rC   rD   ÚdeleteDirectoryþ  r.  zSMBConnection.deleteDirectoryé   c              
   C   sH   z
| j j|||d�W S  tjtjfy# } z	t| ¡ | ¡ ƒ‚d}~ww )a;  
        Waits for a named pipe.

        :param HANDLE treeId: A valid handle for the share where the pipe is.
        :param str pipeName: The pipe name to check.
        :param optional int timeout: Time to wait for an answer.

        :return: None
        :raise SessionError: If encountered an error.
        )r?   N)r%   ÚwaitNamedPiper   r¤   r   r¥   r¦   )r:   rÏ   ÚpipeNamer?   r­   rC   rC   rD   rJ    s   €ÿzSMBConnection.waitNamedPipec              
   C   sJ   z| j j||||d�W S  tjtjfy$ } z	t| ¡ | ¡ ƒ‚d}~ww )až  
        Writes to a named pipe using a transaction command.

        :param HANDLE treeId: A valid handle for the share where the pipe is.
        :param HANDLE fileId: A valid handle for the pipe.
        :param bytes data: A buffer with the data to write.
        :param bool waitAnswer: Whether or not to wait for an answer.

        :return: None
        :raise SessionError: If encountered an error.
        )Ú
waitAnswerN)r%   ÚTransactNamedPiper   r¤   r   r¥   r¦   ©r:   rÏ   r  rH   rL  r­   rC   rC   rD   ÚtransactNamedPipe  s   €ÿzSMBConnection.transactNamedPipec              
   C   s@   z| j  ¡ W S  tjtjfy } z	t| ¡ | ¡ ƒ‚d}~ww )z²
        Reads from a named pipe using a transaction command.

        :return: The data read from the remote pipe.
        :raise SessionError: If encountered an error.
        N)r%   ÚTransactNamedPipeRecvr   r¤   r   r¥   r¦   rÂ   rC   rC   rD   ÚtransactNamedPipeRecv.  s   €ÿz#SMBConnection.transactNamedPipeRecvc              
   C   sl   z|   ¡ tjkr| jj||||dd�W S |  |||d¡W S  tjtjfy5 } z	t| ¡ | 	¡ ƒ‚d}~ww )a‹  
        Writes to a named pipe.

        :param HANDLE treeId: A valid handle for the share where the pipe is.
        :param HANDLE fileId: A valid handle for the pipe.
        :param bytes data: A buffer with the data to write.
        :param optional bool waitAnswer: Whether or not to wait for an answer.

        :return: None
        :raise SessionError: If encountered an error.
        T)Úwait_answerÚwrite_pipe_moder   N)
r7   r   r
   r%   Ú
write_andxr  r¤   r   r¥   r¦   rN  rC   rC   rD   ÚwriteNamedPipe:  s   €ÿzSMBConnection.writeNamedPipec              
   C   sH   z
| j |||dd�W S  tjtjfy# } z	t| ¡ | ¡ ƒ‚d}~ww )aj  
        Reads from a named pipe.

        :param HANDLE treeId: A valid handle for the share where the pipe resides.
        :param HANDLE fileId: A valid handle for the pipe.
        :param optional int bytesToRead: The amount of data to read.

        :return: The bytes read from the named pipe.
        :raise SessionError: If encountered an error.
        T)r#  r$  N)r*  r   r¤   r   r¥   r¦   )r:   rÏ   r  r#  r­   rC   rC   rD   ÚreadNamedPipeN  r  zSMBConnection.readNamedPipec              
   C   sP  |   ¡ ttttfvrttjd�‚| j||t	t
B tB tB tB dtttB d�}zt | jj||tjtjdd�¡}W n tjtjfyV } z|  ||¡ t| ¡ | ¡ ƒ‚d}~ww |d dkr“zt | jj||tjtj|d d d�¡}W n tjtjfy’ } z|  ||¡ t| ¡ | ¡ ƒ‚d}~ww |  ||¡ ttd|d	  d
¡ d¡ƒƒS )a[  
        Lists the VSS snapshots for the given directory on the remote share.

        :param HANDLE tid: A vaild handle for the share where the path resides.
        :param str path: A path of a directory to list the snapshots of.

        :return list: List of snapshot identifiers.
        :raise SessionError: If encountered an error.
        ©r  N)r  r  r  é   )rð   ÚmaxOutputResponseÚSnapShotArraySizeé4   é   Ú	SnapShotsÚutf16ú ) r7   r   r   r   r   r¤   r   ÚSTATUS_NOT_SUPPORTEDr  r   r   r   r   r   r   r   r    r   ÚSRV_SNAPSHOT_ARRAYr%   ÚioctlÚFSCTL_SRV_ENUMERATE_SNAPSHOTSÚSMB2_0_IOCTL_IS_FSCTLr   r   r-  r¥   r¦   ÚlistÚfilterÚdecodeÚsplit)r:   Útidrè   ÚfidÚsnapshotDatar­   rC   rC   rD   ÚlistSnapshots_  s6   þÿ€þÿ€þzSMBConnection.listSnapshotsc                 C   sÐ   |   ¡ tttfvrttjd�‚| j||tt	B t
d�}| d¡r%| d¡}nd|  d¡}| d¡}t ¡ }|d | d |d< t|ƒ|d< t|ƒd	 |d
< t|ƒ|d< | jj||tjtj|d� |  ||¡ dS )ah  
        Creates a mount point at an existing directory

        :param HANDLE tid: A vaild handle for the share where the path resides.
        :param str path: A path to a directory at which to create mount point (must already exist).
        :param str target: A target address of mount point.

        :raise SessionError: If encountered an error.
        rW  ©r  rÆ   rí   z\??\s     Ú
PathBufferÚSubstituteNameLengthrb   ÚPrintNameOffsetÚPrintNameLength©rð   rA  N)r7   r   r   r   r¤   r   r`  r  r   r   r   Ú
startswithr  r   Ú"MOUNT_POINT_REPARSE_DATA_STRUCTUREr  r%   rb  ÚFSCTL_SET_REPARSE_POINTrd  r-  )r:   ri  rè   Útargetrj  Ú
fixed_namer‹   ÚreparseDatarC   rC   rD   ÚcreateMountPoint†  s$   ÿ

ÿzSMBConnection.createMountPointc              
   C   s²   |   ¡ tttfvrttjd�‚| j||tt	B t
d�}t ¡ }d|d< z| jj||tjtj|d� W n tjtjfyP } z|  ||¡ t| ¡ | ¡ ƒ‚d}~ww |  ||¡ dS )a'  
        Removes a mount point without deleting the underlying directory.

        :param HANDLE tid: A vaild handle for the share where the path resides.
        :param str path: A path to a directory to remote a mount point from.

        :raise SessionError: If encountered an error.
        rW  rm  r  Ú
DataBufferrr  N)r7   r   r   r   r¤   r   r`  r  r   r   r   r   Ú'MOUNT_POINT_REPARSE_GUID_DATA_STRUCTUREr%   rb  ÚFSCTL_DELETE_REPARSE_POINTrd  r   r   r-  r¥   r¦   )r:   ri  rè   rj  rx  r­   rC   rC   rD   ÚremoveMountPoint«  s"   ÿ
ÿ€þzSMBConnection.removeMountPointc              
   C   rå   )am  
        Renames a file/directory.

        :param str shareName: The name for the share where the files/directories are.
        :param str oldPath: The old path name of the directory/file to rename.
        :param str newPath: The new path name of the directory/file to rename.

        :return: True
        :raise SessionError: If encountered an error.
        N)r%   Úrenamer   r¤   r   r¥   r¦   )r:   rç   ÚoldPathÚnewPathr­   rC   rC   rD   r~  É  rê   zSMBConnection.renamec           	      C   sl   |   ¡ \}}}}}}}}|  | j¡ | jdu r)|  ||||||| j||| j¡
 dS |  |||||| j¡ dS )ay  
        Reconnects the SMB object based on the original options and credentials used. 
        Only exception is that manualNegotiate will not be honored.
        Not only the connection will be created but also a login attempt using the original credentials and method (Kerberos, PtH, etc)

        :return: True
        :raise SessionError: If encountered an error.
        T)	r¡   r9   r-   r0   r¶   r1   r2   r£   r3   )	r:   ÚuserNamer¨   r©   rª   r«   r»   r½   r¾   rC   rC   rD   Ú	reconnectÚ  s   	
 þzSMBConnection.reconnectc              
   C   rÍ   r{   )r%   Úset_timeoutr   r¤   r   r¥   r¦   )r:   r?   r­   rC   rC   rD   Ú
setTimeoutì  rÑ   zSMBConnection.setTimeoutc                 C   s"   |   ¡ tjkr| j ¡ S | j ¡ S r{   )r7   r   r
   r%   Úget_session_keyÚgetSessionKeyr|   rC   rC   rD   r†  ò  s   

zSMBConnection.getSessionKeyc                 C   s&   |   ¡ tjkr| j |¡S | j |¡S r{   )r7   r   r
   r%   Úset_session_keyÚsetSessionKey)r:   ÚkeyrC   rC   rD   rˆ  ø  s   zSMBConnection.setSessionKeyc                 C   s   | j  |||¡S r{   )r%   Úset_hostname_validation)r:   ÚvalidateÚaccept_emptyÚhostnamerC   rC   rD   ÚsetHostnameValidationþ  s   z#SMBConnection.setHostnameValidationc                 C   s$   z|   ¡  W n   Y | j ¡  dS )z]
        Logs off and closes the underlying _NetBIOSSession()

        :return: None
        N)rÄ   r%   Úclose_sessionr|   rC   rC   rD   r,    s
   zSMBConnection.closec              	   C   s    | j |||ttB tB |||d�S )zs
        retrieve regular files and also those locked with open (weak) handles by remote process ( #1894 )
        )r5  r4  r  r¨   )r9  r   r    r!   )r:   rç   r  r8  r4  r  r¨   rC   rC   rD   Ú	getFileEx  s   ÿzSMBConnection.getFileEx)Tr   r   N)r#   r#   r#   T)r#   r#   r#   r#   NNNTr{   )r   )r   NT)rI  )T)UÚ__name__Ú
__module__Ú__qualname__Ú__doc__r   rN   rE   r   r5   ÚFLAGS1_PATHCASELESSÚFLAGS1_CANONICALIZED_PATHSrk   rq   rr   r9   rS   r}   r   r7   rƒ   r…   r‡   r‰   rŒ   r�   r‘   r“   r•   r—   r™   r›   rœ   rž   r    r¡   r¢   r£   r¶   rÁ   rÄ   rÌ   rÐ   rä   ré   r   r   r    r!   r   r   r   r   ÚSMB2_IL_IMPERSONATIONÚSMB2_OPLOCK_LEVEL_NONEr  r   r   r   r  r  r*  r-  r1  r9  r;  r?  rC  rF  rH  rJ  rO  rQ  rU  rV  rl  ry  r}  r~  r‚  r„  r†  rˆ  rŽ  r,  r�  rC   rC   rC   rD   r"   .   sª    
ÿ 
ýF
ÿ,

ÿ9


üC
ý
C
1
ÿ
ÿ




'%ÿr"   c                   @   s:   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )r¤   zé
    This is the exception every client should catch regardless of the underlying SMB version used. 
    We'll take care of that. 
    NETBIOS exceptions are NOT included, since all SMB versions share the same NETBIOS instances.
    r   c                 C   s   t  | ¡ || _|| _d S r{   )rU   rE   r  r]   )r:   r  r]   rC   rC   rD   rE     s   

zSessionError.__init__c                 C   rz   r{   rW  r|   rC   rC   rD   r·      r~   zSessionError.getErrorCodec                 C   rz   r{   )r]   r|   rC   rC   rD   ÚgetErrorPacket#  r~   zSessionError.getErrorPacketc                 C   s   t j| j S r{   )r   ÚERROR_MESSAGESr  r|   rC   rC   rD   ÚgetErrorString&  r�   zSessionError.getErrorStringc                 C   sF   | j }|tjv rtj| d }tj| d }d| j ||f S d| j  S )Nr   rI   z&SMB SessionError: code: 0x%x - %s - %sz*SMB SessionError: unknown error code: 0x%x)r  r   rš  )r:   r‰  Úerror_msg_shortÚerror_msg_verboserC   rC   rD   Ú__str__)  s   

zSessionError.__str__N)r   r   )	r‘  r’  r“  r”  rE   r·   r™  r›  rž  rC   rC   rC   rD   r¤     s    
r¤   ))rÇ   rd   Úimpacketr   r   r   r   r   r   Úimpacket.ntlmr   r	   Úimpacket.smbr
   Úimpacket.smb3structsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   rU   r¤   rC   rC   rC   rD   Ú<module>   s*    ,       n