diff options
| author | xengineering <me@xengineering.eu> | 2023-05-21 15:30:39 +0200 | 
|---|---|---|
| committer | xengineering <me@xengineering.eu> | 2023-05-21 15:30:39 +0200 | 
| commit | 50618675c84d2246f48a18de206200d27a733300 (patch) | |
| tree | af731af431d5d3059cfe8a9a5806860bf2ca8b12 /xmpp | |
| parent | 8d4ebab923ae23d1dfbc9b47eeabec33d3605ef5 (diff) | |
| download | limox-50618675c84d2246f48a18de206200d27a733300.tar limox-50618675c84d2246f48a18de206200d27a733300.tar.zst limox-50618675c84d2246f48a18de206200d27a733300.zip  | |
Implement SASL PLAIN authentication
Diffstat (limited to 'xmpp')
| -rw-r--r-- | xmpp/jid.go | 20 | ||||
| -rw-r--r-- | xmpp/routing.go | 39 | ||||
| -rw-r--r-- | xmpp/xmpp.go | 13 | 
3 files changed, 55 insertions, 17 deletions
diff --git a/xmpp/jid.go b/xmpp/jid.go index f3a5d49..672e934 100644 --- a/xmpp/jid.go +++ b/xmpp/jid.go @@ -21,3 +21,23 @@ func domainpart(jid string) string {  	return string(list)  } + +func username(jid string) string { +	list := []rune(jid) + +	for i, v := range list { +		if v == '/' { +			list = list[:i] +			break +		} +	} + +	for i, v := range list { +		if v == '@' { +			list = list[:i] +			break +		} +	} + +	return string(list) +} diff --git a/xmpp/routing.go b/xmpp/routing.go index 55ec135..23f92bb 100644 --- a/xmpp/routing.go +++ b/xmpp/routing.go @@ -2,6 +2,7 @@ package xmpp  import (  	"encoding/xml" +	"encoding/base64"  	"errors"  	"log"  ) @@ -14,15 +15,14 @@ type tokenRouter struct {  	enc          *encoder  } -func newTokenRouter(e *encoder) tokenRouter { +func newTokenRouter() tokenRouter {  	return tokenRouter{  		buffer: make([]xml.Token, 0),  		level:  0, -		enc:    e,  	}  } -func (r *tokenRouter) route(t xml.Token) error { +func (r *tokenRouter) route(t xml.Token, c *Conn) error {  	r.buffer = append(r.buffer, t)  	switch unwrapped := t.(type) { @@ -43,8 +43,7 @@ func (r *tokenRouter) route(t xml.Token) error {  		case 0:  			return errors.New("Stream was closed by server")  		case 1: -			// call elementRouter -			err := routeElement(r.buffer) +			err := routeElement(r.buffer, c)  			if err != nil {  				return err  			} @@ -64,7 +63,7 @@ func (r *tokenRouter) route(t xml.Token) error {  	return nil  } -func routeElement(b []xml.Token) error { +func routeElement(b []xml.Token, c *Conn) error {  	tab := elementRoutingTable{  		{xml.Name{"http://etherx.jabber.org/streams", "features"}, streamFeatures},  	} @@ -73,7 +72,7 @@ func routeElement(b []xml.Token) error {  	case xml.StartElement:  		for _, v := range(tab) {  			if unwrapped.Name == v.name { -				err := v.handler(b) +				err := v.handler(b, c)  				if err != nil {  					return err  				} @@ -91,11 +90,11 @@ func routeElement(b []xml.Token) error {  type elementRoutingTable []struct {  	name    xml.Name -	handler func(b []xml.Token) error +	handler func(b []xml.Token, c *Conn) error  } -func streamFeatures(b []xml.Token) error { -	err := sendSaslAuth(b) +func streamFeatures(b []xml.Token, c *Conn) error { +	err := sendSaslAuth(b, c)  	if err != nil {  		return err  	} @@ -103,7 +102,7 @@ func streamFeatures(b []xml.Token) error {  	return nil  } -func sendSaslAuth(b []xml.Token) error { +func sendSaslAuth(b []xml.Token, c *Conn) error {  	mechanisms := make([]string, 0)  	for i, v := range(b) {  		switch token := v.(type) { @@ -121,6 +120,24 @@ func sendSaslAuth(b []xml.Token) error {  	for _, v := range(mechanisms) {  		if v == "PLAIN" { +			start := xml.StartElement{ +				xml.Name{"urn:ietf:params:xml:ns:xmpp-sasl", "auth"}, +				[]xml.Attr{ +					xml.Attr{xml.Name{"", "mechanism"}, "PLAIN"}, +				}, +			} + +			data := []byte("\x00" + username(c.jid) + "\x00" + c.pwd) +			dst := make([]byte, base64.StdEncoding.EncodedLen(len(data))) +			base64.StdEncoding.Encode(dst, data) +			payload := xml.CharData(dst) + +			end := start.End() + +			c.enc.encodeNow(start) +			c.enc.encode(payload) +			c.enc.encodeNow(end) +  			return nil  		}  	} diff --git a/xmpp/xmpp.go b/xmpp/xmpp.go index 624090b..07d4c6d 100644 --- a/xmpp/xmpp.go +++ b/xmpp/xmpp.go @@ -19,6 +19,7 @@ type Conn struct {  	ch chan Event  	jid, pwd string  	tcp *tls.Conn +	enc encoder  }  func NewConn(ch chan Event, jid string, pwd string) *Conn { @@ -65,13 +66,13 @@ func (c *Conn) Run() {  	go decoder.run()  	defer decoder.stop() -	enc := newEncoder(c.tcp) -	defer enc.Close() +	c.enc = newEncoder(c.tcp) +	defer c.enc.Close() -	tr := newTokenRouter(&enc) +	tr := newTokenRouter() -	end := sendStreamStart(&enc, c.jid) -	defer sendStreamEnd(&enc, end) +	end := sendStreamStart(&c.enc, c.jid) +	defer sendStreamEnd(&c.enc, end)  	c.ch <- ConnectEvent  	defer func() { c.ch <- DisconnectEvent }() @@ -86,7 +87,7 @@ func (c *Conn) Run() {  				log.Printf("Unknown Event '%d'!\n", ev)  			}  		case token := <-decoder.data: -			err = tr.route(token) +			err = tr.route(token, c)  			if err != nil {  				log.Println(err)  				return  | 
