public bool stopAccounting(string username, Packet.Acct_Terminate_CauseType? terminateCause) { Packet accountingRequest = new Packet(Packet.Code.Accounting_Request, identifier, sharedKey); accountingRequest.addAttribute(Packet.AttributeType.User_Name, username); if(String.IsNullOrEmpty(sessionId)) throw new RADIUSException("Session ID must be present for accounting."); accountingRequest.addAttribute(Packet.AttributeType.Acct_Session_Id, sessionId); accountingRequest.addAttribute(Packet.AttributeType.Acct_Status_Type, (int)Packet.Acct_Status_TypeType.Stop); if(terminateCause != null) accountingRequest.addAttribute(Packet.AttributeType.Acct_Terminate_Cause, (int) Packet.Acct_Terminate_CauseType.User_Request); //Accounting request packet created, sending data... UdpClient client = new UdpClient(server, accountingPort); client.Client.SendTimeout = timeout; client.Client.ReceiveTimeout = timeout; m_logger.DebugFormat("Attempting to send {0} for user {1}", accountingRequest.code, username); int retryCt = 0; while (true) { try { client.Send(accountingRequest.toBytes(), accountingRequest.length); //Listen for response, since the server has been specified, we don't need to re-specify server IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); byte[] respBytes = client.Receive(ref RemoteIpEndPoint); Packet responsePacket = new Packet(respBytes); //Verify packet response is good, authenticator should be MD5(Code+ID+Length+RequestAuth+Attributes+Secret) if (!responsePacket.verifyResponseAuthenticator(accountingRequest.authenticator, sharedKey)) throw new RADIUSException(String.Format("Received response to accounting request with code: {0}, but an incorrect response authenticator was supplied.", responsePacket.code)); lastReceievedPacket = responsePacket; client.Close(); m_logger.DebugFormat("Received accounting response: {0} for user {1}", responsePacket.code, username); return responsePacket.code == Packet.Code.Accounting_Response; //SocketException is thrown if the server does not respond by end of timeout } catch (SocketException se) { m_logger.DebugFormat("Accounting stop attempt {0}/{1} failed. Reason: {2}", retryCt + 1, maxRetries, se.Message); retryCt++; if (retryCt >= maxRetries) throw new RADIUSException(String.Format("No response from server after {0} tries.", maxRetries), se); } catch (Exception e) { throw new RADIUSException("Unexpected error while trying stop accounting.", e); } } }
public bool interimUpdate(string username) { Packet p = new Packet(Packet.Code.Accounting_Request, this.identifier, this.sharedKey); p.addAttribute(Packet.AttributeType.User_Name, username); if (String.IsNullOrEmpty(sessionId)) throw new RADIUSException("Session ID must be present for accounting."); p.addAttribute(Packet.AttributeType.Acct_Session_Id, sessionId); p.addAttribute(Packet.AttributeType.Acct_Status_Type, (int)Packet.Acct_Status_Type.Interim_Update); p.addAttribute(Packet.AttributeType.Acct_Session_Time, (int)(DateTime.Now - accountingStartTime).TotalSeconds); if (NAS_IP_Address != null) p.addAttribute(Packet.AttributeType.NAS_IP_Address, NAS_IP_Address); if (!String.IsNullOrEmpty(NAS_Identifier)) p.addAttribute(Packet.AttributeType.NAS_Identifier, NAS_Identifier); if (!String.IsNullOrEmpty(called_station_id)) p.addAttribute(Packet.AttributeType.Called_Station_Id, called_station_id); m_logger.DebugFormat("Attempting to send interim-update for user {0}", username); for (int retryCt = 0; retryCt <= maxRetries; retryCt++) { foreach (string server in servers) { //Accounting request packet created, sending data... UdpClient client = new UdpClient(server, accountingPort); client.Client.SendTimeout = timeout; client.Client.ReceiveTimeout = timeout; try { client.Send(p.toBytes(), p.length); //Listen for response, since the server has been specified, we don't need to re-specify server IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); byte[] respBytes = client.Receive(ref RemoteIpEndPoint); Packet responsePacket = new Packet(respBytes); //Verify packet response is good, authenticator should be MD5(Code+ID+Length+RequestAuth+Attributes+Secret) if (!responsePacket.verifyResponseAuthenticator(p.authenticator, sharedKey)) throw new RADIUSException(String.Format("Received response to interim-update with code: {0}, but an incorrect response authenticator was supplied.", responsePacket.code)); lastReceievedPacket = responsePacket; client.Close(); m_logger.DebugFormat("Received interim-update response: {0} for user {1}", responsePacket.code, username); return responsePacket.code == Packet.Code.Accounting_Response; //SocketException is thrown if the server does not respond by end of timeout } catch (SocketException se) { m_logger.DebugFormat("Accounting interim-update attempt {0}/{1} using {2} failed. Reason: {3}", retryCt + 1, maxRetries + 1, server, se.Message); } catch (Exception e) { throw new RADIUSException("Unexpected error while sending interim-update.", e); } } } throw new RADIUSException(String.Format("No response from server(s) after {0} tries.", maxRetries + 1)); }
//Connects to the RADIUS server and attempts to authenticate the specified user info //Sets username value and authenticated members IFF successful public bool Authenticate(string username, string password) { UdpClient client = new UdpClient(server, authenticationPort); client.Client.SendTimeout = timeout; client.Client.ReceiveTimeout = timeout; Packet authPacket = new Packet(Packet.Code.Access_Request, identifier, sharedKey); authPacket.sharedKey = sharedKey; authPacket.addAttribute(Packet.AttributeType.User_Name, username); authPacket.addAttribute(Packet.AttributeType.User_Password, password); if(!String.IsNullOrEmpty(sessionId)) authPacket.addAttribute(Packet.AttributeType.Acct_Session_Id, sessionId); if (NAS_Identifier == null && NAS_IP_Address == null) throw new RADIUSException("A NAS_Identifier or NAS_IP_Address (or both) must be supplied."); if(NAS_IP_Address != null) authPacket.addRawAttribute(Packet.AttributeType.NAS_IP_Address, NAS_IP_Address); if (NAS_Identifier != null) authPacket.addAttribute(Packet.AttributeType.NAS_Identifier, NAS_Identifier); m_logger.DebugFormat("Attempting to send {0} for user {1}", authPacket.code, username); int retryCt = 0; while (true) { try { client.Send(authPacket.toBytes(), authPacket.length); //Listen for response, since the server has been specified, we don't need to re-specify server IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); byte[] respBytes = client.Receive(ref RemoteIpEndPoint); Packet responsePacket = new Packet(respBytes); //Verify packet authenticator is correct if (!responsePacket.verifyResponseAuthenticator(authPacket.authenticator, sharedKey)) throw new RADIUSException(String.Format("Received response to authentication with code: {0}, but an incorrect response authenticator was supplied.", responsePacket.code)); lastReceievedPacket = responsePacket; client.Close(); m_logger.DebugFormat("Received authentication response: {0} for user {1}", responsePacket.code, username); if (responsePacket.code == Packet.Code.Access_Accept) { this.authenticated = true; return true; } else return false; } //SocketException is thrown if the server does not respond by end of timeout catch (SocketException se) { m_logger.DebugFormat("Authentication attempt {0}/{1} failed. Reason: {2}", retryCt+1, maxRetries, se.Message); retryCt++; if (retryCt >= maxRetries) throw new RADIUSException(String.Format("No response from server after {0} tries.", maxRetries), se); } catch (Exception e) { throw new RADIUSException("Unexpected error while trying to authenticate.", e); } } }
//Sends a start accounting request to the RADIUS server, returns true on acknowledge of request public bool startAccounting(string username, Packet.Acct_Authentic authType) { //Create accounting request packet Packet accountingRequest = new Packet(Packet.Code.Accounting_Request, identifier, sharedKey); accountingRequest.addAttribute(Packet.AttributeType.User_Name, username); accountingRequest.addAttribute(Packet.AttributeType.Acct_Status_Type, (int)Packet.Acct_Status_Type.Start); if (String.IsNullOrEmpty(sessionId)) //Create new guid sessionId = Guid.NewGuid().ToString(); accountingRequest.addAttribute(Packet.AttributeType.Acct_Session_Id, sessionId); if (String.IsNullOrEmpty(NAS_Identifier) && NAS_IP_Address == null) throw new RADIUSException("A NAS_Identifier or NAS_IP_Address (or both) must be supplied."); if (NAS_IP_Address != null) accountingRequest.addAttribute(Packet.AttributeType.NAS_IP_Address, NAS_IP_Address); if (!String.IsNullOrEmpty(NAS_Identifier)) accountingRequest.addAttribute(Packet.AttributeType.NAS_Identifier, NAS_Identifier); if (!String.IsNullOrEmpty(called_station_id)) accountingRequest.addAttribute(Packet.AttributeType.Called_Station_Id, called_station_id); if (authType != Packet.Acct_Authentic.Not_Specified) accountingRequest.addAttribute(Packet.AttributeType.Acct_Authentic, (int)authType); //m_logger.DebugFormat("Attempting to send {0} for user {1}", accountingRequest.code, username); for (int retryCt = 0; retryCt <= maxRetries; retryCt++) { foreach (string server in servers) { //Accounting request packet created, sending data... UdpClient client = new UdpClient(server, accountingPort); client.Client.SendTimeout = timeout; client.Client.ReceiveTimeout = timeout; try { client.Send(accountingRequest.toBytes(), accountingRequest.length); //Listen for response, since the server has been specified, we don't need to re-specify server IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); byte[] respBytes = client.Receive(ref RemoteIpEndPoint); Packet responsePacket = new Packet(respBytes); //Verify packet response is good, authenticator should be MD5(Code+ID+Length+RequestAuth+Attributes+Secret) if (!responsePacket.verifyResponseAuthenticator(accountingRequest.authenticator, sharedKey)) throw new RADIUSException(String.Format("Received response to accounting request with code: {0}, but an incorrect response authenticator was supplied.", responsePacket.code)); lastReceievedPacket = responsePacket; client.Close(); m_logger.DebugFormat("Received accounting response: {0} for user {1}", responsePacket.code, username); if (responsePacket.code == Packet.Code.Accounting_Response) accountingStartTime = DateTime.Now; return responsePacket.code == Packet.Code.Accounting_Response; } //SocketException is thrown if the server does not respond by end of timeout catch (SocketException se) { m_logger.DebugFormat("Accounting start attempt {0}/{1} using {2} failed. Reason: {3}", retryCt + 1, maxRetries + 1, server, se.Message); } catch (Exception e) { throw new RADIUSException("Unexpected error while trying start accounting.", e); } } } throw new RADIUSException(String.Format("No response from server(s) after {0} tries.", maxRetries + 1)); }