diff options
-rw-r--r-- | ROADMAP.md | 2 | ||||
-rw-r--r-- | xmpp/jid.go | 20 | ||||
-rw-r--r-- | xmpp/routing.go | 39 | ||||
-rw-r--r-- | xmpp/xmpp.go | 13 |
4 files changed, 56 insertions, 18 deletions
@@ -6,7 +6,7 @@ - [x] infrastructure to encode and decode XML tokens - [x] basic XML token logging to console - [x] infrastructure to route and handle multi-token XML blocks -- [ ] SASL authentication +- [x] SASL authentication - [ ] ressource binding - [ ] roster retrieval - [ ] single user chat text messages 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 |