diff --git a/.golangci.yml b/.golangci.yml index 08fe5a9..a11d46a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,4 +2,4 @@ linters: enable-all: true output: # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - format: code-climate + format: tab diff --git a/setup.go b/setup.go index 33f44f2..8fb4488 100644 --- a/setup.go +++ b/setup.go @@ -1,6 +1,7 @@ package ldap import ( + "fmt" "strconv" "sync" "time" @@ -96,105 +97,118 @@ func ParseStanza(c *caddy.Controller) (*Ldap, error) { ldap.Upstream = upstream.New() for c.NextBlock() { + fmt.Printf("111 %#v\n", c.Val()) switch c.Val() { // RFC 4516 URL case "ldap_url": - c.NextArg() - ldap.ldapURL = c.Val() - continue - case "paging_limit": - c.NextArg() - pagingLimit, err := strconv.ParseUint(c.Val(), 10, 0) - if err != nil { + if !c.NextArg() { return nil, c.ArgErr() } + ldap.ldapURL = c.Val() + case "paging_limit": + if !c.NextArg() { + return nil, c.ArgErr() + } + pagingLimit, err := strconv.ParseUint(c.Val(), 10, 0) + if err != nil { + return nil, c.Errf("paging_limit: %w", err) + } ldap.pagingLimit = uint32(pagingLimit) - continue case "base_dn": - c.NextArg() // ou=ae-dir - ldap.searchRequest.BaseDN = c.Val() - continue + if !c.NextArg() { + return nil, c.ArgErr() + } + ldap.searchRequest.BaseDN = c.Val() // ou=ae-dir case "filter": - c.NextArg() // (objectClass=aeNwDevice) - ldap.searchRequest.Filter = c.Val() - continue + if !c.NextArg() { + return nil, c.ArgErr() + } + ldap.searchRequest.Filter = c.Val() // (objectClass=aeNwDevice) case "attributes": + c.Next() for c.NextBlock() { switch c.Val() { case "fqdn": - c.NextArg() // aeFqdn + if !c.NextArg() { + return nil, c.ArgErr() + } ldap.searchRequest.Attributes = append(ldap.searchRequest.Attributes, c.Val()) - ldap.fqdnAttr = c.Val() - continue + ldap.fqdnAttr = c.Val() // aeFqdn case "ip4": - c.NextArg() // ipHostNumber + if !c.NextArg() { + return nil, c.ArgErr() + } ldap.searchRequest.Attributes = append(ldap.searchRequest.Attributes, c.Val()) - ldap.ip4Attr = c.Val() - continue + ldap.ip4Attr = c.Val() // ipHostNumber default: return nil, c.Errf("unknown attributes property '%s'", c.Val()) } } continue case "username": - c.NextArg() + if !c.NextArg() { + return nil, c.ArgErr() + } ldap.username = c.Val() - continue case "password": - c.NextArg() + if !c.NextArg() { + return nil, c.ArgErr() + } ldap.password = c.Val() - continue case "sasl": - c.NextArg() ldap.sasl = true - continue case "ttl": - c.NextArg() + if !c.NextArg() { + return nil, c.ArgErr() + } ttl, err := time.ParseDuration(c.Val()) if err != nil { - return nil, c.ArgErr() + return nil, c.Errf("ttl: %w", err) } ldap.ttl = ttl - continue case "sync_interval": - c.NextArg() - syncInterval, err := time.ParseDuration(c.Val()) - if err != nil { + if !c.NextArg() { return nil, c.ArgErr() } + syncInterval, err := time.ParseDuration(c.Val()) + if err != nil { + return nil, c.Errf("sync_interval: %w", err) + } ldap.syncInterval = syncInterval - continue case "fallthrough": ldap.Fall.SetZonesFromArgs(c.RemainingArgs()) - continue default: return nil, c.Errf("unknown property '%s'", c.Val()) } } // validate non-default ldap values ... - if ldap.ldapURL == "" || &ldap.ldapURL == nil { - return nil, c.ArgErr() + if ldap.ldapURL == "" { + return nil, c.Err("ldap_url cannot be empty") } if ldap.searchRequest.BaseDN == "" { - return nil, c.ArgErr() + return nil, c.Err("base_dn cannot be empty") } if ldap.searchRequest.Filter == "" { - return nil, c.ArgErr() + return nil, c.Err("filter cannot be empty") } - if len(ldap.searchRequest.Attributes) != 2 { - return nil, c.ArgErr() + if ldap.fqdnAttr == "" { + return nil, c.Err("fqdn attribute cannot be empty") + } + if ldap.ip4Attr == "" { + return nil, c.Err("ip4 attribute cannot be empty") } // if only one of password and username set - if (&ldap.username == nil) != (&ldap.password == nil) { - return nil, c.ArgErr() + if (ldap.username == "") != (ldap.password == "") { + return nil, c.Err("if not using sasl, both, username and password must be set") } // if both username/password and sasl are set - if &ldap.username != nil && &ldap.sasl != nil { - return nil, c.ArgErr() + if ldap.username != "" && ldap.sasl == true { + fmt.Printf("666 %#v\t%#v", ldap.username, ldap.sasl) + return nil, c.Err("cannot use sasl and username based authentication at the same time") } // if neither username/password nor sasl are set - if &ldap.username == nil && &ldap.sasl == nil { - return nil, c.ArgErr() + if ldap.username == "" && ldap.sasl == false { + return nil, c.Err("authenticate either via username/pwassword or sasl") } return ldap, nil diff --git a/setup_test.go b/setup_test.go index 2779d73..ed484ee 100644 --- a/setup_test.go +++ b/setup_test.go @@ -13,20 +13,23 @@ func TestSetup(t *testing.T) { body string expectedError bool }{ - {`ldap`, false}, + {`ldap`, true}, {`ldap :`, true}, {`ldap { ldap_url ldap://example.com base_dn ou=ae-dir filter (objectClass=aeNwDevice) - attributes aeFqdn ipHostNumber sasl + attributes { + fqdn aeFqdn + ip4 ipHostNumber + } }`, false}, } for i, test := range tests { c := caddy.NewTestController("dns", test.body) - if _, err := ldapParse(c); (err == nil) == test.expectedError { - t.Fatalf("Unexpected errors: %v in test: %d\n\t%s", err, i, test.body) + if _, err := ParseStanza(c); (err == nil) == test.expectedError { + t.Fatalf("Unexpected errors in test %d: %v\n%s", i, err, test.body) } } }