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

📄 ssl.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			pbDecrypted = Buffers[1].pvBuffer;
			cbTrailer   = Buffers[2].cbBuffer;

#ifdef DEBUG
			// There was previously a bug in SSPI where it miscomputed
			// trailer length and an elaborate workaround was needed in the if block
			// below.  Bug has been fixed, leave DEBUGCHK as an extra check for future.
			if ((Buffers[2].BufferType == SECBUFFER_STREAM_TRAILER) && (Buffers[3].BufferType == SECBUFFER_EXTRA)) {
				DEBUGCHK(Buffers[2].cbBuffer < Buffers[3].cbBuffer);
			}
#endif

			if (Buffers[3].BufferType == SECBUFFER_EXTRA) {
				// Extra is effectively left over bytes - i.e. if we pass in 1000
				// bytes to decrypet and header=5 bytes, decrypt=100 bytes, and trailer=5 bytes,
				// then we have 1000-5-100-5=890 bytes extra - i.e. SSPI didn't 
				// modify these bytes and we need to call a decrypt again on them.
				// Just record this so that when we "clean up" the decrypted data in place, 
				// we know how much extra we have to carry with us into the next call.
				cbExtra = Buffers[3].cbBuffer;
				pbExtra = Buffers[3].pvBuffer;
				DEBUGCHK((cbExtra != 0) && (pbExtra != NULL));
			}
			else {
				cbExtra = 0;
				pbExtra = NULL;
			}
		}

		if (scRet == SEC_E_OK)  {
			// DecrypteMessage has decrypted some (not necessarily all) of the data
			// we have passed it.  Since all of this work is done in place, we have
			// to strip out the crypto header and trailer gunk that isn't relevant to
			// HTTP
			
			if (cbHeader) {
				// Get rid of header gunk by copying over non-header bytes.
				memmove(pvBuffer,(PSTR)pvBuffer+cbHeader,dwRemaining-cbHeader);
			}

			// Update counters.
			*pdwBytesDecryptedTotal += cbDecrypted;
			*pdwIgnore += cbHeader+cbTrailer;
			dwRemaining -= (cbDecrypted+cbHeader+cbTrailer);

			DEBUGCHK(dwRemaining == cbExtra);

			DEBUGCHK((int)dwRemaining >= 0);
			DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: DecryptMessage SEC_E_OK, bytes decrypted=%d, dwRemaining=%d,cbExtra=%d\r\n",
			                             cbDecrypted,dwRemaining,cbExtra));

			if (cbExtra) {
				// There is data that was not decrypted on this pass.  In this case,
				// "get rid of" the crypto trailer too (like header), and reset
				// the base pointer for another decrypt operation.
				PSTR pszEnd = (PSTR)pvBuffer+cbDecrypted;
				if (cbTrailer)
					memmove(pszEnd,pszEnd+cbTrailer,cbExtra);

				pvBuffer   = (PVOID) pszEnd;
				*pdwOffset = cbBuffer = cbExtra;
				continue;
			}
		}
		else if (scRet == SEC_I_RENEGOTIATE) {
			// SSL renogotiation.  This is typically (but not always) hit when the
			// Web Server has requested a client certificate from the web client.
			DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: DecryptMessage SEC_I_RENEGOTIATE\r\n"));

			if (m_fPerformedClientInitiatedRenegotiate) {
				// We only allow client to request one renegotiate per session.  We
				// do this to prevent denial of service attacks where client kept sending
				// a renegotiate every few seconds.
				DEBUGMSG(ZONE_ERROR,(L"HTTPD: Client has requested more than one SSL renegotiation, web server does not support this, failing request\r\n"));
				return E_FAIL;
			}

			if (! HandleSSLHandShake(TRUE))
				return E_FAIL;

			m_fPerformedClientInitiatedRenegotiate = TRUE;
			*pfCompletedRenegotiate = TRUE;
		
			// Recalculate lengths.
			*pdwIgnore  += cbHeader+cbTrailer;
			dwRemaining -= (cbHeader+cbTrailer);

			if (cbExtra) {
				// See comments in 'if (cbExtra)' block above...
				PSTR pszEnd = (PSTR)pvBuffer+cbDecrypted;
				if (cbTrailer)
					memmove(pszEnd,pszEnd+cbTrailer,cbExtra);

				pvBuffer   = (PVOID) pszEnd;
				*pdwOffset = cbBuffer = cbExtra;
				continue;
			}
			scRet = SEC_E_OK;
		}
		else {
			// To decrypt the current chunk, we need to read in Buffers[1].cbBuffer more data.
			DEBUGCHK(scRet == SEC_E_INCOMPLETE_MESSAGE);
			DEBUGCHK(Buffers[1].BufferType == SECBUFFER_MISSING);
			*pdwExtraRequired = Buffers[1].cbBuffer;
			DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: DecryptMessage SEC_E_INCOMPLETE_MESSAGE, *pdwExtraRequired=%d\r\n",*pdwExtraRequired));
		}
		
		*pdwOffset = dwLen - *pdwBytesDecryptedTotal - *pdwIgnore;
		break;
	}
	return scRet;
}

