STUBS.C

//+----------------------------------------------------------------------- 
//
// Microsoft Windows
//
// Copyright (c) Microsoft Corporation 1992 - 1994
//
// File: stubs.cxx
//
// Contents: user-mode stubs for security API
//
//
//------------------------------------------------------------------------
#include "sampssp.h"


SecurityFunctionTableW SecTableW = {SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
EnumerateSecurityPackagesW,
NULL,
AcquireCredentialsHandleW,
FreeCredentialsHandle,
NULL, // LogonUser
InitializeSecurityContextW,
AcceptSecurityContext,
CompleteAuthToken,
DeleteSecurityContext,
ApplyControlToken,
QueryContextAttributesW,
ImpersonateSecurityContext,
RevertSecurityContext,
MakeSignature,
VerifySignature,
FreeContextBuffer,
QuerySecurityPackageInfoW
};


PSEC_CONTEXT ContextList;
PCREDENTIAL CredentialList;
ULONG NextId;
TimeStamp Forever = {0x7fffffff,0xfffffff};
TimeStamp Never = {0,0};

//+-------------------------------------------------------------------------
//
// Function: LocateContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


PSEC_CONTEXT
LocateContext(ULONG ContextId)
{
PSEC_CONTEXT TestContext;
EnterCriticalSection(&DllCritSect);

TestContext = ContextList;
while (TestContext != NULL)
{
if (TestContext->ContextId == ContextId)
{
break;
}
TestContext = TestContext->Next;
}
LeaveCriticalSection(&DllCritSect);
return(TestContext);

}

//+-------------------------------------------------------------------------
//
// Function: DeleteContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


BOOLEAN
DeleteContext(ULONG ContextId)
{
PSEC_CONTEXT TestContext, LastContext;

EnterCriticalSection(&DllCritSect);
TestContext = ContextList;
LastContext = NULL;

while (TestContext != NULL)
{
if (TestContext->ContextId == ContextId)
{
break;
}
LastContext = TestContext;
TestContext = TestContext->Next;
}
if (TestContext != NULL)
{
if (LastContext != NULL)
{
LastContext->Next = TestContext->Next;
}
else
{
assert(ContextList == TestContext);
ContextList = TestContext->Next;
}
LocalFree(TestContext);
}
LeaveCriticalSection(&DllCritSect);
return( TestContext == NULL ? FALSE : TRUE );
}

//+-------------------------------------------------------------------------
//
// Function: AddContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


VOID
AddContext(PSEC_CONTEXT Context)
{
EnterCriticalSection(&DllCritSect);
Context->Next = ContextList;
ContextList = Context;
LeaveCriticalSection(&DllCritSect);
}


//+-------------------------------------------------------------------------
//
// Function: InitSecurityInterfaceW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------



PCREDENTIAL
LocateCredential(ULONG CredentialId)
{
PCREDENTIAL TestCredential;
EnterCriticalSection(&DllCritSect);

TestCredential = CredentialList;
while (TestCredential != NULL)
{
if (TestCredential->CredentialId == CredentialId)
{
break;
}
TestCredential = TestCredential->Next;
}
LeaveCriticalSection(&DllCritSect);
return(TestCredential);

}

BOOLEAN
DeleteCredential(ULONG CredentialId)
{
PCREDENTIAL TestCredential, LastCredential;

EnterCriticalSection(&DllCritSect);
TestCredential = CredentialList;
LastCredential = NULL;

while (TestCredential != NULL)
{
if (TestCredential->CredentialId == CredentialId)
{
break;
}
LastCredential = TestCredential;
TestCredential = TestCredential->Next;
}
if (TestCredential != NULL)
{
if (LastCredential != NULL)
{
LastCredential->Next = TestCredential->Next;
}
else
{
assert(CredentialList == TestCredential);
CredentialList = TestCredential->Next;
}
LocalFree(TestCredential);
}
LeaveCriticalSection(&DllCritSect);
return( TestCredential == NULL ? FALSE : TRUE );
}

