mirror of
https://github.com/glauth/glauth.git
synced 2026-10-24 21:23:11 +00:00
241 lines
9.2 KiB
Go
241 lines
9.2 KiB
Go
package main
|
|
|
|
import (
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
)
|
|
|
|
type testEnv struct {
|
|
checkanonymousrootDSE bool
|
|
checkTOTP bool
|
|
checkbindUPN bool
|
|
svcdn string
|
|
svcdnnogroup string
|
|
otpdn string
|
|
expectedinfo string
|
|
expectedaccount string
|
|
scopedaccount string
|
|
expectedfirstaccount string
|
|
expectedgroup string
|
|
checkemployeetype string
|
|
}
|
|
|
|
func TestIntegerStuff(t *testing.T) {
|
|
|
|
Convey("Testing sample-simple local file-based LDAP server", t, func() {
|
|
svc := startSvc(SD, "bin/glauth", "-c", "sample-simple.cfg")
|
|
batteryOfTests(
|
|
t,
|
|
svc, testEnv{
|
|
checkanonymousrootDSE: true,
|
|
checkTOTP: true,
|
|
checkbindUPN: true,
|
|
expectedinfo: "supportedLDAPVersion: 3",
|
|
svcdn: "cn=serviceuser,ou=svcaccts,dc=glauth,dc=com",
|
|
svcdnnogroup: "cn=serviceuser,dc=glauth,dc=com",
|
|
otpdn: "cn=otpuser,ou=superheros,dc=glauth,dc=com",
|
|
expectedaccount: "dn: cn=hackers,ou=superheros,ou=users,dc=glauth,dc=com",
|
|
scopedaccount: "dn: cn=hackers,ou=superheros,dc=glauth,dc=com",
|
|
expectedfirstaccount: "dn: cn=hackers,ou=superheros,ou=users,dc=glauth,dc=com",
|
|
expectedgroup: "dn: ou=superheros,ou=users,dc=glauth,dc=com",
|
|
checkemployeetype: "cn=hackers",
|
|
})
|
|
stopSvc(svc)
|
|
})
|
|
|
|
matchingLibrary := doRunGetFirst(RD, "ls", "bin/sqlite.so")
|
|
if matchingLibrary == "bin/sqlite.so" {
|
|
Convey("Testing sample-database LDAP server", t, func() {
|
|
svc := startSvc(SD, "bin/glauth", "-c", "pkg/plugins/sample-database.cfg")
|
|
batteryOfTests(
|
|
t,
|
|
svc, testEnv{
|
|
checkanonymousrootDSE: true,
|
|
checkTOTP: false,
|
|
checkbindUPN: true,
|
|
expectedinfo: "supportedLDAPVersion: 3",
|
|
svcdn: "cn=serviceuser,ou=svcaccts,dc=glauth,dc=com",
|
|
svcdnnogroup: "cn=serviceuser,dc=glauth,dc=com",
|
|
otpdn: "cn=otpuser,ou=superheros,dc=glauth,dc=com",
|
|
expectedaccount: "dn: cn=hackers,ou=superheros,ou=users,dc=glauth,dc=com",
|
|
scopedaccount: "dn: cn=hackers,ou=superheros,dc=glauth,dc=com",
|
|
expectedfirstaccount: "dn: cn=hackers,ou=superheros,ou=users,dc=glauth,dc=com",
|
|
expectedgroup: "dn: ou=superheros,ou=users,dc=glauth,dc=com",
|
|
checkemployeetype: "",
|
|
})
|
|
stopSvc(svc)
|
|
})
|
|
}
|
|
|
|
matchingContainers := doRunGetFirst(RD, "sh", "-c", "docker ps | grep openldap-service | wc -l")
|
|
if matchingContainers == "1" {
|
|
Convey("Testing sample-simple local LDAP server", t, func() {
|
|
svc := startSvc(SD, "bin/glauth", "-c", "sample-ldap-injection.cfg")
|
|
batteryOfTests(
|
|
t,
|
|
svc, testEnv{
|
|
checkanonymousrootDSE: false,
|
|
checkTOTP: true,
|
|
checkbindUPN: false,
|
|
expectedinfo: "objectClass: top",
|
|
svcdn: "cn=serviceuser,cn=svcaccts,ou=users,dc=glauth,dc=com",
|
|
svcdnnogroup: "", // ignore
|
|
otpdn: "cn=otpuser,cn=superheros,ou=users,dc=glauth,dc=com",
|
|
expectedaccount: "dn: cn=hackers,cn=superheros,ou=users,dc=glauth,dc=com",
|
|
scopedaccount: "dn: cn=hackers,cn=superheros,dc=glauth,dc=com",
|
|
expectedfirstaccount: "dn: cn=johndoe,cn=superheros,ou=users,dc=glauth,dc=com",
|
|
expectedgroup: "dn: ou=superheros,ou=users,dc=glauth,dc=com",
|
|
checkemployeetype: "",
|
|
})
|
|
stopSvc(svc)
|
|
})
|
|
}
|
|
}
|
|
|
|
func batteryOfTests(t *testing.T, svc *exec.Cmd, env testEnv) {
|
|
Convey("When searching for the 'hackers' user", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdn, "-w", "mysecret", "-x", "-bdc=glauth,dc=com", "cn=hackers")
|
|
Convey("We should find them in the 'superheros' group", func() {
|
|
So(out, ShouldEqual, env.expectedaccount)
|
|
})
|
|
})
|
|
|
|
if env.svcdnnogroup != "" {
|
|
Convey("When searching for the 'hackers' user without binding with a group", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdnnogroup, "-w", "mysecret", "-x", "-bdc=glauth,dc=com", "cn=hackers")
|
|
Convey("We should find them in the 'superheros' group", func() {
|
|
So(out, ShouldEqual, env.expectedaccount)
|
|
})
|
|
})
|
|
}
|
|
|
|
if env.checkbindUPN {
|
|
Convey("When searching for the 'hackers' user after binding using the account's UPN", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", "serviceuser@example.com", "-w", "mysecret", "-x", "-bdc=glauth,dc=com", "cn=hackers")
|
|
Convey("We should find them in the 'superheros' group", func() {
|
|
So(out, ShouldEqual, env.expectedaccount)
|
|
})
|
|
})
|
|
}
|
|
|
|
Convey("When querying the root SDE", func() {
|
|
out := doRunGetSecond(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdn, "-w", "mysecret", "-x", "-s", "base", "(objectclass=*)")
|
|
Convey("We should get some meta information", func() {
|
|
So(out, ShouldEqual, env.expectedinfo)
|
|
})
|
|
})
|
|
|
|
if env.checkanonymousrootDSE {
|
|
Convey("When querying the root SDE anonymously without authorizing in config file", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-x", "-s", "base", "(objectclass=*)")
|
|
Convey("We should get error 50", func() {
|
|
So(out, ShouldEqual, "exit status 50")
|
|
})
|
|
})
|
|
}
|
|
|
|
Convey("When enumerating posix groups", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdn, "-w", "mysecret", "-x", "-bdc=glauth,dc=com", "(objectclass=posixgroup)")
|
|
Convey("We should get a list starting with the 'superheros' group", func() {
|
|
So(out, ShouldEqual, env.expectedgroup)
|
|
})
|
|
})
|
|
|
|
Convey("When searching for members of the 'superheros' group", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdn, "-w", "mysecret", "-x", "-bdc=glauth,dc=com", "(memberOf=ou=superheros,ou=groups,dc=glauth,dc=com)")
|
|
Convey("We should get a list starting with the 'hackers' user", func() {
|
|
So(out, ShouldEqual, env.expectedfirstaccount)
|
|
})
|
|
})
|
|
|
|
Convey("When performing a complex search for members of 'superheros' group", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdn, "-w", "mysecret", "-x", "-bdc=glauth,dc=com", "(&(objectClass=*)(memberOf=ou=superheros,ou=groups,dc=glauth,dc=com))")
|
|
Convey("We should get a list starting with the 'hackers' user", func() {
|
|
So(out, ShouldEqual, env.expectedfirstaccount)
|
|
})
|
|
})
|
|
|
|
if env.checkTOTP {
|
|
Convey("When searching for the 'hacker' user using a TOTP-enabled account", func() {
|
|
otpvalue := doRunGetFirst(RD, "oathtool", "--totp", "-b", "-d", "6", "3hnvnk4ycv44glzigd6s25j4dougs3rk")
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.otpdn, "-w", "mysecret"+otpvalue, "-x", "-bou=superheros,dc=glauth,dc=com", "cn=hackers")
|
|
Convey("We should find them in in the 'superheros' group", func() {
|
|
So(out, ShouldEqual, env.scopedaccount)
|
|
})
|
|
})
|
|
|
|
Convey("When searching for the 'hacker' user using a TOTP-enabled account and no value", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.otpdn, "-w", "mysecret", "-x", "-bou=superheros,dc=glauth,dc=com", "cn=hackers")
|
|
Convey("We should get 'Invalid credentials(49)'", func() {
|
|
So(out, ShouldEqual, "exit status 49")
|
|
})
|
|
})
|
|
|
|
Convey("When searching for the 'hacker' user using a TOTP-enabled account and the wrong value", func() {
|
|
out := doRunGetFirst(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.otpdn, "-w", "mysecret123456", "-x", "-bou=superheros,dc=glauth,dc=com", "cn=hackers")
|
|
Convey("We should get 'Invalid credentials(49)'", func() {
|
|
So(out, ShouldEqual, "exit status 49")
|
|
})
|
|
})
|
|
}
|
|
|
|
if env.checkemployeetype != "" {
|
|
Convey("When searching for the 'hacker' user", func() {
|
|
out := doRunGetSecond(RD, "ldapsearch", "-LLL", "-H", "ldap://localhost:3893", "-D", env.svcdn, "-w", "mysecret", "-x", "-bdc=glauth,dc=com", env.checkemployeetype, "employeetype")
|
|
Convey("Employee type should be 'Intern'", func() {
|
|
So(out, ShouldEqual, "employeetype: Intern")
|
|
})
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
// -----=============================================================================----
|
|
|
|
const SD = 3 // Start Delay
|
|
const RD = 2 // Response Delay
|
|
|
|
func startSvc(delay time.Duration, name string, arg ...string) *exec.Cmd {
|
|
cmd := exec.Command(name, arg...)
|
|
cmd.Start()
|
|
if delay != 0 {
|
|
time.Sleep(time.Second * delay)
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
func stopSvc(svc *exec.Cmd) {
|
|
svc.Process.Kill()
|
|
}
|
|
|
|
func doRunGetFirst(delay time.Duration, name string, arg ...string) string {
|
|
out := strings.SplitN(doRun(delay, name, arg...), "\n", 2)
|
|
if out == nil || len(out) < 1 {
|
|
return "*fail*"
|
|
}
|
|
return out[0]
|
|
}
|
|
|
|
func doRunGetSecond(delay time.Duration, name string, arg ...string) string {
|
|
out := strings.SplitN(doRun(delay, name, arg...), "\n", 3)
|
|
if out == nil || len(out) < 2 {
|
|
return "*fail*"
|
|
}
|
|
return out[1]
|
|
}
|
|
|
|
func doRun(delay time.Duration, name string, arg ...string) string {
|
|
out, err := exec.Command(name, arg...).Output()
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
if delay != 0 {
|
|
time.Sleep(time.Second * delay)
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|