// Authenticate implements the Mechanism interface for PlainMech func (pm plainMech) Authenticate(data string, props stream.Properties) ([]element.Element, stream.Properties, bool) { decoded, err := base64.StdEncoding.DecodeString(data) if err != nil { return []element.Element{element.SASLFailure.MalformedRequest}, props, false } res := strings.Split(string(decoded), "\000") if len(res) != 3 { return []element.Element{element.SASLFailure.MalformedRequest}, props, false } identity, user, password := res[0], res[1], res[2] err = pm.auth.Authenticate(identity, user, password) // TODO: Handle different types of errors if err != nil { return []element.Element{element.SASLFailure.NotAuthorized}, props, false } if identity != "" { user = identity } else { // TODO: Add a way to determine the address of the server for the domain // part of the jid (do it better than this.) user += "@" + props.Domain } j := jid.New(user) props.Header.To = j.String() props.Status = props.Status | stream.Restart | stream.Auth return []element.Element{element.SASLSuccess}, props, false }
func (h Handler) HandleIQ(iq stanza.IQ, props stream.Properties) ([]stanza.Stanza, stream.Properties) { var sts []stanza.Stanza // ensure we have a bind request req, err := stanza.TransformBindRequest(iq) if err != nil { // TODO: Should this return an error? return sts, props } if req.Resource == "" { // TODO: Create a random resource generator req.Resource = genResourceID() } // Should do some resource validation here. // TODO: Need to use proper jids here. props.Header.To += "/" + req.Resource j := jid.New(props.Header.To) res := stanza.NewBindResult(iq, j) sts = append(sts, res.TransformStanza()) props.Status = props.Status | stream.Bind return sts, props }
// Start starts or restarts the stream. // // In recieving mode, the transport will wait to recieve a stream header // from the initiating entity, then sends its own header and the stream // features. This transport will add the starttls feature under certain // conditions. func (t *TCP) Start(props stream.Properties) (stream.Properties, error) { if t.mode == stream.Initiating { if props.Header == (stream.Header{}) { return props, stream.ErrHeaderNotSet } b := props.Header.WriteBytes() _, err := t.Write(b) return props, err } // We're in recieving mode if props.Domain == "" { return props, stream.ErrDomainNotSet } var el element.Element var h stream.Header var err error el, err = t.Next() if err != nil { return props, err } h, err = stream.NewHeader(el) if err != nil { return props, err } h.ID = genStreamID() if h.To != props.Domain { h.To, h.From = h.From, props.Domain b := h.WriteBytes() t.Write(b) err = t.WriteElement(element.StreamError.HostUnknown) props.Status = stream.Closed return props, err } h.From, h.To = props.Domain, h.From if props.To != "" { h.To = props.To } props.Header = h b := props.Header.WriteBytes() _, err = t.Write(b) if err != nil { return props, err } ftrs := element.StreamFeatures for _, f := range props.Features { ftrs = ftrs.AddChild(f) } // Stream features if t.conf != nil && !t.secure { tlsFeature := element.StartTLS if t.tlsRequired { tlsFeature = tlsFeature.AddChild(element.Required) } // Overwrite any other features ftrs.Child = []element.Token{tlsFeature} } err = t.WriteElement(ftrs) return props, err }