You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.9 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  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. Attributes string // Attribut to search
  20. Filter string // Query filter to validate entry
  21. MsAdSAFormat string // in the case of MS AD Simple Authen, the format to use (see: http://msdn.microsoft.com/en-us/library/cc223499.aspx)
  22. Enabled bool // if this source is disabled
  23. }
  24. //Global LDAP directory pool
  25. var (
  26. Authensource []Ldapsource
  27. )
  28. // Add a new source (LDAP directory) to the global pool
  29. func AddSource(name string, host string, port int, usessl bool, basedn string, attributes string, filter string, msadsaformat string) {
  30. ldaphost := Ldapsource{name, host, port, usessl, basedn, attributes, filter, msadsaformat, true}
  31. Authensource = append(Authensource, ldaphost)
  32. }
  33. //LoginUser : try to login an user to LDAP sources, return requested (attribut,true) if ok, ("",false) other wise
  34. //First match wins
  35. //Returns first attribute if exists
  36. func LoginUser(name, passwd string) (a string, r bool) {
  37. r = false
  38. for _, ls := range Authensource {
  39. a, r = ls.SearchEntry(name, passwd)
  40. if r {
  41. return
  42. }
  43. }
  44. return
  45. }
  46. // searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter
  47. func (ls Ldapsource) SearchEntry(name, passwd string) (string, bool) {
  48. l, err := ldapDial(ls)
  49. if err != nil {
  50. log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err)
  51. ls.Enabled = false
  52. return "", false
  53. }
  54. defer l.Close()
  55. nx := fmt.Sprintf(ls.MsAdSAFormat, name)
  56. err = l.Bind(nx, passwd)
  57. if err != nil {
  58. log.Debug("LDAP Authan failed for %s, reason: %s", nx, err.Error())
  59. return "", false
  60. }
  61. search := ldap.NewSearchRequest(
  62. ls.BaseDN,
  63. ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
  64. fmt.Sprintf(ls.Filter, name),
  65. []string{ls.Attributes},
  66. nil)
  67. sr, err := l.Search(search)
  68. if err != nil {
  69. log.Debug("LDAP Authen OK but not in filter %s", name)
  70. return "", false
  71. }
  72. log.Debug("LDAP Authen OK: %s", name)
  73. if len(sr.Entries) > 0 {
  74. r := sr.Entries[0].GetAttributeValue(ls.Attributes)
  75. return r, true
  76. }
  77. return "", true
  78. }
  79. func ldapDial(ls Ldapsource) (*ldap.Conn, error) {
  80. if ls.UseSSL {
  81. return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), nil)
  82. } else {
  83. return ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
  84. }
  85. }