windows-nt/Source/XPSP1/NT/base/ntsetup/encrypt/setpwd.c
2020-09-26 16:20:57 +08:00

390 lines
8.9 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
setpwd.c
Abstract:
Sets a user's password based on OWF password hash strings
Calls SamiChangePasswordUser with encoded passwords.
Author:
Ovidiu Temereanca 17-Mar-2000 Initial implementation
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#undef DOMAIN_ALL_ACCESS // defined in both ntsam.h and ntwinapi.h
#include <ntsam.h>
#include <ntsamp.h>
//#include <ntlsa.h>
#include <windef.h>
#include <winbase.h>
//#include <lmcons.h>
#include <align.h>
//#include <lm.h>
//#include <limits.h>
//#include <rpcutil.h>
//#include <secobj.h>
//#include <stddef.h>
//#include <ntdsapi.h>
//#include <dsgetdc.h>
#include <windows.h>
#include "encrypt.h"
NTSTATUS
pGetDomainId (
IN SAM_HANDLE ServerHandle,
OUT PSID* DomainId
)
/*++
Routine Description:
Return a domain ID of the account domain of a server.
Arguments:
ServerHandle - A handle to the SAM server to open the domain on
DomainId - Receives a pointer to the domain ID.
Caller must deallocate buffer using SamFreeMemory.
Return Value:
Error code for the operation.
--*/
{
NTSTATUS status;
SAM_ENUMERATE_HANDLE EnumContext;
PSAM_RID_ENUMERATION EnumBuffer = NULL;
DWORD CountReturned = 0;
PSID LocalDomainId = NULL;
DWORD LocalBuiltinDomainSid[sizeof(SID) / sizeof(DWORD) + SID_MAX_SUB_AUTHORITIES];
SID_IDENTIFIER_AUTHORITY BuiltinAuthority = SECURITY_NT_AUTHORITY;
BOOL b = FALSE;
ULONG i;
//
// Compute the builtin domain sid.
//
RtlInitializeSid((PSID) LocalBuiltinDomainSid, &BuiltinAuthority, 1);
*(RtlSubAuthoritySid((PSID)LocalBuiltinDomainSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
//
// Loop getting the list of domain ids from SAM
//
EnumContext = 0;
do {
//
// Get several domain names.
//
status = SamEnumerateDomainsInSamServer (
ServerHandle,
&EnumContext,
&EnumBuffer,
8192,
&CountReturned
);
if (!NT_SUCCESS (status)) {
goto exit;
}
if (status != STATUS_MORE_ENTRIES) {
b = TRUE;
}
//
// Lookup the domain ids for the domains
//
for(i = 0; i < CountReturned; i++) {
//
// Free the sid from the previous iteration.
//
if (LocalDomainId != NULL) {
SamFreeMemory (LocalDomainId);
LocalDomainId = NULL;
}
//
// Lookup the domain id
//
status = SamLookupDomainInSamServer (
ServerHandle,
&EnumBuffer[i].Name,
&LocalDomainId
);
if (!NT_SUCCESS (status)) {
goto exit;
}
if (RtlEqualSid ((PSID)LocalBuiltinDomainSid, LocalDomainId)) {
continue;
}
*DomainId = LocalDomainId;
LocalDomainId = NULL;
status = NO_ERROR;
goto exit;
}
SamFreeMemory(EnumBuffer);
EnumBuffer = NULL;
} while (!b);
status = ERROR_NO_SUCH_DOMAIN;
exit:
if (EnumBuffer != NULL) {
SamFreeMemory(EnumBuffer);
}
return status;
}
DWORD
pSamOpenLocalUser (
IN PCWSTR UserName,
IN ACCESS_MASK DesiredAccess,
IN PSAM_HANDLE DomainHandle,
OUT PSAM_HANDLE UserHandle
)
/*++
Routine Description:
Returns a user handle given its name, desired access and a domain handle.
Arguments:
UserName - Specifies the user name
DesiredAccess - Specifies the desired access to this user
DoaminHandle - A handle to the domain to open the user on
UserHandle - Receives a user handle.
Caller must free the handle using SamCloseHandle.
Return Value:
Error code for the operation.
--*/
{
DWORD status;
UNICODE_STRING uniUserName;
ULONG rid, *prid;
PSID_NAME_USE nameUse;
//
// Lookup the RID
//
RtlInitUnicodeString (&uniUserName, UserName);
status = SamLookupNamesInDomain (
DomainHandle,
1,
&uniUserName,
&prid,
&nameUse
);
if (status != NO_ERROR) {
return status;
}
//
// Save the RID
//
rid = *prid;
//
// free the memory.
//
SamFreeMemory (prid);
SamFreeMemory (nameUse);
//
// Open the user object.
//
status = SamOpenUser(
DomainHandle,
DesiredAccess,
rid,
UserHandle
);
return status;
}
DWORD
SetLocalUserEncryptedPassword (
IN PCWSTR User,
IN PCWSTR OldPassword,
IN BOOL OldIsEncrypted,
IN PCWSTR NewPassword,
IN BOOL NewIsEncrypted
)
/*++
Routine Description:
Sets a new password for the given user. The password is in encrypted format (see encrypt.h for details).
Arguments:
User - Specifies the user name
OldPassword - Specifies the old password
OldIsEncrypted - Specifies TRUE if old password is provided in encrypted form
or FALSE if it's in clear text
OldIsComplex - Specifies TRUE if old password is complex; used only if OldIsEncrypted is TRUE,
otherwise it's ignored.
NewPassword - Specifies the new password
NewIsEncrypted - Specifies TRUE if new password is provided in encrypted form
or FALSE if it's in clear text
Return Value:
Win32 error code for the operation.
--*/
{
DWORD status;
LM_OWF_PASSWORD lmOwfOldPwd;
NT_OWF_PASSWORD ntOwfOldPwd;
BOOL complexOldPassword;
LM_OWF_PASSWORD lmOwfNewPwd;
NT_OWF_PASSWORD ntOwfNewPwd;
UNICODE_STRING unicodeString;
PSID serverHandle = NULL;
PSID sidAccountsDomain = NULL;
SAM_HANDLE handleAccountsDomain = NULL;
SAM_HANDLE handleUser = NULL;
if (!User) {
return ERROR_INVALID_PARAMETER;
}
if (OldIsEncrypted) {
if (!StringDecodeOwfPasswordW (OldPassword, &lmOwfOldPwd, &ntOwfOldPwd, &complexOldPassword)) {
return ERROR_INVALID_PARAMETER;
}
} else {
if (!EncodeLmOwfPasswordW (OldPassword, &lmOwfOldPwd, &complexOldPassword) ||
!EncodeNtOwfPasswordW (OldPassword, &ntOwfOldPwd)
) {
return ERROR_INVALID_PARAMETER;
}
}
if (NewIsEncrypted) {
if (!StringDecodeOwfPasswordW (NewPassword, &lmOwfNewPwd, &ntOwfNewPwd, NULL)) {
return ERROR_INVALID_PARAMETER;
}
} else {
if (!EncodeLmOwfPasswordW (NewPassword, &lmOwfNewPwd, NULL) ||
!EncodeNtOwfPasswordW (NewPassword, &ntOwfNewPwd)
) {
return ERROR_INVALID_PARAMETER;
}
}
__try {
//
// Use SamConnect to connect to the local domain ("")
// and get a handle to the local SAM server
//
RtlInitUnicodeString (&unicodeString, L"");
status = SamConnect (
&unicodeString,
&serverHandle,
SAM_SERVER_LOOKUP_DOMAIN | SAM_SERVER_ENUMERATE_DOMAINS,
NULL
);
if (status != NO_ERROR) {
__leave;
}
status = pGetDomainId (serverHandle, &sidAccountsDomain);
if (status != NO_ERROR) {
__leave;
}
//
// Open the domain.
//
status = SamOpenDomain (
serverHandle,
DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
sidAccountsDomain,
&handleAccountsDomain
);
if (status != NO_ERROR) {
__leave;
}
status = pSamOpenLocalUser (
User,
USER_CHANGE_PASSWORD,
handleAccountsDomain,
&handleUser
);
if (status != NO_ERROR) {
__leave;
}
status = SamiChangePasswordUser (
handleUser,
!complexOldPassword,
&lmOwfOldPwd,
&lmOwfNewPwd,
TRUE,
&ntOwfOldPwd,
&ntOwfNewPwd
);
}
__finally {
if (handleUser) {
SamCloseHandle (handleUser);
}
if (handleAccountsDomain) {
SamCloseHandle (handleAccountsDomain);
}
if (sidAccountsDomain) {
SamFreeMemory (sidAccountsDomain);
}
if (serverHandle) {
SamCloseHandle (serverHandle);
}
}
return RtlNtStatusToDosError (status);
}