diff options
author | Will Rouesnel <wrouesnel@wrouesnel.com> | 2023-05-10 15:52:02 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-10 07:52:02 +0200 |
commit | b2fb2ef276e38405e358c6be8a32d41de609ee00 (patch) | |
tree | 4d2ef6d4d5d23a62c5f61ecc5f775e7c6c81176d | |
parent | e136d11dce15bb268943c5334db88d3a9884f29f (diff) |
lib/api: Allow BindDN to exclude any username formatting (fixes #8899) (#8900)
This allows a syncthing instance to be locked to exactly 1 user without
needing search capability on the LDAP instance.
-rw-r--r-- | lib/api/api_auth.go | 11 | ||||
-rw-r--r-- | lib/api/api_auth_test.go | 20 |
2 files changed, 30 insertions, 1 deletions
diff --git a/lib/api/api_auth.go b/lib/api/api_auth.go index e84ae645e4..ad3d86638f 100644 --- a/lib/api/api_auth.go +++ b/lib/api/api_auth.go @@ -161,7 +161,7 @@ func authLDAP(username string, password string, cfg config.LDAPConfiguration) bo defer connection.Close() - err = connection.Bind(fmt.Sprintf(cfg.BindDN, username), password) + err = connection.Bind(ldapTemplateBindDN(cfg.BindDN, username), password) if err != nil { l.Warnln("LDAP Bind:", err) return false @@ -199,6 +199,15 @@ func authLDAP(username string, password string, cfg config.LDAPConfiguration) bo return true } +func ldapTemplateBindDN(bindDN string, username string) string { + // Check if formatting directives are included in the ldapTemplateBindDN - if so add username. + // (%%s is a literal %s - unlikely for LDAP, but easy to handle here). + if strings.Count(bindDN, "%s") != strings.Count(bindDN, "%%s") { + bindDN = fmt.Sprintf(bindDN, username) + } + return bindDN +} + // Convert an ISO-8859-1 encoded byte string to UTF-8. Works by the // principle that ISO-8859-1 bytes are equivalent to unicode code points, // that a rune slice is a list of code points, and that stringifying a slice diff --git a/lib/api/api_auth_test.go b/lib/api/api_auth_test.go index 046b06a077..be6a0c3a80 100644 --- a/lib/api/api_auth_test.go +++ b/lib/api/api_auth_test.go @@ -45,3 +45,23 @@ func TestStaticAuthPasswordFail(t *testing.T) { t.Fatalf("should fail auth") } } + +func TestAuthLDAPSendsCorrectBindDNWithTemplate(t *testing.T) { + t.Parallel() + + templatedDn := ldapTemplateBindDN("cn=%s,dc=some,dc=example,dc=com", "username") + expectedDn := "cn=username,dc=some,dc=example,dc=com" + if expectedDn != templatedDn { + t.Fatalf("ldapTemplateBindDN should be %s != %s", expectedDn, templatedDn) + } +} + +func TestAuthLDAPSendsCorrectBindDNWithNoTemplate(t *testing.T) { + t.Parallel() + + templatedDn := ldapTemplateBindDN("cn=fixedusername,dc=some,dc=example,dc=com", "username") + expectedDn := "cn=fixedusername,dc=some,dc=example,dc=com" + if expectedDn != templatedDn { + t.Fatalf("ldapTemplateBindDN should be %s != %s", expectedDn, templatedDn) + } +} |