Пример #1
0
        /// <summary>
        /// Attempts to login in the system.
        /// </summary>
        /// <param name="UserName">User name</param>
        /// <param name="Password">Password</param>
        /// <param name="RemoteEndPoint">Remote endpoint of user attempting to login.</param>
        /// <param name="Protocol">Protocol used for login.</param>
        /// <returns>Login result.</returns>
        public static async Task <LoginResult> Login(string UserName, string Password, string RemoteEndPoint, string Protocol)
        {
            if (string.IsNullOrEmpty(Password))
            {
                return(new LoginResult());
            }

            if (!(loginAuditor is null))
            {
                DateTime?Next = await loginAuditor.GetEarliestLoginOpportunity(RemoteEndPoint, Protocol);

                if (Next.HasValue)
                {
                    return(new LoginResult(Next.Value));
                }
            }

            User User = await GetUser(UserName, false);

            if (!(User is null) && User.PasswordHash != Convert.ToBase64String(ComputeHash(UserName, Password)))
            {
                User = null;
            }

            if (User is null)
            {
                LoginAuditor.Fail("Invalid login.", UserName, RemoteEndPoint, Protocol);
            }
            else
            {
                LoginAuditor.Success("Successful login.", UserName, RemoteEndPoint, Protocol);
            }

            return(new LoginResult(User));
        }
Пример #2
0
        /// <summary>
        /// Registers a Hash Digest Computation Method.
        /// </summary>
        /// <param name="HashComputationMethod">Hash Digest Computation Method.</param>
        /// <param name="HashMethodTypeName">Hash Digest Computation Method Type Name.</param>
        /// <param name="LoginAuditor">Auditor of login attempts.</param>
        /// <param name="Lock">If the registration should be locked.</param>
        public static void Register(HashComputationMethod HashComputationMethod, string HashMethodTypeName, LoginAuditor LoginAuditor, bool Lock)
        {
            if (hashMethodLocked)
            {
                throw new InvalidOperationException("Hash method already registered, and locked.");
            }

            loginAuditor       = LoginAuditor;
            hashMethod         = HashComputationMethod;
            hashMethodTypeName = HashMethodTypeName;
            hashMethodLocked   = Lock;
        }
Пример #3
0
        /// <summary>
        /// Checks if the request is authorized.
        /// </summary>
        /// <param name="Request">Request object.</param>
        /// <param name="User">User object, if authenticated.</param>
        /// <returns>If the request is authorized.</returns>
        public override bool IsAuthenticated(HttpRequest Request, out IUser User)
        {
            HttpFieldAuthorization Authorization = Request.Header.Authorization;

            if (Authorization != null && Authorization.Value.StartsWith("Basic ", StringComparison.CurrentCultureIgnoreCase))
            {
                byte[] Data = Convert.FromBase64String(Authorization.Value.Substring(6).Trim());
                string s    = InternetContent.ISO_8859_1.GetString(Data);
                int    i    = s.IndexOf(':');
                if (i > 0)
                {
                    string UserName = s.Substring(0, i);
                    string Password = s.Substring(i + 1);

                    if (!this.users.TryGetUser(UserName, out User))
                    {
                        LoginAuditor.Fail("Login attempt using invalid user name.", UserName, Request.RemoteEndPoint, "HTTP");
                        return(false);
                    }

                    switch (User.PasswordHashType)
                    {
                    case "":
                        break;

                    case "DIGEST-MD5":
                        Password = DigestAuthentication.ToHex(DigestAuthentication.H(UserName + ":" + this.realm + ":" + Password));
                        break;

                    default:
                        User = null;
                        return(false);
                    }

                    if (Password == User.PasswordHash)
                    {
                        LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP");
                        return(true);
                    }
                    else
                    {
                        LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP");
                        User = null;
                        return(false);
                    }
                }
            }

            User = null;
            return(false);
        }
Пример #4
0
        public static void AssemblyInitialize(TestContext _)
        {
            Types.Initialize(
                typeof(Database).Assembly,
                typeof(FilesProvider).Assembly,
                typeof(ObjectSerializer).Assembly,
                typeof(LoginAuditor).Assembly);

            filesProvider = new FilesProvider("Data", "Default", 8192, 10000, 8192, Encoding.UTF8, 10000, true);
            Database.Register(filesProvider);

            auditor = new LoginAuditor("Login Auditor",
                                       new LoginInterval(5, TimeSpan.FromHours(1)), // Maximum 5 failed login attempts in an hour
                                       new LoginInterval(2, TimeSpan.FromDays(1)),  // Maximum 2x5 failed login attempts in a day
                                       new LoginInterval(2, TimeSpan.FromDays(7)),  // Maximum 2x2x5 failed login attempts in a week
                                       new LoginInterval(2, TimeSpan.MaxValue));    // Maximum 2x2x2x5 failed login attempts in total, then blocked.
        }
