Example #1
0
// Initializes the SASL handshake using the specified mechanism
func Init(mechanism string, data []byte) ([]byte, []byte, error) {
	switch mechanism {
	case "SCRAM-SHA-1":
		msg, err := auth.DecodeBase64(data)
		if err != nil {
			log.Println(err)
			return nil, nil, AuthFailError
		}
		nonce := genNonce()
		response, err := InitialResponseSCRAMSHA1(msg, nonce)
		if err != nil {
			return nil, nil, err
		}
		splitMsg := strings.Split(string(msg), ",")
		data := []byte(splitMsg[2] + "," + splitMsg[3] + "," + string(response))

		return auth.EncodeBase64(response), data, nil

	default:
		return nil, nil, UnsupportedAuthenticationMechanism(mechanism)
	}

	log.Printf("Impossible program flow!\n")
	return nil, nil, nil
}
Example #2
0
func (a *Auth) GetUserName() (string, error) {
	raw, err := auth.DecodeBase64(a.Data)
	if err != nil {
		return "", err
	}

	parts := strings.Split(string(raw), ",")

	return parts[2][2:], nil
}
Example #3
0
func FinalResponseSCRAMSHA1(clientFinalMsg, prevMsg []byte) ([]byte, error) {
	oldMsg := strings.Split(string(prevMsg), ",")
	components := strings.Split(string(clientFinalMsg), ",")

	if oldMsg[2] != components[1] {
		log.Println("session nonce does not match")
		return nil, AuthFailError
	}

	authMsg := string(prevMsg) + "," + components[0] + "," + components[1]

	username := oldMsg[2][2:]
	user := records.Users.FindByName(username)

	// for some reason there are null characters at the end?
	tmp := strings.TrimRight(components[2][2:], "\x00")
	clientProof, err := auth.DecodeBase64([]byte(tmp))
	if err != nil {
		log.Println(err)
		return nil, AuthFailError
	}
	clientKey := auth.HMAC(user.Pass.Key, "Client Key")
	storedKey := auth.H(clientKey)
	clientSignature := auth.HMAC(storedKey, authMsg)

	length := len(storedKey)
	authFailed := false
	for i := 0; i < length; i++ {
		v := clientKey[i] ^ clientSignature[i]
		if clientProof[i] != v {
			authFailed = true
		}
	}

	// avoid early exit when comparing password related data
	if authFailed {
		log.Println("Invalid Client Proof")
		return nil, AuthFailError
	}

	serverKey := auth.HMAC(user.Pass.Key, "Server Key")
	signature := auth.HMAC(serverKey, authMsg)
	armouredSignature := auth.EncodeBase64(signature)
	return []byte("v=" + string(armouredSignature)), nil
}
Example #4
0
// Continues the SASL handshake
func Respond(mech string, data []byte, storedData []byte) ([]byte, error) {
	switch mech {
	case "SCRAM-SHA-1":
		raw, err := auth.DecodeBase64(data)
		if err != nil {
			log.Println(err)
			return nil, AuthFailError
		}

		response, err := FinalResponseSCRAMSHA1(raw, storedData)
		if err != nil {
			return nil, err
		}

		return auth.EncodeBase64(response), nil

	default:
		return nil, UnsupportedAuthenticationMechanism(mech)
	}
}
	Describe("final response", func() {
		It("should not accept mismatch between the input and cached nonce", func() {
			_, err := FinalResponseSCRAMSHA1([]byte("c=,r=abcd,p="), []byte("n=,r=,r=abc,s=,i="))
			Expect(err).NotTo(BeNil())
		})

		It("should not accept invalid Client Proofs", func() {
			_, err := FinalResponseSCRAMSHA1([]byte("c=,r=abc,p=hello"), []byte("n=,r=,r=abc,s=,i="))
			Expect(err).NotTo(BeNil())
		})
	})

	Context("full handshake", func() {

		salt, _ := auth.DecodeBase64([]byte("QSXCR+Q6sek8bf92"))
		StubUser = models.User{
			Pass: auth.Pass{
				Salt: salt,
				Key:  auth.Hi([]byte("pencil"), salt, auth.PASSWORD_ITERATIONS),
			},
		}
		iters := strconv.Itoa(auth.PASSWORD_ITERATIONS)
		clientNonce := "fyko+d2lbbFgONRv9qkxdawL"
		nonce := "3rfcNHYJY1ZVvWVs7j"
		username := "******"

		It("should respond correctly to the first message", func() {
			clientMsg := "n,,u=" + username + ",n=" + clientNonce
			msg, err := InitialResponseSCRAMSHA1([]byte(clientMsg), []byte(nonce))