VOID
AddCredential(PCREDENTIAL Credential)
{
EnterCriticalSection(&DllCritSect);
Credential->Next = CredentialList;
CredentialList = Credential;
LeaveCriticalSection(&DllCritSect);
}

ULONG
GetNewId()
{
ULONG NewId;

EnterCriticalSection(&DllCritSect);
NewId = NextId;
NextId ++;
LeaveCriticalSection(&DllCritSect);
return(NewId);

}

PSecBuffer
LocateBuffer(PSecBufferDesc Buffer, ULONG MinimumSize)
{
ULONG Index;
if (Buffer == NULL)
{
return(NULL);
}

for (Index = 0; Index < Buffer->cBuffers ; Index++)
{
if (((Buffer->pBuffers[Index].BufferType) & ~SECBUFFER_ATTRMASK)
== SECBUFFER_TOKEN)
{

//
// Do size checking
//

if (Buffer->pBuffers[Index].cbBuffer < MinimumSize)
{
return(NULL);
}
return(&Buffer->pBuffers[Index]);
}
}
return(NULL);
}



PSecBuffer
LocateSecBuffer(PSecBufferDesc Buffer)
{
return(LocateBuffer(Buffer, sizeof(MESSAGE)));
}


PSecBuffer
LocateSigBuffer(PSecBufferDesc Buffer)
{
return(LocateBuffer(Buffer, sizeof(SIGNATURE)));
}


//+-------------------------------------------------------------------------
//
// Function: InitSecurityInterfaceW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
PSecurityFunctionTableW SEC_ENTRY
InitSecurityInterfaceW(VOID)
{
InitializeCriticalSection( &DllCritSect );
return(&SecTableW);
}


//+-------------------------------------------------------------------------
//
// Function: AcquireCredentialsHandleW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------



SECURITY_STATUS SEC_ENTRY
AcquireCredentialsHandleW(
LPWSTR pszPrincipal, // Name of principal
LPWSTR pszPackageName, // Name of package
unsigned long fCredentialUse, // Flags indicating use
void SEC_FAR * pvLogonId, // Pointer to logon ID
void SEC_FAR * pAuthData, // Package specific data
SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
PCredHandle phCredential, // (out) Cred Handle
PTimeStamp ptsExpiry // (out) Lifetime (optional)
)
{
PCREDENTIAL NewCredential = NULL;

if ((fCredentialUse & (SECPKG_CRED_BOTH)) == 0)
{
return(SEC_E_UNKNOWN_CREDENTIALS);
}
NewCredential = (PCREDENTIAL) LocalAlloc(0,sizeof(CREDENTIAL));
if (NewCredential == NULL)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}
NewCredential->CredentialId = GetNewId();
NewCredential->Use = fCredentialUse;
NewCredential->AuthData = *(ULONG *)pAuthData;
phCredential->dwUpper = NewCredential->CredentialId;
*ptsExpiry = Forever;
AddCredential(NewCredential);
return(SEC_E_OK);

}



//+-------------------------------------------------------------------------
//
// Function: FreeCredentialsHandle
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
FreeCredentialsHandle(
PCredHandle phCredential // Handle to free
)
{
if (DeleteCredential(phCredential->dwUpper))
{
return(SEC_E_OK);
}
else
{
return(SEC_E_UNKNOWN_CREDENTIALS);
}
}


//+-------------------------------------------------------------------------
//
// Function: InitializeSecurityContextW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
InitializeSecurityContextW(
PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
LPWSTR pszTargetName, // Name of target
unsigned long fContextReq, // Context Requirements
unsigned long Reserved1, // Reserved, MBZ
unsigned long TargetDataRep, // Data rep of target
PSecBufferDesc pInput, // Input Buffers
unsigned long Reserved2, // Reserved, MBZ
PCtxtHandle phNewContext, // (out) New Context handle
PSecBufferDesc pOutput, // (inout) Output Buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
PTimeStamp ptsExpiry // (out) Life span (OPT)
)
{
PCREDENTIAL Credential = NULL;
PSEC_CONTEXT Context = NULL;
PMESSAGE Message = NULL;
PSecBuffer OutputBuffer;
PSecBuffer InputBuffer;
MESSAGE SampleMessage;


if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}

