//******************************************************************************************************
// SecureForm.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:
// ----------------------------------------------------------------------------------------------------
// 05/26/2010 - Pinal C. Patel
// Generated original version of source code.
// 06/02/2010 - Pinal C. Patel
// Added authentication check in Form.Load event.
// 06/09/2010 - Pinal C. Patel
// Added design-time check in Form.Load event to skip authentication when in design mode.
// 08/11/2010 - Pinal C. Patel
// Made key methods virtual for extensibility.
// 12/20/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Security;
using System.Security.Principal;
using System.Threading;
using System.Windows.Forms;
using GSF.Security;
namespace GSF.Windows.Forms
{
///
/// Represents a windows form secured using role-based security.
///
///
/// Required config file entries:
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
/// ]]>
///
///
///
public partial class SecureForm : Form
{
#region [ Constructors ]
///
/// Initializes a new instance of the class.
///
public SecureForm()
{
// Initialize form components.
InitializeComponent();
}
#endregion
#region [ Properties ]
///
/// Gets current security principal for secure form.
///
public SecurityPrincipal SecurityPrincipal
{
get;
private set;
}
///
/// Gets or sets exception handler for secure form.
///
public Action ExceptionHandler
{
get;
set;
}
#endregion
#region [ Methods ]
///
/// Gets the name of resource being accessed.
///
/// Name of the resource being accessed.
protected virtual string GetResourceName()
{
return Name;
}
private void SecureForm_Load(object sender, EventArgs e)
{
try
{
// Don't proceed if the form is opened in design mode
if (DesignMode)
return;
// Check if the resource is excluded from being secured
string resource = GetResourceName();
if (!SecurityProviderUtility.IsResourceSecurable(resource))
return;
// Set up security provider for passthrough authentication
ISecurityProvider securityProvider = SecurityProviderCache.CreateProvider(WindowsIdentity.GetCurrent().Name);
securityProvider.PassthroughPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
securityProvider.Authenticate();
// Setup the security principal for role-based security
SecurityIdentity securityIdentity = new SecurityIdentity(securityProvider);
SecurityPrincipal = new SecurityPrincipal(securityIdentity);
// Verify that the current thread principal has been authenticated
if (!SecurityPrincipal.Identity.IsAuthenticated)
throw new SecurityException($"Authentication failed for user '{SecurityPrincipal.Identity.Name}'");
// Perform a top-level permission check on the resource being accessed
if (!SecurityProviderUtility.IsResourceAccessible(resource, SecurityPrincipal))
throw new SecurityException($"Access to '{resource}' is denied");
// Set up the current thread principal
// NOTE: Provided for backwards compatibility;
// recommended to use the SecurityPrincipal instead
Thread.CurrentPrincipal = SecurityPrincipal;
}
catch (Exception ex)
{
if (ExceptionHandler is null)
throw;
ExceptionHandler(ex);
}
}
#endregion
}
}