Skip to content
This repository was archived by the owner on Jun 14, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 65 additions & 29 deletions DscResources/MSFT_UserResource/MSFT_UserResource.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function Get-TargetResource
<#
.SYNOPSIS
Creates, modifies, or deletes a user.

.PARAMETER UserName
The name of the user to create, modify, or delete.

Expand Down Expand Up @@ -91,7 +91,7 @@ function Get-TargetResource
Specifies whether the user is allowed to change their password or not.
By default this is set to $false

.NOTES
.NOTES
If Ensure is set to 'Present' then the password parameter is required.
#>
function Set-TargetResource
Expand Down Expand Up @@ -296,7 +296,7 @@ function Get-TargetResourceOnFullSKU
<#
.SYNOPSIS
Creates, modifies, or deletes a user when on a full server.

.PARAMETER UserName
The name of the user to create, modify, or delete.

Expand Down Expand Up @@ -330,7 +330,7 @@ function Get-TargetResourceOnFullSKU
Specifies whether the user is allowed to change their password or not.
By default this is set to $false

.NOTES
.NOTES
If Ensure is set to 'Present' then the Password parameter is required.
#>
function Set-TargetResourceOnFullSKU
Expand Down Expand Up @@ -386,7 +386,7 @@ function Set-TargetResourceOnFullSKU
try
{
$user = Find-UserByNameOnFullSku -UserName $UserName

}
catch
{
Expand Down Expand Up @@ -432,7 +432,7 @@ function Set-TargetResourceOnFullSKU
}
elseif (-not $userExists)
{
<#
<#
For a newly created user, set the DisplayName property to an empty string
since by default DisplayName is set to user's name.
#>
Expand Down Expand Up @@ -761,7 +761,7 @@ function Get-TargetResourceOnNanoServer
<#
.SYNOPSIS
Creates, modifies, or deletes a user when on Nano Server.

.PARAMETER UserName
The name of the user to create, modify, or delete.

Expand Down Expand Up @@ -795,7 +795,7 @@ function Get-TargetResourceOnNanoServer
Specifies whether the user is allowed to change their password or not.
By default this is set to $false

.NOTES
.NOTES
If Ensure is set to 'Present' then the Password parameter is required.
#>
function Set-TargetResourceOnNanoServer
Expand Down Expand Up @@ -843,7 +843,7 @@ function Set-TargetResourceOnNanoServer

# Try to find a user by a name.
$userExists = $false

try
{
$user = Find-UserByNameOnNanoServer -UserName $UserName
Expand Down Expand Up @@ -925,12 +925,12 @@ function Set-TargetResourceOnNanoServer
# NOTE: The parameter name and the property name have opposite meaning.
$expected = (-not $PasswordChangeNotAllowed)
$actual = $expected

if ($userExists)
{
$actual = $user.UserMayChangePassword
}

if ($PSBoundParameters.ContainsKey('PasswordChangeNotAllowed') -and ((-not $userExists) -or ($expected -ne $actual)))
{
Set-LocalUser -Name $UserName -UserMayChangePassword $expected
Expand Down Expand Up @@ -1130,7 +1130,7 @@ function Assert-UserNameValid

# Check if the name consists of only periods and/or white spaces
$wrongName = $true

for ($i = 0; $i -lt $UserName.Length; $i++)
{
if (-not [Char]::IsWhiteSpace($UserName, $i) -and $UserName[$i] -ne '.')
Expand Down Expand Up @@ -1160,7 +1160,7 @@ function Assert-UserNameValid
<#
.SYNOPSIS
Tests the local user's credentials on the local machine.

.PARAMETER UserName
The username to validate the credentials of.

Expand Down Expand Up @@ -1265,7 +1265,7 @@ function Test-CredentialsValidOnNanoServer
.SYNOPSIS
Queries a user by the given username. If found the function returns a UserPrincipal object.
Otherwise, the function returns $null.

.PARAMETER UserName
The username to search for.
#>
Expand Down Expand Up @@ -1293,7 +1293,7 @@ function Find-UserByNameOnFullSku
<#
.SYNOPSIS
Adds a user with the given username and returns the new user object

.PARAMETER UserName
The username for the new user
#>
Expand Down Expand Up @@ -1333,7 +1333,7 @@ function Add-UserOnFullSku
<#
.SYNOPSIS
Sets the password for the given user

.PARAMETER User
The user to set the password for

Expand Down Expand Up @@ -1365,7 +1365,7 @@ function Set-UserPasswordOnFullSku
.SYNOPSIS
Validates the password is correct for the given user. Returns $true if the
Password is correct for the given username, false otherwise.

.PARAMETER UserName
The UserName to check

Expand All @@ -1390,17 +1390,53 @@ function Test-UserPasswordOnFullSku
$Password
)

$principalContext = New-Object `
-TypeName 'System.DirectoryServices.AccountManagement.PrincipalContext' `
-ArgumentList @( [System.DirectoryServices.AccountManagement.ContextType]::Machine )
try
$logonUserSignature =
@'
[DllImport("advapi32.dll")]
public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
'@

$closeHandleSignature =
@'
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
'@

$advApi32 = Add-Type -MemberDefinition $logonUserSignature -Name 'AdvApi32' -Namespace 'PsInvoke.NativeMethods' -PassThru
$kernel32 = Add-Type -MemberDefinition $closeHandleSignature -Name 'Kernel32' -Namespace 'PsInvoke.NativeMethods' -PassThru
$null = [Reflection.Assembly]::LoadWithPartialName('System.Security')
<#
LOGON32_PROVIDER_DEFAULT, Use the standard logon provider for the system
Constant = 0, reference WinSDK\WinBase.h
For more details on advapi32.dll LogonUser parameter values
see - https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-logonusera
#>
$logon32ProviderDefault = 0
<#
LOGON32_LOGON_INTERACTIVE, This logon type is intended for users who will
be interactively using the computer, such as a user being logged on by
a terminal server, remote shell, or similar process.
Constant = 2, reference WinSDK\WinBase.h
For more details on advapi32.dll LogonUser parameter values
see - https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-logonusera
#>
$Logon32LogonInteractive = 2

$tokenHandle = [IntPtr]::Zero
$success = $false
$domainName = $null

#Attempt a logon using this credential
$success = $advApi32::LogonUser($UserName, $domainName, $Password.GetNetworkCredential().Password, $Logon32LogonInteractive, $logon32ProviderDefault, [Ref]$tokenHandle)

if (-not $success)
{
$credentailsValid = $principalContext.ValidateCredentials($UserName, $Password.GetNetworkCredential().Password)
return $credentailsValid
return $false
}
finally
else
{
$principalContext.Dispose()
$null = $kernel32::CloseHandle( $tokenHandle )
return $true
}
}

Expand All @@ -1409,7 +1445,7 @@ function Test-UserPasswordOnFullSku
.SYNOPSIS
Queries a user by the given username. If found the function returns a UserPrincipal object.
Otherwise, the function returns $null.

.PARAMETER UserName
The username to search for.
#>
Expand Down Expand Up @@ -1448,7 +1484,7 @@ function Remove-UserOnFullSku
<#
.SYNOPSIS
Saves changes for the given user on a machine.

.PARAMETER User
The user to save the changes of
#>
Expand All @@ -1469,7 +1505,7 @@ function Save-UserOnFullSku
<#
.SYNOPSIS
Expires the password of the given user.

.PARAMETER User
The user to expire the password of.
#>
Expand All @@ -1491,7 +1527,7 @@ function Revoke-UserPassword
.SYNOPSIS
Queries a user by the given username. If found the function returns a LocalUser object.
Otherwise, the function throws an error that the user was not found.

.PARAMETER UserName
The username to search for.
#>
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,8 @@ The following parameters will be the same for each process in the set:
## Versions

### Unreleased
* User
* Fixed Test-TargetResource throws System.InvalidOperationException when defined user lacks login permissions - Fixes [Issue #116](https://github.com/PowerShell/PSDscResources/issues/116)

### 2.10.0.0

Expand Down