⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntlmauth.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
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 + -