Solved

help with HTTP-Authentication - URGENT !!!!!

Posted on 2001-07-03
14
766 Views
Last Modified: 2010-05-18
I must implement HTTP authentication in my client
application, but faced difficulties to do so.

the server sends WWW-Authenticate field which consists of a scheme part (in my case "Digest"), "nonce" line, and qop part ("auth").

after that I must return a valid authenticated response, which consists of the username, password, "cnonce" field, and the response part.

the way to do so is to work with three security functions
in the following order:

1. EnumerateSecurityPackages - to select the package (like -"digest" in my case)

2. AcquireCredentialsHandle - to obtain the credential handle

3. InitializeSecurityContext - to generate the required response.

the problem is that I don't know how to work with the last two function properly.
all the documentation are very basic, and non of them shows how to actually return a valid response like I need to.

I know that WinInet functions are able to handle authentication but I must do it by myself.

thanx,
Yuval.
0
Comment
Question by:ygross
  • 5
  • 4
  • 3
  • +2
14 Comments
 
LVL 22

Expert Comment

by:CJ_S
ID: 6247757
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 6247760
0
 

Author Comment

by:ygross
ID: 6248799
thanx but I know this example already and it didn't help me at all.

it doesn't show how the real work with digest authentication goes.

when I get the server response with its parameters (scheme,
nonce and qop) i need somehow to pass them into the InitializeSecurityContext function in a way which is not clear to me.
all i know is that they should be arranged in the input buffer of this function, together somehow with the realm and the password, but the exact way to do it is obscure.

I need a real example.

to demonstrate the input and the output result
let's say the server parameters are:

realm="hotmail.com"
nonce="OTk0MDc5MTMxOjdhMzhlN2M3YTk4Mjk3Y2VmOWQ5MDQzYjNhMzliYzQ4"
qop="auth"

some of the result parameters should be sent to server is accordingly:

nonce="OTk0MDc5MTMxOjdhMzhlN2M3YTk4Mjk3Y2VmOWQ5MDQzYjNhMzliYzQ4"
cnonce="11404ceed183e46fdb324005b2d46d8d"
response="97dc72b8dea4ac8f1af8c64080ac4d"

these should be obtained using the InitializeSecurityContext
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 6248854
SECURITY.C
/*++
 
Copyright 1996 - 1998 Microsoft Corporation
 
Module Name:
 
    security.c
 
Abstract:
 
    Handles communication with the SSP package.
 
Revision History:
 
--*/
 
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#define SECURITY_WIN32
#include "sspi.h"
#include "issperr.h"
#include "security.h"
#include "collect.h"
 
static HINSTANCE g_hLib;
static DWORD g_cbMaxToken;
static PSecurityFunctionTable g_pFuncs;
 
// structure storing the state of the authentication sequence
//
typedef struct _AUTH_SEQ {
    BOOL _fNewConversation;
    CredHandle _hcred;
    BOOL _fHaveCredHandle;
    BOOL _fHaveCtxtHandle;
    struct _SecHandle  _hctxt;
} AUTH_SEQ, *PAUTH_SEQ;
 
#define SEC_SUCCESS(Status) ((Status) >= 0)
 
#define PACKAGE_NAME"negotiate"
#define NT_DLL_NAME"security.dll"
 
