reSIProcate/DialogUsageManager  9694
Public Types | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes
resip::ServerAuthManager Class Reference

#include <ServerAuthManager.hxx>

Inheritance diagram for resip::ServerAuthManager:
Inheritance graph
[legend]
Collaboration diagram for resip::ServerAuthManager:
Collaboration graph
[legend]

List of all members.

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 SipMessagehandleUserAuthInfo (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 DatagetChallengeRealm (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

Detailed Description

Definition at line 16 of file ServerAuthManager.hxx.


Member Typedef Documentation

typedef std::map<Data, SipMessage*> resip::ServerAuthManager::MessageMap [protected]

Definition at line 72 of file ServerAuthManager.hxx.


Member Enumeration Documentation

Enumerator:
True 
False 
Async 

Definition at line 46 of file ServerAuthManager.hxx.

      {
           True,  // response is true
           False, // response is false
           Async  // response will be sent asynchronously
      };
Enumerator:
InvalidRequest 
BadCredentials 
Error 

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
      };
Enumerator:
RequestedInfo 
RequestedCredentials 
Challenged 
Skipped 
Rejected 

Definition at line 19 of file ServerAuthManager.hxx.


Constructor & Destructor Documentation

ServerAuthManager::ServerAuthManager ( DialogUsageManager dum,
TargetCommand::Target target 
)

Definition at line 19 of file ServerAuthManager.cxx.

                                                                                         :
   DumFeature(dum, target)
{
}
ServerAuthManager::~ServerAuthManager ( ) [virtual]

Definition at line 25 of file ServerAuthManager.cxx.

References InfoLog, and mMessages.

{
   InfoLog(<< "~ServerAuthManager:  " << mMessages.size() << " messages in memory when destroying.");
}

Member Function Documentation

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;
}

Here is the call graph for this function:

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().

{
   return msg.header(h_RequestLine).uri().host();
}

Here is the call graph for this function:

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;
}

Here is the call graph for this function:

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;
   }
}

Here is the call graph for this function:

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);
}

Here is the call graph for this function:

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);
}

Here is the call graph for this function:

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;
   }
}

Here is the call graph for this function:

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;   
}

Here is the call graph for this function:

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;
}

Member Data Documentation


The documentation for this class was generated from the following files: