Skip to content

Commit

Permalink
Fixes an issue where the config file was overwritten by the installer
Browse files Browse the repository at this point in the history
Adds trace message support
  • Loading branch information
ryannewington committed Nov 17, 2016
1 parent 9f6be86 commit 47cc7c7
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 79 deletions.
2 changes: 1 addition & 1 deletion src/Lithnet.Pan.RAProxy.Setup/Components.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

</Component>

<Component Id="cmpb69520521cbba41ac82adecb1ef714866" Guid="*" Win64="yes">
<Component Id="cmpb69520521cbba41ac82adecb1ef714866" Guid="*" NeverOverwrite="yes" Win64="yes">
<File Id="App.config" KeyPath="yes" Source="$(var.Lithnet.Pan.RAProxy.TargetDir)Lithnet.Pan.RAProxy.exe.config" />
</Component>

Expand Down
2 changes: 1 addition & 1 deletion src/Lithnet.Pan.RAProxy.Setup/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Platform="x64" />
<Media Id="1" Cabinet="Cab1.cab" EmbedCab="yes" />

<MajorUpgrade Schedule="afterInstallInitialize" AllowSameVersionUpgrades="yes"
<MajorUpgrade Schedule="afterInstallExecute" AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A later version of [ProductName] is already installed" />

<PropertyRef Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED"/>
Expand Down
4 changes: 2 additions & 2 deletions src/Lithnet.Pan.RAProxy/ConfigSections/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static void Failover()
Config.activeEndpointEnumerator.MoveNext();
}

EventLog.WriteEntry(Program.EventSourceName, $"Failed over to API endpoint {Config.ActiveEndPoint.ApiUri}\n", EventLogEntryType.Warning, Logging.EventIDApiEndpointFailover);
Logging.WriteEntry($"Failed over to API endpoint {Config.ActiveEndPoint.ApiUri}\n", EventLogEntryType.Warning, Logging.EventIDApiEndpointFailover);
}

public static bool DisableCertificateValidation => Config.section.PanApi.DisableCertificateValidation;
Expand All @@ -90,7 +90,7 @@ public static string GetSecretForIP(IPAddress address)
}
}

EventLog.WriteEntry(Program.EventSourceName, $"A RADIUS message was received from an unknown source {address} and was discarded", EventLogEntryType.Error, Logging.EventIDUnknownRadiusHost);
Logging.WriteEntry($"A RADIUS message was received from an unknown source {address} and was discarded", EventLogEntryType.Error, Logging.EventIDUnknownRadiusHost);

return null;
}
Expand Down
22 changes: 19 additions & 3 deletions src/Lithnet.Pan.RAProxy/Logging.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
namespace Lithnet.Pan.RAProxy
using System.Diagnostics;

namespace Lithnet.Pan.RAProxy
{
internal class Logging
{
// Warnings
public const int EventIDServerCertificateValidationDisabled = 2001;

// Api Errors
public const int EventIDApiException = 3001;
public const int EventIDUnknownApiException = 3002;
public const int EventIDUnknownApiResponse= 3003;
public const int EventIDUnknownApiResponse = 3003;
public const int EventIDMessageSendException = 3004;
public const int EventIDApiEndpointExceptionWillFailover = 3005;
public const int EventIDApiEndpointFailover = 3006;
Expand All @@ -25,6 +27,20 @@ internal class Logging
public const int EventIDAccountingRequestRecieved = 4001;
public const int EventIDUserIDUpdateComplete = 4002;

public static void WriteEntry(string message, EventLogEntryType type, int eventID)
{
Trace.WriteLine(message);
EventLog.WriteEntry(Program.EventSourceName, message, type, eventID);

}

public static void WriteDebugEntry(string message, EventLogEntryType type, int eventID)
{
Trace.WriteLine(message);
if (Config.DebuggingEnabled)
{
EventLog.WriteEntry(Program.EventSourceName, message, type, eventID);
}
}
}
}
10 changes: 5 additions & 5 deletions src/Lithnet.Pan.RAProxy/PanApi/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void Send()
}
catch (Exception ex)
{
EventLog.WriteEntry(Program.EventSourceName, $"The attempt to send the update failed\n{ex.Message}\n{ex.Source}\n", EventLogEntryType.Error, Logging.EventIDMessageSendException);
Logging.WriteEntry($"The attempt to send the update failed\n{ex.Message}\n{ex.Source}\n", EventLogEntryType.Error, Logging.EventIDMessageSendException);
throw;
}

Expand Down Expand Up @@ -60,19 +60,19 @@ public void Send()
}
}

EventLog.WriteEntry(Program.EventSourceName, $"The API called failed with status {status.InnerText}\n{response}", EventLogEntryType.Error, Logging.EventIDApiException);
Logging.WriteEntry($"The API called failed with status {status.InnerText}\n{response}", EventLogEntryType.Error, Logging.EventIDApiException);
throw new PanApiException($"The API called failed with status {status.InnerText}", response);

}
else
{
EventLog.WriteEntry(Program.EventSourceName, $"The API called failed with an unknown result\n{response}", EventLogEntryType.Error, Logging.EventIDUnknownApiException);
Logging.WriteEntry($"The API called failed with an unknown result\n{response}", EventLogEntryType.Error, Logging.EventIDUnknownApiException);
throw new PanApiException($"The API called failed with an unknown result", response);
}
}
catch
{
EventLog.WriteEntry(Program.EventSourceName, $"The API called failed with an unsupported response\n{response}", EventLogEntryType.Error, Logging.EventIDUnknownApiResponse);
Logging.WriteEntry($"The API called failed with an unsupported response\n{response}", EventLogEntryType.Error, Logging.EventIDUnknownApiResponse);
throw new PanApiException($"The API called failed with an unsupported response", response);
}
}
Expand Down Expand Up @@ -111,7 +111,7 @@ private string Submit()
throw;
}

EventLog.WriteEntry(Program.EventSourceName, $"The attempt to send the update to endpoint {ep.ApiUri} failed with a communciations error\n{ex.Message}\n{ex.Source}\nThe service will attempt to fail over to the next endpoint", EventLogEntryType.Warning, Logging.EventIDApiEndpointExceptionWillFailover);
Logging.WriteEntry($"The attempt to send the update to endpoint {ep.ApiUri} failed with a communciations error\n{ex.Message}\n{ex.Source}\nThe service will attempt to fail over to the next endpoint", EventLogEntryType.Warning, Logging.EventIDApiEndpointExceptionWillFailover);
Config.Failover();
return this.Submit();
}
Expand Down
26 changes: 9 additions & 17 deletions src/Lithnet.Pan.RAProxy/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,23 @@ public static void Main()
else
{
Start();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
Thread.Sleep(Timeout.Infinite);
}
}

internal static void Start()
{
Program.cancellationToken = new CancellationTokenSource();


if (!EventLog.SourceExists(Program.EventSourceName))
{
EventLog.CreateEventSource(new EventSourceCreationData(Program.EventSourceName, "Application"));
}

if (Config.DisableCertificateValidation)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => true;
EventLog.WriteEntry(Program.EventSourceName, "Server certificate validation has been disabled. The SSL certificate on the Palo Alto device will not be validated", EventLogEntryType.Warning, Logging.EventIDServerCertificateValidationDisabled);
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => true;
Logging.WriteEntry("Server certificate validation has been disabled. The SSL certificate on the Palo Alto device will not be validated", EventLogEntryType.Warning, Logging.EventIDServerCertificateValidationDisabled);
}

Program.StartQueue();
Expand Down Expand Up @@ -96,24 +95,17 @@ private static void StartQueue()
{
try
{

if (Config.DebuggingEnabled)
{
EventLog.WriteEntry(Program.EventSourceName, $"Incoming accounting request received\n{request}", EventLogEntryType.Information, Logging.EventIDAccountingRequestRecieved);
}
Logging.WriteDebugEntry($"Incoming accounting request received\n{request}", EventLogEntryType.Information, Logging.EventIDAccountingRequestRecieved);

Program.SendMessage(request);
}
catch (MissingValueException ex)
{
if (Config.DebuggingEnabled)
{
EventLog.WriteEntry(Program.EventSourceName, $"A radius accounting packet was discarded because it had incomplete information.\n{ex.Message}", EventLogEntryType.Warning, Logging.EventIDMessageSendFailure);
}
Logging.WriteDebugEntry($"A radius accounting packet was discarded because it had incomplete information.\n{ex.Message}", EventLogEntryType.Warning, Logging.EventIDMessageSendFailure);
}
catch (Exception ex)
{
EventLog.WriteEntry(Program.EventSourceName, $"An error occured while submitting the user-id update\n{ex.Message}\n{ex.StackTrace}", EventLogEntryType.Error, Logging.EventIDMessageSendFailure);
Logging.WriteEntry($"An error occured while submitting the user-id update\n{ex.Message}\n{ex.StackTrace}", EventLogEntryType.Error, Logging.EventIDMessageSendFailure);
}
}
}
Expand Down Expand Up @@ -184,16 +176,16 @@ private static void SendMessage(AccountingRequest request)
try
{
message.Send();
EventLog.WriteEntry(Program.EventSourceName, $"UserID API mapping succeeded\nUsername: {username.ValueAsString}\nIP address: {framedIP.ValueAsString}\nType: {type}", EventLogEntryType.Information, Logging.EventIDUserIDUpdateComplete);
Logging.WriteEntry($"UserID API mapping succeeded\nUsername: {username.ValueAsString}\nIP address: {framedIP.ValueAsString}\nType: {type}", EventLogEntryType.Information, Logging.EventIDUserIDUpdateComplete);

}
catch (PanApiException ex)
{
EventLog.WriteEntry(Program.EventSourceName, $"The UserID API called failed\nUsername: {username.ValueAsString}\nIP address: {framedIP.ValueAsString}\n{ex.Message}\n{ex.StackTrace}\n{ex.Detail}", EventLogEntryType.Error, Logging.EventIDMessageSendFailure);
Logging.WriteEntry($"The UserID API called failed\nUsername: {username.ValueAsString}\nIP address: {framedIP.ValueAsString}\n{ex.Message}\n{ex.StackTrace}\n{ex.Detail}", EventLogEntryType.Error, Logging.EventIDMessageSendFailure);
}
catch (Exception ex)
{
EventLog.WriteEntry(Program.EventSourceName, $"An error occured while submitting the user-id update\nUsername: {username.ValueAsString}\nIP address: {framedIP.ValueAsString}\n{ex.Message}\n{ex.StackTrace}", EventLogEntryType.Error, Logging.EventIDMessageSendFailure);
Logging.WriteEntry($"An error occured while submitting the user-id update\nUsername: {username.ValueAsString}\nIP address: {framedIP.ValueAsString}\n{ex.Message}\n{ex.StackTrace}", EventLogEntryType.Error, Logging.EventIDMessageSendFailure);
}
}
}
Expand Down
88 changes: 61 additions & 27 deletions src/Lithnet.Pan.RAProxy/RadiusAccounting/AccountingListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,44 +33,78 @@ public AccountingListener(int usePort = 1813)

public void Start(CancellationToken token)
{
Debug.WriteLine($"RADIUS accounting server listening on port {this.Port}.");
Task.Run(async () =>
Trace.WriteLine($"RADIUS accounting server listening on port {this.Port}.");
Task t = new Task((async () =>
{
using (UdpClient listener = new UdpClient(this.Port))
{
while (!token.IsCancellationRequested)
{
var receiveResult = await listener.ReceiveAsync();
Debug.WriteLine($"Received packet from {receiveResult.RemoteEndPoint.Address}:{receiveResult.RemoteEndPoint.Port}");

// If this is a valid sized RADIUS packet, try to parse, otherwise silently ignore
if (receiveResult.Buffer?.Length >= 20)
try
{
byte[] response = ParseRequestMessage(receiveResult.Buffer, receiveResult.RemoteEndPoint.Address);
var receiveResult = await listener.ReceiveAsync();
Trace.WriteLine($"Received packet from {receiveResult.RemoteEndPoint.Address}:{receiveResult.RemoteEndPoint.Port}");

if (response?.Length > 0)
// If this is a valid sized RADIUS packet, try to parse, otherwise silently ignore
if (receiveResult.Buffer?.Length >= 20)
{
listener.Send(response, response.Length, receiveResult.RemoteEndPoint);
Debug.WriteLine($"Sent accounting response to {receiveResult.RemoteEndPoint.Address}:{receiveResult.RemoteEndPoint.Port}");
byte[] response = ParseRequestMessage(receiveResult.Buffer, receiveResult.RemoteEndPoint.Address);

if (response?.Length > 0)
{
listener.Send(response, response.Length, receiveResult.RemoteEndPoint);
Trace.WriteLine($"Sent accounting response to {receiveResult.RemoteEndPoint.Address}:{receiveResult.RemoteEndPoint.Port}");
}
else
{
Trace.WriteLine($"Not sending an accounting response to {receiveResult.RemoteEndPoint.Address}:{receiveResult.RemoteEndPoint.Port}");
}
}
else
{
Debug.WriteLine($"Not sending an accounting response to {receiveResult.RemoteEndPoint.Address}:{receiveResult.RemoteEndPoint.Port}");
Trace.WriteLine("Invalid accounting request received");
}
}
else
catch (SocketException x)
{
Debug.WriteLine("Invalid accounting request received");
switch (x.SocketErrorCode)
{
case SocketError.Interrupted:
case SocketError.AccessDenied:
case SocketError.Fault:
case SocketError.NetworkDown:
case SocketError.NetworkUnreachable:
case SocketError.NetworkReset:
case SocketError.ConnectionAborted:
case SocketError.ConnectionReset:
case SocketError.TimedOut:
case SocketError.ConnectionRefused:
case SocketError.HostDown:
case SocketError.HostUnreachable:
case SocketError.Disconnecting:
case SocketError.HostNotFound:
case SocketError.TryAgain:
case SocketError.NoData:
case SocketError.OperationAborted:
Trace.WriteLine($"Socket error, resetting:{x.Message}");
Thread.Sleep(100);
break;

default:
Trace.WriteLine($"Socket error, re-throwing:{x.Message}");
throw;
}
}
}
}
}, token);
}), token);

