/// <summary> /// Sends a packet /// </summary> /// <param name="responsePacket"></param> /// <param name="remoteEndpoint"></param> /// <param name="dictionary"></param> private void SendResponsePacket(IRadiusPacket responsePacket, IPEndPoint remoteEndpoint, IRadiusDictionary dictionary) { var responseBytes = responsePacket.GetBytes(dictionary); _server.Send(responseBytes, responseBytes.Length, remoteEndpoint); // todo thread safety... although this implementation will be implicitly thread safeish... _log.Info($"{responsePacket.Code} sent to {remoteEndpoint} Id={responsePacket.Identifier}"); }
/// <summary> /// Tries to get a packet from the stream. Returns true if successful /// Returns false if no packet could be parsed or stream is empty ie closing /// </summary> /// <param name="stream"></param> /// <param name="packet"></param> /// <returns></returns> public bool TryParsePacketFromStream(Stream stream, out IRadiusPacket packet, byte[] sharedSecret) { var packetHeaderBytes = new byte[4]; var i = stream.Read(packetHeaderBytes, 0, 4); if (i != 0) { try { var packetLength = BitConverter.ToUInt16(packetHeaderBytes.Reverse().ToArray(), 0); var packetContentBytes = new byte[packetLength - 4]; stream.Read(packetContentBytes, 0, packetContentBytes.Length); // todo stream.read should use loop in case everything is not available immediately packet = Parse(packetHeaderBytes.Concat(packetContentBytes).ToArray(), sharedSecret); return(true); } catch (Exception ex) { _logger.LogWarning(ex, "Unable to parse packet from stream"); } } packet = null; return(false); }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { if (packet.Code == PacketCode.AccessRequest) { if (packet.GetAttribute <String>("User-Password") == "arctangent") { var responsepacket = packet.CreateResponsePacket(PacketCode.AccessAccept); responsepacket.AddAttribute("Service-Type", 1); responsepacket.AddAttribute("Login-Service", 0); responsepacket.AddAttribute("Login-IP-Host", IPAddress.Parse("192.168.1.3")); return(responsepacket); } } var sb = new StringBuilder(); sb.AppendLine($"Packet dump for {packet.Identifier}:"); foreach (var attribute in packet.Attributes) { attribute.Value.ForEach(o => sb.AppendLine($"{attribute.Key} : {o} [{o.GetType()}]")); } Console.WriteLine(sb.ToString()); //Console.WriteLine(packet.GetAttribute<String>("3GPP-GGSN-MCC-MNC")); throw new InvalidOperationException("Couldnt handle request?!"); }
private IRadiusPacket Stop(IRadiusPacket packet) { var user = UsernameDomain.Parse(packet.GetAttribute <String>("User-Name")); var msisdn = packet.GetAttribute <String>("Calling-Station-Id"); var acctSessionId = packet.GetAttribute <String>("Acct-Session-Id"); var acctStatusType = "Stop"; // duuh var acctInputOctets = packet.GetAttribute <UInt32>("Acct-Input-Octets"); var acctOutputOctets = packet.GetAttribute <UInt32>("Acct-Output-Octets"); var acctSessionTime = packet.GetAttribute <UInt32>("Acct-Session-Time"); var acctTerminateCause = packet.GetAttribute <UInt32>("Acct-Terminate-Cause"); // oh crap, guess i need values as well... var acctInputGigawords = packet.GetAttribute <UInt32?>("Acct-Input-Gigawords"); var acctOutputGigawords = packet.GetAttribute <UInt32?>("Acct-Output-Gigawords"); _log.Debug($"Handling stop packet for {msisdn} with AcctSessionId {acctSessionId}"); try { using (var db = _contextFactory.GetContext()) { db.AccountingStop(user.Username, user.Domain, msisdn, acctStatusType, acctSessionId, acctInputOctets, acctOutputOctets, (int)acctSessionTime, acctTerminateCause.ToString(), acctInputGigawords, acctOutputGigawords); } } catch (EntityCommandExecutionException ex) { if (ex.InnerException?.Message.Contains("duplicate") ?? false) { _log.Warn($"Duplicate stop packet for AcctSessionId {acctSessionId}"); } else { throw; } } return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); }
/// <summary> /// Sends a packet /// </summary> private void Send(IRadiusPacket responsePacket, IPEndPoint remoteEndpoint) { var responseBytes = _radiusPacketParser.GetBytes(responsePacket); _server.Send(responseBytes, responseBytes.Length, remoteEndpoint); _logger.Debug($"{responsePacket.Code} sent to {remoteEndpoint} Id={responsePacket.Identifier}"); }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { var config = ConfigurationManager.AppSettings; var domain = config.Get("Domain"); var groupName = config.Get("AdGroupName"); _log.Info($"Recived request with packet code {packet.Code}"); if (packet.Code == PacketCode.AccessRequest) { var userName = packet.GetAttribute <String>("User-Name"); var userPassword = packet.GetAttribute <String>("User-Password"); var userLogin = ValidateCredentials(domain, userName, userPassword, userName, userName); var userInGroup = IsUserInAdGroup(domain, userName, groupName, userName, userPassword); _log.Info($"User Login result ={userLogin} UserInGroup result = {userInGroup} for user {userName}"); if (userInGroup && userLogin) { var response = packet.CreateResponsePacket(PacketCode.AccessAccept); response.AddAttribute("Acct-Interim-Interval", 60); return(response); } return(packet.CreateResponsePacket(PacketCode.AccessReject)); } _log.Info($"Cant handle request code {packet.Code}"); throw new InvalidOperationException($"Can't handle other requests besides AccessRequests with code {PacketCode.AccessRequest}"); }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { if (packet.Code == PacketCode.AccountingRequest) { switch (packet.GetAttribute <AcctStatusType>("Acct-Status-Type")) { case AcctStatusType.Start: case AcctStatusType.Stop: case AcctStatusType.InterimUpdate: return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); default: break; } } else if (packet.Code == PacketCode.AccessRequest) { if (packet.GetAttribute <string>("User-Name") == UserName && packet.GetAttribute <string>("User-Password") == UserPassword) { var response = packet.CreateResponsePacket(PacketCode.AccessAccept); response.AddAttribute("Acct-Interim-Interval", 60); return(response); } return(packet.CreateResponsePacket(PacketCode.AccessReject)); } throw new InvalidOperationException("Couldnt handle request?!"); }
private IRadiusPacket Interim(IRadiusPacket packet) { var user = UsernameDomain.Parse(packet.GetAttribute <String>("User-Name")); var msisdn = packet.GetAttribute <String>("Calling-Station-Id"); var acctSessionId = packet.GetAttribute <String>("Acct-Session-Id"); var acctStatusType = "Alive"; // duuh var acctInputOctets = packet.GetAttribute <UInt32>("Acct-Input-Octets"); var acctOutputOctets = packet.GetAttribute <UInt32>("Acct-Output-Octets"); var acctSessionTime = packet.GetAttribute <UInt32>("Acct-Session-Time"); var acctInputGigawords = packet.GetAttribute <UInt32?>("Acct-Input-Gigawords"); var acctOutputGigawords = packet.GetAttribute <UInt32?>("Acct-Output-Gigawords"); var nasIpAddress = packet.GetAttribute <IPAddress>("NAS-IP-Address"); var mccmnc = Utils.GetMccMncFrom3GPPLocationInfo(packet.GetAttribute <Byte[]>("3GPP-User-Location-Info")).mccmnc; _log.Debug($"Handling interim packet for {msisdn} on {mccmnc} with AcctSessionId {acctSessionId}"); using (var db = _contextFactory.GetContext()) { db.AccountingInterim(user.Username, user.Domain, msisdn, acctStatusType, acctSessionId, acctInputOctets, acctOutputOctets, (int)acctSessionTime, acctInputGigawords, acctOutputGigawords); } Task.Factory.StartNew(() => { if (CheckDisconnect(acctSessionId)) { _disconnector.DisconnectUserByMsisdn(msisdn); } }, TaskCreationOptions.LongRunning); return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); }
private IRadiusPacket Start(IRadiusPacket packet) { var user = UsernameDomain.Parse(packet.GetAttribute <String>("User-Name")); var msisdn = packet.GetAttribute <String>("Calling-Station-Id"); var acctSessionId = packet.GetAttribute <String>("Acct-Session-Id"); var acctStatusType = "Start"; // duuh var locationInfo = Utils.GetMccMncFrom3GPPLocationInfo(packet.GetAttribute <Byte[]>("3GPP-User-Location-Info")); _log.Debug($"Handling start packet for {msisdn} with AcctSessionId {acctSessionId}"); try { using (var db = _contextFactory.GetContext()) { db.AccountingStart(user.Username, user.Domain, msisdn, acctStatusType, acctSessionId, locationInfo.mccmnc); } Task.Factory.StartNew(() => _welcomeSender.CheckWelcomeSms(msisdn), TaskCreationOptions.LongRunning); } catch (EntityCommandExecutionException ex) { if (ex.InnerException?.Message.Contains("duplicate") ?? false) { _log.Warn($"Duplicate start packet for AcctSessionId {acctSessionId}"); } else { throw; } } return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); }
/// <summary> /// Sends a packet /// </summary> private void Send(IRadiusPacket responsePacket, string user, IPEndPoint remoteEndpoint, IPEndPoint proxyEndpoint, bool debugLog) { var responseBytes = _radiusPacketParser.GetBytes(responsePacket); _server.Send(responseBytes, responseBytes.Length, proxyEndpoint ?? remoteEndpoint); if (proxyEndpoint != null) { if (debugLog) { _logger.Debug("{code:l} sent to {host:l}:{port} via {proxyhost:l}:{proxyport} id={id}", responsePacket.Code.ToString(), remoteEndpoint.Address, remoteEndpoint.Port, proxyEndpoint.Address, proxyEndpoint.Port, responsePacket.Identifier); } else { _logger.Information("{code:l} sent to {host:l}:{port} via {proxyhost:l}:{proxyport} id={id} user='******'", responsePacket.Code.ToString(), remoteEndpoint.Address, remoteEndpoint.Port, proxyEndpoint.Address, proxyEndpoint.Port, responsePacket.Identifier, user); } } else { if (debugLog) { _logger.Debug("{code:l} sent to {host:l}:{port} id={id}", responsePacket.Code.ToString(), remoteEndpoint.Address, remoteEndpoint.Port, responsePacket.Identifier); } else { _logger.Information("{code:l} sent to {host:l}:{port} id={id} user='******'", responsePacket.Code.ToString(), remoteEndpoint.Address, remoteEndpoint.Port, responsePacket.Identifier, user); } } }
/// <summary> /// Tries to get a packet from the stream. Returns true if successful /// Returns false if no packet could be parsed or stream is empty ie closing /// </summary> /// <param name="stream"></param> /// <param name="packet"></param> /// <param name="dictionary"></param> /// <returns></returns> public static Boolean TryParsePacketFromStream(Stream stream, out IRadiusPacket packet, RadiusDictionary dictionary, Byte[] sharedSecret) { var packetHeaderBytes = new Byte[4]; var i = stream.Read(packetHeaderBytes, 0, 4); if (i != 0) { try { var packetLength = BitConverter.ToUInt16(packetHeaderBytes.Reverse().ToArray(), 0); var packetContentBytes = new Byte[packetLength - 4]; stream.Read(packetContentBytes, 0, packetContentBytes.Length); packet = Parse(packetHeaderBytes.Concat(packetContentBytes).ToArray(), dictionary, sharedSecret); return(true); } catch (Exception ex) { _log.Warn("Unable to parse packet from stream", ex); } } packet = null; return(false); }
/// <summary> /// Sends a packet /// </summary> /// <param name="responsePacket"></param> /// <param name="remoteEndpoint"></param> void SendResponsePacket(IRadiusPacket responsePacket, IPEndPoint remoteEndpoint) { var responseBytes = RadiusPacketParser.GetBytes(responsePacket); Server.Send(responseBytes, responseBytes.Length, remoteEndpoint); //TODO log output here //$"{responsePacket.Code} sent to {remoteEndpoint} Id={responsePacket.Identifier}" }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { // Simulate lag //Thread.Sleep(new Random().Next(100, 3000)); if (packet.Authenticator != null) { Console.WriteLine($"Authenticator {packet.Authenticator.ToHexString()}"); } if (packet.SharedSecret != null) { Console.WriteLine($"SharedSecret {packet.SharedSecret.ToHexString()}"); } foreach (var att in packet.Attributes) { Console.WriteLine($"ATT : {att.Key} - {att.Value}"); } var userName = packet.GetAttribute <String>("User-Name"); var password = packet.GetAttribute <String>("User-Password"); var chap_password = packet.GetAttribute <byte[]>("CHAP-Password"); Console.WriteLine($"userName {userName} password : {password} chap-password : {chap_password?.ToHexString()}"); if (packet.Code == PacketCode.AccountingRequest) { var acctStatusType = packet.GetAttribute <AcctStatusType>("Acct-Status-Type"); if (acctStatusType == AcctStatusType.Start) { return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); } if (acctStatusType == AcctStatusType.Stop) { return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); } if (acctStatusType == AcctStatusType.InterimUpdate) { return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); } } else if (packet.Code == PacketCode.AccessRequest) { if (packet.GetAttribute <String>("User-Name") == "*****@*****.**" && packet.GetAttribute <String>("User-Password") == "1234") { var response = packet.CreateResponsePacket(PacketCode.AccessAccept); response.AddAttribute("Acct-Interim-Interval", 60); return(response); } return(packet.CreateResponsePacket(PacketCode.AccessReject)); } throw new InvalidOperationException("Couldnt handle request?!"); }
private IRadiusPacket Authenticate(IRadiusPacket packet) { var msisdn = packet.GetAttribute <String>("Calling-Station-Id"); if (!packet.Attributes.ContainsKey("3GPP-User-Location-Info")) { _log.Warn("Missing 3GPP-User-Location-Info in packet, ignoring"); return(null); } var locationInfo = Utils.GetMccMncFrom3GPPLocationInfo(packet.GetAttribute <Byte[]>("3GPP-User-Location-Info")); _log.Debug($"Handling authentication packet for {msisdn} on network {locationInfo.locationType}:{locationInfo.mccmnc}"); using (var db = _contextFactory.GetContext()) { if (locationInfo.mccmnc == "99999") { _log.Warn($"No location info for msisdn {msisdn} check m2m portal 3GPP-SGSN-Address: {packet.GetAttribute<IPAddress>("3GPP-SGSN-Address")}"); return(packet.CreateResponsePacket(PacketCode.AccessReject)); } var result = db.Authenticate1(msisdn, "flexinets", msisdn, locationInfo.mccmnc).ToList(); if (result.Count > 0 && result.First() == null) { var response = packet.CreateResponsePacket(PacketCode.AccessAccept); response.AddAttribute("Acct-Interim-Interval", 60); return(response); } else { try { var mccmnc = Convert.ToInt32(locationInfo.mccmnc); var network = db.Networks.SingleOrDefault(o => o.mccmnc == mccmnc); var simcard = db.SimCards.SingleOrDefault(o => o.Msisdn == msisdn); var sb = new StringBuilder(); sb.AppendLine($"Authentication failed for {msisdn} on network {mccmnc} ({network?.providername}, {network?.countryname})"); if (simcard.user_id == null) { sb.AppendLine("Sim card not mapped to a user"); } else { sb.AppendLine($"User: {simcard.UserSetting.user.username}@{simcard.UserSetting.user.realm}, group: {simcard.UserSetting.user.directory.name}"); } _log.Warn(sb.ToString().Trim()); // todo needs throttling to reduce unwanted spam } catch (Exception ex) { _log.Error("huh?", ex); } return(packet.CreateResponsePacket(PacketCode.AccessReject)); } } }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { if (packet.Code == PacketCode.AccountingRequest) { return(HandleAccountingPacket(packet)); } else if (packet.Code == PacketCode.AccessRequest) { return(HandleAuthenticationPacket(packet)); } return(null); }
/// <summary> /// Authenticate user through proxy or locally /// </summary> /// <param name="packet"></param> /// <returns></returns> private IRadiusPacket AuthenticateUser(IRadiusPacket packet) { var usernamedomain = packet.GetAttribute <String>("User-Name").ToLowerInvariant(); var packetPassword = packet.GetAttribute <String>("User-Password"); var proxyresponse = _authProxy.ProxyAuthentication(usernamedomain, packetPassword); if (proxyresponse.HasValue) { _log.Info($"Got response from proxy for username {usernamedomain}"); return(packet.CreateResponsePacket(proxyresponse.Value)); } else { using (var db = _contextFactory.GetContext()) { var username = UsernameDomain.Parse(usernamedomain); var userid = _userAuthProvider.AuthenticateAsync(username.Username, username.Domain, packetPassword).Result; if (userid.HasValue) { return(packet.CreateResponsePacket(PacketCode.AccessAccept)); } else { var user = db.users.SingleOrDefault(o => o.username == username.Username && o.realm == username.Domain); if (user == null) { _log.Warn($"Username {usernamedomain} not found"); } else if (user.status != 1) { _log.Warn($"Username {usernamedomain} is not active, email: {user.email}"); } else { _log.Warn($"Bad password for user {usernamedomain}, password is {packetPassword.Length} characters, email: {user.email}"); } var location = packet.GetAttribute <String>("Ipass-Location-Description"); if (!String.IsNullOrEmpty(location)) { _log.Warn($"iPass location description: {location}"); } return(packet.CreateResponsePacket(PacketCode.AccessReject)); } } } }
/// <summary> /// Check is packet was retransmissed (duplicated) /// </summary> public bool IsRetransmission(IRadiusPacket requestPacket, IPEndPoint remoteEndpoint) { //unique key is combination of packet code, identifier, client endpoint, user name and request authenticator var uniqueKey = requestPacket.CreateUniqueKey(remoteEndpoint); if (_cache.TryGetValue(uniqueKey, out _)) { return(true); } _cache.Set(uniqueKey, "1", DateTimeOffset.UtcNow.AddMinutes(1)); return(false); }
/// <summary> /// Dump the packet attributes to the log /// </summary> /// <param name="packet"></param> private static void DumpPacket(IRadiusPacket packet) { var sb = new StringBuilder(); sb.AppendLine($"Packet dump for {packet.Identifier}:"); foreach (var attribute in packet.Attributes) { if (attribute.Key == "User-Password") { sb.AppendLine($"{attribute.Key} length : {attribute.Value.First().ToString().Length}"); } else { attribute.Value.ForEach(o => sb.AppendLine($"{attribute.Key} : {o} [{o.GetType()}]")); } } _log.Debug(sb.ToString()); }
/// <summary> /// Send a packet with specified timeout /// </summary> /// <param name="packet"></param> /// <param name="remoteEndpoint"></param> /// <param name="timeout"></param> /// <returns></returns> public async Task <IRadiusPacket> SendPacketAsync(IRadiusPacket packet, IPEndPoint remoteEndpoint, TimeSpan timeout) { await _client.ConnectAsync(remoteEndpoint.Address, remoteEndpoint.Port); var sslStream = new SslStream(_client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate)); await sslStream.AuthenticateAsClientAsync("radsecserver", _certs, SslProtocols.Tls12, true); var packetBytes = packet.GetBytes(_dictionary); await sslStream.WriteAsync(packetBytes, 0, packetBytes.Length); if (RadiusPacket.TryParsePacketFromStream(sslStream, out var responsePacket, _dictionary, packet.SharedSecret)) { _client.Close(); return(responsePacket); } _client.Close(); return(null); }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { if (packet.Code == PacketCode.AccessRequest) { return(Authenticate(packet)); } else if (packet.Code == PacketCode.AccountingRequest && packet.GetAttribute <AcctStatusType>("Acct-Status-Type") == AcctStatusType.Start) { return(Start(packet)); } else if (packet.Code == PacketCode.AccountingRequest && packet.GetAttribute <AcctStatusType>("Acct-Status-Type") == AcctStatusType.Stop) { return(Stop(packet)); } else if (packet.Code == PacketCode.AccountingRequest && packet.GetAttribute <AcctStatusType>("Acct-Status-Type") == AcctStatusType.InterimUpdate) { return(Interim(packet)); } throw new InvalidOperationException($"Nothing configured for {packet.Code}"); }
/// <summary> /// Authentication /// </summary> /// <param name="packet"></param> /// <returns></returns> private IRadiusPacket HandleAuthenticationPacket(IRadiusPacket packet) { _log.Info($"Handling {packet.Code} packet for {packet.GetAttribute<String>("User-Name")}"); var usernamedomain = packet.GetAttribute <String>("User-Name").ToLowerInvariant(); var response = AuthenticateUser(packet); if (response.Code == PacketCode.AccessReject) { _failures.Add(usernamedomain); } else if (response.Code == PacketCode.AccessAccept) { if (_failures.Contains(usernamedomain)) { _log.Warn($"Username {usernamedomain} authenticated after failures"); _failures.Remove(usernamedomain); } } return(response); }
public IRadiusPacket HandlePacket(IRadiusPacket packet) { // Simulate lag //Thread.Sleep(new Random().Next(100, 3000)); if (packet.Code == PacketCode.AccountingRequest) { var acctStatusType = packet.GetAttribute <AcctStatusType>("Acct-Status-Type"); if (acctStatusType == AcctStatusType.Start) { return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); } if (acctStatusType == AcctStatusType.Stop) { return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); } if (acctStatusType == AcctStatusType.InterimUpdate) { return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); } } else if (packet.Code == PacketCode.AccessRequest) { if (packet.GetAttribute <String>("User-Name") == "*****@*****.**" && packet.GetAttribute <String>("User-Password") == "1234") { var response = packet.CreateResponsePacket(PacketCode.AccessAccept); response.AddAttribute("Acct-Interim-Interval", 60); return(response); } return(packet.CreateResponsePacket(PacketCode.AccessReject)); } throw new InvalidOperationException("Couldnt handle request?!"); }
/// <summary> /// Send a packet with default timeout of 3 seconds /// </summary> /// <param name="packet"></param> /// <param name="remoteEndpoint"></param> /// <returns></returns> public async Task <IRadiusPacket> SendPacketAsync(IRadiusPacket packet, IPEndPoint remoteEndpoint) { return(await SendPacketAsync(packet, remoteEndpoint, TimeSpan.FromSeconds(3))); }
/// <summary> /// Get the raw packet bytes /// </summary> /// <returns></returns> public byte[] GetBytes(IRadiusPacket packet) { var packetBytes = new List <byte> { (byte)packet.Code, packet.Identifier }; packetBytes.AddRange(new byte[18]); // Placeholder for length and authenticator var messageAuthenticatorPosition = 0; foreach (var attribute in packet.Attributes) { // todo add logic to check attribute object type matches type in dictionary? foreach (var value in attribute.Value) { var contentBytes = GetAttributeValueBytes(value); var headerBytes = new byte[2]; var attributeType = _radiusDictionary.GetAttribute(attribute.Key); switch (attributeType) { case DictionaryVendorAttribute _attributeType: headerBytes = new byte[8]; headerBytes[0] = 26; // VSA type var vendorId = BitConverter.GetBytes(_attributeType.VendorId); Array.Reverse(vendorId); Buffer.BlockCopy(vendorId, 0, headerBytes, 2, 4); headerBytes[6] = (byte)_attributeType.VendorCode; headerBytes[7] = (byte)(2 + contentBytes.Length); // length of the vsa part break; case DictionaryAttribute _attributeType: headerBytes[0] = attributeType.Code; // Encrypt password if this is a User-Password attribute if (_attributeType.Code == 2) { contentBytes = RadiusPassword.Encrypt(packet.SharedSecret, packet.Authenticator, contentBytes); } else if (_attributeType.Code == 80) // Remember the position of the message authenticator, because it has to be added after everything else { messageAuthenticatorPosition = packetBytes.Count; } break; default: throw new InvalidOperationException($"Unknown attribute {attribute.Key}, check spelling or dictionary"); } headerBytes[1] = (byte)(headerBytes.Length + contentBytes.Length); packetBytes.AddRange(headerBytes); packetBytes.AddRange(contentBytes); } } // Note the order of the bytes... var packetLengthBytes = BitConverter.GetBytes(packetBytes.Count); packetBytes[2] = packetLengthBytes[1]; packetBytes[3] = packetLengthBytes[0]; var packetBytesArray = packetBytes.ToArray(); // todo refactor this... if (packet.Code == PacketCode.AccountingRequest || packet.Code == PacketCode.DisconnectRequest || packet.Code == PacketCode.CoaRequest) { if (messageAuthenticatorPosition != 0) { var temp = new byte[16]; Buffer.BlockCopy(temp, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16); var messageAuthenticatorBytes = CalculateMessageAuthenticator(packetBytesArray, packet.SharedSecret, null); Buffer.BlockCopy(messageAuthenticatorBytes, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16); } var authenticator = CalculateRequestAuthenticator(packet.SharedSecret, packetBytesArray); Buffer.BlockCopy(authenticator, 0, packetBytesArray, 4, 16); } else if (packet.Code == PacketCode.StatusServer) { var authenticator = packet.RequestAuthenticator != null?CalculateResponseAuthenticator(packet.SharedSecret, packet.RequestAuthenticator, packetBytesArray) : packet.Authenticator; Buffer.BlockCopy(authenticator, 0, packetBytesArray, 4, 16); if (messageAuthenticatorPosition != 0) { var temp = new byte[16]; Buffer.BlockCopy(temp, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16); var messageAuthenticatorBytes = CalculateMessageAuthenticator(packetBytesArray, packet.SharedSecret, packet.RequestAuthenticator); Buffer.BlockCopy(messageAuthenticatorBytes, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16); } } else { if (messageAuthenticatorPosition != 0) { var temp = new byte[16]; Buffer.BlockCopy(temp, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16); var messageAuthenticatorBytes = CalculateMessageAuthenticator(packetBytesArray, packet.SharedSecret, packet.RequestAuthenticator); Buffer.BlockCopy(messageAuthenticatorBytes, 0, packetBytesArray, messageAuthenticatorPosition + 2, 16); } var authenticator = packet.RequestAuthenticator != null?CalculateResponseAuthenticator(packet.SharedSecret, packet.RequestAuthenticator, packetBytesArray) : packet.Authenticator; Buffer.BlockCopy(authenticator, 0, packetBytesArray, 4, 16); } return(packetBytesArray); }
/// <summary> /// Accounting /// </summary> /// <param name="packet"></param> /// <returns></returns> private IRadiusPacket HandleAccountingPacket(IRadiusPacket packet) { var acctStatusType = packet.GetAttribute <AcctStatusType>("Acct-Status-Type"); if (acctStatusType == AcctStatusType.Start || acctStatusType == AcctStatusType.Stop) { var usernamedomain = UsernameDomain.Parse(packet.GetAttribute <String>("User-Name")); var nodeid = GetUserNodeId(usernamedomain.Username, usernamedomain.Domain); _log.Info($"Handling {acctStatusType} packet for {usernamedomain}"); try { using (var db = _contextFactory.GetContext()) { var entry = new radiatoraccounting { username = usernamedomain.Username, realm = usernamedomain.Domain, node_id = nodeid, ACCTSTATUSTYPE = (packet.GetAttribute <AcctStatusType>("Acct-Status-Type")).ToString(), ACCTINPUTOCTETS = Convert.ToUInt32(packet.GetAttribute <UInt32?>("Acct-Input-Octets")), ACCTOUTPUTOCTETS = Convert.ToUInt32(packet.GetAttribute <UInt32?>("Acct-Output-Octets")), ACCTSESSIONID = packet.GetAttribute <String>("Acct-Session-Id"), ACCTSESSIONTIME = Convert.ToInt32(packet.GetAttribute <UInt32?>("Acct-Session-Time")), NASIDENTIFIER = packet.GetAttribute <String>("NAS-Identifier"), NASPORT = packet.GetAttribute <UInt32?>("NAS-Port"), NASPORTTYPE = packet.GetAttribute <UInt32?>("NAS-Port-Type").ToString(), WISPrLocationName = packet.GetAttribute <String>("WISPr-Location-Name"), temp = packet.GetAttribute <String>("Ipass-Location-Description"), timestamp_datetime = packet.Attributes.ContainsKey("Timestamp") ? (DateTime?)DateTimeOffset.FromUnixTimeSeconds(packet.GetAttribute <Int32>("Timestamp")).UtcDateTime : DateTime.UtcNow }; db.radiatoraccountings.Add(entry); db.SaveChanges(); } } catch (DbUpdateConcurrencyException) { _log.Info($"Duplicate {acctStatusType} request received"); } catch (Exception ex) { _log.Error("Something went wrong", ex); } if (acctStatusType == AcctStatusType.Start) { try { using (var db = _contextFactory.GetContext()) { db.radiatoronlines.Add(new radiatoronline { username = usernamedomain.Username, realm = usernamedomain.Domain, node_id = nodeid, ACCTSESSIONID = packet.GetAttribute <String>("Acct-Session-Id"), timestamp_datetime = packet.Attributes.ContainsKey("Timestamp") ? (DateTime?)DateTimeOffset.FromUnixTimeSeconds(packet.GetAttribute <Int32>("Timestamp")).UtcDateTime : DateTime.UtcNow, NASIDENTIFIER = packet.GetAttribute <String>("NAS-Identifier"), NASPORT = packet.GetAttribute <UInt32?>("NAS-Port"), NASPORTTYPE = packet.GetAttribute <UInt32?>("NAS-Port-Type").ToString(), WISPrLocationName = packet.GetAttribute <String>("Ipass-Location-Description") }); db.SaveChanges(); } } catch (DbUpdateConcurrencyException) { _log.Info("Cannot insert duplicate in radiatoronline"); } } if (acctStatusType == AcctStatusType.Stop) { try { using (var db = _contextFactory.GetContext()) { var acctsessionid = packet.GetAttribute <String>("Acct-Session-Id"); var online = db.radiatoronlines.SingleOrDefault(o => o.ACCTSESSIONID == acctsessionid); if (online != null) { db.radiatoronlines.Remove(online); db.SaveChanges(); } } } catch (DbUpdateConcurrencyException) { _log.Info("Nothing to remove from online"); } } } return(packet.CreateResponsePacket(PacketCode.AccountingResponse)); }