mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-29 23:30:10 +01:00
7c0bc50b4a
Inc. Signed-off-by: Gabor Apati-Nagy<gabor.apati-nagy@citrix.com>
231 lines
9.2 KiB
C#
231 lines
9.2 KiB
C#
/* Copyright (c) Citrix Systems, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms,
|
|
* with or without modification, are permitted provided
|
|
* that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above
|
|
* copyright notice, this list of conditions and the
|
|
* following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the
|
|
* following disclaimer in the documentation and/or other
|
|
* materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using XenAPI;
|
|
using XenAdmin.Actions;
|
|
using XenAdmin.Network;
|
|
using XenAdmin.Core;
|
|
|
|
|
|
namespace XenAdmin.Dialogs
|
|
{
|
|
public partial class RoleElevationDialog : XenDialogBase
|
|
{
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
public Session elevatedSession = null;
|
|
public string elevatedPassword;
|
|
public string elevatedUsername;
|
|
public string originalUsername;
|
|
public string originalPassword;
|
|
|
|
|
|
private List<Role> authorizedRoles;
|
|
|
|
/// <summary>
|
|
/// Displays a dialog informing the user they need a different role to complete the task, and offers the chance to switch user. Optionally logs
|
|
/// out the elevated session. If successful exposes the elevated session, password and username as fields.
|
|
/// </summary>
|
|
/// <param name="connection">The current server connection with the role information</param>
|
|
/// <param name="session">The session on which we have been denied access</param>
|
|
/// <param name="authorizedRoles">A list of roles that are able to complete the task</param>
|
|
/// <param name="actionTitle">A description of the current action, if null or empty will not be displayed</param>
|
|
public RoleElevationDialog(IXenConnection connection, Session session, List<Role> authorizedRoles, string actionTitle)
|
|
{
|
|
InitializeComponent();
|
|
Image icon = SystemIcons.Exclamation.ToBitmap();
|
|
pictureBox1.Image = icon;
|
|
pictureBox1.Width = icon.Width;
|
|
pictureBox1.Height = icon.Height;
|
|
this.connection = connection;
|
|
UserDetails ud = session.CurrentUserDetails;
|
|
labelCurrentUserValue.Text = ud.UserDisplayName ?? ud.UserName ?? Messages.UNKNOWN_AD_USER;
|
|
labelCurrentRoleValue.Text = Role.FriendlyCSVRoleList(session.Roles);
|
|
authorizedRoles.Sort((r1, r2) => r2.CompareTo(r1));
|
|
labelRequiredRoleValue.Text = Role.FriendlyCSVRoleList(authorizedRoles);
|
|
labelServerValue.Text = Helpers.GetName(connection);
|
|
labelServer.Text = Helpers.IsPool(connection) ? Messages.POOL_COLON : Messages.SERVER_COLON;
|
|
originalUsername = session.Connection.Username;
|
|
originalPassword = session.Connection.Password;
|
|
|
|
if (string.IsNullOrEmpty(actionTitle))
|
|
{
|
|
labelCurrentAction.Visible = false;
|
|
labelCurrentActionValue.Visible = false;
|
|
}
|
|
else
|
|
{
|
|
labelCurrentActionValue.Text = actionTitle;
|
|
}
|
|
|
|
this.authorizedRoles = authorizedRoles;
|
|
}
|
|
|
|
private void buttonAuthorize_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Exception delegateException = null;
|
|
log.Debug("Testing logging in with the new credentials");
|
|
DelegatedAsyncAction loginAction = new DelegatedAsyncAction(connection,
|
|
Messages.AUTHORIZING_USER,
|
|
Messages.CREDENTIALS_CHECKING,
|
|
Messages.CREDENTIALS_CHECK_COMPLETE,
|
|
delegate
|
|
{
|
|
try
|
|
{
|
|
elevatedSession = connection.ElevatedSession(TextBoxUsername.Text.Trim(), TextBoxPassword.Text);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
delegateException = ex;
|
|
}
|
|
});
|
|
|
|
using (var dlg = new ActionProgressDialog(loginAction, ProgressBarStyle.Marquee, false))
|
|
dlg.ShowDialog(this);
|
|
|
|
// The exception would have been handled by the action progress dialog, just return the user to the sudo dialog
|
|
if (loginAction.Exception != null)
|
|
return;
|
|
|
|
if(HandledAnyDelegateException(delegateException))
|
|
return;
|
|
|
|
if (elevatedSession.IsLocalSuperuser || SessionAuthorized(elevatedSession))
|
|
{
|
|
elevatedUsername = TextBoxUsername.Text.Trim();
|
|
elevatedPassword = TextBoxPassword.Text;
|
|
DialogResult = DialogResult.OK;
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
ShowNotAuthorisedDialog();
|
|
return;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.DebugFormat("Exception when attempting to sudo action: {0} ", ex);
|
|
using (var dlg = new ThreeButtonDialog(
|
|
new ThreeButtonDialog.Details(
|
|
SystemIcons.Error,
|
|
String.Format(Messages.USER_AUTHORIZATION_FAILED, TextBoxUsername.Text),
|
|
Messages.XENCENTER)))
|
|
{
|
|
dlg.ShowDialog(Parent);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
// Check whether we have a successful elevated session and whether we have been asked to log it out
|
|
// If non successful (most likely the new subject is not authorized) then log it out anyway.
|
|
if (elevatedSession != null && DialogResult != DialogResult.OK)
|
|
{
|
|
elevatedSession.Connection.Logout(elevatedSession);
|
|
elevatedSession = null;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private bool HandledAnyDelegateException(Exception delegateException)
|
|
{
|
|
if (delegateException != null)
|
|
{
|
|
Failure f = delegateException as Failure;
|
|
if (f != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED)
|
|
{
|
|
ShowNotAuthorisedDialog();
|
|
return true;
|
|
}
|
|
|
|
throw delegateException;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
private void ShowNotAuthorisedDialog()
|
|
{
|
|
using (var dlg = new ThreeButtonDialog(
|
|
new ThreeButtonDialog.Details(
|
|
SystemIcons.Error,
|
|
Messages.USER_NOT_AUTHORIZED,
|
|
Messages.PERMISSION_DENIED)))
|
|
{
|
|
dlg.ShowDialog(this);
|
|
}
|
|
}
|
|
|
|
private bool SessionAuthorized(Session s)
|
|
{
|
|
UserDetails ud = s.CurrentUserDetails;
|
|
foreach (Role r in s.Roles)
|
|
{
|
|
if (authorizedRoles.Contains(r))
|
|
{
|
|
|
|
log.DebugFormat("Subject '{0}' is authorized to complete the action", ud.UserDisplayName ?? ud.UserName ?? ud.UserSid);
|
|
return true;
|
|
}
|
|
}
|
|
log.DebugFormat("Subject '{0}' is not authorized to complete the action", ud.UserDisplayName ?? ud.UserName ?? ud.UserSid);
|
|
return false;
|
|
}
|
|
|
|
private void buttonCancel_Click(object sender, EventArgs e)
|
|
{
|
|
DialogResult = DialogResult.Cancel;
|
|
Close();
|
|
}
|
|
|
|
private void UpdateButtons()
|
|
{
|
|
buttonAuthorize.Enabled = TextBoxUsername.Text.Trim() != "" && TextBoxPassword.Text != "";
|
|
}
|
|
|
|
private void TextBoxUsername_TextChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateButtons();
|
|
}
|
|
|
|
private void TextBoxPassword_TextChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateButtons();
|
|
}
|
|
}
|
|
} |