// Target name for the security package
// De-comment after filling appropriate principal name, here.
//
// #define TOKEN_SOURCE_NAME       "<Domain>\\<User>"
 
 
BOOL InitPackage (DWORD *pcbMaxMessage)
/*++
 
 Routine Description:
 
    Finds, loads and initializes the security package
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
FARPROC pInit;
SECURITY_STATUS ss;
PSecPkgInfo pkgInfo;
 
// load and initialize the ntlm ssp
//
g_hLib = LoadLibrary (NT_DLL_NAME);
if (NULL == g_hLib)  {
fprintf (stderr, "Couldn't load dll: %u\n", GetLastError ());
return(FALSE);
}
 
pInit = GetProcAddress (g_hLib, SECURITY_ENTRYPOINT);
if (NULL == pInit)  {
fprintf (stderr, "Couldn't get sec init routine: %u\n", GetLastError ());
return(FALSE);
}
 
g_pFuncs = (PSecurityFunctionTable) pInit ();
if (NULL == g_pFuncs)  {
fprintf (stderr, "Couldn't init package\n");
return(FALSE);
}
 
// Query for the package we're interested in
//
ss = g_pFuncs->QuerySecurityPackageInfo (PACKAGE_NAME, &pkgInfo);
if (!SEC_SUCCESS(ss))  {
fprintf (stderr, "Couldn't query package info for %s, error %u\n",
PACKAGE_NAME, ss);
return(FALSE);
}
 
g_cbMaxToken = pkgInfo->cbMaxToken;
 
g_pFuncs->FreeContextBuffer (pkgInfo);
 
*pcbMaxMessage = g_cbMaxToken;
 
return TRUE;
}
 
BOOL TermPackage ()
{
FreeLibrary (g_hLib);
 
return(TRUE);
}
 
BOOL GenClientContext (
DWORD dwKey,
BYTE *pIn,
DWORD cbIn,
BYTE *pOut,
DWORD *pcbOut,
BOOL *pfDone)
/*++
 
 Routine Description:
 
    Optionally takes an input buffer coming from the server and returns
a buffer of information to send back to the server.  Also returns
an indication of whether or not the context is complete.
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
SECURITY_STATUSss;
TimeStampLifetime;
SecBufferDescOutBuffDesc;
SecBufferOutSecBuff;
SecBufferDescInBuffDesc;
SecBufferInSecBuff;
ULONGContextAttributes;
PAUTH_SEQpAS;
 
// Lookup pAS based on Key
//
if (!GetEntry (dwKey, (PVOID*) &pAS))
return(FALSE);
 
if (pAS->_fNewConversation)  {
ss = g_pFuncs->AcquireCredentialsHandle (
NULL,// principal
PACKAGE_NAME,
SECPKG_CRED_OUTBOUND,
NULL,// LOGON id
NULL,// auth data
NULL,// get key fn
NULL,// get key arg
&pAS->_hcred,
&Lifetime
);
if (SEC_SUCCESS (ss))
pAS->_fHaveCredHandle = TRUE;
else {
fprintf (stderr, "AcquireCreds failed: %u\n", ss);
return(FALSE);
}
}
 
// prepare output buffer
//
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
 
OutSecBuff.cbBuffer = *pcbOut;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = pOut;
 
// prepare input buffer
//
if (!pAS->_fNewConversation)  {
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
 
InSecBuff.cbBuffer = cbIn;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = pIn;
}
 
ss = g_pFuncs->InitializeSecurityContext (
&pAS->_hcred,
pAS->_fNewConversation ? NULL : &pAS->_hctxt,
TOKEN_SOURCE_NAME,
0,// context requirements
0,// reserved1
SECURITY_NATIVE_DREP,
pAS->_fNewConversation ? NULL : &InBuffDesc,
0,// reserved2
&pAS->_hctxt,
&OutBuffDesc,
&ContextAttributes,
&Lifetime
);
if (!SEC_SUCCESS (ss))  {
fprintf (stderr, "init context failed: %u\n", ss);
return FALSE;
}
 
pAS->_fHaveCtxtHandle = TRUE;
 
// Complete token -- if applicable
//
if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))  {
if (g_pFuncs->CompleteAuthToken) {
ss = g_pFuncs->CompleteAuthToken (&pAS->_hctxt, &OutBuffDesc);
if (!SEC_SUCCESS(ss))  {
fprintf (stderr, "complete failed: %u\n", ss);
return FALSE;
}
}
else {
fprintf (stderr, "Complete not supported.\n");
return FALSE;
}
}
 
*pcbOut = OutSecBuff.cbBuffer;
 
if (pAS->_fNewConversation)
pAS->_fNewConversation = FALSE;
 
*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
(SEC_I_COMPLETE_AND_CONTINUE == ss));
 
return TRUE;
}
 
BOOL GenServerContext (
DWORD dwKey,
BYTE *pIn,
DWORD cbIn,
BYTE *pOut,
DWORD *pcbOut,
BOOL *pfDone)
/*++
 
 Routine Description:
 
    Takes an input buffer coming from the client and returns a buffer
to be sent to the client.  Also returns an indication of whether or
not the context is complete.
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
SECURITY_STATUSss;
TimeStampLifetime;
SecBufferDescOutBuffDesc;
SecBufferOutSecBuff;
SecBufferDescInBuffDesc;
SecBufferInSecBuff;
ULONGContextAttributes;
PAUTH_SEQpAS;
 
// Lookup pAS based on Key
//
if (!GetEntry (dwKey, (PVOID*) &pAS))
return(FALSE);
 
if (pAS->_fNewConversation)  {
ss = g_pFuncs->AcquireCredentialsHandle (
NULL,// principal
PACKAGE_NAME,
SECPKG_CRED_INBOUND,
NULL,// LOGON id
NULL,// auth data
NULL,// get key fn
NULL,// get key arg
&pAS->_hcred,
&Lifetime
);
if (SEC_SUCCESS (ss))
pAS->_fHaveCredHandle = TRUE;
else {
fprintf (stderr, "AcquireCreds failed: %u\n", ss);
return(FALSE);
}
}
 
// prepare output buffer
//
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
 
OutSecBuff.cbBuffer = *pcbOut;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = pOut;
 
// prepare input buffer
//
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
 
InSecBuff.cbBuffer = cbIn;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = pIn;
 
ss = g_pFuncs->AcceptSecurityContext (
&pAS->_hcred,
pAS->_fNewConversation ? NULL : &pAS->_hctxt,
&InBuffDesc,
0,// context requirements
SECURITY_NATIVE_DREP,
&pAS->_hctxt,
&OutBuffDesc,
&ContextAttributes,
&Lifetime
);
if (!SEC_SUCCESS (ss))  {
fprintf (stderr, "init context failed: %u\n", ss);
return FALSE;
}
 
pAS->_fHaveCtxtHandle = TRUE;
 
// Complete token -- if applicable
//
if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))  {
if (g_pFuncs->CompleteAuthToken) {
ss = g_pFuncs->CompleteAuthToken (&pAS->_hctxt, &OutBuffDesc);
if (!SEC_SUCCESS(ss))  {
fprintf (stderr, "complete failed: %u\n", ss);
return FALSE;
}
}
else {
fprintf (stderr, "Complete not supported.\n");
return FALSE;
}
}
 
*pcbOut = OutSecBuff.cbBuffer;
 
if (pAS->_fNewConversation)
pAS->_fNewConversation = FALSE;
 
*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
(SEC_I_COMPLETE_AND_CONTINUE == ss));
 
return TRUE;
}
 
BOOL ImpersonateContext (DWORD dwKey)
/*++
 
 Routine Description:
 
    Impersonates the client whose context is associated with the
supplied key.
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
SECURITY_STATUSss;
PAUTH_SEQpAS;
 
// Lookup pAS based on Key
//
if (!GetEntry (dwKey, (PVOID*) &pAS))
return(FALSE);
 
ss = g_pFuncs->ImpersonateSecurityContext (&pAS->_hctxt);
if (!SEC_SUCCESS(ss)) {
fprintf (stderr, "Impersonate failed: %u\n", ss);
return(FALSE);
}
 
return(TRUE);
}
 
BOOL RevertContext (DWORD dwKey)
/*++
 
 Routine Description:
 
    Reverts to the original server context.
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
SECURITY_STATUS ss;
PAUTH_SEQpAS;
 
// Lookup pAS based on Key
//
if (!GetEntry (dwKey, (PVOID*) &pAS))
return(FALSE);
 
ss = g_pFuncs->RevertSecurityContext (&pAS->_hctxt);
if (!SEC_SUCCESS(ss)) {
fprintf (stderr, "Revert failed: %u\n", ss);
return(FALSE);
}
 
return(TRUE);
}
 
BOOL InitSession (DWORD dwKey)
/*++
 
 Routine Description:
 
    Initializes the context associated with a key and adds it to the
collection.
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
PAUTH_SEQ pAS;
 
pAS = (PAUTH_SEQ) malloc (sizeof (AUTH_SEQ));
if (NULL == pAS)
return(FALSE);
 
pAS->_fNewConversation = TRUE;
pAS->_fHaveCredHandle = FALSE;
pAS->_fHaveCtxtHandle = FALSE;
 
if (!AddEntry (dwKey, (PVOID)pAS))  {
free (pAS);
return(FALSE);
}
 
return(TRUE);
}
 
BOOL TermSession (DWORD dwKey)
/*++
 
 Routine Description:
 
    Releases the resources associated with a key and removes it from
the collection.
 
 Return Value:
 
    Returns TRUE is successful; otherwise FALSE is returned.
 
--*/
{
PAUTH_SEQ pAS;
 
if (!DeleteEntry (dwKey, (LPVOID*)&pAS))
return(FALSE);
 
if (pAS->_fHaveCtxtHandle)
g_pFuncs->DeleteSecurityContext (&pAS->_hctxt);
 
if (pAS->_fHaveCredHandle)
g_pFuncs->FreeCredentialHandle (&pAS->_hcred);
 
free (pAS);
 
return(TRUE);
}
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 6248861
That's a sample microsoft provides. I think that I cannot help any further with this, because I have no experience with these functions :-/...if that try doesn't help, I won't try anymore and hope that someone else with the experience will come by...

