master
Harald Wolff 2019-05-10 13:27:06 +02:00
parent dd1cbcfb86
commit 5355940395
11 changed files with 312 additions and 19 deletions

View File

@ -20,6 +20,7 @@ using ln.http;
using ln.http.resources;
using skyspot.http;
using skyspot.session;
using skyspot.hotspot;
namespace skyspot
{
@ -29,16 +30,18 @@ namespace skyspot
{
HTTPServer httpServer = new HTTPServer();
httpServer.AddEndpoint(new IPEndPoint(IPAddress.Any, 80));
httpServer.Start();
HotspotManager hotspotManager = new HotspotManager();
ResourceApplication app = new SkySpotApplication();
httpServer.DefaultApplication = app;
//DHCP httpDHCP = new DHCP(null,dhcpServer);
//(app.RootResource as DirectoryResource).InjectResource(httpDHCP);
SessionManager sessionManager = new SessionManager();
httpServer.Start();
}
}

11
doc/radius.txt 100644
View File

@ -0,0 +1,11 @@

Radius Secret Lookup:
---------------------
1. SecretStore individual secret
2. HotSpot Default Secret
3. SecretStore default secret

View File

@ -0,0 +1,12 @@
using System;
namespace skyspot.hotspot
{
public class ClientProfile
{
public String Name { get; set; }
public ClientProfile()
{
}
}
}

View File

@ -16,6 +16,7 @@ using System.Collections.Generic;
using System.IO;
using skyspot.radius;
using System.Linq;
using skyspot.session;
namespace skyspot.hotspot
{
public class HotspotManager
@ -28,7 +29,12 @@ namespace skyspot.hotspot
public ODBCollection<HotspotNetwork> hotspotNetworks { get; private set; }
public ODBCollection<RadiusSecretsStore> radiusSecretsCollection;
Dictionary<HotspotNetwork, HotspotRuntime> instances = new Dictionary<HotspotNetwork, HotspotRuntime>();
MappingBTree<HotspotNetwork, HotspotNetworkRuntime> hotspotRuntimes = new MappingBTree<HotspotNetwork, HotspotNetworkRuntime>((hr) => hr.HotspotNetwork);
public SessionManager SessionManager { get; private set; }
public HotspotManager()
{
@ -39,17 +45,49 @@ namespace skyspot.hotspot
SecretsStore = radiusSecretsCollection.FirstOrDefault();
if (SecretsStore == null)
SecretsStore = new RadiusSecretsStore();
SessionManager = new SessionManager(this);
}
public void SaveSecretsStore() => radiusSecretsCollection.Upsert(SecretsStore);
class HotspotRuntime
public void AddHotspotNetwork(HotspotNetwork hotspotNetwork)
{
public BTree<MAC, HotspotSession> currentSessions { get; } = new BTree<MAC, HotspotSession>();
if (!hotspotRuntimes.ContainsKey(hotspotNetwork))
hotspotRuntimes.Add(new HotspotNetworkRuntime(hotspotNetwork));
}
public void RemoveHotspotNetwork(HotspotNetwork hotspotNetwork)
{
if (hotspotRuntimes.ContainsKey(hotspotNetwork))
{
hotspotRuntimes.RemoveKey(hotspotNetwork);
}
}
public HotspotNetworkRuntime GetHotspotNetworkRuntime(HotspotNetwork hotspotNetwork)
{
return hotspotRuntimes[hotspotNetwork];
}
public HotspotNetworkRuntime GetHotspotNetworkRuntime(string networkName)
{
foreach (HotspotNetworkRuntime hotspotNetworkRuntime in hotspotRuntimes)
{
if (hotspotNetworkRuntime.HotspotNetwork.Name.Equals(networkName))
return hotspotNetworkRuntime;
}
throw new KeyNotFoundException();
}
public HotspotNetwork GetHotspotNetwork(String name)
{
foreach (HotspotNetworkRuntime hotspotNetworkRuntime in hotspotRuntimes)
{
if (hotspotNetworkRuntime.HotspotNetwork.Name.Equals(name))
return hotspotNetworkRuntime.HotspotNetwork;
}
throw new KeyNotFoundException();
}
}
}

View File

