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