SendFinalResponse() public method

public SendFinalResponse ( SIPResponse finalResponse ) : void
finalResponse SIPResponse
return void
        private RegisterResultEnum Register(SIPTransaction registerTransaction)
        {
            try
            {
                SIPRequest sipRequest = registerTransaction.TransactionRequest;
                SIPURI registerURI = sipRequest.URI;
                SIPToHeader toHeader = sipRequest.Header.To;
                string toUser = toHeader.ToURI.User;
                string canonicalDomain = (m_strictRealmHandling) ? GetCanonicalDomain_External(toHeader.ToURI.Host, true) : toHeader.ToURI.Host;
                int requestedExpiry = GetRequestedExpiry(sipRequest);

                if (canonicalDomain == null)
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for " + toHeader.ToURI.Host + " rejected as no matching domain found.", null));
                    SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                    registerTransaction.SendFinalResponse(noDomainResponse);
                    return RegisterResultEnum.DomainNotServiced;
                }

                SIPAccount sipAccount = GetSIPAccount_External(s => s.SIPUsername == toUser && s.SIPDomain == canonicalDomain);
                SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator_External(registerTransaction.LocalSIPEndPoint, registerTransaction.RemoteEndPoint, sipRequest, sipAccount, FireProxyLogEvent);

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    registerTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Forbidden " + toUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom.ToString() + ", " + sipRequest.Header.UserAgent + ".", null));
                        return RegisterResultEnum.Forbidden;
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Authentication required for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom.ToString() + ".", toUser));
                        return RegisterResultEnum.AuthenticationRequired;
                    }
                }
                else
                {
                    // Authenticated.
                    if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0)
                    {
                        // No contacts header to update bindings with, return a list of the current bindings.
                        List<SIPRegistrarBinding> bindings = m_registrarBindingsManager.GetBindings(sipAccount.Id);
                        //List<SIPContactHeader> contactsList = m_registrarBindingsManager.GetContactHeader(); // registration.GetContactHeader(true, null);
                        if (bindings != null)
                        {
                            sipRequest.Header.Contact = GetContactHeader(bindings);
                        }

                        SIPResponse okResponse = GetOkResponse(sipRequest);
                        registerTransaction.SendFinalResponse(okResponse);
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Empty registration request successful for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom.ToString() + ".", toUser));
                    }
                    else
                    {
                        SIPEndPoint uacRemoteEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : registerTransaction.RemoteEndPoint;
                        SIPEndPoint proxySIPEndPoint = (!sipRequest.Header.ProxyReceivedOn.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedOn) : null;
                        SIPEndPoint registrarEndPoint = registerTransaction.LocalSIPEndPoint;

                        SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok;
                        string updateMessage = null;

                        DateTime startTime = DateTime.Now;

                        List<SIPRegistrarBinding> bindingsList = m_registrarBindingsManager.UpdateBindings(
                            sipAccount,
                            proxySIPEndPoint,
                            uacRemoteEndPoint,
                            registrarEndPoint,
                            //sipRequest.Header.Contact[0].ContactURI.CopyOf(),
                            sipRequest.Header.Contact,
                            sipRequest.Header.CallId,
                            sipRequest.Header.CSeq,
                            //sipRequest.Header.Contact[0].Expires,
                            sipRequest.Header.Expires,
                            sipRequest.Header.UserAgent,
                            out updateResult,
                            out updateMessage);

                        //int bindingExpiry = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString());
                        TimeSpan duration = DateTime.Now.Subtract(startTime);
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding update time for " + toUser + "@" + canonicalDomain + " took " + duration.TotalMilliseconds + "ms.", null));

                        if (updateResult == SIPResponseStatusCodesEnum.Ok)
                        {
                            string proxySocketStr = (proxySIPEndPoint != null) ? " (proxy=" + proxySIPEndPoint.ToString() + ")" : null;

                            int bindingCount = 1;
                            foreach (SIPRegistrarBinding binding in bindingsList)
                            {
                                string bindingIndex = (bindingsList.Count == 1) ? String.Empty : " (" + bindingCount + ")";
                                //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + proxySocketStr + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser));
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser));
                                //FireProxyLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, toUser, uacRemoteEndPoint, sipAccount.Id.ToString()));
                                bindingCount++;
                            }

                            // The standard states that the Ok response should contain the list of current bindings but that breaks some UAs. As a 
                            // compromise the list is returned with the Contact that UAC sent as the first one in the list.
                            bool contactListSupported = m_userAgentConfigs.GetUserAgentContactListSupport(sipRequest.Header.UserAgent);
                            if (contactListSupported)
                            {
                                sipRequest.Header.Contact = GetContactHeader(bindingsList);
                            }
                            else
                            {
                                // Some user agents can't match the contact header if the expiry is added to it.
                                sipRequest.Header.Contact[0].Expires = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString()); ;
                            }

                            SIPResponse okResponse = GetOkResponse(sipRequest);

                            // If a request was made for a switchboard token and a certificate is available to sign the tokens then generate it.
                            if (sipRequest.Header.SwitchboardTokenRequest > 0 && m_switchbboardRSAProvider != null)
                            {
                                SwitchboardToken token = new SwitchboardToken(sipRequest.Header.SwitchboardTokenRequest, sipAccount.Owner, uacRemoteEndPoint.Address.ToString());

                                lock (m_switchbboardRSAProvider)
                                {
                                    token.SignedHash = Convert.ToBase64String(m_switchbboardRSAProvider.SignHash(Crypto.GetSHAHash(token.GetHashString()), null));
                                }

                                string tokenXML = token.ToXML(true);
                                logger.Debug("Switchboard token set for " + sipAccount.Owner + " with expiry of " + token.Expiry + "s.");
                                okResponse.Header.SwitchboardToken = Crypto.SymmetricEncrypt(sipAccount.SIPPassword, sipRequest.Header.AuthenticationHeader.SIPDigest.Nonce, tokenXML);
                            }

                            registerTransaction.SendFinalResponse(okResponse);
                        }
                        else
                        {
                            // The binding update failed even though the REGISTER request was authorised. This is probably due to a 
                            // temporary problem connecting to the bindings data store. Send Ok but set the binding expiry to the minimum so
                            // that the UA will try again as soon as possible.
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registration request successful but binding update failed for " + toUser + "@" + canonicalDomain + " from " + registerTransaction.RemoteEndPoint + ".", toUser));
                            sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                        }
                    }

                    return RegisterResultEnum.Authenticated;
                }
            }
            catch (Exception excp)
            {
                string regErrorMessage = "Exception registrarcore registering. " + excp.Message + "\r\n" + registerTransaction.TransactionRequest.ToString();
                logger.Error(regErrorMessage);
                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, regErrorMessage, null));

                try
                {
                    SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                    registerTransaction.SendFinalResponse(errorResponse);
                }
                catch { }

                return RegisterResultEnum.Error;
            }
        }
