Skip to content

Commit

Permalink
add support for ldap bind requests
Browse files Browse the repository at this point in the history
  • Loading branch information
equinox0815 committed Jan 31, 2024
1 parent f876db8 commit d11a977
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 23 deletions.
21 changes: 10 additions & 11 deletions cmd/whawty-auth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,22 @@ type httpsConfig struct {
TLS *tlsconfig.TLSConfig `yaml:"tls"`
}

// type ldapConfig struct {
// Listen []string `yaml:"listen"`
// StartTLS bool `yaml:"start-tls"`
// TLS *tlsconfig.TLSConfig `yaml:"tls"`
// }
type ldapConfig struct {
Listen []string `yaml:"listen"`
TLS *tlsconfig.TLSConfig `yaml:"tls"`
}

// type ldapsConfig struct {
// Listen []string `yaml:"listen"`
// TLS *tlsconfig.TLSConfig `yaml:"tls"`
// }
type ldapsConfig struct {
Listen []string `yaml:"listen"`
TLS *tlsconfig.TLSConfig `yaml:"tls"`
}

type listenerConfig struct {
SASLAuthd *saslauthdConfig `yaml:"saslauthd"`
HTTP *httpConfig `yaml:"http"`
HTTPs *httpsConfig `yaml:"https"`
// LDAP *ldapConfig `yaml:"ldap"`
// LDAPs *ldapsConfig `yaml:"ldaps"`
LDAP *ldapConfig `yaml:"ldap"`
LDAPs *ldapsConfig `yaml:"ldaps"`
}

func readListenerConfig(configfile string) (*listenerConfig, error) {
Expand Down
97 changes: 97 additions & 0 deletions cmd/whawty-auth/ldap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// Copyright (c) 2016 whawty contributors (see AUTHORS file)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of whawty.auth nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

package main

import (
"crypto/tls"
"net"

"github.com/glauth/ldap"
)

type ldapHandler struct {
store *Store
}

func (h ldapHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAPResultCode, error) {
if ok, _, _, _ := h.store.Authenticate(bindDN, bindSimplePw); !ok {
return ldap.LDAPResultInvalidCredentials, nil
}
return ldap.LDAPResultSuccess, nil
}

func runLDAPsListener(listener *net.TCPListener, config *ldapsConfig, store *Store) error {
server := ldap.NewServer()
server.BindFunc("", ldapHandler{store: store})

tlsConfig, err := config.TLS.ToGoTLSConfig()
if err != nil {
return err
}
wl.Printf("ldap: listening on '%s' using TLS", listener.Addr())
return server.Serve(tls.NewListener(listener, tlsConfig))
}

func runLDAPsAddr(addr string, config *ldapsConfig, store *Store) error {
if addr == "" {
addr = ":ldaps"
}
listener, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return runLDAPsListener(listener.(*net.TCPListener), config, store)
}

func runLDAPListener(listener *net.TCPListener, config *ldapConfig, store *Store) (err error) {
server := ldap.NewServer()
server.BindFunc("", ldapHandler{store: store})
if config.TLS != nil {
if server.TLSConfig, err = config.TLS.ToGoTLSConfig(); err != nil {
return err
}
wl.Printf("ldap: listening on '%s' with StartTLS", listener.Addr())
} else {
wl.Printf("ldap: listening on '%s'", listener.Addr())
}
return server.Serve(listener)
}

func runLDAPAddr(addr string, config *ldapConfig, store *Store) error {
if addr == "" {
addr = ":ldap"
}
listener, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return runLDAPListener(listener.(*net.TCPListener), config, store)
}
60 changes: 60 additions & 0 deletions cmd/whawty-auth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,30 @@ func cmdRun(c *cli.Context) error {
}()
}
}
if lc.LDAP != nil {
for _, addr := range lc.LDAP.Listen {
a := addr
wg.Add(1)
go func() {
defer wg.Done()
if err := runLDAPAddr(a, lc.LDAP, s.GetInterface()); err != nil {
fmt.Printf("warning running web-api failed: %s\n", err)
}
}()
}
}
if lc.LDAPs != nil {
for _, addr := range lc.LDAPs.Listen {
a := addr
wg.Add(1)
go func() {
defer wg.Done()
if err := runLDAPsAddr(a, lc.LDAPs, s.GetInterface()); err != nil {
fmt.Printf("warning running web-api failed: %s\n", err)
}
}()
}
}
wg.Wait()

return cli.NewExitError(fmt.Sprintf("shutting down since all auth sockets have closed."), 0)
Expand Down Expand Up @@ -496,6 +520,42 @@ func cmdRunSa(c *cli.Context) error {
}
}()
}
case "ldap":
if lc.LDAP == nil {
fmt.Printf("ingoring unexpected socket for LDAP listener (no config found in listener-config)\n")
continue
}
for _, listener := range listeners {
ln, ok := listener.(*net.TCPListener)
if !ok {
fmt.Printf("ingoring invalid socket type %T for LDAP listener\n", listener)
}
wg.Add(1)
go func() {
defer wg.Done()
if err := runLDAPListener(ln, lc.LDAP, s.GetInterface()); err != nil {
fmt.Printf("warning running web-api failed: %s\n", err)
}
}()
}
case "ldaps":
if lc.LDAPs == nil {
fmt.Printf("ingoring unexpected socket for LDAPs listener (no config found in listener-config)\n")
continue
}
for _, listener := range listeners {
ln, ok := listener.(*net.TCPListener)
if !ok {
fmt.Printf("ingoring invalid socket type %T for LDAPs listener\n", listener)
}
wg.Add(1)
go func() {
defer wg.Done()
if err := runLDAPsListener(ln, lc.LDAPs, s.GetInterface()); err != nil {
fmt.Printf("warning running web-api failed: %s\n", err)
}
}()
}
}

}
Expand Down
1 change: 0 additions & 1 deletion cmd/whawty-auth/web_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,5 @@ func runHTTPAddr(addr string, config *httpConfig, store *Store) error {
if err != nil {
return err
}

return runHTTPListener(listener.(*net.TCPListener), config, store)
}
25 changes: 14 additions & 11 deletions contrib/listener-cfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,17 @@ https:
# - x25519
# session-tickets: true
# session-ticket-key: "b947e39f50e20351bdd81046e20fff7948d359a3aec391719d60645c5972cc77"
# ldap:
# listen:
# - 127.0.0.1:389
# start-tls: true
# ldaps:
# listen:
# - 127.0.0.1:636
# tls:
# certificate: "/path/to/server-crt.pem"
# certificate-key: "/path/to/server-key.pem"
# min-protocol-version: "TLSv1.2"
ldap:
listen:
- 127.0.0.1:389
tls: ## if set start-tls is enabled
certificate: "/path/to/server-crt.pem"
certificate-key: "/path/to/server-key.pem"
min-protocol-version: "TLSv1.2"
ldaps:
listen:
- 127.0.0.1:636
tls:
certificate: "/path/to/server-crt.pem"
certificate-key: "/path/to/server-key.pem"
min-protocol-version: "TLSv1.2"
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ require (
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/glauth/ldap v0.0.0-20231210225823-b9bf4d1baf6e // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/glauth/ldap v0.0.0-20231210225823-b9bf4d1baf6e h1:ohe1O2DUo198delHsQvA8O+CgAPP8wv1SmSxLPlO9ao=
github.com/glauth/ldap v0.0.0-20231210225823-b9bf4d1baf6e/go.mod h1:EHMcFuVSIs0huelHOhaGtj9IKMB/Dmxo+jDheipjtYA=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM=
Expand Down

0 comments on commit d11a977

Please sign in to comment.