Skip to content

Commit 1e5af8f

Browse files
author
62726164
authored
added SASL EXTERNAL client cert example to both example_test.go files (#277)
* added SASL EXTERNAL client cert example to both example_test.go files
1 parent 7eb0598 commit 1e5af8f

File tree

6 files changed

+114
-12
lines changed

6 files changed

+114
-12
lines changed

bind.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import (
1010
"math/rand"
1111
"strings"
1212

13-
ber "github.com/go-asn1-ber/asn1-ber"
1413
"github.com/Azure/go-ntlmssp"
15-
14+
ber "github.com/go-asn1-ber/asn1-ber"
1615
)
1716

1817
// SimpleBindRequest represents a username/password bind operation
@@ -395,7 +394,7 @@ func (l *Conn) ExternalBind() error {
395394
// NTLMBindRequest represents an NTLMSSP bind operation
396395
type NTLMBindRequest struct {
397396
// Domain is the AD Domain to authenticate too. If not specified, it will be grabbed from the NTLMSSP Challenge
398-
Domain string
397+
Domain string
399398
// Username is the name of the Directory object that the client wishes to bind as
400399
Username string
401400
// Password is the credentials to bind with

error.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ func GetLDAPError(packet *ber.Packet) error {
212212
}
213213
return &Error{
214214
ResultCode: resultCode,
215-
MatchedDN: response.Children[1].Value.(string),
216-
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
217-
Packet: packet,
215+
MatchedDN: response.Children[1].Value.(string),
216+
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
217+
Packet: packet,
218218
}
219219
}
220220
}
@@ -246,6 +246,7 @@ func IsErrorAnyOf(err error, codes ...uint16) bool {
246246

247247
return false
248248
}
249+
249250
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
250251
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
251252
return IsErrorAnyOf(err, desiredResultCode)

examples_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package ldap
22

33
import (
44
"crypto/tls"
5+
"crypto/x509"
56
"fmt"
7+
"io/ioutil"
68
"log"
79
)
810

@@ -340,3 +342,52 @@ func ExampleControlPaging_manualPaging() {
340342
break
341343
}
342344
}
345+
346+
// This example demonstrates how to use EXTERNAL SASL with TLS client certificates.
347+
func ExampleConn_ExternalBind() {
348+
var ldapCert = "/path/to/cert.pem"
349+
var ldapKey = "/path/to/key.pem"
350+
var ldapCAchain = "/path/to/ca_chain.pem"
351+
352+
// Load client cert and key
353+
cert, err := tls.LoadX509KeyPair(ldapCert, ldapKey)
354+
if err != nil {
355+
log.Fatal(err)
356+
}
357+
358+
// Load CA chain
359+
caCert, err := ioutil.ReadFile(ldapCAchain)
360+
if err != nil {
361+
log.Fatal(err)
362+
}
363+
caCertPool := x509.NewCertPool()
364+
caCertPool.AppendCertsFromPEM(caCert)
365+
366+
// Setup TLS with ldap client cert
367+
tlsConfig := &tls.Config{
368+
Certificates: []tls.Certificate{cert},
369+
RootCAs: caCertPool,
370+
InsecureSkipVerify: true,
371+
}
372+
373+
// connect to ldap server
374+
l, err := DialURL("ldap://ldap.example.com:389")
375+
if err != nil {
376+
log.Fatal(err)
377+
}
378+
defer l.Close()
379+
380+
// reconnect using tls
381+
err = l.StartTLS(tlsConfig)
382+
if err != nil {
383+
log.Fatal(err)
384+
}
385+
386+
// sasl external bind
387+
err = l.ExternalBind()
388+
if err != nil {
389+
log.Fatal(err)
390+
}
391+
392+
// Conduct ldap queries
393+
}

v3/bind.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import (
1010
"math/rand"
1111
"strings"
1212

13-
ber "github.com/go-asn1-ber/asn1-ber"
1413
"github.com/Azure/go-ntlmssp"
15-
14+
ber "github.com/go-asn1-ber/asn1-ber"
1615
)
1716

1817
// SimpleBindRequest represents a username/password bind operation
@@ -395,7 +394,7 @@ func (l *Conn) ExternalBind() error {
395394
// NTLMBindRequest represents an NTLMSSP bind operation
396395
type NTLMBindRequest struct {
397396
// Domain is the AD Domain to authenticate too. If not specified, it will be grabbed from the NTLMSSP Challenge
398-
Domain string
397+
Domain string
399398
// Username is the name of the Directory object that the client wishes to bind as
400399
Username string
401400
// Password is the credentials to bind with

v3/error.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ func GetLDAPError(packet *ber.Packet) error {
212212
}
213213
return &Error{
214214
ResultCode: resultCode,
215-
MatchedDN: response.Children[1].Value.(string),
216-
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
217-
Packet: packet,
215+
MatchedDN: response.Children[1].Value.(string),
216+
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
217+
Packet: packet,
218218
}
219219
}
220220
}
@@ -246,6 +246,7 @@ func IsErrorAnyOf(err error, codes ...uint16) bool {
246246

247247
return false
248248
}
249+
249250
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
250251
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
251252
return IsErrorAnyOf(err, desiredResultCode)

v3/examples_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package ldap
22

33
import (
44
"crypto/tls"
5+
"crypto/x509"
56
"fmt"
7+
"io/ioutil"
68
"log"
79
)
810

@@ -340,3 +342,52 @@ func ExampleControlPaging_manualPaging() {
340342
break
341343
}
342344
}
345+
346+
// This example demonstrates how to use EXTERNAL SASL with TLS client certificates.
347+
func ExampleConn_ExternalBind() {
348+
var ldapCert = "/path/to/cert.pem"
349+
var ldapKey = "/path/to/key.pem"
350+
var ldapCAchain = "/path/to/ca_chain.pem"
351+
352+
// Load client cert and key
353+
cert, err := tls.LoadX509KeyPair(ldapCert, ldapKey)
354+
if err != nil {
355+
log.Fatal(err)
356+
}
357+
358+
// Load CA chain
359+
caCert, err := ioutil.ReadFile(ldapCAchain)
360+
if err != nil {
361+
log.Fatal(err)
362+
}
363+
caCertPool := x509.NewCertPool()
364+
caCertPool.AppendCertsFromPEM(caCert)
365+
366+
// Setup TLS with ldap client cert
367+
tlsConfig := &tls.Config{
368+
Certificates: []tls.Certificate{cert},
369+
RootCAs: caCertPool,
370+
InsecureSkipVerify: true,
371+
}
372+
373+
// connect to ldap server
374+
l, err := DialURL("ldap://ldap.example.com:389")
375+
if err != nil {
376+
log.Fatal(err)
377+
}
378+
defer l.Close()
379+
380+
// reconnect using tls
381+
err = l.StartTLS(tlsConfig)
382+
if err != nil {
383+
log.Fatal(err)
384+
}
385+
386+
// sasl external bind
387+
err = l.ExternalBind()
388+
if err != nil {
389+
log.Fatal(err)
390+
}
391+
392+
// Conduct ldap queries
393+
}

0 commit comments

Comments
 (0)