|
|
/*++
Copyright (c) 1987-1993 Microsoft Corporation
Module Name:
utility.cxx
Abstract:
Private NtLmSsp service utility routines.
Author:
Cliff Van Dyke (cliffv) 9-Jun-1993
Environment:
User mode only. Contains NT-specific code. Requires ANSI C extensions: slash-slash comments, long external names.
Revision History: ChandanS 06-Aug-1996 Stolen from net\svcdlls\ntlmssp\common\utility.c
--*/
//
// Common include files.
//
#include <global.h>
//
// Include files specific to this .c file
//
#include <netlib.h> // NetpMemoryFree()
#include <secobj.h> // ACE_DATA ...
#include <stdio.h> // vsprintf().
#include <tstr.h> // TCHAR_ equates.
#define SSP_TOKEN_ACCESS (READ_CONTROL |\
WRITE_DAC |\ TOKEN_DUPLICATE |\ TOKEN_IMPERSONATE |\ TOKEN_QUERY |\ TOKEN_QUERY_SOURCE |\ TOKEN_ADJUST_PRIVILEGES |\ TOKEN_ADJUST_GROUPS |\ TOKEN_ADJUST_DEFAULT)
#if DBG
SECURITY_STATUS SspNtStatusToSecStatus( IN NTSTATUS NtStatus, IN SECURITY_STATUS DefaultStatus ) /*++
Routine Description:
Convert an NtStatus code to the corresponding Security status code. For particular errors that are required to be returned as is (for setup code) don't map the errors.
Arguments:
NtStatus - NT status to convert
Return Value:
Returns security status code.
--*/ { //
// this routine is left here for DBG builds to enable the developer
// to ASSERT on status codes, etc.
//
return(NtStatus); }
#endif
BOOLEAN SspTimeHasElapsed( IN LARGE_INTEGER StartTime, IN DWORD Timeout ) /*++
Routine Description:
Determine if "Timeout" milliseconds have elapsed since StartTime.
Arguments:
StartTime - Specifies an absolute time when the event started (100ns units).
Timeout - Specifies a relative time in milliseconds. 0xFFFFFFFF indicates that the time will never expire.
Return Value:
TRUE -- iff Timeout milliseconds have elapsed since StartTime.
--*/ { LARGE_INTEGER TimeNow; LARGE_INTEGER ElapsedTime; LARGE_INTEGER Period;
//
// If the period to too large to handle (i.e., 0xffffffff is forever),
// just indicate that the timer has not expired.
//
// (0x7fffffff is a little over 24 days).
//
if ( Timeout> 0x7fffffff ) { return FALSE; }
//
// Compute the elapsed time
//
NtQuerySystemTime( &TimeNow ); ElapsedTime.QuadPart = TimeNow.QuadPart - StartTime.QuadPart;
//
// Convert Timeout from milliseconds into 100ns units.
//
Period.QuadPart = Int32x32To64( (LONG)Timeout, 10000 );
//
// If the elapsed time is negative (totally bogus),
// or greater than the maximum allowed,
// indicate the period has elapsed.
//
if ( ElapsedTime.QuadPart < 0 || ElapsedTime.QuadPart > Period.QuadPart ) { return TRUE; }
return FALSE; }
SECURITY_STATUS SspDuplicateToken( IN HANDLE OriginalToken, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, OUT PHANDLE DuplicatedToken ) /*++
Routine Description:
Duplicates a token
Arguments:
OriginalToken - Token to duplicate DuplicatedToken - Receives handle to duplicated token
Return Value:
Any error from NtDuplicateToken
--*/ { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; SECURITY_QUALITY_OF_SERVICE QualityOfService;
InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); QualityOfService.EffectiveOnly = FALSE; QualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING; QualityOfService.ImpersonationLevel = ImpersonationLevel; ObjectAttributes.SecurityQualityOfService = &QualityOfService;
Status = NtDuplicateToken( OriginalToken, SSP_TOKEN_ACCESS, &ObjectAttributes, FALSE, TokenImpersonation, DuplicatedToken );
return(SspNtStatusToSecStatus(Status, SEC_E_NO_IMPERSONATION)); }
LPWSTR SspAllocWStrFromWStr( IN LPWSTR Unicode )
/*++
Routine Description:
Allocate and copy unicode string (wide character strdup)
Arguments:
Unicode - pointer to wide character string to make copy of
Return Value:
NULL - There was some error in the conversion.
Otherwise, it returns a pointer to the zero terminated UNICODE string in an allocated buffer. The buffer must be freed using NtLmFree.
--*/
{ DWORD Size; LPWSTR ptr;
Size = WCSSIZE(Unicode); ptr = (LPWSTR)NtLmAllocate(Size); if ( ptr != NULL) { RtlCopyMemory(ptr, Unicode, Size); } return ptr; }
VOID SspHidePassword( IN OUT PUNICODE_STRING Password ) /*++
Routine Description:
Run-encodes the password so that it is not very visually distinguishable. This is so that if it makes it to a paging file, it wont be obvious.
WARNING - This routine will use the upper portion of the password's length field to store the seed used in encoding password. Be careful you don't pass such a string to a routine that looks at the length (like and RPC routine).
Arguments:
Seed - The seed to use to hide the password.
PasswordSource - Contains password to hide.
Return Value:
--*/ { SspPrint((SSP_API_MORE, "Entering SspHidePassword\n"));
if( (Password->Length != 0) && (Password->MaximumLength != 0) ) { LsaFunctions->LsaProtectMemory( Password->Buffer, (ULONG)Password->MaximumLength ); }
SspPrint((SSP_API_MORE, "Leaving SspHidePassword\n")); }
VOID SspRevealPassword( IN OUT PUNICODE_STRING HiddenPassword ) /*++
Routine Description
Reveals a previously hidden password so that it is plain text once again.
Arguments:
HiddenPassword - Contains the password to reveal
Return Value
--*/ { SspPrint((SSP_API_MORE, "Entering SspRevealPassword\n"));
if( (HiddenPassword->Length != 0) && (HiddenPassword->MaximumLength != 0) ) { LsaFunctions->LsaUnprotectMemory( HiddenPassword->Buffer, (ULONG)HiddenPassword->MaximumLength ); }
SspPrint((SSP_API_MORE, "Leaving SspRevealPassword\n")); }
BOOLEAN SspGetTokenBuffer( IN PSecBufferDesc TokenDescriptor OPTIONAL, IN ULONG BufferIndex, OUT PSecBuffer * Token, IN BOOLEAN ReadonlyOK )
/*++
Routine Description:
This routine parses a Token Descriptor and pulls out the useful information.
Arguments:
TokenDescriptor - Descriptor of the buffer containing (or to contain) the token. If not specified, TokenBuffer and TokenSize will be returned as NULL.
TokenBuffer - Returns a pointer to the buffer for the token.
TokenSize - Returns a pointer to the location of the size of the buffer.
ReadonlyOK - TRUE if the token buffer may be readonly.
Return Value:
TRUE - If token buffer was properly found.
--*/
{ ULONG i, Index = 0;
//
// If there is no TokenDescriptor passed in,
// just pass out NULL to our caller.
//
ASSERT(*Token != NULL); if ( !ARGUMENT_PRESENT( TokenDescriptor) ) { return TRUE; }
if (TokenDescriptor->ulVersion != SECBUFFER_VERSION) { return FALSE; }
//
// Loop through each described buffer.
//
for ( i=0; i<TokenDescriptor->cBuffers ; i++ ) { PSecBuffer Buffer = &TokenDescriptor->pBuffers[i]; if ( (Buffer->BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN ) {
//
// If the buffer is readonly and readonly isn't OK,
// reject the buffer.
//
if (!ReadonlyOK && (Buffer->BufferType & SECBUFFER_READONLY)) { return FALSE; }
//
// It is possible that there are > 1 buffers of type SECBUFFER_TOKEN
// eg, the rdr
//
if (Index != BufferIndex) { Index++; continue; }
//
// Return the requested information
//
if (!NT_SUCCESS(LsaFunctions->MapBuffer(Buffer, Buffer))) { return FALSE; } *Token = Buffer; return TRUE; }
}
//
// If we didn't have a buffer, fine.
//
SspPrint((SSP_API_MORE, "SspGetTokenBuffer: No token passed in\n"));
return TRUE; }
|