Jump to content

SSPI Kerberos for delegation


Recommended Posts

Guest Kasparov
Posted

Hi,

 

We want the authentication to happen without providing credentials

anywhere. For this we are planning to use Windows SSPI. Now the

problem I am facing is once the authentication from client to server

is successful, I want to use the

 

security context created in server to connect back and authenticate to

the client. I am trying to find out if this thing is possible with

SSPI.

 

For this I have written an application (prototype) with client side

and server side. I am connecting to the server and after successfully

authentication at the server side I try to connect back (to the server

component on the client

 

machine, running in the same process and thread as client) using the

same procedure I used in the client side. My understanding is since I

have impersonated I will be able to authenticate the same user again.

But I always get the error

 

"No credentials are available in the security package" and the

credentials might have expired. I have verified that both the user

accounts are trusted for delegation and "cannot be delegated" tab is

unchcked. Also both the servers are

 

trusted for delegation for any service for Kerberos.

 

I have tried doing this with NTLM and Kerberos. With NTLM it looks

like the reverse connection is successful but after impersonation at

the client side if I try to print the user name it says "Anonymous

Logon". With Kerberos I am

 

getting various errors (not enough memory, credentials are expired

etc) and I am still working on that part. The reason I am trying with

Kerberos is that I learned from some articles on Net that such a thing

(delegation) is possible only

 

with Kerberos.

 

Surprisingly I am not able to find out a single working solution of

this kind. I have pasted my entire code below. Can anyone help me on

this and advise me on how this can be achieved ? Please see the code

samples below:

 

Client (Logged in user: win\gtambat)

 

#include <stdio.h>

#include <windows.h>

#include <string.h>

#include <malloc.h>

 

#define SECURITY_WIN32 1

#include <security.h>

 

#pragma hdrstop

 

//

====================================================================

// IMPORTANT NOTICE -- Check out

// http://www.mvps.org/security/sspi.html

// for the gory details of how this works

//

====================================================================

 

 

 

void auth( SOCKET s, CredHandle& cred, CtxtHandle& cliCtx,

const char tokenSource, const char name = NULL,

const char pwd = NULL, const char domain = NULL );

 

PSecurityFunctionTable pf = NULL;

 

void initSecLib( HINSTANCE& hSec );

 

bool Ganesh_auth( SOCKET s, CredHandle& cred, CtxtHandle& srvCtx )

{

int rc;

bool haveToken = true;

SecPkgInfo secPackInfo;

int bytesReceived = 0, bytesSent = 0;

char buf[256];

DWORD bufsiz = sizeof buf;

HANDLE threadRet;

 

puts( "auth() entered" );

 

rc = (pf->QuerySecurityPackageInfo)( "Kerberos", &secPackInfo );

printf( "QSPI(): %08xh\n", rc );

if ( rc != SEC_E_OK )

haveToken = false;

 

TimeStamp useBefore;

 

rc = (pf->AcquireCredentialsHandle)( NULL, "Kerberos",

SECPKG_CRED_BOTH,

NULL, NULL, NULL, NULL, &cred, &useBefore );

 

rc = GetLastError();

 

printf( "ACH(): %08xh\n", rc );

if ( rc != SEC_E_OK )

haveToken = false;

 

// input and output buffers

SecBufferDesc obd, ibd;

SecBuffer ob, ib;

 

DWORD ctxAttr;

 

bool haveContext = false;

 

while ( 1 )

{

// prepare to get the server's response

ibd.ulVersion = SECBUFFER_VERSION;

ibd.cBuffers = 1;

ibd.pBuffers = &ib; // just one buffer

ib.BufferType = SECBUFFER_TOKEN; // preping a token here

 

// receive the client's POD

// MACHINE-DEPENDENT CODE! (Besides, we assume that we

// get the length with a single read, which is not guaranteed)

recv( s, (char ) &ib.cbBuffer, sizeof ib.cbBuffer, 0 );

bytesReceived += sizeof ib.cbBuffer;

ib.pvBuffer = LocalAlloc( 0, ib.cbBuffer );

 

char p = (char ) ib.pvBuffer;

int n = ib.cbBuffer;

while ( n )

{

rc = recv( s, p, n, 0 );

// if ( rc == SOCKET_ERROR )

// wserr( rc, "recv" );

// if ( rc == 0 )

// wserr( 999, "recv" );

bytesReceived += rc;

n -= rc;

p += rc;

}

 

// by now we have an input buffer

 

obd.ulVersion = SECBUFFER_VERSION;

obd.cBuffers = 1;

obd.pBuffers = &ob; // just one buffer

ob.BufferType = SECBUFFER_TOKEN; // preping a token here

ob.cbBuffer = secPackInfo->cbMaxToken;

ob.pvBuffer = LocalAlloc( 0, ob.cbBuffer );

 

// rc = (pf->AcceptSecurityContext)( &cred, haveContext? &srvCtx:

NULL,

// &ibd, 0, SECURITY_NATIVE_DREP, &srvCtx, &obd, &ctxAttr,

// &useBefore );

 

rc = (pf->AcceptSecurityContext)( &cred, haveContext? &srvCtx: NULL,

&ibd, 0, SECURITY_NATIVE_DREP / SECURITY_NETWORK_DREP /, &srvCtx,

&obd, &ctxAttr,

&useBefore );

 

printf( "ASC(): %08xh\n", rc );

 

if ( ib.pvBuffer != NULL )

{

LocalFree( ib.pvBuffer );

ib.pvBuffer = NULL;

}

 

if ( rc == SEC_I_COMPLETE_AND_CONTINUE || rc ==

SEC_I_COMPLETE_NEEDED )

{

if ( pf->CompleteAuthToken != NULL ) // only if implemented

(pf->CompleteAuthToken)( &srvCtx, &obd );

if ( rc == SEC_I_COMPLETE_NEEDED )

rc = SEC_E_OK;

else if ( rc == SEC_I_COMPLETE_AND_CONTINUE )

rc = SEC_I_CONTINUE_NEEDED;

}

 

// send the output buffer off to the server

// warning -- this is machine-dependent! FIX IT!

if ( rc == SEC_E_OK || rc == SEC_I_CONTINUE_NEEDED )

{

if ( ob.cbBuffer != 0 )

{

send( s, (const char ) &ob.cbBuffer, sizeof ob.cbBuffer, 0 );

bytesSent += sizeof ob.cbBuffer;

send( s, (const char ) ob.pvBuffer, ob.cbBuffer, 0 );

bytesSent += ob.cbBuffer;

}

LocalFree( ob.pvBuffer );

ob.pvBuffer = NULL;

}

 

if ( rc != SEC_I_CONTINUE_NEEDED )

break;

 

haveContext = true;

 

// loop back for another round

puts( "looping" );

}

 

// we arrive here as soon as InitializeSecurityContext()

// returns != SEC_I_CONTINUE_NEEDED.

 

if ( rc != SEC_E_OK )

{

printf( "Oops! ASC() returned %08xh!\n", rc );

haveToken = false;

}

 

rc = GetLastError();

 

GetUserName( buf, &bufsiz );

 

// now we try to use the context

rc = (pf->ImpersonateSecurityContext)( &srvCtx );

printf( "ImpSC(): %08xh\n", rc );

if ( rc != SEC_E_OK )

{

printf( "Oops! ImpSC() returns %08xh!\n", rc );

haveToken = false;

}

else

{

char buf[256];

DWORD bufsiz = sizeof buf;

GetUserName( buf, &bufsiz );

printf( "user name: \"%s\"\n", buf );

(pf->RevertSecurityContext)( &srvCtx );

printf( "RSC(): %08xh\n", rc );

}

 

(pf->FreeContextBuffer)( secPackInfo );

 

printf( "auth() exiting (%d received, %d sent)\n", bytesReceived,

bytesSent );

return haveToken;

}

 

int Ganesh_Server_Impl()

{

int rc, port = 12000, addrlen;

bool haveToken;

SOCKET sock, s;

WSADATA wsadata;

PSERVENT pse;

SOCKADDR_IN addr;

HINSTANCE hSecLib;

 

initSecLib( hSecLib );

 

rc = WSAStartup( 2, &wsadata );

// wserr( rc, "WSAStartup" );

 

sock = socket( AF_INET, SOCK_STREAM, 0 );

if ( sock == INVALID_SOCKET )

{

rc = -1;

}

else

{

rc = 0;

}

// wserr( 999, "socket" );

 

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = INADDR_ANY;

 

// try numeric protocol first

if ( port > 0 && port < 32768 )

addr.sin_port = htons( (short) port );

else

{

}

 

rc = bind( sock, (SOCKADDR ) &addr, sizeof addr );

// wserr( rc, "bind" );

 

rc = listen( sock, 2 );

// wserr( rc, "listen" );

 

CredHandle cred;

CtxtHandle srvCtx;

 

while ( 1 )

{

addrlen = sizeof addr;

s = accept( sock, (SOCKADDR ) &addr, &addrlen );

if ( s == INVALID_SOCKET )

{

rc = -1;

}

else

{

rc = 0;

}

// wserr( s, "accept" );

 

haveToken = Ganesh_auth( s, cred, srvCtx );

 

// now we talk to the client

printf( "haveToken = %s\n\n", haveToken? "true": "false" );

send( s, (const char ) &haveToken, sizeof haveToken, 0 );

 

// clean up

(pf->DeleteSecurityContext)( &srvCtx );

(pf->FreeCredentialHandle)( &cred );

closesocket( s );

}

}

 

// wserr() displays winsock errors and aborts. No grace there.

void wserr( int rc, const char const funcname )

{

if ( rc == 0 )

return;

 

fprintf( stderr, "\nWinsock error %d [gle %d] returned by %s().\n"

"Sorry, no bonus!\n", rc, WSAGetLastError(), funcname );

WSACleanup();

exit( rc );

}

 

 

 

void auth( SOCKET s, CredHandle& cred, CtxtHandle& cliCtx,

const char tokenSource, const char name / = NULL /,

const char pwd / = NULL /, const char domain / = NULL / )

{

int rc, rcISC;

SecPkgInfo secPackInfo;

SEC_WINNT_AUTH_IDENTITY nameAndPwd = NULL;

int bytesReceived = 0, bytesSent = 0;

 

puts( "auth() entered" );

 

// the arguments to ISC() is not const ... for once, I decided

// on creating writable copies instead of using a brutalizing cast.

char myTokenSource;

myTokenSource = _strdup( tokenSource );

 

if ( name != NULL )

{

nameAndPwd = (SEC_WINNT_AUTH_IDENTITY ) malloc( sizeof

SEC_WINNT_AUTH_IDENTITY );

memset( nameAndPwd, '\0', sizeof nameAndPwd );

nameAndPwd->Domain = (byte ) _strdup( domain? domain: "" );

nameAndPwd->DomainLength = domain? strlen( domain ): 0;

nameAndPwd->User = (byte ) _strdup( name? name: "" );

nameAndPwd->UserLength = name? strlen( name ): 0;

nameAndPwd->Password = (byte ) _strdup( pwd? pwd: "" );

nameAndPwd->PasswordLength = pwd? strlen( pwd ): 0;

nameAndPwd->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

}

 

rc = (pf->QuerySecurityPackageInfo)( "Kerberos", &secPackInfo );

printf( "QSPI(): %08xh\n", rc );

 

TimeStamp useBefore;

 

rc = (pf->AcquireCredentialsHandle)( NULL, "Kerberos",

SECPKG_CRED_BOTH,

NULL, nameAndPwd, NULL, NULL, &cred, &useBefore );

printf( "ACH(): %08xh\n", rc );

 

// input and output buffers

SecBufferDesc obd, ibd;

SecBuffer ob, ib;

 

DWORD ctxReq, ctxAttr;

 

// from sspi.h:

// #define ISC_REQ_DELEGATE 0x00000001

// #define ISC_REQ_MUTUAL_AUTH 0x00000002

// #define ISC_REQ_REPLAY_DETECT 0x00000004

// #define ISC_REQ_SEQUENCE_DETECT 0x00000008

// #define ISC_REQ_CONFIDENTIALITY 0x00000010

// #define ISC_REQ_USE_SESSION_KEY 0x00000020

// #define ISC_REQ_PROMPT_FOR_CREDS 0x00000040

// #define ISC_REQ_USE_SUPPLIED_CREDS 0x00000080

// #define ISC_REQ_ALLOCATE_MEMORY 0x00000100

// #define ISC_REQ_USE_DCE_STYLE 0x00000200

// #define ISC_REQ_DATAGRAM 0x00000400

// #define ISC_REQ_CONNECTION 0x00000800

// #define ISC_REQ_CALL_LEVEL 0x00001000

// #define ISC_REQ_EXTENDED_ERROR 0x00004000

// #define ISC_REQ_STREAM 0x00008000

// #define ISC_REQ_INTEGRITY 0x00010000

ctxReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |

ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;

 

bool haveInbuffer = false;

bool haveContext = false;

ib.pvBuffer = NULL;

 

while ( 1 )

{

obd.ulVersion = SECBUFFER_VERSION;

obd.cBuffers = 1;

obd.pBuffers = &ob; // just one buffer

ob.BufferType = SECBUFFER_TOKEN; // preping a token here

ob.cbBuffer = secPackInfo->cbMaxToken;

ob.pvBuffer = LocalAlloc( 0, ob.cbBuffer );

 

rcISC = (pf->InitializeSecurityContext)( &cred, haveContext?

&cliCtx: NULL,

myTokenSource, ctxReq, 0, SECURITY_NATIVE_DREP /

SECURITY_NETWORK_DREP /, haveInbuffer? &ibd: NULL,

0, &cliCtx, &obd, &ctxAttr, &useBefore );

printf( "ISC(): %08xh\n", rcISC );

 

if ( ib.pvBuffer != NULL )

{

LocalFree( ib.pvBuffer );

ib.pvBuffer = NULL;

}

 

if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE || rcISC ==

SEC_I_COMPLETE_NEEDED )

{

if ( pf->CompleteAuthToken != NULL ) // only if implemented

(pf->CompleteAuthToken)( &cliCtx, &obd );

if ( rcISC == SEC_I_COMPLETE_NEEDED )

rcISC = SEC_E_OK;

else if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE )

rcISC = SEC_I_CONTINUE_NEEDED;

}

 