regards,
CJ
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 6248872
You might also want to check out the MakeSignature function
0
 

Author Comment

by:ygross
ID: 6249424
thanx again but as you can this example says nothing,
cause what you put into the input buffet is just
InSecBuff.cbBuffer = cbIn;
what does it mean? i don't know. I need to put several parameters as I mentioned before. there is no place where they show how to do it.
I'm aware that this is the only microsoft example, but that's why I posted this question here.

if you are familiar with someone who has an experience with this, let me know and if he/she will bring the answer I'll give you all the credit points.

Yuval.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 49

Expert Comment

by:DanRollins
ID: 7020551
>>InSecBuff.cbBuffer = cbIn;
>> what does it mean?

That sample tesll you everything you need to know.  Here's how to figure out what's going on:
...
InSecBuff.cbBuffer = cbIn;
...etc...
ss = g_pFuncs->AcceptSecurityContext (
      &pAS->_hcred,
      pAS->_fNewConversation ? NULL : &pAS->_hctxt,
      &InBuffDesc,
      0,// context requirements
      SECURITY_NATIVE_DREP,
      &pAS->_hctxt,
      &OutBuffDesc,
      &ContextAttributes,
      &Lifetime
);
...etc...
In the VC++ IDE, click on the word "AcceptSecurityContext" and press F1 (the key marked F1, not the two separate keys "F" and "1").  That brings up all kinds of useful information!  You'll see that the third parameter is expected to be a pointer to something called a SecBuffDesc and the help shows that word with a odd-looking line underneath it.  That means that you can click that word!  It's worth a try at least...  Once when I clicked a word like that the screen changed and showed some new information (well I've never actually done it, but somebody I know said it was so and I believe them).  

I hope this helps.
-- Dan
0
 
LVL 54

Expert Comment

by:nico5038
ID: 7487607

No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
 - PAQ'd and pts removed
Please leave any comments here within the
next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !

Nic;o)
0
 

