Skip to content

Commit

Permalink
Fixed a bug where overage handler could be bypassed.
Browse files Browse the repository at this point in the history
  • Loading branch information
niemyjski committed Oct 5, 2016
1 parent 4af9be8 commit 35f305e
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 30 deletions.
6 changes: 3 additions & 3 deletions Source/Api/AppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static void Build(IAppBuilder app, Container container = null) {

if (Settings.Current.WebsiteMode == WebsiteMode.Dev)
Task.Run(async () => await CreateSampleDataAsync(container));

var context = new OwinContext(app.Properties);
var token = context.Get<CancellationToken>("host.OnAppDisposing");
RunMessageBusBroker(container, logger, token);
Expand All @@ -97,7 +97,7 @@ public static void Build(IAppBuilder app, Container container = null) {
private static void RunMessageBusBroker(Container container, ILogger logger, CancellationToken token = default(CancellationToken)) {
var workItemQueue = container.GetInstance<IQueue<WorkItemData>>();
var subscriber = container.GetInstance<IMessageSubscriber>();

subscriber.Subscribe<PlanOverage>(async overage => {
logger.Info("Enqueueing plan overage work item for organization: {0} IsOverHourlyLimit: {1} IsOverMonthlyLimit: {2}", overage.OrganizationId, overage.IsHourly, !overage.IsHourly);
await workItemQueue.EnqueueAsync(new OrganizationNotificationWorkItem {
Expand Down Expand Up @@ -212,7 +212,7 @@ public static Container CreateContainer(ILoggerFactory loggerFactory, ILogger lo

Core.Bootstrapper.RegisterServices(container, loggerFactory);
Bootstrapper.RegisterServices(container, loggerFactory);

if (!includeInsulation)
return container;

Expand Down
12 changes: 0 additions & 12 deletions Source/Api/Controllers/EventController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -769,18 +769,6 @@ await _eventPostQueue.EnqueueAsync(new EventPostInfo {
// Set the project for the configuration response filter.
Request.SetProject(project);

if (data.LongLength > Settings.Current.MaximumEventPostSize) {
_logger.Error().Critical()
.Message("Attempting to enqueue events greater than the maxiumum queue size")
.Project(projectId)
.Identity(ExceptionlessUser?.EmailAddress)
.Property("User", ExceptionlessUser)
.Property("Headers", Request.Content.Headers)
.Property("Size", data.LongLength)
.Property("MaximumEventPostSize", Settings.Current.MaximumEventPostSize)
.SetActionContext(ActionContext);
}

string contentEncoding = Request.Content.Headers.ContentEncoding.ToString();
bool isCompressed = contentEncoding == "gzip" || contentEncoding == "deflate";
if (!isCompressed && data.Length > 1000) {
Expand Down
8 changes: 6 additions & 2 deletions Source/Api/Utility/Handlers/OverageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ private bool IsEventPost(HttpRequestMessage request) {
if (request.Method != HttpMethod.Post)
return false;

return request.RequestUri.AbsolutePath.EndsWith("/events", StringComparison.OrdinalIgnoreCase)
|| String.Equals(request.RequestUri.AbsolutePath, "/api/v1/error", StringComparison.OrdinalIgnoreCase);
string absolutePath = request.RequestUri.AbsolutePath;
if (absolutePath.EndsWith("/"))
absolutePath = absolutePath.Substring(0, absolutePath.Length - 1);

return absolutePath.EndsWith("/events", StringComparison.OrdinalIgnoreCase)
|| String.Equals(absolutePath, "/api/v1/error", StringComparison.OrdinalIgnoreCase);
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
Expand Down
12 changes: 8 additions & 4 deletions Source/Api/Utility/Handlers/ThrottlingHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public ThrottlingHandler(ICacheClient cacheClient, IMetricsClient metricsClient,
_period = period;
_message = message;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
if (IsUnthrottledRoute(request))
return await base.SendAsync(request, cancellationToken);
Expand Down Expand Up @@ -96,9 +96,13 @@ private bool IsUnthrottledRoute(HttpRequestMessage request) {
if (request.Method != HttpMethod.Get)
return false;

return request.RequestUri.AbsolutePath.EndsWith("/events/session/heartbeat", StringComparison.OrdinalIgnoreCase)
|| request.RequestUri.AbsolutePath.EndsWith("/projects/config", StringComparison.OrdinalIgnoreCase)
|| request.RequestUri.AbsolutePath.StartsWith("/api/v2/push", StringComparison.OrdinalIgnoreCase);
string absolutePath = request.RequestUri.AbsolutePath;
if (absolutePath.EndsWith("/"))
absolutePath = absolutePath.Substring(0, absolutePath.Length - 1);

return absolutePath.EndsWith("/events/session/heartbeat", StringComparison.OrdinalIgnoreCase)
|| absolutePath.EndsWith("/projects/config", StringComparison.OrdinalIgnoreCase)
|| absolutePath.StartsWith("/api/v2/push", StringComparison.OrdinalIgnoreCase);
}
}
}
6 changes: 4 additions & 2 deletions Source/Api/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<system.web>
<authentication mode="None" />
<compilation targetFramework="4.6" debug="false" />
<httpRuntime targetFramework="4.6" maxUrlLength="1024" />
<httpRuntime targetFramework="4.6" maxRequestLength="10000" maxUrlLength="1024" />
<customErrors mode="RemoteOnly" defaultRedirect="~/error.html" />
</system.web>
<system.webServer>
Expand Down Expand Up @@ -80,7 +80,9 @@
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<security>
<requestFiltering allowDoubleEscaping="true" />
<requestFiltering allowDoubleEscaping="true">
<requestLimits maxAllowedContentLength="10000000" />
</requestFiltering>
</security>
</system.webServer>
<location path="error.html">
Expand Down
16 changes: 16 additions & 0 deletions Source/Core/Extensions/NameValueCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ public static int GetInt(this NameValueCollection collection, string name, int d
return GetInt(collection, name) ?? defaultValue;
}

public static long GetInt64(this NameValueCollection collection, string name, long defaultValue) {
return GetInt64(collection, name) ?? defaultValue;
}

public static long? GetInt64(this NameValueCollection collection, string name) {
var value = collection[name];
if (value == null)
return null;

long number;
if (Int64.TryParse(value, out number))
return number;

return null;
}

public static bool? GetBool(this NameValueCollection collection, string name) {
string value = collection[name];
if (value == null)
Expand Down
12 changes: 6 additions & 6 deletions Source/Core/Mail/Mailer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public Task SendInviteAsync(User sender, Organization organization, Invite invit
BaseUrl = Settings.Current.BaseURL
}, "Invite");
msg.To.Add(invite.EmailAddress);

return QueueMessageAsync(msg, "invite");
}

Expand All @@ -71,7 +71,7 @@ public Task SendPaymentFailedAsync(User owner, Organization organization) {
BaseUrl = Settings.Current.BaseURL
}, "PaymentFailed");
msg.To.Add(owner.EmailAddress);

return QueueMessageAsync(msg, "paymentfailed");
}

Expand All @@ -83,7 +83,7 @@ public Task SendAddedToOrganizationAsync(User sender, Organization organization,
BaseUrl = Settings.Current.BaseURL
}, "AddedToOrganization");
msg.To.Add(user.EmailAddress);

return QueueMessageAsync(msg, "addedtoorganization");
}

Expand All @@ -97,21 +97,21 @@ public Task SendEventNoticeAsync(string emailAddress, EventNotification model) {
msg.To = emailAddress;
return QueueMessageAsync(msg.ToMailMessage(), "eventnotice");
}

public Task SendOrganizationNoticeAsync(string emailAddress, OrganizationNotificationModel model) {
model.BaseUrl = Settings.Current.BaseURL;

System.Net.Mail.MailMessage msg = _emailGenerator.GenerateMessage(model, "OrganizationNotice");
msg.To.Add(emailAddress);

return QueueMessageAsync(msg, "organizationnotice");
}

public Task SendDailySummaryAsync(string emailAddress, DailySummaryModel notification) {
notification.BaseUrl = Settings.Current.BaseURL;
System.Net.Mail.MailMessage msg = _emailGenerator.GenerateMessage(notification, "DailySummary");
msg.To.Add(emailAddress);

return QueueMessageAsync(msg, "dailysummary");
}

Expand Down
5 changes: 4 additions & 1 deletion Source/Core/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class Settings : SettingsBase<Settings> {

public bool EventSubmissionDisabled { get; private set; }

/// <summary>
/// In bytes
/// </summary>
public long MaximumEventPostSize { get; private set; }

public int MaximumRetentionDays { get; private set; }
Expand Down Expand Up @@ -143,7 +146,7 @@ public override void Initialize() {
BotThrottleLimit = GetInt(nameof(BotThrottleLimit), 25);
ApiThrottleLimit = GetInt(nameof(ApiThrottleLimit), Int32.MaxValue);
EventSubmissionDisabled = GetBool(nameof(EventSubmissionDisabled));
MaximumEventPostSize = GetInt(nameof(MaximumEventPostSize), Int32.MaxValue);
MaximumEventPostSize = GetInt64(nameof(MaximumEventPostSize), Int64.MaxValue);
MaximumRetentionDays = GetInt(nameof(MaximumRetentionDays), -1);
EnableDailySummary = GetBool(nameof(EnableDailySummary));
MetricsServerName = GetString(nameof(MetricsServerName)) ?? "127.0.0.1";
Expand Down
9 changes: 9 additions & 0 deletions Source/Core/Utility/SettingsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ protected static int GetInt(string name, int defaultValue = 0) {
return Int32.TryParse(value, out number) ? number : defaultValue;
}

protected static long GetInt64(string name, long defaultValue = 0) {
string value = GetEnvironmentVariable(name) ?? GetConfigVariable(name);
if (String.IsNullOrEmpty(value))
return ConfigurationManager.AppSettings.GetInt64(name, defaultValue);

long number;
return Int64.TryParse(value, out number) ? number : defaultValue;
}

protected static string GetString(string name, string defaultValue = null) {
return GetEnvironmentVariable(name) ?? GetConfigVariable(name) ?? ConfigurationManager.AppSettings[name] ?? defaultValue;
}
Expand Down

0 comments on commit 35f305e

Please sign in to comment.