namjaejeon / ksmbd-tools

ksmbd kernel server userspace utilities
GNU General Public License v2.0
52 stars 42 forks source link

windows domain(ads) support #187

Open wangyugui-e16 opened 1 year ago

wangyugui-e16 commented 1 year ago

Hi,

I successed to build ksmbd-tools 3.4.6 with LIBKRB5_CFLAGS="$(/usr/bin/krb5-config krb5 --cflags)" \ LIBKRB5_LIBS="$(/usr/bin/krb5-config krb5 --libs)" \ --enable-krb5

do we have a test command inside ksmbd-tools to test krb5 user/password, and then output the user/group id assigned by windows ads/linux?

Best regards

wangyugui-e16 commented 1 year ago

when build without --enable-krb5, it is OK to access from a windows 10 client. when build with --enable-krb5, ksmbd failed to work with local user/password.

ksmbd support krb5 and local user/passwd at the same time?

Dec 18 08:55:41 T3610 ksmbd[4958]: [ksmbd-worker/4958]: ERROR: Failed to init SPNEGO subsystem
Dec 18 08:55:41 T3610 ksmbd[4953]: [ksmbd.mountd/4953]: INFO: Worker PID 4958 changed state
Dec 18 08:55:42 T3610 ksmbd[4959]: [ksmbd-worker/4959]: ERROR: Cannot determine realm for host: while getting host name
Dec 18 08:55:42 T3610 ksmbd[4959]: [ksmbd-worker/4959]: ERROR: Failed to init Kerberos 5
Dec 18 08:55:42 T3610 ksmbd[4959]: [ksmbd-worker/4959]: ERROR: Failed to init SPNEGO subsystem
Dec 18 08:55:42 T3610 ksmbd[4953]: [ksmbd.mountd/4953]: INFO: Worker PID 4959 changed state
Dec 18 08:55:43 T3610 ksmbd[4960]: [ksmbd-worker/4960]: ERROR: Cannot determine realm for host: while getting host name
Dec 18 08:55:43 T3610 ksmbd[4960]: [ksmbd-worker/4960]: ERROR: Failed to init Kerberos 5
Dec 18 08:55:43 T3610 ksmbd[4960]: [ksmbd-worker/4960]: ERROR: Failed to init SPNEGO subsystem
Dec 18 08:55:43 T3610 ksmbd[4953]: [ksmbd.mountd/4953]: INFO: Worker PID 4960 changed state

os: rocky linux 9.1 kernel: 6.1.0 ksmbd-tools: 3.4.6(github upstream) ksmbd.conf:

# cat /etc/ksmbd/ksmbd.conf
; see ksmbd.conf(5) for details

[global]
        ; global section parameters
        bind interfaces only = no
        deadtime = 0
        guest account = nobody
        interfaces =
        ipc timeout = 0
        kerberos keytab file =
        kerberos service name =
        map to guest = never
        max active sessions = 1024
        max open files = 10000
        netbios name = T3610
        restrict anonymous = 0
        root directory =
        server max protocol = SMB3_11
        server min protocol = SMB2_10
        server multi channel support = no
        server signing = disabled
        server string = SMB SERVER
        share:fake_fscaps = 64
        smb2 leases = no
        smb2 max credits = 8192
        smb2 max read = 4MB
        smb2 max trans = 1MB
        smb2 max write = 4MB
        smb3 encryption = no
        smbd max io size = 8MB
        tcp port = 445
        workgroup = WORKGROUP

        ; share parameters for all sections
        browseable = yes
        comment =
        create mask = 0744
        directory mask = 0755
        force create mode = 0000
        force directory mode = 0000
        force group =
        force user =
        guest ok = no
        hide dot files = yes
        inherit owner = no
        invalid users =
        max connections = 0
        oplocks = yes
        path =
        read list =
        store dos attributes = yes
        valid users =
        veto files =
        vfs objects =
        write list =
        writeable = no

