📄 helper.cxx
字号:
{
return make_pair(BadlyFormed,username);
}
}
return make_pair(BadlyFormed,username);
}
DebugLog (<< "No authentication headers. Failing request.");
return make_pair(Failed,username);
}
// !jf! note that this only authenticates a ProxyAuthenticate header, need to
// add support for WWWAuthenticate as well!!
Helper::AuthResult
Helper::authenticateRequest(const SipMessage& request,
const Data& realm,
const Data& password,
int expiresDelta)
{
DebugLog(<< "Authenticating: realm=" << realm << " expires=" << expiresDelta);
//DebugLog(<< request);
if (request.exists(h_ProxyAuthorizations))
{
const ParserContainer<Auth>& auths = request.header(h_ProxyAuthorizations);
for (ParserContainer<Auth>::const_iterator i = auths.begin(); i != auths.end(); i++)
{
if (i->exists(p_realm) &&
i->exists(p_nonce) &&
i->exists(p_response) &&
i->param(p_realm) == realm)
{
static Data digest("digest");
if(!isEqualNoCase(i->scheme(),digest))
{
DebugLog(<< "Scheme must be Digest");
continue;
}
/* ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size());
if (!pb.eof() && !isdigit(*pb.position()))
{
DebugLog(<< "Invalid nonce; expected timestamp.");
return BadlyFormed;
}
const char* anchor = pb.position();
pb.skipToChar(Symbols::COLON[0]);
if (pb.eof())
{
DebugLog(<< "Invalid nonce; expected timestamp terminator.");
return BadlyFormed;
}
Data then;
pb.data(then, anchor); */
NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce));
if(x_nonce.getCreationTime() == 0)
return BadlyFormed;
if (expiresDelta > 0)
{
UInt64 now = Timer::getTimeMs()/1000;
if (x_nonce.getCreationTime() + expiresDelta < now)
{
DebugLog(<< "Nonce has expired.");
return Expired;
}
}
Data then(x_nonce.getCreationTime());
if (i->param(p_nonce) != makeNonce(request, then))
{
InfoLog(<< "Not my nonce.");
return Failed;
}
InfoLog (<< " username=" << (i->param(p_username))
<< " password=" << password
<< " realm=" << realm
<< " method=" << getMethodName(request.header(h_RequestLine).getMethod())
<< " uri=" << i->param(p_uri)
<< " nonce=" << i->param(p_nonce));
if (i->exists(p_qop))
{
if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt)
{
if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc))
{
if (i->param(p_response) == makeResponseMD5(i->param(p_username),
password,
realm,
getMethodName(request.header(h_RequestLine).getMethod()),
i->param(p_uri),
i->param(p_nonce),
i->param(p_qop),
i->param(p_cnonce),
i->param(p_nc)),
request.getContents())
{
return Authenticated;
}
else
{
return Failed;
}
}
}
else
{
InfoLog (<< "Unsupported qop=" << i->param(p_qop));
return Failed;
}
}
else if(i->exists(p_uri))
{
if (i->param(p_response) == makeResponseMD5(i->param(p_username),
password,
realm,
getMethodName(request.header(h_RequestLine).getMethod()),
i->param(p_uri),
i->param(p_nonce)))
{
return Authenticated;
}
else
{
return Failed;
}
}
}
else
{
return BadlyFormed;
}
}
return BadlyFormed;
}
DebugLog (<< "No authentication headers. Failing request.");
return Failed;
}
Helper::AuthResult
Helper::authenticateRequestWithA1(const SipMessage& request,
const Data& realm,
const Data& hA1,
int expiresDelta)
{
DebugLog(<< "Authenticating with HA1: realm=" << realm << " expires=" << expiresDelta);
//DebugLog(<< request);
if (request.exists(h_ProxyAuthorizations))
{
const ParserContainer<Auth>& auths = request.header(h_ProxyAuthorizations);
for (ParserContainer<Auth>::const_iterator i = auths.begin(); i != auths.end(); i++)
{
if (i->exists(p_realm) &&
i->exists(p_nonce) &&
i->exists(p_response) &&
i->param(p_realm) == realm)
{
static Data digest("digest");
if(!isEqualNoCase(i->scheme(),digest))
{
DebugLog(<< "Scheme must be Digest");
continue;
}
/* ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size());
if (!pb.eof() && !isdigit(*pb.position()))
{
DebugLog(<< "Invalid nonce; expected timestamp.");
return BadlyFormed;
}
const char* anchor = pb.position();
pb.skipToChar(Symbols::COLON[0]);
if (pb.eof())
{
DebugLog(<< "Invalid nonce; expected timestamp terminator.");
return BadlyFormed;
}
Data then;
pb.data(then, anchor); */
NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce));
if(x_nonce.getCreationTime() == 0)
return BadlyFormed;
if (expiresDelta > 0)
{
UInt64 now = Timer::getTimeMs()/1000;
if (x_nonce.getCreationTime() + expiresDelta < now)
{
DebugLog(<< "Nonce has expired.");
return Expired;
}
}
Data then(x_nonce.getCreationTime());
if (i->param(p_nonce) != makeNonce(request, then))
{
InfoLog(<< "Not my nonce.");
return Failed;
}
InfoLog (<< " username=" << (i->param(p_username))
<< " H(A1)=" << hA1
<< " realm=" << realm
<< " method=" << getMethodName(request.header(h_RequestLine).getMethod())
<< " uri=" << i->param(p_uri)
<< " nonce=" << i->param(p_nonce));
if (i->exists(p_qop))
{
if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt)
{
if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc))
{
if (i->param(p_response) == makeResponseMD5WithA1(hA1,
getMethodName(request.header(h_RequestLine).getMethod()),
i->param(p_uri),
i->param(p_nonce),
i->param(p_qop),
i->param(p_cnonce),
i->param(p_nc),
request.getContents()))
{
return Authenticated;
}
else
{
return Failed;
}
}
}
else
{
InfoLog (<< "Unsupported qop=" << i->param(p_qop));
return Failed;
}
}
else if(i->exists(p_uri))
{
if (i->param(p_response) == makeResponseMD5WithA1(hA1,
getMethodName(request.header(h_RequestLine).getMethod()),
i->param(p_uri),
i->param(p_nonce)))
{
return Authenticated;
}
else
{
return Failed;
}
}
}
else
{
return BadlyFormed;
}
}
return BadlyFormed;
}
DebugLog (<< "No authentication headers. Failing request.");
return Failed;
}
SipMessage*
Helper::make405(const SipMessage& request,
const int* allowedMethods,
int len )
{
SipMessage* resp = Helper::makeResponse(request, 405);
if (len < 0)
{
int upperBound = static_cast<int>(MAX_METHODS);
// The UNKNOWN method name is the first in the enum
for (int i = 1 ; i < upperBound; i ++)
{
int last = 0;
// ENUMS must be contiguous in order for this to work.
assert( i - last <= 1);
Token t;
t.value() = getMethodName(static_cast<resip::MethodTypes>(i));
resp->header(h_Allows).push_back(t);
last = i;
}
}
else
{
// use user's list
for ( int i = 0 ; i < len ; i++)
{
Token t;
t.value() = getMethodName(static_cast<resip::MethodTypes>(allowedMethods[i]));
resp->header(h_Allows).push_back(t);
}
}
return resp;
}
SipMessage*
Helper::makeProxyChallenge(const SipMessage& request, const Data& realm, bool useAuth, bool stale)
{
return makeChallenge(request, realm, useAuth, stale, true);
}
SipMessage*
Helper::makeChallenge(const SipMessage& request, const Data& realm, bool useAuth, bool stale, bool proxy)
{
Auth auth;
auth.scheme() = "Digest";
Data timestamp(Timer::getTimeMs()/1000);
auth.param(p_nonce) = makeNonce(request, timestamp);
auth.param(p_algorithm) = "MD5";
auth.param(p_realm) = realm;
if (useAuth)
{
auth.param(p_qopOptions) = "auth,auth-int";
}
if (stale)
{
auth.param(p_stale) = "true";
}
SipMessage *response;
if(proxy)
{
response = Helper::makeResponse(request, 407);
response->header(h_ProxyAuthenticates).push_back(auth);
}
else
{
response = Helper::makeResponse(request, 401);
response->header(h_WWWAuthenticates).push_back(auth);
}
return response;
}
void updateNonceCount(unsigned int& nonceCount, Data& nonceCountString)
{
if (!nonceCountString.empty())
{
return;
}
nonceCount++;
{
DataStream s(nonceCountString);
s << std::setw(8) << std::setfill('0') << std::hex << nonceCount;
}
DebugLog(<< "nonceCount is now: [" << nonceCountString << "]");
}
Auth
Helper::makeChallengeResponseAuth(SipMessage& request,
const Data& username,
const Data& password,
const Auth& challenge,
const Data& cnonce,
unsigned int& nonceCount,
Data& nonceCountString)
{
Auth auth;
auth.scheme() = "Digest";
auth.param(p_username) = username;
assert(challenge.exists(p_realm));
auth.param(p_realm) = challenge.param(p_realm);
assert(challenge.exists(p_nonce));
auth.param(p_nonce) = challenge.param(p_nonce);
Data digestUri;
{
DataStream s(digestUri);
//s << request.header(h_RequestLine).uri().host(); // wrong
s << request.header(h_RequestLine).uri(); // right
}
auth.param(p_uri) = digestUri;
Data authQop = qopOption(challenge);
if (!authQop.empty())
{
updateNonceCount(nonceCount, nonceCountString);
auth.param(p_response) = Helper::makeResponseMD5(username,
password,
challenge.param(p_realm),
getMethodName(request.header(h_RequestLine).getMethod()),
digestUri,
challenge.param(p_nonce),
authQop,
cnonce,
nonceCountString,
request.getContents());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -