diff --git a/v3/bind.go b/v3/bind.go index c3ee84e3..c22a7fed 100644 --- a/v3/bind.go +++ b/v3/bind.go @@ -6,10 +6,9 @@ import ( "crypto/rand" "encoding/binary" "encoding/hex" - enchex "encoding/hex" "errors" "fmt" - "io/ioutil" + "io" "strings" "unicode/utf16" @@ -212,7 +211,7 @@ func (l *Conn) DigestMD5Bind(digestMD5BindRequest *DigestMD5BindRequest) (*Diges if child.Data == nil { return result, GetLDAPError(packet) } - data, _ := ioutil.ReadAll(child.Data) + data, _ := io.ReadAll(child.Data) params, err = parseParams(string(data)) if err != nil { return result, fmt.Errorf("parsing digest-challenge: %s", err) @@ -373,7 +372,7 @@ func computeResponse(params map[string]string, uri, username, password string) ( if err != nil { return "", err } - cnonce := enchex.EncodeToString(rb) + cnonce := hex.EncodeToString(rb) x := username + ":" + params["realm"] + ":" + password y := md5Hash([]byte(x)) @@ -384,8 +383,8 @@ func computeResponse(params map[string]string, uri, username, password string) ( } a2 := bytes.NewBuffer([]byte("AUTHENTICATE")) a2.WriteString(":" + uri) - ha1 := enchex.EncodeToString(md5Hash(a1.Bytes())) - ha2 := enchex.EncodeToString(md5Hash(a2.Bytes())) + ha1 := hex.EncodeToString(md5Hash(a1.Bytes())) + ha2 := hex.EncodeToString(md5Hash(a2.Bytes())) kd := ha1 kd += ":" + params["nonce"] @@ -393,7 +392,7 @@ func computeResponse(params map[string]string, uri, username, password string) ( kd += ":" + cnonce kd += ":" + qop kd += ":" + ha2 - resp := enchex.EncodeToString(md5Hash([]byte(kd))) + resp := hex.EncodeToString(md5Hash([]byte(kd))) return fmt.Sprintf( `username="%s",realm="%s",nonce="%s",cnonce="%s",nc=00000001,qop=%s,digest-uri="%s",response=%s`, quotedStringEscape(username), @@ -502,8 +501,8 @@ func (req *NTLMBindRequest) appendTo(envelope *ber.Packet) (err error) { var negMessage []byte // generate an NTLMSSP Negotiation message for the specified domain (it can be blank) - switch { - case req.Negotiator == nil: + switch req.Negotiator { + case nil: negMessage, err = ntlmssp.NewNegotiateMessage(req.Domain, "") if err != nil { return fmt.Errorf("create NTLM negotiate message: %s", err) @@ -615,11 +614,12 @@ func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindRes case ntlmBindRequest.Hash == "" && ntlmBindRequest.Password == "" && !ntlmBindRequest.AllowEmptyPassword: err = fmt.Errorf("need a password or hash to generate reply") case ntlmBindRequest.Negotiator == nil && ntlmBindRequest.Hash != "": - responseMessage, err = ntlmssp.ProcessChallengeWithHash(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Hash) + responseMessage, err = ntlmssp.NewAuthenticateMessage(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Hash, &ntlmssp.AuthenticateMessageOptions{ + PasswordHashed: true, + }) case ntlmBindRequest.Negotiator == nil && (ntlmBindRequest.Password != "" || ntlmBindRequest.AllowEmptyPassword): // generate a response message to the challenge with the given Username/Password if password is provided - _, _, domainNeeded := ntlmssp.GetDomain(ntlmBindRequest.Username) - responseMessage, err = ntlmssp.ProcessChallenge(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password, domainNeeded) + responseMessage, err = ntlmssp.NewAuthenticateMessage(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password, nil) default: hash := ntlmBindRequest.Hash if len(hash) == 0 { @@ -739,7 +739,7 @@ func (l *Conn) GSSAPIBindRequest(client GSSAPIClient, req *GSSAPIBindRequest) er return l.GSSAPIBindRequestWithAPOptions(client, req, []int{}) } -// GSSAPIBindRequest performs the GSSAPI SASL bind using the provided GSSAPI client. +// GSSAPIBindRequestWithAPOptions performs the GSSAPI SASL bind using the provided GSSAPI client and AP options. func (l *Conn) GSSAPIBindRequestWithAPOptions(client GSSAPIClient, req *GSSAPIBindRequest, APOptions []int) error { //nolint:errcheck defer client.DeleteSecContext() @@ -845,7 +845,7 @@ RESP: if referral.ClassType != ber.ClassContext || referral.Tag != ber.TagObjectDescriptor { break RESP } - return ioutil.ReadAll(referral.Data) + return io.ReadAll(referral.Data) } // Optional: //if len(protocolOp.Children) == 4 { diff --git a/v3/conn.go b/v3/conn.go index 3c3e67e5..152b0319 100644 --- a/v3/conn.go +++ b/v3/conn.go @@ -204,7 +204,7 @@ func (dc *DialContext) dial(u *url.URL) (net.Conn, error) { return tls.DialWithDialer(dc.dialer, "tcp", net.JoinHostPort(host, port), dc.tlsConfig) } - return nil, fmt.Errorf("Unknown scheme '%s'", u.Scheme) + return nil, fmt.Errorf("unknown scheme '%s'", u.Scheme) } // Dial connects to the given address on the given network using net.Dial diff --git a/v3/control.go b/v3/control.go index bfaf67aa..14f5270c 100644 --- a/v3/control.go +++ b/v3/control.go @@ -670,23 +670,25 @@ func DecodeControl(packet *ber.Packet) (Control, error) { sequence := value.Children[0] for _, child := range sequence.Children { - if child.Tag == 0 { + switch child.Tag { + case 0: // Warning warningPacket := child.Children[0] val, err := ber.ParseInt64(warningPacket.Data.Bytes()) if err != nil { return nil, fmt.Errorf("failed to decode data bytes: %s", err) } - if warningPacket.Tag == 0 { + switch warningPacket.Tag { + case 0: // timeBeforeExpiration c.Expire = val warningPacket.Value = c.Expire - } else if warningPacket.Tag == 1 { + case 1: // graceAuthNsRemaining c.Grace = val warningPacket.Value = c.Grace } - } else if child.Tag == 1 { + case 1: // Error bs := child.Data.Bytes() if len(bs) != 1 || bs[0] > 8 { @@ -1129,7 +1131,7 @@ type ControlServerSideSortingResult struct { // AttributeType string } -func (control *ControlServerSideSortingResult) GetControlType() string { +func (c *ControlServerSideSortingResult) GetControlType() string { return ControlTypeServerSideSortingResult } @@ -1151,7 +1153,7 @@ func (c *ControlServerSideSortingResult) String() string { ) } -// Mode for ControlTypeSyncRequest +// ControlSyncRequestMode is the mode for ControlTypeSyncRequest type ControlSyncRequestMode int64 const ( @@ -1225,7 +1227,7 @@ func (c *ControlSyncRequest) String() string { ) } -// State for ControlSyncState +// ControlSyncStateState is the state for ControlSyncState type ControlSyncStateState int64 const ( @@ -1348,7 +1350,7 @@ func (c *ControlSyncDone) String() string { ) } -// Tag For ControlSyncInfo +// ControlSyncInfoValue is the tag for ControlSyncInfo type ControlSyncInfoValue uint64 const ( @@ -1436,7 +1438,7 @@ func NewControlSyncInfo(pkt *ber.Packet) (*ControlSyncInfo, error) { syncUUIDs []uuid.UUID ) c := &ControlSyncInfo{Criticality: false} - switch ControlSyncInfoValue(pkt.Identifier.Tag) { + switch ControlSyncInfoValue(pkt.Tag) { case SyncInfoNewcookie: c.Value = SyncInfoNewcookie c.NewCookie = &ControlSyncInfoNewCookie{ @@ -1500,7 +1502,7 @@ func NewControlSyncInfo(pkt *ber.Packet) (*ControlSyncInfo, error) { SyncUUIDs: syncUUIDs, } default: - return nil, fmt.Errorf("unknown sync info value: %d", pkt.Identifier.Tag) + return nil, fmt.Errorf("unknown sync info value: %d", pkt.Tag) } return c, nil } diff --git a/v3/debug.go b/v3/debug.go index 6f89b4a0..2f852e8a 100644 --- a/v3/debug.go +++ b/v3/debug.go @@ -14,7 +14,7 @@ func (debug *debugging) Enable(b bool) { } // Printf writes debug output. -func (debug debugging) Printf(format string, args ...interface{}) { +func (debug debugging) Printf(format string, args ...any) { if debug { logger.Printf(format, args...) } diff --git a/v3/error.go b/v3/error.go index 1cf09c4f..87e3e3a3 100644 --- a/v3/error.go +++ b/v3/error.go @@ -200,18 +200,18 @@ func (e *Error) Unwrap() error { return e.Err } // This function returns nil if resultCode in the LDAPResult sequence is success(0). func GetLDAPError(packet *ber.Packet) error { if packet == nil { - return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")} + return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("empty packet")} } if len(packet.Children) >= 2 { response := packet.Children[1] if response == nil { - return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet"), Packet: packet} + return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("empty response in packet"), Packet: packet} } if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 { if ber.Type(response.Children[0].Tag) == ber.Type(ber.TagInteger) || ber.Type(response.Children[0].Tag) == ber.Type(ber.TagEnumerated) { if response.Children[0].Value == nil { - return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid result code in packet"), Packet: packet} + return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("invalid result code in packet"), Packet: packet} } resultCode := uint16(response.Children[0].Value.(int64)) @@ -222,7 +222,7 @@ func GetLDAPError(packet *ber.Packet) error { if ber.Type(response.Children[1].Tag) == ber.Type(ber.TagOctetString) && ber.Type(response.Children[2].Tag) == ber.Type(ber.TagOctetString) { if response.Children[1].Value == nil { - return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid matchedDN in packet"), Packet: packet} + return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("invalid matchedDN in packet"), Packet: packet} } return &Error{ ResultCode: resultCode, @@ -235,7 +235,7 @@ func GetLDAPError(packet *ber.Packet) error { } } - return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format"), Packet: packet} + return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("invalid packet format"), Packet: packet} } // NewError creates an LDAP error with the given code and underlying error diff --git a/v3/error_test.go b/v3/error_test.go index fd8fd5c4..551dfb04 100644 --- a/v3/error_test.go +++ b/v3/error_test.go @@ -80,7 +80,6 @@ func TestWrappedError(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() actual := IsErrorAnyOf(tt.err, tt.codes...) @@ -168,7 +167,7 @@ func generateGetLDAPErrorCorpus() map[string]testCorpusErrorEntry { corpus["unexpected ordering"] = testCorpusErrorEntry{ packet: packet, expectedResultCode: ErrorNetwork, - expectedMessage: "Invalid packet format", + expectedMessage: "invalid packet format", shouldError: true, } @@ -176,7 +175,7 @@ func generateGetLDAPErrorCorpus() map[string]testCorpusErrorEntry { corpus["nil packet"] = testCorpusErrorEntry{ packet: nil, expectedResultCode: ErrorUnexpectedResponse, - expectedMessage: "Empty packet", + expectedMessage: "empty packet", shouldError: true, } @@ -189,13 +188,13 @@ func generateGetLDAPErrorCorpus() map[string]testCorpusErrorEntry { corpus["nil first child"] = testCorpusErrorEntry{ packet: packet, expectedResultCode: ErrorUnexpectedResponse, - expectedMessage: "Empty response in packet", + expectedMessage: "empty response in packet", shouldError: true, } // Test that if the result code is nil, we get an appropriate error instead of a panic. // Panic message would be "interface conversion: interface {} is nil, not int64" - diagnosticMessage = "Invalid result code in packet" + diagnosticMessage = "invalid result code in packet" bindResponse = ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindResponse, nil, "Bind Response") bindResponse.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, nil, "resultCode")) bindResponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "dc=example,dc=org", "matchedDN")) @@ -212,15 +211,15 @@ func generateGetLDAPErrorCorpus() map[string]testCorpusErrorEntry { // Test that if the matchedDN is nil, we get an appropriate error instead of a panic. // Panic message would be "interface conversion: interface {} is nil, not string" - panic_data := []byte("07A\x010\x7f\xff00\x02\x010D\"0000000000000000000000000000000000D\x010A\x010A\x010") - packet, err := ber.ReadPacket(bytes.NewReader(panic_data)) + panicData := []byte("07A\x010\x7f\xff00\x02\x010D\"0000000000000000000000000000000000D\x010A\x010A\x010") + packet, err := ber.ReadPacket(bytes.NewReader(panicData)) if err != nil { panic(fmt.Sprintf("failed to read packet for panic test: %s", err)) } corpus["panic data"] = testCorpusErrorEntry{ packet: packet, expectedResultCode: ErrorNetwork, - expectedMessage: "Invalid matchedDN in packet", + expectedMessage: "invalid matchedDN in packet", shouldError: true, } diff --git a/v3/examples_test.go b/v3/examples_test.go index e4e980d8..965a2724 100644 --- a/v3/examples_test.go +++ b/v3/examples_test.go @@ -5,8 +5,8 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "io/ioutil" "log" + "os" "time" ) @@ -522,7 +522,7 @@ func ExampleConn_ExternalBind() { } // Load CA chain - caCert, err := ioutil.ReadFile(ldapCAchain) + caCert, err := os.ReadFile(ldapCAchain) if err != nil { log.Fatal(err) } diff --git a/v3/gssapi/client.go b/v3/gssapi/client.go index 4bbca0cd..bc81fa8f 100644 --- a/v3/gssapi/client.go +++ b/v3/gssapi/client.go @@ -89,7 +89,7 @@ func NewClientFromCCache(ccachePath, krb5confPath string, settings ...func(*clie // Close deletes any established secure context and closes the client. func (client *Client) Close() error { - client.Client.Destroy() + client.Destroy() return nil } @@ -115,7 +115,7 @@ func (client *Client) InitSecContextWithOptions(target string, input []byte, APO switch input { case nil: - tkt, ekey, err := client.Client.GetServiceTicket(target) + tkt, ekey, err := client.GetServiceTicket(target) if err != nil { return nil, false, err } diff --git a/v3/ldap.go b/v3/ldap.go index 802a529e..f5a7062b 100644 --- a/v3/ldap.go +++ b/v3/ldap.go @@ -2,7 +2,6 @@ package ldap import ( "fmt" - "io/ioutil" "log" "os" "strings" @@ -231,23 +230,25 @@ func addControlDescriptions(packet *ber.Packet) error { } sequence := value.Children[0] for _, child := range sequence.Children { - if child.Tag == 0 { + switch child.Tag { + case 0: // Warning warningPacket := child.Children[0] val, err := ber.ParseInt64(warningPacket.Data.Bytes()) if err != nil { return fmt.Errorf("failed to decode data bytes: %s", err) } - if warningPacket.Tag == 0 { + switch warningPacket.Tag { + case 0: // timeBeforeExpiration value.Description += " (TimeBeforeExpiration)" warningPacket.Value = val - } else if warningPacket.Tag == 1 { + case 1: // graceAuthNsRemaining value.Description += " (GraceAuthNsRemaining)" warningPacket.Value = val } - } else if child.Tag == 1 { + case 1: // Error bs := child.Data.Bytes() if len(bs) != 1 || bs[0] > 8 { @@ -297,7 +298,7 @@ func addDefaultLDAPResponseDescriptions(packet *ber.Packet) error { // DebugBinaryFile reads and prints packets from the given filename func DebugBinaryFile(fileName string) error { - file, err := ioutil.ReadFile(fileName) + file, err := os.ReadFile(fileName) if err != nil { return NewError(ErrorDebugging, err) } diff --git a/v3/search.go b/v3/search.go index c0f19e34..045e6b98 100644 --- a/v3/search.go +++ b/v3/search.go @@ -245,7 +245,7 @@ func readTag(f reflect.StructField) (string, bool) { // if err := result.Unmarshal(&user); err != nil { // // ... // } -func (e *Entry) Unmarshal(i interface{}) (err error) { +func (e *Entry) Unmarshal(i any) (err error) { return e.UnmarshalFunc(i, func(entry *Entry, ft reflect.StructField, fv reflect.Value) error { // omitempty can be safely discarded, as it's not needed when unmarshalling fieldTag, _ := readTag(ft) @@ -307,10 +307,10 @@ func (e *Entry) Unmarshal(i interface{}) (err error) { // UnmarshalFunc allows you to define a custom unmarshaler to parse an Entry values. // A custom unmarshaler can be found in the Unmarshal function or in the test files. -func (e *Entry) UnmarshalFunc(i interface{}, +func (e *Entry) UnmarshalFunc(i any, fn func(entry *Entry, fieldType reflect.StructField, fieldValue reflect.Value) error) error { // Make sure it's a ptr - if vo := reflect.ValueOf(i).Kind(); vo != reflect.Ptr { + if vo := reflect.ValueOf(i).Kind(); vo != reflect.Pointer { return fmt.Errorf("ldap: cannot use %s, expected pointer to a struct", vo) } @@ -717,7 +717,7 @@ func (l *Conn) DirSync( return searchResult, nil } -// DirSyncDirSyncAsync performs a search request and returns all search results +// DirSyncAsync performs a search request and returns all search results // asynchronously. This is efficient when the server returns lots of entries. func (l *Conn) DirSyncAsync( ctx context.Context, searchRequest *SearchRequest, bufferSize int, diff --git a/v3/search_test.go b/v3/search_test.go index 381284ef..86708ab9 100644 --- a/v3/search_test.go +++ b/v3/search_test.go @@ -21,16 +21,11 @@ func TestNewEntry(t *testing.T) { } executedEntry := NewEntry(dn, attributes) - iteration := 0 - for { - if iteration == 100 { - break - } + for range 100 { testEntry := NewEntry(dn, attributes) if !reflect.DeepEqual(executedEntry, testEntry) { t.Fatalf("subsequent calls to NewEntry did not yield the same result:\n\texpected:\n\t%v\n\tgot:\n\t%v\n", executedEntry, testEntry) } - iteration = iteration + 1 } }