@ -10,9 +10,10 @@
using System;
using ln.types.odb.attributes;
using ln.types.net;
using System.Text;
namespace skyspot.hotspot
{
public class HotspotNetwork
public class HotspotNetwork : IComparable
{
[DocumentID]
public readonly Guid ID = Guid.NewGuid();
@ -23,10 +24,31 @@ namespace skyspot.hotspot
public string SID { get; set; }
public Network4 ClientsNetwork { get; set; }
public IPv4 Gateway { get; set; }
public byte[] RadiusSecret { get; set; }
public string RadiusTextSecret
{
get => Encoding.UTF8.GetString(RadiusSecret);
set => RadiusSecret = Encoding.UTF8.GetBytes(value);
}
public TimeSpan ClientDefaultSessionTime { get; set; }
public ClientProfile DefaultClientProfile { get; set; }
public HotspotNetwork()
{
}
public int CompareTo(object obj)
{
if (obj is HotspotNetwork)
{
HotspotNetwork you = obj as HotspotNetwork;
return string.Compare(Name, you.Name, StringComparison.Ordinal);
}
return -1;
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using ln.types.btree;
using ln.types.net;
using skyspot.session;
using skyspot.ip;
namespace skyspot.hotspot
{
public class HotspotNetworkRuntime
{
public HotspotNetwork HotspotNetwork { get; private set; }
MappingBTree<MAC, ClientSession> currentSessions = new MappingBTree<MAC, ClientSession>((ClientSession clientSession)=>clientSession.ClientMAC);
IPPool<ClientSession> pool = new IPPool<ClientSession>();
private HotspotNetworkRuntime()
{
}
public HotspotNetworkRuntime(HotspotNetwork hotspotNetwork)
{
HotspotNetwork = hotspotNetwork;
}
public ClientSession GetSession(MAC clientMac)
{
if (!currentSessions.ContainsKey(clientMac))
{
ClientSession newSession = new ClientSession(HotspotNetwork, clientMac);
FixupSession(newSession);
currentSessions.Add(newSession);
return newSession;
}
else
{
ClientSession clientSession = currentSessions[clientMac];
FixupSession(clientSession);
return clientSession; ;
}
}
public void RemoveSession(MAC clientMac)
{
currentSessions.RemoveKey(clientMac);
}
private void FixupSession(ClientSession clientSession)
{
if (clientSession.ClientIP == null)
{
// Todo: Implement IP allocation from pool
}
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace skyspot.hotspot
{
public class HotspotUser
{
public HotspotUser()
{
}
}
}

76
ip/IPPool.cs 100644
View File

@ -0,0 +1,76 @@
using System;
using ln.types.btree;
using ln.types.net;
namespace skyspot.ip
{
public class IPPool<T> where T : IComparable
{
public IPv4 FirstIP { get; set; }
public IPv4 LastIP { get; set; }
public IPv4 NextIP { get; set;}
BTree<IPv4, T> forward = new BTree<IPv4, T>();
BTree<T, IPv4> reverse = new BTree<T, IPv4>();
public IPPool()
{
}
public T FindForward(IPv4 ip)
{
lock (this)
{
return forward[ip];
}
}
public IPv4 FindReverse(T lookup)
{
lock (this)
{
return reverse[lookup];
}
}
public void Assign(IPv4 ip, T assigned)
{
lock (this)
{
if (forward.ContainsKey(ip) || reverse.ContainsKey(assigned))
throw new ArgumentException("<ip> or <assigend> already in pool");
forward.Add(ip, assigned);
reverse.Add(assigned, ip);
}
}
public void Remove(IPv4 ip)
{
lock (this)
{
if (forward.ContainsKey(ip))
{
reverse.Remove(forward[ip]);
forward.Remove(ip);
}
}
}
public void RemoveAssigned(T assigned)
{
lock (this)
{
if (reverse.ContainsKey(assigned))
{
forward.Remove(reverse[assigned]);
reverse.Remove(assigned);
}
}
}
public IPv4 Allocate(T assigned)
{
if (reverse.ContainsKey(assigned))
return reverse[assigned];
}
}
}

View File

@ -0,0 +1,46 @@
using System;
using skyspot.hotspot;
using ln.types.net;
using ln.types.odb.attributes;
namespace skyspot.session
{
public class ClientSession : IComparable
{
[DocumentID]
Guid id = Guid.NewGuid();
public DateTimeOffset Created { get; }
public DateTimeOffset ValidThrough { get; set; }
public HotspotNetwork HotspotNetwork { get; }
public MAC ClientMAC { get; }
public IPv4 ClientIP { get; set; }
public HotspotUser HotspotUser { get; set; }
public ClientProfile CurrentProfile { get; set; }
private ClientSession()
{
Created = DateTimeOffset.Now;
ValidThrough = Created + TimeSpan.FromMinutes(3);
}
public ClientSession(HotspotNetwork hotspotNetwork,MAC clientMac)
:this()
{
HotspotNetwork = hotspotNetwork;
ClientMAC = clientMac;
}
public int CompareTo(object obj)
{
if (obj is ClientSession)
{
ClientSession you = obj as ClientSession;
return ClientMAC.CompareTo(you.ClientMAC);
}
return -1;
}
}
}

View File

@ -17,17 +17,22 @@ using ln.logging;
using ln.types.odb;
using ln.types.odb.mapped;
using skyspot.radius;
using System.Text;
using skyspot.hotspot;
namespace skyspot.session
{
public class SessionManager
{
public RadiusSecretsStore SecretsStore { get; private set; }
public HotspotManager HotspotManager { get; }
public RadiusSecretsStore SecretsStore => HotspotManager.SecretsStore;
RadiusServer accountingRadius;
RadiusServer locatorRadius;
public SessionManager()
public SessionManager(HotspotManager hotspotManager)
{
HotspotManager = hotspotManager;
InitializeRadius();
}
@ -48,6 +53,9 @@ namespace skyspot.session
accountingRadius.MessageReceived = AccountingMessageReceived;
}
/**
* Locator Service
*
@ -97,18 +105,23 @@ namespace skyspot.session
}
MAC clientMac = new MAC(userName.AsText);
String instanceName = calledStationID.AsText;
String networkName = calledStationID.AsText;
HotspotNetworkRuntime hotspotNetworkRuntime = HotspotManager.GetHotspotNetworkRuntime(networkName);
ClientSession clientSession = hotspotNetworkRuntime.GetSession(clientMac);
Logging.Log(LogLevel.INFO, "Accounting: Session start for client {0} on Network {1}",clientMac, instanceName);
if (clientSession.CurrentProfile == null)
clientSession.CurrentProfile = hotspotNetworkRuntime.HotspotNetwork.DefaultClientProfile;
RadiusMessage reply = new RadiusMessage(radiusMessage.EndPoint, RadiusCode.AccessAccept);
reply.Identifier = radiusMessage.Identifier;
Logging.Log(LogLevel.INFO, "Accounting: Session start for client {0} on Network {1}",clientMac, networkName);
RadiusMessage reply = radiusMessage.ConstructReply(RadiusCode.AccessAccept);
reply.AddAttribute(new RadiusAttribute.FramedIPAddress().SetIP(IPv4.Parse("10.123.0.4")));
if (clientSession.CurrentProfile != null)
reply.AddAttribute(new RadiusAttribute.FilterID().SetText(clientSession.CurrentProfile.Name));
reply.Authenticate(SecretsStore.LookupSecret(reply.EndPoint));
radiusServer.Send(reply);
}
}
}
}

View File

@ -49,6 +49,11 @@
<Compile Include="hotspot\HotspotManager.cs" />
<Compile Include="hotspot\locator\MACLocation.cs" />
<Compile Include="radius\RadiusSecretsStore.cs" />
<Compile Include="session\ClientSession.cs" />
<Compile Include="hotspot\HotspotUser.cs" />
<Compile Include="hotspot\ClientProfile.cs" />
<Compile Include="ip\IPPool.cs" />
<Compile Include="hotspot\HotspotNetworkRuntime.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.http\ln.http.csproj">
@ -89,6 +94,8 @@
<Folder Include="hotspot\" />
<Folder Include="hotspot\locator\" />
<Folder Include="radius\" />
<Folder Include="doc\" />
<Folder Include="ip\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@ -201,6 +208,7 @@
<None Include="www\js\sky.controls.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="doc\radius.txt" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>