Hello Folks,
I'm currently setting up sssd (Debian 1.16.3) on Debian Buster 10.0 and I ran into a problem that I was able to trace down to the domain permission/security settings that placed the users into a special OU that machine accounts can't read.
First a bit of background: Currently, there's a way to use winbind + friends in order to join and auth users on the domain. But due to limitations (unreliable no home directories, gid/uid mapping issues, etc.), I want to give sssd a try and I tested this with both of the current Debian sssd version 1.16.3 and 2.2.0-4 (from unstable / sid / rolling release).
I successfully used the "realm" utility to discover and setup the sssd.conf === # realm discover -v DOMAIN (named changed) * Resolving: _ldap._tcp.domain * Performing LDAP DSE lookup on: 1x.y.z.1 * Performing LDAP DSE lookup on: 1z.a.b.c * Performing LDAP DSE lookup on: 1d.e.f.g * Successfully discovered: domain domain type: kerberos realm-name: DOMAIN domain-name: domain configured: no 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
# realm join -v -U me@DOMAIN domain * Resolving: _ldap._tcp.domain * Performing LDAP DSE lookup on: 1x.y.z.1 * Performing LDAP DSE lookup on: 1z.a.b.c * Performing LDAP DSE lookup on: 1d.e.f.g * Successfully discovered: domain Password for me@DOMAIN: ******* * Unconditionally checking packages * Resolving required packages [...] * Generated 120 character computer password * Using keytab: FILE:/etc/krb5.keytab * Found computer account for COMPUTER * Set computer password * Retrieved kvno '14' for computer account in directory: ... * Modifying computer account: userAccountControl * Modifying computer account: operatingSystemVersion, operatingSystemServicePack * Modifying computer account: userPrincipalName * Cleared old entries from keytab: FILE:/etc/krb5.keytab * Discovered which keytab salt to use * Added the entries to the keytab: ... * /usr/sbin/update-rc.d sssd enable * /usr/sbin/service sssd restart * Successfully enrolled machine in realm ===
/etc/sssd/sssd.conf
[sssd] domains = domain config_file_version = 2 services = nss, pam, ifp # added ifp
[domain/domain] ad_domain = domain krb5_realm = DOMAIN realmd_tags = manages-system joined-with-adcli cache_credentials = True id_provider = ad krb5_store_password_if_offline = True default_shell = /bin/bash ldap_id_mapping = True use_fully_qualified_names = True fallback_homedir = /home/%u@%d access_provider = ad ===
klist shows a valid ticket and everything seemed to be working.
But when I was trying to login (yes, I made sure that my time is synced and I made sure /etc/nssswitch.conf was correct) with my "me@domain" login it never worked. I tried also id me@domain and sssctl (had to add ifp, seems like realm doesn't add) but it wasn't working for my login.
After trying a lot of different combinations with different id, auth_providers and ldap I discovered that the AD Server is setup in such a way (probably due to DSVGO) that the Domain-PC Accounts are not allowed to read from the OU where all the staff users are placed. And indeed, when I copied the exact search query from the sssd_domain log with debug-level 7 and instructed ldapsearch to use GSSAPI with the Domain-PC ticket I always got a "not found". However, when I used simple bind with "me@domain" + password auth I got the request worked.
So, I wonder if it is possible to extend sssd in such a way that id lookups could be performed with the provided either a provided user secret instead of the machine secret?
Regards, Christian
On Fri, Jul 26, 2019 at 12:50:16PM +0200, Christian Lamparter wrote:
Hello Folks,
I'm currently setting up sssd (Debian 1.16.3) on Debian Buster 10.0 and I ran into a problem that I was able to trace down to the domain permission/security settings that placed the users into a special OU that machine accounts can't read.
First a bit of background: Currently, there's a way to use winbind + friends in order to join and auth users on the domain. But due to limitations (unreliable no home directories, gid/uid mapping issues, etc.), I want to give sssd a try and I tested this with both of the current Debian sssd version 1.16.3 and 2.2.0-4 (from unstable / sid / rolling release).
I successfully used the "realm" utility to discover and setup the sssd.conf === # realm discover -v DOMAIN (named changed)
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
domain type: kerberos realm-name: DOMAIN domain-name: domain configured: no 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
# realm join -v -U me@DOMAIN domain
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
Password for me@DOMAIN: *******
- Unconditionally checking packages
- Resolving required packages
[...]
- Generated 120 character computer password
- Using keytab: FILE:/etc/krb5.keytab
- Found computer account for COMPUTER
- Set computer password
- Retrieved kvno '14' for computer account in directory: ...
- Modifying computer account: userAccountControl
- Modifying computer account: operatingSystemVersion,
operatingSystemServicePack
- Modifying computer account: userPrincipalName
- Cleared old entries from keytab: FILE:/etc/krb5.keytab
- Discovered which keytab salt to use
- Added the entries to the keytab: ...
- /usr/sbin/update-rc.d sssd enable
- /usr/sbin/service sssd restart
- Successfully enrolled machine in realm
===
/etc/sssd/sssd.conf
[sssd] domains = domain config_file_version = 2 services = nss, pam, ifp # added ifp
[domain/domain] ad_domain = domain krb5_realm = DOMAIN realmd_tags = manages-system joined-with-adcli cache_credentials = True id_provider = ad krb5_store_password_if_offline = True default_shell = /bin/bash ldap_id_mapping = True use_fully_qualified_names = True fallback_homedir = /home/%u@%d access_provider = ad ===
klist shows a valid ticket and everything seemed to be working.
But when I was trying to login (yes, I made sure that my time is synced and I made sure /etc/nssswitch.conf was correct) with my "me@domain" login it never worked. I tried also id me@domain and sssctl (had to add ifp, seems like realm doesn't add) but it wasn't working for my login.
After trying a lot of different combinations with different id, auth_providers and ldap I discovered that the AD Server is setup in such a way (probably due to DSVGO) that the Domain-PC Accounts are not allowed to read from the OU where all the staff users are placed. And indeed, when I copied the exact search query from the sssd_domain log with debug-level 7 and instructed ldapsearch to use GSSAPI with the Domain-PC ticket I always got a "not found". However, when I used simple bind with "me@domain" + password auth I got the request worked.
So, I wonder if it is possible to extend sssd in such a way that id lookups could be performed with the provided either a provided user secret instead of the machine secret?
Sorry, not right now. The AD provider presumes that a keytab is used. But there's nothing saying that the keytab must contain a machine account principal. I guess you could create a keytab for some user, even the one you used for the simple bind authentication and then instruct sssd with the help of ldap_sasl_authid to use your custom principal (by default sssd tries to search for principal based on the host name).
btw as a coincidence, I was looking into extending the IPA provider (which has pretty much the same issues as the AD provider) so that a client side certificate could be used. So in future this might also be possible, but not right now..
Hello again,
On Fri, 2019-07-26 at 14:08 +0200, Jakub Hrozek wrote:
On Fri, Jul 26, 2019 at 12:50:16PM +0200, Christian Lamparter wrote:
I'm currently setting up sssd (Debian 1.16.3) on Debian Buster 10.0 and I ran into a problem that I was able to trace down to the domain permission/security settings that placed the users into a special OU that machine accounts can't read.
First a bit of background: Currently, there's a way to use winbind + friends in order to join and auth users on the domain. But due to limitations (unreliable no home directories, gid/uid mapping issues, etc.), I want to give sssd a try and I tested this with both of the current Debian sssd version 1.16.3 and 2.2.0-4 (from unstable / sid / rolling release).
I successfully used the "realm" utility to discover and setup the sssd.conf === # realm discover -v DOMAIN (named changed)
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
domain type: kerberos realm-name: DOMAIN domain-name: domain configured: no 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
# realm join -v -U me@DOMAIN domain
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
Password for me@DOMAIN: *******
- Unconditionally checking packages
- Resolving required packages
[...]
- Generated 120 character computer password
- Using keytab: FILE:/etc/krb5.keytab
- Found computer account for COMPUTER
- Set computer password
- Retrieved kvno '14' for computer account in directory: ...
- Modifying computer account: userAccountControl
- Modifying computer account: operatingSystemVersion,
operatingSystemServicePack
- Modifying computer account: userPrincipalName
- Cleared old entries from keytab: FILE:/etc/krb5.keytab
- Discovered which keytab salt to use
- Added the entries to the keytab: ...
- /usr/sbin/update-rc.d sssd enable
- /usr/sbin/service sssd restart
- Successfully enrolled machine in realm
===
/etc/sssd/sssd.conf
[sssd] domains = domain config_file_version = 2 services = nss, pam, ifp # added ifp
[domain/domain] ad_domain = domain krb5_realm = DOMAIN realmd_tags = manages-system joined-with-adcli cache_credentials = True id_provider = ad krb5_store_password_if_offline = True default_shell = /bin/bash ldap_id_mapping = True use_fully_qualified_names = True fallback_homedir = /home/%u@%d access_provider = ad ===
klist shows a valid ticket and everything seemed to be working.
But when I was trying to login (yes, I made sure that my time is synced and I made sure /etc/nssswitch.conf was correct) with my "me@domain" login it never worked. I tried also id me@domain and sssctl (had to add ifp, seems like realm doesn't add) but it wasn't working for my login.
After trying a lot of different combinations with different id, auth_providers and ldap I discovered that the AD Server is setup in such a way (probably due to DSVGO) that the Domain-PC Accounts are not allowed to read from the OU where all the staff users are placed. And indeed, when I copied the exact search query from the sssd_domain log with debug-level 7 and instructed ldapsearch to use GSSAPI with the Domain-PC ticket I always got a "not found". However, when I used simple bind with "me@domain" + password auth I got the request worked.
So, I wonder if it is possible to extend sssd in such a way that id lookups could be performed with the provided either a provided user secret instead of the machine secret?
Sorry, not right now. The AD provider presumes that a keytab is used. But there's nothing saying that the keytab must contain a machine account principal. I guess you could create a keytab for some user, even the one you used for the simple bind authentication and then instruct sssd with the help of ldap_sasl_authid to use your custom principal (by default sssd tries to search for principal based on the host name).
btw as a coincidence, I was looking into extending the IPA provider (which has pretty much the same issues as the AD provider) so that a client side certificate could be used. So in future this might also be possible, but not right now..
Ok, thanks. I got it working. what I did was to patch (see below, it was for 1.16.3. But yeah I'll stick around since this has limitations) the sdap_auth_send by adding another state parameter that can overwrite sasl_mech logic and instruct the code to instead use the simple ldap bind with a ldap_default_bind_dn and ldap_default_authtok for the id lookups. (sort of like the binddn/bindpw that nslcd has for (all) lookups).
(The ldap_sasl_authid did OK, but on reboot it broke. From what I can tell, it has to do with Debian decision to make /tmp a ramfs and some secrets get are stored there.)
Anyway onwards!
I can finally use login and friends with a twist. Just after the bash banner there's now a "Invalid user name" (I assume it has something to do with the "@domain.dc" in the user login, as well as the borked full user name (it's a guid instead of a name). But ls -al and id, getent passwd are all working. As well as the groups)
Huge Thanks! Christian
--- From 2a0e3a178d9099b55f2d9c01c4aeb67c8bb1e050 Mon Sep 17 00:00:00 2001 From: Christian Lamparter christian.lamparter@isd.uni-stuttgart.de Date: Tue, 30 Jul 2019 18:24:30 +0200 Subject: [PATCH] ad: make it possible to enumerate users behind locked OUs
This patch adds a switch to sdap_auth_send() which allows it to fall back to the simple bind over SASL. This change makes it possible to mitigate specific permission policy that prevents machine accounts in this active directory to directly enumerate the real users. --- src/providers/ipa/ipa_auth.c | 4 ++-- src/providers/ldap/ldap_auth.c | 5 +++-- src/providers/ldap/sdap_async.h | 5 +++-- src/providers/ldap/sdap_async_connection.c | 19 +++++++++++++++---- src/providers/ldap/sdap_id_op.c | 2 +- src/providers/ldap/sdap_online_check.c | 2 +- 6 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 1bd0177..e56a288 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -302,7 +302,7 @@ static void ipa_pam_auth_handler_flag_done(struct tevent_req *subreq) sdap_auth_ctx->opts, sdap_auth_ctx->be, sdap_auth_ctx->service, - true, CON_TLS_ON, true); + true, CON_TLS_ON, true, false); if (subreq == NULL) { state->pd->pam_status = PAM_SYSTEM_ERR; goto done; @@ -362,7 +362,7 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq) SDAP_OPT_TIMEOUT);
subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn, - state->pd->authtok, timeout); + state->pd->authtok, timeout, false); if (subreq == NULL) { goto done; } diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index d40bc94..836bff6 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -693,7 +693,8 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req) subreq = sdap_cli_connect_send(state, state->ev, state->ctx->opts, state->ctx->be, state->sdap_service, false, - use_tls ? CON_TLS_ON : CON_TLS_OFF, false); + use_tls ? CON_TLS_ON : CON_TLS_OFF, false, + false);
if (subreq == NULL) { tevent_req_error(req, ENOMEM); @@ -787,7 +788,7 @@ static void auth_do_bind(struct tevent_req *req) NULL, NULL, state->dn, state->authtok, dp_opt_get_int(state->ctx->opts->basic, - SDAP_OPT_TIMEOUT)); + SDAP_OPT_TIMEOUT), false); if (!subreq) { tevent_req_error(req, ENOMEM); return; diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 6d09aca..c4e0043 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -145,7 +145,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, const char *sasl_user, const char *user_dn, struct sss_auth_token *authtok, - int simple_bind_timeout); + int simple_bind_timeout, + bool force_simple);
errno_t sdap_auth_recv(struct tevent_req *req, TALLOC_CTX *memctx, @@ -196,7 +197,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_service *service, bool skip_rootdse, enum connect_tls force_tls, - bool skip_auth); + bool skip_auth, bool use_simple); int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx, bool *can_retry, diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index 8aacd67..e51a9ee 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -1308,15 +1308,22 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, const char *sasl_user, const char *user_dn, struct sss_auth_token *authtok, - int simple_bind_timeout) + int simple_bind_timeout, + bool force_simple) { struct tevent_req *req, *subreq; struct sdap_auth_state *state; + bool override_mech = false;
req = tevent_req_create(memctx, &state, struct sdap_auth_state); if (!req) return NULL;
- if (sasl_mech) { + if (sasl_mech && force_simple && user_dn && strlen(user_dn)) { + DEBUG(SSSDBG_TRACE_FUNC,, "Overwrite sasl_mech to force simple bind.\n"); + override_mech = true; + } + + if (sasl_mech && !override_mech) { state->is_sasl = true; subreq = sasl_bind_send(state, ev, sh, sasl_mech, sasl_user, NULL); if (!subreq) { @@ -1432,6 +1439,7 @@ struct sdap_cli_connect_state {
enum connect_tls force_tls; bool do_auth; + bool force_simple; bool use_tls; };
@@ -1487,7 +1495,8 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_service *service, bool skip_rootdse, enum connect_tls force_tls, - bool skip_auth) + bool skip_auth, + bool force_simple) { struct sdap_cli_connect_state *state; struct tevent_req *req; @@ -1505,6 +1514,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, state->use_rootdse = !skip_rootdse; state->force_tls = force_tls; state->do_auth = !skip_auth; + state->force_simple = force_simple;
ret = sdap_cli_resolve_next(req); if (ret) { @@ -1881,7 +1891,8 @@ static void sdap_cli_auth_step(struct tevent_req *req) SDAP_SASL_AUTHID), user_dn, authtok, dp_opt_get_int(state->opts->basic, - SDAP_OPT_TIMEOUT)); + SDAP_OPT_TIMEOUT), + state->force_simple); if (!subreq) { tevent_req_error(req, ENOMEM); return; diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c index e7ff546..c7485f7 100644 --- a/src/providers/ldap/sdap_id_op.c +++ b/src/providers/ldap/sdap_id_op.c @@ -495,7 +495,7 @@ static int sdap_id_op_connect_step(struct tevent_req *req) state->id_conn->id_ctx->opts, state->id_conn->id_ctx->be, state->id_conn->service, false, - CON_TLS_DFL, false); + CON_TLS_DFL, false, true);
if (!subreq) { ret = ENOMEM; diff --git a/src/providers/ldap/sdap_online_check.c b/src/providers/ldap/sdap_online_check.c index f721a5f..68b037a 100644 --- a/src/providers/ldap/sdap_online_check.c +++ b/src/providers/ldap/sdap_online_check.c @@ -54,7 +54,7 @@ static struct tevent_req *sdap_online_check_send(TALLOC_CTX *mem_ctx,
subreq = sdap_cli_connect_send(state, be_ctx->ev, id_ctx->opts, be_ctx, id_ctx->conn->service, false, - CON_TLS_DFL, false); + CON_TLS_DFL, false, false); if (subreq == NULL) { ret = ENOMEM; goto immediately;
On Tue, Jul 30, 2019 at 06:42:06PM +0200, Christian Lamparter wrote:
Hello again,
On Fri, 2019-07-26 at 14:08 +0200, Jakub Hrozek wrote:
On Fri, Jul 26, 2019 at 12:50:16PM +0200, Christian Lamparter wrote:
I'm currently setting up sssd (Debian 1.16.3) on Debian Buster 10.0 and I ran into a problem that I was able to trace down to the domain permission/security settings that placed the users into a special OU that machine accounts can't read.
First a bit of background: Currently, there's a way to use winbind + friends in order to join and auth users on the domain. But due to limitations (unreliable no home directories, gid/uid mapping issues, etc.), I want to give sssd a try and I tested this with both of the current Debian sssd version 1.16.3 and 2.2.0-4 (from unstable / sid / rolling release).
I successfully used the "realm" utility to discover and setup the sssd.conf === # realm discover -v DOMAIN (named changed)
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
domain type: kerberos realm-name: DOMAIN domain-name: domain configured: no 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
# realm join -v -U me@DOMAIN domain
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
Password for me@DOMAIN: *******
- Unconditionally checking packages
- Resolving required packages
[...]
- Generated 120 character computer password
- Using keytab: FILE:/etc/krb5.keytab
- Found computer account for COMPUTER
- Set computer password
- Retrieved kvno '14' for computer account in directory: ...
- Modifying computer account: userAccountControl
- Modifying computer account: operatingSystemVersion,
operatingSystemServicePack
- Modifying computer account: userPrincipalName
- Cleared old entries from keytab: FILE:/etc/krb5.keytab
- Discovered which keytab salt to use
- Added the entries to the keytab: ...
- /usr/sbin/update-rc.d sssd enable
- /usr/sbin/service sssd restart
- Successfully enrolled machine in realm
===
/etc/sssd/sssd.conf
[sssd] domains = domain config_file_version = 2 services = nss, pam, ifp # added ifp
[domain/domain] ad_domain = domain krb5_realm = DOMAIN realmd_tags = manages-system joined-with-adcli cache_credentials = True id_provider = ad krb5_store_password_if_offline = True default_shell = /bin/bash ldap_id_mapping = True use_fully_qualified_names = True fallback_homedir = /home/%u@%d access_provider = ad ===
klist shows a valid ticket and everything seemed to be working.
But when I was trying to login (yes, I made sure that my time is synced and I made sure /etc/nssswitch.conf was correct) with my "me@domain" login it never worked. I tried also id me@domain and sssctl (had to add ifp, seems like realm doesn't add) but it wasn't working for my login.
After trying a lot of different combinations with different id, auth_providers and ldap I discovered that the AD Server is setup in such a way (probably due to DSVGO) that the Domain-PC Accounts are not allowed to read from the OU where all the staff users are placed. And indeed, when I copied the exact search query from the sssd_domain log with debug-level 7 and instructed ldapsearch to use GSSAPI with the Domain-PC ticket I always got a "not found". However, when I used simple bind with "me@domain" + password auth I got the request worked.
So, I wonder if it is possible to extend sssd in such a way that id lookups could be performed with the provided either a provided user secret instead of the machine secret?
Sorry, not right now. The AD provider presumes that a keytab is used. But there's nothing saying that the keytab must contain a machine account principal. I guess you could create a keytab for some user, even the one you used for the simple bind authentication and then instruct sssd with the help of ldap_sasl_authid to use your custom principal (by default sssd tries to search for principal based on the host name).
btw as a coincidence, I was looking into extending the IPA provider (which has pretty much the same issues as the AD provider) so that a client side certificate could be used. So in future this might also be possible, but not right now..
Ok, thanks. I got it working. what I did was to patch (see below, it was for 1.16.3. But yeah I'll stick around since this has limitations) the sdap_auth_send by adding another state parameter that can overwrite sasl_mech logic and instruct the code to instead use the simple ldap bind with a ldap_default_bind_dn and ldap_default_authtok for the id lookups. (sort of like the binddn/bindpw that nslcd has for (all) lookups).
(The ldap_sasl_authid did OK, but on reboot it broke. From what I can tell, it has to do with Debian decision to make /tmp a ramfs and some secrets get are stored there.)
Hmm, strange. As long as ldap_sasl_authid corresponds with a principal in the keytab, this should work. There should not be any secrets stored in /tmp afaik..
Anyway onwards!
I can finally use login and friends with a twist. Just after the bash banner there's now a "Invalid user name" (I assume it has something to do with the "@domain.dc" in the user login, as well as the borked full user name (it's a guid instead of a name). But ls -al and id, getent passwd are all working. As well as the groups)
Huge Thanks! Christian
From 2a0e3a178d9099b55f2d9c01c4aeb67c8bb1e050 Mon Sep 17 00:00:00 2001 From: Christian Lamparter christian.lamparter@isd.uni-stuttgart.de Date: Tue, 30 Jul 2019 18:24:30 +0200 Subject: [PATCH] ad: make it possible to enumerate users behind locked OUs
This patch adds a switch to sdap_auth_send() which allows it to fall back to the simple bind over SASL. This change makes it possible to mitigate specific permission policy that prevents machine accounts in this active directory to directly enumerate the real users.
src/providers/ipa/ipa_auth.c | 4 ++-- src/providers/ldap/ldap_auth.c | 5 +++-- src/providers/ldap/sdap_async.h | 5 +++-- src/providers/ldap/sdap_async_connection.c | 19 +++++++++++++++---- src/providers/ldap/sdap_id_op.c | 2 +- src/providers/ldap/sdap_online_check.c | 2 +- 6 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 1bd0177..e56a288 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -302,7 +302,7 @@ static void ipa_pam_auth_handler_flag_done(struct tevent_req *subreq) sdap_auth_ctx->opts, sdap_auth_ctx->be, sdap_auth_ctx->service,
true, CON_TLS_ON, true);
true, CON_TLS_ON, true, false); if (subreq == NULL) { state->pd->pam_status = PAM_SYSTEM_ERR; goto done;@@ -362,7 +362,7 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq) SDAP_OPT_TIMEOUT);
subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn,
state->pd->authtok, timeout);
if (subreq == NULL) { goto done; }state->pd->authtok, timeout, false);diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index d40bc94..836bff6 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -693,7 +693,8 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req) subreq = sdap_cli_connect_send(state, state->ev, state->ctx->opts, state->ctx->be, state->sdap_service, false,
use_tls ? CON_TLS_ON : CON_TLS_OFF, false);
use_tls ? CON_TLS_ON : CON_TLS_OFF, false,false);if (subreq == NULL) { tevent_req_error(req, ENOMEM);
@@ -787,7 +788,7 @@ static void auth_do_bind(struct tevent_req *req) NULL, NULL, state->dn, state->authtok, dp_opt_get_int(state->ctx->opts->basic,
SDAP_OPT_TIMEOUT));
if (!subreq) { tevent_req_error(req, ENOMEM); return;SDAP_OPT_TIMEOUT), false);diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 6d09aca..c4e0043 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -145,7 +145,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, const char *sasl_user, const char *user_dn, struct sss_auth_token *authtok,
int simple_bind_timeout);
int simple_bind_timeout,bool force_simple);errno_t sdap_auth_recv(struct tevent_req *req, TALLOC_CTX *memctx, @@ -196,7 +197,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_service *service, bool skip_rootdse, enum connect_tls force_tls,
bool skip_auth);
bool skip_auth, bool use_simple);int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx, bool *can_retry, diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index 8aacd67..e51a9ee 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -1308,15 +1308,22 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, const char *sasl_user, const char *user_dn, struct sss_auth_token *authtok,
int simple_bind_timeout)
int simple_bind_timeout,bool force_simple){ struct tevent_req *req, *subreq; struct sdap_auth_state *state;
bool override_mech = false;
req = tevent_req_create(memctx, &state, struct sdap_auth_state); if (!req) return NULL;
- if (sasl_mech) {
- if (sasl_mech && force_simple && user_dn && strlen(user_dn)) {
DEBUG(SSSDBG_TRACE_FUNC,, "Overwrite sasl_mech to force simple bind.\n");override_mech = true;- }
- if (sasl_mech && !override_mech) { state->is_sasl = true; subreq = sasl_bind_send(state, ev, sh, sasl_mech, sasl_user, NULL); if (!subreq) {
@@ -1432,6 +1439,7 @@ struct sdap_cli_connect_state {
enum connect_tls force_tls; bool do_auth;
- bool force_simple; bool use_tls;
};
@@ -1487,7 +1495,8 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_service *service, bool skip_rootdse, enum connect_tls force_tls,
bool skip_auth)
bool skip_auth,bool force_simple){ struct sdap_cli_connect_state *state; struct tevent_req *req; @@ -1505,6 +1514,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, state->use_rootdse = !skip_rootdse; state->force_tls = force_tls; state->do_auth = !skip_auth;
state->force_simple = force_simple;
ret = sdap_cli_resolve_next(req); if (ret) {
@@ -1881,7 +1891,8 @@ static void sdap_cli_auth_step(struct tevent_req *req) SDAP_SASL_AUTHID), user_dn, authtok, dp_opt_get_int(state->opts->basic,
SDAP_OPT_TIMEOUT));
SDAP_OPT_TIMEOUT), if (!subreq) { tevent_req_error(req, ENOMEM); return;state->force_simple);diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c index e7ff546..c7485f7 100644 --- a/src/providers/ldap/sdap_id_op.c +++ b/src/providers/ldap/sdap_id_op.c @@ -495,7 +495,7 @@ static int sdap_id_op_connect_step(struct tevent_req *req) state->id_conn->id_ctx->opts, state->id_conn->id_ctx->be, state->id_conn->service, false,
CON_TLS_DFL, false);
CON_TLS_DFL, false, true);if (!subreq) { ret = ENOMEM;
diff --git a/src/providers/ldap/sdap_online_check.c b/src/providers/ldap/sdap_online_check.c index f721a5f..68b037a 100644 --- a/src/providers/ldap/sdap_online_check.c +++ b/src/providers/ldap/sdap_online_check.c @@ -54,7 +54,7 @@ static struct tevent_req *sdap_online_check_send(TALLOC_CTX *mem_ctx,
subreq = sdap_cli_connect_send(state, be_ctx->ev, id_ctx->opts, be_ctx, id_ctx->conn->service, false,
CON_TLS_DFL, false);
if (subreq == NULL) { ret = ENOMEM; goto immediately;CON_TLS_DFL, false, false);-- 2.20.1 _______________________________________________ sssd-users mailing list -- sssd-users@lists.fedorahosted.org To unsubscribe send an email to sssd-users-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-users@lists.fedorahosted.o...
On Wed, 2019-07-31 at 09:26 +0200, Jakub Hrozek wrote:
On Tue, Jul 30, 2019 at 06:42:06PM +0200, Christian Lamparter wrote:
On Fri, 2019-07-26 at 14:08 +0200, Jakub Hrozek wrote:
On Fri, Jul 26, 2019 at 12:50:16PM +0200, Christian Lamparter wrote:
I'm currently setting up sssd (Debian 1.16.3) on Debian Buster 10.0 and I ran into a problem that I was able to trace down to the domain permission/security settings that placed the users into a special OU that machine accounts can't read.
First a bit of background: Currently, there's a way to use winbind + friends in order to join and auth users on the domain. But due to limitations (unreliable no home directories, gid/uid mapping issues, etc.), I want to give sssd a try and I tested this with both of the current Debian sssd version 1.16.3 and 2.2.0-4 (from unstable / sid / rolling release).
I successfully used the "realm" utility to discover and setup the sssd.conf === # realm discover -v DOMAIN (named changed)
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
domain type: kerberos realm-name: DOMAIN domain-name: domain configured: no 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
# realm join -v -U me@DOMAIN domain
- Resolving: _ldap._tcp.domain
- Performing LDAP DSE lookup on: 1x.y.z.1
- Performing LDAP DSE lookup on: 1z.a.b.c
- Performing LDAP DSE lookup on: 1d.e.f.g
- Successfully discovered: domain
Password for me@DOMAIN: *******
- Unconditionally checking packages
- Resolving required packages
[...]
- Generated 120 character computer password
- Using keytab: FILE:/etc/krb5.keytab
- Found computer account for COMPUTER
- Set computer password
- Retrieved kvno '14' for computer account in directory: ...
- Modifying computer account: userAccountControl
- Modifying computer account: operatingSystemVersion,
operatingSystemServicePack
- Modifying computer account: userPrincipalName
- Cleared old entries from keytab: FILE:/etc/krb5.keytab
- Discovered which keytab salt to use
- Added the entries to the keytab: ...
- /usr/sbin/update-rc.d sssd enable
- /usr/sbin/service sssd restart
- Successfully enrolled machine in realm
===
/etc/sssd/sssd.conf
[sssd] domains = domain config_file_version = 2 services = nss, pam, ifp # added ifp
[domain/domain] ad_domain = domain krb5_realm = DOMAIN realmd_tags = manages-system joined-with-adcli cache_credentials = True id_provider = ad krb5_store_password_if_offline = True default_shell = /bin/bash ldap_id_mapping = True use_fully_qualified_names = True fallback_homedir = /home/%u@%d access_provider = ad ===
klist shows a valid ticket and everything seemed to be working.
But when I was trying to login (yes, I made sure that my time is synced and I made sure /etc/nssswitch.conf was correct) with my "me@domain" login it never worked. I tried also id me@domain and sssctl (had to add ifp, seems like realm doesn't add) but it wasn't working for my login.
After trying a lot of different combinations with different id, auth_providers and ldap I discovered that the AD Server is setup in such a way (probably due to DSVGO) that the Domain-PC Accounts are not allowed to read from the OU where all the staff users are placed. And indeed, when I copied the exact search query from the sssd_domain log with debug-level 7 and instructed ldapsearch to use GSSAPI with the Domain-PC ticket I always got a "not found". However, when I used simple bind with "me@domain" + password auth I got the request worked.
So, I wonder if it is possible to extend sssd in such a way that id lookups could be performed with the provided either a provided user secret instead of the machine secret?
Sorry, not right now. The AD provider presumes that a keytab is used. But there's nothing saying that the keytab must contain a machine account principal. I guess you could create a keytab for some user, even the one you used for the simple bind authentication and then instruct sssd with the help of ldap_sasl_authid to use your custom principal (by default sssd tries to search for principal based on the host name).
btw as a coincidence, I was looking into extending the IPA provider (which has pretty much the same issues as the AD provider) so that a client side certificate could be used. So in future this might also be possible, but not right now..
Ok, thanks. I got it working. what I did was to patch (see below, it was for 1.16.3. But yeah I'll stick around since this has limitations) the sdap_auth_send by adding another state parameter that can overwrite sasl_mech logic and instruct the code to instead use the simple ldap bind with a ldap_default_bind_dn and ldap_default_authtok for the id lookups. (sort of like the binddn/bindpw that nslcd has for (all) lookups).
(The ldap_sasl_authid did OK, but on reboot it broke. From what I can tell, it has to do with Debian decision to make /tmp a ramfs and some secrets get are stored there.)
Hmm, strange. As long as ldap_sasl_authid corresponds with a principal in the keytab, this should work. There should not be any secrets stored in /tmp afaik..
No luck with figuring this out. It seems to me (by looking at Windows as well) that the ticket lifetime are extremly short. Is there a better way to listen to the LDAP + Kerberos Messages other than adding printf & friends everywhere? (since this is integrated into debian, I have to rebuild the whole package each time, so debugging take a long time). Wireshark isn't of much use since everything is encrypted. But at least, for the time being the ldap_authtok_password overwrite works well.
Anyway onwards!
I can finally use login and friends with a twist. Just after the bash banner there's now a "Invalid user name" (I assume it has something to do with the "@domain.dc" in the user login, as well as the borked full user name (it's a guid instead of a name). But ls -al and id, getent passwd are all working. As well as the groups)
Ok, I figured this out. This was coming from the pmvarrun (libpam-mount). And indeed it complains about the "@" in the valid_username() function.
So, while not ideal, the sssd.conf option
use_fully_qualified_names = False
removes this thorn.
Cheers, Christian Lamparter
sssd-users@lists.fedorahosted.org