// send the output buffer off to the server

// warning -- this is machine-dependent! FIX IT!

if ( ob.cbBuffer != 0 )

{

send( s, (const char ) &ob.cbBuffer, sizeof ob.cbBuffer, 0 );

bytesSent += sizeof ob.cbBuffer;

send( s, (const char ) ob.pvBuffer, ob.cbBuffer, 0 );

bytesSent += ob.cbBuffer;

}

LocalFree( ob.pvBuffer );

ob.pvBuffer = NULL;

 

if ( rcISC != SEC_I_CONTINUE_NEEDED )

break;

 

// prepare to get the server's response

ibd.ulVersion = SECBUFFER_VERSION;

ibd.cBuffers = 1;

ibd.pBuffers = &ib; // just one buffer

ib.BufferType = SECBUFFER_TOKEN; // preping a token here

 

// receive the server's response

// MACHINE-DEPENDENT CODE! (Besides, we assume that we

// get the length with a single read, which is not guaranteed)

recv( s, (char ) &ib.cbBuffer, sizeof ib.cbBuffer, 0 );

bytesReceived += sizeof ib.cbBuffer;

ib.pvBuffer = LocalAlloc( 0, ib.cbBuffer );

 

char p = (char ) ib.pvBuffer;

int n = ib.cbBuffer;

while ( n )

{

rc = recv( s, p, n, 0 );

if ( rc == SOCKET_ERROR )

wserr( rc, "recv" );

if ( rc == 0 )

wserr( 999, "recv" );

bytesReceived += rc;

n -= rc;

p += rc;

}

 

// by now we have an input buffer and a client context

 

haveInbuffer = true;

haveContext = true;

 

// loop back for another round

puts( "looping" );

}

 

// we arrive here as soon as InitializeSecurityContext()

// returns != SEC_I_CONTINUE_NEEDED.

 

if ( rcISC != SEC_E_OK )

printf( "Oops! ISC() returned %08xh!\n", rcISC );

 

(pf->FreeContextBuffer)( secPackInfo );

printf( "auth() exiting (%d sent, %d received)\n", bytesSent,

bytesReceived );

free( myTokenSource );

if ( nameAndPwd != 0 )

{

if ( nameAndPwd->Domain != 0 )

free( nameAndPwd->Domain );

if ( nameAndPwd->User != 0 )

free( nameAndPwd->User );

if ( nameAndPwd->Password != 0 )

free( nameAndPwd->Password );

free( nameAndPwd );

}

}

 

 

 

void initSecLib( HINSTANCE& hSec )

{

PSecurityFunctionTable ( pSFT)( void );

 

hSec = LoadLibrary( "security.dll" );

pSFT = (PSecurityFunctionTable ( )( void )) GetProcAddress( hSec,

"InitSecurityInterfaceA" );

if ( pSFT == NULL )

{

puts( "security.dll load messed up ..." );

exit( 1 );

}

 

pf = pSFT();

if ( pf == NULL )

{

puts( "no function table?!?" );

exit( 1 );

}

}

 

 

 

int main( int argc, char argv[] )

