Initial commit
This commit is contained in:
130
ldap.go
Normal file
130
ldap.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/amoghe/go-crypt"
|
||||
"gopkg.in/ldap.v2"
|
||||
)
|
||||
|
||||
type LDAP struct {
|
||||
Host string
|
||||
Port int
|
||||
Starttls bool
|
||||
Ssl bool
|
||||
BaseDN string
|
||||
ServiceDN string
|
||||
ServicePassword string
|
||||
}
|
||||
|
||||
func (l LDAP) Connect() (*LDAPConn, error) {
|
||||
if l.Ssl {
|
||||
if c, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", l.Host, l.Port), &tls.Config{ServerName: l.Host}); err != nil {
|
||||
return nil, errors.New("unable to establish LDAPS connection to " + fmt.Sprintf("%s:%d", l.Host, l.Port) + ": " + err.Error())
|
||||
} else {
|
||||
return &LDAPConn{
|
||||
LDAP: l,
|
||||
connection: c,
|
||||
}, nil
|
||||
}
|
||||
} else if c, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", l.Host, l.Port)); err != nil {
|
||||
return nil, errors.New("unable to establish LDAP connection to " + fmt.Sprintf("%s:%d", l.Host, l.Port) + ": " + err.Error())
|
||||
} else {
|
||||
if l.Starttls {
|
||||
if err = c.StartTLS(&tls.Config{ServerName: l.Host}); err != nil {
|
||||
c.Close()
|
||||
return nil, errors.New("unable to StartTLS: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return &LDAPConn{
|
||||
LDAP: l,
|
||||
connection: c,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type LDAPConn struct {
|
||||
LDAP
|
||||
connection *ldap.Conn
|
||||
}
|
||||
|
||||
func (l LDAPConn) ServiceBind() error {
|
||||
return l.connection.Bind(l.ServiceDN, l.ServicePassword)
|
||||
}
|
||||
|
||||
func (l LDAPConn) Bind(username string, password string) error {
|
||||
return l.connection.Bind(username, password)
|
||||
}
|
||||
|
||||
func (l LDAPConn) SearchDN(username string) (string, error) {
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
l.BaseDN,
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
fmt.Sprintf("(&(objectClass=organizationalPerson)(uid=%s))", username),
|
||||
[]string{"dn"},
|
||||
nil,
|
||||
)
|
||||
|
||||
sr, err := l.connection.Search(searchRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(sr.Entries) != 1 {
|
||||
return "", errors.New("User does not exist or too many entries returned")
|
||||
}
|
||||
|
||||
return sr.Entries[0].DN, nil
|
||||
}
|
||||
|
||||
func (l LDAPConn) GetEntry(dn string) ([]*ldap.EntryAttribute, error) {
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
dn,
|
||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||
"(objectClass=*)", []string{}, nil,
|
||||
)
|
||||
|
||||
sr, err := l.connection.Search(searchRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(sr.Entries) != 1 {
|
||||
return nil, errors.New("User does not exist or too many entries returned")
|
||||
}
|
||||
|
||||
return sr.Entries[0].Attributes, nil
|
||||
}
|
||||
|
||||
func genSalt() (string, error) {
|
||||
b := make([]byte, 16)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
func (l LDAPConn) ChangePassword(dn string, rawpassword string) error {
|
||||
salt, err := genSalt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hashedpasswd, err := crypt.Crypt(rawpassword, "$6$" + salt + "$")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
modify := ldap.NewModifyRequest(dn)
|
||||
modify.Replace("userPassword", []string{"{CRYPT}" + hashedpasswd})
|
||||
|
||||
|
||||
return l.connection.Modify(modify)
|
||||
}
|
||||
Reference in New Issue
Block a user