📄 ntlmauth.cpp
字号:
if (PIDB_lookup(tPIHTTP.pResponseDB,PIDBTYPE_RFC822,KEY_HTTP_CONTENTTYPE,0)) \
PIDB_replace(tPIHTTP.pResponseDB,PIDBTYPE_RFC822,KEY_HTTP_CONTENTTYPE,0,0); \
if (PIDB_lookup(tPIHTTP.pResponseDB,PIDBTYPE_RFC822,KEY_HTTP_CONTENTLENGTH,0)) \
PIDB_replace(tPIHTTP.pResponseDB,PIDBTYPE_RFC822,KEY_HTTP_CONTENTLENGTH,0,0); \
if (PIDB_lookup(tPIHTTP.pResponseDB,PIDBTYPE_STRING,KEY_INT_OBJECTMAP,0)) \
PIDB_replace(tPIHTTP.pResponseDB,PIDBTYPE_STRING,KEY_INT_OBJECTMAP,0,0); \
if (PIDB_lookup(tPIHTTP.pResponseDB,PIDBTYPE_STRING,KEY_INT_AUTHENTICATIONREALM,0)) \
PIDB_replace(tPIHTTP.pResponseDB,PIDBTYPE_STRING,KEY_INT_AUTHENTICATIONREALM,0,0); \
if (PIDB_lookup(tPIHTTP.pResponseDB,PIDBTYPE_STRING,KEY_INT_AUTHTYPE,0)) \
PIDB_replace(tPIHTTP.pResponseDB,PIDBTYPE_STRING,KEY_INT_AUTHTYPE,0,0); \
PIDB_replace(tPIHTTP.pRequestDB,PIDBTYPE_OPAQUE,KEY_HTTP_METHOD,(void *)MD_GET,0); \
PIDB_replace(tPIHTTP.pRequestDB,PIDBTYPE_STRING,KEY_HTTP_METHOD, \
(void *)MD_NAME_GET,0); \
iConvState++; \
PIDB_replace(tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, pfkConvState, \
(void *)iConvState, PIDBFLAG_FASTKEY ); \
return INT_REDIRECT;
if ( iPhase != PH_CHECKAUTH ) { return PIAPI_ERROR; };
/* ---
Get the realm
--- */
const char *szRealm = (const char *)PIDB_lookup( tPIHTTP.pResponseDB, PIDBTYPE_STRING,
KEY_INT_AUTHENTICATIONREALM, 0 );
if ( !szRealm || strcmp( szRealm, sRealm ) )
{
/* ---
Not for this handler to authenticate
--- */
return PIAPI_CONTINUE;
};
/*
** This realm applies. Set the authentication type to 'NTLM'
*/
PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_STRING, KEY_INT_AUTHTYPE,
NTLM_AUTH_TYPE, 0 );
SECURITY_STATUS ss;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuff;
ULONG ContextAttributes;
int Flags = ISC_REQ_DELEGATE | ISC_REQ_CONNECTION;
/*
** Get browser authentication string
*/
const char *pAuthenticate = (const char *)PIDB_lookup(
tPIHTTP.pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_AUTHORIZATION, 0 );
/*
** Retrieve conversation state ...
*/
iConvState = (int)PIDB_lookup( tPIHTTP.pConnectionDB,
PIDBTYPE_OPAQUE, pfkConvState, PIDBFLAG_FASTKEY );
/*
** ... This could not happen! It seems to be a new conversation
** but we still have a context handle.
*/
if (( iConvState == CS_HTTP_CHALLENGE ) && _fHaveCtxtHandle )
{
SECURITY_STATUS ss;
ss = g_pFuncs->DeleteSecurityContext( &_hctxt );
if ( !SEC_SUCCESS(ss) )
{
HTTPCore_logError( &tPIHTTP,
"NtlmAuth: SSPI error no %Xh in 'DeleteSecurityContext'.", ss );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
}
else
{
_fHaveCtxtHandle = FALSE;
};
};
/*
** Another authentication method for this Realm? We should finish here!
*/
if ( pAuthenticate && strncmp( pAuthenticate, "NTLM ", 5 ))
{
ResetConversation( &tPIHTTP );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_UNAUTHORIZED );
};
/*
** Workaround since MSIE makes a new connection after the 1st phase
*/
if (( iConvState == CS_HTTP_CHALLENGE) && pAuthenticate )
{
iConvState = CS_NTLM_CHALLENGE;
};
/*
** Handle the three conversation phases
*/
switch ( iConvState ) {
case CS_HTTP_CHALLENGE:
{
PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_RFC822,
KEY_HTTP_WWW_AUTHENTICATE, NTLM_AUTH_TYPE, 0 );
/* ---
Redirect because of authentication failure
--- */
HANDLE_REDIR;
}
case CS_NTLM_CHALLENGE:
{
/*
** Check authentication string
*/
if ( !pAuthenticate || strncmp( pAuthenticate, "NTLM ", 5 ))
{
ResetConversation( &tPIHTTP );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
// Prepare the output buffer - Note the server is expecting the client's
// negotiation packet on the first call
DWORD nLen;
uudecode( pAuthenticate + 5, g_pInBuf, &nLen );
//--------------------------------------------------------------------
// Prepare input and output buffers
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.cbBuffer = g_cbMaxToken;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = g_pOutBuf;
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
InSecBuff.cbBuffer = nLen;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = g_pInBuf;
ss = g_pFuncs->AcceptSecurityContext (
&_hcred,
NULL,
&InBuffDesc,
Flags,
SECURITY_NATIVE_DREP,
&_hctxt,
&OutBuffDesc,
&ContextAttributes,
&Lifetime
);
if ( !SEC_SUCCESS(ss) )
{
if ( SEC_E_INVALID_TOKEN == ss )
{
ResetConversation( &tPIHTTP );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_UNAUTHORIZED );
}
else
{
HANDLE_ERROR( ss, "AcceptSecurityContext" );
}
};
_fHaveCtxtHandle = TRUE;
//--------------------------------------------------------------------
// Complete token -- if needed
if (( SEC_I_COMPLETE_NEEDED == ss ) || ( SEC_I_COMPLETE_AND_CONTINUE == ss ))
{
if ( g_pFuncs->CompleteAuthToken )
{
ss = g_pFuncs->CompleteAuthToken( &_hctxt, &OutBuffDesc );
if ( !SEC_SUCCESS(ss) )
{
HANDLE_ERROR( ss, "CompleteAuthToken" );
};
}
else
{
HANDLE_ERROR( 0, "CompleteAuthToken not supported." );
};
};
char *pszAuth = (char *)PIUtil_malloc( g_cbMaxToken*2 );
char *pszTmp = (char *)PIUtil_malloc( g_cbMaxToken*2 );
if ( pszAuth && pszTmp )
{
uuencode( g_pOutBuf, OutSecBuff.cbBuffer, pszTmp );
sprintf( pszAuth, "NTLM %s", pszTmp );
PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_RFC822,
KEY_HTTP_WWW_AUTHENTICATE, pszAuth, 0 );
PIUtil_free( pszTmp );
PIUtil_free( pszAuth );
};
/* ---
Redirect because of authentication failure
--- */
HANDLE_REDIR;
}
case CS_NTLM_RESPONSE:
{
/*
** Check authentication string
*/
if ( !pAuthenticate || strncmp( pAuthenticate, "NTLM ", 5 ))
{
ResetConversation( &tPIHTTP );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
DWORD nLen;
uudecode( pAuthenticate + 5, g_pInBuf, &nLen );
//--------------------------------------------------------------------
// Prepare input and output buffers
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.cbBuffer = g_cbMaxToken;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = g_pOutBuf;
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
InSecBuff.cbBuffer = nLen;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = g_pInBuf;
ss = g_pFuncs->AcceptSecurityContext (
&_hcred,
&_hctxt,
&InBuffDesc,
Flags,
SECURITY_NATIVE_DREP,
&_hctxt,
&OutBuffDesc,
&ContextAttributes,
&Lifetime
);
if ( !SEC_SUCCESS(ss) )
{
if ( SEC_E_LOGON_DENIED == ss )
{
ResetConversation( &tPIHTTP );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_UNAUTHORIZED );
}
else
{
HANDLE_ERROR( ss, "AcceptSecurityContext" );
}
};
//--------------------------------------------------------------------
// Complete token -- if needed
if (( SEC_I_COMPLETE_NEEDED == ss ) || ( SEC_I_COMPLETE_AND_CONTINUE == ss ))
{
if ( g_pFuncs->CompleteAuthToken )
{
ss = g_pFuncs->CompleteAuthToken( &_hctxt, &OutBuffDesc );
if ( !SEC_SUCCESS(ss) )
{
HANDLE_ERROR( ss, "CompleteAuthToken" );
};
}
else
{
HANDLE_ERROR( 0, "CompleteAuthToken not supported." );
};
};
/*
** Impersonate Security Context
*/
ss = g_pFuncs->ImpersonateSecurityContext( &_hctxt );
if ( !SEC_SUCCESS(ss) )
{
HANDLE_ERROR( ss, "ImpersonateSecurityContext" );
};
/*
** Get User Name from Security Context
*/
SecPkgContext_Names Names;
ss = g_pFuncs->QueryContextAttributes( &_hctxt,
SECPKG_ATTR_NAMES, (void *)&Names );
if ( !SEC_SUCCESS(ss) )
{
HANDLE_ERROR( ss, "QueryContextAttributes" );
}
else
{
PIDB_replace(tPIHTTP.pResponseDB, PIDBTYPE_STRING,
KEY_INT_REMOTEUSER, Names.sUserName, 0);
};
ResetConversation( &tPIHTTP );
return PIAPI_COMPLETED;
};
default:
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
};
};
#endif //WIN32
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int NtlmAuth_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
#if WIN32
return HandlerBaseHTTP_constructor( pObj, PI_NEW( NtlmAuth( pObj,
iArgc, ppArgv ) ) );
#elif POSIX
(void)pObj;
(void)iArgc;
(void)ppArgv;
return PIAPI_COMPLETED;
#endif
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int NtlmAuth_execute( PIObject *pObj, int iArgc,
const char *ppArgv[] )
{
if ( !pObj ) return PIAPI_ERROR;
#if WIN32
return ((HandlerBaseHTTP *)PIObject_getUserData(pObj))->
Execute( iArgc, ppArgv );
#else
PIHTTP *pPIHTTP = (PIHTTP *)*ppArgv;
#define MSG "\
<BODY BGCOLOR=\"#FFFFFF\" BACKGROUND=\"/icons/Pi3Tile.gif\">\
<H2>Not supported</H2>\
The required handler is not supported on this operating system.</BODY>"
HTTPCore_sendGeneralHeaders( pPIHTTP );
HTTPCore_sendEntityHeaders( pPIHTTP, pPIHTTP->pResponseDB );
PIIOBuffer_write( pPIHTTP->pBuffer, MSG, sizeof(MSG)-1, PIIOBUF_NONE );
return PIAPI_ERROR;
#endif
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int NtlmAuth_destructor( PIObject *pObj, int,
const char *[] )
{
#if WIN32
delete (HandlerBaseHTTP *)PIObject_getUserData( pObj );
#endif
return PIAPI_COMPLETED;
}
#if 0
/*___+++CNF_BEGIN+++___*/
<Class>
Name NtlmAuthClass
Type LogicExtension
Library HTTP
OnClassLoad HandlerBaseHTTP_onClassLoad
Constructor NtlmAuth_constructor
CopyConstructor HandlerBaseHTTP_copyConstructor
Destructor NtlmAuth_destructor
Execute NtlmAuth_execute
</Class>
<Object>
Name NtlmAuth
Class NtlmAuthClass
</Object>
/*___+++CNF_END+++___*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -