diff --git a/xmpp.go b/xmpp.go index 1ea1456..1f041cb 100644 --- a/xmpp.go +++ b/xmpp.go @@ -536,10 +536,23 @@ func (c *Client) init(o *Options) error { fmt.Fprintf(c.stanzaWriter, "%s\n", nsSASL, mechanism, base64.StdEncoding.EncodeToString([]byte(clientFirstMessage))) var sfm string - if err = c.p.DecodeElement(&sfm, nil); err != nil { - return errors.New("unmarshal : " + err.Error()) + _, val, err := next(c.p) + if err != nil { + return err } - b, err := base64.StdEncoding.DecodeString(string(sfm)) + switch v := val.(type) { + case *saslFailure: + errorMessage := v.Text + if errorMessage == "" { + // v.Any is type of sub-element in failure, + // which gives a description of what failed if there was no text element + errorMessage = v.Any.Local + } + return errors.New("auth failure: " + errorMessage) + case *saslChallenge: + sfm = v.Text + } + b, err := base64.StdEncoding.DecodeString(sfm) if err != nil { return err } @@ -1306,6 +1319,11 @@ type saslFailure struct { Text string `xml:"text"` } +type saslChallenge struct { + XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl challenge"` + Text string `xml:",chardata"` +} + // RFC 3920 C.5 Resource binding name space type bindBind struct { XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"` @@ -1480,7 +1498,7 @@ func next(p *xml.Decoder) (xml.Name, interface{}, error) { case nsSASL + " mechanisms": nv = &saslMechanisms{} case nsSASL + " challenge": - nv = "" + nv = &saslChallenge{} case nsSASL + " response": nv = "" case nsSASL + " abort":