Initial commit

This commit is contained in:
Kylie Czar
2021-05-16 15:22:20 -03:00
commit 6455a1a71c
10 changed files with 240 additions and 0 deletions

5
.env.default Normal file
View 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
View File

@@ -0,0 +1,7 @@
BINARY_NAME = fsldap
build:
go build -v
run: build
./$(BINARY_NAME)

23
README.org Normal file
View 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
View File

@@ -0,0 +1,5 @@
package config
var SmtpHostname, SmtpPort, Domain, Base, Uid string
var BaseLenght, UidLenght int

52
fsldap.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
}