Compare commits

..

3 Commits

Author SHA1 Message Date
Chris F Ravenscroft 545da6fd0a chore: debug, openldap, samba 2026-04-19 11:21:40 -07:00
Chris F Ravenscroft d68c78a18b feat: starttls and ldaps now matching features (#458) 2025-08-04 15:34:55 -07:00
Neha Oudin 645dbb2266 fix: Credentials leaked on INFO log level (#451) 2025-05-11 15:12:14 -07:00
23 changed files with 529 additions and 50 deletions
+11
View File
@@ -69,6 +69,9 @@ all: setup binaries verify
#fast: @ run build process for only linuxamd64
fast: setup linuxamd64
#fastdebug: @ run build process for only linuxamd64 in debug mode
fastdebug: setup linuxamd64debug
#binaries: @ list of binary formats to build
binaries: linux386 linuxamd64 linuxarm linuxarm64 darwinamd64 darwinarm64 win386 winamd64
@@ -127,10 +130,18 @@ build: mkbindir
$(MAKE) sha256
.PHONY: build
builddebug: mkbindir
@go build ${TRIM_FLAGS} -tags ${BUILD_TAGS} -gcflags="all=-N -l" -o bin/$(GOOS)$(GOARCH)/glauth -buildvcs .
$(MAKE) sha256
.PHONY: builddebug
sha256:
@sha256sum bin/$(GOOS)$(GOARCH)/glauth > bin/$(GOOS)$(GOARCH)/glauth.sha256
.PHONY: sha256
linuxamd64debug:
GOOS=linux GOARCH=amd64 $(MAKE) builddebug
linux386:
GOOS=linux GOARCH=386 $(MAKE) build
+16 -4
View File
@@ -143,20 +143,32 @@ func startService() {
startConfigWatcher()
var err error
var tlsConfig *tls.Config
var starttlsConfig *tls.Config
if c := activeConfig.LDAP; c.Enabled && c.TLS {
// TODO check if tls params are string or bytes and change config accordingly
tlsConfig, err = _tls.MakeTLS([]byte(c.TLSCert), []byte(c.TLSKey))
starttlsConfig, err = _tls.MakeTLS([]byte(c.TLSCert), []byte(c.TLSKey), c.LegacyTLS)
if err != nil {
log.Warn().Err(err).Msg("unable to configure TLS, proceeding without....StartTLS won't be supported")
log.Warn().Err(err).Msg("unable to configure TLS for StartTLS: StartTLS won't be supported")
}
}
var ldapstlsConfig *tls.Config
if c := activeConfig.LDAPS; c.Enabled {
// TODO check if tls params are string or bytes and change config accordingly
ldapstlsConfig, err = _tls.MakeTLS([]byte(c.Cert), []byte(c.Key), c.LegacyTLS)
if err != nil {
log.Warn().Err(err).Msg("unable to configure TLS for LDAPS")
os.Exit(1)
}
}
s, err := server.NewServer(
server.Logger(log),
server.Config(activeConfig),
server.TLSConfig(tlsConfig),
server.StartTLSConfig(starttlsConfig),
server.LDAPSTLSConfig(ldapstlsConfig),
server.Monitor(monitor),
server.Tracer(tracer),
)
+1
View File
@@ -14,6 +14,7 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+47 -5
View File
@@ -12,8 +12,29 @@ var (
log zerolog.Logger
)
var secureCipherSuites = []uint16{
// TLS 1.3 cipher suites (automatically used when TLS 1.3 is negotiated)
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
// TLS 1.2 ECDHE cipher suites (Forward Secrecy)
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
// Additional secure TLS 1.2 cipher suites (CBC with HMAC-SHA256)
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
// tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
// tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
}
// MakeTLS generates a tls.Config
func MakeTLS(clientCert, key []byte) (*tls.Config, error) {
func MakeTLS(clientCert, key []byte, legacy bool) (*tls.Config, error) {
if clientCert == nil && key == nil {
return new(tls.Config), nil
}
@@ -55,11 +76,24 @@ func MakeTLS(clientCert, key []byte) (*tls.Config, error) {
log.Debug().Interface("root.ca", rootCAs)
log.Debug().Interface("certificates", []tls.Certificate{cert})
if legacy {
return &tls.Config{
RootCAs: rootCAs,
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS13,
PreferServerCipherSuites: true,
CipherSuites: nil,
Certificates: []tls.Certificate{cert},
}, nil
}
return &tls.Config{
RootCAs: rootCAs,
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS13,
Certificates: []tls.Certificate{cert},
RootCAs: rootCAs,
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
PreferServerCipherSuites: true,
CipherSuites: secureCipherSuites,
Certificates: []tls.Certificate{cert},
}, nil
}
@@ -79,3 +113,11 @@ func DecodePEM(certPEM []byte) tls.Certificate {
return cert
}
func CipherSuiteNames(suites []uint16) []string {
var names []string
for _, suite := range suites {
names = append(names, tls.CipherSuiteName(suite))
}
return names
}
+56 -19
View File
@@ -386,13 +386,47 @@ func validateConfig(cfg *config.Config) (*config.Config, error) {
if cfg.LDAPS.Enabled {
// LDAPS enabled - verify requirements (cert, key, listen)
if len(cfg.LDAPS.Cert) == 0 || len(cfg.LDAPS.Key) == 0 {
return cfg, fmt.Errorf("LDAPS was enabled but no certificate or key were specified: please disable LDAPS or use the 'cert' and 'key' options")
}
if len(cfg.LDAPS.Listen) == 0 {
return cfg, fmt.Errorf("no LDAPS bind address was specified: please disable LDAPS or use the 'listen' option")
}
if cfg.LDAPS.Cert == "" && cfg.LDAPS.CertPath != "" {
byteData, err := os.ReadFile(cfg.LDAPS.CertPath)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS certificate file")
}
cfg.LDAPS.Cert = string(byteData)
}
if cfg.LDAPS.Key == "" && cfg.LDAPS.KeyPath != "" {
byteData, err := os.ReadFile(cfg.LDAPS.KeyPath)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS key file")
}
cfg.LDAPS.Key = string(byteData)
}
// Ugly wart for backward compatibility
// In the olden times, we would simply say "please read from this file"
// This is now the role of the Path files.
if !strings.HasPrefix(cfg.LDAPS.Cert, "-----") {
byteData, err := os.ReadFile(cfg.LDAPS.Cert)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS certificate file")
}
cfg.LDAPS.Cert = string(byteData)
}
if !strings.HasPrefix(cfg.LDAPS.Key, "-----") {
byteData, err := os.ReadFile(cfg.LDAPS.Key)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS key file")
}
cfg.LDAPS.Key = string(byteData)
}
if cfg.LDAPS.Cert == "" || cfg.LDAPS.Key == "" {
return cfg, fmt.Errorf("LDAPS was enabled but no certificate or key were specified: please disable LDAPS or use the 'cert'/'key' or 'certpath'/'keypath' options")
}
}
if cfg.LDAP.Enabled {
@@ -401,24 +435,27 @@ func validateConfig(cfg *config.Config) (*config.Config, error) {
return cfg, fmt.Errorf("no LDAP bind address was specified: please disable LDAP or use the 'listen' option")
}
if cfg.LDAP.TLS && cfg.LDAP.TLSCert == "" && cfg.LDAP.TLSCertPath != "" {
byteData, err := os.ReadFile(cfg.LDAP.TLSCertPath)
cfg.LDAP.TLSCert = string(byteData)
if cfg.LDAP.TLS {
if cfg.LDAP.TLSCert == "" && cfg.LDAP.TLSCertPath != "" {
byteData, err := os.ReadFile(cfg.LDAP.TLSCertPath)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS certificate file")
}
cfg.LDAP.TLSCert = string(byteData)
}
if err != nil {
return cfg, fmt.Errorf("unable to read TLS certificate file")
if cfg.LDAP.TLSKey == "" && cfg.LDAP.TLSKeyPath != "" {
byteData, err := os.ReadFile(cfg.LDAP.TLSKeyPath)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS key file")
}
cfg.LDAP.TLSKey = string(byteData)
}
if cfg.LDAP.TLSCert == "" || cfg.LDAP.TLSKey == "" {
return cfg, fmt.Errorf("StartTLS was enabled but no certificate or key were specified: please disable StartTLS or use the 'tlscert'/'tlskey' or 'tlscertpath'/'tlskeypath' options")
}
}
if cfg.LDAP.TLS && cfg.LDAP.TLSKey == "" && cfg.LDAP.TLSKeyPath != "" {
byteData, err := os.ReadFile(cfg.LDAP.TLSKeyPath)
cfg.LDAP.TLSKey = string(byteData)
if err != nil {
return cfg, fmt.Errorf("unable to read TLS key file")
}
}
}
//spew.Dump(cfg)
+3
View File
@@ -0,0 +1,3 @@
olcAccess: to dn.subtree="dc=glauth,dc=com"
by dn.exact="cn=admin,dc=glauth,dc=com" manage
by * break
@@ -0,0 +1,7 @@
dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcAccess
-
add: olcAccess
olcAccess: to attrs=userPassword,shadowLastChange by self write by dn="cn=serviceuser,cn=svcaccts,ou=users,dc=glauth,dc=com" write by anonymous auth by * none
olcAccess: to * by self write by dn="cn=serviceuser,cn=svcaccts,ou=users,dc=glauth,dc=com" write by users read by * none
@@ -0,0 +1,4 @@
dn: cn=serviceuser,cn=svcaccts,ou=users,dc=glauth,dc=com
changetype: modify
replace: userPassword
userPassword: mysecret
+3
View File
@@ -0,0 +1,3 @@
TLS_REQCERT never
URI ldaps://192.168.1.222
BASE dc=test,dc=example,dc=com
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/env bash
for arg in "$@"; do
if [[ "$arg" == *"="* ]]; then
key="${arg%%=*}"
value="${arg#*=}"
eval "$key"="'$value'"
else
eval "$arg"=true
fi
done
if [[ "$ipaddr" == "" ]]; then
echo "Please provide ipaddr=<ip address> to create/use" >&2
exit 1
fi
if [[ "$ipmask" == "" ]]; then
ipmask=24
fi
eipaddr=$(echo "$ipaddr" | sed 's/\./\\./g')
ifname=$(ip -brief addr show | awk "/$eipaddr\// {print \$1}")
if [[ "$ifname" == "" ]]; then
ping -c 1 $ipaddr &>/dev/null
if [[ $? -eq 0 ]]; then
echo "It looks like you specified an already allocated ip address." >&2
exit 1
fi
fi
if [[ "$ifname" == "" ]]; then
passed=0
if [[ "$ipmask" == "" ]]; then
passed=1
fi
if [[ "$iface" == "" ]]; then
passed=2
fi
if [[ $passed -ne 0 ]]; then
echo "To create an interface, specify ipaddr=<ip address> ipmask=<mask> iface=<interface name>" >&2
echo "Example: ipaddr=192.168.1.222 ipmask=24 iface=en0" >&2
exit 1
fi
echo "Creating $ipaddr/$ipmask on interface $iface"
sudo ip addr add $ipaddr/$ipmask dev $iface
fi
if [[ "$domain" == "" ]]; then
domain="TEST.EXAMPLE.COM"
fi
if [[ "$defaultdns" == "" ]]; then
defaultdns="192.168.1.1"
fi
echo "Running Samba AD, listening on $ipaddr for domain $domain"
docker run -d
--name ad \
--hostname DC1 \
--restart unless-stopped \
-e REALM='TEST.LOCAL' \
-e DOMAIN='TEST' \
-e ADMIN_PASS='MySecret2026!' \
-e DNS_FORWARDER='8.8.8.8' \
-v dc_etc:/usr/local/samba/etc \
-v dc_private:/usr/local/samba/private \
-v dc_var:/usr/local/samba/var \
-p $ipaddr:53:53 \
-p $ipaddr:53:53/udp \
-p $ipaddr:88:88 \
-p $ipaddr:88:88/udp \
-p $ipaddr:135:135 \
-p $ipaddr:137-138:137-138/udp \
-p $ipaddr:139:139 \
-p $ipaddr:389:389 \
-p $ipaddr:389:389/udp \
-p $ipaddr:445:445 \
-p $ipaddr:464:464 \
-p $ipaddr:464:464/udp \
-p $ipaddr:636:636 \
-p $ipaddr:1024-1044:1024-1044 \
-p $ipaddr:3268-3269:3268-3269 \
diegogslomp/samba-ad-dc
+33
View File
@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFtDCCA5ygAwIBAgIEhCJsaTANBgkqhkiG9w0BAQsFADB6MR0wGwYDVQQKExRT
YW1iYSBBZG1pbmlzdHJhdGlvbjE3MDUGA1UECxMuU2FtYmEgLSB0ZW1wb3Jhcnkg
YXV0b2dlbmVyYXRlZCBDQSBjZXJ0aWZpY2F0ZTEgMB4GA1UEAxMXVEVTVERDLnRl
c3QuZXhhbXBsZS5jb20wHhcNMjYwMTE4MDAwMDA0WhcNMjcxMjE5MDAwMDA0WjB6
MR0wGwYDVQQKExRTYW1iYSBBZG1pbmlzdHJhdGlvbjE3MDUGA1UECxMuU2FtYmEg
LSB0ZW1wb3JhcnkgYXV0b2dlbmVyYXRlZCBDQSBjZXJ0aWZpY2F0ZTEgMB4GA1UE
AxMXVEVTVERDLnRlc3QuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQDuYBt2jNruSR4xL0wI8Nx2uq+jQKpiViWzDPw4eivNrLXc8Bdr
o9GqCo4uokPZiFS6jGez3holnMKF1bxU8uES2ma228zRIJVAHo0qU2O8zGoMtAuL
Z+F9gZAVSQKUMp0Vl2yyNERY453Ne4B2Oz92G87YtNuDyNYzuK4778FiE5iXjvan
CsAENXrspfxvn8QD5IloHPFoieFkfeaigDA6Zjtr2be+LhDbc2wn6YY7t8Z+5wxG
UPUy8oYKQ5lyHSn6I7aezAJpJJHSN4eSg76smTMjUOAnLqJJHPurGF9zzq+maRg+
M2runjqRcnZzQtkdZJayK8GQ39kEFpHnl1PueexFEIA5PxHaJEbapAiL7nP65bAy
Ey6wiOVvuLgztf8CU6hT/Not3qVG5lCGiK1VC9W684X5vQcVnQXTAIY3Edt91u8C
/wt4i5j58orVbcghAZMsU3FKjjqyvQMMSD2Pwgf6+m2mVQIAnZOrkErsQrltmFxO
CPBbRY+5Yg8v2ZucMWfKNy4IEzm8LyddrZKAENbW73/bZtPCw7cJqeb6ZaWVzrqW
BAgMiyrBYq/oGnXP6rHnTpB02LWTx8dvPPmEgvPhjecCRKroesYeKX38KWywGalA
xXbs+Eo9ApGst7qhkenAzM3E7Fy56OoELUAKGQW9gtVEnn+8BofLhezUyQIDAQAB
o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
ShGTEQzxmK0IrRMPiPYbRxfntYQwDQYJKoZIhvcNAQELBQADggIBAFxD6ShgnqwK
6oMzXKZOXoVfVu8yFKhL9Z3ui+6Q/duckzLf873sMlxz9msLTjH1O2Pk9gaND9/l
25t37BvVLuNTJKHvTfte53l8fQUrqCgOq2feARoXyCAA77bTUh+uSGsjZYGbSJx/
M93fOtabElD9T3o3B0L2EJyL7LHZ3in9MOyVBBcCnOMqi+1eoQEnaoj5TRnE8eEu
RuTs7Vu3lceZuCvH1mTRPis2D8bPCWa3aAI6w+LZoJNP3B1izo6Arjje7TBHBMGJ
A65o9LP1+OeZ5EA+J3nIkU5rSHu+Pk5biBNEThsnkGjEhSTXZPCVgZRQJOgQyvnf
LPWUOMdMLsnsO2oW3/BG6zTmbZw4CMzE8yZUtNZxph7+N1ukzYWZbSwDADxxi+dQ
vFQk6tguKpxBCko+pWajgNcxG97MFQMMCfGfva7xdaqBSB4R8sdmQm+wknAYQrlm
Jc6csvkJgoIHvyBn9yfSKYNvbjh8RUGA2TZMWrbBMdt51ivw6e1NM16OneGtELh+
zGlgv0EfJPaf9IG+RWqvMuhGFF1DgqBi8l816XFy4g3SEFC2F0D6VAv9mQZdq8q1
9y7B9vpcBQbNiHqJahIEwgp1JlHdoj281Ms2KixBf88O0y7zSMbyejxHtGv8IUVD
+Nth1G9FpENenG73njJIh1dLLYyHvxnp
-----END CERTIFICATE-----
+30
View File
@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFETCCAvmgAwIBAgIUHfUrLa/sMlGeT6VIZdkj73UjZfkwDQYJKoZIhvcNAQEL
BQAwGDEWMBQGA1UEAwwNU2FtYmEgVGVzdCBDQTAeFw0yNjAxMTgwMTEzMzVaFw0z
NjAxMTYwMTEzMzVaMBgxFjAUBgNVBAMMDVNhbWJhIFRlc3QgQ0EwggIiMA0GCSqG
SIb3DQEBAQUAA4ICDwAwggIKAoICAQC464FD54YJ1rgi/5Z9DQrIbEzED8NhMjo/
ndqD+0sfqkiYjQEqAh7Wpj+6r9D9AZ1wnTdF2Ee767OTwkSA2lG5aQAF9HDFzgIJ
8yVbeqJIABOzKotLTl1wCNeRx+YeY69xcytzsQ6iNFyOVV/CbkbxtyJvDfxD9rC5
Pwf1A7yBLz0H8U+kXBKC0SCDSW4+SAgmJQu3NQ7wd2eg+EBH/cPVhw0F97K3Yfb0
c8wekQdqAMrvfo/jq81/JADUEmzi1lyQ34zX2ToBIeu42/oTBmJ8ZX2ZAFgUu0y1
Kh+rmmYLhszPLfwB/28j1wizd/iVdpN0+ssJj3y+rEgKeXFfo1x7KSWprHUCJzZk
+T7l59tEg7ZiSuRexgkc3Rf+4DYNq7JzCFnVnBvhC++fym29JRrriX0DOUYMGAS3
dFBiLJT65kdLCwrgkCAZTbsNKTVkEQx3QYn58dUYMTmQXndg4AEG0VUa4s+oqOFu
jokyeqVqp37CUm0MU9cKJVnkMqWkqI9JRTBe90xHSy5xrmB0N1zM/FbUTBvMCh6Z
t7ZAiB3gB1LTXaDRWafJ+opYJtPkVhvAlmFjEwuYCYdUM8lz+i/MKK8hrAoztUvr
C2n5qoDUX5Tm9VygefWVxzCvyzTy+FKEq+4aU8ye0zohCJ+UP1SMi3j98aGdVjBJ
sI9KhOQNmQIDAQABo1MwUTAdBgNVHQ4EFgQUgFOZGLtmwudA8tVaKeLvowVQLMYw
HwYDVR0jBBgwFoAUgFOZGLtmwudA8tVaKeLvowVQLMYwDwYDVR0TAQH/BAUwAwEB
/zANBgkqhkiG9w0BAQsFAAOCAgEAPNmj5RCacwRbySYERx8XBlcV50DRFnFS51G0
EEKObiOBxt/xboAt/bPw+6dVeqS0JILrgMJhHn7dufRTdnGK/z9VkRDrTh6FudAk
16qdhglXzPrPzETGl1VHJxQEkqm+qkUeD4r9waUP5ZIXdsUrvGdnCaXgQRA3v2RD
NDvNldmgCTScjTPM4ox0B2iL0P0Uo4pRzQTGuPmubCMv2B8EkBOPIQx/TO2svL6M
oal/25v06+xUEyVAxWQPD4xolL8ksEjdqa7l5h/1YkpouWq+jaEDpWGzVqt/fLYI
cdGUxSNcaueEmHB2QOklrTdDVvvczAE98ytDZ/zswj8cKKLhe2d3Z3ie40xx+4/x
NprbosIGWrHnz0NbDlzXRvd8yk7ZWk4QFRycJb7Ve3Za3hPOlDeKgm5iCjafCS4G
C1D8r+SwGjCjgsaL7J/zY4IHyxurRVBU+jZSRgy2WQlR/BQ2gSdVt3BhxsEPgbmu
jKOiPltNkqPmUHoXFnosJyAblF8yjYkBPBpbM5luAUiKMYBkdkSA3oSJYK3WuIDl
UNcKwcC9sJPu63ciPDtEZlgV5blvMr80PPyJZDofo+KHxWweKxoyXxQoIKCrP53D
Av2KGBhIZlJUzNrj4LWMGbf+8BAGL+i1oyM77D/N8L589Y0x1mQMa/quQW+TJ8kH
g2wgxQw=
-----END CERTIFICATE-----
+52
View File
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
3tGhl1yrO4/YIpQrp0OgMV1HDYXEOwwI
-----END PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
59634A59EBDC029E7D479619E12C1868317CE811
+17
View File
@@ -0,0 +1,17 @@
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[dn]
CN = TESTDC.test.example.com
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = TESTDC.test.example.com
DNS.2 = localdc.test.example.com
IP.1 = 192.168.1.222
+26
View File
@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEUDCCAjigAwIBAgIUWWNKWevcAp59R5YZ4SwYaDF86BEwDQYJKoZIhvcNAQEL
BQAwGDEWMBQGA1UEAwwNU2FtYmEgVGVzdCBDQTAeFw0yNjAxMTgwMTE0MDRaFw0y
ODA0MjIwMTE0MDRaMCIxIDAeBgNVBAMMF1RFU1REQy50ZXN0LmV4YW1wbGUuY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA04ZWa1/UrP6eAkwvc2oL
XCewax+5GWWhIj0XVgglblPNcPbK0dLTienfGnfEYxgrCl4o+H7c+SFYcJ/Sg5jw
W4/POs+NWoo3ixj71TYWwK+7bUPt2RbNadCAxo4SejdB0zOjpTRn4dDIMZ0+wrg5
Ah3jkTnPmwWjpvt280KkojUz+7mhdKFXBBmyjr/ftWU8C+1nyJt5/tVl7PE0VcOL
MBok9djjHlj2aKLCw8Hj0CyL+yYFM4keWvYAguXYjVayMC2w8VffvjjO3Wd7/LWi
AkDIAhnKyc1oJ8X4h9XK1irEw8lgWH93jyRx54eG32/C3HuNRQA9oQgJrfaK5YCJ
kQIDAQABo4GHMIGEMEIGA1UdEQQ7MDmCF1RFU1REQy50ZXN0LmV4YW1wbGUuY29t
ghhsb2NhbGRjLnRlc3QuZXhhbXBsZS5jb22HBMCoAd4wHQYDVR0OBBYEFJDd+Fmx
vsrKEvBMXBwtBeFxjVjWMB8GA1UdIwQYMBaAFIBTmRi7ZsLnQPLVWini76MFUCzG
MA0GCSqGSIb3DQEBCwUAA4ICAQBwS8/1iAFnopOui1V/qdRBsBTWcXdQS7x1PqVU
nJkd+T5AYtLu3tJ+PBO9rfgDNVWVz37GB8CTgr4TpGOt7ruaVSZvw9uMRBxYeeit
Kf11gssI2eTZESv8yqsa1DtLheQS0AQ7IVjq9wZSw+i3zQ8lQDvFoCWa8nv+C+YZ
cfFSnhfXNRQIM+lxn6vrtZa/GgJh6MTF+vCfLvStveCsTvT7i/w0EzO8NFqGBrsX
ldombU/WNketQXQEaLAU6NQVvJCjkC9Wgc+KcOQOV77U7CHi3lsc2TAoGlMuJ1lP
zyQWJqHKkuWGODeBSd9FfjoZv81+OGPaCAh7bkOHwqAUjgEIL8SV1fX8i13HTkG5
nhbN6XoiezjKixfH/EAQHiKhi6/7nzYltz6bJFHpIfBa097l7Yhx/o/HIdKDWV2S
VnLIJMJpf/Qn80led1HQPeRWR1EC+fWhBzOg2mCJJpYkpqaOlHVujZ2c5JLckhxH
WuIkicvR+LE07IjgZFWUwCXW/PkDDHtiJ0MD6RAiFzFbnuGGMadv3lUBJBUeKL3P
PaDC/pue9AAgbWN9ndg8CTorDR2HHjjOyVTkum5bPL2vChuG3/mx+KHcgwDyEWt8
cJTxXNaid928rR0aSPsSd4WNlCTDwXhUpClaVRaip/rcfrhJaaFUe7xWpQe8dkvO
hiuYEQ==
-----END CERTIFICATE-----
+17
View File
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICvDCCAaQCAQAwIjEgMB4GA1UEAwwXVEVTVERDLnRlc3QuZXhhbXBsZS5jb20w
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDThlZrX9Ss/p4CTC9zagtc
J7BrH7kZZaEiPRdWCCVuU81w9srR0tOJ6d8ad8RjGCsKXij4ftz5IVhwn9KDmPBb
j886z41aijeLGPvVNhbAr7ttQ+3ZFs1p0IDGjhJ6N0HTM6OlNGfh0MgxnT7CuDkC
HeOROc+bBaOm+3bzQqSiNTP7uaF0oVcEGbKOv9+1ZTwL7WfIm3n+1WXs8TRVw4sw
GiT12OMeWPZoosLDwePQLIv7JgUziR5a9gCC5diNVrIwLbDxV9++OM7dZ3v8taIC
QMgCGcrJzWgnxfiH1crWKsTDyWBYf3ePJHHnh4bfb8Lce41FAD2hCAmt9orlgImR
AgMBAAGgVTBTBgkqhkiG9w0BCQ4xRjBEMEIGA1UdEQQ7MDmCF1RFU1REQy50ZXN0
LmV4YW1wbGUuY29tghhsb2NhbGRjLnRlc3QuZXhhbXBsZS5jb22HBMCoAd4wDQYJ
KoZIhvcNAQELBQADggEBAAQGVIMVIWPbCG3blO8iNHetydfz8XWC3w9zYI03QQBv
QdiAYZ9sI+9fxZdsBOOt+vSNyqlwuuQYmmMtMJbUezeOQ8Z4zhkWEzTI4ohhOlzV
sq+7aE+PNKw8CYvOkL4ssVIDU99Hm4ppJbo6sRa9YAXPDU3z0UJhMiGZL7o11048
W8VcWOzyNmEHYL6/+DXwXGiaLiJmMOJiwMPu8TZVnli4Q0k/j7KGdeh8s2MXLwi8
NT0ppSxm+MUIm014OEMA/LOPwRVttHca1VkGR15MJQElakWSaaix533p7lpH3Q3Q
tKZc7RIWeoXs5wyo7Tx7Tx7QdmNJIzA2gh4tRiQvm1o=
-----END CERTIFICATE REQUEST-----
+28
View File
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDThlZrX9Ss/p4C
TC9zagtcJ7BrH7kZZaEiPRdWCCVuU81w9srR0tOJ6d8ad8RjGCsKXij4ftz5IVhw
n9KDmPBbj886z41aijeLGPvVNhbAr7ttQ+3ZFs1p0IDGjhJ6N0HTM6OlNGfh0Mgx
nT7CuDkCHeOROc+bBaOm+3bzQqSiNTP7uaF0oVcEGbKOv9+1ZTwL7WfIm3n+1WXs
8TRVw4swGiT12OMeWPZoosLDwePQLIv7JgUziR5a9gCC5diNVrIwLbDxV9++OM7d
Z3v8taICQMgCGcrJzWgnxfiH1crWKsTDyWBYf3ePJHHnh4bfb8Lce41FAD2hCAmt
9orlgImRAgMBAAECggEAFTygZ5EMWr6zjC/W9xj3Vq4bbciWaRYwNS5PWKa3ugR1
lLkKcuzeVTM4YEFpuQ3qSv+vewd4VcDtzrI/zKY/F4pFjYuHZHGKaGTpP9D5kX3z
QjdMOtFUbU0Zk2schXhlG6MhyR/iVXnZ55/4dvdPrfE58aY4EZc22jiBYE9ZanmL
Nxqby63ntT/8ZqQpi5iu458TrWTAhOqF+0g5Aj8bWnk6xIcauvFuLORfAcg2kig6
+/oUZiQ4U65gvBODckADjTtKmVUlBFFc22xsR5pSm08dI06Fc+1ZWSa3smyA/a+d
iOx2Bb+wD8zQMq20pm3R7Kx/yaTLy+AubBzc7OYQMwKBgQDxrgQnMzjLpLEBe+kp
8DKSUpy06G176Zoz65NP5BiY1S12YSqu9ydapalIKKH32yu6Gzw0JsTDa0z8glDH
Z9VeB9ZM3q+jsPrg7pUUQKC+Yn/Msba5a4BLmdO61qAk1/zPsc/bEIxC6HBXuR5k
7bYRivARdGtYRqkkvVKnn5uWqwKBgQDgDuhC4u9ZBx2QN+bDyT+Ppqd+nLLZemTF
bJRRbfXsMRpgAvQl5f4mTxu/KqtKm/kKGY7F66B1XuSmZqAEsvVw0oM+0+rCDfdk
Iir87ZsdpfoRA5x775zaa2GrW7/hhpvBrenD9vNwo6/G927EjMAhhPaOelxpf+dS
fXBrTOKQswKBgQDC+pp9KbTzjo4DXX2SCSgzppSo2y+hHaj7pF33wVUa0DnaXK/7
8of8eNRm0+lANsFDZz+d730lD8dPnK8hASNBtl7tK2dWT61HlRQO/8jvcDYc5W8+
jn02AQexoAAZWWusAI9p9CLExBQGoeHkmWcfJhFic6M6198UNe2eMIVs+wKBgQCR
D1W0KDSJ0R+ExYxz6ZFrMZxzToREZQdlAh0scyKqnkfTLVZgSv02VDVEmR15Gm4r
6cwTu6+RDbS/PuYO5MYfG0u5m3370QsAG1b1lee9VD4IUew4GTPV/Xuoc6hRHNMu
m6gjJXkKzg75pCxkuDOT//+Y0wONki9zqp7j+U0eHQKBgCkyJ/E+hNFlzqFHugaR
ZC8ccttxs2ibTK4J861EvjA7zFkbnAHy2NfsrNPKm6t+TJOkeJ4XrST1vfS3aNJk
swHRQz8tWwtnJCsvTF5nCXU7dDQPsyxwRHB39Eq9KtXp7F+PD7kaMk8DbYIzcQ55
pe3uxsvKvS6R++L2eg3TfdSB
-----END PRIVATE KEY-----
+7 -2
View File
@@ -48,13 +48,18 @@ type (
TLSKey string
TLSCertPath string
TLSKeyPath string
LegacyTLS bool
}
LDAPS struct {
Enabled bool
Listen string
Cert string
Key string
// LDAPS TLS parameters
Cert string
Key string
CertPath string
KeyPath string
LegacyTLS bool
}
API struct {
+1 -1
View File
@@ -99,7 +99,7 @@ func NewDatabaseHandler(sqlBackend SqlBackend, opts ...handler.Option) handler.H
sqlBackend.CreateSchema(db)
sqlBackend.MigrateSchema(db, ColumnExists)
options.Logger.Info().Msg("Database (" + sqlBackend.GetDriverName() + "::" + options.Backend.Database + ") Plugin: Ready")
options.Logger.Debug().Msg("Database (" + sqlBackend.GetDriverName() + "::" + options.Backend.Database + ") Plugin: Ready")
return handler
}
+17 -9
View File
@@ -16,12 +16,13 @@ type Option func(o *Options)
// Options defines the available options for this package.
type Options struct {
Logger zerolog.Logger
Config *config.Config
TLSConfig *tls.Config
Monitor monitoring.MonitorInterface
Tracer trace.Tracer
Context context.Context
Logger zerolog.Logger
Config *config.Config
StartTLSConfig *tls.Config
LDAPSTLSConfig *tls.Config
Monitor monitoring.MonitorInterface
Tracer trace.Tracer
Context context.Context
}
// newOptions initializes the available default options.
@@ -56,10 +57,17 @@ func Context(val context.Context) Option {
}
}
// TLSConfig provides a function to set the TLS config option.
func TLSConfig(val *tls.Config) Option {
// TLSConfig provides a function to set the StartTLS config option.
func StartTLSConfig(val *tls.Config) Option {
return func(o *Options) {
o.TLSConfig = val
o.StartTLSConfig = val
}
}
// TLSConfig provides a function to set the LDAPSTls config option.
func LDAPSTLSConfig(val *tls.Config) Option {
return func(o *Options) {
o.LDAPSTLSConfig = val
}
}
+27 -10
View File
@@ -1,10 +1,13 @@
package server
import (
"crypto/tls"
"errors"
"fmt"
"plugin"
_tls "github.com/glauth/glauth/v2/internal/tls"
"github.com/rs/zerolog"
"go.opentelemetry.io/otel/trace"
@@ -20,9 +23,10 @@ type LdapSvc struct {
yubiAuth *yubigo.YubiAuth
l *ldap.Server
monitor monitoring.MonitorInterface
tracer trace.Tracer
log zerolog.Logger
ldapstls *tls.Config
monitor monitoring.MonitorInterface
tracer trace.Tracer
log zerolog.Logger
}
func NewServer(opts ...Option) (*LdapSvc, error) {
@@ -96,9 +100,22 @@ func NewServer(opts ...Option) (*LdapSvc, error) {
s.l = ldap.NewServer()
s.l.EnforceLDAP = true
if tlsConfig := options.TLSConfig; tlsConfig != nil {
if tlsConfig := options.StartTLSConfig; tlsConfig != nil {
s.l.TLSConfig = tlsConfig
s.log.Info().Interface("tls.certificates", tlsConfig.Certificates).Msg("enabling LDAP over TLS")
s.log.Info().
Str("tls.min_version", tls.VersionName(tlsConfig.MinVersion)).
Str("tls.max_version", tls.VersionName(tlsConfig.MaxVersion)).
Interface("tls.cipher_suites", _tls.CipherSuiteNames(tlsConfig.CipherSuites)).
Msg("enabling LDAP over TLS")
}
if tlsConfig := options.LDAPSTLSConfig; tlsConfig != nil {
s.ldapstls = tlsConfig
s.log.Info().
Str("tls.min_version", tls.VersionName(tlsConfig.MinVersion)).
Str("tls.max_version", tls.VersionName(tlsConfig.MaxVersion)).
Interface("tls.cipher_suites", _tls.CipherSuiteNames(tlsConfig.CipherSuites)).
Msg("enabling LDAPS")
}
for i, backend := range s.c.Backends {
@@ -199,11 +216,11 @@ func (s *LdapSvc) ListenAndServe() error {
// ListenAndServeTLS listens on the TCP network address s.c.LDAPS.Listen
func (s *LdapSvc) ListenAndServeTLS() error {
s.log.Info().Str("address", s.c.LDAPS.Listen).Msg("LDAPS server listening")
return s.l.ListenAndServeTLS(
s.c.LDAPS.Listen,
s.c.LDAPS.Cert,
s.c.LDAPS.Key,
)
listener, err := tls.Listen("tcp", s.c.LDAPS.Listen, s.ldapstls)
if err != nil {
return err
}
return s.l.Serve(listener)
}
// Shutdown ends listeners by sending true to the ldap serves quit channel
+42
View File
@@ -0,0 +1,42 @@
#################
# glauth.conf
#################
# General configuration.
#debug = true
syslog = true
#################
# Server configuration.
[ldap]
enabled = true
listen = "0.0.0.0:3893"
[ldaps]
enabled = false
listen = "0.0.0.0:636"
cert = "glauth.crt"
key = "glauth.key"
#################
# The backend section controls the data store.
[[backends]]
datastore = "ldap"
servers = [ "ldap://192.168.1.222:389" ]
[[backends]]
datastore = "config"
[[users]]
name = "otpuser"
otpsecret = "3hnvnk4ycv44glzigd6s25j4dougs3rk"
#################
# Enable and configure the optional REST API here.
[api]
enabled = false
tls = true
listen = "localhost:5555"
cert = "glauth.crt"
key = "glauth.key"