{

int rc, port, i, errors;

HINSTANCE hSecLib;

 

unsigned long naddr;

SOCKET sock;

WSADATA wsadata;

PHOSTENT phe;

PSERVENT pse;

SOCKADDR_IN addr;

//const char tokenSource = "Authsamp", server = "server-machine";

const char tokenSource = "win\\gtambat1", server = "server-

machine";

const char portstr = "11000", user = 0, pwd = 0, domain = 0;

 

errors = 0;

for ( i = 1; i < argc; ++ i )

{

if ( argv[0] != '-' && argv[0] != '/' )

{

printf( "\"%s\" is not a valid switch.\n", argv );

++ errors;

continue;

}

 

switch ( argv[1] )

{

case 's':

if ( i >= argc - 1 )

{

printf( "\"%s\" requires an argument.\n", argv );

++ errors;

}

else if ( server != 0 )

{

printf( "\"%s\" has already been used.\n", argv[i ++] );

++ errors;

}

else

server = argv[++ i];

break;

case 'p':

if ( i >= argc - 1 )

{

printf( "\"%s\" requires an argument.\n", argv );

++ errors;

}

else if ( portstr != 0 )

{

printf( "\"%s\" has already been used.\n", argv[i ++] );

++ errors;

}

else

portstr = argv[++ i];

break;

case 't':

if ( i >= argc - 1 )

{

printf( "\"%s\" requires an argument.\n", argv );

++ errors;

}

else if ( tokenSource != 0 )

{

printf( "\"%s\" has already been used.\n", argv[i ++] );

++ errors;

}

else

tokenSource = argv[++ i];

break;

case 'd':

if ( i >= argc - 1 )

{

printf( "\"%s\" requires an argument.\n", argv );

++ errors;

}

else if ( domain != 0 )

{

printf( "\"%s\" has already been used.\n", argv[i ++] );

++ errors;

}

else

domain = argv[++ i];

break;

case 'u':

if ( i >= argc - 2 )

{

printf( "\"%s\" requires two arguments.\n", argv[i ++] );

++ errors;

}

else if ( user != 0 )

{

printf( "\"%s\" has already been used.\n", argv );

i += 2;

++ errors;

}

else

{

user = argv[++ i];

pwd = argv[++ i];

}

break;

default:

printf( "\"%s\" is not a valid switch.\n", argv );

++ errors;

break;

}

}

 

if ( server == 0 )

{

puts( "A server name or IP address must be specified." );

++ errors;

}

 

if ( portstr == 0 )

{

puts( "A port name or port number must be specified." );

++ errors;

}

 

if ( user == 0 && domain != 0 )

puts( "No user name was specified, ignoring the domain." );

 

if ( errors )

{

puts( "\nusage: client -s your.server.com -p serverport" );

puts( " [-t token-source] [-u user pwd [-d domain]]" );

puts( "token-source is _required_ for Kerberos and should be

your" );

puts( "current logon name (e.g., \"MYDOMAIN\\felixk\")." );

puts( "If -u is absent, your current credentials will be used." );

return 1;

}

 

initSecLib( hSecLib );

 

rc = WSAStartup( 2, &wsadata );

wserr( rc, "WSAStartup" );

 

sock = socket( AF_INET, SOCK_STREAM, 0 );

if ( sock == INVALID_SOCKET )

wserr( 999, "socket" );

 

addr.sin_family = AF_INET;

// try numeric IP address first (inet_addr)

naddr = inet_addr( server );

if ( naddr != INADDR_NONE )

{

addr.sin_addr.s_addr = naddr;

}

else

{

phe = gethostbyname( server );

if ( phe == NULL )

wserr( 1, "gethostbyname" );

addr.sin_addr.s_addr = ( (unsigned long ) (phe->h_addr) );

memcpy( (char ) &addr.sin_addr, phe->h_addr, phe->h_length );

}

 

// try numeric protocol first

port = atoi( portstr );

if ( port > 0 && port < 32768 )

addr.sin_port = htons( (short) port );

else

{

pse = getservbyname( portstr, "tcp" );

if ( pse == NULL )

wserr( 1, "getservbyname" );

addr.sin_port = pse->s_port;

}

 

CredHandle cred;

CtxtHandle cliCtx;

 

rc = connect( sock, (SOCKADDR ) &addr, sizeof addr );

wserr( rc, "connect" );

 

struct sockaddr name;

int namelen = sizeof name;;

rc = getsockname( sock, &name, &namelen );

wserr( rc, "getsockname()" );

printf( "I am %u.%u.%u.%u\n", (unsigned int) (unsigned char)

name.sa_data[2],

(unsigned int) (unsigned char) name.sa_data[3], (unsigned int)

(unsigned char) name.sa_data[4],

(unsigned int) (unsigned char) name.sa_data[5] );

 

auth( sock, cred, cliCtx, tokenSource, user, pwd, server ); // this

does the real work

// Added by Ganesh

//auth( sock, cred, cliCtx, tokenSource, "ganesh", "ganesh", "client-

machine" ); // this does the real work

 

// use the authenticated connection here

bool haveToken = false;

rc = recv( sock, (char ) &haveToken, sizeof haveToken, 0 );

if ( rc != sizeof haveToken )

wserr( 999, "result-recv" );

 

if ( haveToken )

puts( "That seems to have worked." );

else

puts( "Oops! Wrong user name or password?" );

 

// the server is probably impersonating us by now

// this is where the client and server talk business

 

// clean up

(pf->DeleteSecurityContext)( &cliCtx );

(pf->FreeCredentialHandle)( &cred );

 

rc = closesocket( sock );

wserr( rc, "closesocket" );

 

rc = WSACleanup();

wserr( rc, "WSACleanup" );

 

 

 

 

int j;

puts("/n/n Should I start server implemenation within client ?: ");

scanf("%d",&j);

 

rc = Ganesh_Server_Impl();

 

__try

{

FreeLibrary( hSecLib );

}

__except ( 1 )

{

puts( "Freelibrary( security.dll ) caused an access violation.

Yuck." );

}

 

return 0;

}

 

 

 

 

Server (Logged in user win\gtambat1)

 

 

 

#include <stdio.h>

#include <windows.h>

#include <string.h>

#include <malloc.h>

 

#define SECURITY_WIN32 1

#include <sspi.h>

//#include <issperr.h> // uncomment if you have an old Platform SDK

 

#pragma hdrstop

 

//

====================================================================

// IMPORTANT NOTICE -- Check out

// http://www.mvps.org/security/sspi.html

// for the gory details of how this works

//

====================================================================

 

 

PSecurityFunctionTable pf = NULL;

 

int Ganesh_Client_Impl(CtxtHandle &srvCtx);

 

void initSecLib( HINSTANCE& hSec );

 

void Ganesh_auth( SOCKET s, CredHandle& cred, CtxtHandle& cliCtx,

const char tokenSource, const char name / = NULL /,

const char pwd / = NULL /, const char domain / = NULL / );

 

 

void Ganesh_auth( SOCKET s, CredHandle& cred, CtxtHandle& cliCtx,

const char tokenSource, const char name / = NULL /,

const char pwd / = NULL /, const char domain / = NULL / )

{

int rc, rcISC;

SecPkgInfo secPackInfo;

SEC_WINNT_AUTH_IDENTITY nameAndPwd = NULL;

int bytesReceived = 0, bytesSent = 0;

 

//puts( "auth() entered" );

 

// the arguments to ISC() is not const ... for once, I decided

// on creating writable copies instead of using a brutalizing cast.

char myTokenSource;

myTokenSource = _strdup( tokenSource );

 

if ( name != NULL )

{

nameAndPwd = (SEC_WINNT_AUTH_IDENTITY ) malloc( sizeof

SEC_WINNT_AUTH_IDENTITY );

memset( nameAndPwd, '\0', sizeof nameAndPwd );

nameAndPwd->Domain = (byte ) _strdup( domain? domain: "" );

nameAndPwd->DomainLength = domain? strlen( domain ): 0;

nameAndPwd->User = (byte ) _strdup( name? name: "" );

nameAndPwd->UserLength = name? strlen( name ): 0;

nameAndPwd->Password = (byte ) _strdup( pwd? pwd: "" );

nameAndPwd->PasswordLength = pwd? strlen( pwd ): 0;

nameAndPwd->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

}

 

rc = (pf->QuerySecurityPackageInfo)( "kerberos", &secPackInfo );

//printf( "QSPI(): %08xh\n", rc );

 

TimeStamp useBefore;

 

rc = GetLastError();

 

rc = (pf->AcquireCredentialsHandle)( NULL, "kerberos",

SECPKG_CRED_BOTH,

NULL, nameAndPwd, NULL, NULL, &cred, &useBefore );

//printf( "ACH(): %08xh\n", rc );

 

rc = GetLastError();

// input and output buffers

SecBufferDesc obd, ibd;

SecBuffer ob, ib;

 

DWORD ctxReq, ctxAttr;

 

// from sspi.h:

// #define ISC_REQ_DELEGATE 0x00000001

// #define ISC_REQ_MUTUAL_AUTH 0x00000002

// #define ISC_REQ_REPLAY_DETECT 0x00000004

// #define ISC_REQ_SEQUENCE_DETECT 0x00000008

// #define ISC_REQ_CONFIDENTIALITY 0x00000010

// #define ISC_REQ_USE_SESSION_KEY 0x00000020

// #define ISC_REQ_PROMPT_FOR_CREDS 0x00000040

// #define ISC_REQ_USE_SUPPLIED_CREDS 0x00000080

// #define ISC_REQ_ALLOCATE_MEMORY 0x00000100

// #define ISC_REQ_USE_DCE_STYLE 0x00000200

// #define ISC_REQ_DATAGRAM 0x00000400

// #define ISC_REQ_CONNECTION 0x00000800

// #define ISC_REQ_CALL_LEVEL 0x00001000

// #define ISC_REQ_EXTENDED_ERROR 0x00004000

// #define ISC_REQ_STREAM 0x00008000

// #define ISC_REQ_INTEGRITY 0x00010000

ctxReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |

ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;

 

bool haveInbuffer = false;

bool haveContext = false;

ib.pvBuffer = NULL;

 

while ( 1 )

{

obd.ulVersion = SECBUFFER_VERSION;

obd.cBuffers = 1;

obd.pBuffers = &ob; // just one buffer

ob.BufferType = SECBUFFER_TOKEN; // preping a token here

ob.cbBuffer = secPackInfo->cbMaxToken;

ob.pvBuffer = LocalAlloc( 0, ob.cbBuffer );

 

rcISC = (pf->InitializeSecurityContext)( &cred, haveContext?

&cliCtx: NULL,

myTokenSource, ctxReq, 0, SECURITY_NATIVE_DREP /

SECURITY_NETWORK_DREP /, haveInbuffer? &ibd: NULL,

0, &cliCtx, &obd, &ctxAttr, &useBefore );

// printf( "ISC(): %08xh\n", rcISC );

 

if ( ib.pvBuffer != NULL )

{

LocalFree( ib.pvBuffer );

ib.pvBuffer = NULL;

}

 

if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE || rcISC ==

SEC_I_COMPLETE_NEEDED )

{

if ( pf->CompleteAuthToken != NULL ) // only if implemented

(pf->CompleteAuthToken)( &cliCtx, &obd );

if ( rcISC == SEC_I_COMPLETE_NEEDED )

rcISC = SEC_E_OK;

else if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE )

rcISC = SEC_I_CONTINUE_NEEDED;

}

 

// send the output buffer off to the server

// warning -- this is machine-dependent! FIX IT!

if ( ob.cbBuffer != 0 )

{

send( s, (const char ) &ob.cbBuffer, sizeof ob.cbBuffer, 0 );

bytesSent += sizeof ob.cbBuffer;

send( s, (const char ) ob.pvBuffer, ob.cbBuffer, 0 );

bytesSent += ob.cbBuffer;

}

LocalFree( ob.pvBuffer );

ob.pvBuffer = NULL;

 

if ( rcISC != SEC_I_CONTINUE_NEEDED )

break;

 

// prepare to get the server's response

ibd.ulVersion = SECBUFFER_VERSION;

ibd.cBuffers = 1;

ibd.pBuffers = &ib; // just one buffer

ib.BufferType = SECBUFFER_TOKEN; // preping a token here

 

// receive the server's response

// MACHINE-DEPENDENT CODE! (Besides, we assume that we

// get the length with a single read, which is not guaranteed)

rc = recv( s, (char ) &ib.cbBuffer, sizeof ib.cbBuffer, 0 );

bytesReceived += sizeof ib.cbBuffer;

ib.pvBuffer = LocalAlloc( 0, ib.cbBuffer );

 

char p = (char ) ib.pvBuffer;

int n = ib.cbBuffer;

while ( n )

{

rc = recv( s, p, n, 0 );

// if ( rc == SOCKET_ERROR )

// wserr( rc, "recv" );

// if ( rc == 0 )

// wserr( 999, "recv" );

bytesReceived += rc;

n -= rc;

p += rc;

}

 

// by now we have an input buffer and a client context

 

haveInbuffer = true;

haveContext = true;

 

// loop back for another round

// puts( "looping" );

}

 

// we arrive here as soon as InitializeSecurityContext()

// returns != SEC_I_CONTINUE_NEEDED.

 

if ( rcISC != SEC_E_OK )

{

printf( "Oops! ISC() returned %08xh!\n", rcISC );

}

 

(pf->FreeContextBuffer)( secPackInfo );

//printf( "auth() exiting (%d sent, %d received)\n", bytesSent,

bytesReceived );

