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-09-08 04:04:47 +04:00
"github.com/gogits/gogs/modules/ldap"
2014-04-22 20:55:27 +04:00
"github.com/gogits/gogs/modules/log"
)
// 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
2014-05-15 16:21:27 +04:00
UseSSL bool // Use SSL
2014-04-22 20:55:27 +04:00
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
2014-05-15 16:21:27 +04:00
func AddSource ( name string , host string , port int , usessl bool , basedn string , attributes string , filter string , msadsaformat string ) {
ldaphost := Ldapsource { name , host , port , usessl , 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 {
2014-05-11 10:12:45 +04:00
a , r = ls . SearchEntry ( name , passwd )
2014-04-22 20:55:27 +04:00
if r {
return
}
}
return
}
// searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter
2014-05-11 10:12:45 +04:00
func ( ls Ldapsource ) SearchEntry ( name , passwd string ) ( string , bool ) {
2014-05-15 16:21:27 +04:00
l , err := ldapDial ( ls )
2014-04-22 20:55:27 +04:00
if err != nil {
2014-07-26 08:24:27 +04:00
log . Error ( 4 , "LDAP Connect error, %s:%v" , ls . Host , err )
2014-04-22 20:55:27 +04:00
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
}
2014-09-08 04:04:47 +04:00
search := ldap . NewSearchRequest (
2014-04-22 20:55:27 +04:00
ls . BaseDN ,
2014-09-08 04:04:47 +04:00
ldap . ScopeWholeSubtree , ldap . NeverDerefAliases , 0 , 0 , false ,
2014-04-22 20:55:27 +04:00
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
}
2014-05-15 16:21:27 +04:00
2014-09-08 04:04:47 +04:00
func ldapDial ( ls Ldapsource ) ( * ldap . Conn , error ) {
2014-05-15 16:21:27 +04:00
if ls . UseSSL {
2014-09-08 04:04:47 +04:00
return ldap . DialTLS ( "tcp" , fmt . Sprintf ( "%s:%d" , ls . Host , ls . Port ) , nil )
2014-05-15 16:21:27 +04:00
} else {
2014-09-08 04:04:47 +04:00
return ldap . Dial ( "tcp" , fmt . Sprintf ( "%s:%d" , ls . Host , ls . Port ) )
2014-05-15 16:21:27 +04:00
}
}