📄 msvpaswd.c
字号:
}
if (DCNameString.Buffer == NULL) {
// BUGBUG: Should really pass both names to internal version of DsGetDcName
if ( ClientDnsDomain.Length != 0 ) {
ClientDsGetDcDomain = &ClientDnsDomain;
} else {
ClientDsGetDcDomain = &ClientNetbiosDomain;
}
//
// Build a zero terminated domain name.
//
DomainName = RtlAllocateHeap(
MspHeap,
0,
ClientDsGetDcDomain->Length + sizeof(WCHAR));
if ( DomainName == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
RtlCopyMemory( DomainName,
ClientDsGetDcDomain->Buffer,
ClientDsGetDcDomain->Length );
DomainName[ClientDsGetDcDomain->Length / sizeof(WCHAR)] = 0;
NetStatus = DsGetDcNameW(
NULL,
DomainName,
NULL, // no domain guid
NULL, // no site name
DS_WRITABLE_REQUIRED,
&DCInfo );
if ( NetStatus != NERR_Success ) {
SspPrint(( SSP_CRITICAL, "MspLm20ChangePassword: DsGetDcNameW returned 0x%lx.\n",
NetStatus));
Status = NetpApiStatusToNtStatus( NetStatus );
if( Status == STATUS_INTERNAL_ERROR )
Status = STATUS_NO_SUCH_DOMAIN;
} else {
RtlInitUnicodeString( &DCNameString, DCInfo->DomainControllerName );
}
AttemptRediscovery = TRUE;
}
if (NT_SUCCESS(Status)) {
Status = MspChangePassword(
&DCNameString,
&ClientName,
&ChangePasswordRequest->OldPassword,
&ChangePasswordRequest->NewPassword,
ClientRequest,
ChangePasswordRequest->Impersonating,
&DomainPasswordInfo,
NULL,
&Authoritative );
//
// If we succeeded or got back an authoritative answer
if ( NT_SUCCESS(Status) || Authoritative) {
goto PasswordChangeSuccessfull;
}
}
}
//
// Free the DC info so we can call DsGetDcName again.
//
if ( DCInfo != NULL ) {
NetApiBufferFree(DCInfo);
DCInfo = NULL;
}
//
// attempt re-discovery.
//
if( AttemptRediscovery ) {
NetStatus = DsGetDcNameW(
NULL,
DomainName,
NULL, // no domain guid
NULL, // no site name
DS_FORCE_REDISCOVERY | DS_WRITABLE_REQUIRED,
&DCInfo );
if ( NetStatus != NERR_Success ) {
SspPrint(( SSP_CRITICAL, "MspLm20ChangePassword: DsGetDcNameW (re-discover) returned 0x%lx.\n",
NetStatus));
DCInfo = NULL;
Status = NetpApiStatusToNtStatus( NetStatus );
if( Status == STATUS_INTERNAL_ERROR )
Status = STATUS_NO_SUCH_DOMAIN;
} else {
RtlInitUnicodeString( &DCNameString, DCInfo->DomainControllerName );
Status = MspChangePassword(
&DCNameString,
&ClientName,
&ChangePasswordRequest->OldPassword,
&ChangePasswordRequest->NewPassword,
ClientRequest,
ChangePasswordRequest->Impersonating,
&DomainPasswordInfo,
NULL,
&Authoritative );
//
// If we succeeded or got back an authoritative answer
if ( NT_SUCCESS(Status) || Authoritative) {
goto PasswordChangeSuccessfull;
}
//
// Free the DC info so we can call DsGetDcName again.
//
if ( DCInfo != NULL ) {
NetApiBufferFree(DCInfo);
DCInfo = NULL;
}
}
}
if (Status != STATUS_BACKUP_CONTROLLER) {
//
// Change the password assuming the DomainName is really a server name
//
// The domain name is overloaded to be either a domain name or a server
// name. The server name is useful when changing the password on a LM2.x
// standalone server, which is a "member" of a domain but uses a private
// account database.
//
Status = MspChangePassword(
&ClientNetbiosDomain,
&ClientName,
&ChangePasswordRequest->OldPassword,
&ChangePasswordRequest->NewPassword,
ClientRequest,
ChangePasswordRequest->Impersonating,
&DomainPasswordInfo,
&PrimaryDomainInfo,
&Authoritative );
//
// If DomainName is actually a server name,
// just return the status to the caller.
//
if ( Authoritative &&
( Status != STATUS_BAD_NETWORK_PATH ||
( ClientNetbiosDomain.Length >= 3 * sizeof(WCHAR) &&
ClientNetbiosDomain.Buffer[0] == L'\\' &&
ClientNetbiosDomain.Buffer[1] == L'\\' ) ) ) {
//
// If \\xxx was specified, but xxx doesn't exist,
// return the status code that the DomainName field is bad.
//
if ( Status == STATUS_BAD_NETWORK_PATH ) {
Status = STATUS_NO_SUCH_DOMAIN;
}
}
//
// If we didn't get an error that this was a backup controller,
// we are out of here.
//
if (Status != STATUS_BACKUP_CONTROLLER) {
goto PasswordChangeSuccessfull;
}
}
//
// If the specified machine was a BDC in a domain,
// Pretend the caller passed us the domain name in the first place.
//
if ( Status == STATUS_BACKUP_CONTROLLER && PrimaryDomainInfo != NULL ) {
ClientNetbiosDomain = PrimaryDomainInfo->Name;
Status = STATUS_BAD_NETWORK_PATH;
} else {
goto PasswordChangeSuccessfull;
}
//
// Build a zero terminated domain name.
//
// BUGBUG: Should really pass both names to internal version of DsGetDcName
if ( ClientDnsDomain.Length != 0 ) {
ClientDsGetDcDomain = &ClientDnsDomain;
} else {
ClientDsGetDcDomain = &ClientNetbiosDomain;
}
if( DomainName )
RtlFreeHeap( MspHeap, 0, DomainName );
DomainName = RtlAllocateHeap(
MspHeap,
0,
ClientDsGetDcDomain->Length + sizeof(WCHAR));
if ( DomainName == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
RtlCopyMemory( DomainName,
ClientDsGetDcDomain->Buffer,
ClientDsGetDcDomain->Length );
DomainName[ClientDsGetDcDomain->Length / sizeof(WCHAR)] = 0;
AttemptRediscovery = FALSE;
retry:
{
DWORD dwGetDcFlags = 0;
if( AttemptRediscovery )
dwGetDcFlags |= DS_FORCE_REDISCOVERY;
//
// Determine the PDC of the named domain so we can change the password there.
//
NetStatus = DsGetDcNameW(
NULL,
DomainName,
NULL, // no domain guid
NULL, // no site name
dwGetDcFlags | DS_WRITABLE_REQUIRED,
&DCInfo );
if ( NetStatus != NERR_Success ) {
SspPrint(( SSP_CRITICAL, "MspLm20ChangePassword: DsGetDcNameW returned 0x%lx.\n",
NetStatus));
Status = NetpApiStatusToNtStatus( NetStatus );
if( Status == STATUS_INTERNAL_ERROR )
Status = STATUS_NO_SUCH_DOMAIN;
goto Cleanup;
}
RtlInitUnicodeString( &DCNameString, DCInfo->DomainControllerName );
Status = MspChangePassword(
&DCNameString,
&ClientName,
&ChangePasswordRequest->OldPassword,
&ChangePasswordRequest->NewPassword,
ClientRequest,
ChangePasswordRequest->Impersonating,
&DomainPasswordInfo,
NULL,
&Authoritative );
if( !NT_SUCCESS(Status) && !Authoritative && !AttemptRediscovery ) {
AttemptRediscovery = TRUE;
goto retry;
}
}
PasswordChangeSuccessfull:
//
// Allocate and initialize the response buffer.
//
SavedStatus = Status;
*ReturnBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_RESPONSE);
Status = NlpAllocateClientBuffer( &ClientBufferDesc,
sizeof(MSV1_0_CHANGEPASSWORD_RESPONSE),
*ReturnBufferSize );
if ( !NT_SUCCESS( Status ) ) {
KdPrint(("MSV1_0: MspLm20ChangePassword: cannot alloc client buffer\n"));
*ReturnBufferSize = 0;
goto Cleanup;
}
ChangePasswordResponse = (PMSV1_0_CHANGEPASSWORD_RESPONSE) ClientBufferDesc.MsvBuffer;
ChangePasswordResponse->MessageType = MsV1_0ChangePassword;
//
// Copy the DomainPassword restrictions out to the caller depending on
// whether it was passed to us.
//
// Mark the buffer as valid or invalid to let the caller know.
//
// if STATUS_PASSWORD_RESTRICTION is returned. This status can be
// returned by either SAM or a down-level change. Only SAM will return
// valid data so we have a flag in the buffer that says whether the data
// is valid or not.
//
if ( DomainPasswordInfo == NULL ) {
ChangePasswordResponse->PasswordInfoValid = FALSE;
} else {
ChangePasswordResponse->DomainPasswordInfo = *DomainPasswordInfo;
ChangePasswordResponse->PasswordInfoValid = TRUE;
}
//
// Flush the buffer to the client's address space.
//
Status = NlpFlushClientBuffer( &ClientBufferDesc,
ProtocolReturnBuffer );
//
// Update cached credentials with the new password.
//
// This is done by calling NlpChangePassword,
// which takes encrypted passwords, so encrypt 'em.
//
if ( NT_SUCCESS(SavedStatus) ) {
//
// Failure of NlpChangePassword is OK, that means that the
// account we've been working with isn't the one we're
// caching credentials for.
//
(VOID) NlpChangePassword(
&ClientNetbiosDomain,
&ClientName,
&ChangePasswordRequest->NewPassword
);
}
Status = SavedStatus;
Cleanup:
//
// Free Locally allocated resources
//
if (DomainName != NULL) {
RtlFreeHeap(MspHeap, 0, DomainName);
}
if ( DCInfo != NULL ) {
NetApiBufferFree(DCInfo);
}
if ( WkstaInfo100 != NULL ) {
NetApiBufferFree(WkstaInfo100);
}
if ( DomainPasswordInfo != NULL ) {
SamFreeMemory(DomainPasswordInfo);
}
if ( PrimaryDomainInfo != NULL ) {
(VOID) LsaFreeMemory( PrimaryDomainInfo );
}
if ( DsHandle != NULL) {
DsUnBindW(
&DsHandle
);
}
//
// Free Policy Server Role Information if used.
//
if (PolicyLsaServerRoleInfo != NULL) {
I_LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyLsaServerRoleInformation,
(PLSAPR_POLICY_INFORMATION) PolicyLsaServerRoleInfo
);
}
//
// Free the return buffer.
//
NlpFreeClientBuffer( &ClientBufferDesc );
//
// Don't let the password stay in the page file.
//
if ( PasswordBufferValidated ) {
RtlEraseUnicodeString( &ChangePasswordRequest->OldPassword );
RtlEraseUnicodeString( &ChangePasswordRequest->NewPassword );
}
//
// Flush the log to disk
//
MsvPaswdSetAndClearLog();
//
// Return status to the caller.
//
*ProtocolStatus = Status;
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -