|
reSIProcate/DialogUsageManager
9694
|
#include <ServerAuthManager.hxx>


Public Types | |
| enum | Result { RequestedInfo, RequestedCredentials, Challenged, Skipped, Rejected } |
Public Member Functions | |
| ServerAuthManager (DialogUsageManager &dum, TargetCommand::Target &target) | |
| virtual | ~ServerAuthManager () |
| virtual ProcessingResult | process (Message *msg) |
| virtual SipMessage * | handleUserAuthInfo (UserAuthInfo *auth) |
| virtual Result | handle (SipMessage *sipMsg) |
Protected Types | |
| enum | AsyncBool { True, False, Async } |
| enum | AuthFailureReason { InvalidRequest, BadCredentials, Error } |
| typedef std::map< Data, SipMessage * > | MessageMap |
Protected Member Functions | |
| virtual void | requestCredential (const Data &user, const Data &realm, const SipMessage &msg, const Auth &auth, const Data &transactionToken)=0 |
| virtual bool | useAuthInt () const |
| virtual bool | proxyAuthenticationMode () const |
| virtual bool | rejectBadNonces () const |
| virtual AsyncBool | requiresChallenge (const SipMessage &msg) |
| should return true if the request must be challenged The default is to challenge all requests - override this class to change this beviour | |
| virtual bool | authorizedForThisIdentity (const resip::Data &user, const resip::Data &realm, resip::Uri &fromUri) |
| should return true if the passed in user is authorized for the provided uri | |
| virtual const Data & | getChallengeRealm (const SipMessage &msg) |
| returns the realm to be used for the challenge | |
| virtual bool | isMyRealm (const Data &realm) |
| should return true if realm passed in is ours and we can challenge | |
| Result | issueChallengeIfRequired (SipMessage *sipMsg) |
| void | issueChallenge (SipMessage *sipMsg) |
| virtual void | onAuthSuccess (const SipMessage &msg) |
| virtual void | onAuthFailure (AuthFailureReason reason, const SipMessage &msg) |
Protected Attributes | |
| MessageMap | mMessages |
Definition at line 16 of file ServerAuthManager.hxx.
typedef std::map<Data, SipMessage*> resip::ServerAuthManager::MessageMap [protected] |
Definition at line 72 of file ServerAuthManager.hxx.
enum resip::ServerAuthManager::AsyncBool [protected] |
Definition at line 46 of file ServerAuthManager.hxx.
enum resip::ServerAuthManager::AuthFailureReason [protected] |
Definition at line 53 of file ServerAuthManager.hxx.
{
InvalidRequest, // some aspect of the request (e.g. nonce)
// is not valid/tampered with
BadCredentials, // credentials didn't match
Error // processing/network error
};
Definition at line 19 of file ServerAuthManager.hxx.
{
//Authorized,
RequestedInfo,
RequestedCredentials,
Challenged,
Skipped,
Rejected
};
| ServerAuthManager::ServerAuthManager | ( | DialogUsageManager & | dum, |
| TargetCommand::Target & | target | ||
| ) |
Definition at line 19 of file ServerAuthManager.cxx.
: DumFeature(dum, target) { }
| ServerAuthManager::~ServerAuthManager | ( | ) | [virtual] |
| bool ServerAuthManager::authorizedForThisIdentity | ( | const resip::Data & | user, |
| const resip::Data & | realm, | ||
| resip::Uri & | fromUri | ||
| ) | [protected, virtual] |
should return true if the passed in user is authorized for the provided uri
Definition at line 279 of file ServerAuthManager.cxx.
References resip::Uri::getAorNoPort(), resip::Uri::host(), and resip::Uri::user().
Referenced by handleUserAuthInfo().
{
// !rwm! good enough for now. TODO eventually consult a database to see what
// combinations of user/realm combos are authorized for an identity
// First try the form where the username parameter in the auth
// header is just the username component of the fromUri
//
if ((fromUri.user() == user) && (fromUri.host() == realm))
return true;
// Now try the form where the username parameter in the auth
// header is the full fromUri, e.g.
// Proxy-Authorization: Digest username="user@domain" ...
//
if ((fromUri.getAorNoPort() == user) && (fromUri.host() == realm))
return true;
// catch-all: access denied
return false;
}

| const Data & ServerAuthManager::getChallengeRealm | ( | const SipMessage & | msg | ) | [protected, virtual] |
returns the realm to be used for the challenge
Definition at line 305 of file ServerAuthManager.cxx.
References h_RequestLine, resip::SipMessage::header(), resip::Uri::host(), and resip::RequestLine::uri().
Referenced by issueChallenge().

| ServerAuthManager::Result ServerAuthManager::handle | ( | SipMessage * | sipMsg | ) | [virtual] |
Definition at line 320 of file ServerAuthManager.cxx.
References resip::ParserContainer< T >::begin(), resip::ParserContainer< T >::end(), resip::SipMessage::exists(), resip::SipMessage::getTransactionId(), h_RequestLine, resip::SipMessage::header(), InfoLog, InvalidRequest, isMyRealm(), resip::SipMessage::isRequest(), issueChallengeIfRequired(), resip::Helper::makeResponse(), resip::DumFeature::mDum, resip::RequestLine::method(), mMessages, onAuthFailure(), proxyAuthenticationMode(), Rejected, requestCredential(), RequestedCredentials, resip::DialogUsageManager::send(), and Skipped.
Referenced by process().
{
//InfoLog( << "trying to do auth" );
if (sipMsg->isRequest() &&
sipMsg->header(h_RequestLine).method() != ACK &&
sipMsg->header(h_RequestLine).method() != CANCEL) // Do not challenge ACKs or CANCELs
{
ParserContainer<Auth>* auths;
if (proxyAuthenticationMode())
{
if(!sipMsg->exists(h_ProxyAuthorizations))
{
return issueChallengeIfRequired(sipMsg);
}
auths = &sipMsg->header(h_ProxyAuthorizations);
}
else
{
if(!sipMsg->exists(h_Authorizations))
{
return issueChallengeIfRequired(sipMsg);
}
auths = &sipMsg->header(h_Authorizations);
}
try
{
for(Auths::iterator it = auths->begin(); it != auths->end(); it++)
{
if (isMyRealm(it->param(p_realm)))
{
InfoLog (<< "Requesting credential for "
<< it->param(p_username) << " @ " << it->param(p_realm));
requestCredential(it->param(p_username),
it->param(p_realm),
*sipMsg,
*it,
sipMsg->getTransactionId());
mMessages[sipMsg->getTransactionId()] = sipMsg;
return RequestedCredentials;
}
}
InfoLog (<< "Didn't find matching realm ");
return issueChallengeIfRequired(sipMsg);
}
catch(BaseException& e)
{
InfoLog (<< "Invalid auth header provided " << e);
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *sipMsg, 400, "Invalid auth header");
mDum.send(response);
onAuthFailure(InvalidRequest, *sipMsg);
return Rejected;
}
}
return Skipped;
}