Пример #5
0
        /// <summary>
        /// Checks if the request is authorized.
        /// </summary>
        /// <param name="Request">Request object.</param>
        /// <returns>User object, if authenticated, or null otherwise.</returns>
        public override async Task <IUser> IsAuthenticated(HttpRequest Request)
        {
            HttpFieldAuthorization Authorization = Request.Header.Authorization;

            if (Authorization != null && Authorization.Value.StartsWith("Bearer ", StringComparison.CurrentCultureIgnoreCase))
            {
                try
                {
                    string   TokenStr = Authorization.Value.Substring(7).Trim();
                    JwtToken Token    = new JwtToken(TokenStr);
                    string   UserName = Token.Subject;

                    if (!this.factory.IsValid(Token) || UserName is null)
                    {
                        LoginAuditor.Fail("Login attempt failed.", UserName ?? string.Empty, Request.RemoteEndPoint, "HTTP");
                        return(null);
                    }

                    IUser User = await this.users.TryGetUser(UserName);

                    if (User is null)
                    {
                        LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP");
                        return(null);
                    }
                    else
                    {
                        LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP");
                        return(User);
                    }
                }
                catch (Exception)
                {
                    return(null);
                }
            }

            return(null);
        }
        /// <summary>
        /// Checks if the request is authorized.
        /// </summary>
        /// <param name="Request">Request object.</param>
        /// <returns>User object, if authenticated, or null otherwise.</returns>
        public override async Task <IUser> IsAuthenticated(HttpRequest Request)
        {
            HttpFieldAuthorization Authorization = Request.Header.Authorization;

            if (Authorization != null && Authorization.Value.StartsWith("Digest ", StringComparison.CurrentCultureIgnoreCase))
            {
                string   UserName = null;
                string   Opaque   = null;
                string   Realm    = null;
                string   Nonce    = null;
                string   Cnonce   = null;
                string   Nc       = null;
                string   Uri      = null;
                string   Qop      = null;
                string[] QopItems;
                string   Response = null;
                bool     Auth     = false;
                bool     AuthInt  = false;

                foreach (KeyValuePair <string, string> P in CommonTypes.ParseFieldValues(Authorization.Value.Substring(7)))
                {
                    switch (P.Key.ToLower())
                    {
                    case "username":
                        UserName = P.Value;
                        break;

                    case "opaque":
                        Opaque = P.Value;
                        break;

                    case "realm":
                        Realm = P.Value;
                        break;

                    case "nonce":
                        Nonce = P.Value;
                        break;

                    case "cnonce":
                        Cnonce = P.Value;
                        break;

                    case "nc":
                        Nc = P.Value;
                        break;

                    case "uri":
                        Uri = P.Value;
                        break;

                    case "qop":
                        Qop      = P.Value;
                        QopItems = Qop.Split(',');

                        Auth    = (Array.IndexOf(QopItems, "auth") >= 0);
                        AuthInt = (Array.IndexOf(QopItems, "auth-int") >= 0);
                        break;

                    case "response":
                        Response = P.Value;
                        break;
                    }
                }

                if (this.realm != Realm || Qop is null || Nonce is null || Cnonce is null || Nc is null ||
                    Uri is null || Response is null || UserName is null || (!Auth && !AuthInt))
                {
                    return(null);
                }

                if (this.opaque != Opaque)
                {
                    // We need to ignore the opaque value if it's a POST from a web form, since it can be used from the original GET
                    // (which might have ocurred when another instance of the application ran).

                    if (Request.Header.Method != "POST" || Request.Header.ContentType.Value != "application/x-www-form-urlencoded")
                    {
                        return(null);
                    }
                }

                DateTime TP = DateTime.Now;

                lock (this)
                {
                    LinkedList <DateTime> ToRemove = null;

                    foreach (KeyValuePair <DateTime, string> Pair in this.nonceByExpiration)
                    {
                        if (Pair.Key <= TP)
                        {
                            if (ToRemove is null)
                            {
                                ToRemove = new LinkedList <DateTime>();
                            }

                            ToRemove.AddLast(Pair.Key);
                            this.expirationByNonce.Remove(Pair.Value);
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (ToRemove != null)
                    {
                        foreach (DateTime ExpiryDate in ToRemove)
                        {
                            this.nonceByExpiration.Remove(ExpiryDate);
                        }
                    }

                    if (!this.expirationByNonce.TryGetValue(Nonce, out TP))
                    {
                        // We need to ignore the nonce value if it's a POST from a web form, since it can be used from the original GET
                        // (which might have ocurred when another instance of the application ran).

                        if (Request.Header.Method != "POST" || Request.Header.ContentType.Value != "application/x-www-form-urlencoded")
                        {
                            return(null);
                        }
                    }

                    if (Request.Header.Method != "HEAD")
                    {
                        this.expirationByNonce.Remove(Nonce);
                        this.nonceByExpiration.Remove(TP);
                    }
                }

                string HA1;
                string HA2;
                string Digest;

                IUser User = await this.users.TryGetUser(UserName);

                if (User is null)
                {
                    return(null);
                }

                switch (User.PasswordHashType)
                {
                case "":
                    HA1 = ToHex(H(UserName + ":" + this.realm + ":" + User.PasswordHash));
                    break;

                case "DIGEST-MD5":
                    HA1 = User.PasswordHash;
                    break;

                default:
                    return(null);
                }

                if (AuthInt)
                {
                    HA2 = ToHex(H(Request.Header.Method + ":" + Uri + ":" + ToHex(H(string.Empty))));
                }
                else
                {
                    HA2 = ToHex(H(Request.Header.Method + ":" + Uri));
                }

                Digest = HA1 + ":" + Nonce + ":" + Nc + ":" + Cnonce + ":" + Qop + ":" + HA2;
                Digest = ToHex(H(Digest));

                if (Digest == Response)
                {
                    LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP");
                    return(User);
                }
                else
                {
                    LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP");
                    return(null);
                }
            }

            return(null);
        }