You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
16 KiB
527 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
password.cxx
|
|
|
|
Abstract:
|
|
|
|
password
|
|
|
|
Author:
|
|
|
|
Larry Zhu (LZhu) December 1, 2001 Created
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "password.hxx"
|
|
|
|
VOID
|
|
Usage(
|
|
IN PCSTR pszApp
|
|
)
|
|
{
|
|
DebugPrintf(SSPI_ERROR, "\n\nUsage: %s [-p<package>] [-s] [-l] -r "
|
|
"-c<client name> -C<client realm> -o<old password> -n<new password>\n"
|
|
"Remarks: package default to NTLM, use -s to set password, -l local only\n"
|
|
" -r not impernating (self)\n\n", pszApp);
|
|
exit(-1);
|
|
}
|
|
|
|
NTSTATUS
|
|
MsvChangePasswordUser(
|
|
IN HANDLE LogonHandle,
|
|
IN ULONG PackageId,
|
|
IN BOOLEAN bCacheOnly,
|
|
IN UNICODE_STRING* pDomainName,
|
|
IN UNICODE_STRING* pUserName,
|
|
IN UNICODE_STRING* pOldPassword,
|
|
IN UNICODE_STRING* pNewPassword,
|
|
IN BOOLEAN bImpersonating
|
|
)
|
|
{
|
|
TNtStatus Status = STATUS_UNSUCCESSFUL;
|
|
NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
|
|
|
|
MSV1_0_CHANGEPASSWORD_RESPONSE* pResponse = NULL ;
|
|
ULONG cbResponseSize;
|
|
MSV1_0_CHANGEPASSWORD_REQUEST* pChangeRequest = NULL;
|
|
ULONG cbChangeRequestSize;
|
|
|
|
DebugPrintf(SSPI_LOG, "MsvChangePasswordUser PackageId %d, DomainName %wZ, "
|
|
"UserName %wZ, OldPass %wZ, NewPass %wZ, Impersonating %s\n",
|
|
PackageId, pDomainName, pUserName, pOldPassword, pNewPassword, bImpersonating ? "true" : "false");
|
|
|
|
cbChangeRequestSize = ROUND_UP_COUNT(sizeof(MSV1_0_CHANGEPASSWORD_REQUEST), sizeof(DWORD))
|
|
+ pUserName->Length
|
|
+ pDomainName->Length
|
|
+ pOldPassword->Length
|
|
+ pNewPassword->Length;
|
|
pChangeRequest = (MSV1_0_CHANGEPASSWORD_REQUEST*) new CHAR[cbChangeRequestSize];
|
|
|
|
Status DBGCHK = pChangeRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
RtlZeroMemory(pChangeRequest, cbChangeRequestSize);
|
|
|
|
pChangeRequest->MessageType = bCacheOnly ? MsV1_0ChangeCachedPassword : MsV1_0ChangePassword;
|
|
|
|
pChangeRequest->AccountName = *pUserName;
|
|
pChangeRequest->AccountName.Buffer = (PWSTR) ROUND_UP_POINTER(sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) + (PBYTE) pChangeRequest, sizeof(DWORD));
|
|
RtlCopyMemory(
|
|
pChangeRequest->AccountName.Buffer,
|
|
pUserName->Buffer,
|
|
pUserName->Length
|
|
);
|
|
|
|
pChangeRequest->DomainName = *pDomainName;
|
|
pChangeRequest->DomainName.Buffer = pChangeRequest->AccountName.Buffer + pChangeRequest->AccountName.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pChangeRequest->DomainName.Buffer,
|
|
pDomainName->Buffer,
|
|
pDomainName->Length
|
|
);
|
|
|
|
pChangeRequest->OldPassword = *pOldPassword;
|
|
pChangeRequest->OldPassword.Buffer = pChangeRequest->DomainName.Buffer + pChangeRequest->DomainName.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pChangeRequest->OldPassword.Buffer,
|
|
pOldPassword->Buffer,
|
|
pOldPassword->Length
|
|
);
|
|
|
|
pChangeRequest->NewPassword = *pNewPassword;
|
|
pChangeRequest->NewPassword.Buffer = pChangeRequest->OldPassword.Buffer + pChangeRequest->OldPassword.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pChangeRequest->NewPassword.Buffer,
|
|
pNewPassword->Buffer,
|
|
pNewPassword->Length
|
|
);
|
|
|
|
//
|
|
// We are running as the caller, so state we are impersonating
|
|
//
|
|
|
|
pChangeRequest->Impersonating = bImpersonating;
|
|
|
|
DebugPrintf(SSPI_LOG, "Msg type %#x\n", pChangeRequest->MessageType);
|
|
Status DBGCHK = LsaCallAuthenticationPackage(
|
|
LogonHandle,
|
|
PackageId,
|
|
pChangeRequest,
|
|
cbChangeRequestSize,
|
|
(VOID**) &pResponse,
|
|
&cbResponseSize,
|
|
&SubStatus
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (pResponse && pResponse->PasswordInfoValid)
|
|
{
|
|
DebugPrintf(SSPI_LOG, "SubStatus %#x, MinPasswordLength %d, PasswordHistoryLength %d\n",
|
|
SubStatus,
|
|
pResponse->DomainPasswordInfo.MinPasswordLength,
|
|
pResponse->DomainPasswordInfo.PasswordHistoryLength);
|
|
DebugPrintSysTimeAsLocalTime(SSPI_LOG, "MaxPasswordAge ", &pResponse->DomainPasswordInfo.MaxPasswordAge);
|
|
DebugPrintSysTimeAsLocalTime(SSPI_LOG, "MinPasswordAge ", &pResponse->DomainPasswordInfo.MinPasswordAge);
|
|
|
|
}
|
|
Status DBGCHK = SubStatus;
|
|
}
|
|
else
|
|
{
|
|
DebugPrintf(SSPI_LOG, "SubStatus %#x\n", SubStatus);
|
|
}
|
|
|
|
if (pResponse)
|
|
{
|
|
LsaFreeReturnBuffer(pResponse);
|
|
}
|
|
|
|
if (pChangeRequest)
|
|
{
|
|
delete [] pChangeRequest;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KerbChangePasswordUser(
|
|
IN HANDLE LogonHandle,
|
|
IN ULONG PackageId,
|
|
IN BOOLEAN bImpersonating,
|
|
IN UNICODE_STRING* pDomainName,
|
|
IN UNICODE_STRING* pUserName,
|
|
IN UNICODE_STRING* pOldPassword,
|
|
IN UNICODE_STRING* pNewPassword
|
|
)
|
|
{
|
|
TNtStatus Status = STATUS_UNSUCCESSFUL;
|
|
NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
|
|
|
|
PVOID pResponse = NULL ;
|
|
ULONG cbResponseSize;
|
|
PKERB_CHANGEPASSWORD_REQUEST pChangeRequest = NULL;
|
|
ULONG cbChangeRequestSize;
|
|
|
|
DebugPrintf(SSPI_LOG, "KerbChangePasswordUser PackageId %d, DomainName %wZ, "
|
|
"UserName %wZ, OldPass %wZ, NewPass %wZ, Impersonating %s\n",
|
|
PackageId, pDomainName, pUserName, pOldPassword, pNewPassword, bImpersonating ? "true" : "false");
|
|
|
|
cbChangeRequestSize = ROUND_UP_COUNT(sizeof(KERB_CHANGEPASSWORD_REQUEST), sizeof(DWORD))
|
|
+ pUserName->Length + pDomainName->Length
|
|
+ pOldPassword->Length + pNewPassword->Length;
|
|
|
|
pChangeRequest = (PKERB_CHANGEPASSWORD_REQUEST) new CHAR[cbChangeRequestSize];
|
|
|
|
Status DBGCHK = pChangeRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
RtlZeroMemory(pChangeRequest, cbChangeRequestSize);
|
|
|
|
pChangeRequest->MessageType = KerbChangePasswordMessage;
|
|
|
|
pChangeRequest->AccountName = *pUserName;
|
|
pChangeRequest->AccountName.Buffer = (PWSTR) ROUND_UP_POINTER(sizeof(KERB_CHANGEPASSWORD_REQUEST) + (PBYTE) pChangeRequest, sizeof(DWORD));
|
|
RtlCopyMemory(
|
|
pChangeRequest->AccountName.Buffer,
|
|
pUserName->Buffer,
|
|
pUserName->Length
|
|
);
|
|
|
|
pChangeRequest->DomainName = *pDomainName;
|
|
pChangeRequest->DomainName.Buffer = pChangeRequest->AccountName.Buffer + pChangeRequest->AccountName.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pChangeRequest->DomainName.Buffer,
|
|
pDomainName->Buffer,
|
|
pDomainName->Length
|
|
);
|
|
|
|
pChangeRequest->OldPassword = *pOldPassword;
|
|
pChangeRequest->OldPassword.Buffer = pChangeRequest->DomainName.Buffer + pChangeRequest->DomainName.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pChangeRequest->OldPassword.Buffer,
|
|
pOldPassword->Buffer,
|
|
pOldPassword->Length
|
|
);
|
|
|
|
pChangeRequest->NewPassword = *pNewPassword;
|
|
pChangeRequest->NewPassword.Buffer = pChangeRequest->OldPassword.Buffer + pChangeRequest->OldPassword.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pChangeRequest->NewPassword.Buffer,
|
|
pNewPassword->Buffer,
|
|
pNewPassword->Length
|
|
);
|
|
|
|
//
|
|
// We are running as the caller, so state we are impersonating
|
|
//
|
|
|
|
pChangeRequest->Impersonating = bImpersonating;
|
|
|
|
Status DBGCHK = LsaCallAuthenticationPackage(
|
|
LogonHandle,
|
|
PackageId,
|
|
pChangeRequest,
|
|
cbChangeRequestSize,
|
|
&pResponse,
|
|
&cbResponseSize,
|
|
&SubStatus
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = SubStatus;
|
|
}
|
|
else
|
|
{
|
|
DebugPrintf(SSPI_LOG, "SubStatus %#x\n", SubStatus);
|
|
}
|
|
|
|
if (pResponse)
|
|
{
|
|
LsaFreeReturnBuffer(pResponse);
|
|
}
|
|
|
|
if (pChangeRequest)
|
|
{
|
|
delete [] pChangeRequest;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KerbSetPasswordUser(
|
|
IN HANDLE LogonHandle,
|
|
IN ULONG PackageId,
|
|
IN UNICODE_STRING* pDomainName,
|
|
IN UNICODE_STRING* pUserName,
|
|
IN UNICODE_STRING* pNewPassword,
|
|
IN OPTIONAL PCredHandle pCredentialsHandle
|
|
)
|
|
{
|
|
TNtStatus Status = STATUS_UNSUCCESSFUL;
|
|
NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
|
|
|
|
PVOID pResponse = NULL ;
|
|
ULONG cbResponseSize = NULL;
|
|
|
|
PKERB_SETPASSWORD_REQUEST pSetRequest = NULL;
|
|
ULONG cbChangeSize;
|
|
|
|
DebugPrintf(SSPI_LOG, "KerbSetPasswordUser PackageId %d, DomainName %wZ, "
|
|
"UserName %wZ, NewPassword %wZ, CredHandle %p\n",
|
|
PackageId, pDomainName, pUserName, pNewPassword, pCredentialsHandle);
|
|
|
|
cbChangeSize = ROUND_UP_COUNT(sizeof(KERB_SETPASSWORD_REQUEST), sizeof(DWORD))
|
|
+ pUserName->Length + pDomainName->Length + pNewPassword->Length;
|
|
|
|
pSetRequest = (PKERB_SETPASSWORD_REQUEST) new CHAR [cbChangeSize];
|
|
|
|
Status DBGCHK = pSetRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
RtlZeroMemory(pSetRequest, cbChangeSize);
|
|
|
|
pSetRequest->MessageType = KerbSetPasswordMessage;
|
|
|
|
pSetRequest->AccountName = *pUserName;
|
|
pSetRequest->AccountName.Buffer = (PWSTR) ROUND_UP_POINTER(sizeof(KERB_SETPASSWORD_REQUEST) + (PBYTE) pSetRequest, sizeof(DWORD));
|
|
|
|
RtlCopyMemory(
|
|
pSetRequest->AccountName.Buffer,
|
|
pUserName->Buffer,
|
|
pUserName->Length
|
|
);
|
|
|
|
pSetRequest->DomainName = *pDomainName;
|
|
pSetRequest->DomainName.Buffer = pSetRequest->AccountName.Buffer + pSetRequest->AccountName.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pSetRequest->DomainName.Buffer,
|
|
pDomainName->Buffer,
|
|
pDomainName->Length
|
|
);
|
|
|
|
pSetRequest->Password = *pNewPassword;
|
|
pSetRequest->Password.Buffer = pSetRequest->DomainName.Buffer + pSetRequest->DomainName.Length / sizeof(WCHAR);
|
|
|
|
RtlCopyMemory(
|
|
pSetRequest->Password.Buffer,
|
|
pNewPassword->Buffer,
|
|
pNewPassword->Length
|
|
);
|
|
|
|
if (pCredentialsHandle)
|
|
{
|
|
pSetRequest->CredentialsHandle = *pCredentialsHandle;
|
|
pSetRequest->Flags |= KERB_SETPASS_USE_CREDHANDLE;
|
|
}
|
|
|
|
Status DBGCHK = LsaCallAuthenticationPackage(
|
|
LogonHandle,
|
|
PackageId,
|
|
pSetRequest,
|
|
cbChangeSize,
|
|
&pResponse,
|
|
&cbResponseSize,
|
|
&SubStatus
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = SubStatus;
|
|
}
|
|
|
|
if (pResponse)
|
|
{
|
|
LsaFreeReturnBuffer(pResponse);
|
|
}
|
|
|
|
if (pSetRequest)
|
|
{
|
|
delete [] pSetRequest;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID __cdecl
|
|
main(
|
|
IN INT argc,
|
|
IN PSTR argv[]
|
|
)
|
|
{
|
|
TNtStatus Status = STATUS_SUCCESS;
|
|
|
|
HANDLE LogonHandle = NULL;
|
|
ULONG PackageId = -1;
|
|
UNICODE_STRING ClientName = {0};
|
|
UNICODE_STRING ClientRealm = {0};
|
|
UNICODE_STRING OldPassword = {0};
|
|
UNICODE_STRING NewPassword = {0};
|
|
|
|
BOOLEAN bIsSetPassword = FALSE;
|
|
BOOLEAN bCacheOnly = FALSE;
|
|
BOOLEAN bImpersonating = TRUE;
|
|
PCSTR pszPackageName = NTLMSP_NAME_A;
|
|
|
|
for (INT i = 1; NT_SUCCESS(Status) && (i < argc); i++)
|
|
{
|
|
if ((*argv[i] == '-') || (*argv[i] == '/'))
|
|
{
|
|
switch (argv[i][1])
|
|
{
|
|
case 'c':
|
|
Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ClientName);
|
|
break;
|
|
|
|
case 'C':
|
|
Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ClientRealm);
|
|
break;
|
|
|
|
case 'p':
|
|
pszPackageName = argv[i] + 2;
|
|
break;
|
|
|
|
case 'o':
|
|
Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &OldPassword);
|
|
break;
|
|
|
|
case 'n':
|
|
Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &NewPassword);
|
|
break;
|
|
|
|
case 'r':
|
|
bImpersonating = FALSE;
|
|
break;
|
|
|
|
case 's':
|
|
bIsSetPassword = TRUE;
|
|
break;
|
|
|
|
case 'l':
|
|
bCacheOnly = TRUE;
|
|
break;
|
|
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
Usage(argv[0]);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Usage(argv[0]);
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = GetLsaHandleAndPackageId(
|
|
pszPackageName,
|
|
&LogonHandle,
|
|
&PackageId
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (0 == _stricmp(NTLMSP_NAME_A, pszPackageName))
|
|
{
|
|
if (bIsSetPassword)
|
|
{
|
|
DebugPrintf(SSPI_ERROR, "SetPassword not supported\n");
|
|
Status DBGCHK = STATUS_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
Status DBGCHK = MsvChangePasswordUser(
|
|
LogonHandle,
|
|
PackageId,
|
|
bCacheOnly,
|
|
&ClientRealm,
|
|
&ClientName,
|
|
&OldPassword,
|
|
&NewPassword,
|
|
bImpersonating
|
|
);
|
|
}
|
|
}
|
|
else if (0 == _stricmp(MICROSOFT_KERBEROS_NAME_A, pszPackageName))
|
|
{
|
|
if (bIsSetPassword)
|
|
{
|
|
Status DBGCHK = KerbSetPasswordUser(
|
|
LogonHandle,
|
|
PackageId,
|
|
&ClientRealm,
|
|
&ClientName,
|
|
&NewPassword,
|
|
NULL // no cred handle
|
|
);
|
|
}
|
|
else
|
|
{
|
|
Status DBGCHK = KerbChangePasswordUser(
|
|
LogonHandle,
|
|
PackageId,
|
|
bImpersonating,
|
|
&ClientRealm,
|
|
&ClientName,
|
|
&OldPassword,
|
|
&NewPassword
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugPrintf(SSPI_ERROR, "%s not supported\n", pszPackageName);
|
|
Status DBGCHK = STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DebugPrintf(SSPI_LOG, "Operation succeeded\n");
|
|
}
|
|
else
|
|
{
|
|
DebugPrintf(SSPI_ERROR, "Operation failed\n");
|
|
}
|
|
|
|
if (LogonHandle)
|
|
{
|
|
LsaDeregisterLogonProcess(LogonHandle);
|
|
}
|
|
|
|
RtlFreeUnicodeString(&ClientName);
|
|
RtlFreeUnicodeString(&ClientRealm);
|
|
RtlFreeUnicodeString(&OldPassword);
|
|
RtlFreeUnicodeString(&NewPassword);
|
|
}
|