Example #2
0
        private void Subscribe(SIPTransaction subscribeTransaction)
        {
            try
            {
                SIPRequest sipRequest = subscribeTransaction.TransactionRequest;
                string fromUser = sipRequest.Header.From.FromURI.User;
                string fromHost = sipRequest.Header.From.FromURI.Host;
                string canonicalDomain = GetCanonicalDomain_External(fromHost, true);

                if (canonicalDomain == null)
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Subscribe request for " + fromHost + " rejected as no matching domain found.", null));
                    SIPResponse noDomainResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                    subscribeTransaction.SendFinalResponse(noDomainResponse);
                    return;
                }

                SIPAccount sipAccount = m_sipAssetPersistor.Get(s => s.SIPUsername == fromUser && s.SIPDomain == canonicalDomain);
                SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator_External(subscribeTransaction.LocalSIPEndPoint, subscribeTransaction.RemoteEndPoint, sipRequest, sipAccount, FireProxyLogEvent);

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    subscribeTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Forbidden " + fromUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom.ToString() + ", " + sipRequest.Header.UserAgent + ".", null));
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Authentication required for " + fromUser + "@" + canonicalDomain + " from " + subscribeTransaction.RemoteEndPoint + ".", sipAccount.Owner));
                    }
                    return;
                }
                else
                {
                    if (sipRequest.Header.To.ToTag != null)
                    {
                        // Request is to renew an existing subscription.
                        SIPResponseStatusCodesEnum errorResponse = SIPResponseStatusCodesEnum.None;
                        string errorResponseReason = null;

                        string sessionID = m_subscriptionsManager.RenewSubscription(sipRequest, out errorResponse, out errorResponseReason);
                        if (errorResponse != SIPResponseStatusCodesEnum.None)
                        {
                            // A subscription renewal attempt failed
                            SIPResponse renewalErrorResponse = SIPTransport.GetResponse(sipRequest, errorResponse, errorResponseReason);
                            subscribeTransaction.SendFinalResponse(renewalErrorResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription renewal failed for event type " + sipRequest.Header.Event + " " + sipRequest.URI.ToString() + ", " + errorResponse + " " + errorResponseReason + ".", sipAccount.Owner));
                        }
                        else if (sipRequest.Header.Expires == 0)
                        {
                            // Existing subscription was closed.
                            SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                            subscribeTransaction.SendFinalResponse(okResponse);
                        }
                        else
                        {
                            // Existing subscription was found.
                            SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                            subscribeTransaction.SendFinalResponse(okResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeRenew, "Subscription renewal for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + " and expiry " + sipRequest.Header.Expires + ".", sipAccount.Owner));
                            m_subscriptionsManager.SendFullStateNotify(sessionID);
                        }
                    }
                    else
                    {
                        // Authenticated but the this is a new subscription request and authorisation to subscribe to the requested resource also needs to be checked.
                        SIPURI canonicalResourceURI = sipRequest.URI.CopyOf();
                        string resourceCanonicalDomain = GetCanonicalDomain_External(canonicalResourceURI.Host, true);
                        canonicalResourceURI.Host = resourceCanonicalDomain;
                        SIPAccount resourceSIPAccount = null;

                        if (resourceCanonicalDomain == null)
                        {
                            SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Domain " + resourceCanonicalDomain + " not serviced");
                            subscribeTransaction.SendFinalResponse(notFoundResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", domain not serviced.", sipAccount.Owner));
                            return;
                        }

                        if (canonicalResourceURI.User != m_wildcardUser)
                        {
                            resourceSIPAccount = m_sipAssetPersistor.Get(s => s.SIPUsername == canonicalResourceURI.User && s.SIPDomain == canonicalResourceURI.Host);

                            if (resourceSIPAccount == null)
                            {
                                SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Requested resource does not exist");
                                subscribeTransaction.SendFinalResponse(notFoundResponse);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", SIP account does not exist.", sipAccount.Owner));
                                return;
                            }
                        }

                        // Check the owner permissions on the requesting and subscribed resources.
                        bool authorised = false;
                        string adminID = null;

                        if (canonicalResourceURI.User == m_wildcardUser || sipAccount.Owner == resourceSIPAccount.Owner)
                        {
                            authorised = true;
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to common owner.", sipAccount.Owner));
                        }
                        else
                        {
                            // Lookup the customer record for the requestor and check the administrative level on it.
                            Customer requestingCustomer = GetCustomer_External(c => c.CustomerUsername == sipAccount.Owner);
                            adminID = requestingCustomer.AdminId;
                            if (!resourceSIPAccount.AdminMemberId.IsNullOrBlank() && requestingCustomer.AdminId == resourceSIPAccount.AdminMemberId)
                            {
                                authorised = true;
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to requestor admin permissions for domain " + resourceSIPAccount.AdminMemberId + ".", sipAccount.Owner));
                            }
                            else if (requestingCustomer.AdminId == m_topLevelAdminID)
                            {
                                authorised = true;
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to requestor having top level admin permissions.", sipAccount.Owner));
                            }
                        }

                        if (authorised)
                        {
                            // Request is to create a new subscription.
                            SIPResponseStatusCodesEnum errorResponse = SIPResponseStatusCodesEnum.None;
                            string errorResponseReason = null;
                            string toTag = CallProperties.CreateNewTag();
                            string sessionID = m_subscriptionsManager.SubscribeClient(sipAccount.Owner, adminID, sipRequest, toTag, canonicalResourceURI, out errorResponse, out errorResponseReason);

                            if (errorResponse != SIPResponseStatusCodesEnum.None)
                            {
                                SIPResponse subscribeErrorResponse = SIPTransport.GetResponse(sipRequest, errorResponse, errorResponseReason);
                                subscribeTransaction.SendFinalResponse(subscribeErrorResponse);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", " + errorResponse + " " + errorResponseReason + ".", sipAccount.Owner));
                            }
                            else
                            {
                                SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                                okResponse.Header.To.ToTag = toTag;
                                okResponse.Header.Expires = sipRequest.Header.Expires;
                                okResponse.Header.Contact = new List<SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(SIPSchemesEnum.sip, subscribeTransaction.LocalSIPEndPoint)) };
                                subscribeTransaction.SendFinalResponse(okResponse);
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Subscription accepted for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + " and expiry " + sipRequest.Header.Expires + ".", sipAccount.Owner));

                                if (sessionID != null)
                                {
                                    m_subscriptionsManager.SendFullStateNotify(sessionID);
                                }
                            }
                        }
                        else
                        {
                            SIPResponse forbiddenResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Requested resource not authorised");
                            subscribeTransaction.SendFinalResponse(forbiddenResponse);
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", requesting account " + sipAccount.Owner + " was not authorised.", sipAccount.Owner));
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception notifiercore subscribing. " + excp.Message + "\r\n" + subscribeTransaction.TransactionRequest.ToString());
                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Error, "Exception notifiercore subscribing. " + excp.Message, null));
                SIPResponse errorResponse = SIPTransport.GetResponse(subscribeTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                subscribeTransaction.SendFinalResponse(errorResponse);
            }
        }