/// <summary> /// Opens a RADIUS client using the <see cref="RadiusClientSettings" /> passed. /// </summary> /// <param name="settings">The client settings.</param> /// <remarks> /// <note> /// Note that all successful calls to <b>Open()</b> must eventually be matched /// with a call to <see cref="Close" /> so that system resources will be /// released promptly. /// </note> /// </remarks> public void Open(RadiusClientSettings settings) { using (TimedLock.Lock(this)) { if (IsOpen) { throw new RadiusException("RADIUS client is already open."); } if (settings.PortCount > 1 && settings.NetworkBinding.Port != 0) { throw new RadiusException("RADIUS client [NetworkBinding.Port] must be zero if [PortCount] is greater than one."); } ports = new RadiusClientPort[settings.PortCount]; for (int i = 0; i < settings.PortCount; i++) { ports[i] = new RadiusClientPort(); ports[i].Open(settings); } bkTimer = new GatedTimer(new TimerCallback(OnBkTimer), null, settings.BkTaskInterval, settings.BkTaskInterval); nextPort = 0; } }
/// <summary> /// Opens a RADIUS client port using the <see cref="RadiusClientSettings" /> passed. /// </summary> /// <param name="settings">The client settings.</param> /// <remarks> /// <note> /// All successful calls to <see cref="Open" /> must eventually be matched /// with a call to <see cref="Close" /> so that system resources will be /// released promptly. /// </note> /// </remarks> public void Open(RadiusClientSettings settings) { using (TimedLock.Lock(this)) { if (isOpen) { throw new RadiusException("RADIUS client port is already open."); } sock = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); sock.Bind(settings.NetworkBinding); this.sock.SendBufferSize = settings.SocketBuffer; this.sock.ReceiveBufferSize = settings.SocketBuffer; isOpen = true; networkBinding = settings.NetworkBinding; servers = settings.Servers; secret = settings.Secret; retryInterval = settings.RetryInterval; maxTransmissions = settings.MaxTransmissions; realmFormat = settings.RealmFormat; nextID = 0; serverPos = 0; transactions = new AuthTransaction[256]; recvBuf = new byte[TcpConst.MTU]; sourceEP = new IPEndPoint(IPAddress.Any, 0); onReceive = new AsyncCallback(OnReceive); if (networkBinding.Address.Equals(IPAddress.Any)) { nasIPAddress = NetHelper.GetActiveAdapter(); } else { nasIPAddress = networkBinding.Address; } // Initiate reception of the first RADIUS packet. sock.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref sourceEP, onReceive, null); } }
//--------------------------------------------------------------------- // Static members /// <summary> /// Reads the RADIUS client settings from the application's configuration /// using the specified key prefix. /// </summary> /// <param name="keyPrefix">The application configuration key prefix.</param> /// <returns>The server settings.</returns> /// <remarks> /// <para> /// The RADIUS client settings are loaded from the application /// configuration, using the specified key prefix. The following /// settings are recognized by the class: /// </para> /// <div class="tablediv"> /// <table class="dtTABLE" cellspacing="0" ID="Table1"> /// <tr valign="top"> /// <th width="1">Setting</th> /// <th width="1">Default</th> /// <th width="90%">Description</th> /// </tr> /// <tr valign="top"> /// <td>Server[#]</td> /// <td>(required)</td> /// <td> /// An array specifying one or more RADIUS server network bindings /// formatted as descibed in <see cref="NetworkBinding" />. Authentication /// packets will be transmitted to these servers using a round robin /// mechanism to implement load balancing and failover. /// </td> /// </tr> /// <tr valign="top"> /// <td>SocketBuffer</td> /// <td>32K</td> /// <td> /// Byte size of the client socket's send and receive buffers. /// </td> /// </tr> /// <tr valign="top"> /// <td>NetworkBinding</td> /// <td>ANY:0</td> /// <td> /// <para> /// Specifies the IP address of the network card the client is /// and port bindings. Use an IP address of ANY to bind to /// all network interfaces. ANY is suitable for single homed machines. /// Machines that are actually connected to multiple networks should /// specify a specific network binding here to ensure that the NAS-IP-Address /// of RADIUS authentication packets are initialized properly. /// </para> /// <para> /// A specific port number may be selected or 0 can be specified, /// indicating that the operating system should select a free port. /// </para> /// </td> /// </tr> /// <tr valign="top"> /// <td>PortCount</td> /// <td>4</td> /// <td> /// The number of RADIUS client UDP ports to open. /// </td> /// </tr> /// <tr valign="top"> /// <td>Secret</td> /// <td>(required)</td> /// <td> /// The secret shared by the RADIUS client and server. /// </td> /// </tr> /// <tr valign="top"> /// <td>RetryInterval</td> /// <td>5s</td> /// <td> /// Maximum time to wait for a response packet before retransmitting /// an authentication request. /// </td> /// </tr> /// <tr valign="top"> /// <td>BkTaskInterval</td> /// <td>1s</td> /// <td> /// The interval at which background tasks such as retransmitting /// a request should be processed. /// </td> /// </tr> /// <tr valign="top"> /// <td>MaxTransmissions</td> /// <td>4</td> /// <td> /// The maximum number of transmission attempts before aborting an /// authentication with a timeout. /// </td> /// </tr> /// <tr valign="top"> /// <td>RealmFormat</td> /// <td>Email</td> /// <td> /// Specifies how user names are to be generated from the /// <b>realm</b> and <b>account</b> components. See /// <see cref="RealmFormat" /> for more information. /// The possible values are: <b>Slash</b> and <b>Email</b>. /// </td> /// </tr> /// </table> /// </div> /// </remarks> public static RadiusClientSettings LoadConfig(string keyPrefix) { RadiusClientSettings settings; Config config; NetworkBinding[] servers; string secret; config = new Config(keyPrefix); servers = config.GetNetworkBindingArray("Server"); if (servers == null || servers.Length == 0) { throw new RadiusException("[{0}Server] configuration setting is missing.", config.KeyPrefix); } secret = config.Get("Secret", (string)null); if (secret == null) { throw new RadiusException("[{0}Secret] configuration setting is missing.", config.KeyPrefix); } settings = new RadiusClientSettings(servers, secret); settings.SocketBuffer = config.Get("SocketBuffer", settings.SocketBuffer); settings.NetworkBinding = config.Get("NetworkBinding", settings.NetworkBinding); settings.RetryInterval = config.Get("RetryInterval", settings.RetryInterval); settings.BkTaskInterval = config.Get("BkTaskInterval", settings.BkTaskInterval); settings.MaxTransmissions = config.Get("MaxTransmissions", settings.MaxTransmissions); settings.PortCount = config.Get("PortCount", settings.PortCount); settings.RealmFormat = config.Get <RealmFormat>("RealmFormat", settings.RealmFormat); if (settings.NetworkBinding.IsHost) { throw new RadiusException("[{0}] is not a valid RADIUS client network binding.", settings.NetworkBinding); } return(settings); }
/// <summary> /// Opens the RADIUS client, initializing it with settings loaded from /// the application configuration. /// </summary> /// <param name="keyPrefix"> /// The key prefix to use when loading client settings from the /// application configuration. /// </param> /// <remarks> /// <para> /// The RADIUS client settings are loaded from the application /// configuration, using the specified key prefix. See /// <see cref="RadiusClientSettings.LoadConfig" /> for a description /// of the client application configuration settings. /// </para> /// <note> /// All successful calls to <b>Open()</b> must eventually be matched /// with a call to <see cref="Close" /> so that system resources will be /// released promptly. /// </note> /// </remarks> public void Open(string keyPrefix) { Open(RadiusClientSettings.LoadConfig(keyPrefix)); }