forked from flatfeestack/fastauth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ldap.go
122 lines (109 loc) · 3.46 KB
/
ldap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
ldapClient "github.com/go-ldap/ldap/v3"
"github.com/lor00x/goldap/message"
log "github.com/sirupsen/logrus"
ldap "github.com/vjeantet/ldapserver"
"strings"
)
func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
r := m.GetBindRequest()
cn := getAttrDN(string(r.Name()), "cn")
pass := string(r.AuthenticationSimple())
if opts.OAuthUser != "" || opts.OAuthPass != "" {
if !(opts.OAuthUser == cn && opts.OAuthPass == pass) {
_, errString, err := checkEmailPassword(cn, string(r.AuthenticationSimple()))
if err != nil {
res := ldap.NewBindResponse(ldap.LDAPResultInvalidCredentials)
if opts.DetailedError {
res.SetDiagnosticMessage(fmt.Sprintf("invalid credentials for %v, %v", string(r.Name()), errString))
}
w.Write(res)
return
}
}
} else {
res := ldap.NewBindResponse(ldap.LDAPResultInvalidCredentials)
if opts.DetailedError {
res.SetDiagnosticMessage("system user need to be set in OAUTH_USER and OAUTH_PASS")
}
w.Write(res)
}
res := ldap.NewBindResponse(ldap.LDAPResultSuccess)
w.Write(res)
}
/*
* Parses a distinguished name and returns the CN portion.
* Given a non-conforming string (such as an already-extracted CN),
* it will be returned as-is.
*/
//https://github.com/chrishoffman/vault
//https://github.com/chrishoffman/vault/blob/master/builtin/credential/ldap/backend.go
func getAttrDN(dn string, atyp string) string {
log.Printf("parsing basedn %v", dn)
parsedDN, err := ldapClient.ParseDN(dn)
if err != nil || len(parsedDN.RDNs) == 0 {
// It was already a CN, return as-is
log.Printf("could not parse %v, %v", dn, err)
return dn
}
for _, rdn := range parsedDN.RDNs {
for _, rdnAttr := range rdn.Attributes {
log.Printf("found attr %v", rdnAttr.Type)
if strings.ToLower(rdnAttr.Type) == strings.ToLower(atyp) {
return rdnAttr.Value
}
}
}
// Default, return self
log.Printf("default attr %v", dn)
return dn
}
func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
r := m.GetSearchRequest()
log.Printf("Request BaseDn=%s, Request Filter=%s, Request FilterString=%s, Request Attributes=%s, Request TimeLimit=%d",
r.BaseObject(), r.Filter(), r.FilterString(), r.Attributes(), r.TimeLimit().Int())
// Handle Stop Signal (server stop / client disconnected / Abandoned request....)
select {
case <-m.Done:
log.Print("Leaving handleSearch...")
return
default:
}
var cn string
if strings.Index(string(r.BaseObject()), "cn") >= 0 {
cn = getAttrDN(string(r.BaseObject()), "cn")
} else if strings.Index(r.FilterString(), "cn") >= 0 {
cn = getAttrDN(r.FilterString(), "cn")
} else {
log.Errorf("no cn found in [%v]", r.BaseObject())
res := ldap.NewSearchResultDoneResponse(ldap.LDAPResultNoSuchObject)
w.Write(res)
return
}
dbRes, err := findAuthByEmail(cn)
if err != nil {
log.Errorf("cannot find user? %v", err)
res := ldap.NewSearchResultDoneResponse(ldap.LDAPResultUnwillingToPerform)
w.Write(res)
return
}
e := ldap.NewSearchResultEntry("cn=" + cn + ", " + string(r.BaseObject()))
if dbRes.metaSystem != nil {
jsonMapSystem, err := toJsonMap(dbRes.metaSystem)
if err != nil {
log.Errorf("no json stored? %v", err)
res := ldap.NewSearchResultDoneResponse(ldap.LDAPResultUnwillingToPerform)
w.Write(res)
return
}
group := jsonMapSystem["ldap_group"]
if group != nil {
e.AddAttribute("cn", message.AttributeValue(group.(string)))
}
}
w.Write(e)
res := ldap.NewSearchResultDoneResponse(ldap.LDAPResultSuccess)
w.Write(res)
}