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

📄 ntlmssp.cpp

📁 VXWORKS源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    VxCritSec cs (m_mutex);    m_channelStatus.erase (cid);    }////////////////////////////////////////////////////////////////////////////// NTLMSSP::authTrailerCheck -- checks the auth-trailer of a received// PDU to ensure its requesting a authn-lvel we can cope with...//HRESULT NTLMSSP::authTrailerCheck    (    const RpcPdu&	pdu		// received PDU    )    {    // Make sure its NTLM protocol...    if (pdu.authTrailer()->authType != RPC_C_AUTHN_WINNT)	return MAKE_HRESULT (SEVERITY_ERROR,			     FACILITY_RPC,			     RPC_S_UNKNOWN_AUTHN_SERVICE);    // Make sure its CONNECT-level authn being asked for...    if (pdu.authTrailer()->authLevel != RPC_C_AUTHN_LEVEL_CONNECT)	return MAKE_HRESULT (SEVERITY_ERROR,			     FACILITY_RPC,			     RPC_S_UNSUPPORTED_AUTHN_LEVEL);    return S_OK;    }////////////////////////////////////////////////////////////////////////////// NTLMSSP::serverRequestValidate -- validate the auth-trailer on a// received RPC REQUEST PDU, which usually contains the 16-byte// 'token' and nothing else...//HRESULT NTLMSSP::serverRequestValidate    (    int			cid,		// channel ID    const RpcPdu&	reqPdu,		// rcvd REQUEST packet     RpcPdu&		reply		// reply to be sent    )    {    if (! reqPdu.isRequest ())	return E_FAIL;    // Is there an auth-trailer?    if (reqPdu.authLen ())	{	rpc_cn_auth_tlr_t 	 authTlrOut;	const rpc_cn_auth_tlr_t* pAuthTlrIn = reqPdu.authTrailer ();		// Look for familiar token in REQUEST packets..	if ((reqPdu.authLen () == TOKEN_LEN) &&	    (memcmp (pAuthTlrIn->authValue, s_token, TOKEN_LEN) == 0))	    {	    // Set outbound pre-amble fields...	    authTlrOut.authType = RPC_C_AUTHN_WINNT;	    authTlrOut.authLevel = RPC_C_AUTHN_LEVEL_CONNECT;	    authTlrOut.stubPadLen = 0;	    authTlrOut.reserved = 0;	    authTlrOut.key = pAuthTlrIn->key;	    // Copy 'token' into place...	    memcpy (authTlrOut.authValue,		    s_token,		    TOKEN_LEN);	    reply.authTrailerAppend (authTlrOut, TOKEN_LEN);	    }	}        return S_OK;    }////////////////////////////////////////////////////////////////////////////// serverBindValidate -- performs authentication checks on incoming// BIND (or ALTER-CONTEXT) PDUs received by a server connection. The// incoming PDU will contain the requesting machine and domain-name.//// Currently these fields are ignored, as we don't recognise NT// domains or do anything with them, so we simply respond by returning// a challenge. The difference between authenticating or not occurs// when the AUTH3 PDU arrives, which we process in the method// serverAuth3Validate().//// If we require authenticated connections, but we receive a BIND// without an auth-trailer, then it must also be rejected, as we// have been configured not to handle un-authenticated// connections. Conversely, if we don't *require* authentication, but// there is a request there in the packet, we still honour it by// adding a challenge, i.e. we move up to the client's level of authn,// but when his AUTH3 arrives we will simply accept it.//HRESULT NTLMSSP::serverBindValidate    (    int			cid,		// channel ID    const RpcPdu&	bindPdu,	// rcvd BIND packet    RpcPdu&		reply		// reply to be sent    )    {    TRACE_CALL;    // Only process BIND packets...    if (! (bindPdu.isBind ()))	return E_FAIL;    // Get current status...    VxCritSec cs (m_mutex);    HRESULT status = m_channelStatus [cid];        // Check what level we require...    switch (m_authnLevel)	{    case RPC_C_AUTHN_LEVEL_NONE:    case RPC_C_AUTHN_LEVEL_CONNECT:	// This case handles both NONE and CONNECT levels, but treats	// NONE as a special case when a received BIND PDU has an	// auth-trailer, in that we respond to it with a challenge	// (just like we do when we require authentication), but we	// effectively ignore the response in the next AUTH3 packet.	//	// CONNECT-level is supported if the user/application has	// registered some user/password combinations, so we *do*	// require some authentication to be present, so if there's	// none, we reject the PDU.	//	// For CONNECT level, we must defer the status-change (to S_OK	// from ACCESS-DENIED) to the time we get the response to our	// challenge, whereas for the NONE case we can simply let the	// connection continue at S_OK...	if (m_authnLevel == RPC_C_AUTHN_LEVEL_CONNECT)	    status = E_ACCESSDENIED;	else	    status = S_OK;	// Now check there is a trailer to process...	if (bindPdu.authLen ())	    {	    // Check the auth-trailer for correctness...	    HRESULT hr = authTrailerCheck (bindPdu);	    if (FAILED (hr))		status = hr;	    else		{		// Okay -- now we can go ahead and prepare the reply		// trailer for sending the challenge...    		rpc_cn_auth_tlr_t	authTlrOut;		size_t			lenTlr=0;		DREP			drep = bindPdu.drep ();		const rpc_cn_auth_tlr_t* pAuthTlrIn = bindPdu.authTrailer ();    		// Set outbound pre-amble fields...		authTlrOut.authType = RPC_C_AUTHN_WINNT;		authTlrOut.authLevel = RPC_C_AUTHN_LEVEL_CONNECT;		authTlrOut.stubPadLen = 0;		authTlrOut.reserved = 0;		authTlrOut.key = pAuthTlrIn->key;		// Find request and challenge structures in PDUs...		request* preq = (request*) pAuthTlrIn->authValue;		challenge* pch = (challenge*) authTlrOut.authValue;    		// Find received sequence-number		ULONG seq = preq->sequence;		ndr_make_right (seq, drep);    		// Normal client request -- fill in codename		strcpy (pch->ntlmssp, "NTLMSSP");		// Look for repeated sequence-number 3 in ALTER-CONTEXT PDUs. If		// its one of these then we can get away without putting an		// auth-trailer on the response, and continue...		if ((seq == 3) &&		    (bindPdu.packetType () == RPC_CN_PKT_ALTER_CONTEXT))		    status = S_OK;		else		    {		    // Increment sequence-number...		    pch->sequence = seq + 1;		    ndr_make_right (pch->sequence, drep);		    // Fill in fields and NDR them		    pch->magic1 = NTLM_MAGIC1;		    ndr_make_right (pch->magic1, drep);		    pch->magic2 = NTLM_MAGIC2_BIND;		    ndr_make_right (pch->magic2, drep);	    		    memcpy (pch->chal, s_defaultChallenge, 8);		    pch->mbz1 = 0;		    pch->mbz2 = 0;		    pch->mbz3 = 0;		    lenTlr = sizeof (NTLMSSP::challenge);		    reply.authTrailerAppend (authTlrOut, lenTlr);		    }		}	    }	break;	    default:	// Other levels we simply don't handle...	status = E_ACCESSDENIED;	}    m_channelStatus [cid] = status;    return status;    }////////////////////////////////////////////////////////////////////////////void NTLMSSP::ndrUnihdr (UNIHDR* puh, DREP drep)    {    ndr_make_right (puh->len, drep);    ndr_make_right (puh->max, drep);    ndr_make_right (puh->offset, drep);    }////////////////////////////////////////////////////////////////////////////// userAdd -- adds a user to the user-table, storing the 16-byte// LM-hash rather than the plain-text password...//	void NTLMSSP::userAdd (const char* userName, const char* userPasswd)    {    // Compute LM-hash of plain-text password...    unsigned char ntlmPasswd [16];       // Mangle the user-password into LanMan format (14 chars max, upper case)    memset (ntlmPasswd, '\0', sizeof (ntlmPasswd));    strncpy ((char*) ntlmPasswd, userPasswd, sizeof (ntlmPasswd));    ntlmPasswd [14] = '\0';    strupper (ntlmPasswd);       // Calculate the SMB (lanman) hash function of the password    NTLMSSP::lmhash ntlmHash;        memset (&ntlmHash, 0, sizeof (ntlmHash));    NTLMSSP::DES::encrypt16 (ntlmPasswd, ntlmHash.data);    // Save the hash into the user-table...    s_userTable [userName] = ntlmHash;        // Erase the hash and plain-text from the stack    memset (&ntlmHash, 0, 16);    memset (ntlmPasswd, 0, 16);    }////////////////////////////////////////////////////////////////////////////// encrypt -- encrypts the user's password-hash with the 8-byte// challenge and produces a 24-byte response...//void NTLMSSP::encrypt    (    const BYTE*		pwdHash,	// the password-hash    const BYTE*		challenge,	// the challenge    BYTE*		p24		// output    )    {    BYTE p21 [21];     memset (p21,'\0',21);    memcpy (p21, pwdHash, 16);        NTLMSSP::DES::encrypt24 (p21, const_cast<BYTE*> (challenge), p24);    }////////////////////////////////////////////////////////////////////////////// serverAuth3Validate -- this function is called when an AUTH3 PDU is// received at the server-side of a connection. This will happen when// the client has attempted to open an authenticated connection to// this machine, and we have sent it a challenge. What we get back is// the response to that challenge, which must match our calculated// response if we are bothered about authentication at all. If we// aren't bothered, (i.e. the authn-level is set to NONE) then we// simply let the AUTH3 PDU 'pass through' as if it were okay...//HRESULT NTLMSSP::serverAuth3Validate    (    int			cid,		// channel ID    const RpcPdu&	auth3Pdu	// rcvd AUTH3 packet    )    {    // Get current status...    VxCritSec cs (m_mutex);    HRESULT status = m_channelStatus [cid];        // Check how much authn we require...    switch (m_authnLevel)	{    case RPC_C_AUTHN_LEVEL_NONE:	// No authn required, we can let this one through...	status = S_OK;	break;	    case RPC_C_AUTHN_LEVEL_CONNECT:	// Connect-level is supported if the user/application has	// registered some user/password combinations, so we must	// continue processing. Check the auth-trailer for	// correctness...	status = authTrailerCheck (auth3Pdu);	if (SUCCEEDED (status))	    {	    // Check there is some data to deal with -- if we get to	    // here then we have received an AUTH3 packet and so there	    // *must* be some, if not we return an error-value and	    // effectively reject the packet...	    if (auth3Pdu.authLen () == 0)		status = E_ACCESSDENIED;	    else		{		// Find the start of the trailer data...		const rpc_cn_auth_tlr_t* pAuthTlr = auth3Pdu.authTrailer ();		response* phdr = (response*) pAuthTlr->authValue;		// NDR the important fields...		ndr_make_right (phdr->sequence, auth3Pdu.drep ());		ndrUnihdr (&phdr->domainName, auth3Pdu.drep ());		ndrUnihdr (&phdr->userName, auth3Pdu.drep ());		ndrUnihdr (&phdr->machineName, auth3Pdu.drep ());		ndr_make_right (phdr->magic2, auth3Pdu.drep ());    		int textBytes = phdr->domainName.len +				phdr->userName.len +				phdr->machineName.len;		USHORT* pwsText = (USHORT*) (phdr+1);		for (int t=0; t < textBytes / 2; ++t)		    ndr_make_right (pwsText [t], auth3Pdu.drep ());		// Extract user-name as ASCII string...		char userName [32];		int n = phdr->userName.len / 2;		pwsText += (phdr->domainName.len / 2);		for (int i=0; i < n; ++i)		    userName [i] = (char) pwsText [i];		userName [n] = 0;		// Find the 'response' data block in the PDU		BYTE* pdata = ((BYTE*) (phdr+1)) + textBytes;		// Calculate what the response should be...		BYTE calculatedResult[24];		memset (calculatedResult, 0, 24);		encrypt (s_userTable [userName].data,			 s_defaultChallenge,			 calculatedResult);		// Did the encrypted response come out right?		if (memcmp (pdata, calculatedResult, 24) != 0)		    {		    S_INFO (LOG_AUTH, "AUTH3:access denied:" << userName);		    status = E_ACCESSDENIED;		    }		else		    {		    S_INFO (LOG_AUTH, "AUTH3:access granted:" << userName);		    status = S_OK;		    }		}	    }	break;	    case RPC_C_AUTHN_LEVEL_CALL:    case RPC_C_AUTHN_LEVEL_PKT:    case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:    case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:	// These levels are not supported...	status = MAKE_HRESULT (SEVERITY_ERROR,			       FACILITY_RPC,			       RPC_S_UNSUPPORTED_AUTHN_LEVEL);    case RPC_C_AUTHN_LEVEL_DEFAULT:    default:	// Unknown errors!	COM_ASSERT (0);	status = E_FAIL;	}    m_channelStatus [cid] = status;    return status;    }////////////////////////////////////////////////////////////////////////////// clientAuthnRequestAdd -- empty stub for now.//HRESULT NTLMSSP::clientAuthnRequestAdd    (    int 		channelId,    RpcPdu&		bindPdu    )    {    return S_OK;    }////////////////////////////////////////////////////////////////////////////// clientAuthnResponse -- empty stub for now.//HRESULT NTLMSSP::clientAuthnResponse    (    int 		channelId,    const RpcPdu&	bindAckPdu,    bool*		pbSendAuth3,    RpcPdu&		auth3Pdu    )    {    *pbSendAuth3 = false;    return S_OK;    }////////////////////////////////////////////////////////////////////////////// clientAuthn -- empty stub for now.//HRESULT NTLMSSP::clientAuthn    (    int 		channelId,    RpcPdu&		reqPdu    )    {    return S_OK;    }    

⌨️ 快捷键说明

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