BOOL CHttpRequest::SendEncryptedData(PSTR pszBuf, DWORD dwLen, BOOL fCopyBuffer) {
	DEBUG_CODE_INIT;
	BOOL            fRet = FALSE;
	SecBuffer       Buffers[4];
	SecBufferDesc   Message;
	CHAR            szHeader[64];
	CHAR            szTrailer[64];
	SECURITY_STATUS scRet;
	DWORD           dwRemaining;
	DWORD           dwOffset = 0;
	CHAR            szStaticBuf[2048];
	PSTR            pszSendBuf = pszBuf;

	DEBUGCHK(sizeof(szHeader) >= m_SSLInfo.m_Sizes.cbHeader);
	DEBUGCHK(sizeof(szTrailer) >= m_SSLInfo.m_Sizes.cbTrailer);
	DEBUGCHK(m_fIsSecurePort && g_pVars->m_fSSL);

	Message.ulVersion = SECBUFFER_VERSION;
	Message.cBuffers = 4;
	Message.pBuffers = Buffers;

	Buffers[0].pvBuffer = szHeader;
	Buffers[0].cbBuffer = m_SSLInfo.m_Sizes.cbHeader;
	Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;

	Buffers[2].pvBuffer = szTrailer;
	Buffers[2].cbBuffer = m_SSLInfo.m_Sizes.cbTrailer;
	Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;

	Buffers[3].BufferType = SECBUFFER_EMPTY;

	dwRemaining = dwLen;

	if (fCopyBuffer) {
		if (dwLen <= sizeof(szStaticBuf)) {
			pszSendBuf = szStaticBuf;
		}
		else {
			if (! (pszSendBuf = MyRgAllocNZ(CHAR,dwLen)))
				myleave(1908);
		}
		memcpy(pszSendBuf,pszBuf,dwLen);
	}

	while (dwRemaining) {
		DWORD dwSend = min(dwRemaining,m_SSLInfo.m_Sizes.cbMaximumMessage);

		Buffers[1].pvBuffer   = pszSendBuf+dwOffset;
		Buffers[1].cbBuffer   = dwSend;
		Buffers[1].BufferType = SECBUFFER_DATA;

		// Note: Assuming nagling is turned on the header+trailer should NOT be sent
		// across in separate packets but along with body.
		scRet = g_pVars->m_SecurityInterface.EncryptMessage(&m_SSLInfo.m_hcred,0,&Message,0);
		if (scRet != SEC_E_OK && scRet != SEC_E_INCOMPLETE_MESSAGE)
			myleave(1909);

		if (SOCKET_ERROR == send(m_socket,(PSTR)Buffers[0].pvBuffer,Buffers[0].cbBuffer,0))
			myleave(1910);

		if (SOCKET_ERROR == send(m_socket,(PSTR)Buffers[1].pvBuffer,Buffers[1].cbBuffer,0))
			myleave(1911);

		if (SOCKET_ERROR == send(m_socket,(PSTR)Buffers[2].pvBuffer,Buffers[2].cbBuffer,0))
			myleave(1912);		

		dwOffset += dwSend;
		dwRemaining -= dwSend;
	}

	fRet = TRUE;
done:
	DEBUGMSG_ERR(ZONE_RESPONSE | ZONE_SSL,(L"HTTPD: SendEncryptedData failed, err = %d, GLE=0x%08x\r\n",err,GetLastError()));
	if (pszSendBuf != szStaticBuf && pszSendBuf != pszBuf) {
		DEBUGCHK(fCopyBuffer);
		MyFree(pszSendBuf);
	}
	return fRet;
}

