From 2f6b1a11209260f4ee7b9469e39d16e78fb23a0f Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 12:09:50 +0200 Subject: Add dummy handler for stream features elements This is the first step to handle stream features correctly with the new routing infrastructure. --- xmpp/stream_pair.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index c9108d1..3e42cd1 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -90,3 +90,7 @@ func closeStream(s *session) { log.Println("Could not encode stream end!") } } + +func streamFeaturesHandler(e []xml.Token) { + log.Println("Received stream features") +} -- cgit v1.2.3-70-g09d2 From d6fa15b7b66d679b7a6291aa6c85780a09cb1755 Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 12:28:48 +0200 Subject: Add detection for SASL mechanism This is needed to respond with a SASL auth attempt. --- xmpp/stream_pair.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index 3e42cd1..b353947 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -91,6 +91,31 @@ func closeStream(s *session) { } } +func getCharData(t xml.Token) string { + switch c := t.(type) { + case xml.CharData: + return string(c) + default: + return "" + } +} + func streamFeaturesHandler(e []xml.Token) { - log.Println("Received stream features") + mechanism := xml.Name{`urn:ietf:params:xml:ns:xmpp-sasl`, `mechanism`} + + for i, t := range e { + switch s := t.(type) { + case xml.StartElement: + if s.Name == mechanism { + if i+1 < len(e) { + if getCharData(e[i+1]) == `PLAIN` { + log.Println("Got offer for SASL PLAIN") + return + } + } + } + } + } + + log.Println("No compatible SASL mechanism offered!") } -- cgit v1.2.3-70-g09d2 From 98740fdc1c777778054dc3e444b9f4542fe04abe Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 12:44:58 +0200 Subject: Move SASL mechanism detection to xmpp/sasl.go --- xmpp/sasl.go | 30 ++++++++++++++++++++++++++++++ xmpp/stream_pair.go | 30 +++++------------------------- 2 files changed, 35 insertions(+), 25 deletions(-) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/sasl.go b/xmpp/sasl.go index 8687782..e06bcd5 100644 --- a/xmpp/sasl.go +++ b/xmpp/sasl.go @@ -34,3 +34,33 @@ func (s *session) sasl() { } } } + +// hasSaslPlain scans the given stream features XML element for the SASL PLAIN +// mechanism which is supported by xengineering.eu/limox/xmpp. It returns true +// if the stream has support for this mechanism and false otherwise. +func hasSaslPlain(e []xml.Token) bool { + mechanism := xml.Name{`urn:ietf:params:xml:ns:xmpp-sasl`, `mechanism`} + + for i, t := range e { + switch s := t.(type) { + case xml.StartElement: + if s.Name == mechanism { + if i+1 < len(e) { + subtype := func() string { + switch c := e[i+1].(type) { + case xml.CharData: + return string(c) + default: + return "" + } + }() + if subtype == `PLAIN` { + return true + } + } + } + } + } + + return false +} diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index b353947..8f70318 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -91,31 +91,11 @@ func closeStream(s *session) { } } -func getCharData(t xml.Token) string { - switch c := t.(type) { - case xml.CharData: - return string(c) - default: - return "" - } -} - func streamFeaturesHandler(e []xml.Token) { - mechanism := xml.Name{`urn:ietf:params:xml:ns:xmpp-sasl`, `mechanism`} - - for i, t := range e { - switch s := t.(type) { - case xml.StartElement: - if s.Name == mechanism { - if i+1 < len(e) { - if getCharData(e[i+1]) == `PLAIN` { - log.Println("Got offer for SASL PLAIN") - return - } - } - } - } + sasl := hasSaslPlain(e) + if sasl { + log.Println("Stream is compatible with SASL PLAIN mechanism") + } else { + log.Println("Stream is not compatible with SASL PLAIN mechanism!") } - - log.Println("No compatible SASL mechanism offered!") } -- cgit v1.2.3-70-g09d2 From 8b608265772ba5df13d24071117c694bdfd1212a Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 13:07:12 +0200 Subject: Add session pointer to routing infrastructure It is nearly useless to route a XML element to an appropriate handler function if the latter has no idea how to send responses to the server or the GUI. Passing a pointer to the session solves this issue. --- xmpp/router.go | 6 +++--- xmpp/router_test.go | 7 ++++--- xmpp/stream_pair.go | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/router.go b/xmpp/router.go index 879579d..bd619b4 100644 --- a/xmpp/router.go +++ b/xmpp/router.go @@ -12,7 +12,7 @@ import ( // entry of the routingTable. type routingTable []struct { name xml.Name - handler func([]xml.Token) + handler func(*session, []xml.Token) } // getRoutingTable returns the routing table used in @@ -29,7 +29,7 @@ func getRoutingTable() routingTable { // route determines the correct handler function for the given XML element by a // given routingTable. In addition it executes the determined handler function. // If no handler function is found an error message is send via the log module. -func route(e []xml.Token, t routingTable) { +func route(s *session, e []xml.Token, t routingTable) { var name xml.Name // TODO a stronger definition of an XML element (as here @@ -50,7 +50,7 @@ func route(e []xml.Token, t routingTable) { for _, r := range t { if name == r.name { - r.handler(e) + r.handler(s, e) return } } diff --git a/xmpp/router_test.go b/xmpp/router_test.go index ea13712..41484c5 100644 --- a/xmpp/router_test.go +++ b/xmpp/router_test.go @@ -23,9 +23,10 @@ type routerTest struct { // validated. func TestRouter(t *testing.T) { var testpoint int + var s session - factory := func(tp *int, i int) func([]xml.Token) { - return func([]xml.Token) { + factory := func(tp *int, i int) func(*session, []xml.Token) { + return func(*session, []xml.Token) { *tp = i } } @@ -60,7 +61,7 @@ func TestRouter(t *testing.T) { tokens = append(tokens, xml.CopyToken(token)) } - route(tokens, testRouting) + route(&s, tokens, testRouting) if testpoint != v.value { t.Fatalf("XML element was not routed correctly!\n") diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index 8f70318..8ec06a6 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -28,7 +28,7 @@ func runStreamPair(s *session) { } if buf.isComplete() { element := buf.reset() - route(element, getRoutingTable()) + route(s, element, getRoutingTable()) } } } @@ -91,7 +91,7 @@ func closeStream(s *session) { } } -func streamFeaturesHandler(e []xml.Token) { +func streamFeaturesHandler(s *session, e []xml.Token) { sasl := hasSaslPlain(e) if sasl { log.Println("Stream is compatible with SASL PLAIN mechanism") -- cgit v1.2.3-70-g09d2 From c87ed02bb55a652b8908c336c3afd5635afdc1a7 Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 13:09:37 +0200 Subject: Send SASL request based on new routing --- xmpp/stream_pair.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index 8ec06a6..5674d7b 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -94,7 +94,7 @@ func closeStream(s *session) { func streamFeaturesHandler(s *session, e []xml.Token) { sasl := hasSaslPlain(e) if sasl { - log.Println("Stream is compatible with SASL PLAIN mechanism") + s.sasl() } else { log.Println("Stream is not compatible with SASL PLAIN mechanism!") } -- cgit v1.2.3-70-g09d2 From 04f24e0dade8caf029cb78d3281b3587a8362cbe Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 13:22:15 +0200 Subject: Rework and apply stream nesting on SASL success If SASL authentication is successful a new stream has to be opened by the client. This is implemented with this commit. --- xmpp/sasl.go | 1 + xmpp/session.go | 1 - xmpp/stream_pair.go | 15 ++++++++------- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/sasl.go b/xmpp/sasl.go index 62c312f..23e8f3f 100644 --- a/xmpp/sasl.go +++ b/xmpp/sasl.go @@ -66,4 +66,5 @@ func hasSaslPlain(e []xml.Token) bool { } func saslSuccessHandler(s *session, e []xml.Token) { + runStreamPair(s) } diff --git a/xmpp/session.go b/xmpp/session.go index f14cd34..bfa2582 100644 --- a/xmpp/session.go +++ b/xmpp/session.go @@ -19,7 +19,6 @@ type session struct { transport *tls.Conn ed encoderDecoder rx chan xml.Token - streamEnd xml.EndElement } func StartSession(out chan<- any, jid string, pwd string) (in chan<- any) { diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index 5674d7b..f1de345 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -6,8 +6,8 @@ import ( ) func runStreamPair(s *session) { - openStream(s) - defer closeStream(s) + end := openStream(s) + defer closeStream(s, end) buf := newElementBuffer() @@ -34,7 +34,7 @@ func runStreamPair(s *session) { } } -func openStream(s *session) { +func openStream(s *session) xml.EndElement { start := xml.StartElement{ xml.Name{"jabber:client", "stream:stream"}, []xml.Attr{ @@ -45,8 +45,7 @@ func openStream(s *session) { xml.Attr{xml.Name{"", "xmlns:stream"}, "http://etherx.jabber.org/streams"}, }, } - - s.streamEnd = start.End() + end := start.End() err := s.ed.encodeToken(start) if err != nil { @@ -54,6 +53,8 @@ func openStream(s *session) { } syncStreams(s) + + return end } // syncStreams drops XML tokens from the receiving stream until an @@ -84,8 +85,8 @@ func syncStreams(s *session) { } } -func closeStream(s *session) { - err := s.ed.encodeToken(s.streamEnd) +func closeStream(s *session, end xml.EndElement) { + err := s.ed.encodeToken(end) if err != nil { log.Println("Could not encode stream end!") } -- cgit v1.2.3-70-g09d2 From 6fd36e07a5d645295f34fcbab36cce5e08a9d84c Mon Sep 17 00:00:00 2001 From: xengineering Date: Fri, 30 Jun 2023 13:28:06 +0200 Subject: Make streamFeaturesHandler() more generic The new structure allows to check for different stream features and act according to them or - if nothing matches - do nothing apart from an error message to the log. --- xmpp/stream_pair.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'xmpp/stream_pair.go') diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index f1de345..693972e 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -93,10 +93,10 @@ func closeStream(s *session, end xml.EndElement) { } func streamFeaturesHandler(s *session, e []xml.Token) { - sasl := hasSaslPlain(e) - if sasl { + if hasSaslPlain(e) { s.sasl() - } else { - log.Println("Stream is not compatible with SASL PLAIN mechanism!") + return } + + log.Println("Stream has no implemented features!") } -- cgit v1.2.3-70-g09d2