Ejemplo n.º 1
0
        /// <summary>
        /// If the msg contains a handshake token, inject it into the given params </summary>
        private static SortedDictionary <string, string> InjectHandshakeToken(AuthMsg msg,
                                                                              SortedDictionary <string, string> @params)
        {
            string tok = msg.Param("handshakeToken", false);

            if (tok != null)
            {
                @params["handshakeToken"] = tok;
            }
            return(@params);
        }
Ejemplo n.º 2
0
        private AuthMsg FinalMsg(IAuthClientContext cx, AuthMsg msg)
        {
            // Decode server-first-message
            string      s1_msg = Base64.URI.decodeUTF8(msg.Param("data"));
            IDictionary data   = DecodeMsg(s1_msg);

            // c2-no-proof
            string cbind_input     = gs2_header;
            string channel_binding = Base64.URI.EncodeUtf8(cbind_input);
            string nonce           = (string)data["r"];
            string c2_no_proof     = "c=" + channel_binding + ",r=" + nonce;

            // proof
            string hash       = msg.Param("hash");
            string salt       = (string)data["s"];
            int    iterations = int.Parse((string)data["i"]);
            string c1_bare    = (string)cx.stash["c1_bare"];
            string authMsg    = c1_bare + "," + s1_msg + "," + c2_no_proof;

            string c2_msg = null;

            try
            {
                sbyte[] saltedPassword = Pbk(hash, cx.pass, salt, iterations);
                string  clientProof    = CreateClientProof(hash, saltedPassword, (sbyte[])(Array)Encoding.UTF8.GetBytes(authMsg));
                c2_msg = c2_no_proof + ",p= " + clientProof;
            }
            catch (Exception e)
            {
                throw new AuthException("Failed to compute scram", e);
            }

            // build auth msg
            SortedDictionary <string, string> @params = new SortedDictionary <string, string>();

            @params["data"] = Base64.URI.EncodeUtf8(c2_msg);
            return(new AuthMsg(name, InjectHandshakeToken(msg, @params)));
        }
        /// <summary>
        ///   Attempt standard authentication
        /// </summary>
        /// <param name="resp"> The response to the hello message </param>
        /// <returns>
        ///   true if haystack authentciation was used, false if the
        ///   server does not appear to implement RFC 7235.
        /// </returns>
        private bool OpenStd(HttpWebResponse resp)
        {
            // must be 401 challenge with WWW-Authenticate header
            if (resp.StatusCode != HttpStatusCode.Unauthorized)
            {
                return(false);
            }
            var wwwAuth = ResHeader(resp, "WWW-Authenticate");

            // don't Use this mechanism for Basic which we
            // handle as a non-standard scheme because the headers
            // don't fit nicely into our restricted AuthMsg format
            if (string.IsNullOrEmpty(wwwAuth) || wwwAuth.ToLower().StartsWith("basic", StringComparison.Ordinal))
            {
                return(false);
            }
            // process res/req messages until we have 200 or non-401 failure
            AuthScheme scheme = null;

            for (var loopCount = 0; ; ++loopCount)
            {
                // sanity check that we don't loop too many times
                if (loopCount > 5)
                {
                    throw new AuthException("Loop count exceeded");
                }

                // parse the WWW-Auth header and Use the first scheme
                var       header  = ResHeader(resp, "WWW-Authenticate");
                AuthMsg[] resMsgs = AuthMsg.ListFromStr(header);
                var       resMsg  = resMsgs[0];
                scheme = AuthScheme.Find(resMsg.scheme);

                // let scheme handle message
                var reqMsg = scheme.OnClient(this, resMsg);
                // send request back to the server
                resp = GetAuth(reqMsg);
                try
                {
                    DumpRes(resp, false);
                }
                catch (Exception e)
                {
                    e.ToString();
                }
                // 200 means we are done, 401 means keep looping,
                // consider anything else a failure
                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    break;
                }
                if (resp.StatusCode == HttpStatusCode.Unauthorized)
                {
                    continue;
                }
                throw new AuthException((int)resp.StatusCode + " " + resp.GetResponseStream());
            }
            // init the bearer token
            var     authInfo    = ResHeader(resp, "Authentication-Info");
            AuthMsg authInfoMsg = AuthMsg.FromStr("bearer " + authInfo);

            // callback to scheme for client Success
            scheme.OnClientSuccess(this, authInfoMsg);

            // only keep authToken parameter for Authorization header
            authInfoMsg = new AuthMsg("bearer", new[]
            {
                "authToken",
                authInfoMsg.Param("authToken")
            });
            headers["Authorization"] = authInfoMsg.ToString();

            // we did it!
            return(true);
        }
Ejemplo n.º 4
0
 public override AuthMsg OnClient(IAuthClientContext cx, AuthMsg msg)
 {
     return(ReferenceEquals(msg.Param("data", false), null) ? FirstMsg(cx, msg) : FinalMsg(cx, msg));
 }