//
//  CSSLUsers implementation functions
//
VOID
ReverseMemCopy(PUCHAR Dest, PUCHAR Source, ULONG Size) {
	PUCHAR  p;

	p = Dest + Size - 1;
	do {
		*p-- = *Source++;
	} while (p >= Dest);
}

// Called on web server initialization, reads SSL users into table from registry.
void CSSLUsers::InitializeSSLUsers(CReg *pSSLReg, FixedMemDescr *pUserMem) {
#if defined (DEBUG) || defined (_DEBUG)
	BYTE b[sizeof(CSSLUsers)] = {0};
	DEBUGCHK(0 == memcmp(b,this,sizeof(CSSLUsers)));
#endif
	CReg  rootReg((HKEY) (*pSSLReg),RK_USERS);

	if (! rootReg.IsOK())
		return;

	DWORD cUsers = rootReg.NumSubkeys();
	if (0 == cUsers)	
		return;

	for (DWORD i = 0; i < cUsers; i++) {
		CReg  userReg;
		WCHAR szUserName[MAX_PATH];
		DWORD cbUserName;  // size in bytes, not WCHARs

		if (! rootReg.EnumKey(szUserName,SVSUTIL_ARRLEN(szUserName)))
			continue;

		if (! userReg.Open(rootReg,szUserName)) {
			DEBUGCHK(0); // EnumKey shouldn't have suceeded if Opening can fail.
			continue;
		}

		DWORD cMappings = userReg.NumSubkeys();
		if (0 == cMappings)
			continue;

		cbUserName = (wcslen(szUserName)+1)*sizeof(WCHAR);

		for (DWORD j = 0; j < cMappings; j++) {
			CReg mapReg;
			WCHAR szUserMap[MAX_PATH];

			// open mapping registry key and read in its parameters
			if (! userReg.EnumKey(szUserMap,SVSUTIL_ARRLEN(szUserMap)))
				continue;

			if (! mapReg.Open(userReg,szUserMap)) {
				DEBUGCHK(0);
				continue;
			}

			WCHAR szIssuerCN[MAX_ISSUER_LEN];
			BYTE  bSerialNumber[MAX_SERIAL_NUMBER];
			DWORD cbIssuerCN     = sizeof(szIssuerCN);
			DWORD cbSerialNumber = sizeof(bSerialNumber);;

			if (! mapReg.IsOK()) {
				DEBUGCHK(0);
				continue;
			}

			if (ERROR_SUCCESS != RegQueryValueEx(mapReg, RV_SSL_ISSUER_CN, NULL, NULL, (LPBYTE)szIssuerCN, &cbIssuerCN))
				cbIssuerCN = 0;

			if (ERROR_SUCCESS != RegQueryValueEx(mapReg, RV_SSL_SERIAL_NUMBER, NULL, NULL, (LPBYTE)bSerialNumber, &cbSerialNumber))
				cbSerialNumber = 0;
			
			if ((cbIssuerCN == 0) && (cbSerialNumber == 0)) {
				DEBUGMSG(ZONE_SSL,(L"HTTPD: Initialize SSL skipping user %s's path %s, either issuer or serial number must be set\r\n",szUserName,szUserMap));
				continue;
			}

			SSLUserMap *pNew = (SSLUserMap *)svsutil_GetFixed(pUserMem);
			if (! pNew)
				return;

			pNew->pNext  = pUserMapHead;
			pUserMapHead = pNew;

			memset(pNew,0,sizeof(SSLUserMap));
			DWORD cbAlloc = cbUserName+cbIssuerCN+cbSerialNumber;

			if (NULL == (pNew->pBuffer = MyRgAllocNZ(BYTE,cbAlloc)))
				return;

			// write this mapping information to the buffer
			BYTE *pWrite = pNew->pBuffer;

			memcpy(pWrite,szUserName,cbUserName);
			pNew->szUserName = (WCHAR*)pWrite;
			pWrite += cbUserName;

			if (cbIssuerCN) {
				memcpy(pWrite,szIssuerCN,cbIssuerCN);
				pNew->szIssuerCN = (WCHAR*)pWrite;
				pWrite += cbIssuerCN;
			}

			pNew->cbSerialNumber = cbSerialNumber;
			if (cbSerialNumber) {
				// Serial number is in reverse byte order in cert.  Reverse it 
				// now so we can do memcmp's per request.
				ReverseMemCopy(pWrite,bSerialNumber,cbSerialNumber);
				pNew->pSerialNumber = pWrite;
				pWrite += cbSerialNumber;
			}
			DEBUGCHK(pWrite == (pNew->pBuffer + cbAlloc));
		}
	}
}

