/// <summary> /// Process the second server challenge /// </summary> /// <param name="challenge">Server issued challenge</param> /// <returns>The client response</returns> private byte[] OnFinalResponse(byte[] challenge) { DigestChallenge dch = DigestChallenge.Parse(_encoding.GetString(challenge)); if (dch.Rspauth == null || dch.Rspauth.Length == 0) { throw new SaslException("Expected 'rspauth' in server challenge not found"); } SetComplete(); return(new byte[0]); }
// // Private Methods // /// <summary> /// Process the first challenge from the server /// and calculate a response /// </summary> /// <param name="challenge">The server issued challenge</param> /// <returns>Client response</returns> private byte[] OnInitialChallenge(byte[] challenge) { DigestChallenge dch = DigestChallenge.Parse(_encoding.GetString(challenge)); // validate input challenge if (dch.Nonce == null || dch.Nonce.Length == 0) { throw new SaslException("Nonce value missing in server challenge"); } if (dch.Algorithm != "md5-sess") { throw new SaslException("Invalid or missing algorithm value in server challenge"); } NameCallback nameCB = new NameCallback(AuthorizationId); PasswordCallback pwdCB = new PasswordCallback(); RealmCallback realmCB = new RealmCallback(dch.Realm); ISaslCallback[] callbacks = { nameCB, pwdCB, realmCB }; Handler.Handle(callbacks); DigestResponse response = new DigestResponse(); response.Username = nameCB.Text; response.Realm = realmCB.Text; response.Nonce = dch.Nonce; response.Cnonce = Cnonce; response.NonceCount = 1; response.Qop = DigestQop.Auth; // only auth supported for now response.DigestUri = Protocol.ToLower() + "/" + ServerName; response.MaxBuffer = dch.MaxBuffer; response.Charset = dch.Charset; response.Cipher = null; // not supported for now response.Authzid = AuthorizationId; response.AuthParam = dch.AuthParam; response.Response = CalculateResponse( nameCB.Text, realmCB.Text, pwdCB.Text, dch.Nonce, response.NonceCount, response.Qop, response.DigestUri ); return(_encoding.GetBytes(response.ToString())); }