private HttpWebResponse SendHello()
 {
     // hello message
     try
     {
         var parameters = new SortedDictionary <string, string>();
         parameters["username"] = Base64.URI.EncodeUtf8(user);
         var hello = new AuthMsg("hello", parameters);
         return(GetAuth(hello));
     }
     catch (WebException e)
     {
         var response = e.Response;
         if (response != null)
         {
             var httpresp = (HttpWebResponse)response;
             // 401 Unauthorized
             // 500 Internal Server Error, for compatibility with nhaystack
             if (httpresp.StatusCode == HttpStatusCode.Unauthorized || httpresp.StatusCode == HttpStatusCode.InternalServerError)
             {
                 return(httpresp);
             }
         }
         throw;
     }
 }
Пример #2
0
 private async Task <HttpWebResponse> GetAuthAsync(AuthMsg msg)
 {
     return(await ServerCallAsync("about", c =>
     {
         // set Authorization header
         c.Headers.Set("Authorization", msg.ToString());
     }));
 }
Пример #3
0
        //////////////////////////////////////////////////////////////////////////
        // Construction
        //////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Parse a List of AuthSchemes such as a List of 'challenge'
        /// productions for the WWW-Authentication header per RFC 7235.
        /// </summary>
        public static AuthMsg[] ListFromStr(string s)
        {
            string[]  toks = SplitList(s);
            AuthMsg[] arr  = new AuthMsg[toks.Length];
            for (int i = 0; i < toks.Length; ++i)
            {
                arr[i] = AuthMsg.FromStr(toks[i]);
            }
            return(arr);
        }
Пример #4
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);
        }
        private HttpWebResponse GetAuth(AuthMsg msg)
        {
            try
            {
                // all AuthClientContext requests are GET message to the /About uri
                var c = Prepare(OpenHttpConnection(uri, "GET"));

                // set Authorization header
                c.Headers.Set("Authorization", msg.ToString());
                return(Get(c));
            }
            catch (IOException e)
            {
                throw e;
            }
        }
Пример #6
0
        private AuthMsg FirstMsg(IAuthClientContext cx, AuthMsg msg)
        {
            // construct client-first-message
            string c_nonce = GenNonce();
            string c1_bare = "n=" + cx.user + ",r=" + c_nonce;
            string c1_msg  = gs2_header + c1_bare;

            // stash for final msg
            cx.stash["c_nonce"] = c_nonce;
            cx.stash["c1_bare"] = c1_bare;

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

            @params["data"] = Base64.URI.EncodeUtf8(c1_msg);
            return(new AuthMsg(name, InjectHandshakeToken(msg, @params)));
        }
Пример #7
0
        public override bool Equals(object o)
        {
            if (this == o)
            {
                return(true);
            }
            if (o == null || this.GetType() != o.GetType())
            {
                return(false);
            }

            AuthMsg authMsg = (AuthMsg)o;

            if (!scheme.Equals(authMsg.scheme))
            {
                return(false);
            }
            var comparer = new SortedDictComparer();

            return(comparer.Compare(@params, authMsg.@params) == 1);
        }
Пример #8
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)));
        }
Пример #9
0
 public override AuthMsg OnClient(IAuthClientContext cx, AuthMsg msg)
 {
     throw new System.NotSupportedException();
 }
        /// <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);
        }
Пример #11
0
 /// <summary>
 ///	Handle a standardized client authentication challenge message from
 ///	the server using RFC 7235.
 /// </summary>
 /// <param name="cx">the current AuthClientContext</param>
 /// <param name="msg">the AuthMsg sent by the server</param>
 /// <returns>AuthMsg to send back to the server to authenticate</returns>
 public abstract AuthMsg OnClient(IAuthClientContext cx, AuthMsg msg);
Пример #12
0
 /// <summary>
 ///	Callback after successful authentication with the server.
 ///	The default implementation is a no-op.
 /// </summary>
 /// <param name="cx">the current AuthClientContext</param>
 /// <param name="msg">AuthMsg sent by the server when it authenticated the client</param>
 public virtual void OnClientSuccess(IAuthClientContext cx, AuthMsg msg)
 {
 }
Пример #13
0
 public override AuthMsg OnClient(IAuthClientContext cx, AuthMsg msg)
 {
     return(ReferenceEquals(msg.Param("data", false), null) ? FirstMsg(cx, msg) : FinalMsg(cx, msg));
 }