~samwhited/xmpp

1738793608e2a2fb0c1702f0c3468e610bd7bdd7 — Sam Whited 10 months ago df2fda8 namespace_fixes
all: be strict about namespace validation

When decoding stanzas, be more strict about verifying the namespace.
Previously stanzas would have an empty namespace, but the session should
always setup the default namespace correctly now.

Signed-off-by: Sam Whited <sam@samwhited.com>
4 files changed, 12 insertions(+), 7 deletions(-)

M mux/mux.go
M ping/ping_test.go
M session.go
M xtime/time_test.go
M mux/mux.go => mux/mux.go +1 -4
@@ 70,10 70,7 @@ func (m *ServeMux) Handler(name xml.Name) (h xmpp.Handler, ok bool) {
		return h, true
	}

	// Route stanzas.
	// TODO: Fix the session so that a default namespace is always declared and
	// then remove the check for an empty namespace.
	if name.Space == "" || name.Space == ns.Client || name.Space == ns.Server {
	if name.Space == ns.Client || name.Space == ns.Server {
		switch name.Local {
		case "iq":
			return xmpp.HandlerFunc(m.iqRouter), true

M ping/ping_test.go => ping/ping_test.go +2 -0
@@ 13,6 13,7 @@ import (
	"testing"

	"mellium.im/xmlstream"
	"mellium.im/xmpp/internal/ns"
	"mellium.im/xmpp/internal/xmpptest"
	"mellium.im/xmpp/jid"
	"mellium.im/xmpp/mux"


@@ 81,6 82,7 @@ func TestRoundTrip(t *testing.T) {
	}

	d := xml.NewDecoder(strings.NewReader(req.String()))
	d.DefaultSpace = ns.Client
	tok, _ := d.Token()
	start := tok.(xml.StartElement)
	var b strings.Builder

M session.go => session.go +7 -3
@@ 444,7 444,7 @@ func (rw *responseChecker) EncodeToken(t xml.Token) error {
	switch tok := t.(type) {
	case xml.StartElement:
		_, id := attr.Get(tok.Attr, "id")
		if rw.level < 1 && isIQ(tok.Name) && id == rw.id && !iqNeedsResp(tok.Attr) {
		if rw.level < 1 && isIQEmptySpace(tok.Name) && id == rw.id && !iqNeedsResp(tok.Attr) {
			rw.wroteResp = true
		}
		rw.level++


@@ 712,12 712,16 @@ func iqNeedsResp(attrs []xml.Attr) bool {
}

func isIQ(name xml.Name) bool {
	return name.Local == "iq" && (name.Space == ns.Client || name.Space == ns.Server)
}

func isIQEmptySpace(name xml.Name) bool {
	return name.Local == "iq" && (name.Space == "" || name.Space == ns.Client || name.Space == ns.Server)
}

func isStanza(name xml.Name) bool {
	return (name.Local == "iq" || name.Local == "message" || name.Local == "presence") &&
		(name.Space == "" || name.Space == ns.Client || name.Space == ns.Server)
		(name.Space == ns.Client || name.Space == ns.Server)
}

// SendIQ is like Send except that it returns an error if the first token read


@@ 750,7 754,7 @@ func (s *Session) SendIQ(ctx context.Context, r xml.TokenReader) (xmlstream.Toke
	if !ok {
		return nil, fmt.Errorf("expected IQ start element, got %T", tok)
	}
	if !isIQ(start.Name) {
	if !isIQEmptySpace(start.Name) {
		return nil, fmt.Errorf("expected start element to be an IQ")
	}


M xtime/time_test.go => xtime/time_test.go +2 -0
@@ 14,6 14,7 @@ import (
	"time"

	"mellium.im/xmlstream"
	"mellium.im/xmpp/internal/ns"
	"mellium.im/xmpp/internal/xmpptest"
	"mellium.im/xmpp/jid"
	"mellium.im/xmpp/mux"


@@ 52,6 53,7 @@ func TestRoundTrip(t *testing.T) {
	}

	d := xml.NewDecoder(strings.NewReader(req.String()))
	d.DefaultSpace = ns.Server
	tok, _ := d.Token()
	start := tok.(xml.StartElement)
	var b strings.Builder