Added username/password auth
This commit is contained in:
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"git.thequux.com/thequux/ipasso/sso-proxy/backend"
|
||||
"git.thequux.com/thequux/ipasso/util"
|
||||
"git.thequux.com/thequux/ipasso/util/genpool"
|
||||
@@ -35,8 +36,10 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoValidServer = errors.New("no valid server")
|
||||
ldapRootLogger, ldapPoolLogger *zap.Logger
|
||||
ErrNoValidServer = errors.New("no valid server")
|
||||
ErrLoginFailed = errors.New("login failed")
|
||||
ldapRootLogger *zap.Logger
|
||||
ldapPoolLogger *zap.Logger
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -67,6 +70,9 @@ func init() {
|
||||
ldapRootLogger.Debug("Configured LDAP rootDN", zap.String("rootDN", *ldapRootDN))
|
||||
}
|
||||
|
||||
// configure username basedn
|
||||
ldapUserBase = "cn=users,cn=accounts," + *ldapRootDN
|
||||
|
||||
krb5Config, err := config.Load(*krb5conf)
|
||||
var realmSource string = ""
|
||||
if err != nil {
|
||||
@@ -260,7 +266,31 @@ func getUserByPrincipal(principal string) (*ldap.Entry, error) {
|
||||
func getUserByDn(dn string) (*ldap.Entry, error) {
|
||||
return ldapSearchSingle(&ldap.SearchRequest{
|
||||
BaseDN: dn,
|
||||
Filter: "(objectClass=top)",
|
||||
Scope: ldap.ScopeBaseObject,
|
||||
Attributes: interestingUserAttr,
|
||||
})
|
||||
}
|
||||
|
||||
func getUserByUsernamePassword(username, password string) (*ldap.Entry, error) {
|
||||
server := selectServer()
|
||||
if server == nil {
|
||||
return nil, ErrNoValidServer
|
||||
}
|
||||
conn, err := ldap.DialURL(server.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// try bind
|
||||
userDN := fmt.Sprintf("uid=%s,%s", username, ldapUserBase)
|
||||
//ldapRootLogger.Debug("Attempting bind login", zap.String("user", userDN), zap.String("password", password))
|
||||
err = conn.Bind(userDN, password)
|
||||
if err != nil {
|
||||
return nil, ErrLoginFailed
|
||||
}
|
||||
|
||||
//ldapRootLogger.Info("Successfully authorized using simple bind", zap.String("user", username), zap.String("dn", userDN))
|
||||
return getUserByDn(userDN)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.thequux.com/thequux/ipasso/sso-proxy/backend"
|
||||
"git.thequux.com/thequux/ipasso/util/startup"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
startup.Routes.Add(func(router *httprouter.Router) {
|
||||
router.HandlerFunc("POST", "/login/krb5", loginKrb)
|
||||
router.HandlerFunc("POST", "/login/password", loginPassword)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,7 +25,6 @@ func loginKrb(w http.ResponseWriter, r *http.Request) {
|
||||
// The fact that we got here implies that the login succeeded
|
||||
env := fcgi.ProcessEnv(r)
|
||||
user := env["GSS_NAME"]
|
||||
uid := strings.Split(user, "@")[0]
|
||||
expirationTxt, hasExpiration := env["GSS_SESSION_EXPIRATION"]
|
||||
var expiration time.Time
|
||||
if hasExpiration {
|
||||
@@ -41,21 +42,64 @@ func loginKrb(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
SessionID, err := datastore.NewSessionID()
|
||||
if err != nil {
|
||||
ReportError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
entry, err := getUserByPrincipal(user)
|
||||
if err != nil {
|
||||
ReportError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
finishLogin(w, r, entry, &expiration)
|
||||
}
|
||||
|
||||
func loginPassword(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
ReportError(w, err)
|
||||
}
|
||||
user := r.Form.Get("user")
|
||||
password := r.Form.Get("password")
|
||||
|
||||
if user == "" || password == "" {
|
||||
ldapRootLogger.Debug("Missing value")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
entry, err := getUserByUsernamePassword(user, password)
|
||||
if errors.Is(err, ErrLoginFailed) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
} else if err != nil {
|
||||
ReportError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
finishLogin(w, r, entry, nil)
|
||||
}
|
||||
|
||||
func finishLogin(w http.ResponseWriter, req *http.Request, entry *ldap.Entry, expiration *time.Time) {
|
||||
SessionID, err := datastore.NewSessionID()
|
||||
if err != nil {
|
||||
ReportError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var uid string
|
||||
for _, attr := range entry.Attributes {
|
||||
if attr.Name == "uid" && len(attr.Values) > 0 {
|
||||
uid = attr.Values[0]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make configurable
|
||||
if expiration == nil {
|
||||
defExpiration := time.Now().Add(time.Hour * 14)
|
||||
expiration = &defExpiration
|
||||
}
|
||||
|
||||
session := backend.Session{
|
||||
SessionID: SessionID,
|
||||
Expiration: expiration,
|
||||
Expiration: *expiration,
|
||||
UserID: uid,
|
||||
LdapDN: entry.DN,
|
||||
}
|
||||
@@ -65,4 +109,6 @@ func loginKrb(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
_ = datastore.PutSession(session, sessionCache)
|
||||
|
||||
// TODO: set cookies, return success
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user