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

📄 casisapi.cpp

📁 cas 客户端文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
Developer: Jim Klopfenstein				Date: 12/17/02
Name: CASIsapi.cpp

Function: ISAPI filter to provide CAS client functionality on IIS

*Change Log*
Developer:		Date:		Comments
Alan Walsh		12/20/02 	Started using basic string class instead of char* in some places
							in order to eliminate use of unsafe strX functions (e.g. strcat)
Alan Walsh		12/20/02 	Added support for IUCAS appcode (e.g. cassvc="MY") in querystring
Alan Walsh		01/03/03	Added calls to CryptDestroyKey and CryptReleaseContext in destructor
Jim K			01/28/03	Made string comparison in DoesAuthApply case-insensitive
Jim K			01/28/03	In InitEncryption, add second CryptAcquireContext if first fails
Jim K			01/28/03	In OnAuthComplete, replace all "goto authcontinues" with
							"return SF_STATUS_REQ_ERROR" to avoid race condition
Jim K			01/30/03	Back off from basic string class, but replace strcpy with
							safestrcpy and strcat with safestrcat
Jim K			01/30/03	Remove dependencies on MFC wrapper class
Jim K			01/30/03	New bInit variable traps initialization success/failure;
							custom HTML page is returned for all access after failure
Jim K			02/05/03	Added event logging
Jim K			02/07/03	Remove ticket parameter from query string before redirect
Jim K			02/12/03	Added "excludeFromStartOfURL" to work around ColdFusion MX bug
Jim K			02/12/03	Added bSuccessful check in Init to catch malformed XML
Jim K			03/10/03	Added secure cookie, requiresSSL parameter and checks for it
Jim K			04/02/03	Handle CRLF as line break in response file (as well as just LF)
Jim K			04/28/03	Redirect via HTTP 307 return code on HTTP 1.1 POSTs
*/

#include "stdafx.h"
#include <httpfilt.h>
#include <wincrypt.h>
#include <time.h>
#include "C:\Program Files\MSXML 4.0\inc\msxml2.h"
#include "CasIsapiMsg.h"

static char* pValidateURL;
static char* pLoginURL;
static char* pAppParamName;
static char* pServiceParamName;
static char* pTicketParamName;
static char* pTicketParamSearchValue;
static char* pAppCode;
static int cookieTimeout;
static long resolveTimeout;
static long connectTimeout;
static long sendTimeout;
static long receiveTimeout;
static char* pEncryptionPassword;
static char* pSecurityTriggerFile;
static size_t lenTriggerFile;
static char* pExcludeFromStartOfURL = NULL;

static bool InitEncryption();
static char* decryptCookie(char* pCypherText);
static char* safestrcat(char* to,const char* from,size_t len);
static char* safestrcpy(char* to,const char* from,size_t len);
static int str2int(char* instr);
static long str2long(char* instr);
static void hexEncode(BYTE* inBytes,DWORD len,char* outBuf);
static void hexEncodeInPlace(BYTE* inBytes,DWORD len);
static void hexDecode(char* inBuf,BYTE* outBuf);
static DWORD encryptLength(char* pPlainText);
static bool encryptCookie(char* pPlainText,DWORD encryptLen);
static bool AddEventSource();
static void ReportInitError(char* szMsg);
static void ReportInitSuccess();
static void ReportRedirect(char* szMsg);
static void ReportValidation(char* szMsg1,char* szMsg2);
static void ReportCookieAuthentication(char* szMsg1,char* szMsg2);
static void ReportApplyDecision(char* szMsg1,char* szMsg2,char* szMsg3);

//CryptoAPI elements

static HCRYPTPROV hProv = 0;
static HCRYPTKEY hKey = 0;
static bool bInit = true;
static bool bSecure = true;
static char* pFailReason = NULL;
const char* pConfigError = "Error in configuration file";
const char* pEventLogError = "Error configuring event log";
const char* pXMLHTTPError = "Error instantiating XMLHTTP object";
const char* pMissingConfigParameter = "Configuration parameter missing";
const char* pEncryptError = "Error initializing encryption";

static char* ConfigValueHelper(wchar_t* paramName,IXMLDOMDocument* pXmlDoc)
{
	IXMLDOMNode *pResultNode;
	IXMLDOMElement* pDomElement;
	char* pszReturn;
	size_t len;
	BSTR bstrText;

	if (FAILED(pXmlDoc->get_documentElement(&pDomElement))) {return NULL;}
	if (FAILED(pDomElement->selectSingleNode(paramName,&pResultNode)))
	{
		pDomElement->Release();
		return NULL;
	}
	if (pResultNode == NULL)
		return NULL;
	if (FAILED(pDomElement->Release())) {return NULL;}
	if (FAILED(pResultNode->get_text(&bstrText))) {return NULL;}
	len = wcslen(bstrText) + 1;
	if (NULL == (pszReturn=(char*)malloc(len))) {return NULL;}
	wcstombs(pszReturn,bstrText,len);
	SysFreeString(bstrText);
	if (FAILED(pResultNode->Release())) {return NULL;}
	return pszReturn; 
}

