Skip to content

Commit

Permalink
Merge 923dc02 into 1480014
Browse files Browse the repository at this point in the history
  • Loading branch information
devtekve authored Nov 21, 2022
2 parents 1480014 + 923dc02 commit 8b42820
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 71 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,5 @@ $RECYCLE.BIN/
# End of https://www.toptal.com/developers/gitignore/api/rider,dotnetcore,aspnetcore,macos,windows
# Ignoring customized settings to avoid commiting sensitive information by accident!
appsettings.*.json
.fleet/**
.fleet/**
/Properties/launchSettings.json
41 changes: 36 additions & 5 deletions GenericHandlerMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
using ISRORBilling.Models.Authentication;
using Microsoft.IdentityModel.Tokens;

namespace ISRORBilling;

public class GenericHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GenericHandlerMiddleware> _logger;
private readonly string? _portalCgiAgentHeader;
private readonly string? _saltKey;

public GenericHandlerMiddleware(RequestDelegate next, ILogger<GenericHandlerMiddleware> logger)
public GenericHandlerMiddleware(RequestDelegate next, ILogger<GenericHandlerMiddleware> logger,
IConfiguration configuration)
{
_next = next;
_logger = logger;
_portalCgiAgentHeader = configuration.GetSection("PortalCGIAgentHeader").Value;
_saltKey = configuration.GetSection("SaltKey").Value;
}

public async Task Invoke(HttpContext context)
{
await _next(context);
var request = context.Request;
var response = context.Response;
if (response.StatusCode == StatusCodes.Status404NotFound)
_logger.LogWarning($"Unhandled [{request.Method}] request received to: {request.Path}{request.QueryString}");
var request = context.Request;

var userAgentHeader = context.Request.Headers.UserAgent;
if (_saltKey.IsNullOrEmpty())
_logger.LogWarning(
"THERE'S NO SALT KEY CONFIGURED IN APPSETTINGS; WE CAN'T VALIDATE IF REQUEST WAS TAMPERED!");

if (_portalCgiAgentHeader.IsNullOrEmpty())
_logger.LogWarning(
"THERE'S NO PORTAL AGENT CONFIGURED IN APPSETTINGS; ANY BROWSER CAN BROWSE YOUR BILLING!");

if (!_portalCgiAgentHeader.IsNullOrEmpty() &&
userAgentHeader.All(userAgent => userAgent != _portalCgiAgentHeader))
{
_logger.LogCritical(
"PORTAL AGENT DOES NOT MATCH; SOMEONE TRYING TO BROWSE YOUR BILLING URL FROM A NORMAL BROWSER\nUserAgent: [{UserAgent}] \nMethod: [{RequestMethod}] \nRequest: [{RequestPath}{RequestQueryString}]",
userAgentHeader, request.Method, request.Path, request.QueryString);
await response.WriteAsync(new AUserLoginResponse
{ ReturnValue = LoginResponseCodeEnum.BrowserAgentNotMatch }.ToString());
}
else
{
await _next(context);
if (context.Response.StatusCode == StatusCodes.Status404NotFound)
_logger.LogWarning("Unhandled [{RequestMethod}] request received to: {RequestPath}{RequestQueryString}",
request.Method, request.Path, request.QueryString);
}
}
}
4 changes: 4 additions & 0 deletions ISRORBilling.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
<PublishSingleFile Condition="'$(Configuration)' == 'Release'">true</PublishSingleFile>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>

<ItemGroup>
<None Remove=".gitignore" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MailKitLite" Version="3.4.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0" />
Expand Down
2 changes: 1 addition & 1 deletion Models/Authentication/AUserLoginResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ public override string ToString()
$"{(VipExpireTime ?? DateTime.Now).ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture)}|" +
$"{(int)(VipUserType ?? Enums.VipUserType.Free)}|" +
$"AFAILUREDESCRIPTION?|" + //This is named "desc" on the error message on the gateway when there's a failure during login.
$"URL-RELATED?|" ; //This is named "url" on the error message on the gateway when there's a failure during login.
$"URL-RELATED?" ; //This is named "url" on the error message on the gateway when there's a failure during login.
}
}
7 changes: 6 additions & 1 deletion Models/Authentication/CheckUserRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ public class CheckUserRequest : GatewayRequest
public string HashedUserPassword { get; }
public string UserIp { get; }
public int UnixTimeStamp { get; }
public int ServiceCompany { get; }
public int RequestTimeoutSeconds { get; }

protected override string CalculatedToken
{
get
Expand All @@ -20,7 +23,7 @@ protected override string CalculatedToken
}
}

public CheckUserRequest(string values, string? saltKey = null)
public CheckUserRequest(string values, string? saltKey = null, int serviceCompany = 11, int requestTimeout = 60)
{
SaltKey = saltKey;
var allValues = values.Split('|');
Expand All @@ -30,5 +33,7 @@ public CheckUserRequest(string values, string? saltKey = null)
UserIp = allValues.ElementAtOrDefault(3) ?? "0";
UnixTimeStamp = int.Parse(allValues.ElementAtOrDefault(4) ?? "0");
UserProvidedValidationToken = allValues.ElementAtOrDefault(5);
ServiceCompany = serviceCompany;
RequestTimeoutSeconds = UnixTimeStamp + requestTimeout;
}
}
5 changes: 4 additions & 1 deletion Models/Authentication/LoginResponseCodeEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ public enum LoginResponseCodeEnum : int
BlockedIp = -131080,
NotSubscribedToService = -131081, //Check if JID is in dbo.AUH_AgreedService
BlockedCountry = -131084,
EmailAuthNotUsed = -262145
EmailAuthNotUsed = -262145,
//Not from JMX
ExpiredRequestUrl = -65561,
BrowserAgentNotMatch = -65562
}
12 changes: 3 additions & 9 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,17 @@
break;
}

var serviceCompany = int.Parse(builder.Configuration.GetSection("ServiceCompany").Value ?? "1");
var requestTimeoutSeconds = int.Parse(builder.Configuration.GetSection("RequestTimeoutSeconds").Value ?? "3600");
var saltKey = builder.Configuration.GetSection("SaltKey").Value ?? string.Empty;
var app = builder.Build();


app.MapGet("/Property/Silkroad-r/checkuser.aspx",
([FromQuery] string values, [FromServices] ILogger<Program> logger, [FromServices] IAuthService authService) =>
{
if(saltKey.IsNullOrEmpty())
logger.LogWarning("THERE'S NO SALT KEY CONFIGURED IN APPSETTINGS; WE CAN'T VALIDATE IF REQUEST WAS TAMPERED!");

logger.LogDebug("Received in params: {Values}", values);
var request = new CheckUserRequest(values, saltKey, serviceCompany, requestTimeoutSeconds);

var request = new CheckUserRequest(values, saltKey);
return authService.Login(request).ToString();
});

Expand All @@ -111,11 +109,7 @@
async ([FromQuery] string values, [FromServices] ILogger<Program> logger, [FromServices] AccountContext accountContext,
[FromServices] INotificationService notificationService) =>
{
if (saltKey.IsNullOrEmpty())
logger.LogWarning("THERE'S NO SALT KEY CONFIGURED IN APPSETTINGS; WE CAN'T VALIDATE IF REQUEST WAS TAMPERED!");

logger.LogDebug("Received in params: {Values}", values);

var request = new SendCodeRequest(values, saltKey);

if (await notificationService.SendItemLockCode(request))
Expand Down
116 changes: 65 additions & 51 deletions Services/Authentication/FullAuthService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ISRORBilling.Database;
using ISRORBilling.Models.Authentication;
using Microsoft.EntityFrameworkCore;
using System.Net;

namespace ISRORBilling.Services.Authentication;

Expand All @@ -21,65 +22,78 @@ public FullAuthService(JoymaxPortalContext joymaxPortalContext, ILogger<FullAuth

public AUserLoginResponse Login(CheckUserRequest request)
{
if (request.RequestTimeoutSeconds < DateTimeOffset.Now.ToUnixTimeSeconds())
{
_logger.LogCritical("Request Login URL is expired [Error Code: {0}]\nDetails: Request UnixTimeStamp({1}) < Now UnixTimeStamp({2})", (int)LoginResponseCodeEnum.ExpiredRequestUrl, request.RequestTimeoutSeconds, DateTimeOffset.Now.ToUnixTimeSeconds());
return new AUserLoginResponse { ReturnValue = LoginResponseCodeEnum.ExpiredRequestUrl };
}

if (!request.Validate())
{
_logger.LogCritical("Couldn't validate if request was legitimate. Ensure the SaltKey matches the one in GatewayServer. [Error Code: {ErrorCode}]\nDetails:{Request}", (int)LoginResponseCodeEnum.Emergency, request);
return new AUserLoginResponse { ReturnValue = LoginResponseCodeEnum.Emergency };
}

return Login(request.UserId, request.HashedUserPassword, request.ChannelId.ToString());
return Login(request.UserId, request.HashedUserPassword, request.ChannelId.ToString(), request.ServiceCompany, request.UserIp);
}

public AUserLoginResponse Login(string userId, string userPw, string channel)
{
var loginResponse = _joymaxPortalContext.AUserLoginResponses.FromSqlInterpolated(
$@"
DECLARE @return_value int
, @UserID varchar(30)
, @UserPwd char(32)
, @ServiceCode smallint
, @UserIP binary(4)
, @Channel char(1)
, @JID int
, @CurrentDate datetime
, @ARCode smallint
, @EmailAddr varchar(128)
, @EmailCertificationStatus char(1)
, @EmailUniqueStatus char(1)
, @NickName varchar(30)
, @VipLevel int
, @VipExpireTime datetime
, @VipUserType int;
public AUserLoginResponse Login(string userId, string userPw, string channel, int serviceCompany, string userIp)
{
var loginResponse = _joymaxPortalContext.AUserLoginResponses.FromSqlInterpolated(
$@"
DECLARE @return_value int
, @UserID varchar(30)
, @UserPwd char(32)
, @ServiceCode smallint
, @UserIP binary(4)
, @Channel char(1)
, @JID int
, @CurrentDate datetime
, @ARCode smallint
, @EmailAddr varchar(128)
, @EmailCertificationStatus char(1)
, @EmailUniqueStatus char(1)
, @NickName varchar(30)
, @VipLevel int
, @VipExpireTime datetime
, @VipUserType int;
EXEC @return_value = [dbo].[A_UserLogin] @UserID = {userId},
@UserPwd = {userPw},
@ServiceCode = {serviceCompany},
@UserIP = {IP2Bin(userIp)},
@Channel = {channel},
@JID = @JID OUTPUT,
@CurrentDate = @CurrentDate OUTPUT,
@ARCode = @ARCode OUTPUT,
@EmailAddr = @EmailAddr OUTPUT,
@EmailCertificationStatus = @EmailCertificationStatus OUTPUT,
@EmailUniqueStatus = @EmailUniqueStatus OUTPUT,
@NickName = @NickName OUTPUT,
@VipLevel = @VipLevel OUTPUT,
@VipExpireTime = @VipExpireTime OUTPUT,
@VipUserType = @VipUserType OUTPUT;
EXEC @return_value = [dbo].[A_UserLogin] @UserID = {userId},
@UserPwd = {userPw},
@ServiceCode = 1,
@UserIP = 0,
@Channel = {channel},
@JID = @JID OUTPUT,
@CurrentDate = @CurrentDate OUTPUT,
@ARCode = @ARCode OUTPUT,
@EmailAddr = @EmailAddr OUTPUT,
@EmailCertificationStatus = @EmailCertificationStatus OUTPUT,
@EmailUniqueStatus = @EmailUniqueStatus OUTPUT,
@NickName = @NickName OUTPUT,
@VipLevel = @VipLevel OUTPUT,
@VipExpireTime = @VipExpireTime OUTPUT,
@VipUserType = @VipUserType OUTPUT;
SELECT 'ReturnValue' = @return_value,
@JID as N'JID',
@CurrentDate as N'CurrentDate',
@ARCode as N'ARCode',
@EmailAddr as N'EmailAddr',
@EmailCertificationStatus as N'EmailCertificationStatus',
@EmailUniqueStatus as N'EmailUniqueStatus',
@NickName as N'NickName',
@VipLevel as N'VipLevel',
@VipExpireTime as N'VipExpireTime',
@VipUserType as N'VipUserType';");
return loginResponse.AsEnumerable().FirstOrDefault() ?? new AUserLoginResponse()
{ ReturnValue = LoginResponseCodeEnum.NotFoundUid };
}

SELECT 'ReturnValue' = @return_value,
@JID as N'JID',
@CurrentDate as N'CurrentDate',
@ARCode as N'ARCode',
@EmailAddr as N'EmailAddr',
@EmailCertificationStatus as N'EmailCertificationStatus',
@EmailUniqueStatus as N'EmailUniqueStatus',
@NickName as N'NickName',
@VipLevel as N'VipLevel',
@VipExpireTime as N'VipExpireTime',
@VipUserType as N'VipUserType';");

return loginResponse.AsEnumerable().FirstOrDefault() ?? new AUserLoginResponse()
{ ReturnValue = LoginResponseCodeEnum.NotFoundUid };
}
private static byte[] IP2Bin(string userIp)
{
var ipbytes = IPAddress.Parse(userIp).GetAddressBytes();
if (BitConverter.IsLittleEndian) Array.Reverse(ipbytes);
return ipbytes;
}
}
7 changes: 5 additions & 2 deletions appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"File": {
"Path": "BillingLog.txt",
"Append": true,
"MinLevel": "Trace",
"FileSizeLimitBytes": 10240,
"MinLevel": "Trace",
"FileSizeLimitBytes": 10240,
"MaxRollingFiles": 5
}
},
Expand Down Expand Up @@ -42,6 +42,9 @@
"Password": "FOLLOW https://code-maze.com/aspnetcore-send-email/",
"SkipTokenValidation": false
},
"ServiceCompany": 11,
"RequestTimeoutSeconds": 60,
"PortalCGIAgentHeader": "Portal_CGI_Agent",
"SaltKey": "eset5ag.nsy-g6ky5.mp",
"AllowedHosts": "*"
}

0 comments on commit 8b42820

Please sign in to comment.