~samwhited/xmpp

7dbc2b92c0508df99b9fabf1e1d5ed0caaf29085 — Sam Whited 2 years ago 18f5577
Update mellium.im/sasl to v0.2.1

The XMPP library now performs its own Base64 encoding and decoding since
this is no longer part of the SASL library (it's XMPP specific and
shouldn't have been in the SASL library to begin with).

Fixes #3
4 files changed, 75 insertions(+), 21 deletions(-)

M go.mod
M go.sum
M sasl.go
M sasl2/sasl.go
M go.mod => go.mod +4 -3
@@ 1,9 1,10 @@
module mellium.im/xmpp

require (
	golang.org/x/image v0.0.0-20171214225156-12117c17ca67
	golang.org/x/net v0.0.0-20180216171745-136a25c244d3
	golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869 // indirect
	golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b
	golang.org/x/net v0.0.0-20181114220301-adae6a3d119a
	golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54
	mellium.im/sasl v0.1.1
	mellium.im/sasl v0.2.1
	mellium.im/xmlstream v0.13.1
)

M go.sum => go.sum +9 -8
@@ 1,14 1,15 @@
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb h1:Ah9YqXLj6fEgeKqcmBuLCbAsrF3ScD7dJ/bYM0C6tXI=
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/image v0.0.0-20171214225156-12117c17ca67 h1:L8S612DBEq9tpLTxczHuhrf5il+KEdSha8b5A5njQMc=
golang.org/x/image v0.0.0-20171214225156-12117c17ca67/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/net v0.0.0-20180216171745-136a25c244d3 h1:ccQe92wkcq8fxMUi0JfXsoHS6cSzB4Gs6Y5M4UoTzJY=
golang.org/x/net v0.0.0-20180216171745-136a25c244d3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869 h1:kkXA53yGe04D0adEYJwEVQjeBppL01Exg+fnMjfUraU=
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b h1:VHyIDlv3XkfCa5/a81uzaoDkHH4rr81Z62g+xlnO8uM=
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54 h1:a5WocgxWTnjG0C4hZblDx+yonFbQMMbv8yJGhHMz/nY=
golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
mellium.im/reader v0.0.4 h1:6nhK1YuHmn60bmLdRol3BQdiLGtta4RJ8dCbSmmhmDI=
mellium.im/reader v0.0.4/go.mod h1:rtqlYmkQriWPf1vKtmH0iIellTSRU/1JUFV8MVS6vek=
mellium.im/sasl v0.1.1 h1:kqCOm1txrnyeKNTnDX/JAHYEnXMNP0DgMdHkQjrlofo=
mellium.im/sasl v0.1.1/go.mod h1:vmQYTr1V4pFjgdorcqVEwA4WXck2n1JLx30pawPsSuY=
mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w=
mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ=
mellium.im/xmlstream v0.13.1 h1:km33K3lpXe8eGK8mIRn3Vk7+uJEL7CKbsCrrYsRrIsk=
mellium.im/xmlstream v0.13.1/go.mod h1:PDwtcQeiAyF7FrUBRWnVO91nIskvhOFYzOeftngiM7Q=

M sasl.go => sasl.go +27 -5
@@ 7,6 7,7 @@ package xmpp
import (
	"context"
	"crypto/tls"
	"encoding/base64"
	"encoding/xml"
	"errors"
	"fmt"


@@ 118,14 119,18 @@ func SASL(identity, password string, mechanisms ...sasl.Mechanism) StreamFeature
			//     response, it MUST transmit the response as a single equals sign
			//     character ("="), which indicates that the response is present but
			//     contains no data.
			var encodedResp []byte
			if len(resp) == 0 {
				resp = []byte{'='}
				encodedResp = []byte{'='}
			} else {
				encodedResp = make([]byte, base64.StdEncoding.EncodedLen(len(resp)))
				base64.StdEncoding.Encode(encodedResp, resp)
			}

			// Send <auth/> and the initial payload to start SASL auth.
			if _, err = fmt.Fprintf(c,
				`<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='%s'>%s</auth>`,
				selected.Name, resp,
				selected.Name, encodedResp,
			); err != nil {
				return mask, nil, err
			}


@@ 178,9 183,18 @@ func SASL(identity, password string, mechanisms ...sasl.Mechanism) StreamFeature
					// We're done with SASL and we're successful
					break
				}

				var encodedResp []byte
				if len(resp) == 0 {
					encodedResp = []byte{'='}
				} else {
					encodedResp = make([]byte, base64.StdEncoding.EncodedLen(len(resp)))
					base64.StdEncoding.Encode(encodedResp, resp)
				}

				// TODO: What happens if there's more and success (broken server)?
				if _, err = fmt.Fprintf(c,
					`<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>`, resp); err != nil {
				_, err = fmt.Fprintf(c, `<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>`, encodedResp)
				if err != nil {
					return mask, nil, err
				}
			}


@@ 201,7 215,15 @@ func decodeSASLChallenge(d *xml.Decoder, start xml.StartElement, allowChallenge 
		if err = d.DecodeElement(&challenge, &start); err != nil {
			return nil, false, err
		}
		return challenge.Data, start.Name.Local == "success", nil

		decodedChallenge := make([]byte, base64.StdEncoding.DecodedLen(len(challenge.Data)))
		n, err := base64.StdEncoding.Decode(decodedChallenge, challenge.Data)
		if err != nil {
			return nil, false, err
		}
		decodedChallenge = decodedChallenge[:n]

		return decodedChallenge, start.Name.Local == "success", nil
	case xml.Name{Space: ns.SASL, Local: "failure"}:
		fail := saslerr.Failure{}
		if err = d.DecodeElement(&fail, &start); err != nil {

M sasl2/sasl.go => sasl2/sasl.go +35 -5
@@ 13,6 13,7 @@ package sasl2 // import "mellium.im/xmpp/sasl2"
import (
	"context"
	"crypto/tls"
	"encoding/base64"
	"encoding/xml"
	"errors"
	"fmt"


@@ 137,15 138,19 @@ func SASL(identity, password string, mechanisms ...sasl.Mechanism) xmpp.StreamFe
			//     In order to explicitly transmit a zero-length SASL challenge or
			//     response, the sending party sends a single equals sign character
			//     ("=").
			var encodedResp []byte
			if len(resp) == 0 {
				resp = []byte{'='}
				encodedResp = []byte{'='}
			} else {
				encodedResp = make([]byte, base64.StdEncoding.EncodedLen(len(resp)))
				base64.StdEncoding.Encode(encodedResp, resp)
			}

			// TODO: Printf'ing is probably a bad idea. Encode the tokens properly.
			// Send <auth/> and the initial payload to start SASL auth.
			if _, err = fmt.Fprintf(conn,
				`<authenticate xmlns='%s' mechanism='%s'><initial-response>%s</initial-response></authenticate>`,
				NS, selected.Name, resp,
				NS, selected.Name, encodedResp,
			); err != nil {
				return mask, nil, err
			}


@@ 196,9 201,18 @@ func SASL(identity, password string, mechanisms ...sasl.Mechanism) xmpp.StreamFe
					// We're done with SASL and we're successful
					break
				}

				var encodedResp []byte
				if len(resp) == 0 {
					encodedResp = []byte{'='}
				} else {
					encodedResp = make([]byte, base64.StdEncoding.EncodedLen(len(resp)))
					base64.StdEncoding.Encode(encodedResp, resp)
				}

				// TODO: What happens if there's more and success (broken server)?
				if _, err = fmt.Fprintf(conn,
					`<response xmlns='urn:xmpp:sasl:0'>%s</response>`, resp); err != nil {
					`<response xmlns='urn:xmpp:sasl:0'>%s</response>`, encodedResp); err != nil {
					return mask, nil, err
				}
			}


@@ 220,7 234,15 @@ func decodeSASLChallenge(r xml.TokenReader, start xml.StartElement, allowChallen
		if err = d.DecodeElement(&challenge, &start); err != nil {
			return nil, false, err
		}
		return challenge.Data, false, nil

		decodedChallenge := make([]byte, base64.StdEncoding.DecodedLen(len(challenge.Data)))
		n, err := base64.StdEncoding.Decode(decodedChallenge, challenge.Data)
		if err != nil {
			return nil, false, err
		}
		decodedChallenge = decodedChallenge[:n]

		return decodedChallenge, false, nil
	case xml.Name{Space: NS, Local: "success"}:
		success := struct {
			XMLName xml.Name `xml:"urn:xmpp:sasl:0 success"`


@@ 229,7 251,15 @@ func decodeSASLChallenge(r xml.TokenReader, start xml.StartElement, allowChallen
		if err = d.DecodeElement(&challenge, &start); err != nil {
			return nil, true, err
		}
		return success.Data, true, nil

		decodedChallenge := make([]byte, base64.StdEncoding.DecodedLen(len(success.Data)))
		n, err := base64.StdEncoding.Decode(decodedChallenge, success.Data)
		if err != nil {
			return nil, false, err
		}
		decodedChallenge = decodedChallenge[:n]

		return decodedChallenge, true, nil
	case xml.Name{Space: NS, Local: "failure"}:
		fail := saslerr.Failure{}
		if err = d.DecodeElement(&fail, &start); err != nil {