Sanitizing input to LDAP authentication module.
This commit is contained in:
parent
b9f5def5dc
commit
630ebbe6c2
1 changed files with 39 additions and 3 deletions
|
@ -9,6 +9,7 @@ package ldap
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/ldap"
|
"github.com/gogits/gogs/modules/ldap"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
|
@ -33,6 +34,28 @@ type Source struct {
|
||||||
Enabled bool // if this source is disabled
|
Enabled bool // if this source is disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ls *Source) sanitizedUserQuery(username string) (string, bool) {
|
||||||
|
// See http://tools.ietf.org/search/rfc4515
|
||||||
|
badCharacters := "\x00()*\\"
|
||||||
|
if strings.ContainsAny(username, badCharacters) {
|
||||||
|
log.Debug("'%s' contains invalid query characters. Aborting.", username)
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(ls.Filter, username), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *Source) sanitizedUserDN(username string) (string, bool) {
|
||||||
|
// See http://tools.ietf.org/search/rfc4514: "special characters"
|
||||||
|
badCharacters := "\x00()*\\,='\"#+;<> "
|
||||||
|
if strings.ContainsAny(username, badCharacters) {
|
||||||
|
log.Debug("'%s' contains invalid DN characters. Aborting.", username)
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(ls.UserDN, username), true
|
||||||
|
}
|
||||||
|
|
||||||
func (ls *Source) FindUserDN(name string) (string, bool) {
|
func (ls *Source) FindUserDN(name string) (string, bool) {
|
||||||
l, err := ldapDial(ls)
|
l, err := ldapDial(ls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -55,7 +78,11 @@ func (ls *Source) FindUserDN(name string) (string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A search for the user.
|
// A search for the user.
|
||||||
userFilter := fmt.Sprintf(ls.Filter, name)
|
userFilter, ok := ls.sanitizedUserQuery(name)
|
||||||
|
if !ok {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
log.Trace("Searching using filter %s", userFilter)
|
log.Trace("Searching using filter %s", userFilter)
|
||||||
search := ldap.NewSearchRequest(
|
search := ldap.NewSearchRequest(
|
||||||
ls.UserBase, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0,
|
ls.UserBase, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0,
|
||||||
|
@ -85,7 +112,12 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
|
||||||
var userDN string
|
var userDN string
|
||||||
if directBind {
|
if directBind {
|
||||||
log.Trace("LDAP will bind directly via UserDN template: %s", ls.UserDN)
|
log.Trace("LDAP will bind directly via UserDN template: %s", ls.UserDN)
|
||||||
userDN = fmt.Sprintf(ls.UserDN, name)
|
|
||||||
|
var ok bool
|
||||||
|
userDN, ok = ls.sanitizedUserDN(name)
|
||||||
|
if !ok {
|
||||||
|
return "", "", "", false, false
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Trace("LDAP will use BindDN.")
|
log.Trace("LDAP will use BindDN.")
|
||||||
|
|
||||||
|
@ -112,7 +144,11 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace("Bound successfully with userDN: %s", userDN)
|
log.Trace("Bound successfully with userDN: %s", userDN)
|
||||||
userFilter := fmt.Sprintf(ls.Filter, name)
|
userFilter, ok := ls.sanitizedUserQuery(name)
|
||||||
|
if !ok {
|
||||||
|
return "", "", "", false, false
|
||||||
|
}
|
||||||
|
|
||||||
search := ldap.NewSearchRequest(
|
search := ldap.NewSearchRequest(
|
||||||
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
|
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
|
||||||
[]string{ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
|
[]string{ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
|
||||||
|
|
Reference in a new issue