Attribute PasswordNeverExpires & UserMayNotChangePassword in New-LocalUser function not working.
These attributes where working until, I restarted the machine. After restarting, I found these functionalities were not working.
I had certain network issues in my computer so, I manually installed the LocalAccount module. Then, I checked the LocalAccount.psm1 file where these attributes where missing. I myself added these attributes but, I am not sure whether its syntactically correct or not.
Initial LocalAccount.psm1 file
function New-LocalUser
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string[]]$Name,
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[string[]]$Computername = "$Env:computername",
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateScript({$_.GetType().Name -eq 'SecureString'})]
[array][system.security.securestring]$Password,
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[string[]]$Description=' ',
)
Begin
{
}
Process
{
$cred=New-Object -TypeName System.management.automation.pscredential -ArgumentList "null",$Password[0]
$Plaintextpassword=$cred.GetNetworkCredential().password
$computer = [ADSI]"WinNT://$($ComputerName[0]),computer"
$user = $computer.Create("User", "$($Name[0])")
$user.setpassword("$PlainTextPassword")
$user.put("Description",$($Description[0]))
$user.SetInfo()
}
End
{
}
}
After modification
function New-LocalUser
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string[]]$Name,
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[string[]]$Computername = "$Env:computername",
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateScript({$_.GetType().Name -eq 'SecureString'})]
[array][system.security.securestring]$Password,
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[string[]]$Description=' ',
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[bool]$PasswordNeverExpires,
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=5)]
[bool]$UserMayNotChangePassword
)
Begin
{
}
Process
{
$cred=New-Object -TypeName System.management.automation.pscredential -ArgumentList "null",$Password[0]
$Plaintextpassword=$cred.GetNetworkCredential().password
$computer = [ADSI]"WinNT://$($ComputerName[0]),computer"
$user = $computer.Create("User", "$($Name[0])")
$user.setpassword("$PlainTextPassword")
$user.put("Description",$($Description[0]))
$user.set("PasswordNeverExpires",$($PasswordNeverExpires))
$user.set("UserMayNotChangePassword",$($UserMayNotChangePassword))
$user.SetInfo()
}
End
{
}
}
Can anyone please check your localaccount.psm1 and suggest me where I went wrong. Thanks in advance.
CodePudding user response:
You need to alter certain bits in the UserFlags
property of the user:
if ($UserMayNotChangePassword) {
# ADS_UF_PASSWD_CANT_CHANGE --> user cannot change password
$user.UserFlags.value = $user.UserFlags.value -bor 0x40
$user.SetInfo()
}
if ($PasswordNeverExpires) {
# ADS_UF_DONT_EXPIRE_PASSWD --> password never expires
$user.UserFlags.value = $user.UserFlags.value -bor 0x10000
$user.SetInfo()
}
alternative for the above
$flags = 0
if ($UserMayNotChangePassword) {
# ADS_UF_PASSWD_CANT_CHANGE --> user cannot change password
$flags = 0x40
}
if ($PasswordNeverExpires) {
# ADS_UF_DONT_EXPIRE_PASSWD --> password never expires
$flags = 0x10000
}
# if one or both properties are set
if ($flags) {
$user.UserFlags.value = $user.UserFlags.value -bor $flags
$user.SetInfo()
}
These are the values for the ADS_USER_FLAG_ENUM
ADS_UF_SCRIPT = 0x1
ADS_UF_ACCOUNTDISABLE = 0x2
ADS_UF_HOMEDIR_REQUIRED = 0x8
ADS_UF_LOCKOUT = 0x10
ADS_UF_PASSWD_NOTREQD = 0x20
ADS_UF_PASSWD_CANT_CHANGE = 0x40
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x80
ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0x100
ADS_UF_NORMAL_ACCOUNT = 0x200
ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0x800
ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000
ADS_UF_SERVER_TRUST_ACCOUNT = 0x2000
ADS_UF_DONT_EXPIRE_PASSWD = 0x10000
ADS_UF_MNS_LOGON_ACCOUNT = 0x20000
ADS_UF_SMARTCARD_REQUIRED = 0x40000
ADS_UF_TRUSTED_FOR_DELEGATION = 0x80000
ADS_UF_NOT_DELEGATED = 0x100000
ADS_UF_USE_DES_KEY_ONLY = 0x200000
ADS_UF_DONT_REQUIRE_PREAUTH = 0x400000
ADS_UF_PASSWORD_EXPIRED = 0x800000
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000
BTW. I would make both parameters [switch]
instead of [bool]
like this:
[switch]$PasswordNeverExpires,
[switch]$UserMayNotChangePassword
so you can either leave them out or add to the New-LocalUser
function call