OutputBuffer = LocateSecBuffer(pOutput);
if (OutputBuffer == NULL)
{
return(SEC_E_INVALID_TOKEN);
}

if (phContext == NULL)
{

Credential = LocateCredential(phCredential->dwUpper);
if (Credential == NULL)
{
return(SEC_E_UNKNOWN_CREDENTIALS);
}

if ((Credential->Use & SECPKG_CRED_OUTBOUND) == 0)
{
return(SEC_E_UNKNOWN_CREDENTIALS);
}

}

//
// If the context is NULL, create a new one.
//

if (phContext == NULL)
{
Context = (PSEC_CONTEXT) LocalAlloc(0,sizeof(SEC_CONTEXT));
if (Context == NULL)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}
Context->ContextId = GetNewId();
phNewContext->dwUpper = Context->ContextId;
Context->CredentialId = phCredential->dwUpper;
Context->State = FirstInit;
Context->Nonce = 0;
Context->ContextFlags = fContextReq;
*pfContextAttr = fContextReq;
*ptsExpiry = Forever;

//
// Build an output token.
//

Message = (PMESSAGE) OutputBuffer->pvBuffer;
Message->MessageType = Negotiate;
memset(Message->Buffer,'x',MESSAGE_SIZE);
OutputBuffer->cbBuffer = sizeof(MESSAGE);

AddContext(Context);

return(SEC_I_CONTINUE_NEEDED);

} else {
//
// This is the second call. Lookup the old context.
//

Context = LocateContext(phContext->dwUpper);
if (Context == NULL)
{
return(SEC_E_INVALID_HANDLE);
}

if ((Context->State != FirstInit) &&
(Context->State != SecondInit))
{
return(SEC_E_INVALID_HANDLE);
}


//
// Build the new output message
//

if (Context->State == FirstInit)
{

//
// Check that the input message is what we expected.
//

InputBuffer = LocateSecBuffer(pInput);
if (InputBuffer == NULL)
{
return(SEC_E_INVALID_TOKEN);
}
Message = (PMESSAGE) InputBuffer->pvBuffer;

SampleMessage.MessageType = Challenge;
memset(SampleMessage.Buffer, 'y', MESSAGE_SIZE);

if (memcmp(&SampleMessage,Message,MESSAGE_SIZE) != 0)
{
return(SEC_E_INVALID_TOKEN);
}

Message = (PMESSAGE) OutputBuffer->pvBuffer;
Message->MessageType = ChallengeResponse;
memset(Message->Buffer,'z',MESSAGE_SIZE);
}
else
{
Message = (PMESSAGE) OutputBuffer->pvBuffer;
Message->MessageType = ReAuthenticate;
memset(Message->Buffer,'q',MESSAGE_SIZE);
}

OutputBuffer->cbBuffer = sizeof(MESSAGE);
Context->State = SecondInit;
return(SEC_E_OK);
}
}



