Giter Club home page Giter Club logo

smbprotocol's Introduction

smbprotocol

SMBv2 and v3 Client for Python.

Test workflow codecov PyPI version License

SMB is a network file sharing protocol and has numerous iterations over the years. This library implements the SMBv2 and SMBv3 protocol based on the MS-SMB2 document.

Features

  • Negotiation of the SMB 2.0.2 protocol to SMB 3.1.1 (Windows 10/Server 2016)
  • Authentication with both NTLM and Kerberos
  • Message signing
  • Message encryption (SMB 3.x.x+)
  • Connect to a Tree/Share
  • Opening of files, pipes and directories
  • Set create contexts when opening files
  • Read and writing of files and pipes
  • Sending IOCTL commands
  • Sending of multiple messages in one packet (compounding)
  • Experimental support for both standalone and DFS server shares

This is definitely not feature complete as SMB is quite a complex protocol, see backlog for features that would be nice to have in this library.

Requirements

To use Kerberos authentication on Linux, further dependencies are required, to install these dependencies run

# for Debian/Ubuntu/etc:
sudo apt-get install gcc python-dev libkrb5-dev
pip install smbprotocol[kerberos]

# for RHEL/CentOS/etc:
sudo yum install gcc python-devel krb5-devel krb5-workstation python-devel
pip install smbprotocol[kerberos]

Kerberos auth with Windows should just work out of the box with the pyspnego library but on Linux, the python-gssapi library must be installed and smbprotocol requires a particular GSSAPI extension to be available to work. This extension should be installed on the majority of MIT or Heimdal Kerberos installs but that is not a guarantee. To verify that Kerberos is available on Linux you can run the following check in a Python console:

try:
    from gssapi.raw import inquire_sec_context_by_oid
    print("python-gssapi extension is available")
except ImportError as exc:
    print(f"python-gssapi extension is not available: {exc}")

If it isn't available, then either a newer version of the system's gssapi implementation needs to be setup and python-gssapi compiled against that newer version. In the absence of this extension, only NTLM auth is used.

Installation

To install smbprotocol, simply run

pip install smbprotocol

# To install with Kerberos support
pip install smbprotocol[kerberos]

This will download the required packages that are used in this package and get your Python environment ready to go.

Additional Info

One of the first steps as part of the SMB protocol is to negotiate the dialect used and other features that are available. Currently smbprotocol supports the following dialects;

  • 2.0.0: Added with Server 2008/Windows Vista
  • 2.1.0: Added with Server 2008 R2/Windows 7
  • 3.0.0: Added with Server 2012/Windows 8
  • 3.0.2: Added with Server 2012 R2/Windows 8.1
  • 3.1.1: Added with Server 2016/Windows10

Each dialect adds in more features to the protocol where some are minor but some are major. One major changes is in Dialect 3.x where it added message encryption. Message encryption is set to True by default and needs to be overridden when creating a Session object for the older dialects.

By default, the negotiation process will use the latest dialect that is supported by the server but this can be overridden if required. When this is done by the following code

import uuid

from smbprotocol.connection import Connection, Dialects

connection = Connection(uuid.uuid4(), "server", 445)
connection.connect(Dialects.SMB_3_0_2)

While you shouldn't want to downgrade to an earlier version, this does allow you to set a minimum dialect version if required.

Examples

There are 2 different APIs you can use with this library.

  • smbprotocol: Low level interface that can do whatever you want but quite verbose
  • smbclient: Higher level interface that implements the builtin os and os.path file system functions but for SMB support

The examples folder contains some examples of both the high and low level interface but for everyday user's it is recommended to use smbclient as it is a lot simpler.

smbclient Interface

The higher level interface smbclient is designed to make this library easier for people to use for simple and common use cases. It is designed to replicate the builtin os and os.path filesystem functions like os.open(), os.stat(), and os.path.exists(). It is also designed to handle connections to a DFS target unlike smbprotocol.

A connection made by smbclient is kept in a pool and re-used for future requests to the same server until the Python process exists. This makes authentication simple and only required for the first call to the server. Any DFS referrals are also cached in that Python process. This optimises any future requests to that same DFS namespace.

The functions in smbclient have a global config object that can be used to set any connection defaults to use for any future connections. It can also be used to specify any domain based DFS settings for more advanced setups. It is recommended to use ClientConfig() to set any global credentials like so:

import smbclient

smbclient.ClientConfig(username='user', password='password')

The ClientConfig is a singleton and any future instanciations of that object will just update the keys being set. You can set the following keys on the ClientConfig:

  • client_guid: The client GUID to identify the client to the server on a new connection
  • username: The default username to use when creating a new SMB session if explicit credentials weren't set
  • password: The default password to use for authentication
  • domain_controller: The domain controller hostname. This is useful for environments with DFS servers as it is used to identify the DFS domain information automatically
  • skip_dfs: Whether to skip doing any DFS resolution, useful if there is a bug or you don't want to waste any roundtrip requesting referrals
  • auth_protocol: The authentication protocol to use; negotiate (default), kerberos, or ntlm
  • require_secure_negotiate: Control whether the client validates the negotiation info when connecting to a share (default: True).

As well as setting the default credentials on the ClientConfig you can also specify the credentials and other connection parameters on each smbclient function or when registering a new server. These functions accept the following kwargs:

  • username: The username used to connect to the share
  • password: The password used to connect to the share
  • port: Override the default port (445) to connect to
  • encrypt: Whether to force encryption on the connection, requires SMBv3 or newer on the remote server (default: False)
  • connection_timeout: Override the connection timeout in seconds (default: 60)

If using Kerberos authentication and a Kerberos ticket has already set by kinit then smbclient will automatically use those credentials without having to be explicitly set. If no ticket has been retrieved or you wish to use different credentials then set the default credentials on the ClientConfig or specify username and password on the first request to the server.

For example I only need to set the credentials on the first request to create the directory and not for the subsequent file creation in that dir.

import smbclient

# Optional - specify the default credentials to use on the global config object
smbclient.ClientConfig(username='user', password='pass')

# Optional - register the credentials with a server (overrides ClientConfig for that server)
smbclient.register_session("server", username="user", password="pass")

smbclient.mkdir(r"\\server\share\directory", username="user", password="pass")

with smbclient.open_file(r"\\server\share\directory\file.txt", mode="w") as fd:
    fd.write(u"file contents")

If you wish to reset the cache you can either start a new Python process or call smbclient.reset_connection_cache() to close all the connections that have been cached by the client.

Logging

This library makes use of the builtin Python logging facilities. Log messages are logged to the smbprotocol named logger as well as smbprotocol.* where * is each python script in the smbprotocol directory.

These logs are really useful when debugging issues as they give you a more step by step snapshot of what it is doing and what may be going wrong. The debug side will also print out a human readable string of each SMB packet that is sent out from the client so it can get very verbose.

Testing

To this module, you need to install some pre-requisites first. This can be done by running;

# Install in current environment.
# Recommend to have virtual environment installed at .venv path.
pip install -r requirements-dev.txt
pip install -e .

# you can also run tox by installing tox
pip install tox

From there to run the basic tests run;

py.test -v --cov smbprotocol --cov-report term-missing

# or with tox for dedicated virtual environments and multiple Python versions.
tox

Before sending the code for review, besides making sure all the test pass, check that the code complies with the coding standards:

source ./build_helpers/lib.sh

lib::sanity::run

There are extra tests that only run when certain environment variables are set. To run these tests set the following variables;

  • SMB_USER: The username to authenticate with
  • SMB_PASSWORD: The password to authenticate with
  • SMB_SERVER: The IP or hostname of the server to authenticate with
  • SMB_PORT: The port the SMB server is listening on, default is 445
  • SMB_SHARE: The name of the share to connect to, a share with this name must exist as well as a share with the name$SMB_SHARE-encrypted must also exist that forces encryption

From here running tox or py.test with these environment variables set will activate the integration tests.

This requires either Windows 10 or Server 2016 as they support Dialect 3.1.1 which is required by the tests.

If you don't have access to a Windows host, you can use Docker to setup a Samba container and use that as part of the tests. To do so run the following bash commands;

source ./build_helpers/lib.sh

lib::setup::smb_server

This command will also set the required SMB_* env vars used in testing.

Backlog

Here is a list of features that I would like to incorporate, PRs are welcome if you want to implement them yourself;

  • Multiple channel support to speed up large data transfers
  • Lots and lots more...

smbprotocol's People

Contributors

adiroiban avatar alex-weatherhead avatar brno32 avatar christianknoepfle avatar coreyleavitt avatar dhannasch avatar dolfinus avatar iddohau avatar jborean93 avatar jensvanhooydonck avatar kvv81 avatar linuskr avatar malthe avatar michaelkorn avatar mikekokuba avatar mrmaxi avatar mwedl avatar robbert-brand avatar rsdoherty avatar samuelwcm avatar stastnypremysl avatar tik-stbuehler avatar wokis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smbprotocol's Issues

Error importing smbclient

Hi @jborean93, thanks for your contribution.

I was trying to test the high-level SMB connection using smbclient and got this error:

import smbclient
Traceback (most recent call last):
File "", line 1, in
ModuleNotFoundError: No module named 'smbclient'

I installed smbprotocol via pip

SMBDirectoryIO query_directory does not enumerate after certain limit

After investigating #19 it turns out MS SMB servers do not return a file_index on their SMB2 Query Response and the next_entry_offset for each info response is based on that 1 query. This means once we fill up the max output buffer limit that is set for the response smbclient thinks that is all the files left. What we should be doing is sending a 2nd query and wait until we receive STATUS_NO_MORE_FILES back from the server to verify we have scanned the whole folder.

Getting UNKNOWN_ENUM: 0xc0000466

Description

When I'm trying to connect to the server with NTLM I'm getting 0xc0000466 error which is STATUS_SERVER_UNAVAILABLE. But the server is available and I'm successfully connecting through smbclient for example:

Starting GENSEC submechanism ntlmssp
Got challenge flags:
Got NTLMSSP neg_flags=0x60898215
  NTLMSSP_NEGOTIATE_UNICODE
  NTLMSSP_REQUEST_TARGET
  NTLMSSP_NEGOTIATE_SIGN
  NTLMSSP_NEGOTIATE_NTLM
  NTLMSSP_NEGOTIATE_ALWAYS_SIGN
  NTLMSSP_TARGET_TYPE_DOMAIN
  NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  NTLMSSP_NEGOTIATE_TARGET_INFO
  NTLMSSP_NEGOTIATE_128
  NTLMSSP_NEGOTIATE_KEY_EXCH
NTLMSSP: Set final flags:
Got NTLMSSP neg_flags=0x62088215
  NTLMSSP_NEGOTIATE_UNICODE
  NTLMSSP_REQUEST_TARGET
  NTLMSSP_NEGOTIATE_SIGN
  NTLMSSP_NEGOTIATE_NTLM
  NTLMSSP_NEGOTIATE_ALWAYS_SIGN
  NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  NTLMSSP_NEGOTIATE_VERSION
  NTLMSSP_NEGOTIATE_128
  NTLMSSP_NEGOTIATE_KEY_EXCH
NTLMSSP Sign/Seal - Initialising with flags:
Got NTLMSSP neg_flags=0x62088215
  NTLMSSP_NEGOTIATE_UNICODE
  NTLMSSP_REQUEST_TARGET
  NTLMSSP_NEGOTIATE_SIGN
  NTLMSSP_NEGOTIATE_NTLM
  NTLMSSP_NEGOTIATE_ALWAYS_SIGN
  NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  NTLMSSP_NEGOTIATE_VERSION
  NTLMSSP_NEGOTIATE_128
  NTLMSSP_NEGOTIATE_KEY_EXCH
^[[ANTLMSSP Sign/Seal - Initialising with flags:
Got NTLMSSP neg_flags=0x62088215
  NTLMSSP_NEGOTIATE_UNICODE
  NTLMSSP_REQUEST_TARGET
  NTLMSSP_NEGOTIATE_SIGN
  NTLMSSP_NEGOTIATE_NTLM
  NTLMSSP_NEGOTIATE_ALWAYS_SIGN
  NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  NTLMSSP_NEGOTIATE_VERSION
  NTLMSSP_NEGOTIATE_128
  NTLMSSP_NEGOTIATE_KEY_EXCH
 session setup ok
signed SMB2 message
signed SMB2 message
 tconx ok

Log

INFO:smbprotocol.connection:Initialising connection, guid: 3683b9d7-c080-4104-84db-012322e8d87d, require_singing: True, server_name: xxx, port: 445
INFO:smbprotocol.connection:Setting up transport connection
INFO:smbprotocol.connection:Starting negotiation with SMB server
INFO:smbprotocol.connection:Negotiating with SMB2 protocol with highest client dialect of: SMB_3_1_1
INFO:smbprotocol.connection:Sending SMB2 Negotiate message
INFO:smbprotocol.transport:Connecting to DirectTcp socket
INFO:smbprotocol.connection:Receiving SMB2 Negotiate response
INFO:smbprotocol.connection:Negotiated dialect: (785) SMB_3_1_1
INFO:smbprotocol.connection:Connection require signing: True
INFO:smbprotocol.session:Initialising session with username: xxx
INFO:smbprotocol.session:Attempting auth with mech KRB5 (1.2.840.113554.1.2.2)
WARNING:smbprotocol.session:Failed auth for mech KRB5 (1.2.840.113554.1.2.2): Mech Type 1.2.840.113554.1.2.2 is not yet supported
INFO:smbprotocol.session:Attempting auth with mech NTLMSSP (1.3.6.1.4.1.311.2.2.10)
INFO:smbprotocol.session:Setting up NTLM Security Context for user xxx
INFO:smbprotocol.session:NTLM: Generating Negotiate message
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
WARNING:smbprotocol.session:Failed auth for mech NTLMSSP (1.3.6.1.4.1.311.2.2.10): Received unexpected status from the server: (3221226598) UNKNOWN_ENUM: 0xc0000466
Traceback (most recent call last):
  File "main.py", line 171, in <module>
    main()
  File "main.py", line 155, in main
    concats.append(process(**el))
  File "main.py", line 40, in process
    df = concat_block(paths, sheets, columns, spec)
  File "main.py", line 53, in concat_block
    p, sheet_name=s, header=spec["header"] if "header" in spec else 0)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/pandas/util/_decorators.py", line 296, in wrapper
    return func(*args, **kwargs)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/pandas/io/excel/_base.py", line 304, in read_excel
    io = ExcelFile(io, engine=engine)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/pandas/io/excel/_base.py", line 867, in __init__
    self._reader = self._engines[engine](self._io)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/pandas/io/excel/_xlrd.py", line 22, in __init__
    super().__init__(filepath_or_buffer)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/pandas/io/excel/_base.py", line 344, in __init__
    filepath_or_buffer, _, _, _ = get_filepath_or_buffer(filepath_or_buffer)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/pandas/io/common.py", line 222, in get_filepath_or_buffer
    filepath_or_buffer, mode=mode or "rb", **(storage_options or {})
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/fsspec/core.py", line 399, in open
    **kwargs
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/fsspec/core.py", line 250, in open_files
    expand=expand,
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/fsspec/core.py", line 570, in get_fs_token_paths
    fs = cls(**options)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/fsspec/spec.py", line 55, in __call__
    obj = super().__call__(*args, **kwargs)
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/fsspec/implementations/smb.py", line 101, in __init__
    self._connect()
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/fsspec/implementations/smb.py", line 110, in _connect
    connection_timeout=self.timeout,
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/smbclient/_pool.py", line 113, in register_session
    session.connect()
  File "/home/dtrishkin/.pyenv/versions/3.7.8/lib/python3.7/site-packages/smbprotocol/session.py", line 319, in connect
    "%s" % str(errors))
smbprotocol.exceptions.SMBAuthenticationError: Failed to authenticate with server: {'KRB5 (1.2.840.113554.1.2.2)': 'Mech Type 1.2.840.113554.1.2.2 is not yet supported', 'NTLMSSP (1.3.6.1.4.1.311.2.2.10)': 'Received unexpected status from the server: (3221226598) UNKNOWN_ENUM: 0xc0000466'}
INFO:smbprotocol.connection:Disconnecting transport connection
INFO:smbprotocol.transport:Disconnecting DirectTcp socket

System: Ubuntu 20.04.1 LTS

copy_tree tries to connect to source root

I'm using copytree with the following parameters for src and dst:

------------ FILEPATH ------------ (src)
T:\x\synctest\folder
------------ DESTINATION ------------ (dst)
\IP\write_test\testroot\testdir\folder

and get the following error: ValueError: Failed to connect to 'T::445': [Errno 11001] getaddrinfo failed

However, when i use copy2 to transfer files it works.

EOF issue

Hi Jordan, great work on this repo esp the new 'high level" addition.

I attempted to use open_file with v1.0.0 and got error like

   smbprotocol.exceptions.SMBResponseException: Received unexpected status from the server: (3221225489) STATUS_END_OF_FILE: 0xc0000011

which from this site means "Attempted to read beyond the end of the file."

The code almost identical to example... python3 code;

import smbclient
smbclient.register_session("server", username="user@domain", password="pass")
with smbclient.open_file(file_path) as fd:
print (fd.read())

I have verified the connection is fine as stat() works fine on file_path which is a .txt file.

kind regards,
AK

Any way to disable connection cache?

Sometimes when I open SMB files from processes generated by Dask, some SMB operations hang there like forever (at least > 10min). After I add smbclient.reset_connection_cache() before each smbclient operation, the issue disappears.

So I guess that there is something abnormal in the caching, especially when Dask tries to implicitly share (serialize here and deserialize there) objects among the processes it creates.

I'd like to disable the cache. Is there any way for it? In case the users can take the performance penalty.

SMBException - How can I transfer a large file?

Hi - I was trying to copy a file to SMB and encountered this error: SMBException: The requested write length 842899 is greater than the maximum negotiated write size 65536

This is how I'm using it:

    with open(localpath, 'rb') as src, smbclient.open_file(remotepath, mode='wb') as dst:
        dst.write(src.read())
 

How to close session?

After smbclient.register_session("server", username="user", password="pass")
How to close this session?

I/O-Free / Sans-I/O / async io protocol Implementation

Hi Jordan,

Many thanks for creating this nice library.

Would you consider a patch for supporting a sans-io [1] implementation of the protocol

The code already provide a nice organization of the all SMB messages for creating and parsing the packages.

I am looking into reusing your code with asyncio [2] / twisted and maybe the implementations can share more code.

[1] https://sans-io.readthedocs.io/how-to-sans-io.html
[2] https://docs.python.org/3.9/library/asyncio.html

Kerberos Authentication: Publish a new release with connection_cache argument

Hi,

I've seen there's now an option to specify a connection_cache, but it's not available on the latest release available on PyPi.
Is there any plan when it should be release?

Also, if may I ask, today to authenticate using Kerberos is only required to have installed dependencies and omit username/password?

Thanks and nice project!

There is support for symlink / junctions created by mklink?

Hi,
I've seen there is support for symlink, I've tried to use it on linux and it seems that is working, but I have some issues with symlink and junctions created by mklink in windows with the following commands:
mklink /J D:\Share\LinkToFolder1 D:\Folder1
mklink /D D:\Share\LinkToFolder1 D:\Folder1

My Setup:
I have Folder Share and a folder named Folder1.
"Share" is used for smb share connection as root.
Inside Share I'm creating one junction or one symlink to Folder1

Both Share and Folder1 are on the same machine.

The error that I'm getting when I try to parse the files is the following:
image

Thanks.

STATUS_BAD_NETWORK_NAME: 0xc00000cc

Good day folks. Looking for some assistance. I'm getting the above error upon a write to a DFS share. The piece of code is working as I do get files/etc on the share but the script is long running (should take up to 5 hours). Fails at around the 35 minute mark. Files are around the 100 to 200 MB size.

Any advice on how to fix?

Overview of code/environment:
smbprotocol v1.4.0 (Python 3.8.3)
importing smbclient module only
ClientConfig using defaults (except user/password)
file contents is the text output from a SSH session (mode="w", share_access="r", encoding='utf-16')
file handler closed after write

Traceback (most recent call last):
	File "\Python\Python38\lib\site-packages\smbclient\_pool.py", line 302, in get_smb_tree
		tree.connect(require_secure_negotiate=client_config.require_secure_negotiate)
	File "\Python\Python38\lib\site-packages\smbprotocol\tree.py", line 245, in connect
		response = self.session.connection.receive(request)
	File "\Python\Python38\lib\site-packages\smbprotocol\connection.py", line 617, in wrapped
		return func(self, *args, **kwargs)
	File "\Python\Python38\lib\site-packages\smbprotocol\connection.py", line 931, in receive
		raise SMBResponseException(response)
	smbprotocol.exceptions.BadNetworkName: Received unexpected status from the server: The specified share name cannot be found on the remote server. (3221225676) STATUS_BAD_NETWORK_NAME: 0xc00000cc

STATUS_NETWORK_SESSION_EXPIRED not handled

I have a long running process. After "a while" it fails to write with the following:

Traceback (most recent call last):
  File "/home/worker/venv/lib/python3.8/site-packages/smbclient/_io.py", line 368, in open
    open_result = self.fd.create(
  File "/home/worker/venv/lib/python3.8/site-packages/smbprotocol/open.py", line 1213, in create
    return self._create_response(request)
  File "/home/worker/venv/lib/python3.8/site-packages/smbprotocol/open.py", line 1219, in _create_response
    response = self.connection.receive(request)
  File "/home/worker/venv/lib/python3.8/site-packages/smbprotocol/connection.py", line 928, in receive
    raise SMBResponseException(response)
smbprotocol.exceptions.SMBResponseException: Received unexpected status from the server: Unknown error. (3221226332) UNKNOWN_ENUM: 0xc000035c

Looking here I can see this corresponds to STATUS_NETWORK_SESSION_EXPIRED.

Is there a way to handle this?

ConnectionResetError

Hi,

When doing some testing with your library, I happen to stumble onto a ConnectionResetError as follows:

  File "<stdin>", line 1, in <module>
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbclient\_os.py", line 230, in listdir
    with SMBDirectoryIO(path, mode='r', share_access='r', **kwargs) as dir_fd:
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbclient\_io.py", line 295, in __enter__
    self.open()
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbclient\_io.py", line 334, in open
    open_result = self.fd.create(
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbprotocol\open.py", line 1207, in create
    request = self.connection.send(create,
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbprotocol\connection.py", line 965, in send
    return self._send([message], session_id=sid, tree_id=tid, message_id=message_id, credit_request=credit_request,
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbprotocol\connection.py", line 763, in wrapped
    return func(self, *args, **kwargs)
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbprotocol\connection.py", line 1251, in _send
    self.transport.send(send_data)
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbprotocol\transport.py", line 67, in wrapped
    func(self, *args, **kwargs)
  File "D:\Python\Anaconda3-2019.10\envs\test_env\lib\site-packages\smbprotocol\transport.py", line 108, in send
    sent = self._sock.send(data)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

The funny thing is, it's never a problem the first time I try to use the smbclient, but it happens after some undetermined amount of time, which helps a lot in debugging /s
I manage to solve this problem by either restarting my Python shell, or by deleting the connection from the pool in smbclient._pool._SMB_CONNECTIONS. Note that I was able to find this second solution by trying to delete the connection and resetting the connection cache, and seeing that the code fails when trying to disconnect the connection, yet it still works as smbclient._pool.delete_session first deletes the connection from the pool then tries to disconnect it, while smbclient._pool.reset_connection_cache does it the other way around (might be an other issue that you should look into?).

I can manage with this weird solution, but it doesn't feel right, especially because I'm never closing the connection in the end. Do you have any idea where that could come from? My guess is that it's because I'm behind a proxy using Kerberos authentication, which should be invalidated after a certain amount of time, but I've been running the following code for almost 25min straight without any error, despite the error happening much quicker in other cases and Kerberos authentication supposedly running out after 15min max.

import smbclient
import time

start_time = time.perf_counter()

try:
    while True:
        smbclient.listdir(server)
except:
    pass

stop_time = time.perf_counter()

print("Elapsed time: {diff}s".format(diff=stop_time-start_time))

Thanks in advance for any help you could provide.

Handle large number of connections

We use the smbprotocol library to access a Samba share in our code. When the same client tries to open a large number of connections, the server appears to be overloaded and the operation fails, either due to insufficient credits or because of a broken pipe. Here are tracebacks for these two cases:

...
  File "/home/apache/adidas/custom/adidas/utilities/file_operation/smb_file_operation.py", line 91, in copy
    if smbclient.path.isdir(source_path, **self.common_kwargs):
  File "/usr/local/lib/python2.7/dist-packages/smbclient/path.py", line 110, in isdir
    return _stat_ismode(path, py_stat.S_ISDIR, True, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/path.py", line 154, in _stat_ismode
    return check(stat(path, follow_symlinks=follow, **kwargs).st_mode)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/_os.py", line 551, in stat
    query_info(transaction, FileAttributeTagInformation)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/_io.py", line 202, in __exit__
    self.commit()
  File "/usr/local/lib/python2.7/dist-packages/smbclient/_io.py", line 228, in commit
    requests = self.raw.fd.connection.send_compound(send_msgs, sid, tid, related=True)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/connection.py", line 981, in send_compound
    return self._send(messages, session_id=sid, tree_id=tid, related=related)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/connection.py", line 763, in wrapped
    return func(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/connection.py", line 1189, in _send
    % (credit_charge, credits_available))
SMBException: Request requires 1 credits but only 0 credits are available
...
  File "/home/apache/adidas/custom/adidas/utilities/file_operation/smb_file_operation.py", line 120, in exists
    return smbclient.path.exists(path, **self.common_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/path.py", line 27, in exists
    return _exists(path, False, True, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/path.py", line 141, in _exists
    stat(path, follow_symlinks=follow_symlinks, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/_os.py", line 551, in stat
    query_info(transaction, FileAttributeTagInformation)
  File "/usr/local/lib/python2.7/dist-packages/smbclient/_io.py", line 202, in __exit__
    self.commit()
  File "/usr/local/lib/python2.7/dist-packages/smbclient/_io.py", line 228, in commit
    requests = self.raw.fd.connection.send_compound(send_msgs, sid, tid, related=True)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/connection.py", line 981, in send_compound
    return self._send(messages, session_id=sid, tree_id=tid, related=related)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/connection.py", line 763, in wrapped
    return func(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/connection.py", line 1244, in _send
    self.transport.send(send_data)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/transport.py", line 67, in wrapped
    func(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/smbprotocol/transport.py", line 108, in send
    sent = self._sock.send(data)
error: [Errno 32] Broken pipe

Is there a way to handle such a case within the functionalities of this library?

Transfering files and dirs with this package

Hello, how would I go about transfering local files to smb shares with this package?

source = smbclient._io.SMBDirectoryIO(filepath, 'r') filetTransaction = smbclient._io.SMBFileTransaction(source) filetTransaction.commit

is this a viable way to do it?

Possible to check for locked files?

I'm looking for a way to determine if there are any files being actively written to a samba share server, similar to the output of the smbstatus command. Is that possible with smbprotocol? Thanks!

connection.py timeout in _send_smb2_negotiate, line 1354

Normally, I would not produce an "issue" for a simple timeout. However, in this case, the remote server never responds (and thus the timeout occurs every time) while another library I'm trying out always connects. Here's the output from the negotiate call (I figure this is important and meaningful to you):

INFO     | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Starting negotiation with SMB server
INFO     | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Negotiating with SMB2 protocol with highest client dialect of: SMB_3_1_1
DEBUG    | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Adding client guid cd3ede82-b089-46b7-80f8-966f86cb82c9 to negotiate request
DEBUG    | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Adding client capabilities 68 to negotiate request
DEBUG    | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Adding preauth integrity capabilities of hash SHA512 and salt á—?Nͬ?áV¼fÑWHUÉ· ÞQ�©��¿
žtÆ!á� to negotiate request
DEBUG    | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Adding encryption capabilities of AES128 GCM and AES128 CCM to negotiate request
INFO     | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Sending SMB2 Negotiate message
DEBUG    | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | SMB3NegotiateRequest:
    structure_size = 36
    dialect_count = 5
    security_mode = (2) SMB2_NEGOTIATE_SIGNING_REQUIRED
    reserved = 0
    capabilities = (68) SMB2_GLOBAL_CAP_ENCRYPTION, SMB2_GLOBAL_CAP_LARGE_MTU
    client_guid = cd3ede82-b089-46b7-80f8-966f86cb82c9
    negotiate_context_offset = 112
    negotiate_context_count = 2
    reserved2 = 0
    dialects = [
        (514) SMB_2_0_2,
        (528) SMB_2_1_0,
        (768) SMB_3_0_0,
        (770) SMB_3_0_2,
        (785) SMB_3_1_1
    ]
    padding = 00 00
    negotiate_context_list = [
        SMB2NegotiateContextRequest:
            context_type = (1) SMB2_PREAUTH_INTEGRITY_CAPABILITIES
            data_length = 38
            reserved = 0
            data =
            SMB2PreauthIntegrityCapabilities:
                hash_algorithm_count = 1
                salt_length = 32
                hash_algorithms = [
                    (1) SHA_512
                ]
                salt = E1 97 90 4E CD AC 90 E1 56 BC 66 D1 57 48 55 C9 B7 A0 DE 51 02 A9 14 06 BF 0D 9E 74 C6 21 E1 13

                Raw Hex:
                    01 00 20 00 01 00 E1 97
                    90 4E CD AC 90 E1 56 BC
                    66 D1 57 48 55 C9 B7 A0
                    DE 51 02 A9 14 06 BF 0D
                    9E 74 C6 21 E1 13
            padding = 00 00

            Raw Hex:
                01 00 26 00 00 00 00 00
                01 00 20 00 01 00 E1 97
                90 4E CD AC 90 E1 56 BC
                66 D1 57 48 55 C9 B7 A0
                DE 51 02 A9 14 06 BF 0D
                9E 74 C6 21 E1 13 00 00,
        SMB2NegotiateContextRequest:
            context_type = (2) SMB2_ENCRYPTION_CAPABILITIES
            data_length = 6
            reserved = 0
            data =
            SMB2EncryptionCapabilities:
                cipher_count = 2
                ciphers = [
                    (2) AES_128_GCM,
                    (1) AES_128_CCM
                ]

                Raw Hex:
                    02 00 02 00 01 00
            padding = 

            Raw Hex:
                02 00 06 00 00 00 00 00
                02 00 02 00 01 00
    ]

    Raw Hex:
        24 00 05 00 02 00 00 00
        44 00 00 00 CD 3E DE 82
        B0 89 46 B7 80 F8 96 6F
        86 CB 82 C9 70 00 00 00
        02 00 00 00 02 02 10 02
        00 03 02 03 11 03 00 00
        01 00 26 00 00 00 00 00
        01 00 20 00 01 00 E1 97
        90 4E CD AC 90 E1 56 BC
        66 D1 57 48 55 C9 B7 A0
        DE 51 02 A9 14 06 BF 0D
        9E 74 C6 21 E1 13 00 00
        02 00 06 00 00 00 00 00
        02 00 02 00 01 00
INFO     | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | Created SMB Packet Header for (0) SMB2_NEGOTIATE request
DEBUG    | Thread-27    |08-31-18 13:01:09 | discovery.lib.connec | SMB2HeaderRequest:
    protocol_id = FE 53 4D 42
    structure_size = 64
    credit_charge = 0
    channel_sequence = 0
    reserved = 0
    command = (0) SMB2_NEGOTIATE
    credit_request = 0
    flags = 0
    next_command = 0
    message_id = 0
    process_id = 0
    tree_id = 0
    session_id = 0
    signature = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    data = 

    Raw Hex:
        FE 53 4D 42 40 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00

the timeout occurs at this point in the receive call:
connection.py, receive(),

  • line 1022 never receives a response
  • line 1028 now properly times out (after the timeout=timeout) fix

What is the maximum data write limit?

I am trying to download a very large file from a client to the remote server that I am creating using the smbclient, I break down my file into chunks, I perform the following steps:

  1. Open an empty file in the remote share server
  2. truncate the length of the destination file to source file length
  3. Now I want to write the chunk to their respective offset however I am unable to perform this
smbclient.truncate(path=destination_file_path, length=file_size)

with smbclient.open_file(path=destination_file_path, mode="ab", share_access="rw") as fd:
    fd.seek(chunk_start)
    fd.write(chunk_data_in_bytes)

I am able to write at most 8MBs of a data per chunk at a specified offset, when I try to write for more than 8Mb I get the following error

Traceback (most recent call last):
  File "/var/task/smbclient/_io.py", line 505, in write
    transaction += self.fd.write(b, offset=self._offset, send=False)
  File "/var/task/smbprotocol/open.py", line 1345, in write
    raise SMBException("The requested write length %d is greater than "
smbprotocol.exceptions.SMBException: The requested write length 20971520 is greater than the maximum negotiated write size 8388608

Wanted to confirm if 8MB is the write limit?

SMBClient fails: STATUS_MORE_PROCESSING_REQUIRED

Hey @jborean93 ,

I am keep getting (3221225494) STATUS_MORE_PROCESSING_REQUIRED
I am trying to access to share within some organization, if i use the windows explorer or Linux mount it works normally, how i can solve this issue ?

The line i am executing
smbclient.register_session("100.100.180.140", username="USER", password="PASS")

I am running on Ubuntu 18.04 and this code passes
try: from gssapi.raw import inquire_sec_context_by_oid print("python-gssapi extension is available") except ImportError as exc: print("python-gssapi extension is not available: %s" % str(exc))

Tried the same code on Windows also getting the same error

Exception: STATUS_NOT_SUPPORTED: 0xc00000bb

What can be the reason?

If I set dialect (2.0.2 or 2.1.0) in the connection, open session and connect a tree
tree.connect()
it works
without setting dialect it throws the same exception both in low-level and high-level APIs:

INFO:smbprotocol.tree:Session: user, Tree: \\my_server\common - Receiving secure negotiation response
Traceback (most recent call last):
  File "C:/Users/user/prj/research/python/sandbox/misc/smb_tester.py", line 41, in <module>
    for filename in listdir(r"\\my_server\common\DataScienceIn"):
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbclient\_os.py", line 232, in listdir
    with SMBDirectoryIO(path, mode='r', share_access='r', **kwargs) as dir_fd:
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbclient\_io.py", line 291, in __init__
    tree, fd_path = get_smb_tree(path, **kwargs)
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbclient\_pool.py", line 299, in get_smb_tree
    tree.connect()
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbprotocol\tree.py", line 271, in connect
    self._verify_dialect_negotiate()
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbprotocol\tree.py", line 329, in _verify_dialect_negotiate
    response = self.session.connection.receive(request)
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbprotocol\connection.py", line 617, in wrapped
    return func(self, *args, **kwargs)
  File "C:\Users\user\prj\research\python\sandbox\.venv-win\lib\site-packages\smbprotocol\connection.py", line 929, in receive
    raise SMBResponseException(response)
smbprotocol.exceptions.NotSupported: Received unexpected status from the server: The request is not supported. (3221225659) STATUS_NOT_SUPPORTED: 0xc00000bb
INFO:smbprotocol.tree:Session: user, Tree: \\my_server\common - Disconnecting from Tree Connect
INFO:smbprotocol.tree:Session: user, Tree: \\my_server\common - Sending Tree Disconnect message

Add support for DFS shares

Hello,

I am getting this error when I try to used it with my File Server. On the Microsoft doc it seems related to STATUS_PATH_NOT_COVERED. Im trying with the full DFS share name but impossible. Is smbprotocol support DFS ? Or any idea of what should I used ?

smbprotocol.exceptions.SMBResponseException: Received unexpected status from the server: (3221226071) UNKNOWN_ENUM: 0xc0000257

Impossible to list the root of any share and any directories from share.

Thank for your hints :)

Interface is overly complex: couple of file operations takes 120 lines

Hi,

While the project is extensible and "correct" from OOP point of view, it lacks sensible defaults and shortcuts. In the examples in this repo, it took 120 lines to open, read and delete a file. This makes the project unusable...

It would be cool to get a file this way, for example:

with Session.connect('server', 12345, 'Administrator', password) as session:
    with session.open_file('C$', '/path/to/file') as f:
        ...

Having only two visible entities, session and opened file, would be enough for most users. Connection and TreeConnect may be hidden. Security stuff needs more shurtcuts as it's impossible for average user to quickly come up with correct ones.

Low read performance

Hi!

I'm looking into accessing files on SMB shares from Dask via fsspec and eventually smbprotocol. This works very well. But in tests it seemed that reading was a bit slow. Comparison with a Linux cifsfs mount and pysmbc showed that write performance is almost on par between them but reads with smbclient are only about half as fast as writes.

I've created this small testcase (and analogous ones for local/cifsfs and pysmb accesses):

import smbclient
import datetime

smbclient.register_session("dc")

string = ""
for j in range(1000):
    string += "%d:%s" % (j, ",".join("%d" % i for i in range(1000)))

start = datetime.datetime.now()
with smbclient.open_file("//dc/share/fsspec-smbprotocol.txt", "w", encrypt=False) as f:
    for i in range(100):
        f.write("%d:%s\n" % (i, string))

print("read: %s" % (datetime.datetime.now() - start))

start = datetime.datetime.now()
with smbclient.open_file("//dc/share/fsspec-smbprotocol.txt", "r", encrypt=False) as f:
    while f.read(1024*1024*10):
        pass

print("write: %s" % (datetime.datetime.now() - start))

In my testing environment it logs:

read: 0:00:02.762513
write: 0:00:04.584177

Is this something you're aware of or have an idea what could be causing it?

With Linux cifsfs mount and pysmbc both read and write of this ~380MiB test data is in the range of 2.5 to 3 seconds.

I've tried profiling the read and write parts and noticed that the read part spends a lot more time waiting for locks and, particularly, in

def unpack(self, data):
.
Reproducer:

import cProfile, pstats, io
from pstats import SortKey
pr = cProfile.Profile()
pr.enable()

import smbclient

start = datetime.datetime.now()
with smbclient.open_file("//dc/share/fsspec-smbprotocol.txt", "r", encrypt=False) as f:
    while f.read(1024*1024*10):
        pass
print(datetime.datetime.now() - start)

pr.disable()
s = io.StringIO()
ps = pstats.Stats(pr, stream=s)
ps.sort_stats('cumtime')
ps.print_callers()
print(s.getvalue())

Output excerpt:

0:00:04.415829
   Ordered by: cumulative time

Function                                                                                                                            was called by...
                                                                                                                                        ncalls  tottime  cumtime
/srv/conda/envs/notebook/lib/python3.8/site-packages/IPython/core/interactiveshell.py:3377(run_code)                                <- 
{built-in method builtins.exec}                                                                                                     <-       5    0.000    4.416  /srv/conda/envs/notebook/lib/python3.8/site-packages/IPython/core/interactiveshell.py:3377(run_code)
<ipython-input-16-c7a4da727bf9>:9(<module>)                                                                                         <-       1    0.000    4.416  {built-in method builtins.exec}
{method 'read' of '_io.TextIOWrapper' objects}                                                                                      <-      39    0.127    4.408  <ipython-input-16-c7a4da727bf9>:9(<module>)
/srv/conda/envs/notebook/lib/python3.8/site-packages/smbclient/_io.py:499(readinto)                                                 <-      77    0.078    4.190  {method 'read' of '_io.TextIOWrapper' objects}
/srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1309(_read_response)                                       <-      75    0.003    3.991  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbclient/_io.py:499(readinto)
/srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/connection.py:834(receive)                                         <-       1    0.000    0.001  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1215(_create_response)
                                                                                                                                            75    0.002    3.481  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1309(_read_response)
                                                                                                                                             1    0.000    0.002  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1539(_close_response)
/srv/conda/envs/notebook/lib/python3.8/threading.py:540(wait)                                                                       <-      77    0.001    3.479  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/connection.py:834(receive)
/srv/conda/envs/notebook/lib/python3.8/threading.py:270(wait)                                                                       <-      77    0.001    3.478  /srv/conda/envs/notebook/lib/python3.8/threading.py:540(wait)
{method 'acquire' of '_thread.lock' objects}                                                                                        <-      77    0.000    0.000  /srv/conda/envs/notebook/lib/python3.8/threading.py:258(_acquire_restore)
                                                                                                                                            77    0.000    0.000  /srv/conda/envs/notebook/lib/python3.8/threading.py:261(_is_owned)
                                                                                                                                           154    3.476    3.476  /srv/conda/envs/notebook/lib/python3.8/threading.py:270(wait)
                                                                                                                                             3    0.000    0.000  /srv/conda/envs/notebook/lib/python3.8/threading.py:1017(_wait_for_tstate_lock)
/srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/structure.py:146(unpack)                                           <-       1    0.000    0.000  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1215(_create_response)
                                                                                                                                            75    0.004    0.498  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1309(_read_response)
                                                                                                                                             2    0.000    0.000  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/open.py:1539(_close_response)
/srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/structure.py:233(unpack)                                           <-     555    0.477    0.494  /srv/conda/envs/notebook/lib/python3.8/site-packages/smbprotocol/structure.py:146(unpack)
[nothing above 100ms cumulative time below that]

The function looks benign at first but a closer look reveals that it calls more methods and properties which for some reason the profiling doesn't show. So it's unclear to me where the time is spent.

Also, might there be lock contention in the read case that could be avoided?

Thanks!

IPv6 and v6 link-local not supported

The following fails on IPv6 global addresses and IPv6 link-local but a IPv4 addresses works successfully.

#!/usr/bin/env python3

from pypsexec.client import Client

# creates an encrypted connection to the host with the username and password
c = Client('[fe80::250:56ff:feab:9405%ens192]', username="Administrator", password="somepass")

c.connect()
try:
    c.create_service()

    # After creating the service, you can run multiple exe's without
    # reconnecting

    # run a simple cmd.exe program with arguments
    result = c.run_executable("cmd.exe",
                              arguments="/c echo Hello World")
finally:
    c.remove_service()
    c.disconnect()

print("STDOUT:\n%s" % result[0].decode('utf-8') if result[0] else "")
print("STDERR:\n%s" % result[1].decode('utf-8') if result[1] else "")
print("RC: %d" % result[2])

Port 445 is open via IPv6

[root@jumphost ~]# telnet fe80::250:56ff:feab:9405%ens192 445
Trying fe80::250:56ff:feab:9405%ens192...
Connected to fe80::250:56ff:feab:9405%ens192.
Escape character is '^]'.
^]
telnet> quit

Error Message:

[root@jumphost ~]# python3 psexec_test.py                        
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/transport.py", line 57, in wrapped
    self._sock = socket.create_connection((self.server, self.port), timeout=self.timeout)
  File "/usr/lib64/python3.6/socket.py", line 704, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/usr/lib64/python3.6/socket.py", line 745, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "psexec_test.py", line 11, in <module>
    c.connect()
  File "/usr/local/lib/python3.6/site-packages/pypsexec/client.py", line 60, in connect
    self.connection.connect(timeout=timeout)
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 881, in connect
    smb_response = self._send_smb2_negotiate(dialect, timeout)
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 1446, in _send_smb2_negotiate
    request = self.send(neg_req)
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 966, in send
    async_id=async_id)[0]
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 763, in wrapped
    return func(self, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 1244, in _send
    self.transport.send(send_data)
  File "/usr/local/lib/python3.6/site-packages/smbprotocol/transport.py", line 59, in wrapped
    raise ValueError("Failed to connect to '%s:%s': %s" % (self.server, self.port, str(err)))
ValueError: Failed to connect to '[fe80::250:56ff:feab:9405%ens192]:445': [Errno -2] Name or service not known

Use Azure File Storage to transfer files

Hi all.
I like to use the smb functionality of Microsoft Azure Filestorage to transfer files via SMB .

Unfortunately I receive the following error: pyasn1.error.SubstrateUnderrunError: Short octet stream on tag decoding

If I have a closer look to the Session.connect methode I see that the self.connection.gss_negotiate_token value is empty.

I used the example python file of this project.

Here is the log:

INFO:smbprotocol.connection:Initialising connection, guid: 693fa1c0-1ddd-4a0a-b3a6-b4173beff67a, require_singing: True, server_name: foo.file.core.windows.net, port: 445
INFO:smbprotocol.connection:Setting up transport connection
INFO:smbprotocol.connection:Starting negotiation with SMB server
INFO:smbprotocol.connection:Negotiating with SMB2 protocol with highest client dialect of: SMB_3_1_1
DEBUG:smbprotocol.connection:Adding client guid 693fa1c0-1ddd-4a0a-b3a6-b4173beff67a to negotiate request
DEBUG:smbprotocol.connection:Adding client capabilities 68 to negotiate request
DEBUG:smbprotocol.connection:Adding preauth integrity capabilities of hash SHA512 and salt b'\x1aJ\x87pb;\xa2zt\xe7\x0f\xd7\x1d5\x02`\xf3\xc6\xa4\x90\xac\xeel$B\x13\xa3\xdevv\x91\xcd' to negotiate request
DEBUG:smbprotocol.connection:Adding encryption capabilities of AES128 GCM and AES128 CCM to negotiate request
INFO:smbprotocol.connection:Sending SMB2 Negotiate message
DEBUG:smbprotocol.connection:SMB3NegotiateRequest:
    structure_size = 36
    dialect_count = 5
    security_mode = (2) SMB2_NEGOTIATE_SIGNING_REQUIRED
    reserved = 0
    capabilities = (68) SMB2_GLOBAL_CAP_ENCRYPTION, SMB2_GLOBAL_CAP_LARGE_MTU
    client_guid = 693fa1c0-1ddd-4a0a-b3a6-b4173beff67a
    negotiate_context_offset = 112
    negotiate_context_count = 2
    reserved2 = 0
    dialects = [
        (514) SMB_2_0_2,
        (528) SMB_2_1_0,
        (768) SMB_3_0_0,
        (770) SMB_3_0_2,
        (785) SMB_3_1_1
    ]
    padding = 00 00
    negotiate_context_list = [
        SMB2NegotiateContextRequest:
            context_type = (1) SMB2_PREAUTH_INTEGRITY_CAPABILITIES
            data_length = 38
            reserved = 0
            data =
            SMB2PreauthIntegrityCapabilities:
                hash_algorithm_count = 1
                salt_length = 32
                hash_algorithms = [
                    (1) SHA_512
                ]
                salt = 1A 4A 87 70 62 3B A2 7A 74 E7 0F D7 1D 35 02 60 F3 C6 A4 90 AC EE 6C 24 42 13 A3 DE 76 76 91 CD

                Raw Hex:
                    01 00 20 00 01 00 1A 4A
                    87 70 62 3B A2 7A 74 E7
                    0F D7 1D 35 02 60 F3 C6
                    A4 90 AC EE 6C 24 42 13
                    A3 DE 76 76 91 CD
            padding = 00 00

            Raw Hex:
                01 00 26 00 00 00 00 00
                01 00 20 00 01 00 1A 4A
                87 70 62 3B A2 7A 74 E7
                0F D7 1D 35 02 60 F3 C6
                A4 90 AC EE 6C 24 42 13
                A3 DE 76 76 91 CD 00 00,
        SMB2NegotiateContextRequest:
            context_type = (2) SMB2_ENCRYPTION_CAPABILITIES
            data_length = 6
            reserved = 0
            data =
            SMB2EncryptionCapabilities:
                cipher_count = 2
                ciphers = [
                    (2) AES_128_GCM,
                    (1) AES_128_CCM
                ]

                Raw Hex:
                    02 00 02 00 01 00
            padding = 

            Raw Hex:
                02 00 06 00 00 00 00 00
                02 00 02 00 01 00
    ]

    Raw Hex:
        24 00 05 00 02 00 00 00
        44 00 00 00 69 3F A1 C0
        1D DD 4A 0A B3 A6 B4 17
        3B EF F6 7A 70 00 00 00
        02 00 00 00 02 02 10 02
        00 03 02 03 11 03 00 00
        01 00 26 00 00 00 00 00
        01 00 20 00 01 00 1A 4A
        87 70 62 3B A2 7A 74 E7
        0F D7 1D 35 02 60 F3 C6
        A4 90 AC EE 6C 24 42 13
        A3 DE 76 76 91 CD 00 00
        02 00 06 00 00 00 00 00
        02 00 02 00 01 00
INFO:smbprotocol.transport:Connecting to DirectTcp socket
INFO:smbprotocol.connection:Receiving SMB2 Negotiate response
DEBUG:smbprotocol.connection:SMB2HeaderResponse:
    protocol_id = FE 53 4D 42
    structure_size = 64
    credit_charge = 0
    status = (0) STATUS_SUCCESS
    command = (0) SMB2_NEGOTIATE
    credit_response = 1
    flags = (1) SMB2_FLAGS_SERVER_TO_REDIR
    next_command = 0
    message_id = 0
    reserved = 0
    tree_id = 0
    session_id = 0
    signature = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    data = 41 00 03 00 00 03 00 00 95 AB 1A 2F 2F 08 88 46 9D 2B 0B F5 CF 4A 01 3A 47 00 00 00 00 00 10 00 00 00 10 00 00 00 10 00 60 87 E7 05 8D 3D D6 01 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00

    Raw Hex:
        FE 53 4D 42 40 00 00 00
        00 00 00 00 00 00 01 00
        01 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00
        41 00 03 00 00 03 00 00
        95 AB 1A 2F 2F 08 88 46
        9D 2B 0B F5 CF 4A 01 3A
        47 00 00 00 00 00 10 00
        00 00 10 00 00 00 10 00
        60 87 E7 05 8D 3D D6 01
        00 00 00 00 00 00 00 00
        80 00 00 00 00 00 00 00
INFO:smbprotocol.connection:Negotiated dialect: (768) SMB_3_0_0
INFO:smbprotocol.connection:Connection require signing: True
INFO:smbprotocol.session:Initialising session with username: Azure\foo
DEBUG:smbprotocol.session:Decoding SPNEGO token containing supported auth mechanisms
ERROR:root:Fatal error during test:
Traceback (most recent call last):
  File "c:\fpo\foo-WorkpieceImporterPy\workpieceImporter\filesystemExporter.py", line 29, in <module>
    session.connect()
  File "C:\Program Files\Python37\lib\site-packages\smbprotocol\session.py", line 288, in connect
    asn1Spec=InitialContextToken())
  File "C:\Program Files\Python37\lib\site-packages\pyasn1\codec\ber\decoder.py", line 1338, in __call__
    'Short octet stream on tag decoding'
pyasn1.error.SubstrateUnderrunError: Short octet stream on tag decoding
INFO:smbprotocol.connection:Disconnecting transport connection
INFO:smbprotocol.transport:Disconnecting DirectTcp socket

RPC with Netlogon secure channel

A recent Netlogon vulnerability Domain Controller update (CVE-2020-1472) broke our SMB python interface code using your smbclient package.

The Linux smbclient command and the perl package Filesys::SmbClientParser based on that still works, and I was able to call a perl script as a temporary fix, but I have not found a way to get the python smbclient to connect again.

I updated to smbprotocol 1.4.0 and get the following error:
Error: Failed to authenticate with server: SpnegoError (6): A token had an invalid Message Integrity Check (MIC), Context: Invalid Message integrity Check (MIC) detected

Specifically, the update enforces secure RPC with Netlogon secure channel. I'm not sure how to turn this on via your smbclient or if it is supported.

Do you have any advice? Thanks!

Kerberos authentication fails when accessing a DFS share on Linux

Hi, I am encountering a gssapi.raw.exceptions.BadNameError when I try to access a DFS fileshare using Kerberos auth on Linux. I do not encounter the same error on Windows.

I suspect this is due to the DFS referral not quite working properly on Linux, perhaps it is generating the incorrect SPN? Possibly a similar issue to this: https://lists.samba.org/archive/samba-technical/2017-January/118057.html

I am still digging into the code to figure out what's going on here. I'll report back if I find any more clues.

>>> import smbclient as smb
>>> smb.listdir(r"\\fileserver\share$\dir")
['subdir1', 'subdir2']
>>> smb.listdir(r"\\company.com\dfs\share\dir")
Traceback (most recent call last):
  File "/opt/python37/lib/python3.7/site-packages/spnego/_context.py", line 88, in wrapper
    return func(*args, **kwargs)
  File "/opt/python37/lib/python3.7/site-packages/spnego/gss.py", line 435, in step
    out_token = self._context.step(in_token)
  File "<decorator-gen-15>", line 2, in step
  File "/opt/python37/lib/python3.7/site-packages/gssapi/_utils.py", line 155, in check_last_err
    return func(self, *args, **kwargs)
  File "<decorator-gen-5>", line 2, in step
  File "/opt/python37/lib/python3.7/site-packages/gssapi/_utils.py", line 128, in catch_and_return_token
    return func(self, *args, **kwargs)
  File "/opt/python37/lib/python3.7/site-packages/gssapi/sec_contexts.py", line 519, in step
    return self._initiator_step(token=token)
  File "/opt/python37/lib/python3.7/site-packages/gssapi/sec_contexts.py", line 540, in _initiator_step
    token)
  File "gssapi/raw/sec_contexts.pyx", line 245, in gssapi.raw.sec_contexts.init_sec_context
gssapi.raw.exceptions.BadNameError: Major (131072): An invalid name was supplied, Minor (100001): Success
 
The above exception was the direct cause of the following exception:
 
Traceback (most recent call last):
  File "/opt/python37/lib/python3.7/site-packages/smbprotocol/session.py", line 267, in connect
    out_token = context.step(in_token)
  File "/opt/python37/lib/python3.7/site-packages/spnego/negotiate.py", line 124, in step
    mech_token_out = self._step_spnego_token(in_token=mech_token_in)
  File "/opt/python37/lib/python3.7/site-packages/spnego/negotiate.py", line 220, in _step_spnego_token
    out_token = context.step(in_token=in_token)
  File "/opt/python37/lib/python3.7/site-packages/spnego/_context.py", line 91, in wrapper
    reraise(SpnegoError(base_error=native_err, context_msg=context))
  File "/opt/python37/lib/python3.7/site-packages/spnego/_compat.py", line 60, in reraise
    raise exc
spnego.exceptions.SpnegoError: SpnegoError (4294967295): Major (131072): An invalid name was supplied, Minor (100001): Success, Context: Processing security token
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/python37/lib/python3.7/site-packages/smbclient/_os.py", line 232, in listdir
    with SMBDirectoryIO(path, mode='r', share_access='r', **kwargs) as dir_fd:
  File "/opt/python37/lib/python3.7/site-packages/smbclient/_io.py", line 265, in __init__
    tree, fd_path = get_smb_tree(path, **kwargs)
  File "/opt/python37/lib/python3.7/site-packages/smbclient/_pool.py", line 287, in get_smb_tree
    connection_timeout=connection_timeout, connection_cache=connection_cache)
  File "/opt/python37/lib/python3.7/site-packages/smbclient/_pool.py", line 348, in register_session
    session.connect()
  File "/opt/python37/lib/python3.7/site-packages/smbprotocol/session.py", line 269, in connect
    raise SMBAuthenticationError("Failed to authenticate with server: %s" % str(err.message))
smbprotocol.exceptions.SMBAuthenticationError: Failed to authenticate with server: SpnegoError (4294967295): Major (131072): An invalid name was supplied, Minor (100001): Success, Context: Processing security token

AttributeError: __enter__

I would like to get the list of files present in a network share. Seeing how smbprotocol replicates the os and os.path functions, I've tried to modify a piece of code that uses os.scandir, so it uses smbclient.scandir instead.

The piece of code (which works when using os.scandir instead):

with smbclient.scandir(r"\\server\share\directory", username=network_username, password=network_password) as dir_contents:
	for f in dir_contents:
		fileList_array[f.name] = f.stat().st_mtime

Upon running, it throws the following error:

Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    with smbclient.scandir(r"\\server\share\directory", username=network_username, password=network_password) as dir_contents:
AttributeError: __enter__

Using Python 3.7.0

smbclient: Broken Pipe error when python kernel sits too long

Firstly, thanks for writing this module. I've been able to get it to connect to our windows shares to open and find files from a JupyterLab environment.

The issue I've having is that if I let my python kernel sit for a bit (>10 minutes or so), I will get a [Errno 32] Broken Pipe error when I try to use smbclient.open_file or smbclient.listdir. I tried to use the smbclient.reset_connection_cache() function to fix it but also got the broken pipe error. I was able to resolve this by restarting the python kernel. I'm guessing that my connection to the server is being disconnected, but I would expect that there could be a way to re-connect without restarting the kernel or throwing an error. Thoughts?

System Information:
Environment: JupyterHub (TLJH) /JupyterLab V1.1.3 running on an Ubuntu 18 server
Python: 3.6

Here are details of the error from the listdir command:

`---------------------------------------------------------------------------
BrokenPipeError Traceback (most recent call last)
in
----> 1 smbclient.listdir(r"\servername\removed")

/opt/tljh/user/lib/python3.6/site-packages/smbclient/_os.py in listdir(path, search_pattern, **kwargs)
218 :return: A list containing the names of the entries in the directory.
219 """
--> 220 with SMBDirectoryIO(path, mode='r', share_access='r', **kwargs) as dir_fd:
221 try:
222 raw_filenames = dir_fd.query_directory(search_pattern, FileInformationClass.FILE_NAMES_INFORMATION)

/opt/tljh/user/lib/python3.6/site-packages/smbclient/_io.py in enter(self)
292
293 def enter(self):
--> 294 self.open()
295 return self
296

/opt/tljh/user/lib/python3.6/site-packages/smbclient/_io.py in open(self, transaction)
338 create_disposition,
339 self._create_options,
--> 340 send=(transaction is None),
341 )
342 except SMBResponseException as exc:

/opt/tljh/user/lib/python3.6/site-packages/smbprotocol/open.py in create(self, impersonation_level, desired_access, file_attributes, share_access, create_disposition, create_options, create_contexts, oplock_level, send)
1208 request = self.connection.send(create,
1209 self.tree_connect.session.session_id,
-> 1210 self.tree_connect.tree_connect_id)
1211 return self._create_response(request)
1212

/opt/tljh/user/lib/python3.6/site-packages/smbprotocol/connection.py in send(self, message, sid, tid, credit_request, message_id, async_id)
964 """
965 return self._send([message], session_id=sid, tree_id=tid, message_id=message_id, credit_request=credit_request,
--> 966 async_id=async_id)[0]
967
968 def send_compound(self, messages, sid, tid, related=False):

/opt/tljh/user/lib/python3.6/site-packages/smbprotocol/connection.py in wrapped(self, *args, **kwargs)
761 def wrapped(self, *args, **kwargs):
762 self._check_worker_running()
--> 763 return func(self, *args, **kwargs)
764 return wrapped
765

/opt/tljh/user/lib/python3.6/site-packages/smbprotocol/connection.py in _send(self, messages, session_id, tree_id, message_id, credit_request, related, async_id)
1242 send_data = self._encrypt(send_data, session)
1243
-> 1244 self.transport.send(send_data)
1245 return requests
1246

/opt/tljh/user/lib/python3.6/site-packages/smbprotocol/transport.py in wrapped(self, *args, **kwargs)
65 self._connected = True
66
---> 67 func(self, *args, **kwargs)
68
69 return wrapped

/opt/tljh/user/lib/python3.6/site-packages/smbprotocol/transport.py in send(self, header)
106 data = tcp_packet.pack()
107 while data:
--> 108 sent = self._sock.send(data)
109 data = data[sent:]
110

BrokenPipeError: [Errno 32] Broken pipe`

Fallback to SMB1

As far as i understand only SMB2+ is supported?
Any chance for SMB1 support?
There are still devices (home network routers...) that only supports SMB1
Have tried a samba connection with my router to no avail, I guess it only supports SMB1 and I always get:

raise SMBConnectionClosed('SMB socket was closed, cannot send or receive any more data')

auth_protocol="kerberos" does not seem to work

By default, the module can successfully use Kerberos whenever a TGT is present -- I'm able to open files without specifying any username or password.

However, if I specifically request auth_protocol="kerberos", it's no longer able to connect -- I receive "Major (589824): Invalid token was supplied, Minor (100001): Success".

I'm testing against Windows Server 2019, and this happens immediately after receiving the Negotiate Protocol Response from the server.

Full backtrace:

Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/spnego/_context.py", line 88, in wrapper
    return func(*args, **kwargs)
  File "/usr/lib/python3.9/site-packages/spnego/gss.py", line 435, in step
    out_token = self._context.step(in_token)
  File "<decorator-gen-15>", line 2, in step
  File "/usr/lib/python3.9/site-packages/gssapi/_utils.py", line 155, in check_last_err
    return func(self, *args, **kwargs)
  File "<decorator-gen-5>", line 2, in step
  File "/usr/lib/python3.9/site-packages/gssapi/_utils.py", line 128, in catch_and_return_token
    return func(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/gssapi/sec_contexts.py", line 519, in step
    return self._initiator_step(token=token)
  File "/usr/lib/python3.9/site-packages/gssapi/sec_contexts.py", line 535, in _initiator_step
    res = rsec_contexts.init_sec_context(self._target_name, self._creds,
  File "gssapi/raw/sec_contexts.pyx", line 245, in gssapi.raw.sec_contexts.init_sec_context
gssapi.raw.exceptions.InvalidTokenError: Major (589824): Invalid token was supplied, Minor (100001): Success

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/smbprotocol/session.py", line 273, in connect
    out_token = context.step(in_token)
  File "/usr/lib/python3.9/site-packages/spnego/_context.py", line 91, in wrapper
    reraise(SpnegoError(base_error=native_err, context_msg=context))
  File "/usr/lib/python3.9/site-packages/spnego/_compat.py", line 60, in reraise
    raise exc
spnego.exceptions.InvalidTokenError: SpnegoError (9): Major (589824): Invalid token was supplied, Minor (100001): Success, Context: Processing security token

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/site-packages/smbclient/_os.py", line 362, in open_file
    raw_fd = file_class(path, mode=mode, share_access=share_access, desired_access=desired_access,
  File "/usr/lib/python3.9/site-packages/smbclient/_io.py", line 291, in __init__
    tree, fd_path = get_smb_tree(path, **kwargs)
  File "/usr/lib/python3.9/site-packages/smbclient/_pool.py", line 290, in get_smb_tree
    session = register_session(server, username=username, password=password, port=port, encrypt=encrypt,
  File "/usr/lib/python3.9/site-packages/smbclient/_pool.py", line 356, in register_session
    session.connect()
  File "/usr/lib/python3.9/site-packages/smbprotocol/session.py", line 275, in connect
    raise SMBAuthenticationError("Failed to authenticate with server: %s" % str(err.message))
smbprotocol.exceptions.SMBAuthenticationError: Failed to authenticate with server: SpnegoError (9): Major (589824): Invalid token was supplied, Minor (100001): Success, Context: Processing security token

trying to access smb share failed with 'STATUS_SERVER_UNAVAILABLE'

When I am trying to connect to NetApp share I get this message.
After doing more troubleshooting I succeed to access if join the linux machine to domain and using kerberos.
if using ntlm it seem like domain is always NULL

image

Traceback (most recent call last):
File "smb_test.py", line 3, in
smbclient.register_session('192.168.35.101', username='KOKO', password='Netapp1!')
File "/usr/local/lib/python3.6/site-packages/smbclient/_pool.py", line 348, in register_session
session.connect()
File "/usr/local/lib/python3.6/site-packages/smbprotocol/session.py", line 284, in connect
response = self.connection.receive(request)
File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 617, in wrapped
return func(self, *args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/smbprotocol/connection.py", line 929, in receive
raise SMBResponseException(response)
smbprotocol.exceptions.ServerUnavailable: Received unexpected status from the server: The file server is temporarily unavailable. (3221226598) STATUS_SERVER_UNAVAILABLE: 0xc0000466

do you have any idea how to overcome this issue ?

Samba connection fails with SMBResponseException

I am trying to connect from my Raspberry Pi A+ to the samba share of my home network router.
This simple script below works on my Windows 10 machine, however on my Raspberry Pi A+ it fails.
The only difference ist the Python 3 version.
The versions of the pip3 packages are identical.
Are there any more underlying dependencies?
Any ideas what to do or what else to check?

Python 3 script

import logging
import smbclient
logging.basicConfig(level=logging.INFO)
smbclient.register_session(server="fritz.box", username="samba", password="sambauser")

Python 3 packages on my Windows 10 machine

Python 3.8.8
smbprotocol==1.5.0
six==1.15.0
pyspnego==0.1.5
cryptography==3.4.7

Python 3 packages on my Raspberry Pi A+

Python 3.7.3
smbprotocol==1.5.0
six==1.15.0
pyspnego==0.1.5
cryptography==3.4.7

Logging Output (OK) on my Windows 10 machine

INFO:smbprotocol.connection:Initialising connection, guid: 6ee81800-7be7-4c7e-b83b-e53c10fb14aa, require_signing: True, server_name: fritz.box, port: 445
INFO:smbprotocol.connection:Setting up transport connection
INFO:smbprotocol.transport:Connecting to DirectTcp socket
INFO:smbprotocol.connection:Starting negotiation with SMB server
INFO:smbprotocol.connection:Negotiating with SMB2 protocol with highest client dialect of: SMB_3_1_1
INFO:smbprotocol.connection:Sending SMB2 Negotiate message
INFO:smbprotocol.connection:Receiving SMB2 Negotiate response
INFO:smbprotocol.connection:Negotiated dialect: (785) SMB_3_1_1
INFO:smbprotocol.connection:Connection require signing: True
INFO:smbprotocol.session:Initialising session with username: samba
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
INFO:smbprotocol.session:More processing is required for SMB2_SESSION_SETUP
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
INFO:smbprotocol.session:Setting session id to 1501
INFO:smbprotocol.session:Verifying the SMB Setup Session signature as auth is successful
INFO:smbprotocol.session:Session: samba - Logging off of SMB Session
INFO:smbprotocol.session:Session: samba - Sending Logoff message
INFO:smbprotocol.session:Session: samba - Receiving Logoff response
INFO:smbprotocol.connection:Disconnecting transport connection
INFO:smbprotocol.transport:Disconnecting DirectTcp socket

Logging Output (FAIL) on my Raspberry Pi A+

INFO:smbprotocol.connection:Initialising connection, guid: 3c9bed14-66d0-40e2-b8c5-1056d6de1ae4, require_signing: True, server_name: fritz.box, port: 445
INFO:smbprotocol.connection:Setting up transport connection
INFO:smbprotocol.transport:Connecting to DirectTcp socket
INFO:smbprotocol.connection:Starting negotiation with SMB server
INFO:smbprotocol.connection:Negotiating with SMB2 protocol with highest client dialect of: SMB_3_1_1
INFO:smbprotocol.connection:Sending SMB2 Negotiate message
INFO:smbprotocol.connection:Receiving SMB2 Negotiate response
INFO:smbprotocol.connection:Negotiated dialect: (785) SMB_3_1_1
INFO:smbprotocol.connection:Connection require signing: True
INFO:smbprotocol.session:Initialising session with username: samba
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
INFO:smbprotocol.session:More processing is required for SMB2_SESSION_SETUP
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
Traceback (most recent call last):
  File "ptest.py", line 6, in <module>
    smbclient.register_session(server="fritz.box", username="samba", password="sambauser")
  File "/usr/local/lib/python3.7/dist-packages/smbclient/_pool.py", line 360, in register_session
    session.connect()
  File "/usr/local/lib/python3.7/dist-packages/smbprotocol/session.py", line 292, in connect
    response = self.connection.receive(request)
  File "/usr/local/lib/python3.7/dist-packages/smbprotocol/connection.py", line 928, in receive
    raise SMBResponseException(response)
smbprotocol.exceptions.InvalidParameter: Received unexpected status from the server: An invalid parameter was passed to a service or function. (3221225485) STATUS_INVALID_PARAMETER: 0xc000000d
INFO:smbprotocol.connection:Disconnecting transport connection
INFO:smbprotocol.transport:Disconnecting DirectTcp socket

replace/rename support for DFS file path

Thanks a lot for so great work!
I try to use your library with DFS file shares, but get some trouble.
"open_file", "listdir", "walk" and "remove" work correctly, but "rename" and "replace" cause STATUS_ACCESS_DENIED exception.

>>>smbclient.ClientConfig(username='user', password=’xxxx')

Traceback (most recent call last):
  File "C:/APPS/auto_env38/smbprotocol/t1.py", line 8, in <module>
    smbclient.replace('\\\\my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\4.txt', '\\\\ my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\6.txt')
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_os.py", line 488, in replace
    _rename_information(src, dst, replace_if_exists=True, **kwargs)
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_os.py", line 1047, in _rename_information
    set_info(transaction, file_rename)
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_io.py", line 237, in __exit__
    self.commit()
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_io.py", line 277, in commit
    raise failures[0]
smbprotocol.exceptions.SMBOSError: [Error 0] [NtStatus 0xc0000022] Unknown NtStatus error returned 'STATUS_ACCESS_DENIED': '\\my-company.com\DFS\Report$\Used\Test\Used\FRB\4.txt'

If I open_file().read() first, and then replace, it cause another exception “smbprotocol.exceptions.SMBOSError: [Error 2] [NtStatus 0xc000003a] No such file or directory”

print(smbclient.open_file('\\\\my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\4.txt').read())
smbclient.replace('\\\\my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\4.txt', '\\\\my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\6.txt')

Hello world
Traceback (most recent call last):
  File "C:/APPS/auto_env38/smbprotocol/t1.py", line 8, in <module>
    smbclient.replace('\\\\my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\4.txt', '\\\\my-company.com\\DFS\\Report$\\Used\\Test\\Used\\FRB\\6.txt')
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_os.py", line 488, in replace
    _rename_information(src, dst, replace_if_exists=True, **kwargs)
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_os.py", line 1047, in _rename_information
    set_info(transaction, file_rename)
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_io.py", line 237, in __exit__
    self.commit()
  File "C:\APPS\auto_env38\smbprotocol\smbclient\_io.py", line 277, in commit
    raise failures[0]
smbprotocol.exceptions.SMBOSError: [Error 2] [NtStatus 0xc000003a] No such file or directory: '\\my-company.com\DFS\Report$\Used\Test\Used\FRB\4.txt'

If I execute replace with direct path (instead of using DFS), it work perfectly:
smbclient.replace('\\\\fs-p24\\Report$\\Used\\Test\\Used\\FRB\\5.txt', '\\\\fs-p24\\Report$\\Used\\Test\\Used\\FRB\\6.txt')

I understand that DFS support is experimental, but is replace through DFS not implemented, or just I made something wrong?

Recv_thread: Unpack requires a buffer of 4 bytes

Hi,
I've encountered a issue while using the library and I cannot figure it out why.
The error encountered is this:
image

I've also checked the code and I found this. Could you describe a little bit why this is happening?

image
Because of this warning the recv_thread is stopped.

The scenario is the following:
I have a grpc server that receives requests to download files from a share.
The download part is done via streaming of chunks of bytes.
The grpc server is configured to receive max 10 requests at a time and every requests creates his own thread, in which a smb connection is opened and a read -> stream process is starting.

The issue is visible when I try do download multiple large files, after a while the warning appear(notthing else) and all the requests for that share stops.
I've observed also that if I use only one grpc request, I didn't encountered the issue.

Thanks

SMB2_CREATE_REQUEST_LEASE context is not handled properly in SMB2 reply

CreateContextName.SMB2_CREATE_REQUEST_LEASE_V2:

Please note that SMB2_CREATE_REQUEST_LEASE has exactly the same value as SMB2_CREATE_REQUEST_LEASE_V2 so you cannot use context name only as the unique key in CreateContextName.get_response_structure() . Since duplicated keys are still used to match lease v1 and lease v2, python always return lease_v2 response data structure, so when we have lease_v1 in Create Response we fail on unpacking the structure because lease_v2 is longer than lease_v1. See stack-trace of this problem below.

To handle this corner-case properly I propose to follow suggestion by Microsoft.
See [MS-SMB2] 2.2.14.2 SMB2_CREATE_CONTEXT Response Values:
SMB2_CREATE_RESPONSE_LEASE_V2 : This context value is the same as the SMB2_CREATE_RESPONSE_LEASE value; the client differentiates these responses based on the value of the DataLength field.

So I propose to pass context length ('buffer_data' length) to CreateContextName.get_response_structure() as the second parameter and if context name is SMB2_CREATE_REQUEST_LEASE then we should check also 'buffer_data' length to return proper response context structure (either lease V1 or V2).

Stack trace:

  File "test.py", line 394, in _open_file_with_lease
    file = self._open_file(file_name, desired_access=access_mask, create_contexts=ctx)
  File "test.py", line 298, in _open_file
    create_contexts_response = file.create(impersonation_level, desired_access, file_attributes, share_access,
    create_disposition, create_options, create_contexts, send)
  File "lib/python3.6/site-packages/smbprotocol/open.py", line 1012, in create
    return self._create_response(request)
  File "lib/python3.6/site-packages/smbprotocol/open.py", line 1043, in _create_response
    create_contexts_response.append(context.get_context_data())
  File "lib/python3.6/site-packages/smbprotocol/create_contexts.py", line 221, in get_context_data
    structure.unpack(self['buffer_data'].get_value())
  File "lib/python3.6/site-packages/smbprotocol/structure.py", line 118, in unpack
    data = field.unpack(data)
  File "lib/python3.6/site-packages/smbprotocol/structure.py", line 212, in unpack
    self.set_value(data[0:size])
  File "lib/python3.6/site-packages/smbprotocol/structure.py", line 199, in set_value
    parsed_value = self._parse_value(value)
  File "lib/python3.6/site-packages/smbprotocol/structure.py", line 351, in _parse_value
    int_value = struct.unpack(struct_string, value)[0]
struct.error: unpack requires a buffer of 2 bytes

Import Error: cannot import name inquire_sec_context_by_oid

Hi Team,

I am trying to run pypsexec in kerberos mode. I have installed gssapi library using pip, but when i do the following import

from gssapi.raw import inquire_sec_context_by_oid

it is failing.

Due to this HAVE_GSSAPI flag in session.py is not set, and kerberos mode is not working.

Any insights on workaround will be helpful.

Unhelpful exception on locked out account / incorrect password

smbprotocol ==1.4.0

When attempting to register_session, if the user account used to authenticate is locked out or an incorrect password is specified, the following exception is thrown:

smbclient.register_session(server, username=username, password=password)
  File "lib\site-packages\smbclient\_pool.py", line 359, in register_session
    session.connect()
  File "lib\site-packages\smbprotocol\session.py", line 292, in connect
    response = self.connection.receive(request)
  File "lib\site-packages\smbprotocol\connection.py", line 617, in wrapped
    return func(self, *args, **kwargs)
  File "lib\site-packages\smbprotocol\connection.py", line 931, in receive
    raise SMBResponseException(response)
smbprotocol.exceptions.SMBResponseException: Received unexpected status from the server: Unknown error. (3221225578) UNKNOWN_ENUM: 0xc000006a

I'm not sure if there's something more meaningful that can be done with this, but we've encountered it both when an incorrect password was attempted, and when the correct password was attempted but the user was locked out.

We're catching similar errors for now and logging a hint that there may be an account issue. Let me know if I can provide any additional info.

Getting issue while disconnecting session

I am using below code to authenticate and validate the given credentials for a smb share. For which I am calling connect and if response is received then I am closing the connection. Below is my code:

Code:

import smbclient
connection = smbclient.register_session(ip, username, pwd)
Print("Credentials validation for ip %s is Successful", ip)
connection.disconnect(False)

Error:

Server message signature could not be verified: 00000000000000000000000000000000 != 4665675f0932baa153f563aefe36e50b

Unable to authenticate from python smbclient while ok with shell tool smbclient

Hello Jordan and thanks for this great work.

I'm trying to get some SMB stuff (listing files, checking size...) done from a Linux (Debian 10) server running a python 3.7 service.

While I can get this done with the command line tool smbclient through subprocess calls, I would like to do it natively from python with your module.

But I get a STATUS_LOGON_FAILURE and after googling for a while, I can't figure out why since my credentials are OK and the linux client succeeds.

Here is a sample code:

import os
import smbclient
SMB_SRV = os.getenv('SMB_SERVER')
SMB_PASS = os.getenv('SMB_PASSWORD')
SMB_USER = os.getenv('SMB_USER') # format is 'DOMAIN/user_id'
sess = smbclient.register_session(SMB_SRV, username=SMB_USER, password=SMB_PASS, connection_timeout=10 )

The exception raised is:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/smbclient/_pool.py", line 113, in register_session
    session.connect()
  File "/usr/local/lib/python3.7/site-packages/smbprotocol/session.py", line 319, in connect
    "%s" % str(errors))
smbprotocol.exceptions.SMBAuthenticationError: Failed to authenticate with server: {'NEGOEX (1.3.6.1.4.1.311.2.2.30)': 'Mech Type 1.3.6.1.4.1.311.2.2.30 is not yet supported',
 'KRB5 (1.2.840.113554.1.2.2)': 'Failed to acquire GSSAPI credential with password: Major (131072): An invalid name was supplied, Minor (2529639136): Configuration file does not specify default realm',
 'KRB5_U2U (1.2.840.113554.1.2.2.3)': 'Mech Type 1.2.840.113554.1.2.2.3 is not yet supported',
 'NTLMSSP (1.3.6.1.4.1.311.2.2.10)': 'Received unexpected status from the server: (3221225581) STATUS_LOGON_FAILURE: 0xc000006d'}

Debug log says:

Initialising session with username: DOMAIN/user_id
Decoding SPNEGO token containing supported auth mechanisms
Both MS_KRB5 and KRB5 received in the initial SPNGEO token, removing MS_KRB5 to avoid duplication of work
Attempting auth with mech NEGOEX (1.3.6.1.4.1.311.2.2.30)
Failed auth for mech NEGOEX (1.3.6.1.4.1.311.2.2.30): Mech Type 1.3.6.1.4.1.311.2.2.30 is not yet supported
Attempting auth with mech KRB5 (1.2.840.113554.1.2.2)
Setting up GSSAPI Security Context for Kerberos auth
GSSAPI: Acquiring credentials handle
GSSAPI: Acquiring credentials handle for user DOMAIN/user_id with password
Failed auth for mech KRB5 (1.2.840.113554.1.2.2): Failed to acquire GSSAPI credential with password: Major (131072): An invalid name was supplied, Minor (2529639136): Configuration file does not specify default realm
Attempting auth with mech KRB5_U2U (1.2.840.113554.1.2.2.3)
Failed auth for mech KRB5_U2U (1.2.840.113554.1.2.2.3): Mech Type 1.2.840.113554.1.2.2.3 is not yet supported
Attempting auth with mech NTLMSSP (1.3.6.1.4.1.311.2.2.10)
Setting up NTLM Security Context for user DOMAIN/user_id
NTLM: Generating Negotiate message
NTLM: Negotiate message: 4e544c4d5353500001000000329088e2000000002800000000000000280000000601b11d0000000f
Sending SMB2_SESSION_SETUP request message
Failed auth for mech NTLMSSP (1.3.6.1.4.1.311.2.2.10): [Errno 32] Broken pipe
Disconnecting transport connection
Disconnecting DirectTcp socket

Inspecting the session object, I do know dialect 3.1.1 is used which is fine because target server is Windows 2016.
The command line which is working is:

smbclient "//$SMB_SERVER/$SMB_SHARE" -d -k -U "$SMB_USER%$SMB_PASSWORD" -m SMB3 -c 'dir'

Any advise would be appreciated :)
Regards,
Fred.

Unable to authenticate to Win box because none of the negotiation mechanisms is supported

In attempting to connect to a remote Windows system, I get the following messages during the negotiation process:

smbprotocol.session | Failed auth for mech NEGOEX (1.3.6.1.4.1.311.2.2.30): Mech Type 1.3.6.1.4.1.311.2.2.30 is not yet supported
smbprotocol.session | Failed auth for mech KRB5 (1.2.840.113554.1.2.2): Mech Type 1.2.840.113554.1.2.2 is not yet supported
smbprotocol.session | Failed auth for mech KRB5_U2U (1.2.840.113554.1.2.2.3): Mech Type 1.2.840.113554.1.2.2.3 is not yet supported
smbprotocol.session | Failed auth for mech NTLMSSP (1.3.6.1.4.1.311.2.2.10): [WinError 10054] An existing connection was forcibly closed by the remote host

Bottom-line, I expect none of the authentication protocols supported by the remote system are supported by smbprotocol.

Please advise,

Peter

Any way to check for or handle connection errors while manipulating files?

I have a scenario where i am writing files to a remote SMB share, however I would like to handle a case where the file writing stops and exception is raised when the connection between the two machines are interrupted for example. Currently the program just freezes and no exception is raised when this happens. I have also tried to execute the writing of file to SMB share in a separate thread and call that thread with a timeout but that doesn't seem to work either.

Is there anyway to handle this issue?

I am connecting from a windows client to a linux server over local area network.

import time
import smbclient
import threading
import _thread

class timeout():


    def __init__(self, time):
        self.time = time
        self.exit = False

    def __enter__(self):
        threading.Thread(target=self.callme).start()

    def callme(self):
        time.sleep(self.time)
        if self.exit == False:
            _thread.interrupt_main()  

    def __exit__(self, a, b, c):
        self.exit = True


with timeout(20):
    try:
        while True:
            time.sleep(0.3)
            try:
                smbclient.stat(
                    somefilehere)
            except Exception as e:
                print(e)
            print("done inner")
    except KeyboardInterrupt:
        print("done outer")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.