@@ -0,0 +1 @@ | |||
xn--cckl0itdpc9763ahlyc.tv |
@@ -0,0 +1,178 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Specialized; | |||
using System.IO; | |||
using System.Linq; | |||
using System.ServiceModel.Channels; | |||
using System.Web; | |||
using System.Web.Caching; | |||
using System.Web.Helpers; | |||
using System.Web.Mvc; | |||
using System.Web.Routing; | |||
using Teknik.Areas.Error.Controllers; | |||
using Teknik.Configuration; | |||
namespace Teknik.Modules | |||
{ | |||
public class BlacklistModule : IHttpModule | |||
{ | |||
private EventHandler onBeginRequest; | |||
public BlacklistModule() | |||
{ | |||
onBeginRequest = new EventHandler(this.HandleBeginRequest); | |||
} | |||
void IHttpModule.Dispose() | |||
{ | |||
} | |||
void IHttpModule.Init(HttpApplication context) | |||
{ | |||
context.BeginRequest += onBeginRequest; | |||
} | |||
#region Referrer Info | |||
private const string BLOCKEDREFERRERKEY = "BlockedReferrer"; | |||
private static string referrerFileName = null; | |||
private static object referrerFileNameObj = new object(); | |||
public static string GetReferrerFilePath() | |||
{ | |||
if (referrerFileName != null) | |||
return referrerFileName; | |||
lock (referrerFileNameObj) | |||
{ | |||
if (referrerFileName == null) | |||
{ | |||
Config config = Config.Load(); | |||
referrerFileName = config.ReferrerBlacklistFile; | |||
} | |||
} | |||
return referrerFileName; | |||
} | |||
#endregion | |||
#region IP Info | |||
private const string BLOCKEDIPKEY = "BlockedIP"; | |||
private static string ipFileName = null; | |||
private static object ipFileNameObj = new object(); | |||
public static string GetIPFilePath() | |||
{ | |||
if (ipFileName != null) | |||
return ipFileName; | |||
lock (ipFileNameObj) | |||
{ | |||
if (ipFileName == null) | |||
{ | |||
Config config = Config.Load(); | |||
ipFileName = config.IPBlacklistFile; | |||
} | |||
} | |||
return ipFileName; | |||
} | |||
#endregion | |||
public static StringDictionary GetFileData(HttpContext context, string key, Func<string> fn) | |||
{ | |||
StringDictionary data = (StringDictionary)context.Cache[key]; | |||
if (data == null) | |||
{ | |||
string filePath = fn(); | |||
data = GetFileLines(filePath); | |||
context.Cache.Insert(key, data, new CacheDependency(filePath)); | |||
} | |||
return data; | |||
} | |||
public static StringDictionary GetFileLines(string configPath) | |||
{ | |||
StringDictionary retval = new StringDictionary(); | |||
if (File.Exists(configPath)) | |||
{ | |||
using (StreamReader sr = new StreamReader(configPath)) | |||
{ | |||
String line; | |||
while ((line = sr.ReadLine()) != null) | |||
{ | |||
line = line.Trim(); | |||
if (line.Length != 0) | |||
{ | |||
retval.Add(line, null); | |||
} | |||
} | |||
} | |||
} | |||
return retval; | |||
} | |||
private void HandleBeginRequest(object sender, EventArgs evargs) | |||
{ | |||
HttpApplication app = sender as HttpApplication; | |||
if (app != null) | |||
{ | |||
bool blocked = false; | |||
string blockReason = string.Empty; | |||
#region Detect Blacklisted IPs | |||
if (!blocked) | |||
{ | |||
string IPAddr = app.Context.Request.ServerVariables["REMOTE_ADDR"]; | |||
if (!string.IsNullOrEmpty(IPAddr)) | |||
{ | |||
StringDictionary badIPs = GetFileData(app.Context, BLOCKEDIPKEY, GetIPFilePath); | |||
blocked |= (badIPs != null && badIPs.ContainsKey(IPAddr)); | |||
blockReason = $"This IP address ({IPAddr}) has been blacklisted. If you feel this is in error, please contact support@teknik.io for assistance."; | |||
} | |||
} | |||
#endregion | |||
#region Detect Blacklisted Referrers | |||
if (!blocked) | |||
{ | |||
string referrer = app.Context.Request.UrlReferrer?.Host; | |||
if (!string.IsNullOrEmpty(referrer)) | |||
{ | |||
StringDictionary badReferrers = GetFileData(app.Context, BLOCKEDREFERRERKEY, GetReferrerFilePath); | |||
blocked |= (badReferrers != null && badReferrers.ContainsKey(referrer)); | |||
blockReason = $"This referrer ({referrer}) has been blacklisted. If you feel this is in error, please contact support@teknik.io for assistance."; | |||
} | |||
} | |||
#endregion | |||
if (blocked) | |||
{ | |||
// Clear the response | |||
app.Context.Response.Clear(); | |||
RouteData routeData = new RouteData(); | |||
routeData.DataTokens.Add("namespaces", new[] { typeof(ErrorController).Namespace }); | |||
routeData.DataTokens.Add("area", "Error"); | |||
routeData.Values.Add("controller", "Error"); | |||
routeData.Values.Add("scheme", "https"); | |||
routeData.Values.Add("action", "Http403"); | |||
// Clear the error on server. | |||
app.Context.Server.ClearError(); | |||
// Avoid IIS7 getting in the middle | |||
app.Context.Response.TrySkipIisCustomErrors = true; | |||
string jsonResult = Json.Encode(new { error = new { type = "Blacklist", message = blockReason } }); | |||
app.Context.Response.Write(jsonResult); | |||
app.Context.Response.End(); | |||
return; | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -29,46 +29,45 @@ namespace Teknik.Modules | |||
string username = string.Empty; | |||
bool hasAuthToken = false; | |||
if (context.Request != null) | |||
if (context.Request.Headers.HasKeys()) | |||
{ | |||
if (context.Request.Headers.HasKeys()) | |||
string auth = context.Request.Headers["Authorization"]; | |||
if (!string.IsNullOrEmpty(auth)) | |||
{ | |||
string auth = context.Request.Headers["Authorization"]; | |||
if (!string.IsNullOrEmpty(auth)) | |||
string[] parts = auth.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); | |||
string type = string.Empty; | |||
string value = string.Empty; | |||
if (parts.Length > 0) | |||
{ | |||
string[] parts = auth.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); | |||
string type = string.Empty; | |||
string value = string.Empty; | |||
if (parts.Length > 0) | |||
{ | |||
type = parts[0].ToLower(); | |||
} | |||
if (parts.Length > 1) | |||
{ | |||
value = parts[1]; | |||
} | |||
type = parts[0].ToLower(); | |||
} | |||
using (TeknikEntities entities = new TeknikEntities()) | |||
if (parts.Length > 1) | |||
{ | |||
value = parts[1]; | |||
} | |||
using (TeknikEntities entities = new TeknikEntities()) | |||
{ | |||
// Get the user information based on the auth type | |||
switch (type) | |||
{ | |||
// Get the user information based on the auth type | |||
switch (type) | |||
{ | |||
case "basic": | |||
KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value); | |||
case "basic": | |||
KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value); | |||
bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value); | |||
if (tokenValid) | |||
{ | |||
// it's valid, so let's update it's Last Used date | |||
UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now); | |||
bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value); | |||
if (tokenValid) | |||
{ | |||
// it's valid, so let's update it's Last Used date | |||
UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now); | |||
// Set the username | |||
username = authCreds.Key; | |||
} | |||
// Set the username | |||
username = authCreds.Key; | |||
} | |||
break; | |||
default: | |||
break; | |||
} | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
} |
@@ -321,6 +321,7 @@ | |||
<Compile Include="Areas\Vault\ViewModels\VaultItemViewModel.cs" /> | |||
<Compile Include="Attributes\TeknikAuthorizeAttribute.cs" /> | |||
<Compile Include="Hubs\IRCClientHub.cs" /> | |||
<Compile Include="Modules\BlacklistModule.cs" /> | |||
<Compile Include="Modules\UserAuthModule.cs" /> | |||
<Compile Include="Security\ITeknikPrincipal.cs" /> | |||
<Compile Include="Security\TeknikPrincipal.cs" /> | |||
@@ -395,6 +396,8 @@ | |||
<Compile Include="BaseViewPage.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Content Include="App_Data\ipBlacklist.txt" /> | |||
<Content Include="App_Data\referrerBlacklist.txt" /> | |||
<Content Include="App_Data\reservedUsernames.txt"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</Content> |
@@ -56,6 +56,7 @@ | |||
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" /> | |||
<add name="PerfModule" type="Teknik.Modules.PerformanceMonitorModule, Teknik" /> | |||
<add name="UserAuthModule" type="Teknik.Modules.UserAuthModule, Teknik" /> | |||
<add name="BlacklistModule" type="Teknik.Modules.BlacklistModule, Teknik" /> | |||
<remove name="UrlRoutingModule-4.0" /> | |||
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" /> | |||
</modules> |
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.IO; | |||
using System.Threading; | |||
using Newtonsoft.Json; | |||
@@ -29,6 +29,8 @@ namespace Teknik.Configuration | |||
private string _Salt1; | |||
private string _Salt2; | |||
private string _CdnHost; | |||
private string _IPBlacklistFile; | |||
private string _ReferrerBlacklistFile; | |||
private UserConfig _UserConfig; | |||
private ContactConfig _ContactConfig; | |||
private EmailConfig _EmailConfig; | |||
@@ -46,21 +48,23 @@ namespace Teknik.Configuration | |||
private PiwikConfig _PiwikConfig; | |||
private IRCConfig _IRCConfig; | |||
public bool DevEnvironment { get { return _DevEnvironment; } set { _DevEnvironment = value; } } | |||
public bool Migrate { get { return _Migrate; } set { _Migrate = value; } } | |||
public bool UseCdn { get { return _UseCdn; } set { _UseCdn = value; } } | |||
public bool DevEnvironment { get { return _DevEnvironment; } set { _DevEnvironment = value; } } | |||
public bool Migrate { get { return _Migrate; } set { _Migrate = value; } } | |||
public bool UseCdn { get { return _UseCdn; } set { _UseCdn = value; } } | |||
// Site Information | |||
public string Title { get { return _Title; } set { _Title = value; } } | |||
public string Description { get { return _Description; } set { _Description = value; } } | |||
public string Author { get { return _Author; } set { _Author = value; } } | |||
public string Host { get { return _Host; } set { _Host = value; } } | |||
public string SupportEmail { get { return _SupportEmail; } set { _SupportEmail = value; } } | |||
public string NoReplyEmail { get { return _NoReplyEmail; } set { _NoReplyEmail = value; } } | |||
public string BitcoinAddress { get { return _BitcoinAddress; } set { _BitcoinAddress = value; } } | |||
public string Salt1 { get { return _Salt1; } set { _Salt1 = value; } } | |||
public string Salt2 { get { return _Salt2; } set { _Salt2 = value; } } | |||
public string CdnHost { get { return _CdnHost; } set { _CdnHost = value; } } | |||
public string Title { get { return _Title; } set { _Title = value; } } | |||
public string Description { get { return _Description; } set { _Description = value; } } | |||
public string Author { get { return _Author; } set { _Author = value; } } | |||
public string Host { get { return _Host; } set { _Host = value; } } | |||
public string SupportEmail { get { return _SupportEmail; } set { _SupportEmail = value; } } | |||
public string NoReplyEmail { get { return _NoReplyEmail; } set { _NoReplyEmail = value; } } | |||
public string BitcoinAddress { get { return _BitcoinAddress; } set { _BitcoinAddress = value; } } | |||
public string Salt1 { get { return _Salt1; } set { _Salt1 = value; } } | |||
public string Salt2 { get { return _Salt2; } set { _Salt2 = value; } } | |||
public string CdnHost { get { return _CdnHost; } set { _CdnHost = value; } } | |||
public string IPBlacklistFile { get { return _IPBlacklistFile;} set { _IPBlacklistFile = value; }} | |||
public string ReferrerBlacklistFile { get { return _ReferrerBlacklistFile;} set { _ReferrerBlacklistFile = value; }} | |||
// User Configuration | |||
public UserConfig UserConfig { get { return _UserConfig; } set { _UserConfig = value; } } | |||
@@ -122,35 +126,37 @@ namespace Teknik.Configuration | |||
public void SetDefaults() | |||
{ | |||
DevEnvironment = false; | |||
Migrate = false; | |||
UseCdn = false; | |||
Title = string.Empty; | |||
Description = string.Empty; | |||
Author = string.Empty; | |||
Host = string.Empty; | |||
SupportEmail = string.Empty; | |||
NoReplyEmail = string.Empty; | |||
BitcoinAddress = string.Empty; | |||
Salt1 = string.Empty; | |||
Salt2 = string.Empty; | |||
CdnHost = string.Empty; | |||
UserConfig = new UserConfig(); | |||
EmailConfig = new EmailConfig(); | |||
ContactConfig = new ContactConfig(); | |||
GitConfig = new GitConfig(); | |||
BlogConfig = new BlogConfig(); | |||
UploadConfig = new UploadConfig(); | |||
PasteConfig = new PasteConfig(); | |||
ApiConfig = new ApiConfig(); | |||
PodcastConfig = new PodcastConfig(); | |||
StreamConfig = new StreamConfig(); | |||
ShortenerConfig = new ShortenerConfig(); | |||
VaultConfig = new VaultConfig(); | |||
StatusConfig = new StatusConfig(); | |||
LoggingConfig = new LoggingConfig(); | |||
PiwikConfig = new PiwikConfig(); | |||
IRCConfig = new IRCConfig(); | |||
DevEnvironment = false; | |||
Migrate = false; | |||
UseCdn = false; | |||
Title = string.Empty; | |||
Description = string.Empty; | |||
Author = string.Empty; | |||
Host = string.Empty; | |||
SupportEmail = string.Empty; | |||
NoReplyEmail = string.Empty; | |||
BitcoinAddress = string.Empty; | |||
Salt1 = string.Empty; | |||
Salt2 = string.Empty; | |||
CdnHost = string.Empty; | |||
IPBlacklistFile = string.Empty; | |||
ReferrerBlacklistFile = string.Empty; | |||
UserConfig = new UserConfig(); | |||
EmailConfig = new EmailConfig(); | |||
ContactConfig = new ContactConfig(); | |||
GitConfig = new GitConfig(); | |||
BlogConfig = new BlogConfig(); | |||
UploadConfig = new UploadConfig(); | |||
PasteConfig = new PasteConfig(); | |||
ApiConfig = new ApiConfig(); | |||
PodcastConfig = new PodcastConfig(); | |||
StreamConfig = new StreamConfig(); | |||
ShortenerConfig = new ShortenerConfig(); | |||
VaultConfig = new VaultConfig(); | |||
StatusConfig = new StatusConfig(); | |||
LoggingConfig = new LoggingConfig(); | |||
PiwikConfig = new PiwikConfig(); | |||
IRCConfig = new IRCConfig(); | |||
} | |||
public static Config Deserialize(string text) | |||
@@ -210,4 +216,4 @@ namespace Teknik.Configuration | |||
File.WriteAllText(path, configContents); | |||
} | |||
} | |||
} | |||
} |