/// <summary> /// Create a new user - base level simple insertion /// uses salted hash for password authentication /// </summary> /// <param name="username">username</param> /// <param name="password">cleartext password</param> /// <param name="noDuplicates">Will we allow duplicates? Not usually...</param> /// <param name="parameters">Additional parameters to save in user record as Key,value pairs key must match db colname</param> /// <returns>numer of rows inserted or -1 means something bad happened</returns> public int CreateNewUser(string username, string password, bool noDuplicates = true, Dictionary <string, string> parameters = null) { int retval = -1; DataTools dt = new DataTools(); dt.Provider = provider; dt.ConnectionString = connectionString; dt.OpenConnection(); string[] parameter = { UsernameCol, username }; //!!! What is wrong with parameterized query? //dt.GetResultSet(findUserQuery, parameter); dt.GetResultSet(string.Format(findUserQueryTok, username)); if (dt.rowcount > 0 && noDuplicates) { return(retval); //* EXIT } //optionally to fill other fields via parameters Dictionary <string, string> items = null; if (parameters != null) { items = new Dictionary <string, string>(parameters); } else { items = new Dictionary <string, string>(); } items.Add(UsernameCol, username); byte[] salt = GenerateSalt(); string saltString = Convert.ToBase64String(salt); string hash = HashPassword(password, salt); items.Add(HashCol, hash); items.Add(SaltCol, saltString); //string insertStatement = dt.InsertStatement(items,UsersTableName); ; int result = dt.Insert(items, UsersTableName); retval = result; //number of rows inserted... return(retval); }
/// <summary> /// Simply get a user from the localDb /// </summary> /// <param name="username"></param> /// <returns></returns> public Dictionary <string, string> GetUser(string username) { Dictionary <string, string> retVal = new Dictionary <string, string>(); //$$$ Centalize this - without locking up a connection DataTools dt = new DataTools(); dt.Provider = provider; dt.ConnectionString = connectionString; dt.OpenConnection(); string[] parameter = { UsernameCol, username }; //!!! What is wrong with parameterized query? //dt.GetResultSet(findUserQuery, parameter); dt.GetResultSet(string.Format(findUserQueryTok, username)); while (!dt.EOF) { var row = dt.GetRow(); var nm = row[UsernameCol]; retVal.Add(UsernameCol, nm.ToString()); dt.NextRow(); } return(retVal); }
/// <summary> /// Given username and other information authenticate the user from local db /// </summary> /// <param name="username">domain\user name or just name</param> /// <param name="password"></param> /// <param name="authmode"> /// -1 - uninitialized or undefined authentication profile /// 0 - active directory user /// 1 - local database user</param> /// <returns> 0 - authenticated, 1 - user doesnt exist, 2 - user info populated but no data, /// 3 - invalid password, 4 - user is set to inactive/no_access</returns> public int AuthenticateUser(string username, string password, out int authmode) { int retval = USER_NONEXISTENT; //Unintialized - undefined user authmode = -1; //Get the data first //$$$ Centalize this - without locking up a connection DataTools dt = new DataTools(); dt.Provider = provider; dt.ConnectionString = connectionString; dt.OpenConnection(); string[] parameter = { "@username", username }; //!!! What is wrong with parameterized query? //dt.GetResultSet(getUserRecordQuery, parameter); string query = string.Format(getHashQueryTok, username); dt.GetResultSet(query); Dictionary <string, string> results = null; if (dt.rowcount < 1) { return(retval); } //assume unique if (dt.rowcount == 1) { results = dt.GetRowStrings(); } else { //TODO handle this situation - check email, return(USER_NOT_UNIQUE); } //inactive? if (!results["active"].Equals("Y", StringComparison.OrdinalIgnoreCase)) { retval = USER_INACTIVE; } //Active Directory returns.... authmode = results["authmode"].IsNullOrEmpty() ? -1 : Convert.ToInt32(results["authmode"]); if (authmode == -1 || string.IsNullOrEmpty(results["hash"])) { return(USER_NO_DATA); } //Given we have data, verify secret //get the hash and salt string salt = results[SaltCol]; byte[] saltAsBytes = Convert.FromBase64String(salt); string storedHash = results[HashCol]; byte[] storedHashBytes = Convert.FromBase64String(storedHash); //hash the salt and the password passed in byte[] PWtoBeHashed = Encoding.ASCII.GetBytes(password); var hashedPW = HashPasswordWithSalt(PWtoBeHashed, saltAsBytes); //compare the hash in the db from the computed value bool match = hashedPW.SequenceEqual(storedHashBytes); // return appropriate information - including authmode // if (match) { return(USER_AUTHENTICATED); //authenticated } else { return(USER_PW_FAIL); //no match in local db } return(retval); }