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

📄 helper.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
      auth.param(p_cnonce) = cnonce;
      auth.param(p_nc) = nonceCountString;
      auth.param(p_qop) = authQop;
   }
   else
   {
      assert(challenge.exists(p_realm));
      auth.param(p_response) = Helper::makeResponseMD5(username, 
                                                       password,
                                                       challenge.param(p_realm), 
                                                       getMethodName(request.header(h_RequestLine).getMethod()),
                                                       digestUri, 
                                                       challenge.param(p_nonce));
   }
   
   if (challenge.exists(p_algorithm))
   {
      auth.param(p_algorithm) = challenge.param(p_algorithm);
   }
   else
   {
      auth.param(p_algorithm) = "MD5";
   }

   if (challenge.exists(p_opaque))
   {
      auth.param(p_opaque) = challenge.param(p_opaque);
   }
   
   return auth;
}

Data
Helper::qopOption(const Auth& challenge)
{
   // priority-order list of preferred qop tokens
   static Data preferredTokens[] = 
   {
      Symbols::authInt,
      Symbols::auth
   };

   bool found = false;
   size_t index = 0;
   if (challenge.exists(p_qopOptions) && !challenge.param(p_qopOptions).empty())
   {
      ParseBuffer pb(challenge.param(p_qopOptions).data(), challenge.param(p_qopOptions).size());
      do
      {
         const char* anchor = pb.skipWhitespace();
         pb.skipToChar(Symbols::COMMA[0]);
         if (!pb.eof())
            pb.skipChar();
         Data q;
         pb.data(q, anchor);
         for (size_t i=0; i < sizeof(preferredTokens)/sizeof(*preferredTokens); i++) 
         {
            if (q == preferredTokens[i]) 
            {
               // found a preferred token; is it higher priority?
               if (!found || i < index) 
               {
                  found = true;
                  index = i;
               }
            }
         }
      }
      while(!pb.eof());
   }

   if (found)
      return preferredTokens[index];

   return Data::Empty;
   
}
   

Auth 
Helper::makeChallengeResponseAuthWithA1(const SipMessage& request,
                                        const Data& username,
                                        const Data& a1,
                                        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::makeResponseMD5WithA1(a1,
                                                             getMethodName(request.header(h_RequestLine).getMethod()), 
                                                             digestUri, 
                                                             challenge.param(p_nonce),
                                                             authQop,
                                                             cnonce,
                                                             nonceCountString,
                                                             request.getContents());
      auth.param(p_cnonce) = cnonce;
      auth.param(p_nc) = nonceCountString;
      auth.param(p_qop) = authQop;
   }
   else
   {
      assert(challenge.exists(p_realm));
      auth.param(p_response) = Helper::makeResponseMD5WithA1(a1,
                                                             getMethodName(request.header(h_RequestLine).getMethod()),
                                                             digestUri, 
                                                             challenge.param(p_nonce));
   }
   
   if (challenge.exists(p_algorithm))
   {
      auth.param(p_algorithm) = challenge.param(p_algorithm);
   }
   else
   {
      auth.param(p_algorithm) = "MD5";
   }

   if (challenge.exists(p_opaque))
   {
      auth.param(p_opaque) = challenge.param(p_opaque);
   }
   
   return auth;
}
   
//.dcm. all the auth stuff should be yanked out of helper and
//architected for algorithm independance
bool 
Helper::algorithmAndQopSupported(const Auth& challenge)
{
   if ( !(challenge.exists(p_nonce) && challenge.exists(p_realm)))
   {
      return false;
   }
   return (!challenge.exists(p_algorithm) 
           || isEqualNoCase(challenge.param(p_algorithm), "MD5")
           && (!challenge.exists(p_qop) 
               || isEqualNoCase(challenge.param(p_qop), Symbols::auth)
               || isEqualNoCase(challenge.param(p_qop), Symbols::authInt)));
}

SipMessage& 
Helper::addAuthorization(SipMessage& request,
                         const SipMessage& challenge,
                         const Data& username,
                         const Data& password,
                         const Data& cnonce,
                         unsigned int& nonceCount)
{
   Data nonceCountString = Data::Empty;
   
   assert(challenge.isResponse());
   assert(challenge.header(h_StatusLine).responseCode() == 401 ||
          challenge.header(h_StatusLine).responseCode() == 407);

   if (challenge.exists(h_ProxyAuthenticates))
   {
      const ParserContainer<Auth>& auths = challenge.header(h_ProxyAuthenticates);
      for (ParserContainer<Auth>::const_iterator i = auths.begin();
           i != auths.end(); i++)
      {
         request.header(h_ProxyAuthorizations).push_back(makeChallengeResponseAuth(request, username, password, *i, 
                                                                                    cnonce, nonceCount, nonceCountString));
      }
   }
   if (challenge.exists(h_WWWAuthenticates))
   {
      const ParserContainer<Auth>& auths = challenge.header(h_WWWAuthenticates);
      for (ParserContainer<Auth>::const_iterator i = auths.begin();
           i != auths.end(); i++)
      {
         request.header(h_Authorizations).push_back(makeChallengeResponseAuth(request, username, password, *i,
                                                                               cnonce, nonceCount, nonceCountString));
      }
   }
   return request;
}
      
Uri
Helper::makeUri(const Data& aor, const Data& scheme)
{
   assert(!aor.prefix("sip:"));
   assert(!aor.prefix("sips:"));
   
   Data tmp(aor.size() + scheme.size() + 1, Data::Preallocate);
   tmp += scheme;
   tmp += Symbols::COLON;
   tmp += aor;
   Uri uri(tmp);
   return uri;
}

void
Helper::processStrictRoute(SipMessage& request)
{
   if (request.exists(h_Routes) && 
       !request.header(h_Routes).empty() &&
       !request.header(h_Routes).front().uri().exists(p_lr))
   {
      // The next hop is a strict router.  Move the next hop into the
      // Request-URI and move the ultimate destination to the end of the
      // route list.  Force the message target to be the next hop router.
      request.header(h_Routes).push_back(NameAddr(request.header(h_RequestLine).uri()));
      request.header(h_RequestLine).uri() = request.header(h_Routes).front().uri();
      request.header(h_Routes).pop_front(); // !jf!
      assert(!request.hasForceTarget());
      request.setForceTarget(request.header(h_RequestLine).uri());
   }
}

int
Helper::getPortForReply(SipMessage& request, bool returnDefault)
{
   assert(request.isRequest());
   int port = -1;
   if (request.header(h_Vias).front().exists(p_rport))
   {
       port = request.getSource().getPort();
   }
   else
   {
      port = request.header(h_Vias).front().sentPort();
      if (port <= 0 || port > 65535) 
      {
         if(!returnDefault)
         {
            port=0;
         }
         else if(request.header(h_Vias).front().transport() == Symbols::TLS ||
            request.header(h_Vias).front().transport() == Symbols::DTLS)
         {
            port = Symbols::DefaultSipsPort;
         }
         else
         {
            port = Symbols::DefaultSipPort;
         }
      }
   }
   assert(port != -1);
   return port;
}

Uri 
Helper::fromAor(const Data& aor, const Data& scheme)
{
   return makeUri(aor, scheme);
}

bool
Helper::validateMessage(const SipMessage& message,resip::Data* reason)
{
   if (!message.exists(h_To) || 
       !message.exists(h_From) || 
       !message.exists(h_CSeq) || 
       !message.exists(h_CallId) || 
       !message.exists(h_Vias) ||
       message.header(h_Vias).empty())
   {
      InfoLog(<< "Missing mandatory header fields (To, From, CSeq, Call-Id or Via)");
      DebugLog(<< message);
      if(reason) *reason="Missing mandatory header field";
      return false;
   }
   else
   {
      try
      {
         message.header(h_CSeq).checkParsed();
      }
      catch(ParseBuffer::Exception&)
      {
         InfoLog(<<"Malformed CSeq header");
         if(reason) *reason="Malformed CSeq header";
         return false;
      }
      
      try
      {
         message.header(h_Vias).front().checkParsed();
      }
      catch(ParseBuffer::Exception& e)
      {
         InfoLog(<<"Malformed topmost Via header: " << e);
         if(reason) *reason="Malformed topmost Via header";
         return false;
      }
      
      if (message.isRequest())
      {
         try
         {
            message.header(h_RequestLine).checkParsed();            
         }
         catch(ParseBuffer::Exception& e)
         {
            InfoLog(<< "Illegal request line " << e);
            if(reason) *reason="Malformed Request Line";
            return false;            
         }
         
         if(message.header(h_RequestLine).method()!=message.header(h_CSeq).method())
         {
            InfoLog(<< "Method mismatch btw Request Line and CSeq");
            if(reason) *reason="Method mismatch btw Request Line and CSeq";
            return false;
         }
      }
      else
      {
         try
         {
            message.header(h_StatusLine).checkParsed();
         }
         catch(ParseBuffer::Exception& e)
         {
            InfoLog(<< "Malformed status line " << e);
            if(reason) *reason="Malformed status line";
            return false;            
         }
      }
      
      return true;
   }
}

#if defined(USE_SSL)
#include <openssl/blowfish.h>

static const Data sep("[]");
static const Data pad("\0\0\0\0\0\0\0", 7);
static const Data GRUU("_GRUU");
static const int saltBytes(16);

Data
Helper::gruuUserPart(const Data& instanceId,
                     const Data& aor,
                     const Data& key)
{
   unsigned char ivec[8];      

   ivec[0] = '\x6E';
   ivec[1] = '\xE7';
   ivec[2] = '\xB0';
   ivec[3] = '\x4A';
   ivec[4] = '\x45';
   ivec[5] = '\x93';
   ivec[6] = '\x7D';
   ivec[7] = '\x51';

   BF_KEY fish;
   BF_set_key(&fish, key.size(), (const unsigned char*)key.data());

   const Data salt(resip::Random::getRandomHex(saltBytes));

   const Data token(salt + instanceId + sep + aor + '\0' +
                    pad.substr(0, (8 - ((salt.size() + 
                                         instanceId.size() + 
                                         sep.size() + 1 
                                         + aor.size() ) % 8))
                               % 8));
   auto_ptr <unsigned char> out(new unsigned char[token.size()]);
   BF_cbc_encrypt((const unsigned char*)token.data(),
                  out.get(),
                  token.size(),
                  &fish,
                  ivec, 
                  BF_ENCRYPT);

   return GRUU + Data(out.get(),token.size()).base64encode(true/*safe URL*/);
}

std::pair<Data,Data> 
Helper::fromGruuUserPart(const Data& gruuUserPart,
                         const Data& key)
{
   unsigned char ivec[8];      

   ivec[0] = '\x6E';

⌨️ 快捷键说明

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