/// <summary> /// Establishes a session with the realm map provider. /// </summary> /// <param name="engineSettings">The associated authentication engine's settings.</param> /// <param name="path"> /// The fully qualified path to the ANSI encoded mapping file. /// </param> /// <remarks> /// <para> /// This provider simply loads a static list of provider mappings from an /// ANSI encoded text file. The mappings are specified one per line in /// the file. The format for each mapping is: /// </para> /// <code language="none"> /// <realm>$$<extension typeref>$$<args>$$<query> /// </code> /// <para> /// where <b>realm</b> identifies the authentication realm, <b>extension typeref</b> /// specifies the type implementing <see cref="IAuthenticationExtension" /> formatted as /// specified for <see cref="Config.Parse(string,System.Type)" />, <b>args</b> /// are the provider arguments and <b>query</b> is the optional provider query /// string. Note the use of <b>$$</b> as field separators. /// </para> /// <para> /// Empty lines and comment lines beginning with "//" are ignored. Note that /// environment variables embedded in the realm mappings will be expanded before /// the mapping is processed. Environment variables are formatted as <b>$(variable)</b>. /// See <see cref="EnvironmentVars" /> for a list of the build-in environment /// variables. /// </para> /// <code language="none"> /// // This is a comment line /// /// lilltek.com$$LillTek.Datacenter.Server.FileAuthenticationExtension:LillTek.Datacenter.Server.dll$$path=c:\lilltek.txt$$ /// test.com$$LillTek.Datacenter.Server.FileAuthenticationExtension:LillTek.Datacenter.Server.dll$$path=c:\test.txt$$ /// </code> /// <note> /// Every call to <see cref="Open" /> should be matched by a call to /// <see cref="Close" /> or <see cref="Dispose" />. /// </note> /// </remarks> /// <exception cref="AuthenticationException">Thrown if there's an error loading the map.</exception> public void Open(AuthenticationEngineSettings engineSettings, string path) { using (TimedLock.Lock(this)) { if (IsOpen) { throw new AuthenticationException("Provider is already open."); } this.path = path; this.engineSettings = engineSettings; } }
/// <summary> /// Constructor. /// </summary> /// <param name="engineSettings">The <see cref="AuthenticationEngineSettings" />.</param> /// <param name="realm">The realm string.</param> /// <param name="extensionType">The <see cref="IAuthenticationExtension" /> type.</param> /// <param name="args">The realm and provider arguments.</param> /// <param name="query">The optional provider query.</param> /// <remarks> /// See the <see cref="RealmMapping" /> comments for a description of the /// realm settings retrieved from the <b>args</b> parameter and the /// comments for the specific <see cref="IAuthenticationExtension" /> /// implementation for a description of the provider specific arguments. /// </remarks> public RealmMapping(AuthenticationEngineSettings engineSettings, string realm, System.Type extensionType, ArgCollection args, string query) { this.Realm = realm; this.ExtensionType = extensionType; this.ExtensionName = extensionType.Name; this.Args = args; this.Query = query; this.AuthExtension = null; this.LockoutCount = args.Get("LockoutCount", engineSettings.LockoutCount); this.LockoutThreshold = args.Get("LockoutThreshold", engineSettings.LockoutThreshold); this.LockoutTime = args.Get("LockoutTime", engineSettings.LockoutTime); }
//--------------------------------------------------------------------- // Static members /// <summary> /// Loads the settings for a <see cref="AuthenticationEngine" /> instance /// from the application configuration, using the specified configuration /// key prefix. /// </summary> /// <param name="keyPrefix">The application configuration key prefix.</param> /// <returns>An <see cref="AuthenticationEngineSettings" /> instance.</returns> /// <remarks> /// <para> /// The <see cref="AuthenticationEngine" /> settings are loaded from the application /// configuration, under 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>RealmMapLoadInterval</td> /// <td>10m</td> /// <td> /// The interval at which the realm map will be reloaded. /// </td> /// </tr> /// <tr valign="top"> /// <td>CacheTTL</td> /// <td>10m</td> /// <td> /// The maximuim time an authentication result should be cached by the engine. /// Use 0 to disable caching. This overrides the MaxCacheTime time returned by an /// authentication source if this number is smaller. /// </td> /// </tr> /// <tr valign="top"> /// <td>MaxCacheSize</td> /// <td>100000</td> /// <td> /// The maximum number of cached authentication success results. Use 0 to disable /// caching. /// </td> /// </tr> /// <tr valign="top"> /// <td>NakCacheTTL</td> /// <td>15m</td> /// <td> /// Specifies the maximum time a failed authentication attempt should be /// cached. Set this to <see cref="TimeSpan.Zero" /> to /// disable NAK caching. Note that the actual time a failed attempt will /// be cached is the minimum of this value and <b>LockoutThreshold</b> /// or <b>LockoutTime</b> depending on whether the account has been /// locked. /// </td> /// </tr> /// <tr valign="top"> /// <td>MaxNakCacheSize</td> /// <td>100000</td> /// <td> /// The maximum number of cached authentication failure results. This overrides the /// MaxCacheTime time returned by an authentication source if this number is smaller. /// Use 0 to disable NAK caching. /// </td> /// </tr> /// <tr valign="top"> /// <td>CacheFlushInterval</td> /// <td>1m</td> /// <td> /// The interval between authentication success and failure cache flushes. /// </td> /// </tr> /// <tr valign="top"> /// <td>BkTaskInterval</td> /// <td>5s</td> /// <td> /// The interval at which engine background tasks are scheduled. These /// tasks include periodically reloading the realm map and flushing the /// authentication cache. /// </td> /// </tr> /// <tr valign="top"> /// <td>LogAuthSuccess</td> /// <td>true</td> /// <td> /// Indicates whether successful login attempts should be logged. /// </td> /// </tr> /// <tr valign="top"> /// <td>LogAuthFailure</td> /// <td>true</td> /// <td> /// Indicates whether failed login attempts should be logged. /// </td> /// </tr> /// <tr valign="top"> /// <td>LockoutCount</td> /// <td>5</td> /// <td> /// Indicates the default maximum number of failed authentication requests /// to be allowed for a realm/account combinations for nonexistent realms /// before the account will be locked out. This parameter can be overridden /// for specific realms. /// </td> /// </tr> /// <tr valign="top"> /// <td>LockoutThreshold</td> /// <td>1m</td> /// <td> /// The default period of time that can elapse between failed authentication /// attempts where the failed attempts will <b>not</b> be counted against the /// <see cref="LockoutCount" />. Set this to <see cref="TimeSpan.Zero" /> /// to disable account lockout for the realm. This parameter can be overridden /// for specific realms. /// </td> /// </tr> /// <tr valign="top"> /// <td>LockoutTime</td> /// <td>5m</td> /// <td> /// The default period of time an account will remain locked after being locked /// out due to too many failed authentication attempts. This parameter can be overridden /// for specific realms. /// </td> /// </tr> /// </table> /// </div> /// </remarks> public static AuthenticationEngineSettings LoadConfig(string keyPrefix) { var settings = new AuthenticationEngineSettings(); var config = new Config(keyPrefix); settings.RealmMapLoadInterval = config.Get("RealmMapLoadInterval", settings.RealmMapLoadInterval); settings.CacheTTL = config.Get("CacheTTL", settings.CacheTTL); settings.MaxCacheSize = config.Get("MaxCacheSize", settings.MaxCacheSize); settings.NakCacheTTL = config.Get("NakCacheTTL", settings.NakCacheTTL); settings.MaxNakCacheSize = config.Get("MaxNakCacheSize", settings.MaxNakCacheSize); settings.CacheFlushInterval = config.Get("CacheFlushInterval", settings.CacheFlushInterval); settings.BkTaskInterval = config.Get("BkTaskInterval", settings.BkTaskInterval); settings.LogAuthSuccess = config.Get("LogAuthSuccess", settings.LogAuthSuccess); settings.LogAuthFailure = config.Get("LogAuthFailure", settings.LogAuthFailure); settings.LockoutCount = config.Get("LockoutCount", settings.LockoutCount); settings.LockoutThreshold = config.Get("LockoutThreshold", settings.LockoutThreshold); settings.LockoutTime = config.Get("LockoutTime", settings.LockoutTime); return(settings); }
/// <summary> /// Establishes a session with the realm map provider. /// </summary> /// <param name="engineSettings">The associated authentication engine's settings.</param> /// <param name="key"> /// The configuration key holding the ODBC connection string and query /// (see the remarks section for more information. /// </param> /// <remarks> /// <para> /// The <b>key</b> parameter is passed as the fully qualified name of /// the configuration key that specifies the ODBC connection string as /// well as the SQL query to be used to retrieve the realm map from the /// data source. The key value must be formatted as: /// </para> /// <code language="none"> /// <connection string>$$<query> /// </code> /// <para> /// where <b>connection string</b> is the ODBC connection string and /// <b>query</b> is the SQL query or stored procedure call that returns /// the realm map as a result set. /// </para> /// <note> /// Every call to <see cref="Open" /> should be matched by a call to /// <see cref="Close" /> or <see cref="Dispose" />. /// </note> /// </remarks> /// <exception cref="AuthenticationException">Thrown if there's an opening the provider.</exception> public void Open(AuthenticationEngineSettings engineSettings, string key) { string value; string[] fields; using (TimedLock.Lock(this)) { if (IsOpen) { throw new AuthenticationException("Provider is already open."); } this.engineSettings = engineSettings; value = Config.Global.Get(key); if (value == null) { throw new AuthenticationException("Configuration key [{0}] not found.", key); } fields = value.Split(new string[] { "$$" }, StringSplitOptions.None); if (fields.Length != 2) { throw new AuthenticationException("Expected [<ODBC connection string>$$<query>] in configuration key[{0}].", key); } conString = fields[0].Trim(); query = fields[1].Trim(); if (conString == string.Empty) { throw new AuthenticationException("Invalid ODBC connection string in key [{0}].", key); } if (query == string.Empty) { throw new AuthenticationException("Missing query in key [{0}].", key); } } }
/// <summary> /// Establishes a session with the realm map provider. /// </summary> /// <param name="engineSettings">The associated authentication engine's settings.</param> /// <param name="key"> /// This is simply the name of the configuration array that holds the /// static realm mappings. /// </param> /// <remarks> /// <para> /// This provider simply loads a static list of provider mappings from the /// application's configuration settings. The mappings are loaded from /// the configuration key array specified by the <b>key</b> parameter. /// Each element in the array specifies a single realm mapping. The format /// of each is mapping is: /// </para> /// <code language="none"> /// <realm>$$<extension typeref>$$<args>$$<query> /// </code> /// <para> /// where <b>realm</b> identifies the authentication realm, <b>extension typeref</b> /// specifies the type implementing <see cref="IAuthenticationExtension" /> formatted as /// specified for <see cref="Config.Parse(string,System.Type)" />, <b>key</b> /// are the provider arguments and <b>query</b> is the optional provider query /// string. Note the use of <b>$$</b> as field separators. Here's an example /// configuration: /// </para> /// <code language="none"> /// realm-map[0] = lilltek.com$$LillTek.Datacenter.Server.FileAuthenticationExtension:LillTek.Datacenter.Server.dll$$path=c:\lilltek.txt$$ /// realm-map[1] = test.com$$LillTek.Datacenter..Server.FileAuthenticationExtension:LillTek.Datacenter.Server.dll$$path=c:\test.txt$$ /// </code> /// <note> /// Every call to <see cref="Open" /> should be matched by a call to /// <see cref="Close" /> or <see cref="Dispose" />. /// </note> /// </remarks> /// <exception cref="AuthenticationException">Thrown if there's an error loading the map.</exception> public void Open(AuthenticationEngineSettings engineSettings, string key) { string[] configMap; using (TimedLock.Lock(this)) { if (IsOpen) { throw new AuthenticationException("Provider is already open."); } this.engineSettings = engineSettings; configMap = Config.Global.GetArray(key); if (configMap == null) { throw new AuthenticationException("Configuration key [{0}] not found.", key); } realmMap = new List <RealmMapping>(); foreach (string map in configMap) { string[] fields; string realm; System.Type providerType; string args; string query; fields = map.Split(new string[] { "$$" }, StringSplitOptions.None); if (fields.Length != 4) { throw new AuthenticationException("Four realm map fields expected: [{0}]", map); } realm = fields[0].Trim(); args = fields[2].Trim(); query = fields[3].Trim(); if (realm.Length == 0) { throw new AuthenticationException("<realm> field cannot be empty."); } providerType = Config.Parse(fields[1], (System.Type)null); if (providerType == null) { throw new AuthenticationException("Unable to instantiate provider class: [{0}]", fields[1]); } for (int i = 0; i < realmMap.Count; i++) { if (String.Compare(realmMap[i].Realm, realm, true) == 0) { throw new AuthenticationException("Duplicate realm: {0}", realm); } } realmMap.Add(new RealmMapping(engineSettings, realm, providerType, new ArgCollection(EnvironmentVars.Expand(args)), query)); } } }