mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
commit
815852191c
@ -5,6 +5,7 @@ package irc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
@ -1466,7 +1467,7 @@ func (am *AccountManager) ChannelsForAccount(account string) (channels []string)
|
||||
return unmarshalRegisteredChannels(channelStr)
|
||||
}
|
||||
|
||||
func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid string) (err error) {
|
||||
func (am *AccountManager) AuthenticateByCertificate(client *Client, certfp string, peerCerts []*x509.Certificate, authzid string) (err error) {
|
||||
if certfp == "" {
|
||||
return errAccountInvalidCredentials
|
||||
}
|
||||
@ -1495,7 +1496,7 @@ func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid s
|
||||
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()})
|
||||
AuthScriptInput{Certfp: certfp, IP: client.IP().String(), peerCerts: peerCerts})
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
|
||||
} else if output.Success && output.AccountName != "" {
|
||||
|
@ -4,7 +4,9 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
@ -13,9 +15,11 @@ import (
|
||||
|
||||
// JSON-serializable input and output types for the script
|
||||
type AuthScriptInput struct {
|
||||
AccountName string `json:"accountName,omitempty"`
|
||||
Passphrase string `json:"passphrase,omitempty"`
|
||||
Certfp string `json:"certfp,omitempty"`
|
||||
AccountName string `json:"accountName,omitempty"`
|
||||
Passphrase string `json:"passphrase,omitempty"`
|
||||
Certfp string `json:"certfp,omitempty"`
|
||||
PeerCerts []string `json:"peerCerts,omitempty"`
|
||||
peerCerts []*x509.Certificate
|
||||
IP string `json:"ip,omitempty"`
|
||||
}
|
||||
|
||||
@ -31,6 +35,14 @@ func CheckAuthScript(sem utils.Semaphore, config ScriptConfig, input AuthScriptI
|
||||
defer sem.Release()
|
||||
}
|
||||
|
||||
// PEM-encode the peer certificates before applying JSON
|
||||
if len(input.peerCerts) != 0 {
|
||||
input.PeerCerts = make([]string, len(input.peerCerts))
|
||||
for i, cert := range input.peerCerts {
|
||||
input.PeerCerts[i] = string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}))
|
||||
}
|
||||
}
|
||||
|
||||
inputBytes, err := json.Marshal(input)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -6,6 +6,7 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
@ -163,6 +164,7 @@ type Session struct {
|
||||
destroyed uint32
|
||||
|
||||
certfp string
|
||||
peerCerts []*x509.Certificate
|
||||
sasl saslStatus
|
||||
passStatus serverPassStatus
|
||||
|
||||
@ -384,7 +386,7 @@ func (server *Server) RunClient(conn IRCConn) {
|
||||
|
||||
if wConn.Config.TLSConfig != nil {
|
||||
// error is not useful to us here anyways so we can ignore it
|
||||
session.certfp, _ = utils.GetCertFP(wConn.Conn, RegisterTimeout)
|
||||
session.certfp, session.peerCerts, _ = utils.GetCertFP(wConn.Conn, RegisterTimeout)
|
||||
}
|
||||
|
||||
if session.isTor {
|
||||
|
@ -99,6 +99,7 @@ func (client *Client) ApplyProxiedIP(session *Session, proxiedIP net.IP, tls boo
|
||||
// nickmask will be updated when the client completes registration
|
||||
// set tls info
|
||||
session.certfp = ""
|
||||
session.peerCerts = nil
|
||||
client.SetMode(modes.TLS, tls)
|
||||
|
||||
return nil, ""
|
||||
|
@ -303,7 +303,7 @@ func authExternalHandler(server *Server, client *Client, mechanism string, value
|
||||
rb.session.deviceID = deviceID
|
||||
}
|
||||
}
|
||||
err = server.accounts.AuthenticateByCertFP(client, rb.session.certfp, authzid)
|
||||
err = server.accounts.AuthenticateByCertificate(client, rb.session.certfp, rb.session.peerCerts, authzid)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -721,7 +721,7 @@ func nsIdentifyHandler(server *Server, client *Client, command string, params []
|
||||
|
||||
// try certfp
|
||||
if !loginSuccessful && rb.session.certfp != "" {
|
||||
err = server.accounts.AuthenticateByCertFP(client, rb.session.certfp, "")
|
||||
err = server.accounts.AuthenticateByCertificate(client, rb.session.certfp, rb.session.peerCerts, "")
|
||||
loginSuccessful = (err == nil)
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
@ -92,10 +93,10 @@ func NormalizeCertfp(certfp string) (result string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func GetCertFP(conn net.Conn, handshakeTimeout time.Duration) (result string, err error) {
|
||||
func GetCertFP(conn net.Conn, handshakeTimeout time.Duration) (fingerprint string, peerCerts []*x509.Certificate, err error) {
|
||||
tlsConn, isTLS := conn.(*tls.Conn)
|
||||
if !isTLS {
|
||||
return "", ErrNotTLS
|
||||
return "", nil, ErrNotTLS
|
||||
}
|
||||
|
||||
// ensure handshake is performed
|
||||
@ -104,16 +105,16 @@ func GetCertFP(conn net.Conn, handshakeTimeout time.Duration) (result string, er
|
||||
tlsConn.SetDeadline(time.Time{})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
peerCerts := tlsConn.ConnectionState().PeerCertificates
|
||||
peerCerts = tlsConn.ConnectionState().PeerCertificates
|
||||
if len(peerCerts) < 1 {
|
||||
return "", ErrNoPeerCerts
|
||||
return "", nil, ErrNoPeerCerts
|
||||
}
|
||||
|
||||
rawCert := sha256.Sum256(peerCerts[0].Raw)
|
||||
fingerprint := hex.EncodeToString(rawCert[:])
|
||||
fingerprint = hex.EncodeToString(rawCert[:])
|
||||
|
||||
return fingerprint, nil
|
||||
return fingerprint, peerCerts, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user