public ManualResetEvent DelayMRE; // If the call needs to be delayed DelaySeconds this MRE will be used. /// <summary> /// /// </summary> /// <param name="toSIPAccount"></param> /// <param name="uri">The uri can be different to the to SIP account if a dotted notation is used. For /// example [email protected].</param> /// <param name="fromHeader"></param> /// <param name="contentType"></param> /// <param name="content"></param> public SIPCallDescriptor(SIPAccount toSIPAccount, string uri, string fromHeader, string contentType, string content) { ToSIPAccount = toSIPAccount; Uri = uri ?? toSIPAccount.SIPUsername + "@" + toSIPAccount.SIPDomain; From = fromHeader; ContentType = contentType; Content = content; }
public bool LoadSIPAccountForIncomingCall() { try { bool loaded = false; if (GetSIPAccount_External == null) { // No point trying to authenticate if we haven't been given a delegate to load the SIP account. Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null); } else { m_sipAccount = GetSIPAccount_External(s => s.SIPUsername == m_sipUsername && s.SIPDomain == m_sipDomain); if (m_sipAccount == null) { // A full lookup failed. Now try a partial lookup if the incoming username is in a dotted domain name format. if (m_sipUsername.Contains(".")) { string sipUsernameSuffix = m_sipUsername.Substring(m_sipUsername.LastIndexOf(".") + 1); m_sipAccount = GetSIPAccount_External(s => s.SIPUsername == sipUsernameSuffix && s.SIPDomain == m_sipDomain); } if (m_sipAccount == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Rejecting public " + m_transaction.TransactionRequest.Method + " request for " + m_sipUsername + "@" + m_sipDomain + ", SIP account not found.", null)); Reject(SIPResponseStatusCodesEnum.NotFound, null, null); } else { loaded = true; } } else { loaded = true; } } if (loaded) { SetOwner(m_sipAccount.Owner, m_sipAccount.AdminMemberId); } return(loaded); } catch (Exception excp) { logger.Error("Exception LoadSIPAccountForIncomingCall. " + excp.Message); Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null); return(false); } }
public Dictionary <Guid, object> LoadAssetsFromXMLRecordSet(XmlDocument dom) { try { Dictionary <Guid, object> assets = new Dictionary <Guid, object>(); DataSet sipAssetSet = new DataSet(); XmlTextReader xmlReader = new XmlTextReader(dom.OuterXml, XmlNodeType.Document, null); sipAssetSet.ReadXml(xmlReader); if (sipAssetSet != null && sipAssetSet.Tables != null && sipAssetSet.Tables.Count > 0) { try { foreach (DataRow row in sipAssetSet.Tables[0].Rows) { SIPAccount sipAsset = new SIPAccount(); sipAsset.Load(row); assets.Add(sipAsset.Id, sipAsset); } } catch (Exception excp) { logger.Error("Exception loading SIP asset record in LoadAssetsFromXMLRecordSet (" + (new SIPAccount()).GetType().ToString() + "). " + excp.Message); } logger.Debug(" " + assets.Count + " " + (new SIPAccount()).GetType().ToString() + " assets loaded from XML record set."); } else { //logger.Warn("The XML supplied to LoadAssetsFromXMLRecordSet for asset type " + (new T()).GetType().ToString() + " did not contain any assets."); logger.Debug(" no " + (new SIPAccount()).GetType().ToString() + " assets loaded from XML record set."); } xmlReader.Close(); return(assets); } catch (Exception excp) { logger.Error("Exception LoadAssetsFromXMLRecordSet. " + excp.Message); throw; } }
/// <summary></summary> /// <param name="uacRecvdEndPoint">If this is non-null it indicates the contact header should be mangled based on the public socket the register request was demmed /// to have originated from rather then relying on the contact value recieved from the uac.</param> public SIPRegistrarBinding( SIPAccount sipAccount, SIPURI bindingURI, string callId, int cseq, string userAgent, SIPEndPoint remoteSIPEndPoint, SIPEndPoint proxySIPEndPoint, SIPEndPoint registrarSIPEndPoint, int expiry) { Id = Guid.NewGuid(); LastUpdate = DateTime.UtcNow; SIPAccountId = sipAccount.Id; SIPAccountName = sipAccount.SIPUsername + "@" + sipAccount.SIPDomain; Owner = sipAccount.Owner; AdminMemberId = sipAccount.AdminMemberId; m_contactURI = bindingURI.CopyOf(); m_mangledContactURI = m_contactURI.CopyOf(); CallId = callId; CSeq = cseq; UserAgent = userAgent; RemoteSIPEndPoint = remoteSIPEndPoint; m_proxySIPEndPoint = proxySIPEndPoint; m_registrarSIPEndPoint = registrarSIPEndPoint; //if (SIPTransport.IsPrivateAddress(sipRequest.Header.Contact[0].ContactURI.Host) && m_mangleUACContact) if (!sipAccount.DontMangleEnabled && Regex.Match(m_mangledContactURI.Host, @"(\d+\.){3}\d+").Success) { // The Contact URI Host is used by registrars as the contact socket for the user so it needs to be changed to reflect the socket // the intial request was received on in order to work around NAT. It's no good just relying on private addresses as a lot of User Agents // determine their public IP but NOT their public port so they send the wrong port in the Contact header. //logger.Debug("Mangling contact header from " + m_mangledContactURI.Host + " to " + IPSocket.GetSocketString(uacRecvdEndPoint) + "."); m_mangledContactURI.Host = remoteSIPEndPoint.GetIPEndPoint().ToString(); } m_expiry = expiry; }
public bool AuthenticateCall() { m_isAuthenticated = false; try { if (SIPAuthenticateRequest_External == null) { // No point trying to authenticate if we haven't been given an authentication delegate. Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null); } else if (GetSIPAccount_External == null) { // No point trying to authenticate if we haven't been given a delegate to load the SIP account. Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null); } else { m_sipAccount = GetSIPAccount_External(s => s.SIPUsername == m_sipUsername && s.SIPDomain == m_sipDomain); if (m_sipAccount == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Rejecting authentication required " + m_transaction.TransactionRequest.Method + " for " + m_sipUsername + "@" + m_sipDomain + ", SIP account not found.", null)); Reject(SIPResponseStatusCodesEnum.Forbidden, null, null); } else { SIPRequest sipRequest = m_transaction.TransactionRequest; SIPEndPoint localSIPEndPoint = (!sipRequest.Header.ProxyReceivedOn.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedOn) : sipRequest.LocalSIPEndPoint; SIPEndPoint remoteEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : sipRequest.RemoteSIPEndPoint; SIPRequestAuthenticationResult authenticationResult = SIPAuthenticateRequest_External(localSIPEndPoint, remoteEndPoint, sipRequest, m_sipAccount, Log_External); if (authenticationResult.Authenticated) { if (authenticationResult.WasAuthenticatedByIP) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, m_transaction.TransactionRequest.Method + " request from " + remoteEndPoint.ToString() + " successfully authenticated by IP address.", m_sipAccount.Owner)); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, m_transaction.TransactionRequest.Method + " request from " + remoteEndPoint.ToString() + " successfully authenticated by digest.", m_sipAccount.Owner)); } SetOwner(m_sipAccount.Owner, m_sipAccount.AdminMemberId); m_isAuthenticated = true; } else { // Send authorisation failure or required response SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null); authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, m_transaction.TransactionRequest.Method + " request not authenticated for " + m_sipUsername + "@" + m_sipDomain + ", responding with " + authenticationResult.ErrorResponse + ".", null)); m_transaction.SendFinalResponse(authReqdResponse); } } } } catch (Exception excp) { logger.Error("Exception SIPNonInviteUserAgent AuthenticateCall. " + excp.Message); Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null); } return(m_isAuthenticated); }
public static string ValidateAndClean(SIPAccount sipAccount) { if (sipAccount.Owner.IsNullOrBlank()) { return("The owner must be specified when creating a new SIP account."); } if (sipAccount.SIPUsername.IsNullOrBlank()) { return("The username must be specified when creating a new SIP account."); } if (sipAccount.SIPDomain.IsNullOrBlank()) { return("The domain must be specified when creating a new SIP account."); } else if (sipAccount.SIPUsername.Length < USERNAME_MIN_LENGTH) { return("The username must be at least " + USERNAME_MIN_LENGTH + " characters long."); } else if (Regex.Match(sipAccount.SIPUsername, BANNED_SIPACCOUNT_NAMES).Success) { return("The username you have requested is not permitted."); } else if (Regex.Match(sipAccount.SIPUsername, "[^" + USERNAME_ALLOWED_CHARS + "]").Success) { return("The username had an invalid character, characters permitted are alpha-numeric and .-_."); } else if (sipAccount.SIPUsername.Contains(".") && (sipAccount.SIPUsername.Substring(sipAccount.SIPUsername.LastIndexOf(".") + 1).Trim().Length >= USERNAME_MIN_LENGTH && sipAccount.SIPUsername.Substring(sipAccount.SIPUsername.LastIndexOf(".") + 1).Trim() != sipAccount.Owner)) { return("You are not permitted to create this username. Only user " + sipAccount.SIPUsername.Substring(sipAccount.SIPUsername.LastIndexOf(".") + 1).Trim() + " can create SIP accounts ending in " + sipAccount.SIPUsername.Substring(sipAccount.SIPUsername.LastIndexOf(".")).Trim() + "."); } else if (!sipAccount.IsIncomingOnly || !sipAccount.SIPPassword.IsNullOrBlank()) { if (sipAccount.SIPPassword.IsNullOrBlank()) { return("A password must be specified."); } else if (sipAccount.SIPPassword.Length < PASSWORD_MIN_LENGTH || sipAccount.SIPPassword.Length > PASSWORD_MAX_LENGTH) { return("The password field must be at least " + PASSWORD_MIN_LENGTH + " characters and no more than " + PASSWORD_MAX_LENGTH + " characters."); } else { #region Check the password illegal characters. char[] passwordChars = sipAccount.SIPPassword.ToCharArray(); bool illegalCharFound = false; char illegalChar = ' '; foreach (char passwordChar in passwordChars) { if (Regex.Match(passwordChar.ToString(), "[a-zA-Z0-9]").Success) { continue; } else { bool validChar = false; foreach (char allowedChar in NONAPLPHANUM_ALLOWED_PASSWORD_CHARS) { if (allowedChar == passwordChar) { validChar = true; break; } } if (validChar) { continue; } else { illegalCharFound = true; illegalChar = passwordChar; break; } } } #endregion if (illegalCharFound) { return("Your password has an invalid character " + illegalChar + " it can only contain a to Z, 0 to 9 and characters in this set " + SafeXML.MakeSafeXML(new String(NONAPLPHANUM_ALLOWED_PASSWORD_CHARS)) + "."); } } } sipAccount.Owner = sipAccount.Owner.Trim(); sipAccount.SIPUsername = sipAccount.SIPUsername.Trim(); sipAccount.SIPPassword = (sipAccount.SIPPassword.IsNullOrBlank()) ? null : sipAccount.SIPPassword.Trim(); sipAccount.SIPDomain = sipAccount.SIPDomain.Trim(); return(null); }
/// <summary> /// Authenticates a SIP request. /// </summary> public static SIPRequestAuthenticationResult AuthenticateSIPRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest, SIPAccount sipAccount, SIPMonitorLogDelegate logSIPMonitorEvent) { try { if (sipAccount == null) { return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null)); } else if (sipAccount.IsDisabled) { logSIPMonitorEvent?.Invoke(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.DialPlan, "SIP account " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " is disabled for " + sipRequest.Method + ".", sipAccount.Owner)); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null)); } else { SIPAuthenticationHeader reqAuthHeader = sipRequest.Header.AuthenticationHeader; if (reqAuthHeader == null) { // 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 { return(new SIPRequestAuthenticationResult(true, false)); //// 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); // } //} //string requestNonce = reqAuthHeader.SIPDigest.Nonce; //string uri = reqAuthHeader.SIPDigest.URI; //string response = reqAuthHeader.SIPDigest.Response; //// Check for stale nonces. //if (IsNonceStale(requestNonce)) //{ // if (logSIPMonitorEvent != null) // { // logSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.Warn, "Authentication failed stale nonce for realm=" + sipAccount.SIPDomain + ", username="******", uri=" + uri + ", nonce=" + requestNonce + ", method=" + sipRequest.Method + ".", null)); // } // SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); // return new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader); //} //else //{ // SIPAuthorisationDigest checkAuthReq = reqAuthHeader.SIPDigest; // checkAuthReq.SetCredentials(sipAccount.SIPUsername, sipAccount.SIPPassword, uri, sipRequest.Method.ToString()); // string digest = checkAuthReq.Digest; // if (digest == response) // { // // Successfully authenticated // return new SIPRequestAuthenticationResult(true, false); // } // else // { // if (logSIPMonitorEvent != null) // { // logSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.Warn, "Authentication token check failed for realm=" + sipAccount.SIPDomain + ", username="******", uri=" + uri + ", nonce=" + requestNonce + ", method=" + sipRequest.Method + ".", sipAccount.Owner)); // } // SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); // return new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader); // } //} } } } catch (Exception excp) { logSIPMonitorEvent?.Invoke(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.Error, "Exception AuthoriseSIPRequest. " + excp.Message, null)); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.InternalServerError, null)); } }