t.Start();
}

public void Stop()
{
Debug.WriteLine($"RADIUS accounting server shutdown.");
Trace.WriteLine($"RADIUS accounting server shutdown.");
}

/// <summary>
Expand All @@ -84,22 +118,22 @@ public void Stop()
/// <returns>Acknowledgement response data, if successfully parsed</returns>
private static byte[] ParseRequestMessage(byte[] data, IPAddress sender)
{
byte requestType = data[0]; // Type code is first 8 bits, 4 = AccountingRequest, 5 = AccountingResponse
byte requestIdentifier = data[1]; // Identifier is next 8 bits, representing sequence of message
int requestLength = (data[2] << 8) | data[3]; // Length is next 16 bits, representing packet length
byte requestType = data[0]; // Type code is first 8 bits, 4 = AccountingRequest, 5 = AccountingResponse
byte requestIdentifier = data[1]; // Identifier is next 8 bits, representing sequence of message
int requestLength = (data[2] << 8) | data[3]; // Length is next 16 bits, representing packet length

// Determine if the packet contains Accounting-Request type code (4), otherwise do nothing
if (requestType != 4)
{
Debug.WriteLine(" - Ignored: Not AccountingRequest type.");
Trace.WriteLine(" - Ignored: Not AccountingRequest type.");
return null;
}
Debug.WriteLine($" - AccountingRequest #{requestIdentifier} with length {requestLength}.");
Trace.WriteLine($" - AccountingRequest #{requestIdentifier} with length {requestLength}.");

// Check the authenticator token matches the shared secret, otherwise do nothing
if (!AuthenticateRequest(data, sender))
{
Debug.WriteLine(" - Ignored: Invalid Authenticator Token.");
Trace.WriteLine(" - Ignored: Invalid Authenticator Token.");
return null;
}

Expand All @@ -110,9 +144,9 @@ private static byte[] ParseRequestMessage(byte[] data, IPAddress sender)
List<byte> responseAttributes = new List<byte>();
foreach (var item in attributes)
{
Debug.WriteLine($" | " + item.ToString());
Trace.WriteLine($" | " + item.ToString());

if (item.ResponseRequired())
if (item.IsRequiredInResponse())
responseAttributes.AddRange(item.GetResponse());
}

Expand All @@ -123,10 +157,10 @@ private static byte[] ParseRequestMessage(byte[] data, IPAddress sender)
byte[] responsePacket = new byte[responseAttributes.Count + 20];

// First populate any attributes into the response, since their length is known
responsePacket[0] = 5; // Type code is 5 for response
responsePacket[1] = requestIdentifier; // Identifier is the same as sent in request
responsePacket[0] = 5; // Type code is 5 for response
responsePacket[1] = requestIdentifier; // Identifier is the same as sent in request

short responseLength = (short)responsePacket.Length; // Length of response message is at minimum 20
short responseLength = (short)responsePacket.Length; // Length of response message is at minimum 20

responsePacket[3] = (byte)(responseLength & 0xff);
responsePacket[2] = (byte)((responseLength >> 8) & 0xff);
Expand Down
Loading

0 comments on commit 47cc7c7

Please sign in to comment.