//+------------------------------------------- ------------------------------
//
// Function: AcceptSecurityContext
//
// Synopsis:Allows a remotely initiated security context between the
// application and a remote peer to be established. To complete
// the establishment of context one or more reply tokens may be
// required from remote peer.
// This function is the server counterpart to the
// InitializeSecurityContext API. The ContextAttributes is a bit
// mask representing various context level functions such as
// delegation, mutual authentication, confidentiality, replay
// detection and sequence detection. This API is used by the
// server side. When a request comes in, the server uses the
// ContextReqFlags parameter to specify what it requires of the
// session. In this fashion, a server can specify that clients
// must be capable of using a confidential or integrity checked
// session, and fail clients that can't meet that demand.
// Alternatively, a server can require nothing, and whatever the
// client can provide or requires is returned in the
// pfContextAttributes parameter. For a package that supports 3
// leg mutual authentication, the calling sequence would be:
// Client provides a token, server calls Accept the first time,
// generating a reply token. The client uses this in a second
// call to InitializeSecurityContext, and generates a final token.
// This token is then used in the final call to Accept to complete
// the session. Another example would be the LAN Manager/NT
// authentication style. The client connects to negotiate a
// protocol. The server calls Accept to set up a context and
// generate a challenge to the client. The client calls
// InitializeSecurityContext and creates a response. The server
// then calls Accept the final time to allow the package to verify
// the response is appropriate for the challenge.
//
// Effects:
//
//
// Arguments:[phCredential] - Handle to the credentials to be used to
// create the context.
//
// [phContext] - Handle to the partially formed context, if
// this is a second call (see above) or NULL if this is the first call.
//
// [pInput] - Pointer to the input token. In the first call
// this token can either be NULL or may contain
// security package specific information.
//
// [fContextReq] - Requirements of the context, package specific. See
// the ASC_REQ_xxx defines in SSPI.H.
//
// [TargetDataRep] - Long indicating the data representation (byte
// ordering, etc) on the target. The constant
// SECURITY_NATIVE_DREP may be supplied by the
// transport indicating that the native format
// is in use.
//
// [phNewContext] - New context handle. If this is a second
// call, this can be same as OldContextHandle.
//
// [pOutput] - Buffer to receive the output token.
//
// [pfContextAttr] - Attributes of the context established. See
// the ASC_RET_xxx defines in SSPI.H
//
// [ptsExpiry] - Expiration time of the context.
//
// Requires:
//
// Returns:STATUS_SUCCESS - Message handled
// SEC_I_CALLBACK_NEEDED - Caller should call again later
// SEC_E_NO_SPM - Security Support Provider is not running
// SEC_E_INVALID_TOKEN - Token improperly formatted
// SEC_E_INVALID_HANDLE - Credential/Context Handle is invalid
// SEC_E_BUFFER_TOO_SMALL- Buffer for output token isn't big enough
// SEC_E_LOGON_DENIED - User is no allowed to logon to this server
// SEC_E_INSUFFICIENT_MEMORY - Not enough memory
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
AcceptSecurityContext(
PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
PSecBufferDesc pInput, // Input buffer
unsigned long fContextReq, // Context Requirements
unsigned long TargetDataRep, // Target Data Rep
PCtxtHandle phNewContext, // (out) New context handle
PSecBufferDesc pOutput, // (inout) Output buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attributes
PTimeStamp ptsExpiry // (out) Life span (OPT)
)
{
PCREDENTIAL Credential = NULL;
PSEC_CONTEXT Context = NULL;
PMESSAGE Message = NULL;
PSecBuffer OutputBuffer;
PSecBuffer InputBuffer;
MESSAGE SampleMessage;


if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}

InputBuffer = LocateSecBuffer(pInput);
if (InputBuffer == NULL)
{
return(SEC_E_INVALID_TOKEN);
}

if (phContext == NULL)
{

Credential = LocateCredential(phCredential->dwUpper);
if (Credential == NULL)
{
return(SEC_E_UNKNOWN_CREDENTIALS);
}

if ((Credential->Use & SECPKG_CRED_INBOUND) == 0)
{
return(SEC_E_UNKNOWN_CREDENTIALS);
}

}

//
// If the context is NULL, create a new one.
//