free( myTokenSource );

if ( nameAndPwd != 0 )

{

if ( nameAndPwd->Domain != 0 )

free( nameAndPwd->Domain );

if ( nameAndPwd->User != 0 )

free( nameAndPwd->User );

if ( nameAndPwd->Password != 0 )

free( nameAndPwd->Password );

free( nameAndPwd );

}

}

 

 

 

// wserr() displays winsock errors and aborts. No grace there.

void wserr( int rc, const char const funcname )

{

if ( rc == 0 )

return;

 

fprintf( stderr, "\nWinsock error %d [gle %d] returned by %s().\n"

"Sorry, no bonus!\n", rc, WSAGetLastError(), funcname );

WSACleanup();

exit( rc );

}

 

 

 

bool auth( SOCKET s, CredHandle& cred, CtxtHandle& srvCtx )

{

int rc;

bool haveToken = true;

SecPkgInfo secPackInfo;

int bytesReceived = 0, bytesSent = 0;

char buf[256];

DWORD bufsiz = sizeof buf;

 

puts( "auth() entered" );

 

rc = (pf->QuerySecurityPackageInfo)( "kerberos", &secPackInfo );

printf( "QSPI(): %08xh\n", rc );

if ( rc != SEC_E_OK )

haveToken = false;

 

TimeStamp useBefore;

 

rc = (pf->AcquireCredentialsHandle)( NULL, "kerberos",

SECPKG_CRED_BOTH,

NULL, NULL, NULL, NULL, &cred, &useBefore );

 

// rc = (pf->AcquireCredentialsHandle)( NULL, "kerberos",

SECPKG_CRED_BOTH,

// NULL, NULL, NULL, NULL, &cred, &useBefore );

 

printf( "ACH(): %08xh\n", rc );

if ( rc != SEC_E_OK )

haveToken = false;

 

// input and output buffers

SecBufferDesc obd, ibd;

SecBuffer ob, ib;

 

DWORD ctxAttr;

 

bool haveContext = false;

 

while ( 1 )

{

// prepare to get the server's response

ibd.ulVersion = SECBUFFER_VERSION;

ibd.cBuffers = 1;

ibd.pBuffers = &ib; // just one buffer

ib.BufferType = SECBUFFER_TOKEN; // preping a token here

 

// receive the client's POD

// MACHINE-DEPENDENT CODE! (Besides, we assume that we

// get the length with a single read, which is not guaranteed)

recv( s, (char ) &ib.cbBuffer, sizeof ib.cbBuffer, 0 );

bytesReceived += sizeof ib.cbBuffer;

ib.pvBuffer = LocalAlloc( 0, ib.cbBuffer );

 

char p = (char ) ib.pvBuffer;

int n = ib.cbBuffer;

while ( n )

{

rc = recv( s, p, n, 0 );

if ( rc == SOCKET_ERROR )

wserr( rc, "recv" );

if ( rc == 0 )

wserr( 999, "recv" );

bytesReceived += rc;

n -= rc;

p += rc;

}

 

// by now we have an input buffer

 

obd.ulVersion = SECBUFFER_VERSION;

obd.cBuffers = 1;

obd.pBuffers = &ob; // just one buffer

ob.BufferType = SECBUFFER_TOKEN; // preping a token here

ob.cbBuffer = secPackInfo->cbMaxToken;

ob.pvBuffer = LocalAlloc( 0, ob.cbBuffer );

 

rc = (pf->AcceptSecurityContext)( &cred, haveContext? &srvCtx: NULL,

&ibd, 0,/ SECURITY_NATIVE_DREP / SECURITY_NATIVE_DREP /

SECURITY_NETWORK_DREP /, &srvCtx, &obd, &ctxAttr,

&useBefore );

printf( "ASC(): %08xh\n", rc );

 

if ( ib.pvBuffer != NULL )

{

LocalFree( ib.pvBuffer );

ib.pvBuffer = NULL;

}

 

if ( rc == SEC_I_COMPLETE_AND_CONTINUE || rc ==

SEC_I_COMPLETE_NEEDED )

{

if ( pf->CompleteAuthToken != NULL ) // only if implemented

(pf->CompleteAuthToken)( &srvCtx, &obd );

if ( rc == SEC_I_COMPLETE_NEEDED )

rc = SEC_E_OK;

else if ( rc == SEC_I_COMPLETE_AND_CONTINUE )

rc = SEC_I_CONTINUE_NEEDED;

}

 

// send the output buffer off to the server

// warning -- this is machine-dependent! FIX IT!

if ( rc == SEC_E_OK || rc == SEC_I_CONTINUE_NEEDED )

{

if ( ob.cbBuffer != 0 )

{

send( s, (const char ) &ob.cbBuffer, sizeof ob.cbBuffer, 0 );

bytesSent += sizeof ob.cbBuffer;

send( s, (const char ) ob.pvBuffer, ob.cbBuffer, 0 );

bytesSent += ob.cbBuffer;

}

LocalFree( ob.pvBuffer );

ob.pvBuffer = NULL;

}

 

if ( rc != SEC_I_CONTINUE_NEEDED )

break;

 

haveContext = true;

 

// loop back for another round

puts( "looping" );

}

 

// we arrive here as soon as InitializeSecurityContext()

// returns != SEC_I_CONTINUE_NEEDED.

 

if ( rc != SEC_E_OK )

{

printf( "Oops! ASC() returned %08xh!\n", rc );

haveToken = false;

}

 

GetUserName( buf, &bufsiz );

// now we try to use the context

rc = (pf->ImpersonateSecurityContext)( &srvCtx );

printf( "ImpSC(): %08xh\n", rc );

if ( rc != SEC_E_OK )

{

printf( "Oops! ImpSC() returns %08xh!\n", rc );

haveToken = false;

}

else

{

char buf[256];

DWORD bufsiz = sizeof buf;

 

printf( "haveToken = %s\n\n", haveToken? "true": "false" );

send( s, (const char ) &haveToken, sizeof haveToken, 0 );

 

GetUserName( buf, &bufsiz );

printf( "user name: \"%s\"\n", buf );

//(pf->RevertSecurityContext)( &srvCtx );

printf( "RSC(): %08xh\n", rc );

}

 

//(pf->FreeContextBuffer)( secPackInfo );

 

printf( "auth() exiting (%d received, %d sent)\n", bytesReceived,

bytesSent );

return haveToken;

}

 

