2

We have had a lot of success with Credssp on our Powershell remote scripting tasks. It solves the 2nd hop problem nicely and was easy to set up.

In this example we launch a deployment script on a remote server. The administrator is prompted for his password and the entire deployment process runs as him. Access to SQL servers and file shares on production systems are all granted.

# Connect to the remote server where the command will run. This will prompt the user for their password...
$Session = New-PSSession -ComputerName $Server -Authentication Credssp -Credential "$env:USERDOMAIN\$env:USERNAME"

# Build up the complete command string that will be run on the server before turning it into a script block...
$Command = "& `"C:\Program Files (x86)\VisBuildPro8\VisBuildCmd.exe`" DEPLOY_CONTEXT=$DeployTarget /b `"Deploy.bld`""

# Convert the command string into script block so it will be compatible with Invoke-Command...
$ScriptBlock = [System.Management.Automation.ScriptBlock]::Create($Command)

# Launch the command on the remote server...
Invoke-Command -Session $Session -ScriptBlock $ScriptBlock

We would like to move this code to a web application so that the administrator gets a web page to launch the deployment rather than a Powershell console. We are stuck on the 2nd hop problem like so many others that have come before. We can ask the administrator for his password on the web page and create a WindowsIdentity. We set up impersonation using this article from MSDN https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx but it fails on access to SQL server and other resources.

Here some of the code we have so far:

// The WindowsIdentity programming used here was taken from https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx
const int LOGON32_PROVIDER_DEFAULT = 0;

// This parameter causes LogonUser to create a primary token. 
const int LOGON32_LOGON_INTERACTIVE = 2;

SafeTokenHandle safeTokenHandle;

// Call LogonUser to obtain a handle to an access token. 
var returnValue = LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);

if (!returnValue)
{
    throw new DrilQuipException(string.Format("User Login {0}\\{1} failed.", domainName, userName));
}

using (var newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
{
    using (var impersonatedUser = newId.Impersonate())
    {
        // This line is the VisBuildPro object model being used to launch the program...
        this.builder.SyncBuildEx();
    }
}

I really don't fully understand this Windows security code. I just poke at it and hope it eventually works.

Is there an option in there somewhere that would let me use the same Credssp protocol with my .Net programming or is this a deadend?

Thanks

Matthew MacFarland
  • 2,413
  • 3
  • 26
  • 34
  • if I am not mistaken, after `LogonUser` you should try calling `DuplicateToken` or `DuplicateTokenEx` API with `SECURITY_IMPERSONATION_LEVEL` set to `SecurityDelegation`. Use this new, duplicated token to construct the WindowsIdentity and impersonate. Like so - `returnValue = DuplicateToken(safeTokenHandle, (int)SecurityImpersonationLevel.SecurityDelegation, out duplicateTokenHandle);` `using (var newId = new WindowsIdentity(duplicateTokenHandle))` – Vikas Gupta Feb 15 '15 at 18:46
  • Hi Vikas, Thanks for your suggestion. I tried it out but it did not make any difference at all. Back to the drawing board.! – Matthew MacFarland Feb 16 '15 at 02:58

0 Answers0