Como um usuário padrão do Windows pode alterar sua senha na linha de comando?

18

No Windows Server 2008 R2, eu tenho um usuário local padrão (não administrador) (não uma conta do Active Directory, embora o servidor esteja em um domínio) que tenha acesso ao servidor apenas pelo PowerShell Remoting. O usuário não pode fazer login via RDP.

Gostaria que esse usuário pudesse alterar sua senha. O comando 'net user' requer direitos de administrador, mesmo que o usuário esteja tentando alterar sua própria senha.

Como um usuário padrão pode alterar sua senha na linha de comando?

elijahbuck
fonte

Respostas:

18

Aqui está um código do PowerShell para fazer o que você está procurando com contas de domínio:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$ADSystemInfo = New-Object -ComObject ADSystemInfo
$type = $ADSystemInfo.GetType()
$user = [ADSI] "LDAP://$($type.InvokeMember('UserName', 'GetProperty', $null, $ADSystemInfo, $null))"
$user.ChangePassword( $oldPassword, $newPassword)

O provedor ASDI também suporta a sintaxe WinNT://computername/usernamedo ChangePassword()método. O ADSystemInfoobjeto, no entanto, não funcionará para contas locais da máquina, portanto, apenas a atualização do código acima com WinNT://...sintaxe não é viável.

(Alguém quer sugerir uma edição com código para diferenciar entre contas locais e de domínio?)

Em uma abordagem completamente diferente, a NetUserChangePasswordAPI antiga também funcionará com contas locais (e de domínio, desde que você especifique o nome de domínio na sintaxe NetBIOS):

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern bool NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Este código pressupõe que você esteja alterando uma senha na máquina local (".").

Evan Anderson
fonte
11
Você me venceu, mas eu ganho pela conservação dos personagens;) Alguma razão para você saber que as peças extras que você usou são necessárias? Ou apenas para ser mais formal e adequado?
charleswj81
11
Você definitivamente recebe o prêmio de código de golfe. Eu sou apenas formal e adequado ... Na verdade, é principalmente tornar o script um pouco mais utilizável para outras pessoas que podem ser do tipo recortar e colar.
Evan Anderson
11
@ charleswj81 - A resposta de Evan é muito mais completa. É um PS1script independente que pode ser chamado com ou sem parâmetros. É muito mais legível também. Código é tudo sobre seres humanos, entendendo o que alguém escreveu, não o computador. Nenhuma solução será mais rápida que a outra.
Mark Henderson
11
Isso parece promissor, mas devo esclarecer que a conta é local para o sistema. Tentei o seguinte: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS") Mas retornei 'A senha não atende aos requisitos da diretiva de senha ...'. A nova senha atende a esses requisitos.
precisa saber é
11
Na verdade, depois de adicionar o usuário a 'Usuários da área de trabalho remota' e tentar alterar a senha dessa maneira, recebo o mesmo erro. Acredito que a maneira correta de alterar uma conta local é: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS")
elijahbuck
9

Na verdade, isso é bastante simples no PowerShell:

([ADSI]'LDAP://CN=User,CN=Users,DC=domain').ChangePassword('currentpassword','newpassword')
charleswj81
fonte
3

Tentei as duas respostas acima sem sucesso, alterando a senha de um administrador local que não ingressou no domínio. Cavar nos comentários rendeu o que eu precisava.

Para a segunda parte da resposta atualmente aceita, você deseja atualizar a assinatura para usar em longvez do boolvalor de retorno, e isso pode ser solucionado nos documentos dos códigos de erro do sistema . Então você acaba com:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern **long** NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

No entanto, isso não funcionou para mim. Os códigos de erro alternaram entre 86 e 2221, dependendo de como eu configuro os parâmetros. Estava prestes a desistir e cavar mais comentários, e finalmente encontrou sucesso em fazer:

([ADSI]'WinNT://./USERNAME').ChangePassword("OLDPASS‌​", "NEWPASS")

Absolutamente ridículo que a simples mudança de uma senha de administrador local seja tão complicada no Powershell. Se você armazenar proteções de segurança no seu sistema, a atualização da senha deverá ser feita com o fornecimento da senha antiga ou o risco de perder a capacidade de descriptografar adequadamente essas cadeias de caracteres seguras!

gnalck
fonte