if (phContext == NULL)
{
//
// Make sure the output buffer exists.
//

OutputBuffer = LocateSecBuffer(pOutput);
if (OutputBuffer == NULL)
{
return(SEC_E_INVALID_TOKEN);
}



//
// Check that the input message is what we expected.
//

Message = (PMESSAGE) InputBuffer->pvBuffer;
SampleMessage.MessageType = Negotiate;
memset(SampleMessage.Buffer, 'x', MESSAGE_SIZE);

if (memcmp(&SampleMessage,Message,MESSAGE_SIZE) != 0)
{
return(SEC_E_INVALID_TOKEN);
}

//
// Build a new context.
//

Context = (PSEC_CONTEXT) LocalAlloc(0,sizeof(SEC_CONTEXT));
if (Context == NULL)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}
Context->ContextId = GetNewId();
phNewContext->dwUpper = Context->ContextId;
Context->CredentialId = phCredential->dwUpper;
Context->State = FirstAccept;
Context->Nonce = 0;
Context->ContextFlags = fContextReq;
*pfContextAttr = fContextReq;
*ptsExpiry = Forever;

//
// Build an output token.
//

Message = (PMESSAGE) OutputBuffer->pvBuffer;
Message->MessageType = Challenge;
memset(Message->Buffer,'y',MESSAGE_SIZE);
OutputBuffer->cbBuffer = sizeof(MESSAGE);

AddContext(Context);

return(SEC_I_CONTINUE_NEEDED);

} else {
//
// This is the second call. Lookup the old context.
//

Context = LocateContext(phContext->dwUpper);
if (Context == NULL)
{
return(SEC_E_INVALID_HANDLE);
}
if ((Context->State != FirstAccept) &&
(Context->State != SecondAccept))
{
return(SEC_E_INVALID_HANDLE);
}

Message = (PMESSAGE) InputBuffer->pvBuffer;

//
// Check that the input message is what we expected.
//

if (Context->State == FirstAccept)
{
SampleMessage.MessageType = ChallengeResponse;
memset(SampleMessage.Buffer, 'z', MESSAGE_SIZE);
}
else
{
SampleMessage.MessageType = ReAuthenticate;
memset(SampleMessage.Buffer, 'q', MESSAGE_SIZE);
}

if (memcmp(&SampleMessage,Message,MESSAGE_SIZE) != 0)
{
return(SEC_E_INVALID_TOKEN);
}

Context->State = SecondAccept;
return(SEC_E_OK);
}
}






//+-------------------------------------------------------------------------
//
// Function: DeleteSecurityContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
DeleteSecurityContext(
PCtxtHandle phContext // Context to delete
)
{
if (DeleteContext(phContext->dwUpper))
{
return(SEC_E_OK);
}
else
{
return(SEC_E_INVALID_HANDLE);
}
}



//+-------------------------------------------------------------------------
//
// Function: ApplyControlToken
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
ApplyControlToken(
PCtxtHandle phContext, // Context to modify
PSecBufferDesc pInput // Input token to apply
)
{
return(SEC_E_UNSUPPORTED_FUNCTION);

}




//+-------------------------------------------------------------------------
//
// Function: EnumerateSecurityPackagesW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------



SECURITY_STATUS SEC_ENTRY
EnumerateSecurityPackagesW(
unsigned long SEC_FAR * pcPackages, // Receives num. packages
PSecPkgInfoW SEC_FAR * ppPackageInfo // Receives array of info
)
{
SECURITY_STATUS SecStatus;

SecStatus = QuerySecurityPackageInfoW(
PACKAGE_NAME,
ppPackageInfo
);
if (SecStatus == SEC_E_OK)
{
*pcPackages = 1;

}

return(SecStatus);

}



//+-------------------------------------------------------------------------
//
// Function: QuerySecurityPackageInfoW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
QuerySecurityPackageInfoW(
LPWSTR pszPackageName, // Name of package
PSecPkgInfoW SEC_FAR * ppPackageInfo // Receives package info
)
{
PSecPkgInfoW PackageInfo;
ULONG PackageInfoSize;
PUCHAR Where;

if (_wcsicmp(pszPackageName, PACKAGE_NAME))
{
return(SEC_E_SECPKG_NOT_FOUND);
}

PackageInfoSize = sizeof(SecPkgInfoW) +
(wcslen(PACKAGE_NAME) + 1 +
wcslen(PACKAGE_COMMENT) + 1) * sizeof(WCHAR);

PackageInfo = (PSecPkgInfoW) LocalAlloc(0,PackageInfoSize);
if (PackageInfo == NULL)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}
PackageInfo->fCapabilities = PACKAGE_CAPABILITIES;
PackageInfo->wVersion = PACKAGE_VERSION;
PackageInfo->wRPCID = PACKAGE_RPCID;
PackageInfo->cbMaxToken = PACKAGE_MAXTOKEN;

Where = (PUCHAR) (PackageInfo + 1);
PackageInfo->Name = (LPWSTR) Where;
Where += (wcslen(PACKAGE_NAME) + 1) * sizeof(WCHAR);
wcscpy(PackageInfo->Name, PACKAGE_NAME);

PackageInfo->Comment = (LPWSTR) Where;
Where += (wcslen(PACKAGE_COMMENT) + 1) * sizeof(WCHAR);
wcscpy(PackageInfo->Comment, PACKAGE_COMMENT);

assert(Where - (PBYTE) PackageInfo == (LONG) PackageInfoSize);

*ppPackageInfo = PackageInfo;
return(SEC_E_OK);
}






//+-------------------------------------------------------------------------
//
// Function: FreeContextBuffer
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------

SECURITY_STATUS SEC_ENTRY
FreeContextBuffer(
void SEC_FAR * pvContextBuffer
)
{
LocalFree(pvContextBuffer);
return(SEC_E_OK);
}



//+-------------------------------------------------------------------------
//
// Function: CompleteAuthToken
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------



SECURITY_STATUS SEC_ENTRY
CompleteAuthToken(
PCtxtHandle phContext, // Context to complete
PSecBufferDesc pToken // Token to complete
)
{

return(SEC_E_OK);

}



//+-------------------------------------------------------------------------
//
// Function: ImpersonateSecurityContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
ImpersonateSecurityContext(
PCtxtHandle phContext // Context to impersonate
)
{
return(SEC_E_OK);
}



//+-------------------------------------------------------------------------
//
// Function: RevertSecurityContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//

//  Notes: 
//
//
//--------------------------------------------------------------------------


SECURITY_STATUS SEC_ENTRY
RevertSecurityContext(
PCtxtHandle phContext // Context from which to re
)
{
return(SEC_E_OK);
}


//+-------------------------------------------------------------------------
//
// Function: QueryContextAttributes
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------



SECURITY_STATUS SEC_ENTRY
QueryContextAttributesW(
PCtxtHandle phContext, // Context to query
unsigned long ulAttribute, // Attribute to query
void SEC_FAR * pBuffer // Buffer for attributes
)
{
PSEC_CONTEXT Context;
PSecPkgContext_Sizes ContextSizes;
PSecPkgContext_NamesW ContextNames;
PSecPkgContext_Lifespan ContextLifespan;
PSecPkgContext_DceInfo ContextDceInfo;

Context = LocateContext(phContext->dwUpper);

if (Context == NULL)
{
return(SEC_E_INVALID_HANDLE);
}

switch(ulAttribute) {
case SECPKG_ATTR_SIZES:
ContextSizes = (PSecPkgContext_Sizes) pBuffer;
ContextSizes->cbMaxSignature = PACKAGE_SIGNATURE_SIZE;
if ((Context->ContextFlags & ISC_REQ_CONFIDENTIALITY) != 0)
{
ContextSizes->cbSecurityTrailer = PACKAGE_SIGNATURE_SIZE;
ContextSizes->cbBlockSize = 1;
}
else
{
ContextSizes->cbSecurityTrailer = 0;
ContextSizes->cbBlockSize = 0;
}
ContextSizes->cbMaxToken = PACKAGE_MAXTOKEN;
break;
case SECPKG_ATTR_NAMES:
ContextNames = (PSecPkgContext_Names) pBuffer;
ContextNames->sUserName = (LPWSTR) LocalAlloc(0,sizeof(L"dummy user"));
if (ContextNames->sUserName == NULL)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}
wcscpy(ContextNames->sUserName, L"dummy user");
break;
case SECPKG_ATTR_LIFESPAN:
ContextLifespan = (PSecPkgContext_Lifespan) pBuffer;
ContextLifespan->tsStart = Never;
ContextLifespan->tsExpiry = Forever;
break;
case SECPKG_ATTR_DCE_INFO:
ContextDceInfo = (PSecPkgContext_DceInfo) pBuffer;
ContextDceInfo->AuthzSvc = 0;
ContextDceInfo->pPac = (PVOID) LocalAlloc(0,sizeof(L"dummy user"));
if (ContextDceInfo->pPac == NULL)
{
return(SEC_E_INSUFFICIENT_MEMORY);
}
wcscpy((LPWSTR) ContextDceInfo->pPac, L"dummy user");

break;
default:
return(SEC_E_INVALID_TOKEN);
}

return(SEC_E_OK);
}

#if 0

//+-------------------------------------------------------------------------
//
// Function: QueryCredentialsAttributes
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------



SECURITY_STATUS SEC_ENTRY
QueryCredentialsAttributesW(
PCredHandle phCredentials, // Credentials to query
unsigned long ulAttribute, // Attribute to query
void SEC_FAR * pBuffer // Buffer for attributes
)
{
return( pspPackages[phCredentials->dwLower].pftTableW->QueryCredentialsAttributesW(
phCredentials,
ulAttribute,
pBuffer ) );
}

#endif

//+-------------------------------------------------------------------------
//
// Function: MakeSignature
//
// Synopsis:
//
// Effects:
//
// Arguments: [phContext] -- context to use
// [fQOP] -- quality of protection to use
// [pMessage] -- message
// [MessageSeqNo] -- sequence number of message
//
// Requires:
//
// Returns:
//
// Notes:
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY
MakeSignature( PCtxtHandle phContext,
ULONG fQOP,
PSecBufferDesc pMessage,
ULONG MessageSeqNo)
{
PSEC_CONTEXT Context;
PSecBuffer SignatureBuffer;
PSIGNATURE Signature;

Context = LocateContext(phContext->dwUpper);
if (Context == NULL)
{
return(SEC_E_INVALID_HANDLE);
}

SignatureBuffer = LocateSigBuffer(pMessage);
if (SignatureBuffer == NULL)
{
return(SEC_E_INVALID_TOKEN);
}
Signature = (PSIGNATURE) SignatureBuffer->pvBuffer;
Signature->MessageId = Context->Nonce++;
Signature->Tag = PACKAGE_SIGNATURE_TAG;
SignatureBuffer->cbBuffer = sizeof(SIGNATURE);
return(SEC_E_OK);
}



//+-------------------------------------------------------------------------
//
// Function: VerifySignature
//
// Synopsis:
//
// Effects:
//
// Arguments: [phContext] -- Context performing the unseal
// [pMessage] -- Message to verify
// [MessageSeqNo] -- Sequence number of this message
// [pfQOPUsed] -- quality of protection used
//
// Requires:
//
// Returns:
//
// Notes:
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY
VerifySignature(PCtxtHandle phContext,
PSecBufferDesc pMessage,
ULONG MessageSeqNo,
ULONG * pfQOP)
{
PSEC_CONTEXT Context;
PSecBuffer SignatureBuffer;
PSIGNATURE Signature;

Context = LocateContext(phContext->dwUpper);
if (Context == NULL)
{
return(SEC_E_INVALID_HANDLE);
}

SignatureBuffer = LocateSigBuffer(pMessage);
if (SignatureBuffer == NULL)
{
return(SEC_E_INVALID_TOKEN);
}
Signature = (PSIGNATURE) SignatureBuffer->pvBuffer;

if (Signature->Tag != PACKAGE_SIGNATURE_TAG)
{
return(SEC_E_MESSAGE_ALTERED);
}

if (Signature->MessageId != Context->Nonce++)
{
Context->State = Idle;
return(SEC_E_OUT_OF_SEQUENCE);
}

return(SEC_E_OK);
}