minor refactoring; check server challenge for NTLMv2 support

This commit is contained in:
Günter Obiltschnig
2019-03-19 08:07:41 +01:00
parent 9422825790
commit ad7cad8d64

View File

@@ -17,6 +17,7 @@
#include "Poco/Net/HTTPAuthenticationParams.h" #include "Poco/Net/HTTPAuthenticationParams.h"
#include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h" #include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/DateTime.h" #include "Poco/DateTime.h"
#include "Poco/NumberFormatter.h" #include "Poco/NumberFormatter.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
@@ -115,25 +116,19 @@ std::string HTTPNTLMCredentials::createNTLMMessage(const std::string& responseAu
std::string username; std::string username;
splitUsername(_username, username, negotiateMsg.domain); splitUsername(_username, username, negotiateMsg.domain);
std::vector<unsigned char> negotiateBuf = NTLMCredentials::formatNegotiateMessage(negotiateMsg); std::vector<unsigned char> negotiateBuf = NTLMCredentials::formatNegotiateMessage(negotiateMsg);
return toBase64(negotiateBuf);
std::ostringstream ostr;
Poco::Base64Encoder base64(ostr);
base64.rdbuf()->setLineLength(0);
base64.write(reinterpret_cast<const char*>(&negotiateBuf[0]), negotiateBuf.size());
base64.close();
return ostr.str();
} }
else else
{ {
Poco::MemoryInputStream istr(responseAuthParams.data(), responseAuthParams.size()); std::vector<unsigned char> buffer = fromBase64(responseAuthParams);
Poco::Base64Decoder debase64(istr); NTLMCredentials::ChallengeMessage challengeMsg;
std::vector<unsigned char> buffer(responseAuthParams.size()); if (NTLMCredentials::parseChallengeMessage(&buffer[0], buffer.size(), challengeMsg))
debase64.read(reinterpret_cast<char*>(&buffer[0]), buffer.size());
std::size_t size = static_cast<std::size_t>(debase64.gcount());
Poco::Net::NTLMCredentials::ChallengeMessage challengeMsg;
if (NTLMCredentials::parseChallengeMessage(&buffer[0], size, challengeMsg))
{ {
if ((challengeMsg.flags & NTLMCredentials::NTLM_FLAG_NEGOTIATE_NTLM2_KEY) == 0)
{
throw HTTPException("Proxy does not support NTLMv2 authentication");
}
std::string username; std::string username;
std::string domain; std::string domain;
splitUsername(_username, username, domain); splitUsername(_username, username, domain);
@@ -143,22 +138,18 @@ std::string HTTPNTLMCredentials::createNTLMMessage(const std::string& responseAu
authenticateMsg.target = challengeMsg.target; authenticateMsg.target = challengeMsg.target;
authenticateMsg.username = username; authenticateMsg.username = username;
std::vector<unsigned char> nonce = NTLMCredentials::createNonce(); std::vector<unsigned char> lmNonce = NTLMCredentials::createNonce();
std::vector<unsigned char> ntlmNonce = NTLMCredentials::createNonce();
Poco::UInt64 timestamp = NTLMCredentials::createTimestamp(); Poco::UInt64 timestamp = NTLMCredentials::createTimestamp();
std::vector<unsigned char> ntlm2Hash = NTLMCredentials::createNTLMv2Hash(username, challengeMsg.target, _password); std::vector<unsigned char> ntlm2Hash = NTLMCredentials::createNTLMv2Hash(username, challengeMsg.target, _password);
authenticateMsg.lmResponse = NTLMCredentials::createLMv2Response(ntlm2Hash, challengeMsg.challenge, nonce);
authenticateMsg.ntlmResponse = Poco::Net::NTLMCredentials::createNTLMv2Response(ntlm2Hash, challengeMsg.challenge, nonce, challengeMsg.targetInfo, timestamp);
std::vector<unsigned char> authenticateBuf = Poco::Net::NTLMCredentials::formatAuthenticateMessage(authenticateMsg); authenticateMsg.lmResponse = NTLMCredentials::createLMv2Response(ntlm2Hash, challengeMsg.challenge, lmNonce);
authenticateMsg.ntlmResponse = NTLMCredentials::createNTLMv2Response(ntlm2Hash, challengeMsg.challenge, ntlmNonce, challengeMsg.targetInfo, timestamp);
std::ostringstream ostr; std::vector<unsigned char> authenticateBuf = NTLMCredentials::formatAuthenticateMessage(authenticateMsg);
Poco::Base64Encoder base64(ostr); return toBase64(authenticateBuf);
base64.rdbuf()->setLineLength(0);
base64.write(reinterpret_cast<const char*>(&authenticateBuf[0]), authenticateBuf.size());
base64.close();
return ostr.str();
} }
else throw Poco::InvalidArgumentException("Invalid NTLM challenge"); else throw HTTPException("Invalid NTLM challenge");
} }
} }
@@ -186,5 +177,26 @@ void HTTPNTLMCredentials::splitUsername(const std::string& usernameAndDomain, st
} }
std::string HTTPNTLMCredentials::toBase64(const std::vector<unsigned char>& buffer)
{
std::ostringstream ostr;
Poco::Base64Encoder base64(ostr);
base64.rdbuf()->setLineLength(0);
base64.write(reinterpret_cast<const char*>(&buffer[0]), buffer.size());
base64.close();
return ostr.str();
}
std::vector<unsigned char> HTTPNTLMCredentials::fromBase64(const std::string& base64)
{
Poco::MemoryInputStream istr(base64.data(), base64.size());
Poco::Base64Decoder debase64(istr);
std::vector<unsigned char> buffer(base64.size());
debase64.read(reinterpret_cast<char*>(&buffer[0]), buffer.size());
buffer.resize(static_cast<std::size_t>(debase64.gcount()));
return buffer;
}
} } // namespace Poco::Net } } // namespace Poco::Net