Open hackoflpf opened 2 years ago
Technically it should be possible but I remember trying to get it working when I first wrote the code and it was difficult. You can try setting the username to Guest
with an empty string as the password but I doubt that’s going to work. Using a Guest or Anonymous logon loses a lot of the security benefits that SMB had introduced like message signatures and encryption. You are better off adding an account that can you and authenticate with rather than an anonymous user in general.
Does your server support anonymous/guest session?
I remember that guest accounts are supported by Windows Desktop, but guest accounts are disabled by default with Windows Server.
See this docs - https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj852219%28v=ws.11%29
As commented by Jordan, you will need to use Guest
as username.
You will need to set password to something ... and that value is ignored.
From my code
# Some custom logicc
anonymous = True
username = 'Guest'
# Anonymous needs to have a password that is later ignored.
# Otherwise pyspnego will try to load it from a file.
password = 'ignored'
Setting to None
should be avoided as username and password API should require these values to have a text type.
And you can see from the error that it fails as it tries to load the password from a file.
Thanks @adiroiban that about sums up what I came across before, the Guest
could be used with any value for the password
as it was ignored on the server. I believe Anonymous
accounts are slightly different to Guest
and needs extra work in pyspnego
to use.
Of course,i test this on ubuntu with samba 4.15.0,i can use the default samba tool smbclient to login without password,but if i set the password with None value,smbprotocol will raise exceptions.This is my smb.conf [check] path = /home/test/ browseable = yes public = yes available = yes oplocks = yes follow symlinks = yes map archive = no guest ok = yes writable = yes Maybe the Spnego library doesn't support this operation,i haven't check the code,but i can use samba python library to login without password,only to set the username is "" and password is None,it works well.
Pyspnego certainly doesn’t support anonymous users as you’ve seen which leans smbprotocol also does not support anonymous logons. It should work with Guest logins which has a username of Guest
and the password is set to any string value. They are slightly different but could still work in your scenario if your samba server is configured to allow it.
I have the same problem. Set up a server with:
mkdir /tmp/smbshare
echo bar > /tmp/smbshare/foo
sudo apt install samba
cat <<EOF | sudo tee /etc/samba/smb.conf
[test]
path = /tmp/smbshare
browsable = yes
guest ok = yes
read only = yes
create mask = 0755
EOF
sudo systemctl restart smbd nmbd
Connect to it anonymously works with smbclient
by not specifying any user and specifying any password:
sudo apt install smbclient
smbclient --password=ignored --port 445 -c ls //127.0.0.1/test
I fail to achieve the same goal with smbprotocol. I tried:
import smbclient
smbclient.register_session(server="127.0.0.1")'
# spnego.exceptions.BadMechanismError: SpnegoError (1): SpnegoError (16): Operation not supported or available,
# Context: No username or password was specified and the credential cache did not exist or contained no credentials,
# Context: Unable to negotiate common mechanism
smbclient.register_session(server="127.0.0.1", username="", password="")
# Same as above
smbclient.register_session(server="127.0.0.1", username="Guest", password="ignored")
# smbprotocol.exceptions.LogonFailure: Received unexpected status from the server:
# The attempted logon is invalid. This is either due to a bad username or authentication information.
# (3221225581) STATUS_LOGON_FAILURE: 0xc000006d
Hi Max,
Thanks for the report.
As far as I know, the SMB protocol has no "native" support for anonymous accounts.
In Windows, we have "guest" account
Windows documentation is here:
smbclient.register_session(server="127.0.0.1", username="Guest", password="ignored")
# smbprotocol.exceptions.LogonFailure: Received unexpected status from the server:
# The attempted logon is invalid. This is either due to a bad username or authentication information.
# (3221225581) STATUS_LOGON_FAILURE: 0xc000006d
Inside Samba documentation, we also have references to the "guest" account
See for example https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html#MAPTOGUEST
Not sure if you have setup the guest accout inside Samba..
smbclient.register_session(server="127.0.0.1", username="", password="")
# Same as above
smbclient.register_session(server="127.0.0.1", username="", password="")
I think that the issue here is with pyspnego
which handles an empty string, the same was as None
I don't know how this can be fixed without breaking backward compatibility
So, to fix the "anonymous" login, I think that we need an explicit guest/anonymous request.
It can look something like this:
smbclient.register_session(server="127.0.0.1", username=pyspnego.GUEST)
Now, the pyspnego.GUEST
constant can be aliased in the smbprotocol
API so that you don't need to explicity import pyspnego
... but we need to tell pyspnego
that we want to go via the "guest credentials" use case , and not the normal "userame + password" credentials
Anonymous user support is not present at the pyspnego
library does not support anonymous authentication. It's been a while since I last looked at the guest support but AFAIK guest logons are used when you attempt to log on with a user that is not valid. For Samba the times when it will map to a guest logon are configured by https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html#MAPTOGUEST with the default being never map to a guest user. You would have to explicitly configure that value to something else like Bad User
and then specify a user that doesn't exist with any random password string. You cannot use an empty string for either as that means use the implicit user identity which may or may not exist depending on your environment.
I can confirm the following Samba config works
[global]
map to guest = Bad User
[test]
path = /tmp/smbshare
browsable = yes
guest ok = yes
read only = yes
create mask = 0755
I was able to test this out with the following Python code
import smbclient
smbclient.ClientConfig(require_secure_negotiate=False)
smbclient.register_session(
'localhost',
username='Guest',
password='ignored',
port=8445,
require_signing=False,
)
res = smbclient.listdir(
r'\\localhost\test',
port=8445,
)
print(res)
The smbclient.ClientConfig(require_secure_negotiate=False)
is needed to disable the post tree connect verification that is done to verify the protocol hasn't been downgraded. The require_signing=False
is then needed when registering the session to also allow that session to not require signing. The signing bits all need to be disabled for guest and anonymous accounts as there is no secret session key required by signing.
All of this is unfortunately sub-optimal but considering it's simpler to just create a dummy account and still achieve the same result of guest/anon accounts there is not much of a pressing need to do this. I am hoping to revamp the whole config/kwargs setup to be more user friendly as the current implementation can be confusing to use.
I can confirm the following Samba config works
Works for me, too.
I can't use smbprotocol to login as a guest user,if i set username and password is None,the program behave like belows, INFO:smbprotocol.connection:Initialising connection, guid: 0f41207e-d29d-4543-a60c-6dcad6339edf, require_signing: False, server_name: 127.0.0.1, port: 445 False 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_0_0 INFO:smbprotocol.connection:Sending SMB2 Negotiate message INFO:smbprotocol.connection:Receiving SMB2 Negotiate response INFO:smbprotocol.connection:Negotiated dialect: (768) SMB_3_0_0 INFO:smbprotocol.connection:Connection require signing: False INFO:smbprotocol.session:Initialising session with username: admins INFO:smbprotocol.connection:Disconnecting transport connection INFO:smbprotocol.transport:Disconnecting DirectTcp socket Traceback (most recent call last): File "/home/admins/.local/lib/python3.8/site-packages/smbprotocol/session.py", line 266, in connect context = spnego.client(self.username, self.password, service='cifs', hostname=self.connection.server_name, File "/home/admins/.local/lib/python3.8/site-packages/spnego/auth.py", line 202, in client return _new_context( File "/home/admins/.local/lib/python3.8/site-packages/spnego/auth.py", line 117, in _new_context return proxy( File "/home/admins/.local/lib/python3.8/site-packages/spnego/_ntlm.py", line 287, in init self._credential = _NTLMCredential(next(c for c in credentials if "ntlm" in c.supported_protocols)) File "/home/admins/.local/lib/python3.8/site-packages/spnego/_ntlm.py", line 227, in init self.domain, self.username, self.lm_hash, self.nt_hash = _get_credential(self._store, domain, username) File "/home/admins/.local/lib/python3.8/site-packages/spnego/_ntlm.py", line 137, in _get_credential raise OperationNotAvailableError(context_msg="Retrieving NTLM store without NTLM_USER_FILE set to a filepath") spnego.exceptions.OperationNotAvailableError: SpnegoError (16): Operation not supported or available, Context: Retrieving NTLM store without NTLM_USER_FILE set to a filepath
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "file-management.py", line 30, in
session.connect()
File "/home/admins/.local/lib/python3.8/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 (16): Operation not supported or available, Context: Retrieving NTLM store without NTLM_USER_FILE set to a filepath
my code is