Beispiel #1
0
func Login(user, pass, secret string) (string, error) {
	if skipLogin {
		return "dummysecret", nil // just let everything pass
	}
	// Checking if we are already logged in
	var LDAPConn *ldap.LDAPConnection
	req := &Request{user, secret, false, make(chan bool)}
	LookupSession(req)
	if !req.LoggedIn {
		LDAPConn = ldap.NewLDAPSSLConnection(LdapServer, LdapPort, TlsConfig)
		err := LDAPConn.Connect()
		if err != nil {
			return "", err
		}
		err = LoginBind(user, pass, LDAPConn)
		if err != nil {
			return "", err
		}
		now := strconv.FormatInt(time.Now().Unix(), 10)
		sec := string(crypto.Encrypt([]byte(pass + now)))
		re := regexp.MustCompile("[^a-zA-Z0-9]")
		sec = re.ReplaceAllString(sec, "")
		req.Secret = sec
	}
	CreateSession(req, LDAPConn)
	return req.Secret, nil
}
func (s *Server) authenticate(username, password string) (r bool, e error) {
	l := ldap.NewLDAPSSLConnection(*host, uint16(*port), tlsConfig)
	e = l.Connect()
	if e != nil {
		return
	}

	defer l.Close()
	dn := fmt.Sprintf(*userf, username)
	e = l.Bind(dn, password)

	if e == nil {
		r = true
	}
	return
}
Beispiel #3
0
func LdapAuthenticator(options *LdapOptions) (martini.Handler, error) {
	hostInfo := HostExpr.FindStringSubmatch(options.Host)

	config := &ldapConfig{}
	switch hostInfo[1] {
	case "ldap":
		config.SSL = false
	case "ldaps":
		config.SSL = true
	default:
		return nil, fmt.Errorf("invalid ldap protocol: %s", hostInfo[1])
	}
	config.Host = hostInfo[2]

	if hostInfo[4] != "" {
		port, err := strconv.ParseUint(hostInfo[4], 10, 16)
		if err != nil {
			return nil, fmt.Errorf("unable to parse ldap port: %s", err)
		}
		config.Port = uint16(port)
	} else {
		if config.SSL {
			config.Port = 636
		} else {
			config.Port = 389
		}
	}

	return func(res http.ResponseWriter, req *http.Request, c martini.Context, log *log.Logger) {
		// HACK TODO: do not put routing logic in the auth handler
		// The /ping endpoint does not have auth, so explicitly exclude it here
		if req.URL.Path == "/ping" {
			return
		}

		authHandler := auth.BasicFunc(func(username, password string) bool {
			// create the ldap server connection
			var conn *ldap.LDAPConnection
			if config.SSL {
				tlsConfig := tls.Config{
					ServerName: config.Host,
				}
				conn = ldap.NewLDAPSSLConnection(config.Host, config.Port, &tlsConfig)
			} else {
				conn = ldap.NewLDAPConnection(config.Host, config.Port)
			}

			// attempt to connect to the ldap server
			if err := conn.Connect(); err != nil {
				log.Printf("Unable to connect to LDAP: %s", err)
				return false
			}

			// perform an anonymous search for the user's dn so we can attempt to bind as them
			req := ldap.SearchRequest{
				BaseDN: options.BaseDN,
				Filter: fmt.Sprintf(options.UserFilter, ldap.EscapeFilterValue(username)),
				Scope:  ldap.ScopeWholeSubtree,
			}
			res, err := conn.Search(&req)
			if err != nil {
				log.Printf("Error performing LDAP search: %s", err)
				return false
			}

			// Return false if the number of entries isn't exactly 1.  If multiple
			// results were returned, there is an ambiguity so return false instead
			// of proceeding. If no entries were returned, we have no idea who this
			// is and cannot authenticate.
			if len(res.Entries) != 1 {
				if len(res.Entries) > 1 {
					log.Printf("User '%s' attempted to authenticate but multiple entries exists", username)
				} else {
					log.Printf("User '%s' attempted to authenticate but does not exist", username)
				}
				return false
			}

			dn := res.Entries[0].DN
			if err := conn.Bind(dn, password); err != nil {
				log.Printf("User '%s' attempted to authenticate but provided an invalid password", username)
				return false
			}
			log.Printf("Authenticated successfully as %s", username)
			return true
		})
		authenticate := authHandler.(func(http.ResponseWriter, *http.Request, martini.Context))
		authenticate(res, req, c)
	}, nil
}