//Authenticates user BooleanResult IPluginAuthentication.AuthenticateUser(SessionProperties properties) { m_logger.DebugFormat("AuthenticateUser({0})", properties.Id.ToString()); if (!(bool)Settings.Store.EnableAuth) { m_logger.Debug("Authentication stage set on RADIUS plugin but authentication is not enabled in plugin settings."); return(new BooleanResult() { Success = false }); } // Get user info UserInformation userInfo = properties.GetTrackedSingle <UserInformation>(); if (String.IsNullOrEmpty(userInfo.Username) || String.IsNullOrEmpty(userInfo.Password)) { return new BooleanResult() { Success = false, Message = "Username and password must be provided." } } ; try { RADIUSClient client = GetClient(); bool result = client.Authenticate(userInfo.Username, userInfo.Password); if (result) { Session session = new Session(properties.Id, userInfo.Username, client); Packet p = client.lastReceievedPacket; //Check for session timeout if ((bool)Settings.Store.AllowSessionTimeout && p.containsAttribute(Packet.AttributeType.Session_Timeout)) { int seconds = client.lastReceievedPacket.getFirstIntAttribute(Packet.AttributeType.Session_Timeout); session.SetSessionTimeout(seconds, SessionTimeoutCallback); //m_logger.DebugFormat("Setting timeout for {0} to {1} seconds.", userInfo.Username, seconds); } if (p.containsAttribute(Packet.AttributeType.Idle_Timeout)) { int seconds = client.lastReceievedPacket.getFirstIntAttribute(Packet.AttributeType.Idle_Timeout); } if (p.containsAttribute(Packet.AttributeType.Vendor_Specific)) { foreach (byte[] val in p.getByteArrayAttributes(Packet.AttributeType.Vendor_Specific)) { //m_logger.DebugFormat("Vendor ID: {0:D}, Type: {1:D}, Value: {2}", Packet.VSA_vendorID(val), Packet.VSA_VendorType(val), Packet.VSA_valueAsString(val)); if ((bool)Settings.Store.WisprSessionTerminate && Packet.VSA_vendorID(val) == (int)Packet.VSA_WISPr.Vendor_ID && Packet.VSA_VendorType(val) == (int)Packet.VSA_WISPr.WISPr_Session_Terminate_Time) { try { //Value is in format "2014-03-11T23:59:59" string sdt = Packet.VSA_valueAsString(val); DateTime dt = DateTime.ParseExact(sdt, "yyyy-MM-dd'T'HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); if (dt > DateTime.Now) { session.Set_Session_Terminate(dt, SessionTerminateCallback); } else { m_logger.DebugFormat("The timestamp provided for WisperSessionTerminate time value has passed."); } } catch (FormatException e) { m_logger.DebugFormat("Unable to parse timestamp: {0}", Packet.VSA_valueAsString(val)); } } } } //Check for interim-update if ((bool)Settings.Store.SendInterimUpdates) { int seconds = 0; if (p.containsAttribute(Packet.AttributeType.Acct_Interim_Interval)) { seconds = client.lastReceievedPacket.getFirstIntAttribute(Packet.AttributeType.Acct_Interim_Interval); } //Check to see if plugin is set to send interim updates more frequently if ((bool)Settings.Store.ForceInterimUpdates) { int forceTime = (int)Settings.Store.InterimUpdateTime; if (forceTime > 0) { seconds = forceTime; } } //Set interim update if (seconds > 0) { session.SetInterimUpdate(seconds, InterimUpdatesCallback); m_logger.DebugFormat("Setting interim update interval for {0} to {1} seconds.", userInfo.Username, seconds); } else { m_logger.DebugFormat("Interim Updates are enabled, but no update interval was provided by the server or user."); } } lock (m_sessionManager) { //m_logger.DebugFormat("Adding session to m_sessionManager. ID: {0}, session: {1}", session.id, session); m_sessionManager.Add(session.id, session); } string message = null; if (p.containsAttribute(Packet.AttributeType.Reply_Message)) { message = p.getFirstStringAttribute(Packet.AttributeType.Reply_Message); } return(new BooleanResult() { Success = result, Message = message }); } //Failure string msg = "Unable to validate username or password."; if (client.lastReceievedPacket == null) { msg = msg + " No response from server."; } else if (client.lastReceievedPacket.containsAttribute(Packet.AttributeType.Reply_Message)) { msg = client.lastReceievedPacket.getFirstStringAttribute(Packet.AttributeType.Reply_Message); } else if (client.lastReceievedPacket.code == Packet.Code.Access_Reject) { msg = msg + String.Format(" Access Rejected."); } return(new BooleanResult() { Success = result, Message = msg }); } catch (RADIUSException re) { m_logger.Error("An error occurred during while authenticating.", re); return(new BooleanResult() { Success = false, Message = re.Message }); } catch (Exception e) { m_logger.Error("An unexpected error occurred while authenticating.", e); throw e; } }
//Authenticates user BooleanResult IPluginAuthentication.AuthenticateUser(SessionProperties properties) { m_logger.DebugFormat("AuthenticateUser({0})", properties.Id.ToString()); if (!(bool)Settings.Store.EnableAuth) { m_logger.Debug("Authentication stage set on RADIUS plugin but authentication is not enabled in plugin settings."); return new BooleanResult() { Success = false }; } // Get user info UserInformation userInfo = properties.GetTrackedSingle<UserInformation>(); if(String.IsNullOrEmpty(userInfo.Username) || String.IsNullOrEmpty(userInfo.Password)) return new BooleanResult() { Success = false, Message = "Username and password must be provided." }; try { RADIUSClient client = GetClient(); bool result = client.Authenticate(userInfo.Username, userInfo.Password); if (result) { Session session = new Session(properties.Id, userInfo.Username, client); Packet p = client.lastReceievedPacket; //Check for session timeout if ((bool)Settings.Store.AllowSessionTimeout && p.containsAttribute(Packet.AttributeType.Session_Timeout)) { int seconds = client.lastReceievedPacket.getFirstIntAttribute(Packet.AttributeType.Session_Timeout); session.SetSessionTimeout(seconds, SessionTimeoutCallback); //m_logger.DebugFormat("Setting timeout for {0} to {1} seconds.", userInfo.Username, seconds); } if (p.containsAttribute(Packet.AttributeType.Idle_Timeout)) { int seconds = client.lastReceievedPacket.getFirstIntAttribute(Packet.AttributeType.Idle_Timeout); } if(p.containsAttribute(Packet.AttributeType.Vendor_Specific)){ foreach(byte[] val in p.getByteArrayAttributes(Packet.AttributeType.Vendor_Specific)){ //m_logger.DebugFormat("Vendor ID: {0:D}, Type: {1:D}, Value: {2}", Packet.VSA_vendorID(val), Packet.VSA_VendorType(val), Packet.VSA_valueAsString(val)); if ((bool)Settings.Store.WisprSessionTerminate && Packet.VSA_vendorID(val) == (int)Packet.VSA_WISPr.Vendor_ID && Packet.VSA_VendorType(val) == (int)Packet.VSA_WISPr.WISPr_Session_Terminate_Time) { try { //Value is in format "2014-03-11T23:59:59" string sdt = Packet.VSA_valueAsString(val); DateTime dt = DateTime.ParseExact(sdt, "yyyy-MM-dd'T'HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); if (dt > DateTime.Now) { session.Set_Session_Terminate(dt, SessionTerminateCallback); } else m_logger.DebugFormat("The timestamp provided for WisperSessionTerminate time value has passed."); } catch (FormatException e) { m_logger.DebugFormat("Unable to parse timestamp: {0}", Packet.VSA_valueAsString(val)); } } } } //Check for interim-update if ((bool)Settings.Store.SendInterimUpdates) { int seconds = 0; if (p.containsAttribute(Packet.AttributeType.Acct_Interim_Interval)) { seconds = client.lastReceievedPacket.getFirstIntAttribute(Packet.AttributeType.Acct_Interim_Interval); } //Check to see if plugin is set to send interim updates more frequently if ((bool)Settings.Store.ForceInterimUpdates) { int forceTime = (int)Settings.Store.InterimUpdateTime; if (forceTime > 0) seconds = forceTime; } //Set interim update if (seconds > 0) { session.SetInterimUpdate(seconds, InterimUpdatesCallback); m_logger.DebugFormat("Setting interim update interval for {0} to {1} seconds.", userInfo.Username, seconds); } else { m_logger.DebugFormat("Interim Updates are enabled, but no update interval was provided by the server or user."); } } lock (m_sessionManager) { //m_logger.DebugFormat("Adding session to m_sessionManager. ID: {0}, session: {1}", session.id, session); m_sessionManager.Add(session.id, session); } string message = null; if (p.containsAttribute(Packet.AttributeType.Reply_Message)) message = p.getFirstStringAttribute(Packet.AttributeType.Reply_Message); return new BooleanResult() { Success = result, Message = message }; } //Failure string msg = "Unable to validate username or password."; if (client.lastReceievedPacket == null) { msg = msg + " No response from server."; } else if (client.lastReceievedPacket.containsAttribute(Packet.AttributeType.Reply_Message)) { msg = client.lastReceievedPacket.getFirstStringAttribute(Packet.AttributeType.Reply_Message); } else if (client.lastReceievedPacket.code == Packet.Code.Access_Reject) { msg = msg + String.Format(" Access Rejected."); } return new BooleanResult() { Success = result, Message = msg }; } catch (RADIUSException re) { m_logger.Error("An error occurred during while authenticating.", re); return new BooleanResult() { Success = false, Message = re.Message }; } catch (Exception e) { m_logger.Error("An unexpected error occurred while authenticating.", e); throw e; } }
//Processes accounting on logon/logoff public void SessionChange(System.ServiceProcess.SessionChangeDescription changeDescription, pGina.Shared.Types.SessionProperties properties) { if (changeDescription.Reason != System.ServiceProcess.SessionChangeReason.SessionLogon && changeDescription.Reason != System.ServiceProcess.SessionChangeReason.SessionLogoff) { //m_logger.DebugFormat("Not logging on or off for this session change call ({0})... exiting.", changeDescription.Reason); return; } if (properties == null) { //m_logger.DebugFormat("No session properties available. This account does not appear to be managed by pGina. Exiting SessionChange()"); return; } if (!(bool)Settings.Store.EnableAcct) { m_logger.Debug("Session Change stage set on RADIUS plugin but accounting is not enabled in plugin settings."); return; } //Determine username (may change depending on value of UseModifiedName setting) string username = null; UserInformation ui = properties.GetTrackedSingle <UserInformation>(); if (ui == null) { //m_logger.DebugFormat("No userinformation for this session logoff... exiting..."); return; } if ((bool)Settings.Store.UseModifiedName) { username = ui.Username; } else { username = ui.OriginalUsername; } Session session = null; //User is logging on if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogon) { lock (m_sessionManager) { //Check if session information is already available for this id if (!m_sessionManager.Keys.Contains(properties.Id)) { //No session info - must have authed with something other than RADIUS. //m_logger.DebugFormat("RADIUS Accounting Logon: Unable to find session for {0} with GUID {1}", username, properties.Id); if (!(bool)Settings.Store.AcctingForAllUsers) { //m_logger.Debug("Accounting for non-RADIUS users is disabled. Exiting."); return; } RADIUSClient client = GetClient(); session = new Session(properties.Id, username, client); m_sessionManager.Add(properties.Id, session); //Check forced interim-update setting if ((bool)Settings.Store.SendInterimUpdates && (bool)Settings.Store.ForceInterimUpdates) { int interval = (int)Settings.Store.InterimUpdateTime; session.SetInterimUpdate(interval, InterimUpdatesCallback); } } else { session = m_sessionManager[properties.Id]; } } //Determine which plugin authenticated the user (if any) PluginActivityInformation pai = properties.GetTrackedSingle <PluginActivityInformation>(); Packet.Acct_Authentic authSource = Packet.Acct_Authentic.Not_Specified; IEnumerable <Guid> authPlugins = pai.GetAuthenticationPlugins(); Guid LocalMachinePluginGuid = new Guid("{12FA152D-A2E3-4C8D-9535-5DCD49DFCB6D}"); foreach (Guid guid in authPlugins) { if (pai.GetAuthenticationResult(guid).Success) { if (guid == SimpleUuid) { authSource = Packet.Acct_Authentic.RADIUS; } else if (guid == LocalMachinePluginGuid) { authSource = Packet.Acct_Authentic.Local; } else //Not RADIUS, not Local, must be some other auth plugin { authSource = Packet.Acct_Authentic.Remote; } break; } } //We can finally start the accounting process try { lock (session) { session.windowsSessionId = changeDescription.SessionId; //Grab session ID now that we're authenticated session.username = username; //Accting username may have changed depending on 'Use Modified username for accounting option' session.client.startAccounting(username, authSource); //m_logger.DebugFormat("Successfully completed accounting start process..."); } } catch (Exception e) { m_logger.Error("Error occurred while starting accounting.", e); } } //User is logging off else if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogoff) { lock (m_sessionManager) { if (m_sessionManager.Keys.Contains(properties.Id)) { session = m_sessionManager[properties.Id]; } else { //m_logger.DebugFormat("Users {0} is logging off, but no RADIUS session information is available for session ID {1}.", username, properties.Id); return; } //Remove the session from the session manager m_sessionManager.Remove(properties.Id); } lock (session) { //Disbale any active callbacks for this session session.disableCallbacks(); session.active = false; //Assume normal logout if no other terminate reason is listed. if (session.terminate_cause == null) { session.terminate_cause = Packet.Acct_Terminate_Cause.User_Request; } try { //m_logger.DebugFormat("About to send accounting stop packet. Session has been active {0} seconds.", (DateTime.Now - session.client.accountingStartTime).TotalSeconds); session.client.stopAccounting(session.username, session.terminate_cause); } catch (RADIUSException re) { m_logger.DebugFormat("Unable to send accounting stop message for user {0} with ID {1}. Message: {2}", session.username, session.id, re.Message); } } } }
//Processes accounting on logon/logoff public void SessionChange(System.ServiceProcess.SessionChangeDescription changeDescription, pGina.Shared.Types.SessionProperties properties) { if (changeDescription.Reason != System.ServiceProcess.SessionChangeReason.SessionLogon && changeDescription.Reason != System.ServiceProcess.SessionChangeReason.SessionLogoff) { //m_logger.DebugFormat("Not logging on or off for this session change call ({0})... exiting.", changeDescription.Reason); return; } if (properties == null) { //m_logger.DebugFormat("No session properties available. This account does not appear to be managed by pGina. Exiting SessionChange()"); return; } if (!(bool)Settings.Store.EnableAcct) { m_logger.Debug("Session Change stage set on RADIUS plugin but accounting is not enabled in plugin settings."); return; } //Determine username (may change depending on value of UseModifiedName setting) string username = null; UserInformation ui = properties.GetTrackedSingle<UserInformation>(); if (ui == null) { //m_logger.DebugFormat("No userinformation for this session logoff... exiting..."); return; } if ((bool)Settings.Store.UseModifiedName) username = ui.Username; else username = ui.OriginalUsername; Session session = null; //User is logging on if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogon) { lock (m_sessionManager) { //Check if session information is already available for this id if (!m_sessionManager.Keys.Contains(properties.Id)) { //No session info - must have authed with something other than RADIUS. //m_logger.DebugFormat("RADIUS Accounting Logon: Unable to find session for {0} with GUID {1}", username, properties.Id); if(!(bool)Settings.Store.AcctingForAllUsers){ //m_logger.Debug("Accounting for non-RADIUS users is disabled. Exiting."); return; } RADIUSClient client = GetClient(); session = new Session(properties.Id, username, client); m_sessionManager.Add(properties.Id, session); //Check forced interim-update setting if ((bool)Settings.Store.SendInterimUpdates && (bool)Settings.Store.ForceInterimUpdates) { int interval = (int)Settings.Store.InterimUpdateTime; session.SetInterimUpdate(interval, InterimUpdatesCallback); } } else session = m_sessionManager[properties.Id]; } //Determine which plugin authenticated the user (if any) PluginActivityInformation pai = properties.GetTrackedSingle<PluginActivityInformation>(); Packet.Acct_Authentic authSource = Packet.Acct_Authentic.Not_Specified; IEnumerable<Guid> authPlugins = pai.GetAuthenticationPlugins(); Guid LocalMachinePluginGuid = new Guid("{12FA152D-A2E3-4C8D-9535-5DCD49DFCB6D}"); foreach (Guid guid in authPlugins) { if (pai.GetAuthenticationResult(guid).Success) { if (guid == SimpleUuid) authSource = Packet.Acct_Authentic.RADIUS; else if (guid == LocalMachinePluginGuid) authSource = Packet.Acct_Authentic.Local; else //Not RADIUS, not Local, must be some other auth plugin authSource = Packet.Acct_Authentic.Remote; break; } } //We can finally start the accounting process try { lock (session) { session.windowsSessionId = changeDescription.SessionId; //Grab session ID now that we're authenticated session.username = username; //Accting username may have changed depending on 'Use Modified username for accounting option' session.client.startAccounting(username, authSource); //m_logger.DebugFormat("Successfully completed accounting start process..."); } } catch (Exception e) { m_logger.Error("Error occurred while starting accounting.", e); } } //User is logging off else if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogoff) { lock (m_sessionManager) { if (m_sessionManager.Keys.Contains(properties.Id)) session = m_sessionManager[properties.Id]; else { //m_logger.DebugFormat("Users {0} is logging off, but no RADIUS session information is available for session ID {1}.", username, properties.Id); return; } //Remove the session from the session manager m_sessionManager.Remove(properties.Id); } lock (session) { //Disbale any active callbacks for this session session.disableCallbacks(); session.active = false; //Assume normal logout if no other terminate reason is listed. if (session.terminate_cause == null) session.terminate_cause = Packet.Acct_Terminate_Cause.User_Request; try { //m_logger.DebugFormat("About to send accounting stop packet. Session has been active {0} seconds.", (DateTime.Now - session.client.accountingStartTime).TotalSeconds); session.client.stopAccounting(session.username, session.terminate_cause); } catch (RADIUSException re) { m_logger.DebugFormat("Unable to send accounting stop message for user {0} with ID {1}. Message: {2}", session.username, session.id, re.Message); } } } }