Author Comment

by:ygross
ID: 7489370
will I get back my credit point?
By the way, how do I cancel a question?
Many questions I have posted here have been either resolved or become irrelevant.
0
 
LVL 54

Expert Comment

by:nico5038
ID: 7489511
Hi ygross,

>will I get back my credit point?
That depends on the judgement of the moderator.
I proposed to NOT refund the points as you didn't react on the DanRollins comment. In such a case I assume the Q has been abandonned by the questionner.

>By the way, how do I cancel a question?
A Q can be deleted or PAQ'd by posting a zero points Q (with a link to the Q in question) in the Community Support Topic Area:
http://www.experts-exchange.com/Community_Support/
You won't need it for this Q as this one will be handled by a moderator on the 30th of this month.

Nic;o)
0
 

Author Comment

by:ygross
ID: 7492659
the answer proposed by Rollins didn't not help me at all and was inncorrect. that's the reason I didn't answer. Therefore I think that the right thing is to refund me my points to this question.

By the way, I can I see ALL of my opened question? they are scattered between the areas here, and some of them were forgotten... I need this in order to request the refund you've mentioned.

Thanx,
Yuval.
0
 
LVL 54

Expert Comment

by:nico5038
ID: 7492788
Hmm, I see you've asked 18 Q's and answered/finalized only 5.
I know a lot of experts that first look into the profile to see whether an asker finalizes Q's as he should.
Making comments is time consuming and askers with a grading record as bad as yours will certainly be ignored by a number of experts....

You stated "the answer proposed by Rollins didn't not help me at all and was inncorrect."
But as long as you don't add that to this thread (and tell why it's incorrect), no other expert will react.

That's also the reason why I won't change my proposal yet.

As I believe there should be a foundation to the statement why it doesn't work and you would have to allow the expert to react on that.

When you want to improve your grading record, you can make a list of all URL-addresses and propose a way to finalize the Q.
All Q's are listed under your profile (just click your membername).
When you want a delete or PAQ and refund, a moderator will ask for a comment on the Q and a 72 hrs period allowing the experts to react.
You can post a request in the CS topic area:
http://www.experts-exchange.com/Community_Support/

Nic;o)
0
 
LVL 5

Accepted Solution

by:
Netminder earned 0 total points
ID: 7518892
ygross,

Your record of opening and not closing questions is atrocious. As such, the recommendation that you have abandoned, without comment, this question, and that therefore your points should be removed, is upheld.

If you wish to avoid this in the future, I suggest that you maintain your open questions in short order, as I can assure you, we will not look kindly on your record in the future.

Per recommendation, points NOT refunded and question closed.

Netminder
EE Admin
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now