diff --git a/changelog/unreleased/ldap-escape-dn.md b/changelog/unreleased/ldap-escape-dn.md new file mode 100644 index 00000000000..78e38cd5fde --- /dev/null +++ b/changelog/unreleased/ldap-escape-dn.md @@ -0,0 +1,6 @@ +Bugfix: Escape DN attribute value + +Escaped the DN attribute value on creating users and groups. + + +https://github.com/owncloud/ocis/pull/4117 diff --git a/ocis-pkg/ldap/ldap.go b/ocis-pkg/ldap/ldap.go index 8eceaf3cb94..cfa452f1a5d 100644 --- a/ocis-pkg/ldap/ldap.go +++ b/ocis-pkg/ldap/ldap.go @@ -5,6 +5,7 @@ import ( "errors" "io/ioutil" "os" + "strings" "time" "github.com/owncloud/ocis/v2/ocis-pkg/log" @@ -15,6 +16,20 @@ const ( caCheckSleep = 2 ) +var ( + dnEscaper = strings.NewReplacer( + "\\", "\\\\", + ",", "\\,", + "+", "\\+", + `"`, `\\"`, + "<", "\\<", + ">", "\\>", + ";", "\\;", + "=", "\\=", + "\000", "\\00", + ) +) + func WaitForCA(log log.Logger, insecure bool, caCert string) error { if !insecure && caCert != "" { for i := 0; i < caCheckRetries; i++ { @@ -38,3 +53,20 @@ func WaitForCA(log log.Logger, insecure bool, caCert string) error { } return nil } + +// EscapeDNAttributeValue escapes special characters in an attribute value as [described in RFC4514](https://datatracker.ietf.org/doc/html/rfc4514). +func EscapeDNAttributeValue(v string) string { + if v == "" { + return v + } + + v = dnEscaper.Replace(v) + + if strings.HasSuffix(v, " ") { + v = v[:len(v)-1] + "\\ " + } + if strings.HasPrefix(v, "#") || strings.HasPrefix(v, " ") { + v = "\\" + v + } + return v +} diff --git a/ocis-pkg/ldap/ldap_suite_test.go b/ocis-pkg/ldap/ldap_suite_test.go new file mode 100644 index 00000000000..3eee47856d2 --- /dev/null +++ b/ocis-pkg/ldap/ldap_suite_test.go @@ -0,0 +1,13 @@ +package ldap_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestLdap(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Ldap Suite") +} diff --git a/ocis-pkg/ldap/ldap_test.go b/ocis-pkg/ldap/ldap_test.go new file mode 100644 index 00000000000..d3ee3152cfb --- /dev/null +++ b/ocis-pkg/ldap/ldap_test.go @@ -0,0 +1,25 @@ +package ldap_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/owncloud/ocis/v2/ocis-pkg/ldap" +) + +var _ = Describe("ldap", func() { + DescribeTable("EscapeDNAttributeValue should escape special characters", + func(input, expected string) { + escaped := ldap.EscapeDNAttributeValue(input) + Expect(escaped).To(Equal(expected)) + }, + Entry("normal dn", "foobar", "foobar"), + Entry("including comma", "foo,bar", "foo\\,bar"), + Entry("including equals", "foo=bar", "foo\\=bar"), + Entry("beginning with number sign", "#foobar", "\\#foobar"), + Entry("beginning with space", " foobar", "\\ foobar"), + Entry("only one space", " ", "\\ "), + Entry("two spaces", " ", "\\ \\ "), + Entry("ending with space", "foobar ", "foobar\\ "), + Entry("containing multiple special chars", "f+o>o,bo\,b\