Windows 10 and Server 2016 clients block access to (Samba) shares with public guest account: Technical analysis and workaround for event 31017

Written by - 4 comments

Published on - Listed in Windows Linux Security Samba


Everyone knows how easy it is to access public network shares from a Windows client. Simply enter \\SERVERNAME (or \\SERVER.IP.ADDRESS) in the Windows Explorer and a list of shares appears. Or... they should.

But something has changed in Windows 10 and Windows Server 2016 clients. Suddenly public shares using a guest account will not show up anymore. In Windows Explorer the following error message shows up:

Windows Explorer Samba Mount Error

Note: The screenshot is in German. Translated to English:

Windows cannot access "\\twwfs011". Check the spelling of the name and try again.

What happened?!

Accessing a public share with a guest access means no authentication. So everyone with network access to the share is able to access data from it. Depending on the share's configuration even write to it. This is of course handy as a user doesn't have to enter some credentials he already had forgotten a while ago. But convenience always breaks security. A couple of years ago, an exploit of the SMB1 protocol, called EternalBlue, was released. This vulnerability opened the door to the probably best known Ransomeware: WannaCry. It infected a computer, searched for SMB1 and open (public) network shares without authentication and placed or even installed itself on the server hosting the network share, too.

Microsoft decided to close these doors by disabling SMB1 (CIFS) file sharing support and by disabling the guest access to network shares.

Tell me about the Samba config

Samba was set up running as a standalone server and allowing guests to read and write into public shares. On some servers these shares are mounted, others (especially Windows clients) mount the shares on demand. All shares use the same local Unix user (set by force user).

#======================= Global Settings =======================

[global]

## Browsing/Identification ###

   workgroup = DOMAIN
   server string = %h server (Samba, Ubuntu)
   dns proxy = no

#### Debugging/Accounting ####

   log file = /var/log/samba/log.%m
   max log size = 1000
   panic action = /usr/share/samba/panic-action %d

####### Authentication #######

   server role = standalone server
   passdb backend = tdbsam
   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
   pam password change = yes

############ Misc ############

   usershare allow guests = yes
   guest ok = yes
   guest account = mylocaluser
   map to guest = bad user

#========================= Share Definitions ==============================

   [archiv]
   comment = Application Archive
   path = /data/archive
   public = yes
   writable = yes
   printable = no
   force user = mylocaluser
   force group = users

The following settings are important in our case:

  • guest account = mylocaluser: Tells Samba which local Unix user to use as guest. Or differently explained: When a user connects to the share using the public guest account, which Unix user permissions should this user get?
  • map to guest = bad user: Tells Samba under which circumstances a client should be treated as a guest. The "bad user" value means that all users which could not be identified (in our case anyone but "mylocaluser") will get the guest accont.
  • public = yes in the share "archiv": Same setting as "guest ok = yes", tells Samba that this share is public.
  • writable = yes in the share "archiv": Tells Samba that this share is writable.
  • force user = mylocaluser in the share "archiv": Tells Samba to force the Unix privileges of the local user "mylocaluser" for this share. Every connected client will therefore navigate as "mylocaluser" inside the share. Newly created files or directories will therefore also be owned by "mylocaluser".

Note there is no external password authentication happening. 

Analyzing access from Windows 10 client

As mentioned above, the error message shown in Windows Explorer is not helpful at all; it suggests that the server could not be found. However a closer look into the Event Log of the SMBClient Windows application reveals more. An event with ID 31017 was logged and contained the following description:

This event indicates that the server tried to log on the user as an unauthenticated guest but was denied by the client. Guest logons do not support standard security features such as signing and encryption. Therefore, guest logons are vulnerable to man-in-the-middle attacks that can expose sensitive data on the network. Windows disables "insecure" (nonsecure) guest logons by default. Microsoft recommends that you do not enable insecure guest logons.

OK this event now gives us relevant information but technically we're non the wiser. Let's dig into the Samba logs.

Access seeing with Samba debug logging

To be able to see the communication between the Windows 10 client and our public Samba share, debug logging was enabled. Samba allows to define per client logging, so I prepared a config file with debug 3 (that's sufficient to log authentication problems):

root@sambaserver:~# cat /etc/samba/smb.conf.client-debug
[global]
# no log file size limitation
max log size = 0
# specific log file name
log file = /var/log/samba/log.%I
# set the debug level
log level = 3
# add the pid to the log
debug pid = yes
# add the uid to the log
debug uid = yes
# add the debug class to the log
debug class = yes
# add microsecond resolution to timestamp
debug hires timestamp = yes

Using this prepared config, a simple symlink with the client's IP address can be created. For example if you connect to the SMB share from a client with IP 172.30.123.195:

root@sambaserver:~# ln -s /etc/samba/smb.conf.client-debug /etc/samba/smb.conf.client-172.30.123.195

Now don't forget to tell Samba about the external config file(s) for client specific logging. In the [global] section (= before the definition of shares) of /etc/samba/smb.conf add:

include = /etc/samba/smb.conf.client-%I

Trying the same share access again from our Windows 10 client, Samba spits out a log of lines:

root@sambaserver:~# tail -f /var/log/samba/log.172.30.123.195
[...]
[2019/07/18 13:44:58.071184,  3, pid=32345, effective(0, 0), real(0, 0)] ../source3/param/loadparm.c:1609(lp_add_ipc)
  adding IPC service
[2019/07/18 13:44:58.071208,  3, pid=32345, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:189(auth_check_ntlm_password)
  check_ntlm_password:  Checking password for unmapped user [DOMAIN]\[claudiokuenzler]@[WM2674] with the new password interface
[2019/07/18 13:44:58.071230,  3, pid=32345, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:192(auth_check_ntlm_password)
  check_ntlm_password:  mapped user is: [DOMAIN]\[claudiokuenzler]@[WM2674]
[2019/07/18 13:44:58.071277,  3, pid=32345, effective(0, 0), real(0, 0), class=auth] ../source3/auth/check_samsec.c:399(check_sam_security)
  check_sam_security: Couldn't find user 'claudiokuenzler' in passdb.
[2019/07/18 13:44:58.071301,  2, pid=32345, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:332(auth_check_ntlm_password)
  check_ntlm_password:  Authentication for user [claudiokuenzler] -> [claudiokuenzler] FAILED with error NT_STATUS_NO_SUCH_USER, authoritative=1
[2019/07/18 13:44:58.071351,  2, pid=32345, effective(0, 0), real(0, 0)] ../auth/auth_log.c:760(log_authentication_event_human_readable)
  Auth: [SMB2,(null)] user [DOMAIN]\[claudiokuenzler] at [Thu, 18 Jul 2019 13:44:58.071341 CEST] with [NTLMv2] status [NT_STATUS_NO_SUCH_USER] workstation [WM2674] remote host [ipv4:172.30.123.195:65168] mapped to [DOMAIN]\[claudiokuenzler]. local host [ipv4:10.130.136.38:445]
[2019/07/18 13:44:58.071481,  2, pid=32345, effective(0, 0), real(0, 0)] ../auth/auth_log.c:220(log_json)
  JSON Authentication: {"timestamp": "2019-07-18T13:44:58.071393+0200", "type": "Authentication", "Authentication": {"version": {"major": 1, "minor": 0}, "status": "NT_STATUS_NO_SUCH_USER", "localAddress": "ipv4:10.130.136.38:445", "remoteAddress": "ipv4:172.30.123.195:65168", "serviceDescription": "SMB2", "authDescription": null, "clientDomain": "DOMAIN", "clientAccount": "claudiokuenzler", "workstation": "WM2674", "becameAccount": null, "becameDomain": null, "becameSid": "(NULL SID)", "mappedAccount": "claudiokuenzler", "mappedDomain": "DOMAIN", "netlogonComputer": null, "netlogonTrustAccount": null, "netlogonNegotiateFlags": "0x00000000", "netlogonSecureChannelType": 0, "netlogonTrustAccountSid": "(NULL SID)", "passwordType": "NTLMv2"}}
[2019/07/18 13:44:58.071506,  3, pid=32345, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth_util.c:1626(do_map_to_guest_server_info)
  No such user claudiokuenzler [DOMAIN] - using guest account
[2019/07/18 13:44:58.079573,  3, pid=32345, effective(0, 0), real(0, 0)] ../source3/smbd/server_exit.c:244(exit_server_common)
  Server exit (NT_STATUS_CONNECTION_RESET)

From this information we can see that:

  • Windows client submitted the logged in Windows user (claudiokuenzler), the logon domain (DOMAIN) and the client's machine (WM2674) to Samba
  • Samba was unable to find the local user claudiokuenzler or DOMAIN\claudiokuenzler
  • Because this Samba server has map to guest = bad user configured, Samba now tells the client to "using guest account"
  • This is the moment when Windows chokes and leaves the party

How did it look with a Windows 7 client?

In Windows 7, guest accounts are still allowed. By checking the debug log of a Windows 7 client, we can spot the difference at the end:

[2019/07/22 13:47:13.209774,  3, pid=13389, effective(0, 0), real(0, 0)] ../source3/param/loadparm.c:1609(lp_add_ipc)
  adding IPC service
[2019/07/22 13:47:13.209807,  3, pid=13389, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:189(auth_check_ntlm_password)
  check_ntlm_password:  Checking password for unmapped user [DOMAIN]\[claudiokuenzler]@[WM2856] with the new password interface
[2019/07/22 13:47:13.209828,  3, pid=13389, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:192(auth_check_ntlm_password)
  check_ntlm_password:  mapped user is: [DOMAIN]\[claudiokuenzler]@[WM2856]
[2019/07/22 13:47:13.209954,  3, pid=13389, effective(0, 0), real(0, 0), class=auth] ../source3/auth/check_samsec.c:399(check_sam_security)
  check_sam_security: Couldn't find user 'claudiokuenzler' in passdb.
[2019/07/22 13:47:13.209983,  2, pid=13389, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:332(auth_check_ntlm_password)
  check_ntlm_password:  Authentication for user [claudiokuenzler] -> [claudiokuenzler] FAILED with error NT_STATUS_NO_SUCH_USER, authoritative=1
[2019/07/22 13:47:13.210075,  2, pid=13389, effective(0, 0), real(0, 0)] ../auth/auth_log.c:760(log_authentication_event_human_readable)
  Auth: [SMB2,(null)] user [DOMAIN]\[claudiokuenzler] at [Mon, 22 Jul 2019 13:47:13.210050 CEST] with [NTLMv2] status [NT_STATUS_NO_SUCH_USER] workstation [WM2856] remote host [ipv4:10.130.136.194:49419] mapped to [DOMAIN]\[claudiokuenzler]. local host [ipv4:10.130.136.38:445]
[2019/07/22 13:47:13.210276,  2, pid=13389, effective(0, 0), real(0, 0)] ../auth/auth_log.c:220(log_json)
  JSON Authentication: {"timestamp": "2019-07-22T13:47:13.210151+0200", "type": "Authentication", "Authentication": {"version": {"major": 1, "minor": 0}, "status": "NT_STATUS_NO_SUCH_USER", "localAddress": "ipv4:10.130.136.38:445", "remoteAddress": "ipv4:10.130.136.194:49419", "serviceDescription": "SMB2", "authDescription": null, "clientDomain": "DOMAIN", "clientAccount": "claudiokuenzler", "workstation": "WM2856", "becameAccount": null, "becameDomain": null, "becameSid": "(NULL SID)", "mappedAccount": "claudiokuenzler", "mappedDomain": "DOMAIN", "netlogonComputer": null, "netlogonTrustAccount": null, "netlogonNegotiateFlags": "0x00000000", "netlogonSecureChannelType": 0, "netlogonTrustAccountSid": "(NULL SID)", "passwordType": "NTLMv2"}}
[2019/07/22 13:47:13.210320,  3, pid=13389, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth_util.c:1626(do_map_to_guest_server_info)
  No such user claudiokuenzler [DOMAIN] - using guest account
[2019/07/22 13:47:13.214199,  3, pid=13389, effective(0, 0), real(0, 0)] ../lib/util/access.c:365(allow_access)
  Allowed connection from 10.130.136.194 (10.130.136.194)

After switching to the guest account, access was allowed.

And how do I solve this now?

The first question you should ask yourself is: What is the reason I want to provide a public share with anonymous (guest) access? Are the users just too lazy to authenticate before connecting to the share? Is a (legacy) application connecting to the share and has no way to use authentication? Using authentication should be the goal and is the primary solution. However if, for any good reason, the share needs guest access, you have a couple of workarounds.

Allow guest access in Windows registry

The Microsoft KB/help entry 4046019 informs about the cause of the changed client behavior, but also shows a workaround (presented as resolution): Simply enable the guest access again. This needs to be done in the Group Policy settings in Computer Configuration -> Administrative Templates -> Network -> Lanman Workstation. The relevant setting is "Enable insecure guest logons".

Another way is to change the setting in the Windows Regsitry: HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Services -> LanmanWorkstation -> Parameters:

Windows 10 Registry change to allow guest access to network share

This parameter (AllowInsecureGuestAuth) does not exist by default and needs to be created manually as a DWORD (32bit) entry. The Hexadecimal value needs to be set to 1 to enable guest access again.

This may be an acceptable workaround in a local network and limited external communication. But what about notebooks and BYOD strategies? The Windows notebook may be in the wild, connected to public networks. Talking security, this workaround should not be used. Microsoft stopped allowing guest access on shares for a good reason.

Authenticate the users against the domain

On the Samba (server) side another possibility exists: Authenticate the users. As seen in the debug log, the Windows client sends the username, logon domain and workstation name (and also the Windows password, encrypted). But how would Samba be able to verify if the user credentials are correct? Right, we do not know the user (Windows) password and creating local users for each user would be unmanageable. Instead we can tell Samba to forward the credentials to a domain controller of the domain and let the authentication happen there. In order to do this, the Samba server needs to join the domain as a domain member.

Install more stuff

For this we need to install Kerberos and Winbind:

root@sambaserver:~# apt-get install krb5-user winbind

Modify Samba config

The Samba config /etc/samba/smb.conf needs some adjustments prior to joining the domain:

#======================= Global Settings =======================

   workgroup = DOMAIN
   realm = DOMAIN.LOCAL
   encrypt passwords = yes
   password server = 10.130.136.20
   security = ADS
   server string = %h server (Samba, Ubuntu)
   dns proxy = no
   idmap uid = 20000-42000
   idmap gid = 20000-42000
   winbind use default domain = yes

####### Authentication #######
   server role = standalone server
   passdb backend = tdbsam
   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
   pam password change = yes

############ Misc ############

   usershare allow guests = yes
   guest ok = yes
   guest account = mylocaluser
   map to guest = bad user
   include = /etc/samba/smb.conf.client-%I

#========================= Share Definitions ==============================

   [archiv]
   comment = Application Archive
   path = /data/archive
   public = yes
   writable = yes
   printable = no
   force user = mylocaluser
   force group = users

To explain the additional parameters:

  • workgroup = DOMAIN: This was already set in the previous version of smb.conf. This setting tells Samba to which domain (workgroup) it is part of. Without being a domain member, this setting is just used for broadcasting the share in a workgroup (not domain).
  • realm = DOMAIN.LOCAL: The FQDN of the domain we're about to join.
  • encrypt passwords = yes: Required setting to handle the encrypted passwords coming from the client. Should be the default in recent Samba versions, however always good to keep in the smb.conf.
  • password server = 10.130.136.20: The default value would be "*", however here I chose to forward the credentials to a specific (local) domain controller.
  • security = ADS: Tells Samba to act as a domain member of the defined realm and forward the credentials to a domain controller (or specific password server).
  • idmap uid = 20000-42000: Tells Samba to assign this (virtual) user id range for authenticated non-unix users (Note: Deprecated, should be replaced by idmap config in the future).
  • idmap gid = 20000-42000: Tells Samba to assign this (virtual) group id range for authenticated non-unix users (Note: Deprecated, should be replaced by idmap config in the future).
  • winbind use default domain = yes: Tells the Windbind daemon to allow handling of the user without using the domain. For example my user "claudiokuenzler" will automatically become "DOMAIN\claudiokuenzler".

Kerberos config

The Kerberos config /etc/krb5.conf also needs some modifications. First create a backup of the default config:

root@sambaserver:~# cp /etc/krb5.conf{,.dist}

Then adjust the config:

root@sambaserver:~# cat /etc/krb5.conf
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log

[libdefaults]
default_realm = DOMAIN.LOCAL
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
forwardable = yes

[realms]
DOMAIN.LOCAL = {
kdc = dc01.DOMAIN.locaL:88
admin_server = dc01.DOMAIN.local:749
default_domain = DOMAIN.LOCAL
}

DNS resolving

All you need to adjust for your own domain is (obviously) DOMAIN.LOCAL and the domain controller (dc01).

You might also want to make sure that the Samba server is able to resolve dc01 correctly:

a) Adjust /etc/resolv.conf (or change the network configuration if you use resolvconf) and use the IP address of the primary domain controller of the domain as new nameserver (10.130.136.20 in my case)
b) Create a new entry in /etc/hosts for dc01:

root@sambaserver:~# grep dc01 /etc/hosts
10.130.136.20 dc01.domain.local dc01

c) You might need to adjust /etc/hosts again for our Samba server, so it can "look it up" itself:

root@sambaserver:~# grep sambaserver /etc/hosts
10.130.136.38 sambaserver.domain.local sambaserver

Joining the domain

Stop Samba now:

root@sambaserver:~# service smbd stop

Now you might have to call one of your Windows admin buddies, because you need a domain administrator account to join the domain. If you have the necessary credentials, proceed:

root@sambaserver:~# net ads join -U adm_claudiokuenzler
Enter adm_claudiokuenzler's password:
Using short domain name -- DOMAIN
Joined 'sambaserver' to dns domain 'DOMAIN.local'

Verify with wbinfo if you're correctly joined:

root@sambaserver:~# wbinfo -t
checking the trust secret for domain DOMAIN via RPC calls succeeded

Samba can be started again:

root@sambaserver:~# service smbd start

Trying and failing again

With the Samba config adjusted and the Samba server being a member of the Windows domain, it is time to attempt a new connection to the share from our beloved Windows 10 client. But the same error message still shows up in Windows Explorer. On the Samba server the debug log shows:

[2019/07/23 08:56:42.347787,  3, pid=994, effective(0, 0), real(0, 0)] ../source3/param/loadparm.c:1609(lp_add_ipc)
  adding IPC service
[2019/07/23 08:56:42.347812,  3, pid=994, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:189(auth_check_ntlm_password)
  check_ntlm_password:  Checking password for unmapped user [DOMAIN]\[claudiokuenzler]@[WM2674] with the new password interface
[2019/07/23 08:56:42.347850,  3, pid=994, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:192(auth_check_ntlm_password)
  check_ntlm_password:  mapped user is: [DOMAIN]\[claudiokuenzler]@[WM2674]
[2019/07/23 08:56:42.360449,  3, pid=994, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth_util.c:1249(check_account)
  Failed to find authenticated user DOMAIN\claudiokuenzler via getpwnam(), denying access.
[2019/07/23 08:56:42.360526,  2, pid=994, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:332(auth_check_ntlm_password)
  check_ntlm_password:  Authentication for user [claudiokuenzler] -> [claudiokuenzler] FAILED with error NT_STATUS_NO_SUCH_USER, authoritative=1
[2019/07/23 08:56:42.360566,  2, pid=994, effective(0, 0), real(0, 0)] ../auth/auth_log.c:760(log_authentication_event_human_readable)
  Auth: [SMB2,(null)] user [DOMAIN]\[claudiokuenzler] at [Tue, 23 Jul 2019 08:56:42.360556 CEST] with [NTLMv2] status [NT_STATUS_NO_SUCH_USER] workstation [WM2674] remote host [ipv4:172.30.123.195:49902] mapped to [DOMAIN]\[claudiokuenzler]. local host [ipv4:10.130.136.38:445]
[2019/07/23 08:56:42.360833,  2, pid=994, effective(0, 0), real(0, 0)] ../auth/auth_log.c:220(log_json)
  JSON Authentication: {"timestamp": "2019-07-23T08:56:42.360614+0200", "type": "Authentication", "Authentication": {"version": {"major": 1, "minor": 0}, "status": "NT_STATUS_NO_SUCH_USER", "localAddress": "ipv4:10.130.136.38:445", "remoteAddress": "ipv4:172.30.123.195:49902", "serviceDescription": "SMB2", "authDescription": null, "clientDomain": "DOMAIN", "clientAccount": "claudiokuenzler", "workstation": "WM2674", "becameAccount": null, "becameDomain": null, "becameSid": "(NULL SID)", "mappedAccount": "claudiokuenzler", "mappedDomain": "DOMAIN", "netlogonComputer": null, "netlogonTrustAccount": null, "netlogonNegotiateFlags": "0x00000000", "netlogonSecureChannelType": 0, "netlogonTrustAccountSid": "(NULL SID)", "passwordType": "NTLMv2"}}
[2019/07/23 08:56:42.360903,  3, pid=994, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth_util.c:1626(do_map_to_guest_server_info)
  No such user claudiokuenzler [DOMAIN] - using guest account
[2019/07/23 08:56:42.370811,  3, pid=994, effective(0, 0), real(0, 0)] ../source3/smbd/server_exit.c:244(exit_server_common)
  Server exit (NT_STATUS_CONNECTION_RESET)

Before even attempting to authenticate the user, Samba was unable to find a local user and fails back to the guest account - which Windows 10 doesn't like and stops again. We've been here already.

So before Samba forwards the credentials to the domain controller, it first needs to accept the received username in its local config. But do we want to create all AD users as local Samba users? Again, this is unmanageable. In this case we can use a Samba setting called username map.

Using username map

This parameter in /etc/samba/smb.conf is very helpful if you need to handle a lot of (AD) usernames, yet you only have a couple of local Samba users defined. Remember, in this setup there's only one local user "mylocaluser":

root@sambaserver:~# pdbedit -L
mylocaluser:1001:

Now we can map "all the other" usernames to this local user:

root@sambaserver:~# cat /etc/samba/usermap.txt
#unixuser = #windowsuser
mylocaluser = *

The username map needs to be enabled in /etc/samba/smb.conf:

############ Misc ############

   usershare allow guests = yes
   guest ok = yes
   guest account = mylocaluser
   map to guest = bad user
   include = /etc/samba/smb.conf.client-%I
   username map = /etc/samba/usermap.txt

Reload Samba:

 root@sambaserver:~# systemctl reload smbd

The eagle has landed!

Back on the Windows 10 client, another attempt is made and finally the share shows up in the Windows Explorer, without asking for any credentials:

Windows 10 samba share mounted

On the Samba side, the debug log reveals:

[2019/07/22 14:48:37.753833,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/param/loadparm.c:1609(lp_add_ipc)
  adding IPC service
[2019/07/22 14:48:37.753912,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/auth/user_util.c:416(map_username)
  Mapped user claudiokuenzler to mylocaluser
[2019/07/22 14:48:37.753934,  3, pid=993, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:189(auth_check_ntlm_password)
  check_ntlm_password:  Checking password for unmapped user [DOMAIN]\[claudiokuenzler]@[WM2674] with the new password interface
[2019/07/22 14:48:37.753949,  3, pid=993, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:192(auth_check_ntlm_password)
  check_ntlm_password:  mapped user is: [DOMAIN]\[mylocaluser]@[WM2674]
[2019/07/22 14:48:37.763063,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/auth/user_util.c:416(map_username)
  Mapped user DOMAIN\claudiokuenzler to mylocaluser
[2019/07/22 14:48:37.763164,  3, pid=993, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:256(auth_check_ntlm_password)
  auth_check_ntlm_password: winbind authentication for user [claudiokuenzler] succeeded
[2019/07/22 14:48:37.765439,  3, pid=993, effective(0, 0), real(0, 0)] ../auth/auth_log.c:760(log_authentication_event_human_readable)
  Auth: [SMB2,(null)] user [DOMAIN]\[claudiokuenzler] at [Mon, 22 Jul 2019 14:48:37.765421 CEST] with [NTLMv2] status [NT_STATUS_OK] workstation [WM2674] remote host [ipv4:172.30.123.195:51707] became [DOMAIN]\[claudiokuenzler] [S-1-5-21-4181380970-2636666227-1608733132-21669]. local host [ipv4:10.130.136.38:445]
[2019/07/22 14:48:37.765565,  3, pid=993, effective(0, 0), real(0, 0)] ../auth/auth_log.c:220(log_json)
  JSON Authentication: {"timestamp": "2019-07-22T14:48:37.765526+0200", "type": "Authentication", "Authentication": {"version": {"major": 1, "minor": 0}, "status": "NT_STATUS_OK", "localAddress": "ipv4:10.130.136.38:445", "remoteAddress": "ipv4:172.30.123.195:51707", "serviceDescription": "SMB2", "authDescription": null, "clientDomain": "DOMAIN", "clientAccount": "claudiokuenzler", "workstation": "WM2674", "becameAccount": "claudiokuenzler", "becameDomain": "DOMAIN", "becameSid": "S-1-5-21-4181380970-2636666227-1608733132-21669", "mappedAccount": "mylocaluser", "mappedDomain": "DOMAIN", "netlogonComputer": null, "netlogonTrustAccount": null, "netlogonNegotiateFlags": "0x00000000", "netlogonSecureChannelType": 0, "netlogonTrustAccountSid": "(NULL SID)", "passwordType": "NTLMv2"}}
[2019/07/22 14:48:37.765612,  2, pid=993, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:314(auth_check_ntlm_password)
  check_ntlm_password:  authentication for user [claudiokuenzler] -> [mylocaluser] -> [mylocaluser] succeeded
[2019/07/22 14:48:37.765642,  3, pid=993, effective(0, 0), real(0, 0)] ../auth/ntlmssp/ntlmssp_sign.c:509(ntlmssp_sign_reset)
  NTLMSSP Sign/Seal - Initialising with flags:
[2019/07/22 14:48:37.765654,  3, pid=993, effective(0, 0), real(0, 0)] ../auth/ntlmssp/ntlmssp_util.c:69(debug_ntlmssp_flags)
  Got NTLMSSP neg_flags=0xe2088215
[2019/07/22 14:48:37.765684,  3, pid=993, effective(0, 0), real(0, 0)] ../auth/ntlmssp/ntlmssp_sign.c:509(ntlmssp_sign_reset)
  NTLMSSP Sign/Seal - Initialising with flags:
[2019/07/22 14:48:37.765698,  3, pid=993, effective(0, 0), real(0, 0)] ../auth/ntlmssp/ntlmssp_util.c:69(debug_ntlmssp_flags)
  Got NTLMSSP neg_flags=0xe2088215
[2019/07/22 14:48:37.769227,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/passdb/lookup_sid.c:1680(get_primary_group_sid)
  Forcing Primary Group to 'Domain Users' for mylocaluser
[2019/07/22 14:48:37.808783,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/password.c:144(register_homes_share)
  Adding homes service for user 'mylocaluser' using home directory: '/home/mylocaluser'
[2019/07/22 14:48:37.907932,  3, pid=993, effective(0, 0), real(0, 0)] ../lib/util/access.c:365(allow_access)
  Allowed connection from 172.30.123.195 (172.30.123.195)
[2019/07/22 14:48:37.908048,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:595(make_connection_snum)
  Connect path is '/tmp' for service [IPC$]
[2019/07/22 14:48:37.908090,  3, pid=993, effective(0, 0), real(0, 0), class=vfs] ../source3/smbd/vfs.c:113(vfs_init_default)
  Initialising default vfs hooks
[2019/07/22 14:48:37.908139,  3, pid=993, effective(0, 0), real(0, 0), class=vfs] ../source3/smbd/vfs.c:139(vfs_init_custom)
  Initialising custom vfs hooks from [/[Default VFS]/]
[2019/07/22 14:48:37.908226,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:841(make_connection_snum)
  wm2674 (ipv4:172.30.123.195:51707) connect to service IPC$ initially as user mylocaluser (uid=1001, gid=1001) (pid 993)
[2019/07/22 14:48:37.928352,  3, pid=993, effective(1001, 1001), real(1001, 0), class=rpc_srv] ../source3/rpc_server/srv_pipe.c:748(api_pipe_bind_req)
  api_pipe_bind_req: srvsvc -> srvsvc rpc service
[2019/07/22 14:48:37.928447,  3, pid=993, effective(1001, 1001), real(1001, 0), class=rpc_srv] ../source3/rpc_server/srv_pipe.c:356(check_bind_req)
  check_bind_req for srvsvc context_id=0
[2019/07/22 14:48:37.928485,  3, pid=993, effective(1001, 1001), real(1001, 0), class=rpc_srv] ../source3/rpc_server/srv_pipe.c:399(check_bind_req)
  check_bind_req: srvsvc -> srvsvc rpc service
[2019/07/22 14:48:37.940486,  3, pid=993, effective(1001, 1001), real(1001, 0), class=rpc_srv] ../source3/rpc_server/srv_pipe.c:1528(api_rpcTNP)
  api_rpcTNP: rpc command: SRVSVC_NETSHAREENUMALL
[2019/07/22 14:48:37.943543,  1, pid=993, effective(0, 0), real(0, 0)] ../source3/printing/printer_list.c:234(printer_list_get_last_refresh)
  Failed to fetch record!
[2019/07/22 14:48:37.943623,  1, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/server_reload.c:69(delete_and_reload_printers)
  pcap cache not loaded
[2019/07/22 14:48:38.218579,  3, pid=993, effective(1001, 1001), real(1001, 0), class=msdfs] ../source3/smbd/msdfs.c:1008(get_referred_path)
  get_referred_path: |archiv| in dfs path \10.130.136.38\archiv is not a dfs root.
[2019/07/22 14:48:38.218684,  3, pid=993, effective(1001, 1001), real(1001, 0)] ../source3/smbd/smb2_server.c:3139(smbd_smb2_request_error_ex)
  smbd_smb2_request_error_ex: smbd_smb2_request_error_ex: idx[1] status[NT_STATUS_NOT_FOUND] || at ../source3/smbd/smb2_ioctl.c:309
[2019/07/22 14:48:38.224444,  3, pid=993, effective(0, 0), real(0, 0)] ../lib/util/access.c:365(allow_access)
  Allowed connection from 172.30.123.195 (172.30.123.195)
[2019/07/22 14:48:38.224919,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/passdb/lookup_sid.c:1680(get_primary_group_sid)
  Forcing Primary Group to 'Domain Users' for mylocaluser
[2019/07/22 14:48:38.228580,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/passdb/lookup_sid.c:1680(get_primary_group_sid)
  Forcing Primary Group to 'Domain Users' for mylocaluser
[2019/07/22 14:48:38.229046,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:414(set_conn_force_user_group)
  Forced user mylocaluser
[2019/07/22 14:48:38.234587,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:306(find_forced_group)
  Forced group users
[2019/07/22 14:48:38.234655,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:595(make_connection_snum)
  Connect path is '/data/archive' for service [archiv]
[2019/07/22 14:48:38.234696,  3, pid=993, effective(0, 0), real(0, 0), class=vfs] ../source3/smbd/vfs.c:113(vfs_init_default)
  Initialising default vfs hooks
[2019/07/22 14:48:38.234739,  3, pid=993, effective(0, 0), real(0, 0), class=vfs] ../source3/smbd/vfs.c:139(vfs_init_custom)
  Initialising custom vfs hooks from [/[Default VFS]/]
[2019/07/22 14:48:38.235782,  2, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:841(make_connection_snum)
  wm2674 (ipv4:172.30.123.195:51707) connect to service archiv initially as user mylocaluser (uid=1001, gid=100) (pid 993)
[2019/07/22 14:48:49.504462,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:1120(close_cnum)
  wm2674 (ipv4:172.30.123.195:51707) closed connection to service IPC$
[2019/07/22 14:48:49.504749,  2, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/service.c:1120(close_cnum)
  wm2674 (ipv4:172.30.123.195:51707) closed connection to service archiv
[2019/07/22 14:48:49.519833,  3, pid=993, effective(0, 0), real(0, 0)] ../source3/smbd/server_exit.c:244(exit_server_common)
  Server exit (NT_STATUS_CONNECTION_RESET)

The big difference: At the very beginning, right after "adding IPC service", the received user is mapped to the local user:

  Mapped user claudiokuenzler to mylocaluser

This local user is known to Samba so it continues and forwards the credentials to the domain controller:

  check_ntlm_password:  Checking password for unmapped user [DOMAIN]\[claudiokuenzler]@[WM2674] with the new password interface
  check_ntlm_password:  mapped user is: [DOMAIN]\[mylocaluser]@[WM2674]
  Mapped user DOMAIN\claudiokuenzler to mylocaluser
  auth_check_ntlm_password: winbind authentication for user [claudiokuenzler] succeeded
  Auth: [SMB2,(null)] user [DOMAIN]\[claudiokuenzler] at [Mon, 22 Jul 2019 14:48:37.765421 CEST] with [NTLMv2] status [NT_STATUS_OK] workstation [WM2674] remote host [ipv4:172.30.123.195:51707] became [DOMAIN]\[claudiokuenzler] [S-1-5-21-4181380970-2636666227-1608733132-21669]. local host [ipv4:10.130.136.38:445]
  JSON Authentication: {"timestamp": "2019-07-22T14:48:37.765526+0200", "type": "Authentication", "Authentication": {"version": {"major": 1, "minor": 0}, "status": "NT_STATUS_OK", "localAddress": "ipv4:10.130.136.38:445", "remoteAddress": "ipv4:172.30.123.195:51707", "serviceDescription": "SMB2", "authDescription": null, "clientDomain": "DOMAIN", "clientAccount": "claudiokuenzler", "workstation": "WM2674", "becameAccount": "claudiokuenzler", "becameDomain": "DOMAIN", "becameSid": "S-1-5-21-4181380970-2636666227-1608733132-21669", "mappedAccount": "mylocaluser", "mappedDomain": "DOMAIN", "netlogonComputer": null, "netlogonTrustAccount": null, "netlogonNegotiateFlags": "0x00000000", "netlogonSecureChannelType": 0, "netlogonTrustAccountSid": "(NULL SID)", "passwordType": "NTLMv2"}}
  check_ntlm_password:  authentication for user [claudiokuenzler] -> [mylocaluser] -> [mylocaluser] succeeded

Windows gets the news that the user was successfully authenticated and is happy. Samba mapped the AD user to the local Samba user and is happy too.

This is a "workaround" which combines security (authentication is happening) and easy access (no credentials needed for this share). Note however that this setup only works in internal networks with Active Directory users. 

But what about guest access from non-AD machines?

If a non-Windows user tries to access the share, the access is now denied:

$ smbclient -L \\10.130.136.38
WARNING: The "syslog" option is deprecated
Enter claudio's password:
session setup failed: NT_STATUS_LOGON_FAILURE

This happens because Samba mapped an "empty" username to "mylocaluser". Neither the "empty" username nor "mylocaluser" can be authenticated against the domain which results in the following log events on the Samba server:

[2019/07/23 11:05:32.345328,  2, pid=1255, effective(0, 0), real(0, 0), class=auth] ../source3/auth/auth.c:332(auth_check_ntlm_password)
  check_ntlm_password:  Authentication for user [] -> [mylocaluser] FAILED with error NT_STATUS_WRONG_PASSWORD, authoritative=1
[2019/07/23 11:05:32.345732,  2, pid=1255, effective(0, 0), real(0, 0)] ../auth/auth_log.c:760(log_authentication_event_human_readable)
  Auth: [SMB,(null)] user [WORKGROUP]\[] at [Tue, 23 Jul 2019 11:05:32.345575 CEST] with [No-Password] status [NT_STATUS_WRONG_PASSWORD] workstation [WM2856L] remote host [ipv4:10.130.136.195:41132] mapped to [WORKGROUP]\[mylocaluser]. local host [ipv4:10.130.136.38:445]
[2019/07/23 11:05:32.346178,  2, pid=1255, effective(0, 0), real(0, 0)] ../auth/auth_log.c:220(log_json)
  JSON Authentication: {"timestamp": "2019-07-23T11:05:32.345996+0200", "type": "Authentication", "Authentication": {"version": {"major": 1, "minor": 0}, "status": "NT_STATUS_WRONG_PASSWORD", "localAddress": "ipv4:10.130.136.38:445", "remoteAddress": "ipv4:10.130.136.195:41132", "serviceDescription": "SMB", "authDescription": null, "clientDomain": "WORKGROUP", "clientAccount": "", "workstation": "WM2856L", "becameAccount": null, "becameDomain": null, "becameSid": "(NULL SID)", "mappedAccount": "mylocaluser", "mappedDomain": "WORKGROUP", "netlogonComputer": null, "netlogonTrustAccount": null, "netlogonNegotiateFlags": "0x00000000", "netlogonSecureChannelType": 0, "netlogonTrustAccountSid": "(NULL SID)", "passwordType": "No-Password"}}
[2019/07/23 11:05:32.346556,  2, pid=1255, effective(0, 0), real(0, 0)] ../auth/gensec/spnego.c:605(gensec_spnego_server_negTokenTarg)
  SPNEGO login failed: NT_STATUS_WRONG_PASSWORD
[2019/07/23 11:05:32.347087,  3, pid=1255, effective(0, 0), real(0, 0)] ../source3/smbd/error.c:82(error_packet_set)
  NT error packet at ../source3/smbd/sesssetup.c(247) cmd=115 (SMBsesssetupX) NT_STATUS_LOGON_FAILURE
[2019/07/23 11:05:32.348113,  3, pid=1255, effective(0, 0), real(0, 0)] ../source3/smbd/server_exit.c:244(exit_server_common)
  Server exit (failed to receive smb request)

In this case the map to guest setting can be changed in /etc/samba/smb.conf:

root@sambaserver:~# grep "map to guest" /etc/samba/smb.conf
   map to guest = bad password

This tells Samba to apply a guest account to every connection which got a NT_STATUS_WRONG_PASSWORD. Meaning non-AD users and/or mounts on Unix machines.

$ smbclient -L \\10.130.136.38
WARNING: The "syslog" option is deprecated
Enter claudio's password:
Domain=[DOMAIN] OS=[Windows 6.1] Server=[Samba 4.7.6-Ubuntu]

    Sharename       Type      Comment
    ---------       ----      -------
    archiv          Disk      Application Archive
    IPC$            IPC       IPC Service (sambaserver server (Samba, Ubuntu))
Domain=[DOMAIN] OS=[Windows 6.1] Server=[Samba 4.7.6-Ubuntu]

Lesson learned?

  • Guest access (anonymous access) to network shares was disabled by Microsoft for Windows 10 and Windows Server 2016 and newer versions for (important) security reasons.
  • On Windows (client) side, a workaround is to enable guest access again by changing the Group Policy or Registry settings. But this will open a potential security risk again.
  • On Samba (server) side a simple yet effective (and secure) workaround is to join the Samba server to the AD domain and use the AD's domain controller(s) to authenticate the users.
  • To "simulate guest access", username map in the Samba config can be used.

Helpful resources


Add a comment

Show form to leave a comment

Comments (newest first)

Brian Milnes from United Kingdom wrote on Nov 14th, 2020:

Thanks for the Regedit - that did it

Win 10 Updates are resetting this Registry Key! (I had previously edited Group Policy - and Insecure access was enabled.)

Only by using the Registry key edit did I restore SMB access!!!


Nathan Mansberger from BR wrote on Oct 3rd, 2019:

Thank you man, you save my project.


ck from Switzerland wrote on Jul 23rd, 2019:

Baracha, if you can connect the IIS server and the Samba server to the same Active Directory domain, you should be able to use a service account user to connect to the share. I'd try this. If these hosts must be in separate domains (for whatever reason) you probably have no other choice than a) use proper authentication to mount the SMB share or b) use the Windows workaround and allow guest authentication in GPO or Registry.


Baracha from wrote on Jul 23rd, 2019:

Great article!
I have similar issue. The main difference is that I want to have samba with guest access from non-domain computers. The problem is that I want to have this access from application running in IIS (on default ApplicationPoolIdentity).
This is working for me from Windows2012R2 but not from Windows2016:
https://forums.iis.net/p/1243367/2150913.aspx?Re+windows+2016+IIS+10+vs+windows+2012R2+IIS+8+5+access+to+SMB+from+app

Any hints ;-)?
BR


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder