diff --git a/internal/ldap/util.go b/internal/ldap/util.go index 1f428e0..4dd8fbf 100644 --- a/internal/ldap/util.go +++ b/internal/ldap/util.go @@ -16,15 +16,24 @@ func (s *server) entityIDFromDN(dn message.LDAPDN) (string, error) { parts[i] = strings.TrimSpace(parts[i]) } + if len(parts) < 2 { + return "", errors.New("malformed DN") + } + if !strings.HasPrefix(parts[0], "uid=") { return "", errors.New("entity DN must start with uid=") } if parts[1] != "ou=entities" { - return "", errors.New("entity DN is underneath ou=entities") + return "", errors.New("entity DN must be underneath ou=entities") } - for i, p := range parts[2:] { + rest := parts[2:] + if len(rest) != len(s.nc) { + return "", errors.New("queries must be rooted at " + strings.Join(s.nc, ",")) + } + + for i, p := range rest { if p != s.nc[i] { return "", errors.New("queries must be rooted at " + strings.Join(s.nc, ",")) } diff --git a/internal/ldap/util_test.go b/internal/ldap/util_test.go new file mode 100644 index 0000000..6a2071f --- /dev/null +++ b/internal/ldap/util_test.go @@ -0,0 +1,50 @@ +package ldap + +import ( + "testing" + + "github.com/ps78674/goldap/message" +) + +func testServer() *server { + return &server{ + nc: []string{"dc=netauth", "dc=example", "dc=com"}, + } +} + +func TestEntityIDFromDN(t *testing.T) { + s := testServer() + + valid := []struct { + dn string + id string + }{ + {"uid=jsmith,ou=entities,dc=netauth,dc=example,dc=com", "jsmith"}, + {"uid=jsmith, ou=entities, dc=netauth, dc=example, dc=com", "jsmith"}, + } + for _, tc := range valid { + id, err := s.entityIDFromDN(message.LDAPDN(tc.dn)) + if err != nil { + t.Errorf("%q: unexpected error %q", tc.dn, err) + continue + } + if id != tc.id { + t.Errorf("%q: got id %q, want %q", tc.dn, id, tc.id) + } + } + + invalid := []string{ + "", + "uid=jsmith", + "cn=jsmith,ou=entities,dc=netauth,dc=example,dc=com", + "uid=jsmith,ou=groups,dc=netauth,dc=example,dc=com", + "uid=jsmith,ou=entities,dc=netauth", + "uid=jsmith,ou=entities,dc=netauth,dc=example,dc=com,dc=extra", + "uid=jsmith,ou=entities,dc=netauth,dc=other,dc=com", + } + for _, dn := range invalid { + if id, err := s.entityIDFromDN(message.LDAPDN(dn)); err == nil { + t.Errorf("%q: expected an error, got id %q", dn, id) + } + } +}