static void Init()
{
	VARIANT_BOOL bSuccessful;
	VARIANT xmlSource;
	char* pTemp;
	IXMLDOMDocument* pXmlDoc;
	IServerXMLHTTPRequest2 *pRequest;
	size_t alloclen;

	if (!AddEventSource())
	{
		bInit = false;
		return;
	}
	pFailReason = (char*)pXMLHTTPError;
	if (FAILED(CoCreateInstance(CLSID_ServerXMLHTTP40,NULL,CLSCTX_INPROC_SERVER,IID_IServerXMLHTTPRequest,(LPVOID*)&pRequest)))
	{
		bInit = false;
		return;
	}
	pRequest->Release();
	pFailReason = (char*)pConfigError;
	if (FAILED(CoCreateInstance(CLSID_DOMDocument,NULL,CLSCTX_INPROC_SERVER,IID_IXMLDOMDocument,(LPVOID*)&pXmlDoc))) {
		bInit = false;
		return;
	}
	if (NULL == (xmlSource.bstrVal=SysAllocString(L"casisapi.config")))
	{
		bInit = false;
		pXmlDoc->Release();
		return;
	}
	xmlSource.vt = VT_BSTR;
	if (FAILED(pXmlDoc->load(xmlSource,&bSuccessful)))
	{
		bInit = false;
		pXmlDoc->Release();
		pXmlDoc = NULL;
		SysFreeString(xmlSource.bstrVal);
		return;
	}
	SysFreeString(xmlSource.bstrVal);
	if (!bSuccessful) {bInit=false; return; }
	pFailReason = (char*)pMissingConfigParameter;
	if (NULL != (pTemp=ConfigValueHelper(L"httpsRequired",pXmlDoc)))
	{
		if (!stricmp(pTemp,"no"))
			bSecure = false;
		free(pTemp);
	}
	if (NULL == (pValidateURL=ConfigValueHelper(L"validation/URL",pXmlDoc))) {bInit = false; return; }
	if (NULL == (pLoginURL=ConfigValueHelper(L"loginURL",pXmlDoc))) {bInit = false; return; }
	if (NULL == (pAppParamName=ConfigValueHelper(L"appParamName",pXmlDoc))) {bInit = false; return; }
	if (NULL == (pServiceParamName=ConfigValueHelper(L"serviceParamName",pXmlDoc))) {bInit = false; return; }
	if (NULL == (pTicketParamName=ConfigValueHelper(L"ticketParamName",pXmlDoc))) {bInit = false; return; }
	alloclen = strlen(pTicketParamName) + 2;
	pTicketParamSearchValue=(char*)malloc(alloclen);
	if (NULL == (pAppCode=ConfigValueHelper(L"appCode",pXmlDoc))) {bInit = false; return; }
	safestrcpy(pTicketParamSearchValue,pTicketParamName,alloclen);
	safestrcat(pTicketParamSearchValue,"=",alloclen);
	pExcludeFromStartOfURL = ConfigValueHelper(L"excludeFromStartOfURL",pXmlDoc);
	if (NULL != (pTemp=ConfigValueHelper(L"cookieTimeout",pXmlDoc)))
	{
		cookieTimeout = str2int(pTemp);
		free(pTemp);
	}
	if (NULL != (pTemp=ConfigValueHelper(L"validation/resolveTimeout",pXmlDoc)))
	{
		resolveTimeout = str2long(pTemp);
		free(pTemp);
	}
	if (NULL != (pTemp=ConfigValueHelper(L"validation/connectTimeout",pXmlDoc)))
	{
		connectTimeout = str2long(pTemp);
		free(pTemp);
	}
	if (NULL != (pTemp=ConfigValueHelper(L"validation/sendTimeout",pXmlDoc)))
	{
		sendTimeout = str2long(pTemp);
		free(pTemp);
	}
	if (NULL != (pTemp=ConfigValueHelper(L"validation/receiveTimeout",pXmlDoc)))
	{
		receiveTimeout = str2long(pTemp);
		free(pTemp);
	}
	if (NULL == (pEncryptionPassword=ConfigValueHelper(L"encryptionPassword",pXmlDoc))) {bInit = false; return; }
	if (NULL == (pSecurityTriggerFile=ConfigValueHelper(L"securityTriggerFile",pXmlDoc))) {bInit = false; return; }
	lenTriggerFile = strlen(pSecurityTriggerFile);
	pFailReason = (char*)pEncryptError;
	if (!InitEncryption()) {bInit = false;};
	pFailReason = NULL;
}

extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
	pVer->dwFilterVersion = HTTP_FILTER_REVISION;
	pVer->dwFlags = SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT | SF_NOTIFY_AUTH_COMPLETE;
	pVer->lpszFilterDesc[0] = '\0';
	Init();
	if (bInit)
		ReportInitSuccess();
	else if (pFailReason)
		ReportInitError(pFailReason);
	else
	{
		pFailReason = (char*)pEventLogError;
	}

	return TRUE;
}	

#define STACK_ALLOC_SERVER_VARIABLE(variable,target) \
	size = 0; \
	if (!pCtxt->GetServerVariable(pCtxt,variable,NULL,(LPDWORD)&size)) \
	{ \
		dwLastError	= GetLastError(); \
		if (122 == dwLastError) \
		{ \
            if (NULL != (target = (char*)_alloca(size))) \
				if (!pCtxt->GetServerVariable(pCtxt,variable,target,(LPDWORD)&size)) \
					target = NULL; \
		} \
		else \
			target = NULL; \
	} 

#define STACK_ALLOC_HEADER(header,target) \
	size = 0; \
	if (!(*pParms->GetHeader)(pCtxt,header,NULL,&size)) \
	{ \
		dwLastError	= GetLastError(); \
		if (122 == dwLastError) \
		{ \
            if (NULL != (target = (char*)_alloca(size))) \
				if (!(*pParms->GetHeader)(pCtxt,header,target,&size)) \
					target = NULL; \
		} \
		else \
			target = NULL; \
	} 

static char *CheckCookie(char* pCookie,char* pRemoteAddr)
{
	char *s;
	char *pCookieRemoteAddr;
	time_t timer,cookieTime;

	for (s=pCookie; *s && *s != '|'; s++) ;
	if (*s = '\0') {return NULL;}
	*(s++) = '\0';
	pCookieRemoteAddr = s;
	for (; *s && *s != '|'; s++) ;
	*(s++) = '\0';
	if (strcmp(pRemoteAddr,pCookieRemoteAddr)) {return NULL;}
	hexDecode(s,(BYTE*)&cookieTime);
	if (&cookieTime == 0) {return NULL;}
	time(&timer);
	if ((cookieTime >= timer) || ((timer - cookieTime) > cookieTimeout)) {return NULL;}
	return pCookie;
}

