• Stars
    star
    293
  • Rank 141,748 (Top 3 %)
  • Language
    Python
  • License
    MIT License
  • Created about 7 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Python SMBv2 and v3 Client

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("python-gssapi extension is not available: %s" % str(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;

pip install -r requirements-dev.txt

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

From there to run the basic tests run;

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

# or with tox 2.7, 2.7, 3.4, 3.5, and 3.6
tox

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...

More Repositories

1

pypsrp

PowerShell Remoting Protocol for Python
Python
327
star
2

ansible-windows

Scripts that are useful for using Ansible with Windows - not affiliated with Ansible in any way
PowerShell
196
star
3

packer-windoze

Packer templates to create Windows vagrant box images
PowerShell
165
star
4

pypsexec

Remote Windows execution like PsExec on Python
Python
113
star
5

PSOpenAD

Cross-platform PowerShell module alternative to Microsoft's Active Directory module
C#
101
star
6

PSDetour

Windows Detour Hooking in PowerShell
C#
71
star
7

dpapi-ng

Python DPAPI NG Decryptor for non-Windows Platforms
Python
55
star
8

PowerShell-AnsibleVault

Ansible Vault cmdlets for use in PowerShell
PowerShell
52
star
9

pyspnego

Python SPNEGO authentication library
Python
52
star
10

ntlm-auth

Calculates NTLM Authentication codes
Python
51
star
11

PSToml

PowerShell TOML Parser and Writer
PowerShell
44
star
12

PSPrivilege

Manage process privileges and adjust Windows rights/privileges in PowerShell
C#
39
star
13

LocalKdc

Info on how to use Kerberos KDC on a non-domain joined host
C#
37
star
14

ProcessEx

Exposes the Windows Process creation Win32 functions in PowerShell
C#
33
star
15

PowerShell-Yayaml

A YAML parser and writer that uses an Assembly Load Context on PowerShell 7+
PowerShell
30
star
16

PowerShell-OpenAuthenticode

Cross platform PowerShell implementation of Authenticode signing and verification
C#
28
star
17

ansible-role-win_openssh

Ansible Role to install Win32-OpenSSH on Windows - https://github.com/PowerShell/Win32-OpenSSH
PowerShell
28
star
18

ansibug

Debug Adapter Protocol for Ansible
Python
27
star
19

PSEtw

PowerShell ETW consumer module
C#
27
star
20

exchange-test-environment

A Vagrantfile and Ansible playbook that can be used to setup test environment with an Exchange server host
PowerShell
26
star
21

requests-credssp

An authentication handler for using CredSSP with Python Requests.
Python
21
star
22

PowerShell-ctypes

PowerShell module for ctypes/PInvoke calls
PowerShell
21
star
23

PowerShell-ALC

Example ALC structures to use with in a PowerShell module
PowerShell
20
star
24

SecretManagement.DpapiNG

PowerShell SecretManagement module for DPAPI-NG
PowerShell
18
star
25

pykrb5

Python krb5 API interface
C
16
star
26

PSWSMan

C#
16
star
27

winrm-cert-auth

Details around how to setup WinRM Certificate Authentication for use in Ansible
PowerShell
16
star
28

PSAccessToken

PowerShell Module that can query, edit, and create Windows Access Tokens
PowerShell
13
star
29

ansible-role-win_laps

Ansible Role to install LAPS on Windows - https://technet.microsoft.com/en-us/mt227395.aspx
PowerShell
12
star
30

PSDetour-Hooks

Auditing Hooks for https://github.com/jborean93/PSDetour
PowerShell
12
star
31

RemoteForge

PowerShell Custom PSRemoting Transport Manager
C#
11
star
32

PSGhost

PowerShell Host Methods using Spectre.Console
PowerShell
9
star
33

ansible-win-demos

Collection of demo scripts for Ansible and Windows
PowerShell
8
star
34

psrpcore

Core Library for the PowerShell Remoting Protocol
Python
8
star
35

PSCSharpInvoker

PowerShell module that can invoke C# code without polluting the Type namespace
PowerShell
8
star
36

PSSPI

PowerShell Module for SSPI
C#
7
star
37

PWSExecConn

PowerShell
7
star
38

ansible-role-win_chocolatey_server

Ansible Role to install Chocolatey Server on Windows - https://chocolatey.org/packages/chocolatey.server
PowerShell
7
star
39

sansldap

Python Sans I/O LDAP Library
Python
6
star
40

AdvReg

PowerShell Module for Advanced Registry Functionality
C#
4
star
41

vscode-ansibug

VSCode Extension for Debugging Ansible Playbooks
TypeScript
4
star
42

krb5-fast

Testing of Kerberos FAST on Linux
PowerShell
3
star
43

wsus-environment

Code to set up a WSUS environment
3
star
44

PSIntegrity

Manage the Windows integrity label policies on an object through PowerShell
PowerShell
3
star
45

SudoForge

PowerShell Remote Forge for Sudo
PowerShell
3
star
46

PInvokeHelper

Helper functions for PInvoking in PowerShell
PowerShell
3
star
47

TestBin

Test binary module for PowerShell
PowerShell
2
star
48

ansible-lookup-laps_password

Repo that contains tests for the laps_password Ansible lookup plugin
2
star
49

ansible-jborean93.vscode

POC for VSCode Ansible Debugger
Python
2
star
50

travis-ci-win-ansible

Testing repo for Travis-CI on Windows and Ansible
2
star
51

pyxca

Python Library for MS-XCA Xpress Compression Algorithm
C
2
star
52

brispug-repo

A repo for random things to do with the Brisbane PowerShell User Group
PowerShell
2
star
53

wsman-environment

Code to set up a WSMan environment
PowerShell
2
star
54

python-hyperv

Python API for Hyper-V
2
star
55

sspilib

Python bindings for Windows SSPI
Python
2
star
56

SSHForge

Hyper-V implementaiton for PowerShell RemoteForge
PowerShell
2
star
57

PowerShell-GistHub

GitHub Gist Provider for PowerShell
C#
1
star
58

CoverletTesting

Testing for Code Coverage in CI
PowerShell
1
star
59

PSConfEU-2024

Demos for PSConfEU talk
PowerShell
1
star
60

ProcessVirtualChannel

POC for a Process spawning RDP virtual channel
C#
1
star
61

ansible-content

Repo storing blog posts about Ansible
1
star