コード例 #1
0
        //Processes accounting on logon/logoff
        public void SessionChange(System.ServiceProcess.SessionChangeDescription changeDescription, pGina.Shared.Types.SessionProperties properties)
        {
            m_logger.DebugFormat("SessionChange({0})", properties.Id.ToString());

            string username = null;

            if ((bool)Settings.Store.UseModifiedName)
            {
                username = properties.GetTrackedSingle <UserInformation>().Username;
            }
            else
            {
                username = properties.GetTrackedSingle <UserInformation>().OriginalUsername;
            }

            if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogon)
            {
                //Create a new unique id for this accounting session and store it
                String sessionId = Guid.NewGuid().ToString();
                lock (sessionIDLock)
                {
                    sessionIDs.Add(username, sessionId);
                }

                //Determine which plugin authenticated the user (if any)
                PluginActivityInformation pai         = properties.GetTrackedSingle <PluginActivityInformation>();
                Packet.Acct_AuthenticType authSource  = Packet.Acct_AuthenticType.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_AuthenticType.RADIUS;
                        }
                        else if (guid == LocalMachinePluginGuid)
                        {
                            authSource = Packet.Acct_AuthenticType.Local;
                        }
                        else
                        {
                            authSource = Packet.Acct_AuthenticType.Remote;
                        }
                        break;
                    }
                }

                try
                {
                    RADIUSClient client = GetClient(sessionId);
                    client.startAccounting(username, authSource);
                }
                catch (Exception e)
                {
                    m_logger.Error("Error occurred while starting accounting.", e);
                }
            }

            else if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogoff)
            {
                //Check if guid was stored from accounting start request (if not, no point in sending a stop request)
                string sessionId = null;
                lock (sessionIDLock)
                {
                    sessionId = sessionIDs.ContainsKey(username) ? sessionIDs[username] : null;

                    if (sessionId == null)
                    {
                        m_logger.ErrorFormat("Error sending accounting stop request. No guid available for {0}", username);
                        return;
                    } //Remove the session id since we're logging off
                    sessionIDs.Remove(username);
                }

                try
                {
                    RADIUSClient client = GetClient(sessionId);
                    client.stopAccounting(username, Packet.Acct_Terminate_CauseType.User_Request);
                }
                catch (Exception e)
                {
                    m_logger.Error("Error occurred while stopping accounting.", e);
                    return;
                }
            }
        }
コード例 #2
0
        //Sends a start accounting request to the RADIUS server, returns true on acknowledge of request
        public bool startAccounting(string username, Packet.Acct_AuthenticType 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_TypeType.Start);
            if (String.IsNullOrEmpty(sessionId))
            {
                throw new RADIUSException("Session ID must be present for accounting.");
            }
            accountingRequest.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)
            {
                accountingRequest.addRawAttribute(Packet.AttributeType.NAS_IP_Address, NAS_IP_Address);
            }
            if (NAS_Identifier != null)
            {
                accountingRequest.addAttribute(Packet.AttributeType.NAS_Identifier, NAS_Identifier);
            }

            if (authType != Packet.Acct_AuthenticType.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);

                        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));
        }