示例#1
0
// Get and add the credentials for sipXregistrar
SipLineMgr*
SipRedirectorJoin::addCredentials (UtlString domain, UtlString realm)
{
   SipLine* line = NULL;
   SipLineMgr* lineMgr = NULL;
   UtlString user;


      Url identity;

      identity.setUserId(REGISTRAR_ID_TOKEN);
      identity.setHostAddress(domain);
      UtlString ha1_authenticator;
      UtlString authtype;
      bool bSuccess = false;

      EntityDB* entityDb = SipRegistrar::getInstance(NULL)->getEntityDB();
      if (entityDb->getCredential(identity, realm, user, ha1_authenticator, authtype))
      {
         if ((line = new SipLine( identity // user entered url
                                 ,identity // identity url
                                 ,user     // user
                                 ,TRUE     // visible
                                 ,SipLine::LINE_STATE_PROVISIONED
                                 ,TRUE     // auto enable
                                 ,FALSE    // use call handling
                                 )))
         {
            if ((lineMgr = new SipLineMgr()))
            {
               if (lineMgr->addLine(*line))
               {
                  if (lineMgr->addCredentialForLine( identity, realm, user, ha1_authenticator
                                                    ,HTTP_DIGEST_AUTHENTICATION
                                                    )
                      )
                  {
                     lineMgr->setDefaultOutboundLine(identity);
                     bSuccess = true;

                     Os::Logger::instance().log(FAC_SIP, PRI_INFO,
                                   "Added identity '%s': user='******' realm='%s'"
                                   ,identity.toString().data(), user.data(), realm.data()
                                   );
                  }
                  else
                  {
                     Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "Error adding identity '%s': user='******' realm='%s'\n"
                                   "Call Join feature will not work!",
                                   identity.toString().data(), user.data(), realm.data()
                                   );
                  }
               }
               else
               {
                  Os::Logger::instance().log(FAC_SIP, PRI_ERR, "addLine failed. Call Join feature will not work!" );
               }
            }
            else
            {
               Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                             "Constructing SipLineMgr failed. Call Join feature will not work!" );
            }
         }
         else
         {
            Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                          "Constructing SipLine failed. Call Join feature will not work!" );
         }
      }
      else
      {
         Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                       "No credential found for '%s' in realm '%s'. "
                       "Call Join feature will not work!"
                       ,identity.toString().data(), realm.data()
                       );
      }

      if( !bSuccess )
      {
         delete line;
         line = NULL;

         delete lineMgr;
         lineMgr = NULL;
      }


   return lineMgr;
}
UtlBoolean
SubscribeServerThread::isAuthenticated (const SipMessage* message,
                                        SipMessage *responseMessage,
                                        UtlString& authenticatedUser,
                                        UtlString& authenticatedRealm )
{
    UtlBoolean retIsAuthenticated = FALSE;

    // if we are not using a database we must assume authenticated
    if ( !mIsCredentialDB )
    {
        Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "SubscribeServerThread::isAuthenticated() "
            ":: No Credential DB - request is always AUTHENTICATED");
        retIsAuthenticated = TRUE;
    } else
    {
        // realm and auth type should be default for server
        // if URI not defined in DB, the user is not authorized to modify bindings -
        Os::Logger::instance().log( FAC_AUTH, PRI_DEBUG, "SubscribeServerThread::isAuthenticated():TRUE realm=\"%s\" ",
                mRealm.data());

        UtlString requestNonce;
        UtlString requestCnonce;
        UtlString requestNonceCount;
        UtlString requestQop;
        UtlString requestRealm;
        UtlString requestUser;
        UtlString requestUserBase;
        UtlString requestUriParam;
        int requestAuthIndex = 0;
        EntityDB* entityDb = StatusServer::getInstance()->getEntityDb();
        // can have multiple authorization / authorization-proxy headers
        // headers search for a realm match
        while ( message->getDigestAuthorizationData ( &requestUser,
                                                      &requestRealm,
                                                      &requestNonce,
                                                      NULL, // opaque
                                                      NULL, // response
                                                      &requestUriParam,
                                                      &requestCnonce,
                                                      &requestNonceCount,
                                                      &requestQop,
                                                      HttpMessage::SERVER,
                                                      requestAuthIndex,
                                                      &requestUserBase) )
        {
            Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, 
                          "SubscribeServerThread::isAuthenticated() "
                          "- Authorization header set in message, validate it.\n"
                          "- reqRealm=\"%s\", reqUser=\"%s\", reqUserBase=\"%s\"",
                          requestRealm.data(), requestUser.data(),
                          requestUserBase.data());

            UtlString qopType;
            UtlString callId;
            UtlString fromTag;
            long     nonceExpires = (5*60); // five minutes

            Url fromUrl;
            message->getFromUrl(fromUrl);
            fromUrl.getFieldParameter("tag", fromTag);
            UtlString reqUri;
            message->getRequestUri(&reqUri);
            Url mailboxUrl(reqUri);

            message->getCallIdField(&callId);

            if (mRealm.compareTo(requestRealm) ) // case sensitive check that realm is correct
            {
               Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG,
                             "SubscribeServerThread::isAuthenticated() "
                             "Realm does not match");
            }

            // See if the nonce is valid - see net/SipNonceDb.cpp
            else if (!mNonceDb.isNonceValid(requestNonce, callId, fromTag, mRealm, nonceExpires))
            {
                Os::Logger::instance().log(FAC_AUTH, PRI_INFO,
                              "SubscribeServerThread::isAuthenticated() "
                              "Invalid NONCE: '%s' found for mailboxUrl '%s' "
                              "realm: '%s' user: '******' "
                              "cnonce: '%s' nc: '%s' qop: '%s' "
                              "expiration: %ld",
                              requestNonce.data(), mailboxUrl.toString().data(),
                              mRealm.data(), requestUser.data(), 
                              requestCnonce.data(), requestNonceCount.data(), 
                              requestQop.data(), nonceExpires);
            }

            // verify that qop,cnonce, nonceCount are compatible
            else if (message->verifyQopConsistency(requestCnonce.data(),
                                                     requestNonceCount.data(),
                                                     &requestQop,
                                                     qopType)
                     >= HttpMessage::AUTH_QOP_NOT_SUPPORTED)
            {
                Os::Logger::instance().log(FAC_AUTH, PRI_INFO,
                              "SubscribeServerThread::isAuthenticated() "
                              "Invalid combination of QOP('%s'), cnonce('%s') and nonceCount('%s')",
                              requestQop.data(), requestCnonce.data(), requestNonceCount.data());
            }

            else // realm, nonce and qop are all ok
            {    
                UtlString authTypeDB;
                UtlString passTokenDB;

                // then get the credentials for this realm
                if (entityDb->getCredential(mailboxUrl, mRealm, requestUserBase, passTokenDB, authTypeDB))
                {
                    // the Digest Password is calculated from the request
                    // user, passtoken, nonce and request URI

                    retIsAuthenticated =
                       message->verifyMd5Authorization(requestUser.data(),
                                                       passTokenDB.data(),
                                                       requestNonce.data(),
                                                       requestRealm.data(),
                                                       requestCnonce.data(),
                                                       requestNonceCount.data(),
                                                       requestQop.data(),
                                                       requestUriParam.data());
                    if (retIsAuthenticated)
                    {
                        // can have multiple credentials for same realm so only break out
                        // when we have a positive match
                        Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, 
                                      "SubscribeServerThread::isAuthenticated() "
                                      "- request is AUTHENTICATED");
                        // copy the authenticated user/realm for subsequent authorization
                        authenticatedUser = requestUserBase;
                        authenticatedRealm = requestRealm;
                        break;
                    }
                    else
                    {
                        Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG,
                                      "SubscribeServerThread::isAuthenticated() "
                                      "- digest authorization failed "
                                      "nonce \"%s\", cnonce \"%s\" for "
                                      "mailboxUrl=\"%s\", reqRealm=\"%s\", reqUser=\"%s\"",
                                      requestNonce.data(),
                                      requestCnonce.data(),
                                      mailboxUrl.toString().data(),
                                      requestRealm.data(),
                                      requestUser.data());
                    }
                }
                else
                {
                    Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, 
                                  "SubscribeServerThread::isAuthenticated() "
                                  "- No Credentials for mailboxUrl=\"%s\", reqRealm=\"%s\", reqUser=\"%s\"",
                        mailboxUrl.toString().data(),
                        requestRealm.data(),
                        requestUser.data());
                }  // end check credentials
            }
            requestAuthIndex++;
        } //end while

        if ( !retIsAuthenticated )
        {
            // Generate the 401 Unauthorized response to challenge for credentials
            // Use the SipNonceDB to generate a nonce
            UtlString newNonce;
            UtlString callId;
            UtlString fromTag;

            Url fromUrl;
            message->getFromUrl(fromUrl);
            fromUrl.getFieldParameter("tag", fromTag);

            message->getCallIdField(&callId);

            mNonceDb.createNewNonce(callId,
                                    fromTag,
                                    mRealm,
                                    newNonce);

            responseMessage->setRequestUnauthorized(message, HTTP_DIGEST_AUTHENTICATION,
                                                    mRealm, newNonce);
        }
    }  // end DB exists
    return retIsAuthenticated;
}