// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using System; using Microsoft.Data.SqlClient; using System.Net; using System.Text.RegularExpressions; namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall { internal interface IFirewallErrorParser { /// /// Parses given error message and error code to see if it's firewall rule error /// and finds the blocked ip address /// FirewallParserResponse ParseErrorMessage(string errorMessage, int errorCode); /// /// Parses given error message and error code to see if it's firewall rule error /// and finds the blocked ip address /// FirewallParserResponse ParseException(SqlException sqlException); } /// /// Parses an error to check for firewall rule error. Will include the blocked ip address if firewall rule error is detected /// public class FirewallErrorParser : IFirewallErrorParser { /// /// Parses given error message and error code to see if it's firewall rule error /// and finds the blocked ip address /// public FirewallParserResponse ParseException(SqlException sqlException) { CommonUtil.CheckForNull(sqlException, "sqlException"); return ParseErrorMessage(sqlException.Message, sqlException.Number); } /// /// Parses given error message and error code to see if it's firewall rule error /// and finds the blocked ip address /// public FirewallParserResponse ParseErrorMessage(string errorMessage, int errorCode) { CommonUtil.CheckForNull(errorMessage, "errorMessage"); FirewallParserResponse response = new FirewallParserResponse(); if (IsSqlAzureFirewallBlocked(errorCode)) { // Connection failed due to blocked client IP IPAddress clientIp; if (TryParseClientIp(errorMessage, out clientIp)) { response = new FirewallParserResponse(true, clientIp); } } return response; } /// /// Parses the given message to find the blocked ip address /// private static bool TryParseClientIp(string message, out IPAddress clientIp) { clientIp = null; try { #pragma warning disable SYSLIB1045 Regex regex = new Regex( @"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b", RegexOptions.IgnoreCase); #pragma warning restore SYSLIB1045 Match match = regex.Match(message); if (match.Success) { string clientIpValue = match.Value; return IPAddress.TryParse(clientIpValue, out clientIp); } return false; } catch (Exception) { //TODO: trace? return false; } } /// /// Returns true if given error code is firewall rule blocked error code /// private bool IsSqlAzureFirewallBlocked(int errorCode) { return errorCode == SqlAzureFirewallBlockedErrorNumber; } private const int SqlAzureFirewallBlockedErrorNumber = 40615; // http://msdn.microsoft.com/en-us/library/windowsazure/ff394106.aspx } }