jborean93 / smbprotocol

Python SMBv2 and v3 Client
MIT License
316 stars 73 forks source link

session setup started falling with Linux #213

Closed MichaelKorn closed 10 months ago

MichaelKorn commented 1 year ago

Hello,

Using smbprotocol==1.10.1 I have a few docker containers running which established the smb connections some time ago and continue to download new files in a loop. Now I observed that these containers can't be restarted for some smb share servers because establishing new smb sessions fails. The docker containers and the VM they run on have not changed in the meantime. Unfortunately I can't say anything about the smb servers (however, apparently there were no major updates that would have terminate the smb connection). I was able to reproduce the issue in WSL2. However, everything still works on Windows!

A WSL2/Linux log (similar to docker container logs, but other paths):

...
INFO:smbprotocol.connection:Negotiated dialect: (785) SMB_3_1_1
INFO:smbprotocol.connection:Connection require signing: True
INFO:smbprotocol.session:Initialising session with username: USERNAME
DEBUG:smbprotocol.session:Decoding SPNEGO token containing supported auth mechanisms
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
DEBUG:smbprotocol.transport:Socket recv() returned 4 bytes (total 4)
DEBUG:smbprotocol.transport:Socket recv(309) (total 309)
DEBUG:smbprotocol.transport:Socket recv() returned 309 bytes (total 309)
DEBUG:smbprotocol.transport:Socket recv(4) (total 4)
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
DEBUG:smbprotocol.transport:Socket recv() returned 4 bytes (total 4)
DEBUG:smbprotocol.transport:Socket recv(73) (total 73)
DEBUG:smbprotocol.transport:Socket recv() returned 73 bytes (total 73)
DEBUG:smbprotocol.transport:Socket recv(4) (total 4)
Traceback (most recent call last):
  File "/home/USER/XXX/mytest_smb.py", line 21, in <module>
    print(set(smb.listdir("//HOST/SHARE/.../", connection_timeout=15)))
  File "/home/USER/miniconda3/envs/XXX/lib/python3.10/site-packages/smbclient/_os.py", line 238, in listdir
    with SMBDirectoryIO(path, mode="r", share_access="r", **kwargs) as dir_fd:
  File "/home/USER/miniconda3/envs/XXX/lib/python3.10/site-packages/smbclient/_io.py", line 353, in __init__
    tree, fd_path = get_smb_tree(path, **kwargs)
  File "/home/USER/miniconda3/envs/XXX/lib/python3.10/site-packages/smbclient/_pool.py", line 304, in get_smb_tree
    session = register_session(
  File "/home/USER/miniconda3/envs/XXX/lib/python3.10/site-packages/smbclient/_pool.py", line 422, in register_session
    session.connect()
  File "/home/USER/miniconda3/envs/XXX/lib/python3.10/site-packages/smbprotocol/session.py", line 303, in connect
    response = self.connection.receive(request)
  File "/home/USER/miniconda3/envs/XXX/lib/python3.10/site-packages/smbprotocol/connection.py", line 1094, 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
INFO:smbprotocol.connection:Disconnecting transport connection
INFO:smbprotocol.transport:Disconnecting DirectTcp socket
DEBUG:smbprotocol.transport:Socket recv() returned 0 bytes (total 4)

a Windows log (above, only some hex values and the GUID are different)("SMB Setup Session signature as auth is successful"):

...
INFO:smbprotocol.connection:Negotiated dialect: (785) SMB_3_1_1
INFO:smbprotocol.connection:Connection require signing: True
INFO:smbprotocol.session:Initialising session with username: USERNAME
DEBUG:smbprotocol.session:Decoding SPNEGO token containing supported auth mechanisms
INFO:smbprotocol.session:Sending SMB2_SESSION_SETUP request message
INFO:smbprotocol.session:Receiving SMB2_SESSION_SETUP response message
DEBUG:smbprotocol.transport:Socket recv() returned 4 bytes (total 4)
DEBUG:smbprotocol.transport:Socket recv(265) (total 265)
DEBUG:smbprotocol.transport:Socket recv() returned 265 bytes (total 265)
DEBUG:smbprotocol.transport:Socket recv(4) (total 4)
INFO:smbprotocol.session:Setting session id to 17889705094835519217
INFO:smbprotocol.session:Verifying the SMB Setup Session signature as auth is successful
INFO:smbprotocol.tree:Session: USERNAME- Creating connection to share \\HOST\SHARE
INFO:smbprotocol.tree:Session: USERNAME- Sending Tree Connect message
DEBUG:smbprotocol.tree:SMB2TreeConnectRequest:
...

I tried to find the differences between Windows and Linux. On Windows spnego uses the SSPIProxy, but on Linux the NegotiateProxy. On Windows and Linux there is the same in_token in session.py, but on Windows the output is large/complex and on Linux it is small and "More processing is required for SMB2_SESSION_SETUP" (which seems to fail).

jborean93 commented 1 year ago

However, everything still works on Windows!

Does this mean smbprotocol targeting Windows still works or a Windows client targeting the same host works?

I tried to find the differences between Windows and Linux. On Windows spnego uses the SSPIProxy, but on Linux the NegotiateProxy. On Windows and Linux there is the same in_token in session.py, but on Windows the output is large/complex and on Linux it is small and "More processing is required for SMB2_SESSION_SETUP" (which seems to fail).

On Windows you are more likely to be able to negotiate with Kerberos authentication which produces larger tokens than NTLM. I don't think the authentication is at play here but rather that the Windows client retries the operation when receiving the error STATUS_SERVER_UNAVAILABLE as per https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/ceba89e3-5e49-489d-959a-7562a597c0d1. This is not currently done in smbprotocol.

MichaelKorn commented 1 year ago

@jborean93 Thank you for your quick response. I do not know what software is running on the smb server and how it is configured. I'm trying to find out more. It doesn't work on Linux clients. In the meantime I've observed that not only smbprotocol not work anymore, but also CIFS does not work. Everything works on Windows clients (smbprotocol, mount as network drive).

I've tried to implement the retry (liked described in your link), unfortunately that hasn't been successful so far (got STATUS_USER_SESSION_DELETED).

I got smbprotocol working with Kerberos on Linux. So now it works again. However, the Kerberos solution is much more complicated, especially not in the docker container, but in my development environment it is not easy to compile something (the main reason here should be conda and side effects from installed packages). I'll keep trying to figure out why it's not working the way it used to.

jborean93 commented 1 year ago

If it works when you use Kerberos with Linux then it sounds like potentially the server just doesn’t want to support NTLM anymore. It’s a strange error message to receive for that error but based on your description it somewhat fits.

toondaey commented 1 year ago

I'm trying out the smbprotocol locally in a containerized environment I've been able to setup the however I seem to be stuck at the auth phase. Initially I got an error of Server cifs/krb5-samba@EXAMPLE.COM not found in Kerberos database and after creating that came the second error of Received unexpected status from the server: An invalid parameter was passed to a service or function. (3221225485) STATUS_INVALID_PARAMETER: 0xc000000d I've tried following the instructions here to use pyspnego-parse in debugging the base64 token like so:

pyspnego-parse -t 'YIICUQYJKoZIhvcSAQICAQBuggJAMIICPKADAgEFoQMCAQ6iBwMFACAAAACjggFTYYIBTzCCAUugAwIBBaENGwtFWEFNUExFLkNPTaIdMBugAwIBA6EUMBIbBGNpZnMbCmtyYjUtc2FtYmGjggEUMIIBEKADAgESoQMCAQKiggECBIH/eZWHSuGGshbpRWghgsDaSCg4YfvjO58skxoEIukwtIcTQ6FlZy2OOE1dDEyLnyEXwsd+1TQaiHMidPGt4ktSOgkeIsI9QuP4vZn4WeHB7IvcYvshuHBuqvz+WZCuSMGSNiKzxp3gALc38TU861jFXGMOyGgwBbLAcyQLT1OzS2QYst4TsMzRWJnxv/tADs4GGzPy4nyPUx3WuRkbIKp+Yw6QjFCQ6XKYOm3w5UvOF/g6AZ+BkPYwsdoGl7sf2IpfA+aQ606R/3BU7nw5360pLUEkByHuwfgbMh/huWAZ5NMxay9+pMJ8bqDQQOCIz4ACc2+G3/fdhIxyMOSSnK9kpIHPMIHMoAMCARKigcQEgcFM/un7nsEdcwD+sa2hUQ44tUbvt2/MzelaqSiiKlGzIrlVCYp6HygrEygwrNo3do2AWaP7rrDRrYa4qoGtUw1KQuWktSQ9ojzhbrEv4E1hYJJlROWfkvJYJjyuks/exnZyKms+8dfTHDa/WJEqfu55rOqdQVdc9aKtHyGLWu25TjKQLaqddSstryb8x+4XnMZjye/7LWZe8hXNregKoGj6Kgdqe5WYsUdkFLW88BtmQod95VgPfyy3uxebFpSVh69V'

But I'm getting this error instead:

TypeError: main() missing 1 required positional argument: 'args'

Kindly assist.

jborean93 commented 1 year ago

Initially I got an error of Server cifs/krb5-samba@EXAMPLE.COM not found in Kerberos database and after creating that came the second error of Received unexpected status from the server: An invalid parameter was passed to a service or function. (3221225485) STATUS_INVALID_PARAMETER: 0xc000000d

The error means that the target SPN cifs/krb5-samba@EXAMPLE.COM was not found in the KDC database. Based on your reply it does sound like you did create that SPN. I'm unsure why STATUS_INVALID_PARAMETER is being returned though, how did you create the SPN, was it for the correct host you are targeting?

But I'm getting this error instead:

Looks like a bug with the entrypoint in pyspnego. I've mostly moved away from that and doing python -m spnego -t ... as it works for both Linux and Windows. When running that I get

{
    "MessageType": "SPNEGO InitialContextToken",
    "Data": {
        "thisMech": "Kerberos (1.2.840.113554.1.2.2)",
        "innerContextToken": {
            "MessageType": "AP-REQ (14)",
            "Data": {
                "pvno": 5,
                "msg-type": "AP-REQ (14)",
                "ap-options": {
                    "raw": 32,
                    "flags": [
                        "mutual-required (32)"
                    ]
                },
                "ticket": {
                    "tkt-vno": 5,
                    "realm": "EXAMPLE.COM",
                    "sname": {
                        "name-type": "NT-SRV-HST (3)",
                        "name-string": [
                            "cifs",
                            "krb5-samba"
                        ]
                    },
                    "enc-part": {
                        "etype": "AES256_CTS_HMAC_SHA1_96 (18)",
                        "kvno": 2,
                        "cipher": "7995874AE186B216E945682182C0DA48283861FBE33B9F2C931A0422E930B4871343A165672D8E384D5D0C4C8B9F2117C2C77ED5341A88732274F1ADE24B523A091E22C23D42E3F8BD99F859E1C1EC8BDC62FB21B8706EAAFCFE5990AE48C1923622B3C69DE000B737F1353CEB58C55C630EC8683005B2C073240B4F53B34B6418B2DE13B0CCD15899F1BFFB400ECE061B33F2E27C8F531DD6B9191B20AA7E630E908C5090E972983A6DF0E54BCE17F83A019F8190F630B1DA0697BB1FD88A5F03E690EB4E91FF7054EE7C39DFAD292D41240721EEC1F81B321FE1B96019E4D3316B2F7EA4C27C6EA0D040E088CF8002736F86DFF7DD848C7230E4929CAF64"
                    }
                },
                "authenticator": {
                    "etype": "AES256_CTS_HMAC_SHA1_96 (18)",
                    "kvno": null,
                    "cipher": "4CFEE9FB9EC11D7300FEB1ADA1510E38B546EFB76FCCCDE95AA928A22A51B322B955098A7A1F282B132830ACDA37768D8059A3FBAEB0D1AD86B8AA81AD530D4A42E5A4B5243DA23CE16EB12FE04D6160926544E59F92F258263CAE92CFDEC676722A6B3EF1D7D31C36BF58912A7EEE79ACEA9D41575CF5A2AD1F218B5AEDB94E32902DAA9D752B2DAF26FCC7EE179CC663C9EFFB2D665EF215CDADE80AA068FA2A076A7B9598B1476414B5BCF01B6642877DE5580F7F2CB7BB179B16949587AF55"
                }
            },
            "RawData": "01006E8202403082023CA003020105A10302010EA20703050020000000A38201536182014F3082014BA003020105A10D1B0B4558414D504C452E434F4DA21D301BA003020103A11430121B04636966731B0A6B7262352D73616D6261A382011430820110A003020112A103020102A28201020481FF7995874AE186B216E945682182C0DA48283861FBE33B9F2C931A0422E930B4871343A165672D8E384D5D0C4C8B9F2117C2C77ED5341A88732274F1ADE24B523A091E22C23D42E3F8BD99F859E1C1EC8BDC62FB21B8706EAAFCFE5990AE48C1923622B3C69DE000B737F1353CEB58C55C630EC8683005B2C073240B4F53B34B6418B2DE13B0CCD15899F1BFFB400ECE061B33F2E27C8F531DD6B9191B20AA7E630E908C5090E972983A6DF0E54BCE17F83A019F8190F630B1DA0697BB1FD88A5F03E690EB4E91FF7054EE7C39DFAD292D41240721EEC1F81B321FE1B96019E4D3316B2F7EA4C27C6EA0D040E088CF8002736F86DFF7DD848C7230E4929CAF64A481CF3081CCA003020112A281C40481C14CFEE9FB9EC11D7300FEB1ADA1510E38B546EFB76FCCCDE95AA928A22A51B322B955098A7A1F282B132830ACDA37768D8059A3FBAEB0D1AD86B8AA81AD530D4A42E5A4B5243DA23CE16EB12FE04D6160926544E59F92F258263CAE92CFDEC676722A6B3EF1D7D31C36BF58912A7EEE79ACEA9D41575CF5A2AD1F218B5AEDB94E32902DAA9D752B2DAF26FCC7EE179CC663C9EFFB2D665EF215CDADE80AA068FA2A076A7B9598B1476414B5BCF01B6642877DE5580F7F2CB7BB179B16949587AF55"
        }
    },
    "RawData": "6082025106092A864886F71201020201006E8202403082023CA003020105A10302010EA20703050020000000A38201536182014F3082014BA003020105A10D1B0B4558414D504C452E434F4DA21D301BA003020103A11430121B04636966731B0A6B7262352D73616D6261A382011430820110A003020112A103020102A28201020481FF7995874AE186B216E945682182C0DA48283861FBE33B9F2C931A0422E930B4871343A165672D8E384D5D0C4C8B9F2117C2C77ED5341A88732274F1ADE24B523A091E22C23D42E3F8BD99F859E1C1EC8BDC62FB21B8706EAAFCFE5990AE48C1923622B3C69DE000B737F1353CEB58C55C630EC8683005B2C073240B4F53B34B6418B2DE13B0CCD15899F1BFFB400ECE061B33F2E27C8F531DD6B9191B20AA7E630E908C5090E972983A6DF0E54BCE17F83A019F8190F630B1DA0697BB1FD88A5F03E690EB4E91FF7054EE7C39DFAD292D41240721EEC1F81B321FE1B96019E4D3316B2F7EA4C27C6EA0D040E088CF8002736F86DFF7DD848C7230E4929CAF64A481CF3081CCA003020112A281C40481C14CFEE9FB9EC11D7300FEB1ADA1510E38B546EFB76FCCCDE95AA928A22A51B322B955098A7A1F282B132830ACDA37768D8059A3FBAEB0D1AD86B8AA81AD530D4A42E5A4B5243DA23CE16EB12FE04D6160926544E59F92F258263CAE92CFDEC676722A6B3EF1D7D31C36BF58912A7EEE79ACEA9D41575CF5A2AD1F218B5AEDB94E32902DAA9D752B2DAF26FCC7EE179CC663C9EFFB2D665EF215CDADE80AA068FA2A076A7B9598B1476414B5BCF01B6642877DE5580F7F2CB7BB179B16949587AF55"
}
toondaey commented 1 year ago

The error means that the target SPN cifs/krb5-samba@EXAMPLE.COM was not found in the KDC database. Based on your reply it does sound like you did create that SPN. I'm unsure why STATUS_INVALID_PARAMETER is being returned though, how did you create the SPN, was it for the correct host you are targeting?

I created the SPN, cifs/krb5-samba@EXAMPLE.COM on the KDC but I'm not sure if I have to move the keytab to the host. I did try doing that but I still ended up with the same error.

Further, after update the command to use python -m spnego -t ..., I got this:

{
    "MessageType": "SPNEGO InitialContextToken",
    "Data": {
        "thisMech": "Kerberos (1.2.840.113554.1.2.2)",
        "innerContextToken": {
            "MessageType": "AP-REQ (14)",
            "Data": {
                "pvno": 5,
                "msg-type": "AP-REQ (14)",
                "ap-options": {
                    "raw": 32,
                    "flags": [
                        "mutual-required (32)"
                    ]
                },
                "ticket": {
                    "tkt-vno": 5,
                    "realm": "EXAMPLE.COM",
                    "sname": {
                        "name-type": "NT-SRV-HST (3)",
                        "name-string": [
                            "cifs",
                            "krb5-samba"
                        ]
                    },
                    "enc-part": {
                        "etype": "AES256_CTS_HMAC_SHA1_96 (18)",
                        "kvno": 2,
                        "cipher": "7995874AE186B216E945682182C0DA48283861FBE33B9F2C931A0422E930B4871343A165672D8E384D5D0C4C8B9F2117C2C77ED5341A88732274F1ADE24B523A091E22C23D42E3F8BD99F859E1C1EC8BDC62FB21B8706EAAFCFE5990AE48C1923622B3C69DE000B737F1353CEB58C55C630EC8683005B2C073240B4F53B34B6418B2DE13B0CCD15899F1BFFB400ECE061B33F2E27C8F531DD6B9191B20AA7E630E908C5090E972983A6DF0E54BCE17F83A019F8190F630B1DA0697BB1FD88A5F03E690EB4E91FF7054EE7C39DFAD292D41240721EEC1F81B321FE1B96019E4D3316B2F7EA4C27C6EA0D040E088CF8002736F86DFF7DD848C7230E4929CAF64"
                    }
                },
                "authenticator": {
                    "etype": "AES256_CTS_HMAC_SHA1_96 (18)",
                    "kvno": null,
                    "cipher": "4CFEE9FB9EC11D7300FEB1ADA1510E38B546EFB76FCCCDE95AA928A22A51B322B955098A7A1F282B132830ACDA37768D8059A3FBAEB0D1AD86B8AA81AD530D4A42E5A4B5243DA23CE16EB12FE04D6160926544E59F92F258263CAE92CFDEC676722A6B3EF1D7D31C36BF58912A7EEE79ACEA9D41575CF5A2AD1F218B5AEDB94E32902DAA9D752B2DAF26FCC7EE179CC663C9EFFB2D665EF215CDADE80AA068FA2A076A7B9598B1476414B5BCF01B6642877DE5580F7F2CB7BB179B16949587AF55"
                }
            },
            "RawData": "01006E8202403082023CA003020105A10302010EA20703050020000000A38201536182014F3082014BA003020105A10D1B0B4558414D504C452E434F4DA21D301BA003020103A11430121B04636966731B0A6B7262352D73616D6261A382011430820110A003020112A103020102A28201020481FF7995874AE186B216E945682182C0DA48283861FBE33B9F2C931A0422E930B4871343A165672D8E384D5D0C4C8B9F2117C2C77ED5341A88732274F1ADE24B523A091E22C23D42E3F8BD99F859E1C1EC8BDC62FB21B8706EAAFCFE5990AE48C1923622B3C69DE000B737F1353CEB58C55C630EC8683005B2C073240B4F53B34B6418B2DE13B0CCD15899F1BFFB400ECE061B33F2E27C8F531DD6B9191B20AA7E630E908C5090E972983A6DF0E54BCE17F83A019F8190F630B1DA0697BB1FD88A5F03E690EB4E91FF7054EE7C39DFAD292D41240721EEC1F81B321FE1B96019E4D3316B2F7EA4C27C6EA0D040E088CF8002736F86DFF7DD848C7230E4929CAF64A481CF3081CCA003020112A281C40481C14CFEE9FB9EC11D7300FEB1ADA1510E38B546EFB76FCCCDE95AA928A22A51B322B955098A7A1F282B132830ACDA37768D8059A3FBAEB0D1AD86B8AA81AD530D4A42E5A4B5243DA23CE16EB12FE04D6160926544E59F92F258263CAE92CFDEC676722A6B3EF1D7D31C36BF58912A7EEE79ACEA9D41575CF5A2AD1F218B5AEDB94E32902DAA9D752B2DAF26FCC7EE179CC663C9EFFB2D665EF215CDADE80AA068FA2A076A7B9598B1476414B5BCF01B6642877DE5580F7F2CB7BB179B16949587AF55"
        }
    },
    "RawData": "6082025106092A864886F71201020201006E8202403082023CA003020105A10302010EA20703050020000000A38201536182014F3082014BA003020105A10D1B0B4558414D504C452E434F4DA21D301BA003020103A11430121B04636966731B0A6B7262352D73616D6261A382011430820110A003020112A103020102A28201020481FF7995874AE186B216E945682182C0DA48283861FBE33B9F2C931A0422E930B4871343A165672D8E384D5D0C4C8B9F2117C2C77ED5341A88732274F1ADE24B523A091E22C23D42E3F8BD99F859E1C1EC8BDC62FB21B8706EAAFCFE5990AE48C1923622B3C69DE000B737F1353CEB58C55C630EC8683005B2C073240B4F53B34B6418B2DE13B0CCD15899F1BFFB400ECE061B33F2E27C8F531DD6B9191B20AA7E630E908C5090E972983A6DF0E54BCE17F83A019F8190F630B1DA0697BB1FD88A5F03E690EB4E91FF7054EE7C39DFAD292D41240721EEC1F81B321FE1B96019E4D3316B2F7EA4C27C6EA0D040E088CF8002736F86DFF7DD848C7230E4929CAF64A481CF3081CCA003020112A281C40481C14CFEE9FB9EC11D7300FEB1ADA1510E38B546EFB76FCCCDE95AA928A22A51B322B955098A7A1F282B132830ACDA37768D8059A3FBAEB0D1AD86B8AA81AD530D4A42E5A4B5243DA23CE16EB12FE04D6160926544E59F92F258263CAE92CFDEC676722A6B3EF1D7D31C36BF58912A7EEE79ACEA9D41575CF5A2AD1F218B5AEDB94E32902DAA9D752B2DAF26FCC7EE179CC663C9EFFB2D665EF215CDADE80AA068FA2A076A7B9598B1476414B5BCF01B6642877DE5580F7F2CB7BB179B16949587AF55"
}
jborean93 commented 1 year ago

The service keytab is done for the service. You need to control how that is setup and isn’t configured by the client. It’s crucial for Kerberos as the KDC produces a secret that only the service for that principal can decrypt. I thought you didn’t have control over the service?

toondaey commented 1 year ago

My setup is mostly experimental so I control both the KDC and the service. I probably don't understand what you're trying to say; could you please elaborate?

jborean93 commented 1 year ago

I'm just confused about the whole scenario. What's the service here, what is working, how are you providing the keytab to the service, etc.

MichaelKorn commented 1 year ago

@jborean93 Many thanks for the support! After two weeks of disruption, NTLM is now working again (and Kerberos is still working, too). Obviously there were problems on the server side, unfortunately the responses from the server weren't particularly helpful!

toondaey commented 1 year ago

I'm just confused about the whole scenario. What's the service here, what is working, how are you providing the keytab to the service, etc.

Here's my setup:

./docker-compose.yaml

version: '3.5'
services:
 kdc-server:
    container_name: kdc
    build:
      context: ./smb
      dockerfile: ./Dockerfile.kdc
    hostname: 'kdc-server'
    ports:
      - 749:749
      - 88:88/udp
    networks:
      smb-testing:
        ipv4_address: 172.41.0.1
    volumes:
      - /dev/urandom:/dev/urandom
      - ./secrets:/secrets
    environment:
      - REALM=EXAMPLE.COM
      - KADMIN_PRINCIPAL=kadmin/admin
      - KADMIN_PASSWORD=pa$$w0rd1
    healthcheck:
      test: ps -q `cat /var/run/kadmind.pid` | grep 'kadmind' > /dev/null && ps -q `cat /var/run/krb5kdc.pid` | grep 'krb5kdc' > /dev/null
      interval: 1m30s
      timeout: 10s
      retries: 5
      start_period: 5s

  krb5-samba:
    container_name: krb5-samba
    hostname: krb5-samba
    ports:
      - 2222:22
    build:
      context: ./smb
      dockerfile: ./Dockerfile.samba
    volumes:
      - ./secrets/sshserver.keytab:/etc/krb5.keytab
      - ./secrets:/secrets
      - ./smb_test_dir:/shared/tests
    networks:
      smb-testing:
        ipv4_address: 172.41.0.2

networks:
  smb-testing:
    name: smb-testing
    ipam:
      driver: default
      config:
        - subnet: 172.41.0.0/16
          gateway: 172.41.0.10

Here's the setup for the kdc server ./smb/Dockerfile.kdc

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get -qq update 
RUN apt-get -qq install locales krb5-kdc krb5-admin-server
RUN apt-get -qq clean

COPY ./init_kdc.sh /docker-entrypoint.sh

RUN chmod +x /docker-entrypoint.sh

ENTRYPOINT [ "/docker-entrypoint.sh" ]

EXPOSE 749 88/udp

and the ./smb/init_kdc.sh

#!/usr/bin/env bash

set -e -u

KDC_ADMIN_SERVER=$(hostname -f)
KADMIN_PRINCIPAL_FULL=$KADMIN_PRINCIPAL@$REALM

## Configure kerberos
tee /etc/krb5.conf <<EOF
[libdefaults]
    default_realm = $REALM

[realms]
    $REALM = {
        kdc_ports = 88,750
        kadmind_port = 749
        kdc = $KDC_ADMIN_SERVER
        admin_server = $KDC_ADMIN_SERVER
    }
EOF

## Configure kerberos kdc 
tee /etc/krb5kdc/kdc.conf <<EOF
[realms]
    $REALM = {
        acl_file = /etc/krb5kdc/kadm5.acl
        max_renewable_life = 7d 0h 0m 0s
        supported_enctypes = aes256-cts-hmac-sha1-96:normal
        default_principal_flags = +preauth
    }
EOF

## Configure default krb acl
tee /etc/krb5kdc/kadm5.acl <<EOF
$KADMIN_PRINCIPAL_FULL *
noPermissions@$REALM X
EOF

# Default realm
MASTER_PASSWORD=$(tr -cd '[:alnum:]' < /dev/urandom | fold -w30 | head -n1)
# This command also starts the krb5-kdc and krb5-admin-server services
krb5_newrealm <<EOF
$MASTER_PASSWORD
$MASTER_PASSWORD
EOF

# KADMIN_PASSWORD=$(tr -cd '[:alnum:]' < /dev/urandom | fold -w30 | head -n1)

kadmin.local -q "delprinc --force $KADMIN_PRINCIPAL_FULL"
kadmin.local -q "addprinc -pw $KADMIN_PASSWORD $KADMIN_PRINCIPAL_FULL"

kadmin.local -q "delprinc --force noPermissions@$REALM"
kadmin.local -q "addprinc -pw $KADMIN_PASSWORD noPermissions@$REALM"

kadmin.local -q "addprinc -randkey host/krb5-samba@$REALM"
kadmin.local -q "ktadd -k /secrets/sshserver.keytab host/krb5-samba@$REALM"

kadmin.local -q "addprinc -randkey cifs/krb5-samba@$REALM"
kadmin.local -q "ktadd -k /secrets/cifsserver.keytab cifs/krb5-samba@$REALM"

kadmin.local -q "addprinc -randkey tester"
kadmin.local -q "ktadd -k /secrets/sshuser.keytab tester@$REALM"

cat >> /etc/hosts <<EOL
172.41.0.2      krb5-samba
EOL

krb5kdc
kadmind -nofork

My ./smb/Dockerfile.samba

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get -qq update
RUN apt-get -qq install samba openssh-server krb5-user sssd-krb5
RUN apt-get -qq clean

COPY ./smb.conf /etc/samba/smb.conf

COPY ./sshd_config /etc/ssh/sshd_config
COPY ./ssh_config /etc/ssh/ssh_config
COPY ./init_samba.sh /docker-entrypoint.sh

RUN chmod +x /docker-entrypoint.sh

RUN mkdir -p /run/sshd

ENTRYPOINT [ "/docker-entrypoint.sh" ]

CMD [ "smbd", "-F", "--debug-stdout", "--no-process-group" ]

EXPOSE 2222 22 445

And finally the ./smb/init_samba.sh:

#!/usr/bin/env bash

set -e -u

tee /etc/krb5.conf <<EOF
[libdefaults]
    default_realm = EXAMPLE.COM
    forwardable = TRUE
[realms]
    EXAMPLE.COM = {
        kdc_ports = 88
        kadmind_port = 749
        kdc = kdc-server
        admin_server = kdc-server
    }
[domain_realm]
    kdc-server = EXAMPLE.COM
EOF

testparm -s

if id -gn testing > /dev/null 2>&1; then
    echo ""
else
    id -g 1000 &> /dev/null || id -gn testing &> /dev/null || groupadd --gid 1000 --system testing
fi;

if id -un tester > /dev/null 2>&1; then
    echo ""
else
    id -u 1100 &> /dev/null || id -un tester &> /dev/null || useradd --uid 1100 -g testing tester
fi;

smbpasswd -a -s tester <<EOF
pa$$w0rd1
pa$$w0rd1
EOF

cat >> /etc/hosts <<EOL
172.41.0.1  kdc-server
EOL

/usr/sbin/sshd

exec "$@"

I didn't include the ssh(d)_configs because they just ensure activation of the use of kerberos authentication. I also created an ubuntu build from where I'm testing the smbprotocol implementation with kerberos auth. I've run kinit -kt /secrets/sshuser.keytab tester and able to ssh into krb5-samba. However, with the smb python run, I always seem to run into this Received unexpected status from the server: An invalid parameter was passed to a service or function. (3221225485) STATUS_INVALID_PARAMETER: 0xc000000d, retrying in 10 seconds... I would have used a host network mode but I can't seem to get that working due to the fact that docker on mac runs behind a VM and host mode doesn't actually point to the mac but the VM.

I've also tried using the cifs keytab as the samba server keytab which results in pretty much the same thing.

toondaey commented 1 year ago

Wanted to follow up on this @jborean93 . I'd really appreciate your help on this?

jborean93 commented 1 year ago

I'm honestly not sure, you'll have to try and enable more logging on the server to figure out why it's returning STATUS_INVALID_PARAMETER.

MichaelKorn commented 10 months ago

I close this issue as the original (my) problem was solved: For some reason NTLM was server side broken. Workaround was using Kerberos (and NTLM is in the meantime working again, too)