mirror of
https://github.com/ergochat/ergo.git
synced 2026-03-14 03:08:11 +01:00
parent
c61859927f
commit
4e65b76c67
@ -46,6 +46,9 @@ This endpoint verifies the credentials of a NickServ account; this allows Ergo t
|
||||
|
||||
* `accountName`: string, name of the account
|
||||
* `passphrase`: string, alleged passphrase of the account
|
||||
* `certfp`: string, alleged certificate fingerprint (hex-encoded SHA-256 checksum of the decoded raw certificate) associated with the account
|
||||
|
||||
Each individual field is optional, since a user may be authenticated either by account-passphrase pair or by certificate.
|
||||
|
||||
The response is a JSON object with fields:
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -2039,12 +2040,6 @@ func (am *AccountManager) AuthenticateByCertificate(client *Client, certfp strin
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return
|
||||
} else if !clientAccount.Verified {
|
||||
err = errAccountUnverified
|
||||
return
|
||||
} else if clientAccount.Suspended != nil {
|
||||
err = errAccountSuspended
|
||||
return
|
||||
}
|
||||
// TODO(#1109) clean this check up?
|
||||
if client.registered {
|
||||
@ -2057,11 +2052,34 @@ func (am *AccountManager) AuthenticateByCertificate(client *Client, certfp strin
|
||||
return
|
||||
}()
|
||||
|
||||
clientAccount, err = am.checkCertAuth(client.IP(), certfp, peerCerts, authzid)
|
||||
return err
|
||||
}
|
||||
|
||||
func (am *AccountManager) checkCertAuth(ip net.IP, certfp string, peerCerts []*x509.Certificate, authzid string) (clientAccount ClientAccount, err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return
|
||||
} else if !clientAccount.Verified {
|
||||
err = errAccountUnverified
|
||||
return
|
||||
} else if clientAccount.Suspended != nil {
|
||||
err = errAccountSuspended
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
config := am.server.Config()
|
||||
if config.Accounts.AuthScript.Enabled {
|
||||
var output AuthScriptOutput
|
||||
output, err = CheckAuthScript(am.server.semaphores.AuthScript, config.Accounts.AuthScript.ScriptConfig,
|
||||
AuthScriptInput{Certfp: certfp, IP: client.IP().String(), peerCerts: peerCerts})
|
||||
var ipString string
|
||||
if ip != nil {
|
||||
ipString = ip.String()
|
||||
}
|
||||
output, err = CheckAuthScript(
|
||||
am.server.semaphores.AuthScript, config.Accounts.AuthScript.ScriptConfig,
|
||||
AuthScriptInput{Certfp: certfp, IP: ipString, peerCerts: peerCerts},
|
||||
)
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
|
||||
} else if output.Success && output.AccountName != "" {
|
||||
@ -2082,18 +2100,19 @@ func (am *AccountManager) AuthenticateByCertificate(client *Client, certfp strin
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if authzid != "" {
|
||||
if cfAuthzid, err := CasefoldName(authzid); err != nil || cfAuthzid != account {
|
||||
return errAuthzidAuthcidMismatch
|
||||
if cfAuthzid, cErr := CasefoldName(authzid); cErr != nil || cfAuthzid != account {
|
||||
err = errAuthzidAuthcidMismatch
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// ok, we found an account corresponding to their certificate
|
||||
clientAccount, err = am.LoadAccount(account)
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
type settingsMunger func(input AccountSettings) (output AccountSettings, err error)
|
||||
|
||||
38
irc/api.go
38
irc/api.go
@ -130,25 +130,29 @@ func (a *ergoAPI) handleCheckAuth(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var response apiCheckAuthResponse
|
||||
|
||||
// try passphrase if present
|
||||
var account ClientAccount
|
||||
var err error
|
||||
|
||||
// try whatever credentials are present
|
||||
if request.AccountName != "" && request.Passphrase != "" {
|
||||
account, err := a.server.accounts.checkPassphrase(request.AccountName, request.Passphrase)
|
||||
switch err {
|
||||
case nil:
|
||||
// success, no error
|
||||
response.Success = true
|
||||
response.AccountName = account.Name
|
||||
case errAccountDoesNotExist, errAccountInvalidCredentials, errAccountUnverified, errAccountSuspended:
|
||||
// fail, no error
|
||||
response.Success = false
|
||||
default:
|
||||
response.Success = false
|
||||
response.Error = err.Error()
|
||||
}
|
||||
account, err = a.server.accounts.checkPassphrase(request.AccountName, request.Passphrase)
|
||||
} else if request.Certfp != "" {
|
||||
account, err = a.server.accounts.checkCertAuth(nil, request.Certfp, nil, "")
|
||||
} else {
|
||||
err = errAccountInvalidCredentials
|
||||
}
|
||||
// try certfp if present
|
||||
if !response.Success && request.Certfp != "" {
|
||||
// TODO support cerftp
|
||||
|
||||
switch err {
|
||||
case nil:
|
||||
// success, no error
|
||||
response.Success = true
|
||||
response.AccountName = account.Name
|
||||
case errAccountDoesNotExist, errAccountInvalidCredentials, errAccountUnverified, errAccountSuspended:
|
||||
// fail, no error
|
||||
response.Success = false
|
||||
default:
|
||||
response.Success = false
|
||||
response.Error = err.Error()
|
||||
}
|
||||
|
||||
a.writeJSONResponse(response, w, r)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user