Ejemplo n.º 1
0
        public void NoUserTypeIdUpdate()
        {
            var r = new Restrictions();

            var user = new User
            {
                Id = 1,
                UserTypeId = 2
            };

            var updates = new Dictionary<object, Restrictions.ShadowModifiedMember[]>();
            updates[user] = new Restrictions.ShadowModifiedMember[]
                { 
                    new Restrictions.ShadowModifiedMember
                    { 
                        Member = typeof(User).GetProperty("UserTypeId"),
                        CurrentValue = user.UserTypeId,
                        OriginalValue = 1
                    }
                };

            string ignored;
            Assert.IsFalse(r.IsValidChangeSet(updates, new List<object>(), new List<object>(), new List<object>() { user }, new List<int>() { 1 }, out ignored));
            Assert.IsFalse(r.IsValidChangeSet(updates, new List<object>(), new List<object>(), new List<object>() { user }, new List<int>(), out ignored));
        }
Ejemplo n.º 2
0
        public void UpdateUsersInList()
        {
            var r = new Restrictions();

            var user = new User
            {
                Id = 1,
                CreationDate = DateTime.UtcNow
            };

            var updates = new Dictionary<object, Restrictions.ShadowModifiedMember[]>();
            updates[user] = new Restrictions.ShadowModifiedMember[]
                { 
                    new Restrictions.ShadowModifiedMember
                    { 
                        Member = typeof(User).GetProperty("CreationDate"),
                        CurrentValue = user.CreationDate,
                        OriginalValue = null
                    }
                };

            string ignored;
            Assert.IsTrue(r.IsValidChangeSet(updates, new List<object>(), new List<object>(), new List<object>() { user }, new List<int>() { 1 }, out ignored), ignored);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Repeated logic from SetNewPassword.
        /// 
        /// Pass it a resetToken to destroy on success (if user is anonymous).
        /// 
        /// Returns null if everything is OK, and an ActionResult if an error occurred.
        /// </summary>
        private ActionResult ChangePasswordAndSendEmail(string password, string password2, string token, PasswordReset resetToken, User user, DateTime now)
        {
            string message;
            if (!Password.CheckPassword(password, password2, user.Email, user.VanityProviderId, user.ProviderId, out message))
                return RecoverableError(message, new { token });

            user.ChangePassword(now, password);

            if (resetToken != null)
            {
                Current.WriteDB.PasswordResets.DeleteOnSubmit(resetToken);
            }

            Current.WriteDB.SubmitChanges();

            var account = SafeRedirect((Func<ActionResult>)(new UserController()).ViewUser);

            if (!Current.Email.SendEmail(user.Email, Email.Template.PasswordChanged, new { AccountLink = Current.Url(account.Url).AsLink() }))
            {
                return IrrecoverableError("An error occurred sending the email", "This has been recorded, and will be looked into shortly");
            }

            return null;
        }
Ejemplo n.º 4
0
 partial void DeleteUser(User instance);
Ejemplo n.º 5
0
 partial void UpdateUser(User instance);
Ejemplo n.º 6
0
 partial void InsertUser(User instance);
Ejemplo n.º 7
0
        /// <summary>
        /// Gives a black mark to an IP that just failed a login attempt.
        /// 
        /// Passes the user, if the account exists at all.
        /// 
        /// Repeated attempts to login to a single account can be very worrying past
        /// a certain number, but fat fingering does happen so we don't want to panic
        /// immediately.
        /// 
        /// Repeated attempts to *different* accounts is almost certainly a sign of an
        /// attack, once the number of involved accounts grows to a certain size.
        /// </summary>
        public static void BadLoginAttempt(User user, string ip)
        {
            UpdateInfractionList(ip,
                new Infraction
                { 
                    Type = Infraction.InfractionType.Login, 
                    Expires = Current.Now.Add(TimeSpan.FromMinutes(5)), 
                    RelatedId = user != null ? user.Id : -1
                }
            );

            var existingInfractions = GetInfractionList(ip);

            var singleUser = existingInfractions.Where(i => i.Type == Infraction.InfractionType.Login && i.RelatedId != -1).GroupBy(i => i.RelatedId).Max(g => (int?)g.Count());

            if (singleUser > 10)
            {
                Ban(ip, TimeSpan.FromMinutes(5), "More than 10 attempts to login as a user.");
                return;
            }

            var noUser = existingInfractions.Count(i => i.Type == Infraction.InfractionType.Login && i.RelatedId == -1);

            if (noUser > 20)
            {
                Ban(ip, TimeSpan.FromMinutes(30), "More than 20 attempts to login.");
                return;
            }

            var total = existingInfractions.Count(i => i.Type == Infraction.InfractionType.Login);

            // This suggests they're trying to actually dodge our single and scan behavior; drop the hammer
            if (total > 30)
            {
                Ban(ip, TimeSpan.FromMinutes(60), "Appears to be spamming login attempts, while dodging throttles.");
                return;
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Create a new account given an email and password
        /// </summary>
        public static bool CreateAccount(string email, PendingUser pendingUser, DateTime now, string vanity, string realname, out User created, out string errorMessage)
        {
            email = email.ToLowerInvariant();

            if (vanity.HasValue() && !Models.User.IsValidVanityId(vanity, out errorMessage))
            {
                created = null;

                return false;
            }

            var db = Current.WriteDB;

            // Quick check to make sure the vanity id is not in use elsewhere
            if (vanity.HasValue() && db.Users.Any(u => u.VanityProviderId == vanity))
            {
                created = null;
                errorMessage = "That Vanity OpenId is already in use";

                return false;
            }

            var provider = Current.UniqueId();

            // Odds of colision are miniscule, but might as well check
            while (db.Users.Any(u => u.ProviderId == provider))
                provider = Current.UniqueId();

            // We need to compute these way before we use them for some length checks
            byte emailVersion;
            string emailIV, emailHMAC;
            var emailEncrypted = Current.Encrypt(email, out emailIV, out emailVersion, out emailHMAC);

            byte nameVersion = 0xFF;
            string nameEncrypted= null, nameIV = null, nameHMAC = null;

            if (realname.HasValue())
            {
                nameEncrypted = Current.Encrypt(realname, out nameIV, out nameVersion, out nameHMAC);
            }

            if (emailEncrypted.Length > 267)
            {
                created = null;
                errorMessage = "Email is too long";

                return false;
            }

            if (nameEncrypted.HasValue() && nameEncrypted.Length > 267)
            {
                created = null;
                errorMessage = "Name is too long";

                return false;
            }

            string emailHash;
            byte emailSaltVersion;
            emailHash = Current.SystemHash(email, out emailSaltVersion);

            var newUser =
                new User
                {
                    LastActivityDate = DateTime.UtcNow,
                    EmailHash = emailHash,
                    EmailSaltVersion = emailSaltVersion,
                    ProviderId = provider,
                    PasswordHash = pendingUser.PasswordHash,
                    PasswordSalt = pendingUser.PasswordSalt,
                    CreationDate = now,
                    VanityProviderId = vanity,
                    UserTypeId = Models.UserTypeId.Normal
                };

            try
            {
                db.Users.InsertOnSubmit(newUser);
                db.SubmitChanges();
            }
            catch (Exception e)
            {
                // Hack: There isn't really a nice way to detect a unique constraint conflict,
                //       so... check the message.  Checking for the constraint name so this isn't
                //       *guaranteed* to break on non-English language systems... still not guaranteed
                //       to work though.
                if(e is System.Data.SqlClient.SqlException && e.Message.Contains("Users_EmailHash_EmailSaltVersion"))
                {
                    created = null;
                    errorMessage = "Email address already registered.";
                    return false;
                }

                Current.LogException(e);
                created = null;
                errorMessage = "User account could not be created.";
                return false;
            }

            // Open season on this user until the context is torn down.
            db.LiftUserRestrictionsOnId = newUser.Id;

            // Can't put a unique constrain on VanityProviderId (as its normally null), so
            //    this is a hack to make sure no two users end up slipping in and getting the 
            //    same vanity id.
            if (vanity.HasValue() && db.Users.Count(u => u.VanityProviderId == vanity) != 1)
            {
                newUser.VanityProviderId = null;
                db.SubmitChanges();
            }

            var emailAttr =
                new UserAttribute
                {
                    UserId = newUser.Id,
                    CreationDate = now,
                    UserAttributeTypeId = UserAttributeTypeId.Email,
                    Encrypted = emailEncrypted,
                    IV = emailIV,
                    KeyVersion = emailVersion,
                    HMAC = emailHMAC
                };

            db.UserAttributes.InsertOnSubmit(emailAttr);
            db.SubmitChanges();

            if (realname.HasValue())
            {
                var nameAttr =
                    new UserAttribute
                    {
                        UserId = newUser.Id,
                        CreationDate = now,
                        UserAttributeTypeId = UserAttributeTypeId.RealName,
                        Encrypted = nameEncrypted,
                        IV = nameIV,
                        KeyVersion = nameVersion,
                        HMAC = nameHMAC
                    };

                db.UserAttributes.InsertOnSubmit(nameAttr);
                db.SubmitChanges();
            }

            created = newUser;
            errorMessage = null;

            return true;
        }