236 lines · 11.8 KB · C#
RawDownload
//******************************************************************************************************//  SecurityProviderUtility.cs - Gbtc////  Copyright © 2012, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  06/25/2010 - Pinal C. Patel//       Generated original version of source code.//  01/05/2011 - Pinal C. Patel//       Added NotificationSmtpServer and NotificationSenderEmail settings to the config file along with//       GeneratePassword() and SendNotification() utility methods.//  01/24/2011 - Pinal C. Patel//       Updated the logic in IsResourceAccessible() to stop looking at other included resources once a //       match is found for the resource being evaluated.//  02/03/2011 - Pinal C. Patel//       Updated the logic in IsResourceSecurable() and IsResourceAccessible() to allow for multiple//       resources to be specified delimited by ',' with the same role requirements in the config file.//  08/02/2011 - Pinal C. Patel//       Modified IsResourceAccessible() to skip security check if no role is specified for a resource//       in the config to allow security to be setup when accessing the resource but not enforced and //       leave it to the resource to enforce it.//  12/20/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Text.RegularExpressions;using System.Threading;using GSF.Collections;using GSF.Configuration;using GSF.Net.Smtp;using GSF.Security.Cryptography;using Random = GSF.Security.Cryptography.Random; namespace GSF.Security{    /// <summary>    /// A helper class containing methods used in the implementation of role-based security.    /// </summary>    public static class SecurityProviderUtility    {        #region [ Members ]         //Constants        private const string SettingsCategory = "SecurityProvider";        private const string DefaultProviderType = "GSF.Security.LdapSecurityProvider, GSF.Security";        private const string DefaultIncludedResources = "*=*";        private const string DefaultExcludedResources = "";        private const string DefaultNotificationSmtpServer = Mail.DefaultSmtpServer;        private const string DefaultNotificationSenderEmail = "sender@company.com";         #endregion         #region [ Static ]         // Static Fields        private static readonly string s_providerType;        private static readonly ICollection<string> s_excludedResources;        private static readonly IDictionary<string, string> s_includedResources;        private static readonly string s_notificationSmtpServer;        private static readonly string s_notificationSenderEmail;         // Static Constructor        static SecurityProviderUtility()        {            // Load settings from config file.            ConfigurationFile config = ConfigurationFile.Current;            CategorizedSettingsElementCollection settings = config.Settings[SettingsCategory];            settings.Add("ProviderType", DefaultProviderType, "The type to be used for enforcing security.");            settings.Add("IncludedResources", DefaultIncludedResources, "Semicolon delimited list of resources to be secured along with role names.");            settings.Add("ExcludedResources", DefaultExcludedResources, "Semicolon delimited list of resources to be excluded from being secured.");            settings.Add("NotificationSmtpServer", DefaultNotificationSmtpServer, "SMTP server to be used for sending out email notification messages.");            settings.Add("NotificationSenderEmail", DefaultNotificationSenderEmail, "Email address of the sender of email notification messages.");             s_providerType = settings["ProviderType"].ValueAsString(DefaultProviderType);            s_includedResources = settings["IncludedResources"].ValueAsString().ParseKeyValuePairs();            s_excludedResources = settings["ExcludedResources"].ValueAsString().Split(';');            s_notificationSmtpServer = settings["NotificationSmtpServer"].ValueAsString();            s_notificationSenderEmail = settings["NotificationSenderEmail"].ValueAsString();        }         // Static Methods         /// <summary>        /// Creates a new <see cref="ISecurityProvider"/> based on the settings in the config file.        /// </summary>        /// <param name="username">Username of the user for whom the <see cref="ISecurityProvider"/> is to be created.</param>        /// <returns>An object that implements <see cref="ISecurityProvider"/>.</returns>        public static ISecurityProvider CreateProvider(string username)        {            // Initialize the username.            if (string.IsNullOrEmpty(username))                username = Thread.CurrentPrincipal.Identity.Name;             // If an application is being launched from an installer it will have the NT AUTHORITY\System Identity which            // will not have available user information - so we pickup username from Environment instead            if (username.StartsWith("NT AUTHORITY\\", StringComparison.OrdinalIgnoreCase))                username = Environment.UserDomainName + "\\" + Environment.UserName;             // Instantiate the provider.            // ReSharper disable once AssignNullToNotNullAttribute            ISecurityProvider provider = Activator.CreateInstance(Type.GetType(s_providerType), username) as ISecurityProvider;             if ((object)provider == null)                throw new InvalidOperationException(string.Format("Failed to acquire security provider from '{0}'. Specified class does not implement ISecurityProvider.", s_providerType));             // Initialize the provider.            provider.Initialize();             // Return initialized provider.            return provider;        }         /// <summary>        /// Determines if the specified <paramref name="resource"/> is to be secured based on settings in the config file.        /// </summary>        /// <param name="resource">Name of the resource to be checked.</param>        /// <returns>true if the <paramref name="resource"/> is to be secured; otherwise false/</returns>        public static bool IsResourceSecurable(string resource)        {            // Check if resource is excluded explicitly.            foreach (string exclusion in s_excludedResources)            {                if (IsRegexMatch(exclusion, resource))                    return false;            }             // Check if resource is included explicitly.            foreach (KeyValuePair<string, string> inclusion in s_includedResources)            {                foreach (string item in inclusion.Key.Split(','))                {                    if (IsRegexMatch(item.Trim(), resource))                        return true;                }            }             return false;        }         /// <summary>        /// Determines if the current user, as defined by the <see cref="Thread.CurrentPrincipal"/>, has permission to access         /// the specified <paramref name="resource"/> based on settings in the config file.        /// </summary>        /// <param name="resource">Name of the resource to be checked.</param>        /// <returns>true if the current user has permission to access the <paramref name="resource"/>; otherwise false.</returns>        public static bool IsResourceAccessible(string resource)        {            // Check if the resource has a role-based access restriction on it.            foreach (KeyValuePair<string, string> inclusion in s_includedResources)            {                foreach (string item in inclusion.Key.Split(','))                {                    if (IsRegexMatch(item.Trim(), resource))                    {                        // Allow security to be implemented inside the resource.                        if (string.IsNullOrEmpty(inclusion.Value))                            return true;                         // Check resource role requirements against user's role subscription.                        return Thread.CurrentPrincipal.IsInRole(inclusion.Value);                    }                }            }             return false;        }         /// <summary>        /// Determines if the specified <paramref name="target"/> matches the specified <paramref name="spec"/>.        /// </summary>        /// <param name="spec">Spec string that can include wildcards ('*'). For example, *.txt</param>        /// <param name="target">Target string to be compared with the <paramref name="spec"/>.</param>        /// <returns>true if the <paramref name="target"/> matches the <paramref name="spec"/>, otherwise false.</returns>        public static bool IsRegexMatch(string spec, string target)        {            spec = spec.Replace(".", "\\.");    // Escape special regex character '.'.            spec = spec.Replace("?", "\\?");    // Escape special regex character '?'.            spec = spec.Replace("*", ".*");     // Convert '*' to its regex equivalent.             // Perform a case-insensitive regex match.            return Regex.IsMatch(target, string.Format("^{0}$", spec), RegexOptions.IgnoreCase);        }         /// <summary>        /// Encrypts the password to a one-way hash using the SHA1 hash algorithm.        /// </summary>        /// <param name="password">Password to be encrypted.</param>        /// <returns>Encrypted password.</returns>        public static string EncryptPassword(string password)        {            return Cipher.GetPasswordHash(password);        }         /// <summary>        /// Generates a random password of the specified <paramref name="length"/> with at least one uppercase letter, one lowercase letter, one special character and one digit.        /// </summary>        /// <param name="length">Length of the password to generate.</param>        /// <returns>Randomly generated password of the specified <paramref name="length"/>.</returns>        /// <exception cref="ArgumentException">A value of less than 8 is specified for the <paramref name="length"/>.</exception>        public static string GeneratePassword(int length)        {            if (length < 8)                throw new ArgumentException("Value must be at least 8", nameof(length));             return PasswordGenerator.Default.GeneratePassword(length);        }         /// <summary>        /// Sends email notification message to the specified <paramref name="recipient"/> using settings specified in the config file.        /// </summary>        /// <param name="recipient">Email address of the notification recipient.</param>        /// <param name="subject">Subject of the notification.</param>        /// <param name="body">Content of the notification.</param>        public static void SendNotification(string recipient, string subject, string body)        {            Mail.Send(s_notificationSenderEmail, recipient, subject, body, false, s_notificationSmtpServer);        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t