int Ganesh_Client_Impl(CtxtHandle &srvCtx)

{

char buf[256];

DWORD bufsiz = sizeof buf;

int rc = 0;

 

//CtxtHandle tmpCtx = srvCtx;

 

 

SecPkgContext_Lifespan lspan;

rc = (pf->QueryContextAttributes)(&srvCtx, SECPKG_ATTR_LIFESPAN,

&lspan);

 

rc = GetLastError();

 

GetUserName( buf, &bufsiz );

//rc = (pf->ImpersonateSecurityContext)( &srvCtx );

 

rc = GetLastError();

GetUserName( buf, &bufsiz );

 

int port, i, errors;

unsigned long naddr;

SOCKET sock;

WSADATA wsadata;

PHOSTENT phe;

PSERVENT pse;

SOCKADDR_IN addr;

HINSTANCE hSecLib;

const char tokenSource = "win\\gtambat", server = "client-machine";

//const char tokenSource = "PUN\\gtambat"/ "Authsamp" /, server =

"client-machine";

const char portstr = "12000", user = 0, pwd = 0, domain = 0;

 

errors = 0;

if ( server == 0 )

{

//puts( "A server name or IP address must be specified." );

++ errors;

}

 

if ( portstr == 0 )

{

//puts( "A port name or port number must be specified." );

++ errors;

}

 

if ( user == 0 && domain != 0 )

{

}

// puts( "No user name was specified, ignoring the domain." );

 

if ( errors )

{

/ puts( "\nusage: client -s your.server.com -p serverport" );

puts( " [-t token-source] [-u user pwd [-d domain]]" );

puts( "token-source is _required_ for Kerberos and should be

your" );

puts( "current logon name (e.g., \"MYDOMAIN\\felixk\")." );

puts( "If -u is absent, your current credentials will be used." ); /

return 1;

}

 

initSecLib( hSecLib );

 

rc = WSAStartup( 2, &wsadata );

//wserr( rc, "WSAStartup" );

 

sock = socket( AF_INET, SOCK_STREAM, 0 );

if ( sock == INVALID_SOCKET )

{

rc = -1;

}

else

{

rc = 0;

}

 

addr.sin_family = AF_INET;

// try numeric IP address first (inet_addr)

naddr = inet_addr( server );

if ( naddr != INADDR_NONE )

{

addr.sin_addr.s_addr = naddr;

}

else

{

phe = gethostbyname( server );

// if ( phe == NULL )

// wserr( 1, "gethostbyname" );

addr.sin_addr.s_addr = ( (unsigned long ) (phe->h_addr) );

memcpy( (char ) &addr.sin_addr, phe->h_addr, phe->h_length );

}

 

// try numeric protocol first

port = atoi( portstr );

if ( port > 0 && port < 32768 )

addr.sin_port = htons( (short) port );

else

{

pse = getservbyname( portstr, "tcp" );

// if ( pse == NULL )

// wserr( 1, "getservbyname" );

addr.sin_port = pse->s_port;

}

 

CredHandle cred;

CtxtHandle cliCtx;

 

rc = connect( sock, (SOCKADDR ) &addr, sizeof addr );

//wserr( rc, "connect" );

 

struct sockaddr name;

int namelen = sizeof name;;

rc = getsockname( sock, &name, &namelen );

/ wserr( rc, "getsockname()" );

printf( "I am %u.%u.%u.%u\n", (unsigned int) (unsigned char)

name.sa_data[2],

(unsigned int) (unsigned char) name.sa_data[3], (unsigned int)

(unsigned char) name.sa_data[4],

(unsigned int) (unsigned char) name.sa_data[5] ); /

 

Ganesh_auth( sock, cred, cliCtx, tokenSource, user, pwd, domain ); //

this does the real work

 

// use the authenticated connection here

bool haveToken = false;

rc = recv( sock, (char ) &haveToken, sizeof haveToken, 0 );

if ( rc != sizeof haveToken )

{

rc = 999;

}

 

// wserr( 999, "result-recv" );

 

if ( haveToken )

puts( "That seems to have worked." );

else

puts( "Oops! Wrong user name or password?" );

 

 

// the server is probably impersonating us by now

// this is where the client and server talk business

 

// clean up

(pf->DeleteSecurityContext)( &cliCtx );

(pf->FreeCredentialHandle)( &cred );

 

rc = closesocket( sock );

wserr( rc, "closesocket" );

 

rc = WSACleanup();

wserr( rc, "WSACleanup" );

 

__try

{

FreeLibrary( hSecLib );

}

__except ( 1 )

{

// puts( "Freelibrary( security.dll ) caused an access violation.

Yuck." );

}

 

return 0;

}

 

struct CapName

{

DWORD bits;

const char name;

const char comment;

} capNames[] = {

{ SECPKG_FLAG_INTEGRITY, "SECPKG_FLAG_INTEGRITY", "Supports integrity

on messages" },

{ SECPKG_FLAG_PRIVACY, "SECPKG_FLAG_PRIVACY", "Supports privacy

(confidentiality)" },

{ SECPKG_FLAG_TOKEN_ONLY, "SECPKG_FLAG_TOKEN_ONLY", "Only security

token needed" },

{ SECPKG_FLAG_DATAGRAM, "SECPKG_FLAG_DATAGRAM", "Datagram RPC

support" },

{ SECPKG_FLAG_CONNECTION, "SECPKG_FLAG_CONNECTION", "Connection

oriented RPC support" },

{ SECPKG_FLAG_MULTI_REQUIRED, "SECPKG_FLAG_MULTI_REQUIRED", "Full 3-

leg required for re-auth." },

{ SECPKG_FLAG_CLIENT_ONLY, "SECPKG_FLAG_CLIENT_ONLY", "Server side

functionality not available" },

{ SECPKG_FLAG_EXTENDED_ERROR, "SECPKG_FLAG_EXTENDED_ERROR", "Supports

extended error msgs" },

{ SECPKG_FLAG_IMPERSONATION, "SECPKG_FLAG_IMPERSONATION", "Supports

impersonation" },

{ SECPKG_FLAG_ACCEPT_WIN32_NAME, "SECPKG_FLAG_ACCEPT_WIN32_NAME",

"Accepts Win32 names" },

{ SECPKG_FLAG_STREAM, "SECPKG_FLAG_STREAM", "Supports stream

semantics" },

{ SECPKG_FLAG_NEGOTIABLE, "SECPKG_FLAG_NEGOTIABLE", "Can be used by

the negotiate package" },

{ SECPKG_FLAG_GSS_COMPATIBLE, "SECPKG_FLAG_GSS_COMPATIBLE", "GSS

Compatibility Available" },

{ SECPKG_FLAG_LOGON, "SECPKG_FLAG_LOGON", "Supports common

LsaLogonUser" },

{ SECPKG_FLAG_ASCII_BUFFERS, "SECPKG_FLAG_ASCII_BUFFERS", "Token

Buffers are in ASCII" },

{ 0xffffffffL, "(fence)", "(fence)" }

};

 

 

 

void initSecLib( HINSTANCE& hSec )

{

PSecurityFunctionTable ( pSFT)( void );

 

hSec = LoadLibrary( "security.dll" );

pSFT = (PSecurityFunctionTable ( )( void )) GetProcAddress( hSec,

"InitSecurityInterfaceA" );

if ( pSFT == NULL )

{

exit( 1 );

}

 

pf = pSFT();

if ( pf == NULL )

{

exit( 1 );

}

 

SECURITY_STATUS rc;

DWORD numPacks = 0, i, j;

SecPkgInfo pPacks = NULL;

 

rc = (pf->EnumerateSecurityPackages)( &numPacks, &pPacks );

if ( rc != 0 )

{

exit( 1 );

}

 

for ( i = 0; i < numPacks; ++ i )

{

for ( j = 0; capNames[j].bits != 0xffffffffL; ++ j )

{

//if ( ( capNames[j].bits & pPacks.fCapabilities ) == capNames

[j].bits )

//printf( " %s (%s)\n", capNames[j].name, capNames

[j].comment );

}

}

 

if ( pPacks != NULL )

(pf->FreeContextBuffer)( pPacks );

}

 

 

 

int main( int argc, char argv[] )

{

 

int rc, port, addrlen;

HINSTANCE hSecLib;

CtxtHandle srvCtx;

 

bool haveToken;

SOCKET sock, s;

WSADATA wsadata;

PSERVENT pse;

SOCKADDR_IN addr;

HANDLE threadRet;

char buf[256];

DWORD bufsiz = sizeof buf;

 

if ( argc != 2 )

{

puts( "usage: server portnumber" );

return 1;

}

 

initSecLib( hSecLib );

 

rc = WSAStartup( 2, &wsadata );

wserr( rc, "WSAStartup" );

 

sock = socket( AF_INET, SOCK_STREAM, 0 );

if ( sock == INVALID_SOCKET )

wserr( 999, "socket" );

 

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = INADDR_ANY;

 

// try numeric protocol first

port = atoi( argv[1] );

if ( port > 0 && port < 32768 )

addr.sin_port = htons( (short) port );

else

{

pse = getservbyname( argv[1], "tcp" );

if ( pse == NULL )

wserr( 1, "getservbyname" );

addr.sin_port = pse->s_port;

}

 

rc = bind( sock, (SOCKADDR ) &addr, sizeof addr );

wserr( rc, "bind" );

 

rc = listen( sock, 2 );

wserr( rc, "listen" );

 

CredHandle cred;

 

while ( 1 )

{

addrlen = sizeof addr;

s = accept( sock, (SOCKADDR ) &addr, &addrlen );

if ( s == INVALID_SOCKET )

wserr( s, "accept" );

 

haveToken = auth( s, cred, srvCtx );

 

// now we talk to the client

printf( "haveToken = %s\n\n", haveToken? "true": "false" );

send( s, (const char ) &haveToken, sizeof haveToken, 0 );

 

// clean up

 

// Modified by Ganesh

/ (pf->DeleteSecurityContext)( &srvCtx );

(pf->FreeCredentialHandle)( &cred );

closesocket( s ); /

break;

}

 

int j;

puts("/n/n Should I start client implemenation within server ?: ");

scanf("%d",&j);

 

LPVOID threadParam = &srvCtx;

DWORD threadId;

 

//PROCESS_INFORMATION Pi;

//STARTUPINFO Si;

//HANDLE hTokenNew = NULL, hTokenDup = NULL;

 

//ZeroMemory( &Pi,sizeof(Pi));

//ZeroMemory( &Si, sizeof( STARTUPINFO ) );

//Si.cb = sizeof( STARTUPINFO );

// Si.lpDesktop = "winsta0\\default";

 

//GetUserName( buf, &bufsiz );

//rc = (pf->ImpersonateSecurityContext)( &srvCtx );

 

//rc = GetLastError();

//GetUserName( buf, &bufsiz );

 

//rc = CreateProcess("C:\\WINDOWS\\system32\\notepad.exe","C:\\WINDOWS

\\system32\\notepad.exe", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,

NULL, NULL, &Si, &Pi);

 

rc = GetLastError();

 

//threadRet = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)

Ganesh_Client_Impl, threadParam, 0, &threadId);

 

j = Ganesh_Client_Impl(srvCtx);

 

WaitForSingleObject(threadRet,INFINITE);

CloseHandle( threadRet );

 

FreeLibrary( hSecLib );

 

return 0;

}

  • Replies 3
  • Created
  • Last Reply

Popular Days

Guest Peter Foldes
Posted

Reply snipped for space

 

Kasparov

 

See the info here.

 

http://msdn.microsoft.com/en-us/library/aa374740(VS.85).aspx

 

--

Peter

 

Please Reply to Newsgroup for the benefit of others

Requests for assistance by email can not and will not be acknowledged.

 

"Kasparov" <ganesh.tambat@gmail.com> wrote in message

news:32196ca3-5b9e-4ea0-b0c7-fe7f23324300@x8g2000yqk.googlegroups.com...<span style="color:blue">

> Hi,

>

> We want the authentication to happen without providing credentials

> anywhere. For this we are planning to use Windows SSPI. Now the

> problem I am facing is once the authentication from client to server

> is successful, I want to use the

>

> security context created in server to connect back and authenticate to

> the client. I am trying to find out if this thing is possible with

> SSPI.

>

> For this I have written an application (prototype) with client side

> and server side. I am connecting to the server and after successfully

> authentication at the server side I try to connect back (to the server

> component on the client

>

> machine, running in the same process and thread as client) using the

> same procedure I used in the client side. My understanding is since I

> have impersonated I will be able to authenticate the same user again.

> But I always get the error</span>

Guest Kasparov
Posted

Well I couldnt make out anything from the msdn article. Could you

please elaborate ?

 

Thanks for your response.

 

Ganesh

 

On Dec 18, 9:52 pm, "Peter Foldes" <okf...@hotmail.com> wrote:<span style="color:blue">

> Reply snipped for space

>

> Kasparov

>

> See the info here.

>

> http://msdn.microsoft.com/en-us/library/aa374740(VS.85).aspx

>

> --

> Peter

>

> Please Reply to Newsgroup for the benefit of others

> Requests for assistance by email can not and will not be acknowledged.

>

> "Kasparov" <ganesh.tam...@gmail.com> wrote in message

>

> news:32196ca3-5b9e-4ea0-b0c7-fe7f23324300@x8g2000yqk.googlegroups.com...

><span style="color:green">

> > Hi,</span>

><span style="color:green">

> > We want the authentication to happen without providing credentials

> > anywhere. For this we are planning to use Windows SSPI. Now the

> > problem I am facing is once the authentication from client to server

> > is successful, I want to use the</span>

><span style="color:green">

> > security context created in server to connect back and authenticate to

> > the client. I am trying to find out if this thing is possible with

> > SSPI.</span>

><span style="color:green">

> > For this I have written an application (prototype) with client side

> > and server side. I am connecting to the server and after successfully

> > authentication at the server side I try to connect back (to the server

> > component on the client</span>

><span style="color:green">

> > machine, running in the same process and thread  as client) using the

> > same procedure I used in the client side. My understanding is since I

> > have impersonated I will be able to authenticate the same user again.

> > But I always get the error</span></span>

Guest Peter Foldes
Posted

Ganesh

 

This is not the newsgroup for this discussion on the issue. You might go and post it

over to the following newsgroup where this belongs.

 

news://msnews.microsoft.com/microsoft.publ...ration.security

 

--

Peter

 

Please Reply to Newsgroup for the benefit of others

Requests for assistance by email can not and will not be acknowledged.

 

"Kasparov" <ganesh.tambat@gmail.com> wrote in message

news:18835f35-20c9-42a3-ab8d-b692d6d35214@f20g2000yqg.googlegroups.com...

Well I couldnt make out anything from the msdn article. Could you

please elaborate ?

 

Thanks for your response.

 

Ganesh

 

On Dec 18, 9:52 pm, "Peter Foldes" <okf...@hotmail.com> wrote:<span style="color:blue">

> Reply snipped for space

>

> Kasparov

>

> See the info here.

>

> http://msdn.microsoft.com/en-us/library/aa374740(VS.85).aspx

>

> --

> Peter

>

> Please Reply to Newsgroup for the benefit of others

> Requests for assistance by email can not and will not be acknowledged.

>

> "Kasparov" <ganesh.tam...@gmail.com> wrote in message

>

> news:32196ca3-5b9e-4ea0-b0c7-fe7f23324300@x8g2000yqk.googlegroups.com...

></span>

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...