func (t *BindFeature) Negotate(strm *stream.Stream) error { if strm.Jid.Resource != "" { t.Resource = &strm.Jid.Resource } id := strconv.Itoa(rand.Intn(1000)) iq := Iq{To: strm.Jid.Server(), Id: &id, Payload: t} typ := IqTypeSet iq.Type = &typ if err := strm.Send(&iq); err != nil { return err } resp, err := strm.Read() if err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch rsp := resp.(type) { case *Iq: if rsp.Type != nil && *rsp.Type == IqTypeResult && rsp.Payload != nil { if newt, ok := rsp.Payload.(*BindFeature); ok { if newt.Jid != nil { strm.Jid = newt.Jid return nil } } else { return stream.ErrMalformedProtocol } } case *stream.Error: return rsp } return stream.ErrMalformedProtocol }
func turnTLS(strm *stream.Stream) error { DefaultConfig.ServerName = strm.Jid.Domain tlsconn := tls.Client(strm.Conn, &DefaultConfig) if err := tlsconn.Handshake(); err != nil { return err } strm.Conn = tlsconn return nil }
func (t *TLSFeature) Negotate(strm *stream.Stream) error { if err := strm.Send(t); err != nil { return err } data, err := strm.Read() if err != nil { return err } if data == nil { return stream.ErrUnexpectedEOF } switch resp := data.(type) { case *starttls.Proceed: return turnTLS(strm) case *starttls.Failure: return resp } return stream.ErrMalformedProtocol }
func sasl_PLAIN(strm *stream.Stream, password string) error { var err error data := "\x00" + strm.Jid.Node + "\x00" + password method := "PLAIN" if err = strm.Send(&sasl.Auth{&method, base64_encode(data)}); err != nil { return err } resp, err := strm.Read() if err != nil { return err } switch resp := resp.(type) { case *sasl.Success: return nil case *sasl.Failure: return resp case *stream.Error: return resp } return stream.ErrMalformedProtocol }
func (t *SessionFeature) Negotate(strm *stream.Stream) error { id := strconv.Itoa(rand.Intn(1000)) typ := IqTypeSet iq := Iq{From: strm.Jid, Id: &id, Payload: t, Type: &typ} if err := strm.Send(&iq); err != nil { return err } resp, err := strm.Read() if err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch resp := resp.(type) { case *Iq: if resp.Type != nil && *resp.Type == IqTypeResult { return nil } case *stream.Error: return resp } return stream.ErrMalformedProtocol }
func sasl_DIGEST_MD5(strm *stream.Stream, password string) error { var err error var resp interface{} method := "DIGEST-MD5" if err = strm.Send(&sasl.Auth{&method, []byte{}}); err != nil { return err } resp, err = strm.Read() if err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch rsp := resp.(type) { case *sasl.Challenge: var t []byte if t, err = base64.StdEncoding.DecodeString(string(rsp.Data)); err != nil { return err } var tokens map[string]string if tokens, err = get_map(t); err != nil { return err } nonce := tokens["nonce"] cnonce := make_cnonce() nc := "00000001" digest_uri := "xmpp/" + strm.Jid.Domain realm := strm.Jid.Domain qop_list := strings.Split(tokens["qop"], ",") exists := false for _, x := range qop_list { if x == "auth" { exists = true break } } if !exists { return errors.New("No known qop method") } qop := "auth" a0 := md5_sum([]byte(strm.Jid.Node + ":" + realm + ":" + password)) a1 := string(a0) + ":" + nonce + ":" + cnonce a2 := "AUTHENTICATE:" + digest_uri t = []byte(hex(md5_sum([]byte(a1))) + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + hex(md5_sum([]byte(a2)))) response := hex(md5_sum(t)) response = `charset=utf-8,username="******",realm="` + realm + `",nonce=` + nonce + ",cnonce=" + cnonce + ",nc=" + nc + `,qop="` + qop + `",digest-uri="` + digest_uri + `",response=` + response if err = strm.Send(&sasl.Response{base64_encode(response)}); err != nil { return err } resp, err = strm.Read() if err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch rsp := resp.(type) { case *sasl.Challenge: if err = strm.Send(&sasl.Response{}); err != nil { return err } if resp, err = strm.Read(); err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch rsp := resp.(type) { case *sasl.Success: return nil case *sasl.Failure: return rsp case *stream.Error: return rsp } case *sasl.Failure: return rsp case *stream.Error: return rsp } } return stream.ErrMalformedProtocol }
func sasl_SCRAM_SHA_1(strm *stream.Stream, password string) error { var err error var resp interface{} cnonce := make_cnonce() clientFirstMessageBare := "n=" + strm.Jid.Node + ",r=" + cnonce data := "n,," + clientFirstMessageBare method := "SCRAM-SHA-1" if err = strm.Send(&sasl.Auth{&method, base64_encode(data)}); err != nil { return err } if resp, err = strm.Read(); err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch rsp := resp.(type) { case *sasl.Challenge: var t []byte if t, err = base64.StdEncoding.DecodeString(string(rsp.Data)); err != nil { return err } ch := string(t) serverFirstMessage := ch tokens := scram_attributes(ch) var salt []byte if salt, err = base64.StdEncoding.DecodeString(tokens["s"]); err != nil { return err } i, _ := strconv.Atoi(tokens["i"]) r := tokens["r"] saltedpassword := scram_Hi([]byte(jid.Resourceprep(password)), salt, i) clientKey := scram_HMAC(saltedpassword, []byte("Client Key")) storedKey := scram_H(clientKey) clientFinalMessageWithoutProof := "c=biws,r=" + r authMessage := []byte(clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof) clientSignature := scram_HMAC(storedKey, []byte(authMessage)) clientProof := scram_XOR(clientKey, clientSignature) serverKey := scram_HMAC(saltedpassword, []byte("Server Key")) serverSignature := scram_HMAC(serverKey, authMessage) response := clientFinalMessageWithoutProof + ",p=" + string(base64_encode(string(clientProof))) if err = strm.Send(&sasl.Response{base64_encode(response)}); err != nil { return err } if resp, err = strm.Read(); err != nil { return err } if resp == nil { return stream.ErrUnexpectedEOF } switch rsp := resp.(type) { case *sasl.Success: var t []byte if t, err = base64.StdEncoding.DecodeString(string(rsp.Data)); err != nil { return err } tokens = scram_attributes(string(t)) v := tokens["v"] if t, err = base64.StdEncoding.DecodeString(v); err != nil { return err } if string(t) != string(serverSignature) { return errors.New("Server Signature mismatch") } return nil case *sasl.Failure: return rsp case *stream.Error: return rsp } case *sasl.Failure: return rsp case *stream.Error: return rsp } return stream.ErrMalformedProtocol }