2014-04-22 20:55:27 +04:00
// Copyright github.com/juju2013. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// package ldap provide functions & structure to query a LDAP ldap directory
// For now, it's mainly tested again an MS Active Directory service, see README.md for more information
package ldap
import (
"fmt"
2014-05-03 06:48:14 +04:00
2014-04-22 20:55:27 +04:00
"github.com/gogits/gogs/modules/log"
goldap "github.com/juju2013/goldap"
)
// Basic LDAP authentication service
2014-05-03 06:48:14 +04:00
type Ldapsource struct {
2014-04-22 20:55:27 +04:00
Name string // canonical name (ie. corporate.ad)
Host string // LDAP host
Port int // port number
BaseDN string // Base DN
Attributes string // Attribut to search
Filter string // Query filter to validate entry
MsAdSAFormat string // in the case of MS AD Simple Authen, the format to use (see: http://msdn.microsoft.com/en-us/library/cc223499.aspx)
Enabled bool // if this source is disabled
}
//Global LDAP directory pool
var (
2014-05-03 06:48:14 +04:00
Authensource [ ] Ldapsource
2014-04-22 20:55:27 +04:00
)
// Add a new source (LDAP directory) to the global pool
func AddSource ( name string , host string , port int , basedn string , attributes string , filter string , msadsaformat string ) {
2014-05-03 06:48:14 +04:00
ldaphost := Ldapsource { name , host , port , basedn , attributes , filter , msadsaformat , true }
2014-04-22 20:55:27 +04:00
Authensource = append ( Authensource , ldaphost )
}
//LoginUser : try to login an user to LDAP sources, return requested (attribut,true) if ok, ("",false) other wise
//First match wins
//Returns first attribute if exists
func LoginUser ( name , passwd string ) ( a string , r bool ) {
r = false
for _ , ls := range Authensource {
a , r = ls . searchEntry ( name , passwd )
if r {
return
}
}
return
}
// searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter
2014-05-03 06:48:14 +04:00
func ( ls Ldapsource ) searchEntry ( name , passwd string ) ( string , bool ) {
2014-04-22 20:55:27 +04:00
l , err := goldap . Dial ( "tcp" , fmt . Sprintf ( "%s:%d" , ls . Host , ls . Port ) )
if err != nil {
log . Debug ( "LDAP Connect error, disabled source %s" , ls . Host )
ls . Enabled = false
return "" , false
}
defer l . Close ( )
nx := fmt . Sprintf ( ls . MsAdSAFormat , name )
err = l . Bind ( nx , passwd )
if err != nil {
log . Debug ( "LDAP Authan failed for %s, reason: %s" , nx , err . Error ( ) )
return "" , false
}
search := goldap . NewSearchRequest (
ls . BaseDN ,
goldap . ScopeWholeSubtree , goldap . NeverDerefAliases , 0 , 0 , false ,
fmt . Sprintf ( ls . Filter , name ) ,
[ ] string { ls . Attributes } ,
nil )
sr , err := l . Search ( search )
if err != nil {
log . Debug ( "LDAP Authen OK but not in filter %s" , name )
return "" , false
}
log . Debug ( "LDAP Authen OK: %s" , name )
if len ( sr . Entries ) > 0 {
r := sr . Entries [ 0 ] . GetAttributeValue ( ls . Attributes )
return r , true
}
return "" , true
}