Adhoc test component can successfully connect to ejabberd

This commit is contained in:
Mickael Remond 2018-01-12 18:01:27 +01:00
parent b31c29a03d
commit 90865aeb8e
No known key found for this signature in database
GPG Key ID: E6F6045D79965AA3
3 changed files with 52 additions and 4 deletions

View File

@ -1,6 +1,8 @@
package xmpp package xmpp
import ( import (
"crypto/sha1"
"encoding/hex"
"encoding/xml" "encoding/xml"
"errors" "errors"
"fmt" "fmt"
@ -15,17 +17,41 @@ const componentStreamOpen = "<?xml version='1.0'?><stream:stream to='%s' xmlns='
// using external components. Component specifications are defined // using external components. Component specifications are defined
// in XEP-0114, XEP-0355 and XEP-0356. // in XEP-0114, XEP-0355 and XEP-0356.
type Component struct { type Component struct {
Host string
Secret string
// TCP level connection // TCP level connection
conn net.Conn conn net.Conn
// read / write // read / write
socketProxy io.ReadWriter socketProxy io.ReadWriter // TODO
decoder *xml.Decoder decoder *xml.Decoder
} }
type Handshake struct {
XMLName xml.Name `xml:"jabber:component:accept handshake"`
}
// Handshake generates an authentication token based on StreamID and shared secret.
func (c *Component) Handshake(streamId string) string {
// 1. Concatenate the Stream ID received from the server with the shared secret.
concatStr := streamId + c.Secret
// 2. Hash the concatenated string according to the SHA1 algorithm, i.e., SHA1( concat (sid, password)).
h := sha1.New()
h.Write([]byte(concatStr))
hash := h.Sum(nil)
// 3. Ensure that the hash output is in hexadecimal format, not binary or base64.
// 4. Convert the hash output to all lowercase characters.
encodedStr := hex.EncodeToString(hash)
return encodedStr
}
// TODO Helper to prepare connection string // TODO Helper to prepare connection string
func Open(connStr string) error { func Open(connStr string) error {
c := Component{} c := Component{Host: connStr, Secret: "mypass"}
var conn net.Conn var conn net.Conn
var err error var err error
@ -36,7 +62,7 @@ func Open(connStr string) error {
// TODO send stream open and check for reply // TODO send stream open and check for reply
// Send stream open tag // Send stream open tag
componentHost := connStr // TODO Fix me componentHost := connStr // TODO Fix me: Extract componentID + secret
if _, err := fmt.Fprintf(conn, componentStreamOpen, componentHost, NSComponent, NSStream); err != nil { if _, err := fmt.Fprintf(conn, componentStreamOpen, componentHost, NSComponent, NSStream); err != nil {
fmt.Println("cannot send stream open.") fmt.Println("cannot send stream open.")
return err return err
@ -53,7 +79,7 @@ func Open(connStr string) error {
fmt.Println("StreamID = ", streamId) fmt.Println("StreamID = ", streamId)
// Authentication // Authentication
if _, err := fmt.Fprint(conn, "<handshake>aaee83c26aeeafcbabeabfcbcd50df997e0a2a1e</handshake>"); err != nil { if _, err := fmt.Fprintf(conn, "<handshake>%s</handshake>", c.Handshake(streamId)); err != nil {
fmt.Println("cannot send stream open.") fmt.Println("cannot send stream open.")
return err return err
} }
@ -68,6 +94,8 @@ func Open(connStr string) error {
switch v := val.(type) { switch v := val.(type) {
case *StreamError: case *StreamError:
fmt.Printf("error: %s", v.Error.Local) fmt.Printf("error: %s", v.Error.Local)
case *Handshake:
fmt.Println("Component connected")
default: default:
return errors.New("unexpected packet, got " + name.Local + " in " + name.Space) return errors.New("unexpected packet, got " + name.Local + " in " + name.Space)
} }

18
component_test.go Normal file
View File

@ -0,0 +1,18 @@
package xmpp
import "testing"
func TestHandshake(t *testing.T) {
c := Component{
Host: "test.localhost",
Secret: "mypass",
}
streamID := "1263952298440005243"
expected := "c77e2ef0109fbbc5161e83b51629cd1353495332"
result := c.Handshake(streamID)
if result != expected {
t.Errorf("incorrect handshake calculation '%s' != '%s'", result, expected)
}
}

View File

@ -86,6 +86,8 @@ func next(p *xml.Decoder) (xml.Name, interface{}, error) {
nv = &ClientPresence{} nv = &ClientPresence{}
case NSClient + " iq": case NSClient + " iq":
nv = &ClientIQ{} nv = &ClientIQ{}
case NSComponent + " handshake":
nv = &Handshake{}
default: default:
return xml.Name{}, nil, errors.New("unexpected XMPP message " + return xml.Name{}, nil, errors.New("unexpected XMPP message " +
se.Name.Space + " <" + se.Name.Local + "/>") se.Name.Space + " <" + se.Name.Local + "/>")