Initial commit
This commit is contained in:
5
.env.default
Normal file
5
.env.default
Normal file
@@ -0,0 +1,5 @@
|
||||
SMTP_HOSTNAME = "localhost"
|
||||
SMTP_PORT = "25"
|
||||
SMTP_DOMAIN = "example.com"
|
||||
LDAP_BASE = "dn=example,dn=com"
|
||||
LDAP_UID = "cn"
|
||||
7
Makefile
Normal file
7
Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
BINARY_NAME = fsldap
|
||||
|
||||
build:
|
||||
go build -v
|
||||
|
||||
run: build
|
||||
./$(BINARY_NAME)
|
||||
23
README.org
Normal file
23
README.org
Normal file
@@ -0,0 +1,23 @@
|
||||
#+TITLE: Fake SMTP LDAP Server
|
||||
#+AUTHOR: czar
|
||||
|
||||
A LDAP server that use SMTP as authentication source
|
||||
|
||||
* Features
|
||||
- LDAP BIND
|
||||
- LDAP SEARCH
|
||||
|
||||
* Build
|
||||
fsldap is a written in Go, so you will need to install the Golang compiler
|
||||
#+BEGIN_QUOTE
|
||||
$ make build
|
||||
#+END_QUOTE
|
||||
|
||||
* Configuration
|
||||
copy the =.env.default= to =.env= and set your variables accordly
|
||||
|
||||
* Running
|
||||
#+BEGIN_QUOTE
|
||||
$ make run
|
||||
#+END_QUOTE
|
||||
|
||||
5
config/main.go
Normal file
5
config/main.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package config
|
||||
|
||||
var SmtpHostname, SmtpPort, Domain, Base, Uid string
|
||||
var BaseLenght, UidLenght int
|
||||
|
||||
52
fsldap.go
Normal file
52
fsldap.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
ldap "github.com/vjeantet/ldapserver"
|
||||
|
||||
"gt.kalli.st/czar/fsldap/config"
|
||||
"gt.kalli.st/czar/fsldap/handler"
|
||||
"gt.kalli.st/czar/fsldap/utils"
|
||||
)
|
||||
|
||||
|
||||
func init(){
|
||||
log.Print("Loading vars...")
|
||||
config.SmtpHostname = utils.Env("SMTP_HOSTNAME")
|
||||
config.SmtpPort = utils.Env("SMTP_PORT")
|
||||
config.Domain = utils.Env("SMTP_DOMAIN")
|
||||
config.Base = utils.Env("LDAP_BASE")
|
||||
config.Uid = utils.Env("LDAP_UID")
|
||||
config.BaseLenght = len(config.Base) + 1
|
||||
config.UidLenght = len(config.Uid) + 1
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
server := ldap.NewServer()
|
||||
routes := ldap.NewRouteMux()
|
||||
routes.Bind(handler.Bind)
|
||||
routes.Extended(handler.WhoAmI).
|
||||
RequestName(ldap.NoticeOfWhoAmI).Label("Ext - WhoAmI")
|
||||
routes.Search(handler.Search).Label("Search - Generic")
|
||||
|
||||
server.Handle(routes)
|
||||
|
||||
log.Print("Starting FSLDAP server...")
|
||||
go func(){
|
||||
err := server.ListenAndServe("127.0.0.1:389")
|
||||
if err != nil{
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-ch
|
||||
close(ch)
|
||||
server.Stop()
|
||||
}
|
||||
|
||||
9
go.mod
Normal file
9
go.mod
Normal file
@@ -0,0 +1,9 @@
|
||||
module gt.kalli.st/czar/fsldap
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/joho/godotenv v1.3.0 // indirect
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
|
||||
github.com/vjeantet/ldapserver v1.0.1
|
||||
)
|
||||
6
go.sum
Normal file
6
go.sum
Normal file
@@ -0,0 +1,6 @@
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
||||
github.com/vjeantet/ldapserver v1.0.1 h1:3z+TCXhwwDLJC3pZCNbuECPDqC2x1R7qQQbswB1Qwoc=
|
||||
github.com/vjeantet/ldapserver v1.0.1/go.mod h1:YvUqhu5vYhmbcLReMLrm/Tq3S7Yj43kSVFvvol6Lh6k=
|
||||
74
handler/ldap_handlers.go
Normal file
74
handler/ldap_handlers.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
|
||||
"github.com/lor00x/goldap/message"
|
||||
ldap "github.com/vjeantet/ldapserver"
|
||||
|
||||
"gt.kalli.st/czar/fsldap/config"
|
||||
"gt.kalli.st/czar/fsldap/utils"
|
||||
)
|
||||
|
||||
|
||||
var smtpHost = config.SmtpHostname
|
||||
var smtpHostPort = fmt.Sprintf("%s:%s", smtpHost,config.SmtpPort)
|
||||
|
||||
var tlsconfig = &tls.Config {
|
||||
InsecureSkipVerify: true,
|
||||
ServerName: smtpHost,
|
||||
}
|
||||
|
||||
func Bind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
r := m.GetBindRequest()
|
||||
res := ldap.NewBindResponse(ldap.LDAPResultSuccess)
|
||||
name := string(r.Name())
|
||||
password := string(r.AuthenticationSimple())
|
||||
user := utils.GetUser(name)
|
||||
mail := utils.GetMail(user)
|
||||
auth := smtp.PlainAuth("", mail, password, smtpHost)
|
||||
client, error := smtp.Dial(smtpHostPort)
|
||||
if error != nil {
|
||||
res.SetResultCode(ldap.LDAPResultInvalidCredentials)
|
||||
res.SetDiagnosticMessage("invalid credentials")
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
client.StartTLS(tlsconfig)
|
||||
err := client.Auth(auth)
|
||||
if err != nil {
|
||||
res.SetResultCode(ldap.LDAPResultInvalidCredentials)
|
||||
res.SetDiagnosticMessage("invalid credentials")
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
w.Write(res)
|
||||
}
|
||||
|
||||
func WhoAmI(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
res := ldap.NewExtendedResponse(ldap.LDAPResultSuccess)
|
||||
w.Write(res)
|
||||
}
|
||||
|
||||
func Search(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
r := m.GetSearchRequest()
|
||||
select {
|
||||
case <-m.Done:
|
||||
return
|
||||
default:
|
||||
}
|
||||
name := string(r.FilterString())
|
||||
if name == ""{
|
||||
return
|
||||
}
|
||||
user := utils.GetSearchUser(name)
|
||||
mail := utils.GetMail(user)
|
||||
attr := utils.GetLdapName(user)
|
||||
entry := ldap.NewSearchResultEntry(attr)
|
||||
entry.AddAttribute("mail", message.AttributeValue(mail))
|
||||
w.Write(entry)
|
||||
response := ldap.NewSearchResultDoneResponse(ldap.LDAPResultSuccess)
|
||||
w.Write(response)
|
||||
}
|
||||
30
utils/dotenv.go
Normal file
30
utils/dotenv.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
|
||||
func init(){
|
||||
loadEnv()
|
||||
}
|
||||
|
||||
func loadEnv(){
|
||||
log.Print("Loading .env file...")
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
log.Fatal("error loading .env file")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func Env(name string) string{
|
||||
envVar := os.Getenv(name)
|
||||
if envVar == "" {
|
||||
log.Fatalf("error getting %s env variable", name)
|
||||
}
|
||||
return envVar
|
||||
}
|
||||
29
utils/ldap.go
Normal file
29
utils/ldap.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gt.kalli.st/czar/fsldap/config"
|
||||
)
|
||||
|
||||
func GetMail(user string) string {
|
||||
return fmt.Sprintf("%s@%s", user, config.Domain)
|
||||
}
|
||||
|
||||
func GetLdapName(user string) string {
|
||||
return fmt.Sprintf("%s=%s,%s", config.Uid, user, config.Base)
|
||||
}
|
||||
|
||||
func GetUser(name string) string {
|
||||
endIndex := len(name) - config.BaseLenght
|
||||
user := name[config.UidLenght:endIndex]
|
||||
return user
|
||||
}
|
||||
|
||||
func GetSearchUser(name string) string {
|
||||
startIndex := config.UidLenght + 1
|
||||
endIndex := len(name) - 1
|
||||
user := name[startIndex:endIndex]
|
||||
return user
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user