From 6c9243326ed182a1749a7537f70bdb5439291aba Mon Sep 17 00:00:00 2001 From: Martin Dosch Date: Mon, 8 Jan 2024 19:30:17 +0100 Subject: [PATCH 1/4] Add XEP-0474 support. --- xmpp.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/xmpp.go b/xmpp.go index 051c11a..8480fea 100644 --- a/xmpp.go +++ b/xmpp.go @@ -34,6 +34,7 @@ import ( "net/http" "net/url" "os" + "slices" "strconv" "strings" "time" @@ -46,6 +47,7 @@ const ( nsTLS = "urn:ietf:params:xml:ns:xmpp-tls" nsSASL = "urn:ietf:params:xml:ns:xmpp-sasl" nsBind = "urn:ietf:params:xml:ns:xmpp-bind" + nsSASLCB = "urn:xmpp:sasl-cb:0" nsClient = "jabber:client" nsSession = "urn:ietf:params:xml:ns:xmpp-session" ) @@ -521,7 +523,7 @@ func (c *Client) init(o *Options) error { if err != nil { return err } - var serverNonce string + var serverNonce, dgProtect string var salt []byte var iterations int for _, serverReply := range strings.Split(string(b), ",") { @@ -542,6 +544,40 @@ func (c *Client) init(o *Options) error { if err != nil { return err } + case strings.HasPrefix(serverReply, "d="): + serverDgProtectHash := strings.SplitN(serverReply, "=", 2)[1] + slices.Sort(f.Mechanisms.Mechanism) + for _, mech := range f.Mechanisms.Mechanism { + if dgProtect == "" { + dgProtect = mech + } else { + dgProtect = dgProtect + "," + mech + } + } + dgProtect = dgProtect + "|" + var cbsSlice []string + for _, cbs := range f.ChannelBindings.ChannelBinding { + cbsSlice = append(cbsSlice, cbs.Type) + } + slices.Sort(cbsSlice) + for i, cb := range cbsSlice { + if i == 0 { + dgProtect = dgProtect + cb + } else { + dgProtect = dgProtect + "," + cb + } + } + dgh := shaNewFn() + dgh.Write([]byte(dgProtect)) + dHash := dgh.Sum(nil) + dHashb64 := base64.StdEncoding.EncodeToString(dHash) + if dHashb64 != serverDgProtectHash { + println("raw", dgProtect) + println("calc:", dHashb64) + println("recv:", serverDgProtectHash) + return errors.New("SCRAM: downgrade protection hash mismatch") + } + dgh.Reset() default: return errors.New("unexpected content in SCRAM challenge") } @@ -1194,12 +1230,12 @@ func (c *Client) Roster() error { // RFC 3920 C.1 Streams name space type streamFeatures struct { - XMLName xml.Name `xml:"http://etherx.jabber.org/streams features"` - StartTLS *tlsStartTLS - Mechanisms saslMechanisms - ChannelBinding saslChannelBinding - Bind bindBind - Session bool + XMLName xml.Name `xml:"http://etherx.jabber.org/streams features"` + StartTLS *tlsStartTLS + Mechanisms saslMechanisms + ChannelBindings saslChannelBindings + Bind bindBind + Session bool } type streamError struct { @@ -1233,7 +1269,7 @@ type saslAuth struct { Mechanism string `xml:",attr"` } -type saslChannelBinding struct { +type saslChannelBindings struct { XMLName xml.Name `xml:"sasl-channel-binding"` Text string `xml:",chardata"` Xmlns string `xml:"xmlns,attr"` @@ -1436,6 +1472,8 @@ func next(p *xml.Decoder) (xml.Name, interface{}, error) { nv = &saslSuccess{} case nsSASL + " failure": nv = &saslFailure{} + case nsSASLCB + " sasl-channel-binding": + nv = &saslChannelBindings{} case nsBind + " bind": nv = &bindBind{} case nsClient + " message": From 346208509802ba0d8526cfe4763616c0ea0b580e Mon Sep 17 00:00:00 2001 From: Martin Dosch Date: Mon, 8 Jan 2024 19:32:08 +0100 Subject: [PATCH 2/4] Add missing error handling. --- xmpp.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmpp.go b/xmpp.go index 8480fea..1d88bae 100644 --- a/xmpp.go +++ b/xmpp.go @@ -535,6 +535,9 @@ func (c *Client) init(o *Options) error { } case strings.HasPrefix(serverReply, "s="): salt, err = base64.StdEncoding.DecodeString(strings.SplitN(serverReply, "=", 2)[1]) + if err != nil { + return err + } if string(salt) == "" { return errors.New("SCRAM: server sent empty salt") } From 2449f4192bdc12f7d5f7dca1c3afb98d4b92e459 Mon Sep 17 00:00:00 2001 From: Martin Dosch Date: Mon, 8 Jan 2024 19:48:13 +0100 Subject: [PATCH 3/4] Remove debugging stuff. Remove previously overlooked println. --- xmpp.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/xmpp.go b/xmpp.go index 1d88bae..88fed91 100644 --- a/xmpp.go +++ b/xmpp.go @@ -575,9 +575,6 @@ func (c *Client) init(o *Options) error { dHash := dgh.Sum(nil) dHashb64 := base64.StdEncoding.EncodeToString(dHash) if dHashb64 != serverDgProtectHash { - println("raw", dgProtect) - println("calc:", dHashb64) - println("recv:", serverDgProtectHash) return errors.New("SCRAM: downgrade protection hash mismatch") } dgh.Reset() From 70c2fe69006b0acd1512335e52d6c9d36a3e2f52 Mon Sep 17 00:00:00 2001 From: Martin Dosch Date: Wed, 10 Jan 2024 13:17:25 +0100 Subject: [PATCH 4/4] Update dependencies. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4adb9c6..89dec08 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/mattn/go-xmpp go 1.20 -require golang.org/x/crypto v0.15.0 +require golang.org/x/crypto v0.18.0 diff --git a/go.sum b/go.sum index fcac726..4dda6b7 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=