| SipMessage * ServerAuthManager::handleUserAuthInfo | ( | UserAuthInfo * | auth | ) | [virtual] |
dcm! -- need to handle stale/unit test advancedAuthenticateRequest dcm! -- delta? deal with.
Definition at line 119 of file ServerAuthManager.cxx.
References resip::Helper::advancedAuthenticateRequest(), resip::Helper::Authenticated, authorizedForThisIdentity(), BadCredentials, resip::Helper::BadlyFormed, resip::UserAuthInfo::DigestAccepted, resip::Data::empty(), Error, resip::Helper::Expired, resip::Helper::Failed, resip::UserAuthInfo::getA1(), resip::UserAuthInfo::getMode(), resip::UserAuthInfo::getRealm(), resip::DumFeatureMessage::getTransactionId(), resip::UserAuthInfo::getUser(), InfoLog, InvalidRequest, issueChallenge(), resip::Helper::makeResponse(), resip::DumFeature::mDum, mMessages, onAuthFailure(), onAuthSuccess(), proxyAuthenticationMode(), rejectBadNonces(), resip::UserAuthInfo::RetrievedA1, resip::DialogUsageManager::send(), resip::UserAuthInfo::Stale, and resip::UserAuthInfo::UserUnknown.
Referenced by process().
{
assert(userAuth);
MessageMap::iterator it = mMessages.find(userAuth->getTransactionId());
assert(it != mMessages.end());
SipMessage* requestWithAuth = it->second;
mMessages.erase(it);
InfoLog( << "Checking for auth result in realm=" << userAuth->getRealm()
<< " A1=" << userAuth->getA1());
if (userAuth->getMode() == UserAuthInfo::UserUnknown ||
(userAuth->getMode() == UserAuthInfo::RetrievedA1 && userAuth->getA1().empty()))
{
InfoLog (<< "User unknown " << userAuth->getUser() << " in " << userAuth->getRealm());
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *requestWithAuth, 404, "User unknown.");
mDum.send(response);
onAuthFailure(BadCredentials, *requestWithAuth);
delete requestWithAuth;
return 0;
}
if (userAuth->getMode() == UserAuthInfo::Error)
{
InfoLog (<< "Error in auth procedure for " << userAuth->getUser() << " in " << userAuth->getRealm());
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *requestWithAuth, 503, "Server Error.");
mDum.send(response);
onAuthFailure(Error, *requestWithAuth);
delete requestWithAuth;
return 0;
}
bool stale = false;
bool digestAccepted = (userAuth->getMode() == UserAuthInfo::DigestAccepted);
if(userAuth->getMode() == UserAuthInfo::RetrievedA1)
{
std::pair<Helper::AuthResult,Data> resPair =
Helper::advancedAuthenticateRequest(*requestWithAuth,
userAuth->getRealm(),
userAuth->getA1(),
3000,
proxyAuthenticationMode());
switch (resPair.first)
{
case Helper::Authenticated:
digestAccepted = true;
break;
case Helper::Failed:
// digestAccepted = false; // already false by default
break;
case Helper::BadlyFormed:
if(rejectBadNonces())
{
InfoLog (<< "Authentication nonce badly formed for " << userAuth->getUser());
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *requestWithAuth, 403, "Invalid nonce");
mDum.send(response);
onAuthFailure(InvalidRequest, *requestWithAuth);
delete requestWithAuth;
return 0;
}
else
{
stale=true;
}
break;
case Helper::Expired:
stale = true;
break;
default:
break;
}
}
if(stale || userAuth->getMode() == UserAuthInfo::Stale)
{
InfoLog (<< "Nonce expired for " << userAuth->getUser());
issueChallenge(requestWithAuth);
delete requestWithAuth;
return 0;
}
if(digestAccepted)
{
if (authorizedForThisIdentity(userAuth->getUser(), userAuth->getRealm(),
requestWithAuth->header(h_From).uri()))
{
InfoLog (<< "Authorized request for " << userAuth->getRealm());
onAuthSuccess(*requestWithAuth);
return requestWithAuth;
}
else
{
// !rwm! The user is trying to forge a request. Respond with a 403
InfoLog (<< "User: " << userAuth->getUser() << " at realm: " << userAuth->getRealm() <<
" trying to forge request from: " << requestWithAuth->header(h_From).uri());
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *requestWithAuth, 403, "Invalid user name provided");
mDum.send(response);
onAuthFailure(InvalidRequest, *requestWithAuth);
delete requestWithAuth;
return 0;
}
}
else
{
// Handles digestAccepted == false, DigestNotAccepted and any other
// case that is not recognised by the foregoing logic
InfoLog (<< "Invalid password provided for " << userAuth->getUser() << " in " << userAuth->getRealm());
InfoLog (<< " a1 hash of password from db was " << userAuth->getA1() );
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *requestWithAuth, 403, "Invalid password provided");
mDum.send(response);
onAuthFailure(BadCredentials, *requestWithAuth);
delete requestWithAuth;
return 0;
}
}

| bool ServerAuthManager::isMyRealm | ( | const Data & | realm | ) | [protected, virtual] |
should return true if realm passed in is ours and we can challenge
Definition at line 312 of file ServerAuthManager.cxx.
References resip::TransactionUser::isMyDomain(), and resip::DumFeature::mDum.
Referenced by handle().
{
return mDum.isMyDomain(realm);
}

| void ServerAuthManager::issueChallenge | ( | SipMessage * | sipMsg | ) | [protected] |
Definition at line 400 of file ServerAuthManager.cxx.
References resip::Message::brief(), getChallengeRealm(), InfoLog, resip::Helper::makeChallenge(), resip::DumFeature::mDum, proxyAuthenticationMode(), resip::DialogUsageManager::send(), and useAuthInt().
Referenced by handleUserAuthInfo(), issueChallengeIfRequired(), and process().
{
//assume TransactionUser has matched/repaired a realm
SharedPtr<SipMessage> challenge(Helper::makeChallenge(*sipMsg,
getChallengeRealm(*sipMsg),
useAuthInt(),
false /*stale*/,
proxyAuthenticationMode()));
InfoLog (<< "Sending challenge to " << sipMsg->brief());
mDum.send(challenge);
}

| ServerAuthManager::Result ServerAuthManager::issueChallengeIfRequired | ( | SipMessage * | sipMsg | ) | [protected] |
Definition at line 381 of file ServerAuthManager.cxx.
References Async, Challenged, False, resip::SipMessage::getTransactionId(), issueChallenge(), mMessages, RequestedInfo, requiresChallenge(), Skipped, and True.
Referenced by handle().
{
// Is challenge required for this message
AsyncBool required = requiresChallenge(*sipMsg);
switch(required)
{
case False:
return Skipped;
case Async:
mMessages[sipMsg->getTransactionId()] = sipMsg;
return RequestedInfo;
case True:
default:
issueChallenge(sipMsg);
return Challenged;
}
}

| void ServerAuthManager::onAuthFailure | ( | AuthFailureReason | reason, |
| const SipMessage & | msg | ||
| ) | [protected, virtual] |
Definition at line 420 of file ServerAuthManager.cxx.
Referenced by handle(), and handleUserAuthInfo().
{
// sub class may want to create a log entry
}
| void ServerAuthManager::onAuthSuccess | ( | const SipMessage & | msg | ) | [protected, virtual] |
Definition at line 414 of file ServerAuthManager.cxx.
Referenced by handleUserAuthInfo().
{
// sub class may want to create a log entry
}
| DumFeature::ProcessingResult ServerAuthManager::process | ( | Message * | msg | ) | [virtual] |
dcm! -- unecessary happens in handle
Implements resip::DumFeature.
Definition at line 35 of file ServerAuthManager.cxx.
References resip::Message::brief(), resip::ChallengeInfo::brief(), resip::DumFeature::ChainDoneAndEventDone, Challenged, resip::DumFeature::EventTaken, resip::DumFeature::FeatureDone, resip::DumFeature::FeatureDoneAndEventDone, resip::DumFeatureMessage::getTransactionId(), handle(), handleUserAuthInfo(), InfoLog, resip::ChallengeInfo::isChallengeRequired(), resip::ChallengeInfo::isFailed(), issueChallenge(), resip::Helper::makeResponse(), resip::DumFeature::mDum, mMessages, resip::DumFeature::postCommand(), Rejected, RequestedCredentials, RequestedInfo, and resip::DialogUsageManager::send().
{
SipMessage* sipMsg = dynamic_cast<SipMessage*>(msg);
if (sipMsg)
{
switch ( handle(sipMsg) )
{
case ServerAuthManager::Challenged:
InfoLog(<< "ServerAuth challenged request " << sipMsg->brief());
return DumFeature::ChainDoneAndEventDone;
case ServerAuthManager::RequestedInfo:
InfoLog(<< "ServerAuth requested info (requiresChallenge) " << sipMsg->brief());
return DumFeature::EventTaken;
case ServerAuthManager::RequestedCredentials:
InfoLog(<< "ServerAuth requested credentials " << sipMsg->brief());
return DumFeature::EventTaken;
case ServerAuthManager::Rejected:
InfoLog(<< "ServerAuth rejected request " << sipMsg->brief());
return DumFeature::ChainDoneAndEventDone;
default: // includes Skipped
return DumFeature::FeatureDone;
}
}
ChallengeInfo* challengeInfo = dynamic_cast<ChallengeInfo*>(msg);
if(challengeInfo)
{
InfoLog(<< "ServerAuth got ChallengeInfo " << challengeInfo->brief());
MessageMap::iterator it = mMessages.find(challengeInfo->getTransactionId());
assert(it != mMessages.end());
std::auto_ptr<SipMessage> sipMsg(it->second);
mMessages.erase(it);
if(challengeInfo->isFailed())
{
// some kind of failure occurred while checking whether a
// challenge is required
InfoLog(<< "ServerAuth requiresChallenge() async failed");
SharedPtr<SipMessage> response(new SipMessage);
Helper::makeResponse(*response, *sipMsg, 500, "Server Internal Error");
mDum.send(response);
return DumFeature::ChainDoneAndEventDone;
}
if(challengeInfo->isChallengeRequired())
{
issueChallenge(sipMsg.get());
InfoLog(<< "ServerAuth challenged request (after async) " << sipMsg->brief());
return DumFeature::ChainDoneAndEventDone;
}
else
{
// challenge is not required, re-instate original message
postCommand(auto_ptr<Message>(sipMsg));
return FeatureDoneAndEventDone;
}
}
UserAuthInfo* userAuth = dynamic_cast<UserAuthInfo*>(msg);
if (userAuth)
{
//InfoLog(<< "Got UserAuthInfo");
UserAuthInfo* userAuth = dynamic_cast<UserAuthInfo*>(msg);
if (userAuth)
{
Message* result = handleUserAuthInfo(userAuth);
if (result)
{
postCommand(auto_ptr<Message>(result));
return FeatureDoneAndEventDone;
}
else
{
InfoLog(<< "ServerAuth rejected request " << *userAuth);
return ChainDoneAndEventDone;
}
}
}
return FeatureDone;
}

| bool ServerAuthManager::proxyAuthenticationMode | ( | ) | const [protected, virtual] |
Definition at line 258 of file ServerAuthManager.cxx.
Referenced by handle(), handleUserAuthInfo(), and issueChallenge().
{
return true;
}
| bool ServerAuthManager::rejectBadNonces | ( | ) | const [protected, virtual] |
Definition at line 265 of file ServerAuthManager.cxx.
Referenced by handleUserAuthInfo().
{
return true;
}
| virtual void resip::ServerAuthManager::requestCredential | ( | const Data & | user, |
| const Data & | realm, | ||
| const SipMessage & | msg, | ||
| const Auth & | auth, | ||
| const Data & | transactionToken | ||
| ) | [protected, pure virtual] |
Referenced by handle().
| ServerAuthManager::AsyncBool ServerAuthManager::requiresChallenge | ( | const SipMessage & | msg | ) | [protected, virtual] |
should return true if the request must be challenged The default is to challenge all requests - override this class to change this beviour
Definition at line 272 of file ServerAuthManager.cxx.
References True.
Referenced by issueChallengeIfRequired().
{
return True;
}
| bool ServerAuthManager::useAuthInt | ( | ) | const [protected, virtual] |
Definition at line 251 of file ServerAuthManager.cxx.
Referenced by issueChallenge().
{
return false;
}
MessageMap resip::ServerAuthManager::mMessages [protected] |
Definition at line 73 of file ServerAuthManager.hxx.
Referenced by handle(), handleUserAuthInfo(), issueChallengeIfRequired(), process(), and ~ServerAuthManager().
1.7.5.1