[hpc-bio]
        ; share parameter overrides for `example' share
        path = /usr/hpc-bio
wangyugui-e16 commented 1 year ago

We already have a build option to enable/disable krb5, we also need a configure option to enable/disable krb5?

a dirty patch to skip krb5 init.

diff --git a/tools/management/spnego.c b/tools/management/spnego.c
index bf2ad79..5bf1ca1 100644
--- a/tools/management/spnego.c
+++ b/tools/management/spnego.c
@@ -46,6 +46,9 @@ int spnego_init(void)
    if (global_conf.krb5_keytab_file)
        mech_ctx->params.krb5.keytab_name =
            strdup(global_conf.krb5_keytab_file);
+   if(mech_ctx->params.krb5.service_name == NULL &&
+       mech_ctx->params.krb5.keytab_name == NULL)
+       return 0;

    mech_ctx = &mech_ctxs[SPNEGO_MECH_KRB5];
    mech_ctx->ops = &spnego_krb5_operations;
namjaejeon commented 1 year ago

@atheik Could you please help review this change ?

namjaejeon commented 1 year ago

@atheik Ping?

atheik commented 1 year ago

@namjaejeon, @wangyugui-e16,

I apologize for the delay.

If I understood correctly, your suggestion is that the authentication should silently fallback to NTLM when Kerberos 5 authentication fails. And, this issue and the suggested workaround was prompted by the Windows client failing to authenticate with Kerberos 5.

Instead of adding this fallback, wouldn't it be better to figure out how to get Kerberos 5 authentication working with the Windows client? To my knowledge, separate Active Domain Directory support in ksmbd is not a requirement to get it working: https://serverfault.com/questions/455793/kerberos-authentication-for-workstations-not-on-domain/1025351#1025351

@wangyugui-e16,

Just to make sure, since you built ksmbd-tools with Kerberos 5 authentication in the first place, do you have some other client (e.g. cifs-utils on Linux) where Kerberos 5 authentication works with your current setup? Your ERROR: Cannot determine realm for host: while getting host name suggests to me that there's something wrong with your Kerberos 5 configuration.

wangyugui-e16 commented 1 year ago

In fact, there are two problems 1, we need build one binary to support krb5 and ksmbd.adduser at the same time. and then change the configure on demond. this dirty patch fix one problem for this.

2, whether the krb5/ads support works as expected. I want to test it with realm/SSSD, but the test is yet not finished.

atheik commented 1 year ago

@wangyugui-e16,

In fact, there are two problems 1, we need build one binary to support krb5 and ksmbd.adduser at the same time. and then change the configure on demond. this dirty patch fix one problem for this.

Sorry, I am not sure I understand what you mean by "support krb5 and ksmbd.adduser at the same time". Even with Kerberos 5 support, there is still the requirement that all users are present in ksmbdpwd.db, it's just that the password fields there are not in use then. For any existing users of ksmbd-tools relying on Kerberos 5 support, the suggested NTLM fallback (I still assume this is what you meant) would mean that the passwords in ksmbdpwd.db would suddenly become meaningful. If the user left them blank or unsafe, knowing that they wouldn't be used with Kerberos 5 enabled, that would be a problem.

wangyugui-e16 commented 1 year ago

@atheik

Can we 'yum/dnf install' just once, and then change the configure file to switch krb5 and ksmbd.adduser support?

atheik commented 1 year ago

@wangyugui-e16,

Can we 'yum/dnf install' just once, and then change the configure file to switch krb5 and ksmbd.adduser support?

As I said earlier, with Kerberos 5 enabled, you still need to use ksmbd.adduser to add users to ksmbdpwd.db, although the passwords fields there are then not used. And, currently support for Kerberos 5 is determined at configure-time before building, i.e. not at package-installation time, and there is currently no way to turn it off without rebuilding.

wangyugui-e16 commented 1 year ago

@atheik with my dirty patch, we can turn off krb5 support without rebuilding. in this dirty patch, when krb5 configure is not setting, just skip krb5 init.

atheik commented 1 year ago

@wangyugui-e16,

@atheik with my dirty patch, we can turn off krb5 support without rebuilding. in this dirty patch, when krb5 configure is not setting, just skip krb5 init.

Please see https://github.com/namjaejeon/ksmbd-tools/issues/187#issuecomment-1374679369 for one potential problem.

wangyugui-e16 commented 1 year ago

Should ksmbd allow more than ssh(SSSD/realm)? or Should ksmbd allow less than ssh(SSSD/realm)?

SSSD/realm already has 'PERMIT/DENY' feature.

for ksmbd.adduser, we may add 'PERMIT/DENY' feature for krb5 support to use a different database?

hcbwiz commented 1 year ago

@wangyugui-e16

Do you mean that?

cifs client --> NTLM auth --> ksmbd --> how to adapt? --> sssd --> windows AD

Let sssd internally handle krb5 auth, id mapping and etc.

wangyugui-e16 commented 1 year ago

@hcbwiz

If a user can login with ssh(SSSD/krb5), then In most case he should be allowed to access ksmbd?

ksmbd may allow more user than ssh(SSSD/krb5) too?

hcbwiz commented 1 year ago

About ssh + krb5, you can check here

In my understanding, ksmbd with windows ad support needs more features than krb5.

I guess this approach may work also (i don't familiar with sssd and Linux PAM)

cifs client --> krb5 TGT --> ksmbd --> bypass krb5 TGT? --> sssd --> windows AD

If sssd can do all related things with Windows AD, The issue is how ksmbd adapts to sssd.

I'm still investigating it.

wangyugui-e16 commented 1 year ago

uid/gid mapping is very complex for smb support 1, sssd support 2 method 1a) POSIX(uidNumber/gidNumber/...) 1b) auto mapping

2, samba/winbind support more, but yet able to find one that match sssd well. 2a) rid default(mapping) 2b) idmap_ad fail to work here 2c) idmap_rfc2307/idmap_nss and more.

mapped gid/uid is saved in every file attr of linux filesystem.

for ksmbd, better to select the best known one, rather than an new one?

and what is the recommand mapping rule that is easy to reproduce?

wangyugui-e16 commented 1 year ago

windows ads server is ready here. and linux is joined into ads with sssd.

# realm list
e16-tech.com
  type: kerberos
  realm-name: E16-TECH.COM
  domain-name: e16-tech.com
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools
  login-formats: %U@e16-tech.com
  login-policy: allow-realm-logins

/etc/ksmbd/ksmbd.conf [global] kerberos keytab file = kerberos service name = cifs/E16-TECH.COM

# systemctl status ksmbd.service
Jan 14 20:17:05 T3610 ksmbd[4775]: [ksmbd-worker/4775]: ERROR: Failed to init SPNEGO subsystem
Jan 14 20:17:05 T3610 ksmbd[4527]: [ksmbd.mountd/4527]: INFO: Worker PID 4775 changed state
Jan 14 20:17:06 T3610 ksmbd[4783]: [ksmbd-worker/4783]: ERROR: Keytab contains no suitable keys for cifs/E16-TECH.COM@:>
Jan 14 20:17:06 T3610 ksmbd[4783]: [ksmbd-worker/4783]: ERROR: Failed to init Kerberos 5
Jan 14 20:17:06 T3610 ksmbd[4783]: [ksmbd-worker/4783]: ERROR: Failed to init SPNEGO subsystem
Jan 14 20:17:06 T3610 ksmbd[4527]: [ksmbd.mountd/4527]: INFO: Worker PID 4783 changed state
Jan 14 20:17:07 T3610 ksmbd[4784]: [ksmbd-worker/4784]: ERROR: Keytab contains no suitable keys for cifs/E16-TECH.COM@:>
Jan 14 20:17:07 T3610 ksmbd[4784]: [ksmbd-worker/4784]: ERROR: Failed to init Kerberos 5
Jan 14 20:17:07 T3610 ksmbd[4784]: [ksmbd-worker/4784]: ERROR: Failed to init SPNEGO subsystem
Jan 14 20:17:07 T3610 ksmbd[4527]: [ksmbd.mountd/4527]: INFO: Worker PID 4784 changed state

any advice for /etc/ksmbd/ksmbd.conf 'kerberos keytab file'?

hcbwiz commented 1 year ago

Maybe need a KCM? https://docs.pagure.org/sssd.sssd/design_pages/kcm.html

wangyugui-e16 commented 1 year ago

1) /etc/ksmbd/ksmbd.conf [global] kerberos keytab file = kerberos service name = cifs/E16-TECH.COM workgroup = E16-TECH

2) sssd-kcm.service is running

3) then ksmbd output: Jan 16 19:02:54 T3610 ksmbd[2292]: [ksmbd-worker/2292]: INFO: User database does not exist, only guest sessions may work Jan 16 19:02:54 T3610 ksmbd[2292]: [ksmbd-worker/2292]: ERROR: Keytab contains no suitable keys for cifs/E16-TECH.COM@:> Jan 16 19:02:54 T3610 ksmbd[2292]: [ksmbd-worker/2292]: ERROR: Failed to init Kerberos 5 Jan 16 19:02:54 T3610 ksmbd[2292]: [ksmbd-worker/2292]: ERROR: Failed to init SPNEGO subsystem Jan 16 19:02:54 T3610 ksmbd[1425]: [ksmbd.mountd/1425]: INFO: Worker PID 2292 changed state

wangyugui-e16 commented 1 year ago

basic sssd(ad, ldap_id_mapping = False) and winbind(idmap ad) works here now, They have almost same, uidNumber/gidNumber based id mapping.

sssd(ad, ldap_id_mapping = False) seems a good option for ksmbd id mapping.

but Single sign-on configure (https://wiki.samba.org/index.php/OpenSSH_Single_sign-on) is still yet able to work here. we need 'GSSAPIStrictAcceptorCheck no' and more?

we need some Single sign-on support for ksmbd too?

hcbwiz commented 1 year ago

Kerberos would be a single-sign-on mechanism.

root@vhost:~# realm list
test.com
  type: kerberos
  realm-name: TEST.COM
  domain-name: test.com
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: sssd-tools
  required-package: sssd
  required-package: libnss-sss
  required-package: libpam-sss
  required-package: adcli
  required-package: samba-common-bin
  login-formats: %U@test.com
  login-policy: allow-realm-logins

root@vhost:~# klist -k
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   2 VHOST$@TEST.COM
   2 VHOST$@TEST.COM
   2 VHOST$@TEST.COM
   2 host/VHOST@TEST.COM
   2 host/VHOST@TEST.COM
   2 host/VHOST@TEST.COM
   2 host/vhost.test.com@TEST.COM
   2 host/vhost.test.com@TEST.COM
   2 host/vhost.test.com@TEST.COM
   2 RestrictedKrbHost/VHOST@TEST.COM
   2 RestrictedKrbHost/VHOST@TEST.COM
   2 RestrictedKrbHost/VHOST@TEST.COM
   2 RestrictedKrbHost/vhost.test.com@TEST.COM
   2 RestrictedKrbHost/vhost.test.com@TEST.COM
   2 RestrictedKrbHost/vhost.test.com@TEST.COM

Then I added another SPN: adcli update --add-service-principal=cifs/vhost.test.com --domain=TEST.COM

root@vhost:~# klist -k
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   2 VHOST$@TEST.COM
   2 VHOST$@TEST.COM
   2 VHOST$@TEST.COM
   2 host/VHOST@TEST.COM
   2 host/VHOST@TEST.COM
   2 host/VHOST@TEST.COM
   2 host/vhost.test.com@TEST.COM
   2 host/vhost.test.com@TEST.COM
   2 host/vhost.test.com@TEST.COM
   2 RestrictedKrbHost/VHOST@TEST.COM
   2 RestrictedKrbHost/VHOST@TEST.COM
   2 RestrictedKrbHost/VHOST@TEST.COM
   2 RestrictedKrbHost/vhost.test.com@TEST.COM
   2 RestrictedKrbHost/vhost.test.com@TEST.COM
   2 RestrictedKrbHost/vhost.test.com@TEST.COM
   2 cifs/vhost.test.com@TEST.COM
   2 cifs/vhost.test.com@TEST.COM
   2 cifs/vhost.test.com@TEST.COM

Modified ksmbd.conf: kerberos keytab file = /etc/krb5.keytab

However, I got the same error:

root@vhost:~# ksmbd.mountd -v -n
[ksmbd-worker/777]: DEBUG: New user `test'
[ksmbd-worker/777]: DEBUG: New share `IPC$'
[ksmbd-worker/777]: DEBUG: New share `mnt'
[ksmbd-worker/777]: DEBUG: New user `nobody'
[ksmbd-worker/777]: ERROR: Keytab contains no suitable keys for cifs/vhost.test.com@: while getting credentials for cifs/vhost.test.com@
[ksmbd-worker/777]: ERROR: Failed to init Kerberos 5
[ksmbd-worker/777]: ERROR: Failed to init SPNEGO subsystem
double free or corruption (fasttop)
[ksmbd-worker/777]: INFO: Worker received signal 6 (Aborted)
double free or corruption (fasttop)
[ksmbd-worker/777]: INFO: Worker received signal 6 (Aborted)
[ksmbd.mountd/776]: INFO: Worker PID 777 changed state

still investigate that how ksmbd works with krb5.

hcbwiz commented 1 year ago

still figure out how krb5 works.

modify the code:

diff --git a/tools/management/spnego_krb5.c b/tools/management/spnego_krb5.c
index e71d3aa..02efe38 100644
--- a/tools/management/spnego_krb5.c
+++ b/tools/management/spnego_krb5.c
@@ -153,7 +153,7 @@ static krb5_error_code acquire_creds_from_keytab(krb5_context context,
        }

        retval = krb5_sname_to_principal(context, host_name, service_name,
-                       KRB5_NT_UNKNOWN, &sprinc);
+                       KRB5_NT_SRV_HST, &sprinc);
        if (retval) {
                pr_krb5_err(context, retval, "while generating service name\n");
                goto out_err;

Got different error

root@vhost:~# KRB5_TRACE=/dev/stdout ksmbd.mountd -v -n
[ksmbd-worker/2610]: DEBUG: New user `test'
[ksmbd-worker/2610]: DEBUG: New share `IPC$'
[ksmbd-worker/2610]: DEBUG: New share `mnt'
[ksmbd-worker/2610]: DEBUG: New user `nobody'
[2610] 1673945914.310609: Getting initial credentials for cifs/vhost.test.com@
[2610] 1673945914.310610: Found entries for cifs/vhost.test.com@TEST.COM in keytab: rc4-hmac, aes128-cts, aes256-cts
[2610] 1673945914.310612: Sending unauthenticated request
[2610] 1673945914.310613: Sending request (214 bytes) to TEST.COM
[2610] 1673945914.310614: Initiating TCP connection to stream 10.252.165.204:88
[2610] 1673945914.310615: Sending TCP request to stream 10.252.165.204:88
[2610] 1673945914.310616: Received answer (90 bytes) from stream 10.252.165.204:88
[2610] 1673945914.310617: Terminating TCP connection to stream 10.252.165.204:88
[2610] 1673945914.310618: Response was from primary KDC
[2610] 1673945914.310619: Received error from KDC: -1765328378/Client not found in Kerberos database
[ksmbd-worker/2610]: ERROR: Client 'cifs/vhost.test.com@TEST.COM' not found in Kerberos database: while getting credentials for cifs/vhost.test.com@
[ksmbd-worker/2610]: ERROR: Failed to init Kerberos 5
[ksmbd-worker/2610]: ERROR: Failed to init SPNEGO subsystem
double free or corruption (fasttop)
[ksmbd-worker/2610]: INFO: Worker received signal 6 (Aborted)
double free or corruption (fasttop)
[ksmbd-worker/2610]: INFO: Worker received signal 6 (Aborted)
[ksmbd.mountd/2609]: INFO: Worker PID 2610 changed state
wangyugui-e16 commented 1 year ago

https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/ktpass [/ptype {KRB5_NT_PRINCIPAL|KRB5_NT_SRV_INST|KRB5_NT_SRV_HST}]

this info maybe helpful.

hcbwiz commented 1 year ago

after more tests:

  1. If you ever used "setspn" and "adcli update --add-service-principal=cifs/vhost.test.com --domain=TEST.COM", it seems to delete the entry. Otherwise, ktpass will show the warning:

    Failed to set property 'servicePrincipalName' to 'cifs/vhost.test.com' on Dn 'CN=vhost,DC=test,DC=com': 0x13.
    WARNING: Unable to set SPN mapping data.
    If vhost already has an SPN mapping installed for cifs/vhost.test.com, this is no cause for concern.
    WARNING: pType and account type do not match. This might cause problems.     

    you can use the command to check setspn -L vhost note: 'vhost' is the hostname of my ksmbd server.

  2. ktpass -princ cifs/vhost.test.com@TEST.COM -mapuser vhost -crypto all -ptype KRB5_NT_PRINCIPAL +rndPass -out c:\cifs.keytab

    Then modify the ksmbd.conf to use the keytab directly

ksmbd can start!!

root@vhost:/etc/ksmbd# KRB5_TRACE=/dev/stdout /usr/local/sbin/ksmbd.mountd -v -n
[ksmbd-worker/3653]: DEBUG: New user `test'
[ksmbd-worker/3653]: DEBUG: New share `IPC$'
[ksmbd-worker/3653]: DEBUG: New share `mnt'
[ksmbd-worker/3653]: DEBUG: New user `nobody'
[3653] 1674025209.702197: Getting initial credentials for cifs/vhost.test.com@
[3653] 1674025209.702198: Found entries for cifs/vhost.test.com@TEST.COM in keytab: rc4-hmac, aes256-cts, aes128-cts
[3653] 1674025209.702200: Sending unauthenticated request
[3653] 1674025209.702201: Sending request (214 bytes) to TEST.COM
[3653] 1674025209.702202: Initiating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702203: Sending TCP request to stream 10.252.165.204:88
[3653] 1674025209.702204: Received answer (190 bytes) from stream 10.252.165.204:88
[3653] 1674025209.702205: Terminating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702206: Response was from primary KDC
[3653] 1674025209.702207: Received error from KDC: -1765328359/Additional pre-authentication required
[3653] 1674025209.702210: Preauthenticating using KDC method data
[3653] 1674025209.702211: Processing preauth types: PA-PK-AS-REQ (16), PA-PK-AS-REP_OLD (15), PA-ETYPE-INFO2 (19), PA-ENC-TIMESTAMP (2)
[3653] 1674025209.702212: Selected etype info: etype aes256-cts, salt "TEST.COMcifsvhost.test.com", params ""
[3653] 1674025209.702213: PKINIT client has no configured identity; giving up
[3653] 1674025209.702214: Preauth module pkinit (16) (real) returned: -1765328174/No pkinit_anchors supplied
[3653] 1674025209.702215: Retrieving cifs/vhost.test.com@TEST.COM from FILE:/etc/ksmbd/cifs.keytab (vno 0, enctype aes256-cts) with result: 0/Success
[3653] 1674025209.702216: AS key obtained for encrypted timestamp: aes256-cts/87B3
[3653] 1674025209.702218: Encrypted timestamp (for 1674025212.197550): plain 301AA011180F32303233303131383037303031325AA10502030303AE, encrypted 81086C5C7B2047448E69C591C53B1595B4FB384F96A4A8806C211238E6E5E7C23E7CEA96B0129C0F13AC1DCF8042A68B884E57FBE4D67CE6
[3653] 1674025209.702219: Preauth module encrypted_timestamp (2) (real) returned: 0/Success
[3653] 1674025209.702220: Produced preauth for next request: PA-ENC-TIMESTAMP (2)
[3653] 1674025209.702221: Sending request (294 bytes) to TEST.COM
[3653] 1674025209.702222: Initiating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702223: Sending TCP request to stream 10.252.165.204:88
[3653] 1674025209.702224: Received answer (1571 bytes) from stream 10.252.165.204:88
[3653] 1674025209.702225: Terminating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702226: Response was from primary KDC
[3653] 1674025209.702227: Processing preauth types: PA-ETYPE-INFO2 (19)
[3653] 1674025209.702228: Selected etype info: etype aes256-cts, salt "TEST.COMcifsvhost.test.com", params ""
[3653] 1674025209.702229: Produced preauth for next request: (empty)
[3653] 1674025209.702230: AS key determined by preauth: aes256-cts/87B3
[3653] 1674025209.702231: Decrypted AS reply; session key is: aes256-cts/AAA1
[3653] 1674025209.702232: FAST negotiation: unavailable
[3653] 1674025209.702233: Getting initial credentials for cifs/vhost.test.com@
[3653] 1674025209.702234: Found entries for cifs/vhost.test.com@TEST.COM in keytab: rc4-hmac, aes256-cts, aes128-cts
[3653] 1674025209.702236: Sending unauthenticated request
[3653] 1674025209.702237: Sending request (214 bytes) to TEST.COM
[3653] 1674025209.702238: Initiating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702239: Sending TCP request to stream 10.252.165.204:88
[3653] 1674025209.702240: Received answer (190 bytes) from stream 10.252.165.204:88
[3653] 1674025209.702241: Terminating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702242: Response was from primary KDC
[3653] 1674025209.702243: Received error from KDC: -1765328359/Additional pre-authentication required
[3653] 1674025209.702246: Preauthenticating using KDC method data
[3653] 1674025209.702247: Processing preauth types: PA-PK-AS-REQ (16), PA-PK-AS-REP_OLD (15), PA-ETYPE-INFO2 (19), PA-ENC-TIMESTAMP (2)
[3653] 1674025209.702248: Selected etype info: etype aes256-cts, salt "TEST.COMcifsvhost.test.com", params ""
[3653] 1674025209.702249: PKINIT client has no configured identity; giving up
[3653] 1674025209.702250: Preauth module pkinit (16) (real) returned: -1765328174/No pkinit_anchors supplied
[3653] 1674025209.702251: Retrieving cifs/vhost.test.com@TEST.COM from FILE:/etc/ksmbd/cifs.keytab (vno 0, enctype aes256-cts) with result: 0/Success
[3653] 1674025209.702252: AS key obtained for encrypted timestamp: aes256-cts/87B3
[3653] 1674025209.702254: Encrypted timestamp (for 1674025212.201551): plain 301AA011180F32303233303131383037303031325AA105020303134F, encrypted D36B8F6E6D9329BD7677DBCC27BDF2B8E0E3C2F21E0A1E9972BB468D623CEAFB1F90F79C83507EC9493159F589BB4BD61AF894B48CBB67A7
[3653] 1674025209.702255: Preauth module encrypted_timestamp (2) (real) returned: 0/Success
[3653] 1674025209.702256: Produced preauth for next request: PA-ENC-TIMESTAMP (2)
[3653] 1674025209.702257: Sending request (294 bytes) to TEST.COM
[3653] 1674025209.702258: Initiating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702259: Sending TCP request to stream 10.252.165.204:88
[3653] 1674025209.702260: Received answer (1571 bytes) from stream 10.252.165.204:88
[3653] 1674025209.702261: Terminating TCP connection to stream 10.252.165.204:88
[3653] 1674025209.702262: Response was from primary KDC
[3653] 1674025209.702263: Processing preauth types: PA-ETYPE-INFO2 (19)
[3653] 1674025209.702264: Selected etype info: etype aes256-cts, salt "TEST.COMcifsvhost.test.com", params ""
[3653] 1674025209.702265: Produced preauth for next request: (empty)
[3653] 1674025209.702266: AS key determined by preauth: aes256-cts/87B3
[3653] 1674025209.702267: Decrypted AS reply; session key is: aes256-cts/B058
[3653] 1674025209.702268: FAST negotiation: unavailable
wangyugui-e16 commented 1 year ago

ksmbd can start here too. Thanks a lot.

the next step maybe the auth and id mapping.

a segment fault happen when wrong 'kerberos service name =' wrong: kerberos service name = cifs/vhost.test.com right: kerberos service name = cifs/test.com

hcbwiz commented 1 year ago

I suppose we can setup a windows client which has been Joined to the same domain.

In my understanding, when a user logins into the client, The user can get krb5 ticket to access cifs service directly without another login process.

According to the above discussion, ksmbd still needs a local user database.

So we can create the accounts in Windows AD and local database with the same user name first.

Then the authentication part maybe work

For id mapping, the ksmbd server has been joined to the domain by sssd/realm. Ksmbd may adapt to it by setuid?

For ACL, ldap or kerbose may query the information. Still need to survey it

wangyugui-e16 commented 1 year ago

for windows client, if it already joined the domain, then it can access ksmbd service without password input. for windows client, if it yet not join the domain, then it can access ksmbd service with the username/password input.

windows SID is 128bit, and it is not used since small value. linux uid is 32bit(?), and it is used since small value. so we need a id mapping.

sssd-ad have 2 id mapping policies

winbind have many policies. such as idmap_ad, idmap_rid.

the id mapping is not an part of krb5, it is a part of sssd/winbind.

If the user direcly ssh login, the he can direct access the filesystem behind ksmb.

so we need to make the id mapping of ksmb and sssd-ad/ssh to be same?

hcbwiz commented 1 year ago

for windows client, if it yet not join the domain, then it can access ksmbd service with the username/password input.

I suppose the windows client will fallback to use NTLM, but I have no idea how ksmbd/ssd authenticate it with windows AD.

About ID mapping, I'm not familiar with this area.

root@vhost:~# id vhost@test.com
uid=756601112(vhost@test.com) gid=756600513(domain users@test.com) groups=756600513(domain users@test.com)
root@vhost:~# id administrator@test.com
uid=756600500(administrator@test.com) gid=756600513(domain users@test.com) groups=756600513(domain users@test.com),756600518(schema admins@test.com),756600520(group policy creator owners@test.com),756600519(enterprise admins@test.com),756600572(denied rodc password replication group@test.com),756600512(domain admins@test.com)

sssd can translate SID to UID.

I think ksmbd can create files on the locale filesystem with the mapped "UID/GID"

In the other hand, how ksmbd/SMB represents "file and ID mapping" to the windows client? I have no idea about it so far. Or is it just related to file ACL?

wangyugui-e16 commented 1 year ago

'/usr/bin/id' can translate SID to UID when login in as local user. so we can do same job(code) in ksmbd to translate SID to UID.

The real job will be done by sssd/winbind, we just call like /usr/bin/id. It will be easy than what I expected.

when sssd, we call id as 'id u2001@e16-tech' when winbind, we call id 'id u2001' we need try both name policies.

wangyugui-e16 commented 1 year ago

one question about krb5_keytab_file,

why kpasswd don't need krb5_keytab_file? but ksmbd-tools need it?

hcbwiz commented 1 year ago

'/usr/bin/id' can translate SID to UID when login in as local user. so we can do same job(code) in ksmbd to translate SID to UID.

The real job will be done by sssd/winbind, we just call like /usr/bin/id. It will be easy than what I expected.

when sssd, we call id as 'id u2001@e16-tech' when winbind, we call id 'id u2001' we need try both name policies.

after joining the domain: modify /etc/sssd/sssd.conf: use_fully_qualified_names = False systemctl restart sssd

root@vhost:~# id administrator
uid=756600500(administrator) gid=756600513(domain users) groups=756600513(domain users),756600520(group policy creator owners),756600512(domain admins),756600518(schema admins),756600519(enterprise admins),756600572(denied rodc password replication group)

Then I create a file from a windows client: 圖片

But it is correct in the local FS: 圖片

wangyugui-e16 commented 1 year ago

sssd-ad can be used for 'Windows SID to linux uid/gid mapping'. but there is yet no well-known API defined for 'linux uid/gid to Windows SID mapping'?

hcbwiz commented 1 year ago

About ksmbd KRB5 authentication with windows AD,, I have figured out more details:

Windows system have two different account types: Computer and User.

Thus, it needs to use a " a dollar sign ($)" for ktpass to specify a Computer account: ktpass -princ cifs/vhost.test.com@TEST.COM -mapuser vhost$@test.com -crypto all -ptype KRB5_NT_PRINCIPAL +rndPass -out c:\cifs.keytab

hcbwiz commented 1 year ago

So far, krb5 authentication is still not working.

If I use IP to connect the ksmbd server, it can fallback NTLM authentication with local database. However, if I use hostname(\\vhost.test.com\mnt) to connect, it shows the error messages from ksmbd.mountd

[2334] 1675152377.871649: Retrieving cifs/vhost.test.com@TEST.COM from FILE:/etc/ksmbd/cifs.keytab (vno 3, enctype aes256-cts) with result: 0/Success
[2334] 1675152377.871650: Failed to decrypt AP-REQ ticket: -1765328353/Cannot decrypt ticket for cifs/vhost.test.com@TEST.COM using keytab key for cifs/vhost.test.com@TEST.COM
[ksmbd-worker/2334]: ERROR: Cannot decrypt ticket for cifs/vhost.test.com@TEST.COM using keytab key for cifs/vhost.test.com@TEST.COM: while decoding AP_REQ with cifs/vhost.test.com@TEST.COM creds
[ksmbd-worker/2334]: INFO: Error authenticating
wangyugui-e16 commented 1 year ago

'mount.nfs -o seck=krb5' works with 'setspn.exe -S nfs/T3610.e16-tech.com T3610' instead of 'ktpass.exe'. what will happen for ksmbd if 'setspn.exe -S cifs/T3610.e16-tech.com T3610' instead of 'ktpass.exe'.

hcbwiz commented 1 year ago

'mount.nfs -o seck=krb5' works with 'setspn.exe -S nfs/T3610.e16-tech.com T3610' instead of 'ktpass.exe'. what will happen for ksmbd if 'setspn.exe -S cifs/T3610.e16-tech.com T3610' instead of 'ktpass.exe'.

ksmbd server with krb5 authentication needs a "keytab" to decrypt the ticket which comes from a client.

currently, krb5 authentication can work in my environment:

  1. create an admin user account: cifsadmin
  2. use the account to "realm join"
  3. use ktpass to generate a keytab which is mapped to the same account: cifsadmin ktpass -princ cifs/vhost.test.com@TEST.COM -mapUser cifsadmin@test.com -pass pass1234 -crypto all -pType KRB5_NT_PRINCIPAL -out c:\cifs.keytab

    the ksmbd.mountd with KRB5_TRACE:

    KRB5_TRACE=/dev/stdout /usr/local/sbin/ksmbd.mountd -v -n

    [646] 1675218330.676792: Retrieving cifs/vhost.test.com@TEST.COM from FILE:/etc/ksmbd/cifs.keytab (vno 3, enctype rc4-hmac) with result: 0/Success
    [646] 1675218330.676793: Decrypted AP-REQ with specified server principal cifs/vhost.test.com@TEST.COM: rc4-hmac/C385
    [646] 1675218330.676794: AP-REQ ticket: Administrator@TEST.COM -> cifs/vhost.test.com@TEST.COM, session key rc4-hmac/781B
    [646] 1675218330.676795: Negotiated enctype based on authenticator: aes256-cts
    [646] 1675218330.676796: Authenticator contains subkey: rc4-hmac/93E1
    [646] 1675218330.676797: Creating AP-REP, time 1675218359.2735, subkey rc4-hmac/93E1, seqnum 0
    [ksmbd-worker/646]: INFO: Authenticated user `Administrator'

    Note:

    1. It sill need to add the corresponding account into the local DB.
    2. apply the patch:

      
      diff --git a/tools/management/spnego_krb5.c b/tools/management/spnego_krb5.c
      index e71d3aa..02efe38 100644
      --- a/tools/management/spnego_krb5.c
      +++ b/tools/management/spnego_krb5.c
      @@ -153,7 +153,7 @@ static krb5_error_code acquire_creds_from_keytab(krb5_context context,
      }
      
      retval = krb5_sname_to_principal(context, host_name, service_name,
      -                       KRB5_NT_UNKNOWN, &sprinc);
      +                       KRB5_NT_SRV_HST, &sprinc);
      if (retval) {
              pr_krb5_err(context, retval, "while generating service name\n");
              goto out_err;

3. make sure enable **CONFIG_SMB_SERVER_KERBEROS5** when you compile the ksmbd module
wangyugui-e16 commented 1 year ago

When diag 'mount.nfs -o seck=krb5' , I noticed that there are some design in windows ad maby different from other krb5.

so many documents are based on ktpass. but failed to works here. Figure 5 in https://www.delltechnologies.com/asset/en-us/products/storage/industry-market/h17769_integrating_onefs_with_kerberos_wp.pdf give me some idea of 'setspn.exe'.

and another point from hcbwiz is very important too. Windows system have two different account types: Computer and User. Thus, it needs to use a " a dollar sign ($)" for ktpass to specify a Computer account:

"kinit -k 'nfs/T3610@E16-TECH.COM'" check is in so many documents. but it seem that we need "kinit -k 'T3610$@E16-TECH.COM'".

# klist -kt
Keytab name: FILE:/etc/krb5.keytab
KVNO Timestamp           Principal
---- ------------------- ------------------------------------------------------
   5 01/31/2023 23:55:51 T3610$@E16-TECH.COM
   5 01/31/2023 23:55:51 T3610$@E16-TECH.COM
   5 01/31/2023 23:55:51 host/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 host/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 host/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 host/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 RestrictedKrbHost/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 RestrictedKrbHost/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 RestrictedKrbHost/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 RestrictedKrbHost/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 cifs/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 cifs/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 cifs/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 cifs/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 nfs/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 nfs/T3610.e16-tech.com@E16-TECH.COM
   5 01/31/2023 23:55:51 nfs/T3610@E16-TECH.COM
   5 01/31/2023 23:55:51 nfs/T3610@E16-TECH.COM`

default /etc/krb5.keytab should be OK. we don't need another krb5.keytab.

CONFIG_SMB_SERVER_KERBEROS5 is defined here.

hcbwiz commented 1 year ago

I suppose ktpass also implies "set service principal name". After executing ktpass, you can use setspn -L 'account name' to check it.

krb5 authentication is also one kind of single-sign-on mechanism. Both of client and server need to communicate with the KDC (windows AD)

wangyugui-e16 commented 1 year ago

windows ad

C:\Users\Administrator>setspn -L T3610$
Registered ServicePrincipalNames for CN=T3610,CN=Computers,DC=e16-tech,DC=com:
        cifs/T3610
        cifs/T3610.e16-tech.com
        nfs/T3610.e16-tech.com
        nfs/T3610
        RestrictedKrbHost/T3610.e16-tech.com
        RestrictedKrbHost/T3610
        host/T3610.e16-tech.com
        host/T3610

linux client

[root@T3610 ~]# klist -kt
Keytab name: FILE:/etc/krb5.keytab
KVNO Timestamp           Principal
---- ------------------- ------------------------------------------------------
   8 02/01/2023 17:07:05 T3610$@E16-TECH.COM
   8 02/01/2023 17:07:05 T3610$@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610@E16-TECH.COM
[root@T3610 ~]# kinit -k 'T3610$@E16-TECH.COM'
[root@T3610 ~]# kinit -k 'cifs/T3610@E16-TECH.COM'
kinit: Client 'cifs/T3610@E16-TECH.COM' not found in Kerberos database while getting initial credentials
[root@T3610 ~]#
hcbwiz commented 1 year ago

windows ad

C:\Users\Administrator>setspn -L T3610$
Registered ServicePrincipalNames for CN=T3610,CN=Computers,DC=e16-tech,DC=com:
        cifs/T3610
        cifs/T3610.e16-tech.com
        nfs/T3610.e16-tech.com
        nfs/T3610
        RestrictedKrbHost/T3610.e16-tech.com
        RestrictedKrbHost/T3610
        host/T3610.e16-tech.com
        host/T3610

How did you create such SPNs? cifs/xxxxx nfs/xxxx

[root@T3610 ~]# klist -kt
Keytab name: FILE:/etc/krb5.keytab
KVNO Timestamp           Principal
---- ------------------- ------------------------------------------------------
   8 02/01/2023 17:07:05 T3610$@E16-TECH.COM
   8 02/01/2023 17:07:05 T3610$@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 host/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 RestrictedKrbHost/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 cifs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610.e16-tech.com@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610@E16-TECH.COM
   8 02/01/2023 17:07:05 nfs/T3610@E16-TECH.COM
[root@T3610 ~]# kinit -k 'T3610$@E16-TECH.COM'
[root@T3610 ~]# kinit -k 'cifs/T3610@E16-TECH.COM'
kinit: Client 'cifs/T3610@E16-TECH.COM' not found in Kerberos database while getting initial credentials
[root@T3610 ~]#

Is it okay to do "kinit -k 'nfs/T3610.e16-tech.com'"?

As I know, realm uses "adcli join" to create a "computer account". However, it seems that using "adcli update" to create new SPNs won't be added to the "Kerberos database" in Windows AD.

There are two alternative tools can work as "AD clients" in Linux : samba-tool and mkutils, but I never try it. I just use ktpass.exe in my windows 2016 server directly.

The other issue is that: With Kerberos authentication, the "Kerberos service account" uses "kerberos service keytab" to authenticate the client tickets. However, there are two types : Computer Account and User Account in Windows AD that can act as Kerberos service account. When using a Computer Account, I have no idea to let it work so far.

wangyugui-e16 commented 1 year ago

How did you create such SPNs? setspn.exe -S nfs/T3610 T3610; setspn.exe -S nfs/T3610.e16-tech.com T3610 setspn.exe -S cifs/T3610 T3610; setspn.exe -S cifs/T3610.e16-tech.com T3610

Is it okay to do "kinit -k 'nfs/T3610.e16-tech.com'"? "kinit -k 'nfs/T3610.e16-tech.com'" failed.

wangyugui-e16 commented 1 year ago

failed to access https://access.redhat.com/solutions/6972993

Now still re-joining domain to flush SPN to client /etc/krb5.keytab.

hcbwiz commented 1 year ago

'setspn' just binds a service principal name (SPN) to the user account. If you don't call ktpass to generate keytab, it won't to be added into "Kerberos database" of Windows AD.

Note: You need not perform setspn separately since ktpass does it automatically when creating a keytab file.

I guess the keytab in your linux client is generated by "realm join".

"realm join" calls adcli (an AD client tool) to create a Computer counts and do related thing for "host/xxxx". Then adcli can generates the keytab for all SPNs for this account. However, the others SPNs you manually created by setspn haven't been added into "kerberos database".

In brief, "binding a SPN to an account" and "add it into the Kerberos database of Windows AD" are necessary.

hcbwiz commented 1 year ago

About id mapping API, there are two libraries: libsss-idmap and libsss-nss-idmap

I try libsss-nss-idmap:

#include <sss_nss_idmap.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
        char *sid = NULL;
        enum sss_id_type type;
        int ret;

        ret = sss_nss_getsidbyname("administrator", &sid, &type);
        printf("ret: %d, sid: %s, type: %d\n", ret, sid, type);
        free(sid);
}

output: ret: 0, sid: S-1-5-21-3675874838-1964521148-1538075311-500, type: 1

wangyugui-e16 commented 1 year ago

thanks a lot for the info 'libsss-idmap and libsss-nss-idmap'.

I movded the uid to windows SID mapping to #189

wangyugui-e16 commented 1 year ago

a patch try to auto config krb5 0002-krb5-auto-config.patch

namjaejeon commented 1 year ago

@wangyugui-e16 Thanks for your patch:)

@atheik Atte, Do you have the time to review this patch(0002-krb5-auto-config.patch) ?

atheik commented 1 year ago

@wangyugui-e16, @namjaejeon,

@atheik Atte, Do you have the time to review this patch(0002-krb5-auto-config.patch) ?

You bypass krb5_kt_default() in acquire_creds_from_keytab() entirely with your changes to setup_krb5_ctx(). If the intention is to check whether the keytab file exists, then why not check it with krb5_kt_have_content() after resolving the keytab in acquire_creds_from_keytab()? The changes to setup_mskrb5() and cleanup_krb5() do not make sense, since mech_ctx->params.krb5.service_name can be NULL in non-fallback scenarios. Could you please also write a proper commit message and give more context there?

Comments https://github.com/namjaejeon/ksmbd-tools/issues/187#issuecomment-1374339878 and https://github.com/namjaejeon/ksmbd-tools/issues/187#issuecomment-1374679369 still apply to this patch. I don't think configuration issues warrant adding a silent fallback like this.

wangyugui-e16 commented 1 year ago

it seems that nfs-utils-2.6.2/utils/gssd/krb5_util.c is a good example to auto config principal_name and realm.

krb5_appdefault_string() krb5_get_default_realm() krb5_build_principal_ext() ...