AuthPlugin::AuthResult TransferControl::authorizeAndModify(const UtlString& id, /**< The authenticated identity of the * request originator, if any (the null * string if not). * This is in the form of a SIP uri * identity value as used in the * credentials database (user@domain) * without the scheme or any parameters. */ const Url& requestUri, ///< parsed target Uri RouteState& routeState, ///< the state for this request. const UtlString& method,///< the request method AuthResult priorResult,///< results from earlier plugins. SipMessage& request, ///< see AuthPlugin wrt modifying bool bSpiralingRequest, ///< request spiraling indication UtlString& reason ///< rejection reason ) { AuthResult result = CONTINUE; // get the call-id to use in logging UtlString callId; request.getCallIdField(&callId); UtlString hostAddress; int hostPort; UtlString hostProtocols; //requestUri.getHostAddress(hostAddress); //request.getContactUri(0, &hostAddress);; request.getContactAddress(0, &hostAddress,&hostPort,&hostProtocols); if (DENY != priorResult) { if (method.compareTo(SIP_REFER_METHOD) == 0) { UtlString targetStr; if (request.getReferToField(targetStr)) { Url target(targetStr, Url::NameAddr); // parse the target URL UtlString targetMethod; if ( Url::SipUrlScheme == target.getScheme() /* REFER can create requests other than INVITE: we don't care about those * * so check that the method is INVITE or is unspecified (INVITE is the default) */ && ( ! target.getUrlParameter(SIP_METHOD_URI_PARAMETER, targetMethod) || (0==targetMethod.compareTo(SIP_INVITE_METHOD, UtlString::ignoreCase)) )) { if (id.isNull()) { // UnAuthenticated REFER. Do challenge the REFER to confirm the // identity of the transferor. Note: prior to XECS-2487, we used to challenge // only the unauthenticated REFERs that didn't carry a Replaces header. // The fix for XECS-2487 now requires that all unauthenticated REFERs // be challenged so that consultative transfers get routed properly // when user-based gateway section is used. See tracker for the details if (mpSipRouter->isLocalDomain(target)) { //White list of two servets to let Exchange REFER to sipXecs endpoints if (hostAddress.compareTo(server1, UtlString::ignoreCase) == 0 || hostAddress.compareTo(server2, UtlString::ignoreCase) == 0) { Os::Logger::instance().log(FAC_AUTH, PRI_INFO, "TransferControl[%s]::authorizeAndModify " "Whitelist host '%s' in call '%s'", mInstanceName.data(),hostAddress.data(),callId.data() ); result = ALLOW; //Whitelist matched so allow the transfer }else{ Os::Logger::instance().log(FAC_AUTH, PRI_INFO, "TransferControl[%s]::authorizeAndModify " "challenging transfer in call '%s' from host '%s'", mInstanceName.data(), callId.data(),hostAddress.data() ); result = DENY; // we need an identity to attach to the Refer-To URI } } else { /* * This is a transfer to a target outside our domain, so let it go * unchallenged. See XECS-806 */ Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "TransferControl[%s]::authorizeAndModify " "allowing foriegn transfer in call '%s'", mInstanceName.data(), callId.data() ); // Add the References to the refer-to. Adding the callId field as a reference // header (will be used in resulting INVITE) in the Refer-To provides us // with enough information to be able to logically tie the calls together. // Useful for CDR records. UtlString refcallId(callId); refcallId.append(";rel=refer"); target.setHeaderParameter(SIP_REFERENCES_FIELD, refcallId.data()); Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "TransferControl[%s]::authorizeAndModify " "adding Reference field [%s] to refer-to", mInstanceName.data(), callId.data() ); request.setReferToField(target.toString().data()); result = ALLOW; } } else { UtlString contactString; request.getContactEntry(0, &contactString); Url contactUri( contactString ); UtlString userId; contactUri.getUserId(contactString); Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "TransferControl::authorizeAndModify - Contact field is: %s ", contactString.data()); if (contactString != "callcontroller") { // Authenticated REFER // annotate the refer-to with the authenticated controller identity SipXauthIdentity controllerIdentity; controllerIdentity.setIdentity(id); controllerIdentity.encodeUri(target); // add the References to the refer-to. UtlString refcallId(callId); refcallId.append(";rel=refer"); target.setHeaderParameter(SIP_REFERENCES_FIELD, refcallId.data()); Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "TransferControl[%s]::authorizeAndModify " "adding Reference field [%s] to refer-to", mInstanceName.data(), callId.data() ); request.setReferToField(target.toString().data()); } } } else { Os::Logger::instance().log(FAC_AUTH, PRI_WARNING, "TransferControl[%s]::authorizeAndModify " "unrecognized refer target '%s' for call '%s'", mInstanceName.data(), targetStr.data(), callId.data() ); } } else { // REFER without a Refer-To header... incorrect, but just ignore it. Os::Logger::instance().log(FAC_AUTH, PRI_WARNING, "TransferControl[%s]::authorizeAndModify " "REFER method without Refer-To in call '%s'", mInstanceName.data(), callId.data() ); } } else if (method.compareTo(SIP_INVITE_METHOD) == 0) { UtlString targetCallId; UtlString targetFromTag; UtlString targetToTag; if (request.getReplacesData(targetCallId, targetToTag, targetFromTag)) { /* * This is an INVITE with Replaces: probably either the completion * of a call pickup or a consultative transfer. * In any case, it will not create a new call - just connect something * to an existing call - so we don't need to make any new authorization * decisions. */ result = ALLOW; } else { // INVITE without Replaces: is not a transfer - ignore it. } } else { // neither REFER nor INVITE, so is not a transfer - ignore it. } } else { // Some earlier plugin already denied this - don't waste time figuring it out. Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "TransferControl[%s]::authorizeAndModify " "prior authorization result %s for call %s", mInstanceName.data(), AuthResultStr(priorResult), callId.data() ); } return result; }
RedirectPlugin::LookUpStatus SipRedirectorAliasDB::lookUp( const SipMessage& message, UtlString& requestString, Url& requestUri, const UtlString& method, ContactList& contactList, RequestSeqNo requestSeqNo, int redirectorNo, SipRedirectorPrivateStorage*& privateStorage, ErrorDescriptor& errorDescriptor) { // If url param sipx-userforward = false, do not redirect to user-forward // aliases. UtlString userforwardParam; requestUri.getUrlParameter("sipx-userforward", userforwardParam); bool disableForwarding = userforwardParam.compareTo("false", UtlString::ignoreCase) == 0; if (disableForwarding) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::lookUp user forwarding disabled by parameter", mLogName.data()); } bool isDomainAlias = false; UtlString domain; UtlString hostAlias; requestUri.getHostAddress(domain); UtlBoolean isMyHostAlias = mpSipUserAgent->isMyHostAlias(requestUri); if (mpSipUserAgent && domain != _localDomain && isMyHostAlias) { isDomainAlias = true; hostAlias = domain; requestUri.setHostAddress(_localDomain); } UtlString requestIdentity; requestUri.getIdentity(requestIdentity); OS_LOG_DEBUG(FAC_SIP, mLogName.data() << "::lookUp identity: " << requestIdentity.data() << " domain: " << domain.data() << " local-domain: " << _localDomain.data() << " isHostAlias: " << isMyHostAlias); //ResultSet aliases; //AliasDB::getInstance()->getContacts(requestUri, aliases); //int numAliasContacts = aliases.getSize(); EntityDB::Aliases aliases; bool isUserIdentity = false; EntityDB* entityDb = SipRegistrar::getInstance(NULL)->getEntityDB(); entityDb->getAliasContacts(requestUri, aliases, isUserIdentity); int numAliasContacts = aliases.size(); if (numAliasContacts > 0) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::lookUp " "got %d AliasDB contacts", mLogName.data(), numAliasContacts); // Check if the request identity is a real user/extension UtlString realm; UtlString authType; SipXauthIdentity authIdentity; authIdentity.setIdentity(requestIdentity); for (EntityDB::Aliases::iterator iter = aliases.begin(); iter != aliases.end(); iter++) { // If disableForwarding and the relation value is "userforward", // do not record this contact. if (!(disableForwarding && iter->relation == ALIASDB_RELATION_USERFORWARD)) { UtlString contact = iter->contact.c_str(); Url contactUri(contact); // if the request identity is a real user if (isUserIdentity) { // Encode AuthIdentity into the URI authIdentity.encodeUri(contactUri, message); } contactUri.setUrlParameter(SIP_SIPX_CALL_DEST_FIELD, "AL"); if (numAliasContacts == 1 && isDomainAlias && isUserIdentity) { UtlString userId; contactUri.getUserId(userId); requestUri.setUserId(userId.data()); requestUri.getUri(requestString); OS_LOG_NOTICE(FAC_SIP, "SipRedirectorAliasDB::lookUp normalized request-uri to " << requestString.data()); } else { // Add the contact. contactList.add( contactUri, *this ); } } } } else if (isDomainAlias) { // // No alias found. If this is was towards a domain alias, make sure to reset it back to // the old value prior to feeding it to the rest of the redirectors. // requestUri.setHostAddress(hostAlias); requestUri.getUri(requestString); } return RedirectPlugin::SUCCESS; }
RedirectPlugin::LookUpStatus SipRedirectorAliasDB::lookUp( const SipMessage& message, UtlString& requestString, Url& requestUri, const UtlString& method, ContactList& contactList, RequestSeqNo requestSeqNo, int redirectorNo, SipRedirectorPrivateStorage*& privateStorage, ErrorDescriptor& errorDescriptor) { // If url param sipx-userforward = false, do not redirect to user-forward // aliases. UtlString userforwardParam; requestUri.getUrlParameter("sipx-userforward", userforwardParam); bool disableForwarding = userforwardParam.compareTo("false", UtlString::ignoreCase) == 0; if (disableForwarding) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::lookUp user forwarding disabled by parameter", mLogName.data()); } if (_enableEarlyAliasResolution) { resolveAlias(message, requestString, requestUri); } UtlString requestIdentity; requestUri.getIdentity(requestIdentity); EntityDB::Aliases aliases; bool isUserIdentity = false; EntityDB* entityDb = SipRegistrar::getInstance(NULL)->getEntityDB(); entityDb->getAliasContacts(requestUri, aliases, isUserIdentity); int numAliasContacts = aliases.size(); if (numAliasContacts > 0) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::lookUp " "got %d AliasDB contacts", mLogName.data(), numAliasContacts); // Check if the request identity is a real user/extension UtlString realm; UtlString authType; SipXauthIdentity authIdentity; authIdentity.setIdentity(requestIdentity); for (EntityDB::Aliases::iterator iter = aliases.begin(); iter != aliases.end(); iter++) { // If disableForwarding and the relation value is "userforward", // do not record this contact. if (!(disableForwarding && iter->relation == ALIASDB_RELATION_USERFORWARD)) { UtlString contact = iter->contact.c_str(); Url contactUri(contact); // if the request identity is a real user if (isUserIdentity) { // Encode AuthIdentity into the URI authIdentity.encodeUri(contactUri, message); } contactUri.setUrlParameter(SIP_SIPX_CALL_DEST_FIELD, "AL"); contactList.add( contactUri, *this ); if (_enableDiversionHeader && contactList.getDiversionHeader().empty()) { // // Add a Diversion header for all deflections // UtlString stringUri; message.getRequestUri(&stringUri); // The requestUri is an addr-spec, not a name-addr. Url diversionUri(stringUri, TRUE); UtlString userId; diversionUri.getUserId(userId); UtlString host; diversionUri.getHostWithPort(host); std::ostringstream strm; strm << "<sip:"; if (!userId.isNull()) strm << userId.data() << "@"; strm << host.data(); strm << ">;reason=unconditional;sipxfwd=" << iter->relation; UtlString diversion = strm.str().c_str(); OS_LOG_INFO(FAC_SIP, "SipRedirectorAliasDB::lookUp inserting diversion from " << diversion.data()); contactList.setDiversionHeader(diversion.data()); } } } } return RedirectPlugin::SUCCESS; }
RedirectPlugin::LookUpStatus SipRedirectorAliasDB::lookUp( const SipMessage& message, const UtlString& requestString, const Url& requestUri, const UtlString& method, ContactList& contactList, RequestSeqNo requestSeqNo, int redirectorNo, SipRedirectorPrivateStorage*& privateStorage, ErrorDescriptor& errorDescriptor) { // If url param sipx-userforward = false, do not redirect to its aliases UtlString disableForwarding; requestUri.getUrlParameter("sipx-userforward", disableForwarding); if (disableForwarding.compareTo("false", UtlString::ignoreCase) == 0) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::lookUp user forwarding disabled by parameter", mLogName.data()); } else { UtlString requestIdentity; requestUri.getIdentity(requestIdentity); OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::lookUp identity '%s'", mLogName.data(), requestIdentity.data()); ResultSet aliases; AliasDB::getInstance()->getContacts(requestUri, aliases); int numAliasContacts = aliases.getSize(); if (numAliasContacts > 0) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s::lookUp " "got %d AliasDB contacts", mLogName.data(), numAliasContacts); // Check if the request identity is a real user/extension UtlString realm; UtlString authType; bool isUserIdentity = CredentialDB::getInstance()->isUriDefined(requestUri, realm, authType); SipXauthIdentity authIdentity; authIdentity.setIdentity(requestIdentity); for (int i = 0; i < numAliasContacts; i++) { static UtlString contactKey("contact"); UtlHashMap record; if (aliases.getIndex(i, record)) { UtlString contact = *((UtlString*)record.findValue(&contactKey)); Url contactUri(contact); // if the request identity is a real user if (isUserIdentity) { // Encode AuthIdentity into the URI authIdentity.encodeUri(contactUri, message); } contactUri.setUrlParameter(SIP_SIPX_CALL_DEST_FIELD, "AL"); // Add the contact. contactList.add( contactUri, *this ); } } } } return RedirectPlugin::SUCCESS; }