ldap.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright github.com/juju2013. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. // package ldap provide functions & structure to query a LDAP ldap directory
  5. // For now, it's mainly tested again an MS Active Directory service, see README.md for more information
  6. package ldap
  7. import (
  8. "fmt"
  9. "github.com/gogits/gogs/modules/ldap"
  10. "github.com/gogits/gogs/modules/log"
  11. )
  12. // Basic LDAP authentication service
  13. type Ldapsource struct {
  14. Name string // canonical name (ie. corporate.ad)
  15. Host string // LDAP host
  16. Port int // port number
  17. UseSSL bool // Use SSL
  18. BaseDN string // Base DN
  19. AttributeUsername string // Username attribute
  20. AttributeName string // First name attribute
  21. AttributeSurname string // Surname attribute
  22. AttributeMail string // E-mail attribute
  23. Filter string // Query filter to validate entry
  24. MsAdSAFormat string // in the case of MS AD Simple Authen, the format to use (see: http://msdn.microsoft.com/en-us/library/cc223499.aspx)
  25. Enabled bool // if this source is disabled
  26. }
  27. //Global LDAP directory pool
  28. var (
  29. Authensource []Ldapsource
  30. )
  31. // Add a new source (LDAP directory) to the global pool
  32. func AddSource(name string, host string, port int, usessl bool, basedn string, attribcn string, attribname string, attribsn string, attribmail string, filter string, msadsaformat string) {
  33. ldaphost := Ldapsource{name, host, port, usessl, basedn, attribcn, attribname, attribsn, attribmail, filter, msadsaformat, true}
  34. Authensource = append(Authensource, ldaphost)
  35. }
  36. //LoginUser : try to login an user to LDAP sources, return requested (attribute,true) if ok, ("",false) other wise
  37. //First match wins
  38. //Returns first attribute if exists
  39. func LoginUser(name, passwd string) (cn, fn, sn, mail string, r bool) {
  40. r = false
  41. for _, ls := range Authensource {
  42. cn, fn, sn, mail, r = ls.SearchEntry(name, passwd)
  43. if r {
  44. return
  45. }
  46. }
  47. return
  48. }
  49. // searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter
  50. func (ls Ldapsource) SearchEntry(name, passwd string) (string, string, string, string, bool) {
  51. l, err := ldapDial(ls)
  52. if err != nil {
  53. log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err)
  54. ls.Enabled = false
  55. return "", "", "", "", false
  56. }
  57. defer l.Close()
  58. nx := fmt.Sprintf(ls.MsAdSAFormat, name)
  59. err = l.Bind(nx, passwd)
  60. if err != nil {
  61. log.Debug("LDAP Authan failed for %s, reason: %s", nx, err.Error())
  62. return "", "", "", "", false
  63. }
  64. search := ldap.NewSearchRequest(
  65. ls.BaseDN,
  66. ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
  67. fmt.Sprintf(ls.Filter, name),
  68. []string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
  69. nil)
  70. sr, err := l.Search(search)
  71. if err != nil {
  72. log.Debug("LDAP Authen OK but not in filter %s", name)
  73. return "", "", "", "", false
  74. }
  75. log.Debug("LDAP Authen OK: %s", name)
  76. if len(sr.Entries) > 0 {
  77. cn := sr.Entries[0].GetAttributeValue(ls.AttributeUsername)
  78. name := sr.Entries[0].GetAttributeValue(ls.AttributeName)
  79. sn := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
  80. mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
  81. return cn, name, sn, mail, true
  82. }
  83. return "", "", "", "", true
  84. }
  85. func ldapDial(ls Ldapsource) (*ldap.Conn, error) {
  86. if ls.UseSSL {
  87. return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), nil)
  88. } else {
  89. return ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
  90. }
  91. }