// Called once an SSL client certificate has been received, uses the cert's serial number 
// and/or issuer to see if it maps to a web server "pseudo-user".
WCHAR * CSSLUsers::MapUser(BYTE *pSerialNumber, DWORD cbSerialNumber, WCHAR *szIssuerCN) {
	SSLUserMap *pTrav = pUserMapHead;

	while (pTrav) {
		// For the SSLUserMap, the serial number and/or issuer is present.  If 
		// both members are set the certificate needs to match both of them, otherwise
		// we're fine if we only match the one present field.
		DEBUGCHK(pTrav->szUserName && ((pTrav->cbSerialNumber && pTrav->pSerialNumber) || pTrav->szIssuerCN));
		
		if (pTrav->cbSerialNumber && ((pTrav->cbSerialNumber != cbSerialNumber) || 
		   (0 != memcmp(pTrav->pSerialNumber,pSerialNumber,cbSerialNumber)))) 
		{
			// User mapping had a serial number but it didn't match passed in certificate.
			pTrav = pTrav->pNext;
		  	continue; 
		}

		if (pTrav->szIssuerCN && (0 != wcscmp(szIssuerCN,pTrav->szIssuerCN))) {
			// User mapping had IssuerCN but it didn't match passed in certificate.
			pTrav = pTrav->pNext;
			continue;
		}

		return pTrav->szUserName;
	}
	return NULL;
}

// Called once an SSL client certificate has been received, tries to map
// certificate to user.
BOOL CHttpRequest::HandleSSLClientCertCheck(void) {
	WCHAR szIssuer[2000];
	WCHAR *szUser;

	// the virtual root must request a mapping explicitly.
	if (! (GetPerms() & HSE_URL_FLAGS_MAP_CERT))
		return FALSE;

	// don't have SSL info.
	if (!m_fHandleSSL || !m_SSLInfo.m_pClientCertContext || 
	    !m_SSLInfo.m_pClientCertContext->pCertInfo       || 
	    !m_SSLInfo.m_pClientCertContext->pCertInfo->SerialNumber.pbData)
		return FALSE;

	int  cbSerialNum    = m_SSLInfo.m_pClientCertContext->pCertInfo->SerialNumber.cbData;
	BYTE *pSerialNumber = m_SSLInfo.m_pClientCertContext->pCertInfo->SerialNumber.pbData;

	if (m_wszRemoteUser == NULL) {
		if (! pCertGetNameStringW(m_SSLInfo.m_pClientCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,CERT_NAME_ISSUER_FLAG,0,szIssuer,sizeof(szIssuer)))
			return FALSE;

		if (NULL == (szUser = g_pVars->m_SSLUsers.MapUser(pSerialNumber,cbSerialNum,szIssuer)))
			return FALSE;

		m_wszRemoteUser = MySzDupW(szUser);
	}
	m_AuthLevelGranted = DeterminePermissionGranted(GetUserList(),m_AuthLevelGranted);

	DEBUGMSG(ZONE_SSL_VERBOSE,(L"HTTPD: SSL Client cert mapping retrieves user=<<%s>>, auth granted = %d\r\n",szUser,m_AuthLevelGranted));
	return TRUE;
}

⌨️ 快捷键说明

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