RE: InitializeSecurityContext() and Digest in C++


Thanks for the reply. I have tried to use the SSPI Workbench but cannot get
Digest to work correctly.

Steps I do in the Workbench and error I receive when running WinXP Prof. SP2:
1. Select Clieint from initial dialog.
2. "Shoose a particular SSP" radio and select "Digest"
3. Click OK and section 2 is enabled.
4. "Provide explicit credentials" radio and enter in:
Authority = domain
Principle = User Name
Password = User password
5. Click on AquireCredentialsHandle and get an error
"AcquireCredentialsHandle Failed: The function requested is not supported".

Here is a funcion that shows what I am working with.. Keep in mind that it
is not pretty and all I am wanting to do at this point is get the code to run
and generate a Digest value - not actually intract with a web server at this
time. But I will end up using the Digest in a web request.

Sample function call and code.
Function call
ret = TestDigest(
"realm=\"Web Server Name here\", algorithm = \"MD5-sess\", qop=\"auth\",
"Domain Naim here",
"User Name here",
"User Password here");
Sample code
BOOL TestDigest(AUTH_SEQ *pAS,
VOID *pBuffIn,
BUFFER *pbuffOut,
const CHAR *pszPackage,
const CHAR *pszDomain,
const CHAR *pszUser,
const CHAR *pszPassword)
TimeStamp Lifetime;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuff[3];
ULONG ContextAttributes = 0;
ULONG fContextReq;
BUFFER buffData;
BUFFER buff;
BOOL fReply;

DWORD cbBuffIn;
SecPkgInfo * pspkg = NULL;


BufferInit( &buffData );
BufferInit( &buff );

pAuthIdentity = &AuthIdentity;

memset( &AuthIdentity, 0, sizeof( AuthIdentity ) );

AuthIdentity.User = (unsigned char *) pszUser;
AuthIdentity.UserLength = pszUser != NULL ? strlen( pszUser ) : 0;

AuthIdentity.Password = (unsigned char *) pszPassword;
AuthIdentity.PasswordLength = pszPassword != NULL ? strlen( pszPassword ) :

AuthIdentity.Domain = (unsigned char *) pszDomain;
AuthIdentity.DomainLength = pszDomain != NULL ? strlen( pszDomain ) : 0;


printf("Call AcquireCredentialsHandle()\r\n");
ss = pAcquireCredentialsHandleA( NULL, // New principal
(char*)pszPackage, // Package name
NULL, // Logon ID
&AuthIdentity, // Auth Data
NULL, // Get key func
NULL, // Get key arg
&Lifetime );


// Need to determine the max token size for this package

if ( ss == STATUS_SUCCESS )
pAS->_fHaveCredHandle = TRUE;
ss = pQuerySecurityPackageInfoA(
(char *) pszPackage,
&pspkg );

if ( ss != STATUS_SUCCESS )
SetLastError( ss );
return FALSE;

pAS->_cbMaxToken = pspkg->cbMaxToken;

pFreeContextBuffer( pspkg );

// Prepare our output buffer. We use a temporary buffer because
// the real output buffer will most likely need to be uuencoded

if ( !BufferResize( &buff, pAS->_cbMaxToken ))
fSt = FALSE;
goto ex;

OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;

OutSecBuff.cbBuffer = pAS->_cbMaxToken;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = BufferQueryPtr( &buff );

// Prepare our Input buffer.

if ( pBuffIn )
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 3;
InBuffDesc.pBuffers = &InSecBuff;

//Complete Digest string returned from server.
InSecBuff[0].cbBuffer = strlen(pBuffIn);
InSecBuff[0].BufferType = SECBUFFER_TOKEN;
InSecBuff[0].pvBuffer = pBuffIn;

//The request method used in the web request.
InSecBuff[1].cbBuffer = 3;
InSecBuff[1].BufferType = SECBUFFER_PKG_PARAMS;
InSecBuff[1].pvBuffer = "GET";

//If I set this to what I believe is the cnonce (client generated hex
string) then it fails
//with Invalid Token.
//If set to NULL and zero then I get No Credentials error.
InSecBuff[2].cbBuffer = 0;
InSecBuff[2].BufferType = SECBUFFER_PKG_PARAMS;
InSecBuff[2].pvBuffer = NULL;
// will return success when its done but we still
// need to send the out buffer if there are bytes to send

printf("First call InitializeSecurityContext()\r\n");
ss = pInitializeSecurityContextA(
&Lifetime );


if(ss == SEC_E_OK || ss == SEC_I_CONTINUE_NEEDED)
printf("Second call InitializeSecurityContext()\r\n");
ss = pInitializeSecurityContextA(
&Lifetime );


if ( !SEC_SUCCESS( ss ) )
if ( ss == SEC_E_LOGON_DENIED )

SetLastError( ss );
fSt = FALSE;
goto ex;

//Encode the digest value that was generated.
if ( !uuencode( (BYTE *) OutSecBuff.pvBuffer,
pbuffOut ))
fSt = FALSE;
goto ex;

fSt = TRUE;

BufferTerminate( &buffData );
BufferTerminate( &buff );

return fSt;

Chuck C

""Jeffrey Tan[MSFT]"" wrote:

Hi Chuck,

Thanks for your post!

1. Is it possible for you to provide a little sample project and detailed
steps to help us reproduce this behavior? With the current information
available it is hard for me to give it a useful suggestion or guess for
root cause.

My current suggestion is downloading "SSPI Workbench Utility" in keith
brown's article below:
"Explore the Security Support Provider Interface Using the SSPI Workbench
Utility "

This tool can be used to do testing on various SSPI protocols including
Digest. You may give it a test and if it works, you may refer to the source
code of the tool for a sample.

2. Yes, it seems ISC_REQ_HTTP is missed in windows header files, I will try
to give it a research and get back to you ASAP. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
Get notification to my posts through email? Please refer to

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
This posting is provided "AS IS" with no warranties, and confers no rights.


Relevant Pages