public static DigestChallenge Parse(string challenge) { DigestChallenge parsed = new DigestChallenge(); StringDictionary parts = ParseParameters(challenge); foreach (string optname in parts.Keys) { switch (optname) { case "realm": parsed._realm = parts[optname]; break; case "nonce": parsed._nonce = parts[optname]; break; case "qop-options": parsed._qopOptions = GetOptions(parts[optname]); break; case "cipher-opts": parsed._cipherOptions = GetOptions(parts[optname]); break; case "stale": parsed._stale = Convert.ToBoolean(parts[optname], CultureInfo.InvariantCulture); break; case "maxbuf": parsed._maxBuffer = Convert.ToInt32(parts[optname], CultureInfo.InvariantCulture); break; case "charset": parsed._charset = parts[optname]; break; case "algorithm": parsed._algorithm = parts[optname]; break; case "auth-param": parsed._authParam = parts[optname]; break; case "rspauth": parsed._rspauth = parts[optname]; break; } } return(parsed); }
/// <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())); }
public static DigestChallenge Parse(string challenge) { DigestChallenge parsed = new DigestChallenge(); StringDictionary parts = ParseParameters(challenge); foreach ( string optname in parts.Keys ) { switch ( optname ) { case "realm": parsed._realm = parts[optname]; break; case "nonce": parsed._nonce = parts[optname]; break; case "qop-options": parsed._qopOptions = GetOptions(parts[optname]); break; case "cipher-opts": parsed._cipherOptions = GetOptions(parts[optname]); break; case "stale": parsed._stale = Convert.ToBoolean(parts[optname], CultureInfo.InvariantCulture); break; case "maxbuf": parsed._maxBuffer = Convert.ToInt32(parts[optname], CultureInfo.InvariantCulture); break; case "charset": parsed._charset = parts[optname]; break; case "algorithm": parsed._algorithm = parts[optname]; break; case "auth-param": parsed._authParam = parts[optname]; break; case "rspauth": parsed._rspauth = parts[optname]; break; } } return parsed; }