static bool DoesAuthApplyToFile(PHTTP_FILTER_CONTEXT pCtxt)
{
	DWORD size;
	BOOL authOkay = false;
	DWORD dwLastError;
	char *pPathTranslated;
	char *pScriptName;
	char *pFileSpec;
	char *s;
	char *pLastSlash;
	size_t lenPathTranslated;
	size_t lenScriptName;
	size_t alloclen;

	STACK_ALLOC_SERVER_VARIABLE("PATH_TRANSLATED",pPathTranslated);
	if (pPathTranslated == NULL) {return true;}
	lenPathTranslated = strlen(pPathTranslated);
	STACK_ALLOC_SERVER_VARIABLE("SCRIPT_NAME",pScriptName);
	if (pScriptName == NULL) {return true;}
	lenScriptName = strlen(pScriptName);

	for (s=pPathTranslated; *s; s++) ;
	for (--s; (s >=pPathTranslated) && (*s != '.') && (*s != '\\'); s--) ;
	if (*s == '.')
	{
		alloclen = lenPathTranslated+lenTriggerFile+1;
		pFileSpec = (char*)_alloca(alloclen);
		if (pFileSpec == NULL) {return true;}
		safestrcpy(pFileSpec,pPathTranslated,alloclen);
	}
	else
	{
		for (s=pScriptName; s && *s; s++)
			if (*s == '/')
				*s = '\\';
//	s = (lenPathTranslated > lenScriptName) ? &pPathTranslated[lenPathTranslated-lenScriptName] : "";
		alloclen = lenPathTranslated+lenScriptName+lenTriggerFile+1;
		pFileSpec = (char*)_alloca(alloclen);
		if (pFileSpec == NULL) {return true;}
		safestrcpy(pFileSpec,pPathTranslated,alloclen);
		safestrcat(pFileSpec,pScriptName,alloclen);
	}
	for (s=pFileSpec;s && *s; s++) 
		if (*s == '\\') {pLastSlash = s;}
	*(++pLastSlash) = '\0';
	safestrcat(pFileSpec,pSecurityTriggerFile,alloclen);
//	ReportApplyDecision(pPathTranslated,pScriptName,pFileSpec);

	HANDLE hFile = CreateFile(pFileSpec,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if (INVALID_HANDLE_VALUE == hFile) {return false;}
	CloseHandle(hFile);
	return true;
}

extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pCtxt,
	DWORD dwNotificationType, LPVOID pvNotification)
{
	PHTTP_FILTER_AUTH_COMPLETE_INFO pParms = (PHTTP_FILTER_AUTH_COMPLETE_INFO)pvNotification;
	DWORD size;
	BOOL authOkay = false;
	DWORD dwLastError;
	char *pRemoteAddr;
	char *pCookie;
	char *pQueryString;
	char *pURL;
	char *pServerName;
	char *pServerPort;
	char *pRequestMethod;
	char *pServerProtocol;
	char *pHTTPS;
	const char* pHeaders1 = "Content-Type: text/html";
	const char* pHeaders1a = "Location: ";
	const char* pHeaders2 = "\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nExpires: Fri, 01-Jan-1970 00:00:01	GMT\r\n\r\n";
	const char* pBoilerplate1 = "<html><body><h3>Authentication Filter Error</h3>\r\n<p>";
	const char* pBoilerplate2 = "</p></body></html>";

	if (!bInit)
	{
		char *pHeaders;
		DWORD writeLen;

		size_t alloclen = strlen(pHeaders1)+strlen(pHeaders2)+1;
		pHeaders = (char*)_alloca(alloclen);
		safestrcpy(pHeaders,pHeaders1,alloclen);
		safestrcat(pHeaders,pHeaders2,alloclen);
		pCtxt->AddResponseHeaders(pCtxt,pHeaders,0);
		pCtxt->ServerSupportFunction(pCtxt,SF_REQ_SEND_RESPONSE_HEADER,
			"200 OKAY",NULL,NULL);
		writeLen = (DWORD)strlen(pBoilerplate1);
		pCtxt->WriteClient(pCtxt,(LPVOID)pBoilerplate1,&writeLen,NULL);
		writeLen = (DWORD)strlen(pFailReason);
		pCtxt->WriteClient(pCtxt,(LPVOID)pFailReason,&writeLen,NULL);
		writeLen = (DWORD)strlen(pBoilerplate2);
		pCtxt->WriteClient(pCtxt,(LPVOID)pBoilerplate2,&writeLen,NULL);
		return SF_STATUS_REQ_FINISHED;
	}
	if (!DoesAuthApplyToFile(pCtxt)) {return SF_STATUS_REQ_NEXT_NOTIFICATION;}

	STACK_ALLOC_SERVER_VARIABLE("REMOTE_ADDR",pRemoteAddr)
		if (pRemoteAddr == NULL) {return SF_STATUS_REQ_ERROR;}

	STACK_ALLOC_HEADER("Cookie:",pCookie)

	// if request includes cookies
	if (pCookie)
	{
		char *s;
		char *t;
		if (s=strstr(pCookie,"UITSAUTH=")) // our cookie	is present
		{
			char* pOurCookie;
			char* pUserName;
			char* pPlainCookie;

			for (t=s+9; *t && *t != ';'; t++) ;
			*t = '\0';
			pOurCookie = s+9;
			pPlainCookie = decryptCookie(pOurCookie);
			if ((NULL != pPlainCookie) && (pUserName=CheckCookie(pPlainCookie,pRemoteAddr)))
			{
				STACK_ALLOC_HEADER("URL",pURL);
				if (pURL == NULL) {return SF_STATUS_REQ_ERROR;}
				ReportCookieAuthentication(pURL,pUserName);
				if (!(*pParms->SetHeader)(pCtxt,"user:",pUserName)) {return SF_STATUS_REQ_ERROR;}
				authOkay = true;
			}
		}
	}
	if (!authOkay)
	{
		STACK_ALLOC_SERVER_VARIABLE("QUERY_STRING",pQueryString)
		if (NULL == pQueryString) {
			return SF_STATUS_REQ_ERROR;
			}
		else
		{
			STACK_ALLOC_SERVER_VARIABLE("HTTPS",pHTTPS);
			if (pHTTPS == NULL) {return SF_STATUS_REQ_ERROR;}
			strcpy(pHTTPS,strcmp(pHTTPS,"on")? "" : "s");
			STACK_ALLOC_SERVER_VARIABLE("SERVER_NAME",pServerName);
			if (pServerName == NULL) {return SF_STATUS_REQ_ERROR;}
			STACK_ALLOC_SERVER_VARIABLE("SERVER_PORT",pServerPort);
			if (pServerPort == NULL) {return SF_STATUS_REQ_ERROR;}
			if (!strcmp(pServerPort,"80") && (pHTTPS[0] == '\0')) {pServerPort[0] = '\0';}
			if (!strcmp(pServerPort,"443") && (pHTTPS[0] == 's')) {pServerPort[0] = '\0';}
			if (strstr(pQueryString,pTicketParamSearchValue))
			{
				char* pValidateQuery;
				IServerXMLHTTPRequest2 *pRequest;
				HRESULT hr;
				time_t timer;
				size_t len;
				wchar_t* pWBuf;
				BSTR bMethod;
				BSTR bUrl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -