/// <summary> /// Cancels an in progress call. This method should be called prior to the remote user agent server answering the call. /// </summary> public void Cancel() { try { m_callCancelled = true; // Cancel server call. if (m_serverTransaction == null) { logger.LogDebug("Cancelling forwarded call leg " + m_sipCallDescriptor.Uri + ", server transaction has not been created yet no CANCEL request required."); } else if (m_cancelTransaction != null) { if (m_cancelTransaction.TransactionState != SIPTransactionStatesEnum.Completed) { logger.LogDebug("Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already been cancelled once, trying again."); m_cancelTransaction.SendRequest(); } else { logger.LogDebug("Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already responded to CANCEL, probably overlap in messages not re-sending."); } } else //if (m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding || m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Trying) { logger.LogDebug("Cancelling forwarded call leg, sending CANCEL to " + m_serverTransaction.TransactionRequest.URI.ToString() + "."); // No response has been received from the server so no CANCEL request necessary, stop any retransmits of the INVITE. m_serverTransaction.CancelCall(); SIPRequest cancelRequest = GetCancelRequest(m_serverTransaction.TransactionRequest); // If auth header is included inside INVITE request, we re-include them inside CANCEL request if (m_serverTransaction.TransactionRequest.Header.HasAuthenticationHeader) { string username = (m_sipCallDescriptor.AuthUsername == null || m_sipCallDescriptor.AuthUsername.Trim().Length <= 0 ? m_sipCallDescriptor.Username : m_sipCallDescriptor.AuthUsername); SIPAuthorisationDigest authDigest = m_serverTransaction.TransactionRequest.Header.AuthenticationHeaders.First().SIPDigest; authDigest.SetCredentials(username, m_sipCallDescriptor.Password, m_sipCallDescriptor.Uri, SIPMethodsEnum.CANCEL.ToString()); var authHeader = new SIPAuthenticationHeader(authDigest); authHeader.SIPDigest.IncrementNonceCount(); authHeader.SIPDigest.Response = authDigest.GetDigest(); cancelRequest.Header.AuthenticationHeaders.Clear(); cancelRequest.Header.AuthenticationHeaders.Add(authHeader); } m_cancelTransaction = new SIPNonInviteTransaction(m_sipTransport, cancelRequest, m_outboundProxy); m_cancelTransaction.SendRequest(); } CallFailed?.Invoke(this, "Call cancelled by user.", null); } catch (Exception excp) { logger.LogError("Exception CancelServerCall. " + excp.Message); } }
/// <summary> /// Authenticates a SIP request. /// </summary> public static SIPRequestAuthenticationResult AuthenticateSIPRequest( SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest, ISIPAccount sipAccount) { try { if (sipAccount == null) { return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null)); } else if (sipAccount.IsDisabled) { logger.LogWarning($"SIP account {sipAccount.SIPUsername}@{sipAccount.SIPDomain} is disabled for {sipRequest.Method}."); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null)); } else { if (!sipRequest.Header.HasAuthenticationHeader) { // Check for IP address authentication. //if (!sipAccount.IPAddressACL.IsNullOrBlank()) //{ // SIPEndPoint uaEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : remoteEndPoint; // if (Regex.Match(uaEndPoint.GetIPEndPoint().ToString(), sipAccount.IPAddressACL).Success) // { // // Successfully authenticated // return new SIPRequestAuthenticationResult(true, true); // } //} SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader)); } else { // Check for IP address authentication. //if (!sipAccount.IPAddressACL.IsNullOrBlank()) //{ // SIPEndPoint uaEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : remoteEndPoint; // if (Regex.Match(uaEndPoint.GetIPEndPoint().ToString(), sipAccount.IPAddressACL).Success) // { // // Successfully authenticated // return new SIPRequestAuthenticationResult(true, true); // } //} SIPAuthenticationHeader reqAuthHeader = sipRequest.Header.AuthenticationHeaders.First(); string requestNonce = reqAuthHeader.SIPDigest.Nonce; string uri = reqAuthHeader.SIPDigest.URI; string response = reqAuthHeader.SIPDigest.Response; // Check for stale nonces. if (IsNonceStale(requestNonce)) { logger.LogWarning($"Authentication failed stale nonce for realm={sipAccount.SIPDomain}, username={sipAccount.SIPUsername}, uri={uri}, nonce={requestNonce}, method={sipRequest.Method}."); SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader)); } else { SIPAuthorisationDigest checkAuthReq = reqAuthHeader.SIPDigest; if (sipAccount.SIPPassword != null) { checkAuthReq.SetCredentials(sipAccount.SIPUsername, sipAccount.SIPPassword, uri, sipRequest.Method.ToString()); } else if (sipAccount.HA1Digest != null) { checkAuthReq.SetCredentials(sipAccount.HA1Digest, uri, sipRequest.Method.ToString()); } else { throw new ApplicationException("SIP authentication cannot be attempted as neither a password or HA1 digest are available."); } string digest = checkAuthReq.GetDigest(); if (digest == response) { // Successfully authenticated return(new SIPRequestAuthenticationResult(true, false)); } else { logger.LogWarning("Authentication token check failed for realm=" + sipAccount.SIPDomain + ", username="******", uri=" + uri + ", nonce=" + requestNonce + ", method=" + sipRequest.Method + "."); SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader)); } } } } } catch (Exception excp) { logger.LogError(0, excp, "Exception AuthoriseSIPRequest. " + excp.Message); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.InternalServerError, null)); } }