diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:49:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:49:46 +0000 |
commit | 50b37d4a27d3295a29afca2286f1a5a086142cec (patch) | |
tree | 9212f763934ee090ef72d823f559f52ce387f268 /raddb/mods-available | |
parent | Initial commit. (diff) | |
download | freeradius-upstream.tar.xz freeradius-upstream.zip |
Adding upstream version 3.2.1+dfsg.upstream/3.2.1+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
72 files changed, 7362 insertions, 0 deletions
diff --git a/raddb/mods-available/README.rst b/raddb/mods-available/README.rst new file mode 100644 index 0000000..79ed5c3 --- /dev/null +++ b/raddb/mods-available/README.rst @@ -0,0 +1,116 @@ +Modules in Version 3 +==================== + +As of Version 3, all of the modules have been placed in the +"mods-available/" directory. This practice follows that used by other +servers such as Nginx, Apache, etc. The "modules" directory should +not be used. + +Modules are enabled by creating a file in the mods-enabled/ directory. +You can also create a soft-link from one directory to another:: + + $ cd raddb/mods-enabled + $ ln -s ../mods-available/foo + +This will enable module "foo". Be sure that you have configured the +module correctly before enabling it, otherwise the server will not +start. You can verify the server configuration by running +"radiusd -XC". + +A large number of modules are enabled by default. This allows the +server to work with the largest number of authentication protocols. +Please be careful when disabling modules. You will likely need to +edit the "sites-enabled/" files to remove references to any disabled +modules. + +Conditional Modules +------------------- + +Version 3 allows modules to be conditionally loaded. This is useful +when you want to have a virtual server which references a module, but +does not require it. Instead of editing the virtual server file, you +can just conditionally enable the module. + +Modules are conditionally enabled by adding a "-" before their name in +a virtual server. For example, you can do:: + + server { + authorize { + ... + ldap + -sql + ... + } + } + +This says "require the LDAP module, but use the SQL module only if it +is configured." + +This feature is not very useful for production configurations. It is, +however, very useful for the default examples that ship with the +server. + +Ignoring module +--------------- + +If you see this message:: + + Ignoring module (see raddb/mods-available/README.rst) + +Then you are in the right place. Most of the time this message can be +ignored. The message can be fixed by finding the references to "-module" +in the virtual server, and deleting them. + +Another way to fix it is to configure the module, as described above. + +Simplification +-------------- + +Allowing conditional modules simplifies the default virtual servers +that are shipped with FreeRADIUS. This means that if you want to +enable LDAP (for example), you no longer need to edit the files in +raddb/sites-available/ in order to enable it. + +Instead, you should edit the raddb/mods-available/ldap file to point +to your local LDAP server. Then, enable the module via the soft-link +method described above. + +Once the module is enabled, it will automatically be used in the +default configuration. + +Multiple Instances +------------------ + +It is sometimes necessary to have the same module do two different +things. The server supports this functionality via "instances" of +modules. + +Normally, a module configuration looks like this: + + sql { + ... sql stuff ... + } + +This module is then refereed to as the "sql" module. + + +But what happens if you want to connect to two different SQL +databases? The solution is simple; copy the "sql" module +configuration, and add an instance name after the "sql" string: + + sql mysql1 { + ... configuration for connecting to mysql11 ... + } + + sql mysql2 { + ... configuration for connecting to mysql12 ... + } + +This configuration says "load the SQL module, but create two copies of +it, with different configurations". The different configurations can +be referred to by name, as "mysql1" and "mysql2". That is, anywhere +you would normally use "sql", you could use either "mysql1" or +"mysql2". + +For further examples of using module instances, see the "attr_filter" +module configuration in this directory. diff --git a/raddb/mods-available/abfab_psk_sql b/raddb/mods-available/abfab_psk_sql new file mode 100644 index 0000000..d75130d --- /dev/null +++ b/raddb/mods-available/abfab_psk_sql @@ -0,0 +1,15 @@ +# -*- text -*- +## +## Module for PSK authorizations from ABFAB trust router +## +## $Id$ + +sql psksql { + + driver = "rlm_sql_sqlite" + + sqlite { + filename = "/var/lib/trust_router/keys" + } + +} diff --git a/raddb/mods-available/always b/raddb/mods-available/always new file mode 100644 index 0000000..b77d00c --- /dev/null +++ b/raddb/mods-available/always @@ -0,0 +1,81 @@ +# -*- text -*- +# +# $Id$ + +# +# The "always" module is here for debugging purposes, or +# for use in complex policies. +# Instance simply returns the same result, always, without +# doing anything. +# +# rcode may be one of the following values: +# - reject - Reject the user. +# - fail - Simulate or indicate a failure. +# - ok - Simulate or indicate a success. +# - handled - Indicate that the request has been handled, +# stop processing, and send response if set. +# - invalid - Indicate that the request is invalid. +# - userlock - Indicate that the user account has been +# locked out. +# - notfound - Indicate that a user account can't be found. +# - noop - Simulate a no-op. +# - updated - Indicate that the request has been updated. +# +# If an instance is listed in a session {} section, +# this simulates a user having <integer> sessions. +# +# simulcount = <integer> +# +# If an instance is listed in a session {} section, +# this simulates the user having multilink +# sessions. +# +# mpp = <integer> +# +# An xlat based on the instance name can be called to change the status +# returned by the instance, in this example "always db_status { ... }" +# +# Force the module status to be alive or dead: +# +# %{db_status:alive} +# %{db_status:dead} +# +# Update the rcode returned by an alive module (a dead module returns fail): +# +# %{db_status:ok} +# %{db_status:fail} +# %{db_status:notfound} +# ... +# +# The above xlats expand to the current status of the module. To fetch the +# current status without affecting it call the xlat with an empty argument: +# +# %{db_status:} +# +always reject { + rcode = reject +} +always fail { + rcode = fail +} +always ok { + rcode = ok +} +always handled { + rcode = handled +} +always invalid { + rcode = invalid +} +always userlock { + rcode = userlock +} +always notfound { + rcode = notfound +} +always noop { + rcode = noop +} +always updated { + rcode = updated +} diff --git a/raddb/mods-available/attr_filter b/raddb/mods-available/attr_filter new file mode 100644 index 0000000..a23d3c0 --- /dev/null +++ b/raddb/mods-available/attr_filter @@ -0,0 +1,61 @@ +# -*- text -*- +# +# $Id$ + +# +# This file defines a number of instances of the "attr_filter" module. +# + +# attr_filter - filters the attributes received in replies from +# proxied servers, to make sure we send back to our RADIUS client +# only allowed attributes. +attr_filter attr_filter.post-proxy { + key = "%{Realm}" + filename = ${modconfdir}/${.:name}/post-proxy +} + +# attr_filter - filters the attributes in the packets we send to +# the RADIUS home servers. +attr_filter attr_filter.pre-proxy { + key = "%{Realm}" + filename = ${modconfdir}/${.:name}/pre-proxy +} + +# Enforce RFC requirements on the contents of Access-Reject +# packets. See the comments at the top of the file for +# more details. +# +attr_filter attr_filter.access_reject { + key = "%{User-Name}" + filename = ${modconfdir}/${.:name}/access_reject +} + +# Enforce RFC requirements on the contents of Access-Challenge +# packets. See the comments at the top of the file for +# more details. +# +attr_filter attr_filter.access_challenge { + key = "%{User-Name}" + filename = ${modconfdir}/${.:name}/access_challenge +} + + +# Enforce RFC requirements on the contents of the +# Accounting-Response packets. See the comments at the +# top of the file for more details. +# +attr_filter attr_filter.accounting_response { + key = "%{User-Name}" + filename = ${modconfdir}/${.:name}/accounting_response +} + +# +# Enforce CoA or Disconnect packets. +# +# Note that you MUST edit the "coa" file below for your +# local configuration. Add in any attributes needed by the NAS. +# +attr_filter attr_filter.coa { + key = "%{User-Name}" + filename = ${modconfdir}/${.:name}/coa +} diff --git a/raddb/mods-available/cache b/raddb/mods-available/cache new file mode 100644 index 0000000..cf0054f --- /dev/null +++ b/raddb/mods-available/cache @@ -0,0 +1,150 @@ +# -*- text -*- +# +# $Id$ + +# +# A module to cache attributes. The idea is that you can look +# up information in a database, and then cache it. Repeated +# requests for the same information will then have the cached +# values added to the request. +# +# The module can cache a fixed set of attributes per key. +# It can be listed in "authorize", "post-auth", "pre-proxy" +# and "post-proxy". +# +# If you want different things cached for authorize and post-auth, +# you will need to define two instances of the "cache" module. +# +# The module returns "ok" if it found or created a cache entry. +# The module returns "updated" if it merged a cached entry. +# The module returns "noop" if it did nothing. +# The module returns "fail" on error. +# +cache { + # The backend datastore used to store the cache entries. + # Current datastores are + # rlm_cache_rbtree - An in memory, non persistent rbtree based datastore. + # Useful for caching data locally. + # rlm_cache_memcached - A non persistent "webscale" distributed datastore. + # Useful if the cached data need to be shared between + # a cluster of RADIUS servers. + # rlm_cache_redis - uses Redis. +# driver = "rlm_cache_rbtree" + + # + # Some drivers accept specific options, to set them a + # config section with the the name as the driver should be added + # to the cache instance. + # + # Driver specific options are: + # +# memcached { +# # Memcached configuration options, as documented here: +# # http://docs.libmemcached.org/libmemcached_configuration.html#memcached +# options = "--SERVER=localhost" +# +# pool { +# start = ${thread[pool].start_servers} +# min = ${thread[pool].min_spare_servers} +# max = ${thread[pool].max_servers} +# spare = ${thread[pool].max_spare_servers} +# uses = 0 +# lifetime = 0 +# idle_timeout = 60 +# } +# } + + # + # See mods-available/redis for documentation on the following + # configuration items. They are identical here. + # + # Note that the "pool" section can re-use the normal Redis + # connections. This is done by setting the "pool" configuration + # item to the name of the Redis module. The other configuration + # items should then be the same as for the original "redis" module. + # +# redis { +# server = ... +# port = +# database = +# query_timeout = ... +# pool = redis +# } + + # The key used to index the cache. It is dynamically expanded + # at run time. + key = "%{User-Name}" + + # The TTL of cache entries, in seconds. Entries older than this + # will be expired. + # + # This value should be between 10 and 86400. + ttl = 10 + + # If yes the following attributes will be added to the request: + # * &request:Cache-Entry-Hits - The number of times this entry + # has been retrieved. + # + # Note: Not supported by the rlm_cache_memcached module. + add_stats = no + + # + # The list of attributes to cache for a particular key. + # + # Each key gets the same set of cached attributes. The attributes + # are dynamically expanded at run time. + # + # The semantics of this construct are identical to an unlang + # update block, except the left hand side of the expression + # represents the cache entry. see man unlang for more information + # on update blocks. + # + # Note: Only request, reply, control and session-state lists + # are available in cache entries. Attempting to store attributes + # in other lists will raise an error during config validation. + # + update { + # <list>:<attribute> <op> <value> + + # Cache all instances of Reply-Message in the reply list + &reply:Reply-Message += &reply:Reply-Message[*] + + # Add our own to show when the cache was last updated + &reply:Reply-Message += "Cache last updated at %t" + + &reply:Class := "%{randstr:ssssssssssssssssssssssssssssssss}" + } + + # This module supports a number of runtime configuration parameters + # represented by attributes in the &control: list. + # + # &control:Cache-TTL - Sets the TTL of an entry to be created, or + # modifies the TTL of an existing entry. + # - Setting a Cache-TTL of > 0 means set the TTL of the entry to + # the new value (and reset the expiry timer). + # - Setting a Cache-TTL of < 0 means expire the existing entry + # (without merging) and create a new one with TTL set to + # value * -1. + # - Setting a Cache-TTL of 0 means expire the existing entry + # (without merging) and don't create a new one. + # + # &control:Cache-Status-Only - If present and set to 'yes' will + # prevent a new entry from being created, and existing entries from + # being merged. It will also alter the module's return codes. + # - The module will return "ok" if a cache entry was found. + # - The module will return "notfound" if no cache entry was found. + # + # &control:Cache-Read-Only - If present and set to 'yes' will + # prevent a new entry from being created, but will allow existing + # entries to be merged. It will also alter the module's return codes. + # - The module will return "updated" if a cache entry was found. + # - The module will return "notfound" if no cache was found. + # + # &control:Cache-Merge - If present and set to 'yes' will merge new + # cache entries into the current request. Useful if results + # of execs or expansions are stored directly in the cache. + # + # All runtime configuration attributes will be removed from the + # &control: list after the cache module is called. + +} diff --git a/raddb/mods-available/cache_auth b/raddb/mods-available/cache_auth new file mode 100644 index 0000000..7485f36 --- /dev/null +++ b/raddb/mods-available/cache_auth @@ -0,0 +1,116 @@ +# -*- text -*- +# +# $Id$ + +# This file contains a collection of cache module configurations +# which have been designed to be used to cache accepts, rejects, and +# LDAP User DNs. The main use of these modules is Google Secure +# LDAP. +# +# In scenarios where there is repeated authentication requests for the same +# user within a short time frame (e.g. 802.1x wifi), these modules can help to +# compensate for slow responses from poor LDAP servers (i.e. Google). +# +# See also mods-available/ldap_google, and sites-available/google-ldap-auth. +# +# The configurations in this file can be used for non-Google LDAP +# servers, too. +# + + +# +# This instance of the cache module caches successful +# authentications. +# +# The TTL controls how often the authentication will be cached. +# +# In addition, if group membership is used as part of the policy, the +# &control:LDAP-Group attribute should be added to the "update: section here. +# +# If a user's authentication is found in the cache, then any data +# which is normally retrieved from LDAP for local policies must also +# be stored in the cache via the "update" section. +# +cache cache_auth_accept { + driver = "rlm_cache_rbtree" + key = "%{md5:%{%{Stripped-User-Name}:-%{User-Name}}%{User-Password}}" + ttl = 7200 + update { + # + # We need to cache something, so we just cache + # a random attribute. This attribute is not used + # for anything else, just as a "place-holder" to + # contain a cache entry. + # + # If you add other attributes to this update section, then + # this attribute can be deleted. + # + &control:User-Category = "success" + } +} + + +# +# This instance of the cache module caches failed authentications. +# +# In many cases, rejected users will repeatedly try to authenticate. +# These repeated authentication attempts can cause significant load +# on the system. By caching the reject, we can avoid hitting the database. +# +# We index the cache by a hash of the client's MAC and the user name +# and password. If a user corrects their user name or password, then +# that authentication attempt won't hit the cache, and their +# credentials will be immediately checked against the database. +# +# The TTL controls how long a combination of device / user and +# password wil be rejected without looking at the database. Once the +# cache entry expires, the server will delete the cache entry, and +# contact the database. +# +cache cache_auth_reject { + driver = "rlm_cache_rbtree" + key = "%{md5:%{Calling-Station-Id}%{Stripped-User-Name}%{User-Password}}" + ttl = 3600 + update { + # + # We need to cache something, so we just cache + # a random attribute. This attribute is not used + # for anything else, just as a "place-holder" to + # contain a cache entry. + # + &control:User-Category = "failure" + } +} + + +# +# An instance of the cache module which caches the LDAP user DN. +# +# If LDAP authentication is being used for a simple auth / reject without +# any need to retrieve other attributes (e.g. group membership), each LDAP +# bind authentication is three steps +# +# - bind as admin user +# - lookup user's DN +# - bind as user using retrieved DN +# +# By caching the DN after the first LDAP querry, the first two steps +# are skipped on subsequent authentications. +# +# If an alternative attribute name is being used for the user DN, you +# should change the update section here appropriately. But that is +# likely rare. +# +# In scenarios where DNs may change, consideration should be given as +# to whether use of this cache may create issues. i.e. if the cache +# doesn't help, then don't use it. +# +cache cache_ldap_user_dn { + driver = "rlm_cache_rbtree" + key = "%{Stripped-User-Name}" + ttl = 86400 + update { + &control:LDAP-UserDN = &control:LDAP-UserDN + } +} + diff --git a/raddb/mods-available/chap b/raddb/mods-available/chap new file mode 100644 index 0000000..e2a3cd3 --- /dev/null +++ b/raddb/mods-available/chap @@ -0,0 +1,11 @@ +# -*- text -*- +# +# $Id$ + +# CHAP module +# +# To authenticate requests containing a CHAP-Password attribute. +# +chap { + # no configuration +} diff --git a/raddb/mods-available/couchbase b/raddb/mods-available/couchbase new file mode 100644 index 0000000..da1a39d --- /dev/null +++ b/raddb/mods-available/couchbase @@ -0,0 +1,204 @@ +couchbase { + # + # List of Couchbase hosts (hosts may be space, tab, comma or semi-colon separated). + # Ports are optional if servers are listening on the standard port. + # Complete pool urls are preferred. + # + server = "http://cb01.blargs.com:8091/pools/ http://cb04.blargs.com:8091/pools/" + + # Couchbase bucket name + bucket = "radius" + + # Couchbase bucket password (optional) + #password = "password" + + # Couchbase accounting document key (unlang supported) + acct_key = "radacct_%{%{Acct-Unique-Session-Id}:-%{Acct-Session-Id}}" + + # Value for the 'docType' element in the json body for accounting documents + doctype = "radacct" + + ## Accounting document expire time in seconds (0 = never) + expire = 2592000 + + # + # Map attribute names to json element names for accounting. + # + # Configuration items are in the format: + # <radius attribute> = '<element name>' + # + # Element names should be single quoted. + # + # Note: Attributes not in this map will not be recorded. + # + update { + Acct-Session-Id = 'sessionId' + Acct-Unique-Session-Id = 'uniqueId' + Acct-Status-Type = 'lastStatus' + Acct-Authentic = 'authentic' + User-Name = 'userName' + Stripped-User-Name = 'strippedUserName' + Stripped-User-Domain = 'strippedUserDomain' + Realm = 'realm' + NAS-IP-Address = 'nasIpAddress' + NAS-Identifier = 'nasIdentifier' + NAS-Port = 'nasPort' + Called-Station-Id = 'calledStationId' + Called-Station-SSID = 'calledStationSSID' + Calling-Station-Id = 'callingStationId' + Framed-Protocol = 'framedProtocol' + Framed-IP-Address = 'framedIpAddress' + NAS-Port-Type = 'nasPortType' + Connect-Info = 'connectInfo' + Acct-Session-Time = 'sessionTime' + Acct-Input-Packets = 'inputPackets' + Acct-Output-Packets = 'outputPackets' + Acct-Input-Octets = 'inputOctets' + Acct-Output-Octets = 'outputOctets' + Acct-Input-Gigawords = 'inputGigawords' + Acct-Output-Gigawords = 'outputGigawords' + Event-Timestamp = 'lastUpdated' + } + + # Couchbase document key for user documents (unlang supported) + user_key = "raduser_%{md5:%{tolower:%{%{Stripped-User-Name}:-%{User-Name}}}}" + + # Set to 'yes' to read radius clients from the Couchbase view specified below. + # NOTE: Clients will ONLY be read on server startup. + #read_clients = no + + # + # Map attribute names to json element names when loading clients. + # + # Configuration follows the same rules as the accounting map above. + # + client { + # Couchbase view that should return all available client documents. + view = "_design/client/_view/by_id" + + # + # Sets default values (not obtained from couchbase) for new client entries + # + template { +# login = 'test' +# password = 'test' +# proto = tcp +# require_message_authenticator = yes + + # Uncomment to add a home_server with the same + # attributes as the client. +# coa_server { +# response_window = 2.0 +# } + } + + # + # Client mappings are in the format: + # <client attribute> = '<element name>' + # + # Element names should be single quoted. + # + # The following attributes are required: + # * ipaddr | ipv4addr | ipv6addr - Client IP Address. + # * secret - RADIUS shared secret. + # + # All attributes usually supported in a client + # definition are also supported here. + # + attribute { + ipaddr = 'clientIdentifier' + secret = 'clientSecret' + shortname = 'clientShortname' + nas_type = 'nasType' + virtual_server = 'virtualServer' + require_message_authenticator = 'requireMessageAuthenticator' + limit { + max_connections = 'maxConnections' + lifetime = 'clientLifetime' + idle_timeout = 'idleTimeout' + } + } + } + + # Set to 'yes' to enable simultaneous use checking (multiple logins). + # NOTE: This will cause the execution of a view request on every check + # and may be a performance penalty. +# check_simul = no + + # Couchbase view that should return all account documents keyed by username. +# simul_view = "_design/acct/_view/by_user" + + # The key to the above view. + # NOTE: This will need to match EXACTLY what you emit from your view. +# simul_vkey = "%{tolower:%{%{Stripped-User-Name}:-%{User-Name}}}" + + # Set to 'yes' to enable verification of the results returned from the above view. + # NOTE: This may be an additional performance penalty to the actual check and + # should be avoided unless absolutely neccessary. +# verify_simul = no + + # Remove stale session if checkrad does not see a double login. + # NOTE: This will only be executed if both check_simul and verify_simul + # are set to 'yes' above. +# delete_stale_sessions = yes + + # + # The connection pool is used to pool outgoing connections. + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # couchbase being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The lifetime (in seconds) of the connection + # + # NOTE: A setting of 0 means infinite (no limit). + lifetime = 0 + + # The idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + # + # NOTE: A setting of 0 means infinite (no timeout). + idle_timeout = 1200 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/raddb/mods-available/counter b/raddb/mods-available/counter new file mode 100644 index 0000000..a5ac1e6 --- /dev/null +++ b/raddb/mods-available/counter @@ -0,0 +1,82 @@ +# -*- text -*- +# +# $Id$ + +# counter module: +# This module takes an attribute (count-attribute). +# It also takes a key, and creates a counter for each unique +# key. The count is incremented when accounting packets are +# received by the server. The value of the increment depends +# on the attribute type. +# If the attribute is Acct-Session-Time or of an integer type we add +# the value of the attribute. If it is anything else we increase the +# counter by one. +# +# The 'reset' parameter defines when the counters are all reset to +# zero. It can be hourly, daily, weekly, monthly or never. +# +# hourly: Reset on 00:00 of every hour +# daily: Reset on 00:00:00 every day +# weekly: Reset on 00:00:00 on sunday +# monthly: Reset on 00:00:00 of the first day of each month +# +# It can also be user defined. It should be of the form: +# num[hdwm] where: +# h: hours, d: days, w: weeks, m: months +# If the letter is omitted days will be assumed. In example: +# reset = 10h (reset every 10 hours) +# reset = 12 (reset every 12 days) +# +# +# The check_name attribute defines an attribute which will be +# registered by the counter module and can be used to set the +# maximum allowed value for the counter after which the user +# is rejected. +# Something like: +# +# DEFAULT Max-Daily-Session := 36000 +# Fall-Through = 1 +# +# You should add the counter module in the instantiate +# section so that it registers check_name before the files +# module reads the users file. +# +# If check_name is set and the user is to be rejected then we +# send back a Reply-Message and we log a Failure-Message in +# the radius.log +# +# If the count attribute is Acct-Session-Time then on each +# login we send back the remaining online time as a +# Session-Timeout attribute ELSE and if the reply_name is +# set, we send back that attribute. The reply_name attribute +# MUST be of an integer type. +# +# The counter-name can also be used instead of using the check_name +# like below: +# +# DEFAULT Daily-Session-Time > 3600, Auth-Type = Reject +# Reply-Message = "You've used up more than one hour today" +# +# The allowed_service_type attribute can be used to only take +# into account specific sessions. For example if a user first +# logs in through a login menu and then selects ppp there will +# be two sessions. One for Login-User and one for Framed-User +# service type. We only need to take into account the second one. +# +# The module should be added in the instantiate, authorize and +# accounting sections. Make sure that in the authorize +# section it comes after any module which sets the +# 'check_name' attribute. +# +counter daily { + filename = ${db_dir}/db.daily + key = User-Name + count_attribute = Acct-Session-Time + reset = daily + counter_name = Daily-Session-Time + check_name = Max-Daily-Session + reply_name = Session-Timeout + allowed_service_type = Framed-User + cache_size = 5000 +} + diff --git a/raddb/mods-available/cui b/raddb/mods-available/cui new file mode 100644 index 0000000..54842d4 --- /dev/null +++ b/raddb/mods-available/cui @@ -0,0 +1,53 @@ +# -*- text -*- +# +# $Id$ + +# +# Write Chargeable-User-Identity to the database. +# +# Schema raddb/mods-config/sql/cui/<DB>/schema.sql +# Queries raddb/mods-config/sql/cui/<DB>/queries.conf +# +sql cuisql { + + # The dialect of SQL you want to use, this should usually match + # the driver below. + # + # If you're using rlm_sql_null, then it should be the type of + # database the logged queries are going to be executed against. + dialect = "sqlite" + + # The sub-module to use to execute queries. This should match + # the database you're attempting to connect to. + # + # There are CUI queries available for: + # * rlm_sql_mysql + # * rlm_sql_postgresql + # * rlm_sql_sqlite + # * rlm_sql_null (log queries to disk) + # + driver = "rlm_sql_${dialect}" + + sqlite { + filename = ${radacctdir}/cui.sqlite + bootstrap = ${modconfdir}/${..:name}/cui/sqlite/schema.sql + } + + # Write CUI queries to a logfile. Useful for debugging. +# logfile = ${logdir}/cuilog.sql + + pool { + start = 5 + min = 4 + max = 10 + spare = 3 + uses = 0 + lifetime = 0 + idle_timeout = 60 + } + + cui_table = "cui" + sql_user_name = "%{User-Name}" + + $INCLUDE ${modconfdir}/${.:name}/cui/${dialect}/queries.conf +} diff --git a/raddb/mods-available/date b/raddb/mods-available/date new file mode 100644 index 0000000..25a64da --- /dev/null +++ b/raddb/mods-available/date @@ -0,0 +1,35 @@ +# +# Registers xlat to convert between time formats. +# +# xlat input string is an attribute name. If this attribute is of date +# or integer type, the date xlat will convert it to a time string in +# the format of the format config item. +# +# If the attribute is a string type, date will attempt to parse it in +# the format specified by the format config item, and will expand +# to a Unix timestamp. +# +date { + format = "%b %e %Y %H:%M:%S %Z" + + # Use UTC instead of local time. + # + # default = no +# utc = yes +} + +# +# The WISPr-Session-Terminate-Time attribute is of type "string", +# and not "date". Use this expansion to create an attribute +# that holds an actual date: +# +# Tmp-Date-0 := "%{wispr2date:&reply:WISPr-Session-Terminate-Time}" +# +date wispr2date { + format = "%Y-%m-%dT%H:%M:%S" + + # Use UTC instead of local time. + # + # default = no +# utc = yes +} diff --git a/raddb/mods-available/detail b/raddb/mods-available/detail new file mode 100644 index 0000000..ccf65f9 --- /dev/null +++ b/raddb/mods-available/detail @@ -0,0 +1,109 @@ +# -*- text -*- +# +# $Id$ + +# Write a detailed log of all accounting records received. +# +detail { + # Note that we do NOT use NAS-IP-Address here, as + # that attribute MAY BE from the originating NAS, and + # NOT from the proxy which actually sent us the + # request. + # + # The following line creates a new detail file for + # every radius client (by IP address or hostname). + # In addition, a new detail file is created every + # day, so that the detail file doesn't have to go + # through a 'log rotation' + # + # If your detail files are large, you may also want to add + # a ':%H' (see doc/configuration/variables.rst) to the end + # of it, to create a new detail file every hour, e.g.: + # + # ..../detail-%Y%m%d:%H + # + # This will create a new detail file for every hour. + # + # If you are reading detail files via the "listen" section + # (e.g. as in raddb/sites-available/robust-proxy-accounting), + # you MUST use a unique directory for each combination of a + # detail file writer, and reader. That is, there can only + # be ONE "listen" section reading detail files from a + # particular directory. + # + # The configuration below puts the detail files into separate + # directories for each client. If you are reading the detail + # files via the "listen" section, just use one directory. + # + # e.g. filename = ${radacctdir}/reader1/detail-%Y%m%d + # + # AND use a separate directory (reader2, reader3, etc.) for each + # reader. + # + filename = ${radacctdir}/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d + + # + # If you are using radrelay, delete the above line for "file", + # and use this one instead: + # +# filename = ${radacctdir}/detail + + # + # Most file systems can handly nearly the full range of UTF-8 + # characters. Ones that can deal with a limited range should + # set this to "yes". + # + escape_filenames = no + + # + # The Unix-style permissions on the 'detail' file. + # + # The detail file often contains secret or private + # information about users. So by keeping the file + # permissions restrictive, we can prevent unwanted + # people from seeing that information. + permissions = 0600 + + # The Unix group of the log file. + # + # The user that the server runs as must be in the specified + # system group otherwise this will fail to work. + # +# group = ${security.group} + + # + # Every entry in the detail file has a header which + # is a timestamp. By default, we use the ctime + # format (see "man ctime" for details). + # + # The header can be customised by editing this + # string. See "doc/configuration/variables.rst" for a + # description of what can be put here. + # + header = "%t" + + # + # Uncomment this line if the detail file reader will be + # reading this detail file. + # +# locking = yes + + # + # Log the Packet src/dst IP/port. This is disabled by + # default, as that information isn't used by many people. + # +# log_packet_header = yes + + # + # Certain attributes such as User-Password may be + # "sensitive", so they should not be printed in the + # detail file. This section lists the attributes + # that should be suppressed. + # + # The attributes should be listed one to a line. + # + #suppress { + # User-Password + #} + +} diff --git a/raddb/mods-available/detail.example.com b/raddb/mods-available/detail.example.com new file mode 100644 index 0000000..827cdf5 --- /dev/null +++ b/raddb/mods-available/detail.example.com @@ -0,0 +1,27 @@ +# -*- text -*- +# +# Detail file writer, used in the following examples: +# +# raddb/sites-available/robust-proxy-accounting +# raddb/sites-available/decoupled-accounting +# +# Note that this module can write detail files that are read by +# only ONE "listen" section. If you use BOTH of the examples +# above, you will need to define TWO "detail" modules. +# +# e.g. detail1.example.com && detail2.example.com +# +# +# We write *multiple* detail files here. They will be processed by +# the detail "listen" section in the order that they were created. +# The directory containing these files should NOT be used for any +# other purposes. i.e. It should have NO other files in it. +# +# Writing multiple detail enables the server to process the pieces +# in smaller chunks. This helps in certain catastrophic corner cases. +# +# $Id$ +# +detail detail.example.com { + filename = ${radacctdir}/detail.example.com/detail-%Y%m%d:%H:%G +} diff --git a/raddb/mods-available/detail.log b/raddb/mods-available/detail.log new file mode 100644 index 0000000..b91cf7c --- /dev/null +++ b/raddb/mods-available/detail.log @@ -0,0 +1,75 @@ +# -*- text -*- +# +# $Id$ + +# +# More examples of doing detail logs. + +# +# Many people want to log authentication requests. +# Rather than modifying the server core to print out more +# messages, we can use a different instance of the 'detail' +# module, to log the authentication requests to a file. +# +# You will also need to un-comment the 'auth_log' line +# in the 'authorize' section, below. +# +detail auth_log { + filename = ${radacctdir}/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/auth-detail-%Y%m%d + + # + # This MUST be 0600, otherwise anyone can read + # the users passwords! + permissions = 0600 + + # You may also strip out passwords completely + suppress { + User-Password + } +} + +# +# This module logs authentication reply packets sent +# to a NAS. Both Access-Accept and Access-Reject packets +# are logged. +# +# You will also need to un-comment the 'reply_log' line +# in the 'post-auth' section, below. +# +detail reply_log { + filename = ${radacctdir}/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/reply-detail-%Y%m%d + + permissions = 0600 +} + +# +# This module logs packets proxied to a home server. +# +# You will also need to un-comment the 'pre_proxy_log' line +# in the 'pre-proxy' section, below. +# +detail pre_proxy_log { + filename = ${radacctdir}/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/pre-proxy-detail-%Y%m%d + + # + # This MUST be 0600, otherwise anyone can read + # the users passwords! + permissions = 0600 + + # You may also strip out passwords completely + #suppress { + # User-Password + #} +} + +# +# This module logs response packets from a home server. +# +# You will also need to un-comment the 'post_proxy_log' line +# in the 'post-proxy' section, below. +# +detail post_proxy_log { + filename = ${radacctdir}/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/post-proxy-detail-%Y%m%d + + permissions = 0600 +} diff --git a/raddb/mods-available/dhcp b/raddb/mods-available/dhcp new file mode 100644 index 0000000..a431633 --- /dev/null +++ b/raddb/mods-available/dhcp @@ -0,0 +1,19 @@ +# -*- text -*- +# +# $Id$ + +# +# This module is useful only for 'xlat'. To use it, +# put 'dhcp' into the 'instantiate' section. +# +# %{dhcp_options:<Attribute-ref>} may be used to decode +# DHCP options data included in RADIUS packets by vendors +# of DHCP to RADIUS gateways. +# +# This is known to work with the following VSAs: +# * Juniper - ERX-Dhcp-Options +# * Alcatel lucent SR - Alc-ToServer-Dhcp-Options +# - Alc-ToClient-Dhcp-Options +# +dhcp { +} diff --git a/raddb/mods-available/dhcp_files b/raddb/mods-available/dhcp_files new file mode 100644 index 0000000..243a241 --- /dev/null +++ b/raddb/mods-available/dhcp_files @@ -0,0 +1,56 @@ +# -*- text -*- +# +# $Id$ + +# Instances of the "files" module for managing DHCP options +# +files dhcp_network { + # The file containing network-specific DHCP options mapping + filename = ${modconfdir}/files/dhcp + + # For network lookups we use a fixed key. Matching + # actual networks is done by additional filtering within + # the file + key = "network" +} + +files dhcp_subnet { + # The file containing subnet-specific DHCP options mapping + filename = ${modconfdir}/files/dhcp + + # For subnet lookups we use a fixed key. Matching + # actual subnets is done by additional filtering within + # the file + key = "subnet" +} + +files dhcp_set_group_options { + # An example of looking up DHCP group options. This + # is designed to be called from a policy configured in + # policy.d/dhcp. + # + # If clients are never members of more than one group, + # then this could be simplified such that DHCP-Group-Name + # is used here in place of Foreach-Variable-0 and this + # module instance called directly rather than the policy + + # Use the same file as for subnets - could be split + # for large, complex installations + filename = ${modconfdir}/files/dhcp + + # The key is a temporary string populated by the calling policy + # which uses a foreach loop. + key = "%{Foreach-Variable-0}" +} + +files dhcp_hosts { + # An example of a DHCP host mapping for option setting + + # Use the same file as for subnets - could be split + # for large, complex installations + filename = ${modconfdir}/files/dhcp + + # If a different identifier is needed for looking up + # host specific entries then amend this key. + key = "host-%{DHCP-Client-Hardware-Address}" +} diff --git a/raddb/mods-available/dhcp_passwd b/raddb/mods-available/dhcp_passwd new file mode 100644 index 0000000..7884a00 --- /dev/null +++ b/raddb/mods-available/dhcp_passwd @@ -0,0 +1,20 @@ +# -*- text -*- +# +# $Id$ + +# An instance of the passwd module designed for looking up +# DHCP client membership. This example is based on hardware +# address. +# The "groups" file should be of the format: +# <group name>|<hardware address>,<hardware address>,<hardware address> +# <group name>|<hardware address>,<hardware address>,<hardware address> +# +# See the passwd module for more details. + +passwd dhcp_group_membership { + filename = "${modconfdir}/files/dhcp_groups" + format = "~DHCP-Group-Name:*,DHCP-Client-Hardware-Address" + hash_size = 100 + allow_multiple_keys = yes + delimiter = "|" +} diff --git a/raddb/mods-available/dhcp_sql b/raddb/mods-available/dhcp_sql new file mode 100644 index 0000000..20dbe3a --- /dev/null +++ b/raddb/mods-available/dhcp_sql @@ -0,0 +1,92 @@ +# -*- text -*- +## +## mods-available/sql -- SQL modules +## +## $Id$ + +###################################################################### +# +# Configuration for the DHCP-specific instance of the SQL module +# +# The database schemas and queries are located in subdirectories: +# +# sql/dhcp/<DB>/schema.sql Schema +# sql/dhcp/<DB>/queries.conf Reply options lookup queries +# +# Where "DB" is mysql, mssql, oracle, or postgresql. +# + +# +# See raddb/mods-available/sql for a description of the configuration items +# for the sql module. +# +sql dhcp_sql { + dialect = "sqlite" + driver = "rlm_sql_null" +# driver = "rlm_sql_${dialect}" + + sqlite { + filename = "/tmp/freeradius.db" + busy_timeout = 200 + bootstrap = "${modconfdir}/${..:name}/dhcp/sqlite/schema.sql" + } + + mysql { + tls { + ca_file = "/etc/ssl/certs/my_ca.crt" + ca_path = "/etc/ssl/certs/" + certificate_file = "/etc/ssl/certs/private/client.crt" + private_key_file = "/etc/ssl/certs/private/client.key" + cipher = "DHE-RSA-AES256-SHA:AES128-SHA" + + tls_required = yes + tls_check_cert = no + tls_check_cert_cn = no + } + warnings = auto + } + + postgresql { + send_application_name = yes + } + + mongo { + appname = "freeradius" + tls { + certificate_file = /path/to/file + certificate_password = "password" + ca_file = /path/to/file + ca_dir = /path/to/directory + crl_file = /path/to/file + weak_cert_validation = false + allow_invalid_hostname = false + } + } + +# server = "localhost" +# port = 3306 +# login = "radius" +# password = "radpass" + + radius_db = "radius" + + dhcpreply_table = "dhcpreply" + groupreply_table = "dhcpgroupreply" + dhcpgroup_table = "dhcpgroup" + read_groups = no + + pool { + start = ${thread[pool].start_servers} + min = ${thread[pool].min_spare_servers} + max = ${thread[pool].max_servers} + spare = ${thread[pool].max_spare_servers} + uses = 0 + retry_delay = 30 + lifetime = 0 + idle_timeout = 60 + } + + group_attribute = "${.:instance}-SQL-Group" + + $INCLUDE ${modconfdir}/${.:name}/dhcp/${dialect}/queries.conf +} diff --git a/raddb/mods-available/dhcp_sqlippool b/raddb/mods-available/dhcp_sqlippool new file mode 100644 index 0000000..909b93c --- /dev/null +++ b/raddb/mods-available/dhcp_sqlippool @@ -0,0 +1,101 @@ +# Configuration for DHCP for the SQL based IP Pools module (rlm_sqlippool). +# +# See raddb/mods-available/sqlippool for common configuration explanation +# +# See raddb/policy.d/dhcp_sqlippool for the "glue" code that allows +# the RADIUS based "sqlippool" module to be used for DHCP. +# +# See raddb/sites-available/dhcp for instructions on how to configure +# the DHCP server. +# +# The database schemas are available at: +# +# raddb/mods-config/sql/ippool-dhcp/<DB>/schema.sql +# +# $Id$ + +sqlippool dhcp_sqlippool { + # SQL instance to use (from mods-available/sql) + # + # If you have multiple sql instances, such as "sql sql1 {...}", + # use the *instance* name here: sql1. + sql_module_instance = "dhcp_sql" + + # This is duplicative of info available in the SQL module, but + # we have to list it here as we do not yet support nested + # reference expansions. + dialect = "mysql" + + # Name of the check item attribute to be used as a key in the SQL queries + pool_name = "Pool-Name" + + # SQL table to use for ippool range and lease info + ippool_table = "dhcpippool" + + # The duration for which a lease is reserved whilst under offer + offer_duration = 10 + + # IP lease duration. (Leases expire even if no DHCP-Release packet is received) + # Either use the value to be sent to the client or a hard coded one. + lease_duration = "%{reply:DHCP-IP-Address-Lease-Time}" + #lease_duration = 7200 + + # The attribute in which the IP address is returned in the reply + attribute_name = "DHCP-Your-IP-Address" + + # Assign the IP address, even if the above attribute already exists in + # the reply. + # +# allow_duplicates = no + + # The attribute in which an IP address hint may be supplied + req_attribute_name = "DHCP-Requested-IP-Address" + + # + # RFC 2132 allows the DHCP client to supply a unique + # identifier ("uid") using Option 61 (DHCP-Client-Identifier) + # in which case it must be used as the lookup key for + # configuration data. + # + pool_key = "%{%{DHCP-Client-Identifier}:-%{DHCP-Client-Hardware-Address}}" + # + # The "uid" is generated by the OS which means that clients + # whose BMC piggybacks on the main interface (sharing its MAC, + # but generating a distinct uid) and dual-booting clients can + # be allocated multiple IPs, consuming more pool entries. To + # avoid this you can ignore the RFCs and key the configuration + # data based only on the client MAC address. + # + # pool_key = "%{DHCP-Client-Hardware-Address}" + + ################################################################ + # + # WARNING: MySQL (MyISAM) has certain limitations that means it can + # hand out the same IP address to 2 different users. + # + # We suggest using an SQL DB with proper transaction + # support, such as PostgreSQL, or using MySQL + # with InnoDB. + # + ################################################################ + + # These messages are added to the "control" items, as + # Module-Success-Message. They are not logged anywhere else, + # unlike previous versions. If you want to have them logged + # to a file, see the "linelog" module, and create an entry + # which writes Module-Success-Message message. + # + messages { + exists = "DHCP: Existing IP: %{reply:${..attribute_name}} (cid %{DHCP-Client-Identifier} chaddr %{DHCP-Client-Hardware-Address} giaddr %{DHCP-Gateway-IP-Address})" + + success = "DHCP: Allocated IP: %{reply:${..attribute_name}} from %{control:${..pool_name}} (cid %{DHCP-Client-Identifier} chaddr %{DHCP-Client-Hardware-Address} giaddr %{DHCP-Gateway-IP-Address})" + + clear = "DHCP: Released IP %{DHCP-Client-IP-Address} (cid %{DHCP-Client-Identifier} chaddr %{DHCP-Client-Hardware-Address} giaddr %{DHCP-Gateway-IP-Address})" + + failed = "DHCP: IP Allocation FAILED from %{control:${..pool_name}} (cid %{DHCP-Client-Identifier} chaddr %{DHCP-Client-Hardware-Address} giaddr %{DHCP-Gateway-IP-Address})" + + nopool = "DHCP: No ${..pool_name} defined (cid %{DHCP-Client-Identifier} chaddr %{DHCP-Client-Hardware-Address} giaddr %{DHCP-Gateway-IP-Address})" + } + + $INCLUDE ${modconfdir}/sql/ippool-dhcp/${dialect}/queries.conf +} diff --git a/raddb/mods-available/digest b/raddb/mods-available/digest new file mode 100644 index 0000000..f0aa9ed --- /dev/null +++ b/raddb/mods-available/digest @@ -0,0 +1,13 @@ +# -*- text -*- +# +# $Id$ + +# +# The 'digest' module currently has no configuration. +# +# "Digest" authentication against a Cisco SIP server. +# See 'doc/rfc/draft-sterman-aaa-sip-00.txt' for details +# on performing digest authentication for Cisco SIP servers. +# +digest { +} diff --git a/raddb/mods-available/dynamic_clients b/raddb/mods-available/dynamic_clients new file mode 100644 index 0000000..cc2bd5f --- /dev/null +++ b/raddb/mods-available/dynamic_clients @@ -0,0 +1,32 @@ +# -*- text -*- +# +# $Id$ + +# This module loads RADIUS clients as needed, rather than when the server +# starts. +# +# There are no configuration entries for this module. Instead, it +# relies on the "client" configuration. You must: +# +# 1) link raddb/sites-enabled/dynamic_clients to +# raddb/sites-available/dynamic_clients +# +# 2) Define a client network/mask (see top of the above file) +# +# 3) uncomment the "directory" entry in that client definition +# +# 4) list "dynamic_clients" in the "authorize" section of the +# "dynamic_clients' virtual server. The default example already +# does this. +# +# 5) put files into the above directory, one per IP. +# e.g. file "192.0.2.1" should contain a normal client definition +# for a client with IP address 192.0.2.1. +# +# For more documentation, see the file: +# +# raddb/sites-available/dynamic-clients +# +dynamic_clients { + +} diff --git a/raddb/mods-available/eap b/raddb/mods-available/eap new file mode 100644 index 0000000..8fd8eb5 --- /dev/null +++ b/raddb/mods-available/eap @@ -0,0 +1,1112 @@ +# -*- text -*- +## +## eap.conf -- Configuration for EAP types (PEAP, TTLS, etc.) +## +## $Id$ + +####################################################################### +# +# Whatever you do, do NOT set 'Auth-Type := EAP'. The server +# is smart enough to figure this out on its own. The most +# common side effect of setting 'Auth-Type := EAP' is that the +# users then cannot use ANY other authentication method. +# +eap { + # Invoke the default supported EAP type when + # EAP-Identity response is received. + # + # The incoming EAP messages DO NOT specify which EAP + # type they will be using, so it MUST be set here. + # + # For now, only one default EAP type may be used at a time. + # + # If the EAP-Type attribute is set by another module, + # then that EAP type takes precedence over the + # default type configured here. + # + default_eap_type = md5 + + # A list is maintained to correlate EAP-Response + # packets with EAP-Request packets. After a + # configurable length of time, entries in the list + # expire, and are deleted. + # + timer_expire = 60 + + # There are many EAP types, but the server has support + # for only a limited subset. If the server receives + # a request for an EAP type it does not support, then + # it normally rejects the request. By setting this + # configuration to "yes", you can tell the server to + # instead keep processing the request. Another module + # MUST then be configured to proxy the request to + # another RADIUS server which supports that EAP type. + # + # If another module is NOT configured to handle the + # request, then the request will still end up being + # rejected. + # + ignore_unknown_eap_types = no + + # Cisco AP1230B firmware 12.2(13)JA1 has a bug. When given + # a User-Name attribute in an Access-Accept, it copies one + # more byte than it should. + # + # We can work around it by configurably adding an extra + # zero byte. + # + cisco_accounting_username_bug = no + + # Help prevent DoS attacks by limiting the number of + # sessions that the server is tracking. For simplicity, + # this is taken from the "max_requests" directive in + # radiusd.conf. + # + max_sessions = ${max_requests} + + + ############################################################ + # + # Supported EAP-types + # + + + # EAP-MD5 + # + # We do NOT recommend using EAP-MD5 authentication + # for wireless connections. It is insecure, and does + # not provide for dynamic WEP keys. + # + md5 { + } + + + # EAP-pwd -- secure password-based authentication + # + #pwd { + # group = 19 + + # server_id = theserver@example.com + + # This has the same meaning as for TLS. + # + # fragment_size = 1020 + + # The virtual server which determines the + # "known good" password for the user. + # Note that unlike TLS, only the "authorize" + # section is processed. EAP-PWD requests can be + # distinguished by having a User-Name, but + # no User-Password, CHAP-Password, EAP-Message, etc. + # + # virtual_server = "inner-tunnel" + #} + + + # Cisco LEAP + # + # We do not recommend using LEAP in new deployments. See: + # http://www.securiteam.com/tools/5TP012ACKE.html + # + # LEAP is not supported. + # It is insecure, and no one should be using it. + # + + + # EAP-GTC -- Generic Token Card + # + # Currently, this is only permitted inside of EAP-TTLS, + # or EAP-PEAP. The module "challenges" the user with + # text, and the response from the user is taken to be + # the User-Password. + # + # Proxying the tunneled EAP-GTC session is a bad idea, + # the users password will go over the wire in plain-text, + # for anyone to see. + # + gtc { + # The default challenge, which many clients + # ignore.. + # + # challenge = "Password: " + + # The plain-text response which comes back + # is put into a User-Password attribute, + # and passed to another module for + # authentication. This allows the EAP-GTC + # response to be checked against plain-text, + # or crypt'd passwords. + # + # If you say "Local" instead of "PAP", then + # the module will look for a User-Password + # configured for the request, and do the + # authentication itself. + # + auth_type = PAP + } + + + # Common TLS configuration for TLS-based EAP types + # ------------------------------------------------ + # + # See raddb/certs/README.md for additional comments + # on certificates. + # + # If OpenSSL was not found at the time the server was + # built, the "tls", "ttls", and "peap" sections will + # be ignored. + # + # If you do not currently have certificates signed by + # a trusted CA you may use the 'snakeoil' certificates. + # Included with the server in raddb/certs. + # + # If these certificates have not been auto-generated: + # cd raddb/certs + # make + # + # These test certificates SHOULD NOT be used in a normal + # deployment. They are created only to make it easier + # to install the server, and to perform some simple + # tests with EAP-TLS, TTLS, or PEAP. + # + # Note that you should NOT use a globally known CA here! + # e.g. using a Verisign cert as a "known CA" means that + # ANYONE who has a certificate signed by them can + # authenticate via EAP-TLS! This is likely not what you want. + # + tls-config tls-common { + private_key_password = whatever + private_key_file = ${certdir}/server.pem + + # If Private key & Certificate are located in + # the same file, then private_key_file & + # certificate_file must contain the same file + # name. + # + # If ca_file (below) is not used, then the + # certificate_file below SHOULD also include all of + # the intermediate CA certificates used to sign the + # server certificate, but NOT the root CA. + # + # Including the ROOT CA certificate is not useful and + # merely inflates the exchanged data volume during + # the TLS negotiation. + # + # This file should contain the server certificate, + # followed by intermediate certificates, in order. + # i.e. If we have a server certificate signed by CA1, + # which is signed by CA2, which is signed by a root + # CA, then the "certificate_file" should contain + # server.pem, followed by CA1.pem, followed by + # CA2.pem. + # + # When using "ca_file" or "ca_path", the + # "certificate_file" should contain only + # "server.pem". And then you may (or may not) need + # to set "auto_chain", depending on your version of + # OpenSSL. + # + # In short, SSL / TLS certificates are complex. + # There are many versions of software, each of which + # behave slightly differently. It is impossible to + # give advice which will work everywhere. Instead, + # we give general guidelines. + # + certificate_file = ${certdir}/server.pem + + # Trusted Root CA list + # + # This file can contain multiple CA certificates. + # ALL of the CA's in this list will be trusted to + # issue client certificates for authentication. + # + # In general, you should use self-signed + # certificates for 802.1x (EAP) authentication. + # In that case, this CA file should contain + # *one* CA certificate. + # + ca_file = ${cadir}/ca.pem + + # OpenSSL will automatically create certificate chains, + # unless we tell it to not do that. The problem is that + # it sometimes gets the chains right from a certificate + # signature view, but wrong from the clients view. + # + # When setting "auto_chain = no", the server certificate + # file MUST include the full certificate chain. + # + # auto_chain = yes + + # If OpenSSL supports TLS-PSK, then we can use a + # fixed PSK identity and (hex) password. These can + # be used at the same time as the certificate + # configuration, but only for TLS 1.0 through 1.2. + # + # If PSK and certificates are configured at the same + # time for TLS 1.3, then the server will warn you, + # and will disable TLS 1.3, as it will not work. + # + # The work around is to have two modules (or for + # RadSec, two listen sections). One will have PSK + # configured, and the other will have certificates + # configured. + # + # psk_identity = "test" + # psk_hexphrase = "036363823" + + # Dynamic queries for the PSK. If TLS-PSK is used, + # and psk_query is set, then you MUST NOT use + # psk_identity or psk_hexphrase. + # + # Instead, use a dynamic expansion similar to the one + # below. It keys off of TLS-PSK-Identity. It should + # return a of string no more than 512 hex characters. + # That string will be converted to binary, and will + # be used as the dynamic PSK hexphrase. + # + # Note that this query is just an example. You will + # need to customize it for your installation. + # + # psk_query = "%{sql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}" + + # For DH cipher suites to work in OpenSSL < 1.1.0, + # you have to run OpenSSL to create the DH file + # first: + # + # openssl dhparam -out certs/dh 2048 + # + # For OpenSSL >= 1.1.0, just leave this commented + # out, and OpenSSL will do the right thing. + # + # dh_file = ${certdir}/dh + + # If your system doesn't have /dev/urandom, + # you will need to create this file, and + # periodically change its contents. + # + # For security reasons, FreeRADIUS doesn't + # write to files in its configuration + # directory. + # + # random_file = /dev/urandom + + # This can never exceed the size of a RADIUS + # packet (4096 bytes), and is preferably half + # that, to accommodate other attributes in + # RADIUS packet. On most APs the MAX packet + # length is configured between 1500 - 1600 + # In these cases, fragment size should be + # 1024 or less. + # + # fragment_size = 1024 + + # include_length is a flag which is + # by default set to yes If set to + # yes, Total Length of the message is + # included in EVERY packet we send. + # If set to no, Total Length of the + # message is included ONLY in the + # First packet of a fragment series. + # + # include_length = yes + + + # Check the Certificate Revocation List + # + # 1) Copy CA certificates and CRLs to same directory. + # 2) Execute 'c_rehash <CA certs&CRLs Directory>'. + # 'c_rehash' is OpenSSL's command. + # 3) uncomment the lines below. + # 5) Restart radiusd + # check_crl = yes + + # Check if intermediate CAs have been revoked. + # check_all_crl = yes + + ca_path = ${cadir} + + # OpenSSL does not reload contents of ca_path dir over time. + # That means that if check_crl is enabled and CRLs are loaded + # from ca_path dir, at some point CRLs will expire and + # RADIUSd will stop authenticating users. + # If ca_path_reload_interval is non-zero, it will force OpenSSL + # to reload all data from ca_path periodically + # + # Flush ca_path each hour + # ca_path_reload_interval = 3600 + + + # Accept an expired Certificate Revocation List + # + # allow_expired_crl = no + + # If check_cert_issuer is set, the value will + # be checked against the DN of the issuer in + # the client certificate. If the values do not + # match, the certificate verification will fail, + # rejecting the user. + # + # This check can be done more generally by checking + # the value of the TLS-Client-Cert-Issuer attribute. + # This check can be done via any mechanism you + # choose. + # + # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" + + # If check_cert_cn is set, the value will + # be xlat'ed and checked against the CN + # in the client certificate. If the values + # do not match, the certificate verification + # will fail rejecting the user. + # + # This check is done only if the previous + # "check_cert_issuer" is not set, or if + # the check succeeds. + # + # This check can be done more generally by writing + # "unlang" statements to examine the value of the + # TLS-Client-Cert-Common-Name attribute. + # + # check_cert_cn = %{User-Name} + + # + # This configuration item only applies when there is + # an intermediate CA between the "root" CA, and the + # client certificate. If we trust the root CA, then + # by definition we also trust ANY intermediate CA + # which is signed by that root. This means ANOTHER + # intermediate CA can issue client certificates, and + # have them accepted by the EAP module. + # + # The solution is to list ONLY the trusted CAs in the + # FreeRADIUS configuration, and then set this + # configuration item to "yes". + # + # Then, when the server receives a client certificate + # from an untrusted CA, that authentication request + # can be rejected. + # + # It is possible to do these checks in "unlang", by + # checking for unknown names in the + # TLS-Cert-Common-Name attribute, but that is + # more complex. So we add a configuration option + # which can be set once, and which works for all + # possible intermediate CAs, no matter what their + # value. + # + # reject_unknown_intermediate_ca = no + + # Set this option to specify the allowed + # TLS cipher suites. The format is listed + # in "man 1 ciphers". + # + cipher_list = "DEFAULT" + + # Set this option to specify the allowed + # TLS signature algorithms for OpenSSL 1.1.1 and above. + # The format and available signature algorithms are listed + # in "man 3 SSL_CTX_set1_sigalgs_list". + # + # sigalgs_list = "" + + # If enabled, OpenSSL will use server cipher list + # (possibly defined by cipher_list option above) + # for choosing right cipher suite rather than + # using client-specified list which is OpenSSl default + # behavior. Setting this to "yes" means that OpenSSL + # will choose the servers ciphers, even if they do not + # best match what the client sends. + # + # TLS negotiation is usually good, but can be imperfect. + # This setting allows administrators to "fine tune" it + # if necessary. + # + cipher_server_preference = no + + # You can selectively disable TLS versions for + # compatability with old client devices. + # + # If your system has OpenSSL 1.1.0 or greater, do NOT + # use these. Instead, set tls_min_version and + # tls_max_version. + # +# disable_tlsv1_2 = yes +# disable_tlsv1_1 = yes +# disable_tlsv1 = yes + + + # Set min / max TLS version. + # + # Generally speaking you should NOT use TLS 1.0 or + # TLS 1.1. They are old, possibly insecure, and + # deprecated. However, it is sometimes necessary to + # enable it for compatibility with legact systems. + # We recommend replacing those legacy systems, and + # using at least TLS 1.2. + # + # Some Debian versions disable older versions of TLS, + # and requires the application to manually enable + # them. + # + # If you are running such a distribution, you should + # set these options, otherwise older clients will not + # be able to connect. + # + # Allowed values are "1.0", "1.1", "1.2", and "1.3". + # + # As of 2021, it is STRONGLY RECOMMENDED to set + # + # tls_min_version = "1.2" + # + # Older TLS versions are insecure and deprecated. + # + # In order to enable TLS 1.0 and TLS 1.1, you may + # also need to update cipher_list below to: + # + # * OpenSSL >= 3.x + # + # cipher_list = "DEFAULT@SECLEVEL=0" + # + # * OpenSSL < 3.x + # + # cipher_list = "DEFAULT@SECLEVEL=1" + # + # The values must be in quotes. + # + # We also STRONGLY RECOMMEND to set + # + # tls_max_version = "1.2" + # + # While the server will accept "1.3" as a value, + # most EAP supplicants WILL NOT DO TLS 1.3 PROPERLY. + # + # i.e. they WILL NOT WORK, SO DO NOT ASK QUESTIONS ON + # THE LIST ABOUT WHY IT DOES NOT WORK. + # + # The TLS 1.3 support is here for future + # compatibility, as clients get upgraded, and people + # don't upgrade their copies of FreeRADIUS. + # + # Also note that we only support TLS 1.3 for EAP-TLS. + # Other versions of EAP (PEAP, TTLS, FAST) DO NOT + # SUPPORT TLS 1.3. + # + tls_min_version = "1.2" + tls_max_version = "1.2" + + # Elliptical cryptography configuration + # + # This configuration should be one of the following: + # + # * a name of the curve to use, e.g. "prime256v1". + # + # * a colon separated list of curve NIDs or names. + # + # * an empty string, in which case OpenSSL will choose + # the "best" curve for the situation. + # + # For supported curve names, please run + # + # openssl ecparam -list_curves + # + ecdh_curve = "" + + # Session resumption / fast reauthentication + # cache. + # + # The cache contains the following information: + # + # session Id - unique identifier, managed by SSL + # User-Name - from the Access-Accept + # Stripped-User-Name - from the Access-Request + # Cached-Session-Policy - from the Access-Accept + # + # See also the "store" subsection below for + # additional attributes which can be cached. + # + # The "Cached-Session-Policy" is the name of a + # policy which should be applied to the cached + # session. This policy can be used to assign + # VLANs, IP addresses, etc. It serves as a useful + # way to re-apply the policy from the original + # Access-Accept to the subsequent Access-Accept + # for the cached session. + # + # On session resumption, these attributes are + # copied from the cache, and placed into the + # reply list. + # + # You probably also want "use_tunneled_reply = yes" + # when using fast session resumption. + # + # You can check if a session has been resumed by + # looking for the existence of the EAP-Session-Resumed + # attribute. Note that this attribute will *only* + # exist in the "post-auth" section. + # + # CAVEATS: The cache is stored and reloaded BEFORE + # the "post-auth" section is run. This limitation + # makes caching more difficult than it should be. In + # practice, it means that the first authentication + # session must set the reply attributes before the + # post-auth section is run. + # + # When the session is resumed, the attributes are + # restored and placed into the session-state list. + # + cache { + # Enable it. The default is "no". Deleting the entire "cache" + # subsection also disables caching. + # + # The session cache requires the use of the + # "name" and "persist_dir" configuration + # items, below. + # + # The internal OpenSSL session cache has been permanently + # disabled. + # + # You can disallow resumption for a particular user by adding the + # following attribute to the control item list: + # + # Allow-Session-Resumption = No + # + # If "enable = no" below, you CANNOT enable resumption for just one + # user by setting the above attribute to "yes". + # + enable = no + + # Lifetime of the cached entries, in hours. The sessions will be + # deleted/invalidated after this time. + # + lifetime = 24 # hours + + # Internal "name" of the session cache. Used to + # distinguish which TLS context sessions belong to. + # + # The server will generate a random value if unset. + # This will change across server restart so you MUST + # set the "name" if you want to persist sessions (see + # below). + # + # name = "EAP module" + + # Simple directory-based storage of sessions. + # Two files per session will be written, the SSL + # state and the cached VPs. This will persist session + # across server restarts. + # + # The default directory is ${logdir}, for historical + # reasons. You should ${db_dir} instead. And check + # the value of db_dir in the main radiusd.conf file. + # It should not point to ${raddb} + # + # The server will need write perms, and the directory + # should be secured from anyone else. You might want + # a script to remove old files from here periodically: + # + # find ${logdir}/tlscache -mtime +2 -exec rm -f {} \; + # + # This feature REQUIRES "name" option be set above. + # + # persist_dir = "${logdir}/tlscache" + + # + # It is possible to partially + # control which attributes exist in the + # session cache. This subsection lists + # attributes which are taken from the reply, + # and saved to the on-disk cache. When the + # session is resumed, these attributes are + # added to the "session-state" list. The + # default configuration will then take care + # of copying them to the reply. + # + store { + Tunnel-Private-Group-Id + } + } + + # Client certificates can be validated via an + # external command. This allows dynamic CRLs or OCSP + # to be used. + # + # This configuration is commented out in the + # default configuration. Uncomment it, and configure + # the correct paths below to enable it. + # + # If OCSP checking is enabled, and the OCSP checks fail, + # the verify section is not run. + # + # If OCSP checking is disabled, the verify section is + # run on successful certificate validation. + # + verify { + # If the OCSP checks succeed, the verify section + # is run to allow additional checks. + # + # If you want to skip verify on OCSP success, + # uncomment this configuration item, and set it + # to "yes". + # + # skip_if_ocsp_ok = no + + # A temporary directory where the client + # certificates are stored. This directory + # MUST be owned by the UID of the server, + # and MUST not be accessible by any other + # users. When the server starts, it will do + # "chmod go-rwx" on the directory, for + # security reasons. The directory MUST + # exist when the server starts. + # + # You should also delete all of the files + # in the directory when the server starts. + # + # tmpdir = /tmp/radiusd + + # The command used to verify the client cert. + # We recommend using the OpenSSL command-line + # tool. + # + # The ${..ca_path} text is a reference to + # the ca_path variable defined above. + # + # The %{TLS-Client-Cert-Filename} is the name + # of the temporary file containing the cert + # in PEM format. This file is automatically + # deleted by the server when the command + # returns. + # + # client = "/path/to/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" + } + + # OCSP Configuration + # + # Certificates can be verified against an OCSP + # Responder. This makes it possible to immediately + # revoke certificates without the distribution of + # new Certificate Revocation Lists (CRLs). + # + ocsp { + # Enable it. The default is "no". + # Deleting the entire "ocsp" subsection + # also disables ocsp checking + # + enable = no + + # The OCSP Responder URL can be automatically + # extracted from the certificate in question. + # To override the OCSP Responder URL set + # "override_cert_url = yes". + # + override_cert_url = yes + + # If the OCSP Responder address is not extracted from + # the certificate, the URL can be defined here. + # + url = "http://127.0.0.1/ocsp/" + + # If the OCSP Responder can not cope with nonce + # in the request, then it can be disabled here. + # + # For security reasons, disabling this option + # is not recommended as nonce protects against + # replay attacks. + # + # Note that Microsoft AD Certificate Services OCSP + # Responder does not enable nonce by default. It is + # more secure to enable nonce on the responder than + # to disable it in the query here. + # See http://technet.microsoft.com/en-us/library/cc770413%28WS.10%29.aspx + # + # use_nonce = yes + + # Number of seconds before giving up waiting + # for OCSP response. 0 uses system default. + # + # timeout = 0 + + # Normally an error in querying the OCSP + # responder (no response from server, server did + # not understand the request, etc) will result in + # a validation failure. + # + # To treat these errors as 'soft' failures and + # still accept the certificate, enable this + # option. + # + # Warning: this may enable clients with revoked + # certificates to connect if the OCSP responder + # is not available. Use with caution. + # + # softfail = no + } + + # + # The server can present different certificates based + # on the realm presented in EAP. See + # raddb/certs/realms/README.md for examples of how to + # configure this. + # + # Note that the default is to use the same set of + # realm certificates for both EAP and RadSec! If + # this is not what you want, you should use different + # subdirectories or each, e.g. ${certdir}/realms/radsec/, + # and ${certdir}/realms/eap/ + # + # realm_dir = ${certdir}/realms/ + } + + + # EAP-TLS + # + # The TLS configuration for TLS-based EAP types is held in + # the "tls-config" section, above. + # + tls { + # Point to the common TLS configuration + # + tls = tls-common + + # As part of checking a client certificate, the EAP-TLS + # sets some attributes such as TLS-Client-Cert-Common-Name. This + # virtual server has access to these attributes, and can + # be used to accept or reject the request. + # + # virtual_server = check-eap-tls + + # You can control whether or not EAP-TLS requires a + # client certificate by setting + # + # configurable_client_cert = yes + # + # Once that setting has been changed, you can then set + # + # EAP-TLS-Require-Client-Cert = No + # + # in the control items for a request, and the EAP-TLS + # module will not require a client certificate from + # the supplicant. + # + # WARNING: This configuration should only be used + # when the users are placed into a "captive portal" + # or "walled garden", where they have limited network + # access. Otherwise the configuraton will allow + # anyone on the network, without authenticating them! + # +# configurable_client_cert = no + } + + + # EAP-TTLS -- Tunneled TLS + # + # The TTLS module implements the EAP-TTLS protocol, + # which can be described as EAP inside of Diameter, + # inside of TLS, inside of EAP, inside of RADIUS... + # + # Surprisingly, it works quite well. + # + ttls { + # Which tls-config section the TLS negotiation parameters + # are in - see EAP-TLS above for an explanation. + # + # In the case that an old configuration from FreeRADIUS + # v2.x is being used, all the options of the tls-config + # section may also appear instead in the 'tls' section + # above. If that is done, the tls= option here (and in + # tls above) MUST be commented out. + # + tls = tls-common + + # The tunneled EAP session needs a default EAP type + # which is separate from the one for the non-tunneled + # EAP module. Inside of the TTLS tunnel, we recommend + # using EAP-MD5. If the request does not contain an + # EAP conversation, then this configuration entry is + # ignored. + # + default_eap_type = md5 + + # The tunneled authentication request does not usually + # contain useful attributes like 'Calling-Station-Id', + # etc. These attributes are outside of the tunnel, + # and normally unavailable to the tunneled + # authentication request. + # + # By setting this configuration entry to 'yes', + # any attribute which is NOT in the tunneled + # authentication request, but which IS available + # outside of the tunnel, is copied to the tunneled + # request. + # + # allowed values: {no, yes} + # + copy_request_to_tunnel = no + + # This configuration item is deprecated. Instead, + # you should use: + # + # update outer.session-state { + # ... + # } + # + # This will cache attributes for the final Access-Accept. + # + # See "update outer.session-state" in the "post-auth" + # sections of sites-available/default, and of + # sites-available/inner-tunnel + # + # The reply attributes sent to the NAS are usually + # based on the name of the user 'outside' of the + # tunnel (usually 'anonymous'). If you want to send + # the reply attributes based on the user name inside + # of the tunnel, then set this configuration entry to + # 'yes', and the reply to the NAS will be taken from + # the reply to the tunneled request. + # + # allowed values: {no, yes} + # + use_tunneled_reply = no + + # The inner tunneled request can be sent + # through a virtual server constructed + # specifically for this purpose. + # + # A virtual server MUST be specified. + # + virtual_server = "inner-tunnel" + + # This has the same meaning, and overwrites, the + # same field in the "tls" configuration, above. + # The default value here is "yes". + # + # include_length = yes + + # Unlike EAP-TLS, EAP-TTLS does not require a client + # certificate. However, you can require one by setting the + # following option. You can also override this option by + # setting + # + # EAP-TLS-Require-Client-Cert = Yes + # + # in the control items for a request. + # + # Note that the majority of supplicants do not support using a + # client certificate with EAP-TTLS, so this option is unlikely + # to be usable for most people. + # + # require_client_cert = yes + } + + + # EAP-PEAP + # + + ################################################## + # + # !!!!! WARNINGS for Windows compatibility !!!!! + # + ################################################## + # + # If you see the server send an Access-Challenge, + # and the client never sends another Access-Request, + # then + # + # STOP! + # + # The server certificate has to have special OID's + # in it, or else the Microsoft clients will silently + # fail. See the "scripts/xpextensions" file for + # details, and the following page: + # + # https://support.microsoft.com/en-us/help/814394/ + # + # If is still doesn't work, and you're using Samba, + # you may be encountering a Samba bug. See: + # + # https://bugzilla.samba.org/show_bug.cgi?id=6563 + # + # Note that we do not necessarily agree with their + # explanation... but the fix does appear to work. + # + ################################################## + + # The tunneled EAP session needs a default EAP type + # which is separate from the one for the non-tunneled + # EAP module. Inside of the TLS/PEAP tunnel, we + # recommend using EAP-MS-CHAPv2. + # + peap { + # Which tls-config section the TLS negotiation parameters + # are in - see EAP-TLS above for an explanation. + # + # In the case that an old configuration from FreeRADIUS + # v2.x is being used, all the options of the tls-config + # section may also appear instead in the 'tls' section + # above. If that is done, the tls= option here (and in + # tls above) MUST be commented out. + # + tls = tls-common + + # The tunneled EAP session needs a default + # EAP type which is separate from the one for + # the non-tunneled EAP module. Inside of the + # PEAP tunnel, we recommend using MS-CHAPv2, + # as that is the default type supported by + # Windows clients. + # + default_eap_type = mschapv2 + + # The PEAP module also has these configuration + # items, which are the same as for TTLS. + # + copy_request_to_tunnel = no + + # This configuration item is deprecated. Instead, + # you should use: + # + # update outer.session-state { + # ... + # } + # + # This will cache attributes for the final Access-Accept. + # + # See "update outer.session-state" in the "post-auth" + # sections of sites-available/default, and of + # sites-available/inner-tunnel + # + use_tunneled_reply = no + + # When the tunneled session is proxied, the + # home server may not understand EAP-MSCHAP-V2. + # Set this entry to "no" to proxy the tunneled + # EAP-MSCHAP-V2 as normal MSCHAPv2. + # + # This setting can be over-ridden on a packet by + # packet basis by setting + # + # &control:Proxy-Tunneled-Request-As-EAP = yes + # + # proxy_tunneled_request_as_eap = yes + + # The inner tunneled request can be sent + # through a virtual server constructed + # specifically for this purpose. + # + # A virtual server MUST be specified. + # + virtual_server = "inner-tunnel" + + # This option enables support for MS-SoH + # see doc/SoH.txt for more info. + # It is disabled by default. + # + # soh = yes + + # The SoH reply will be turned into a request which + # can be sent to a specific virtual server: + # + # soh_virtual_server = "soh-server" + + # Unlike EAP-TLS, PEAP does not require a client certificate. + # However, you can require one by setting the following + # option. You can also override this option by setting + # + # EAP-TLS-Require-Client-Cert = Yes + # + # in the control items for a request. + # + # Note that the majority of supplicants do not support using a + # client certificate with PEAP, so this option is unlikely to + # be usable for most people. + # + # require_client_cert = yes + } + + + # EAP-MSCHAPv2 + # + # Note that it is the EAP MS-CHAPv2 sub-module, not + # the main 'mschap' module. + # + # Note also that in order for this sub-module to work, + # the main 'mschap' module MUST ALSO be configured. + # + # This module is the *Microsoft* implementation of MS-CHAPv2 + # in EAP. There is another (incompatible) implementation + # of MS-CHAPv2 in EAP by Cisco, which FreeRADIUS does not + # currently support. + # + mschapv2 { + # In earlier versions of the server, this module + # never sent the MS-CHAP-Error message to the client. + # This worked, but it had issues when the cached + # password was wrong. The server *should* send + # "E=691 R=0" to the client, which tells it to prompt + # the user for a new password. + # + # The default is to use that functionality. which is + # known to work. If you set "send_error = yes", then + # the error message will be sent back to the client. + # This *may* help some clients work better, but *may* + # also cause other clients to stop working. + # + # send_error = no + + # Server identifier to send back in the challenge. + # This should generally be the host name of the + # RADIUS server. Or, some information to uniquely + # identify it. + # + # identity = "FreeRADIUS" + } + + + # EAP-FAST + # + # The FAST module implements the EAP-FAST protocol + # + #fast { + # Point to the common TLS configuration + # + # tls = tls-common + + # If 'cipher_list' is set here, it will over-ride the + # 'cipher_list' configuration from the 'tls-common' + # configuration. The EAP-FAST module has it's own + # over-ride for 'cipher_list' because the + # specifications mandata a different set of ciphers + # than are used by the other EAP methods. + # + # cipher_list though must include "ADH" for anonymous provisioning. + # This is not as straight forward as appending "ADH" alongside + # "DEFAULT" as "DEFAULT" contains "!aNULL" so instead it is + # recommended "ALL:!EXPORT:!eNULL:!SSLv2" is used + # + # cipher_list = "ALL:!EXPORT:!eNULL:!SSLv2" + + # PAC lifetime in seconds (default: seven days) + # + # pac_lifetime = 604800 + + # Authority ID of the server + # + # If you are running a cluster of RADIUS servers, you should make + # the value chosen here (and for "pac_opaque_key") the same on all + # your RADIUS servers. This value should be unique to your + # installation. We suggest using a domain name. + # + # authority_identity = "1234" + + # PAC Opaque encryption key (must be exactly 32 bytes in size) + # + # This value MUST be secret, and MUST be generated using + # a secure method, such as via 'openssl rand -hex 32' + # + # pac_opaque_key = "0123456789abcdef0123456789ABCDEF" + + # Same as for TTLS, PEAP, etc. + # + # virtual_server = inner-tunnel + #} +} diff --git a/raddb/mods-available/echo b/raddb/mods-available/echo new file mode 100644 index 0000000..ad3e159 --- /dev/null +++ b/raddb/mods-available/echo @@ -0,0 +1,123 @@ +# -*- text -*- +# +# $Id$ + +# +# This is a more general example of the execute module. +# +# This one is called "echo". +# +# Attribute-Name = `%{echo:/path/to/program args}` +# +# If you wish to execute an external program in more than +# one section (e.g. 'authorize', 'pre_proxy', etc), then it +# is probably best to define a different instance of the +# 'exec' module for every section. +# +# The return value of the program run determines the result +# of the exec instance call as follows: +# (See doc/configurable_failover for details) +# +# < 0 : fail the module failed +# = 0 : ok the module succeeded +# = 1 : reject the module rejected the user +# = 2 : fail the module failed +# = 3 : ok the module succeeded +# = 4 : handled the module has done everything to handle the request +# = 5 : invalid the user's configuration entry was invalid +# = 6 : userlock the user was locked out +# = 7 : notfound the user was not found +# = 8 : noop the module did nothing +# = 9 : updated the module updated information in the request +# > 9 : fail the module failed +# +exec echo { + # + # Wait for the program to finish. + # + # If we do NOT wait, then the program is "fire and + # forget", and any output attributes from it are ignored. + # + # If we are looking for the program to output + # attributes, and want to add those attributes to the + # request, then we MUST wait for the program to + # finish, and therefore set 'wait=yes' + # + # allowed values: {no, yes} + wait = yes + + # + # The name of the program to execute, and it's + # arguments. Dynamic translation is done on this + # field, so things like the following example will + # work. + # + program = "/bin/echo %{User-Name}" + + # + # The attributes which are placed into the + # environment variables for the program. + # + # Allowed values are: + # + # request attributes from the request + # config attributes from the configuration items list + # reply attributes from the reply + # proxy-request attributes from the proxy request + # proxy-reply attributes from the proxy reply + # + # Note that some attributes may not exist at some + # stages. e.g. There may be no proxy-reply + # attributes if this module is used in the + # 'authorize' section. + # + input_pairs = request + + # + # Where to place the output attributes (if any) from + # the executed program. The values allowed, and the + # restrictions as to availability, are the same as + # for the input_pairs. + # + output_pairs = reply + + # + # When to execute the program. If the packet + # type does NOT match what's listed here, then + # the module does NOT execute the program. + # + # For a list of allowed packet types, see + # the 'dictionary' file, and look for VALUEs + # of the Packet-Type attribute. + # + # By default, the module executes on ANY packet. + # Un-comment out the following line to tell the + # module to execute only if an Access-Accept is + # being sent to the NAS. + # + #packet_type = Access-Accept + + # + # Should we escape the environment variables? + # + # If this is set, all the RADIUS attributes + # are capitalised and dashes replaced with + # underscores. Also, RADIUS values are surrounded + # with double-quotes. + # + # That is to say: User-Name=BobUser => USER_NAME="BobUser" + shell_escape = yes + + # + # How long should we wait for the program to finish? + # + # Default is 10 seconds, which should be plenty for nearly + # anything. Range is 1 to 30 seconds. You are strongly + # encouraged to NOT increase this value. Decreasing can + # be used to cause authentication to fail sooner when you + # know it's going to fail anyway due to the time taken, + # thereby saving resources. + # + #timeout = 10 + +} diff --git a/raddb/mods-available/etc_group b/raddb/mods-available/etc_group new file mode 100644 index 0000000..114f24a --- /dev/null +++ b/raddb/mods-available/etc_group @@ -0,0 +1,32 @@ +# -*- text -*- +# +# $Id$ + +# "passwd" configuration, for the /etc/group file. Adds a Etc-Group-Name +# attribute for every group that the user is member of. +# +# You will have to define the Etc-Group-Name in the 'dictionary' file +# as a 'string' type. +# +# The module name "etc_group" should also be listed in the "authorize" +# section. Make sure it's listed before any other part of the server +# tries to use the Etc-Group-Name attribute. +# +# The Group and Group-Name attributes are automatically created by +# the Unix module, and do checking against /etc/group automatically. +# This means that you CANNOT use Group or Group-Name to do any other +# kind of grouping in the server. You MUST define a new group +# attribute. +# +# i.e. this module should NOT be used as-is, but should be edited to +# point to a different group file. +# +passwd etc_group { + filename = /etc/group + format = "=Etc-Group-Name:::*,User-Name" + hash_size = 50 + ignore_nislike = yes + allow_multiple_keys = yes + delimiter = ":" +} + diff --git a/raddb/mods-available/exec b/raddb/mods-available/exec new file mode 100644 index 0000000..bb1d437 --- /dev/null +++ b/raddb/mods-available/exec @@ -0,0 +1,29 @@ +# -*- text -*- +# +# $Id$ + +# +# Execute external programs +# +# This module is useful only for 'xlat'. To use it, +# put 'exec' into the 'instantiate' section. You can then +# do dynamic translation of attributes like: +# +# Attribute-Name = `%{exec:/path/to/program args}` +# +# The value of the attribute will be replaced with the output +# of the program which is executed. Due to RADIUS protocol +# limitations, any output over 253 bytes will be ignored. +# +# The RADIUS attributes from the user request will be placed +# into environment variables of the executed program, as +# described in "man unlang" and in doc/configuration/variables.rst +# +# See also "echo" for more sample configuration. +# +exec { + wait = no + input_pairs = request + shell_escape = yes + timeout = 10 +} diff --git a/raddb/mods-available/expiration b/raddb/mods-available/expiration new file mode 100644 index 0000000..5d06454 --- /dev/null +++ b/raddb/mods-available/expiration @@ -0,0 +1,13 @@ +# -*- text -*- +# +# $Id$ + +# +# The expiration module. This handles the Expiration attribute +# It should be included in the *end* of the authorize section +# in order to handle user Expiration. It should also be included +# in the instantiate section in order to register the Expiration +# compare function +# +expiration { +} diff --git a/raddb/mods-available/expr b/raddb/mods-available/expr new file mode 100644 index 0000000..ca0b3bf --- /dev/null +++ b/raddb/mods-available/expr @@ -0,0 +1,148 @@ +# -*- text -*- +# +# $Id$ + +# +# This module performs mathematical calculations: +# +# Attribute-Name = "%{expr:2 + 3 + &NAS-Port}" +# +# It supports the following operators (in order of precedence) +# +# & binary AND +# | binary OR +# << left shift +# >> right shift +# + addition +# - subtraction +# * multiply +# / divide +# %% remainder +# ^ exponentiation +# (...) sub-expression +# +# Operator precedence follows the normal rules. +# Division by zero means that the entire expression is invalid. +# +# It also allows unary negation: -1 +# And twos complement: ~1 +# +# All calculations are done on signed 63-bit integers. +# e.g. int64_t. This should be sufficient for all normal +# purposes. +# +# Hex numbers are supported: 0xabcdef +# +# As with all string expansions, you can nest the expansions: +# +# %{expr: %{NAS-Port} + 1} +# %{expr: %{sql:SELECT ... } + 1} +# +# Attribute references are supported for integer attributes. +# e.g. &NAS-Port. The benefit of using attribute references +# is that the expression is calculated directly on the +# attribute. It skips the step of "print to string, and then +# parse to number". This means it's a little faster. +# +# Otherwise, all numbers are decimal. +# + +# +# The module also registers a few paircompare functions, and +# many string manipulation functions, including: +# +# rand get random number from 0 to n-1 +# "%{rand:10}" == "9" +# +# randstr get random string built from character classes: +# c lowercase letters +# C uppercase letters +# n numbers +# a alphanumeric +# ! punctuation +# . alphanumeric + punctuation +# s alphanumeric + "./" +# o characters suitable for OTP (easily confused removed) +# h binary data as lowercase hex +# H binary data as uppercase hex +# +# "%{randstr:CCCC!!cccnnn}" == "IPFL>{saf874" +# "%{randstr:oooooooo}" == "rfVzyA4y" +# "%{randstr:hhhh}" == "68d60de3" +# +# urlquote quote special characters in URI +# "%{urlquote:http://example.org/}" == "http%3A%47%47example.org%47" +# +# urlunquote unquote URL special characters +# "%{urlunquote:http%%3A%%47%%47example.org%%47}" == "http://example.org/" +# +# escape escape string similar to rlm_sql safe_characters +# "%{escape:<img>foo.jpg</img>}" == "=60img=62foo.jpg=60/img=62" +# +# unescape reverse of escape +# "%{unescape:=60img=62foo.jpg=60/img=62}" == "<img>foo.jpg</img>" +# +# tolower convert to lowercase +# "%{tolower:Bar}" == "bar" +# +# toupper convert to uppercase +# "%{toupper:Foo}" == "FOO" +# +# md5 get md5sum hash +# "%{md5:foo}" == "acbd18db4cc2f85cedef654fccc4a4d8" +# +# sha1 get sha1 hash +# "%{sha1:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" +# +# sha256 get sha256 hash +# "%{sha256:foo}" == "2c26b46b68ffc68ff99b453c1d30413413422d706..." +# +# sha512 get sha512 hash +# "%{sha512:foo}" == "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae29838..." +# +# hmacmd5 generate HMAC-MD5 of string +# "%{hmacmd5:foo bar}" == "31b6db9e5eb4addb42f1a6ca07367adc" +# +# hmacsha1 generate HMAC-SHA1 of string +# "%{hmacsha1:foo bar}" == "85d155c55ed286a300bd1cf124de08d87e914f3a" +# +# crypt encrypt with a salt: %{crypt:salt:password} +# "%{crypt:aa:foo}" == "aaKNIEDOaueR6" +# "%{crypt:$1$abcdefgh:foo}" == "$1$abcdefgh$XxzGe9Muun7wTYbZO4sdr0" +# "%{crypt:$5$%{randstr:aaaaaaaaaaaaaaaa}:foo}" == "$1$fu4P2fcAdo9gM..." +# +# pairs serialize attributes as comma-delimited string +# "%{pairs:request:}" == "User-Name = 'foo', User-Password = 'bar', ..." +# +# base64 encode string as base64 +# "%{base64:foo}" == "Zm9v" +# +# base64tohex convert base64 to hex +# "%{base64tohex:Zm9v}" == "666f6f" +# +# explode split an attribute into multiple new attributes based on a delimiter +# "%{explode:&ref <delim>}" +# +# nexttime calculate number of seconds until next n hour(s), day(s), week(s), year(s) +# if it were 16:18, %{nexttime:1h} would expand to 2520 +# +# lasttime calculate number of seconds until last n hour(s), day(s), week(s), year(s) +# if it were 16:18, %{lasttime:1h} would expand to 4680 +# +# lpad left-pad a string +# if User-Name is "foo": "%{lpad:&User-Name 6 x}" == "xxxfoo" +# +# rpad right-pad a string +# if User-Name is "foo": "%{rpad:&User-Name 5 -}" == "foo--" +# +# concat concatenate a set of attributes, separated by a character. +# "%{concat:foo[*] ;}" +# + +expr { + # + # Characters that will not be encoded by the %{escape} + # xlat function. + # + safe_characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /äéöüàâæçèéêëîïôœùûüaÿÄÉÖÜßÀÂÆÇÈÉÊËÎÏÔŒÙÛÜŸ" +} diff --git a/raddb/mods-available/files b/raddb/mods-available/files new file mode 100644 index 0000000..e3f3bf5 --- /dev/null +++ b/raddb/mods-available/files @@ -0,0 +1,30 @@ +# -*- text -*- +# +# $Id$ + +# Livingston-style 'users' file +# +# See "man users" for more information. +# +files { + # Search for files in a subdirectory of mods-config which + # matches this instance of the files module. + moddir = ${modconfdir}/${.:instance} + + # The default key attribute to use for matches. The content + # of this attribute is used to match the "name" of the + # entry. + #key = "%{%{Stripped-User-Name}:-%{User-Name}}" + + # The old "users" style file is now located here. + filename = ${moddir}/authorize + + # This is accepted for backwards compatibility + # It will be removed in a future release. +# usersfile = ${moddir}/authorize + + # These are accepted for backwards compatibility. + # They will be renamed in a future release. + acctusersfile = ${moddir}/accounting + preproxy_usersfile = ${moddir}/pre-proxy +} diff --git a/raddb/mods-available/idn b/raddb/mods-available/idn new file mode 100644 index 0000000..5340540 --- /dev/null +++ b/raddb/mods-available/idn @@ -0,0 +1,28 @@ +# -*- text -*- +# +# $Id$ + +# +# Internationalised domain names. +# + +# The expansion string: %{idn: example.com} results in an ASCII +# punycode version of the domain name. That version can then be used +# for name comparisons. Using an i18n version of the name is NOT +# RECOMMENDED, as that version is not canonical. +# +# i.e. the "same" domain name can be represented in many, many, +# different ways. Only the idn version has *one* representation. +# +idn { + # + # Allow use of unassigned Unicode code points. + # + allow_unassigned = no + + # + # Prohibit underscores and other invalid characters in domain + # names. + use_std3_ascii_rules = yes + +}
\ No newline at end of file diff --git a/raddb/mods-available/inner-eap b/raddb/mods-available/inner-eap new file mode 100644 index 0000000..576eb77 --- /dev/null +++ b/raddb/mods-available/inner-eap @@ -0,0 +1,107 @@ +# -*- text -*- +# +# $Id$ + +# +# Sample configuration for an EAP module that occurs *inside* +# of a tunneled method. It is used to limit the EAP types that +# can occur inside of the inner tunnel. +# +# See also raddb/sites-available/inner-tunnel +# +# See raddb/mods-available/eap for full documentation on the meaning of these +# configuration entries. +# +eap inner-eap { + # This is the best choice for PEAP. + default_eap_type = mschapv2 + + timer_expire = 60 + + # This should be the same as the outer eap "max sessions" + max_sessions = 2048 + + # Supported EAP-types + md5 { + } + + gtc { + # The default challenge, which many clients + # ignore.. + #challenge = "Password: " + + auth_type = PAP + } + + mschapv2 { + # See eap for documentation +# send_error = no + } + + # No TTLS or PEAP configuration should be listed here. + + ## EAP-TLS + # + # You SHOULD use different certificates than are used + # for the outer EAP configuration! + # + # You can create the "inner-server.pem" file by doing: + # + # cd raddb/certs + # vi inner-server.cnf + # make inner-server + # + # The certificate MUST be different from the "server.cnf" + # file. + # + # Support for PEAP/TLS and RFC 5176 TLS/TLS is experimental. + # It might work, or it might not. + # + tls { + private_key_password = whatever + private_key_file = ${certdir}/inner-server.pem + + # If Private key & Certificate are located in + # the same file, then private_key_file & + # certificate_file must contain the same file + # name. + # + # If ca_file (below) is not used, then the + # certificate_file below MUST include not + # only the server certificate, but ALSO all + # of the CA certificates used to sign the + # server certificate. + certificate_file = ${certdir}/inner-server.pem + + # You may want different CAs for inner and outer + # certificates. If so, edit this file. + ca_file = ${cadir}/ca.pem + + cipher_list = "DEFAULT" + + # You may want to set a very small fragment size. + # The TLS data here needs to go inside of the + # outer EAP-TLS protocol. + # + # Try values and see if they work... + # fragment_size = 1024 + + # Other needful things + dh_file = ${certdir}/dh + random_file = /dev/urandom + + # CRL and OCSP things go here. See the main "eap" + # file for details. + # check_crl = yes + # ca_path = /path/to/directory/with/ca_certs/and/crls/ + + # Accept an expired Certificate Revocation List + # +# allow_expired_crl = no + + # + # The session resumption / fast re-authentication + # cache CANNOT be used for inner sessions. + # + } +} diff --git a/raddb/mods-available/ippool b/raddb/mods-available/ippool new file mode 100644 index 0000000..1d3305b --- /dev/null +++ b/raddb/mods-available/ippool @@ -0,0 +1,66 @@ +# -*- text -*- +# +# $Id$ + +# Do server side ip pool management. Should be added in +# post-auth and accounting sections. +# +# The module also requires the existence of the Pool-Name +# attribute. That way the administrator can add the Pool-Name +# attribute in the user profiles and use different pools for +# different users. The Pool-Name attribute is a *check* item +# not a reply item. +# +# The Pool-Name should be set to the ippool module instance +# name or to DEFAULT to match any module. + +# +# Example: +# radiusd.conf: ippool students { [...] } +# ippool teachers { [...] } +# users file : DEFAULT Group == students, Pool-Name := "students" +# DEFAULT Group == teachers, Pool-Name := "teachers" +# DEFAULT Group == other, Pool-Name := "DEFAULT" +# +# Note: If you change the range parameters you must then erase the +# db files. +# +ippool main_pool { + # The main db file used to allocate addresses. + filename = ${db_dir}/db.ippool + + # The start and end ip addresses for this pool. + range_start = 192.0.2.1 + range_stop = 192.0.2.254 + + # The network mask used for this pool. + netmask = 255.255.255.0 + + # The gdbm cache size for the db files. Should + # be equal to the number of ip's available in + # the ip pool + cache_size = 800 + + # Helper db index file used in multilink + ip_index = ${db_dir}/db.ipindex + + # If set, the Framed-IP-Address already in the + # reply (if any) will be discarded, and replaced + # ith a Framed-IP-Address assigned here. + override = no + + # Specifies the maximum time in seconds that an + # entry may be active. If set to zero, means + # "no timeout". The default value is 0 + maximum_timeout = 0 + + # The key to use for the session database (which + # holds the allocated ip's) normally it should + # just be the nas ip/port (which is the default). + # + # If your NAS sends the same value of NAS-Port + # all requests, the key should be based on some + # other attribute that is in ALL requests, AND + # is unique to each machine needing an IP address. +# key = "%{NAS-IP-Address} %{NAS-Port}" +} diff --git a/raddb/mods-available/json b/raddb/mods-available/json new file mode 100644 index 0000000..02a62ae --- /dev/null +++ b/raddb/mods-available/json @@ -0,0 +1,271 @@ +# -*- text -*- +# +# +# $Id$ + +####################################################################### +# +# = JSON Module +# +# The `json` module provides the `json_encode` XLAT, which may be +# used to encode a given list of attributes into different +# formats of JSON object. +# + +# +# ## Configuration Settings +# +json { + + # + # The only options for the JSON module are to control the output + # format of the `json_encode` xlat. + # + encode { + + # + # output_mode:: set the format of JSON documenta + # that should be created. This may be one of: + # + # - object + # - object_simple + # - array + # - array_of_names + # - array_of_values + # + # Examples of each format are given below. + # +# output_mode = object + + # + # ### Formatting options for attribute names + # + attribute { + # + # prefix:: Add a colon-delimited prefix to all + # attribute names in the output document. For example, + # with a prefix of "foo", `User-Name` will be output as + # `foo:User-Name`. + # +# prefix = + } + + # + # ### Formatting options for attribute values + # + value { + + # + # single_value_as_array:: always put values in an array + # + # Output formats will by default put single values as a + # JSON object (string, integer, etc). More than one + # value will, depending on the output format, be added + # as an array. + # + # When this option is enabled, values will always be + # added as an array. + # +# single_value_as_array = no + + # + # enum_as_integer:: output the integer value of + # enumerated attributes + # + # Where an attribute has enum values, the textual + # representation of the value will normally be output. + # Enable this option to force the numeric value + # instead. + # +# enum_as_integer = no + + # + # always_string:: force all values to be strings + # + # Integer values are normally written to the JSON + # document as numbers (i.e. without quotes). Enable + # this option to force all values to be as quoted + # strings. + # +# always_string = no + } + + } + +} + + +# +# ## Expansions +# +# rlm_json provides the below xlat function. +# +# ### %{json_encode:...} +# +# Generates a JSON document from a given list of attribute templates. The +# format of document generated can be controlled with the 'encode' section in +# the module configuration. Attribute values will automatically be escaped so +# they are JSON-safe. +# +# NOTE: The name of the xlat is based on the instance name of this module. If +# the module was defined as `json jdoc {...}`, then the xlat name will be +# `jdoc_encode`. +# +# The xlat should be passed a list of attributes to encode. Each attribute +# (after template expansion) will be added to a list of attributes to include +# in the JSON document. If any of the attributes given are preceeded with a `!` +# then they are removed from the list. Once all attributes have been processed, +# the JSON document will be created using this list. +# +# For example, the following will produce a JSON document with two attributes in +# it, `User-Name` and `Calling-Station-Id`, from the RADIUS request: +# +# .Example +# +# ``` +# %{json_encode:&User-Name &Calling-Station-Id} +# ``` +# +# The following will include all attributes in the RADIUS request, except for +# `User-Password`: +# +# .Example +# +# ``` +# %{json_encode:&request[*] !&User-Password} +# ``` +# +# In another (contrived) example, all the attributes in the RADIUS request will +# be included in the document, _except_ any attributes in the RADIUS reply. +# `&User-Name` will be included from the control list, too, if it exists: +# +# .Example +# +# ``` +# %{json_encode:&request[*] !&reply[*] &control.User-Name} +# ``` +# +# #### Output format modes +# +# There are a number of output modes, each generating a different format of +# JSON document. +# +# NOTE: In the JSON document, "type" is the type of the _attribute_, which is +# not necessarily the same as the type of the "value" in the document. See e.g. +# `Login-Service` above, an enumerated value. +# +# The following examples assume the three attributes are being added to the +# JSON document: +# +# ``` +# User-Name = bob +# Filter-Id = ab +# Filter-Id += cd +# ``` +# +# #### Object output mode examples +# +# These modes output a JSON object. +# +# .Output mode "object" +# +# [source,json] +# ---- +# { +# "User-Name": { +# "type": "string", +# "value": "bob" +# }, +# "Filter-Id": { +# "type": "string", +# "value": ["ab","cd"] +# } +# } +# ---- +# +# .Output mode "object_simple" +# +# [source,json] +# ---- +# { +# "User-Name": "bob", +# "Filter-Id": ["ab","cd"] +# } +# ---- +# +# #### Array output mode examples +# +# The "array" mode is a list of objects, each containing an attribute. If the +# "single_value_as_array" value option is set then each attribute will only +# appear once in the array, and "value" will be a list of all the values from +# the same attribute. +# +# .Output mode "array" +# +# [source,json] +# ---- +# [ +# { +# "name": "User-Name", +# "type": "string", +# "value": "bob" +# }, +# { +# "name": "Filter-Id", +# "type": "string", +# "value": "ab" +# }, +# { +# "name": "Filter-Id", +# "type": "string", +# "value": "cd" +# } +# ] +# ---- +# +# .Output mode "array" when "single_value_as_array" is also set +# +# [source,json] +# ---- +# [ +# { +# "name": "User-Name", +# "type": "string", +# "value": ["bob"] +# }, +# { +# "name": "Filter-Id", +# "type": "string", +# "value": ["ab","cd"] +# } +# ] +# ---- +# +# The following output modes either do not include the attribute names or +# values. They are likely to be useful only when the attributes are +# individually specified and _guaranteed to exist_. In this case the attribute +# names in `array_of_names` will have corresponding indexes to the values in +# `array_of_values`. +# +# .Output mode "array_of_names" +# +# [source,json] +# ---- +# [ +# "User-Name", +# "Filter-Id", +# "Filter-Id" +# ] +# ---- +# +# .Output mode "array_of_values" +# +# [source,json] +# ---- +# [ +# "bob", +# "ab", +# "cd" +# ] +# ---- +# diff --git a/raddb/mods-available/krb5 b/raddb/mods-available/krb5 new file mode 100644 index 0000000..c88b5fb --- /dev/null +++ b/raddb/mods-available/krb5 @@ -0,0 +1,82 @@ +# -*- text -*- +# +# $Id$ + +# +# Kerberos. See doc/modules/rlm_krb5 for minimal docs. +# +krb5 { + # + # The keytab file MUST be owned by the UID/GID used by the server. + # The keytab file MUST be writable by the server. + # The keytab file MUST NOT be readable by other users on the system. + # The keytab file MUST exist before the server is started. + # + keytab = ${localstatedir}/lib/radiusd/keytab + service_principal = name_of_principle + + # Pool of krb5 contexts, this allows us to make the module multithreaded + # and to avoid expensive operations like resolving and opening keytabs + # on every request. It may also allow TCP connections to the KDC to be + # cached if that is supported by the version of libkrb5 used. + # + # The context pool is only used if the underlying libkrb5 reported + # that it was thread safe at compile time. + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # KDC being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The lifetime (in seconds) of the connection + # + # NOTE: A setting of 0 means infinite (no limit). + lifetime = 0 + + # The idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + # + # NOTE: A setting of 0 means infinite (no timeout). + idle_timeout = 0 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/raddb/mods-available/ldap b/raddb/mods-available/ldap new file mode 100644 index 0000000..bc879cc --- /dev/null +++ b/raddb/mods-available/ldap @@ -0,0 +1,694 @@ +# -*- text -*- +# +# $Id$ + +# +# Lightweight Directory Access Protocol (LDAP) +# +ldap { + # Note that this needs to match the name(s) in the LDAP server + # certificate, if you're using ldaps. See OpenLDAP documentation + # for the behavioral semantics of specifying more than one host. + # + # Depending on the libldap in use, server may be an LDAP URI. + # In the case of OpenLDAP this allows additional the following + # additional schemes: + # - ldaps:// (LDAP over SSL) + # - ldapi:// (LDAP over Unix socket) + # - ldapc:// (Connectionless LDAP) + server = 'localhost' +# server = 'ldap.rrdns.example.org' +# server = 'ldap.rrdns.example.org' + + # Port to connect on, defaults to 389, will be ignored for LDAP URIs. +# port = 389 + + # Administrator account for searching and possibly modifying. + # If using SASL + KRB5 these should be commented out. +# identity = 'cn=admin,dc=example,dc=org' +# password = mypass + + # Unless overridden in another section, the dn from which all + # searches will start from. + base_dn = 'dc=example,dc=org' + + # + # You can run the 'ldapsearch' command line tool using the + # parameters from this module's configuration. + # + # ldapsearch -D ${identity} -w ${password} -h ${server} -b 'CN=user,${base_dn}' + # + # That will give you the LDAP information for 'user'. + # + # Group membership can be queried by using the above "ldapsearch" string, + # and adding "memberof" qualifiers. For ActiveDirectory, use: + # + # ldapsearch ... '(&(objectClass=user)(sAMAccountName=user)(memberof=CN=group,${base_dn}))' + # + # Where 'user' is the user as above, and 'group' is the group you are querying for. + # + + # + # SASL parameters to use for admin binds + # + # When we're prompted by the SASL library, these control + # the responses given, as well as the identity and password + # directives above. + # + # If any directive is commented out, a NULL response will be + # provided to cyrus-sasl. + # + # Unfortunately the only way to control Keberos here is through + # environmental variables, as cyrus-sasl provides no API to + # set the krb5 config directly. + # + # Full documentation for MIT krb5 can be found here: + # + # http://web.mit.edu/kerberos/krb5-devel/doc/admin/env_variables.html + # + # At a minimum you probably want to set KRB5_CLIENT_KTNAME. + # + sasl { + # SASL mechanism +# mech = 'PLAIN' + + # SASL authorisation identity to proxy. +# proxy = 'autz_id' + + # SASL realm. Used for kerberos. +# realm = 'example.org' + } + + # + # Generic valuepair attribute + # + + # If set, this will attribute will be retrieved in addition to any + # mapped attributes. + # + # Values should be in the format: + # <radius attr> <op> <value> + # + # Where: + # <radius attr>: Is the attribute you wish to create + # with any valid list and request qualifiers. + # <op>: Is any assignment operator (=, :=, +=, -=). + # <value>: Is the value to parse into the new valuepair. + # If the value is wrapped in double quotes it + # will be xlat expanded. +# valuepair_attribute = 'radiusAttribute' + + # + # Mapping of LDAP directory attributes to RADIUS dictionary attributes. + # + + # WARNING: Although this format is almost identical to the unlang + # update section format, it does *NOT* mean that you can use other + # unlang constructs in module configuration files. + # + # Configuration items are in the format: + # <radius attr> <op> <ldap attr> + # + # Where: + # <radius attr>: Is the destination RADIUS attribute + # with any valid list and request qualifiers. + # <op>: Is any assignment attribute (=, :=, +=, -=). + # <ldap attr>: Is the attribute associated with user or + # profile objects in the LDAP directory. + # If the attribute name is wrapped in double + # quotes it will be xlat expanded. + # + # Request and list qualifiers may also be placed after the 'update' + # section name to set defaults destination requests/lists + # for unqualified RADIUS attributes. + # + # Note: LDAP attribute names should be single quoted unless you want + # the name value to be derived from an xlat expansion, or an + # attribute ref. + update { + control:Password-With-Header += 'userPassword' +# control:NT-Password := 'ntPassword' +# reply:Reply-Message := 'radiusReplyMessage' +# reply:Tunnel-Type := 'radiusTunnelType' +# reply:Tunnel-Medium-Type := 'radiusTunnelMediumType' +# reply:Tunnel-Private-Group-ID := 'radiusTunnelPrivategroupId' + + # Where only a list is specified as the RADIUS attribute, + # the value of the LDAP attribute is parsed as a valuepair + # in the same format as the 'valuepair_attribute' (above). + control: += 'radiusControlAttribute' + request: += 'radiusRequestAttribute' + reply: += 'radiusReplyAttribute' + } + + # Set to yes if you have eDirectory and want to use the universal + # password mechanism. +# edir = no + + # Set to yes if you want to bind as the user after retrieving the + # Cleartext-Password. This will consume the login grace, and + # verify user authorization. +# edir_autz = no + + # LDAP "bind as user" configuration to check PAP passwords. + # + # Active Directory needs "bind as user", which can be done by + # adding the following "if" statement to the authorize {} section + # of the virtual server, after the "ldap" module. For + # example: + # + # ... + # ldap + # if ((ok || updated) && User-Password && !control:Auth-Type) { + # update { + # control:Auth-Type := ldap + # } + # } + # ... + # + # You will also need to uncomment the "Auth-Type LDAP" block in the + # "authenticate" section. + # + # This configuration is required because AD will not return the users + # "known good" password to FreeRADIUS. Instead, FreeRADIUS has to run + # "Auth-Type LDAP" in order to do an LDAP "bind as user", which will hand + # the user name / password to AD for verification. + # + + # + # Name of the attribute that contains the user DN. + # The default name is LDAP-UserDn. + # + # If you have multiple LDAP instances, you should + # change this configuration item to: + # + # ${.:instance}-LDAP-UserDn + # + # That change allows the modules to set their own + # User DN, and to not conflict with each other. + # + user_dn = "LDAP-UserDn" + + # + # User object identification. + # + user { + # Where to start searching in the tree for users + base_dn = "${..base_dn}" + + # Filter for user objects, should be specific enough + # to identify a single user object. + # + # For Active Directory, you should use + # "samaccountname=" instead of "uid=" + # + filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" + + # For Active Directory nested group, you should comment out the previous 'filter = ...' + # and use the below. Where 'group' is the group you are querying for. + # + # NOTE: The string '1.2.840.113556.1.4.1941' specifies LDAP_MATCHING_RULE_IN_CHAIN. + # This applies only to DN attributes. This is an extended match operator that walks + # the chain of ancestry in objects all the way to the root until it finds a match. + # This reveals group nesting. It is available only on domain controllers with + # Windows Server 2003 SP2 or Windows Server 2008 (or above). + # + # See: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx + # +# filter = "(&(objectClass=user)(sAMAccountName=%{%{Stripped-User-Name}:-%{User-Name}})(memberOf:1.2.840.113556.1.4.1941:=cn=group,${..base_dn}))" + + # SASL parameters to use for user binds + # + # When we're prompted by the SASL library, these control + # the responses given. + # + # Any of the config items below may be an attribute ref + # or and expansion, so different SASL mechs, proxy IDs + # and realms may be used for different users. + sasl { + # SASL mechanism +# mech = 'PLAIN' + + # SASL authorisation identity to proxy. +# proxy = &User-Name + + # SASL realm. Used for kerberos. +# realm = 'example.org' + } + + # Search scope, may be 'base', 'one', sub' or 'children' +# scope = 'sub' + + # Server side result sorting + # + # A list of space delimited attributes to order the result + # set by, if the filter matches multiple objects. + # Only the first result in the set will be processed. + # + # If the attribute name is prefixed with a hyphen '-' the + # sorting order will be reversed for that attribute. + # + # If sort_by is set, and the server does not support sorting + # the search will fail. +# sort_by = '-uid' + + # If this is undefined, anyone is authorised. + # If it is defined, the contents of this attribute + # determine whether or not the user is authorised +# access_attribute = 'dialupAccess' + + # Control whether the presence of 'access_attribute' + # allows access, or denys access. + # + # If 'yes', and the access_attribute is present, or + # 'no' and the access_attribute is absent then access + # will be allowed. + # + # If 'yes', and the access_attribute is absent, or + # 'no' and the access_attribute is present, then + # access will not be allowed. + # + # If the value of the access_attribute is 'false', it + # will negate the result. + # + # e.g. + # access_positive = yes + # access_attribute = userAccessAllowed + # + # With an LDAP object containing: + # userAccessAllowed: false + # + # Will result in the user being locked out. +# access_positive = yes + } + + # + # User membership checking. + # + group { + # Where to start searching in the tree for groups + base_dn = "${..base_dn}" + + # Filter for group objects, should match all available + # group objects a user might be a member of. + # + # If using Active Directory you are likely to need "group" + # instead of "posixGroup". + filter = '(objectClass=posixGroup)' + + # Search scope, may be 'base', 'one', sub' or 'children' +# scope = 'sub' + + # Attribute that uniquely identifies a group. + # Is used when converting group DNs to group + # names. +# name_attribute = cn + + # Filter to find all group objects a user is a member of. + # That is, group objects with attributes that + # identify members (the inverse of membership_attribute). + # + # Note that this configuration references the "user_dn" + # configuration defined above. + # +# membership_filter = "(|(member=%{control:${..user_dn}})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))" + + # The attribute, in user objects, which contain the names + # or DNs of groups a user is a member of. + # + # Unless a conversion between group name and group DN is + # needed, there's no requirement for the group objects + # referenced to actually exist. + # + # If the LDAP server does not support the "memberOf" + # attribute (or equivalent), then you will need to use the + # membership_filter option above instead. If you can't see + # the memberOf attribute then it is also possible that the + # LDAP bind user does not have the correct permissions to + # view it. + membership_attribute = 'memberOf' + + # If cacheable_name or cacheable_dn are enabled, + # all group information for the user will be + # retrieved from the directory and written to LDAP-Group + # attributes appropriate for the instance of rlm_ldap. + # + # For group comparisons these attributes will be checked + # instead of querying the LDAP directory directly. + # + # This feature is intended to be used with rlm_cache. + # + # If you wish to use this feature, you should enable + # the type that matches the format of your check items + # i.e. if your groups are specified as DNs then enable + # cacheable_dn else enable cacheable_name. +# cacheable_name = 'no' +# cacheable_dn = 'no' + + # Override the normal cache attribute (<inst>-LDAP-Group or + # LDAP-Group if using the default instance) and create a + # custom attribute. This can help if multiple module instances + # are used in fail-over. +# cache_attribute = 'LDAP-Cached-Membership' + + # If the group being checked is specified as a name, but + # the user's groups are referenced by DN, and one of those + # group DNs is invalid, the whole group check is treated as + # invalid, and a negative result will be returned. + # When set to 'yes', this option ignores invalid DN + # references. +# allow_dangling_group_ref = 'no' + } + + # + # User profiles. RADIUS profile objects contain sets of attributes + # to insert into the request. These attributes are mapped using + # the same mapping scheme applied to user objects (the update section above). + # + profile { + # Filter for RADIUS profile objects +# filter = '(objectclass=radiusprofile)' + + # The default profile. This may be a DN or an attribute + # reference. + # To get old v2.2.x style behaviour, or to use the + # &User-Profile attribute to specify the default profile, + # set this to &control:User-Profile. +# default = 'cn=radprofile,dc=example,dc=org' + + # The LDAP attribute containing profile DNs to apply + # in addition to the default profile above. These are + # retrieved from the user object, at the same time as the + # attributes from the update section, are are applied + # if authorization is successful. +# attribute = 'radiusProfileDn' + } + + # + # Bulk load clients from the directory + # + client { + # Where to start searching in the tree for clients + base_dn = "${..base_dn}" + + # + # Filter to match client objects + # + filter = '(objectClass=radiusClient)' + + # Search scope, may be 'base', 'one', 'sub' or 'children' +# scope = 'sub' + + # + # Sets default values (not obtained from LDAP) for new client entries + # + template { +# login = 'test' +# password = 'test' +# proto = tcp +# require_message_authenticator = yes + + # Uncomment to add a home_server with the same + # attributes as the client. +# coa_server { +# response_window = 2.0 +# } + } + + # + # Client attribute mappings are in the format: + # <client attribute> = <ldap attribute> + # + # The following attributes are required: + # * ipaddr | ipv4addr | ipv6addr - Client IP Address. + # * secret - RADIUS shared secret. + # + # All other attributes usually supported in a client + # definition are also supported here. + # + # Schemas are available in doc/schemas/ldap for openldap and eDirectory + # + attribute { + ipaddr = 'radiusClientIdentifier' + secret = 'radiusClientSecret' +# shortname = 'radiusClientShortname' +# nas_type = 'radiusClientType' +# virtual_server = 'radiusClientVirtualServer' +# require_message_authenticator = 'radiusClientRequireMa' + } + } + + # Load clients on startup +# read_clients = no + + # + # Modify user object on receiving Accounting-Request + # + + # Useful for recording things like the last time the user logged + # in, or the Acct-Session-ID for CoA/DM. + # + # LDAP modification items are in the format: + # <ldap attr> <op> <value> + # + # Where: + # <ldap attr>: The LDAP attribute to add modify or delete. + # <op>: One of the assignment operators: + # (:=, +=, -=, ++). + # Note: '=' is *not* supported. + # <value>: The value to add modify or delete. + # + # WARNING: If using the ':=' operator with a multi-valued LDAP + # attribute, all instances of the attribute will be removed and + # replaced with a single attribute. + accounting { + reference = "%{tolower:type.%{Acct-Status-Type}}" + + type { + start { + update { + description := "Online at %S" + } + } + + interim-update { + update { + description := "Last seen at %S" + } + } + + stop { + update { + description := "Offline at %S" + } + } + } + } + + # + # Post-Auth can modify LDAP objects too + # + post-auth { + update { + description := "Authenticated at %S" + } + } + + # + # LDAP connection-specific options. + # + # These options set timeouts, keep-alives, etc. for the connections. + # + options { + # Control under which situations aliases are followed. + # May be one of 'never', 'searching', 'finding' or 'always' + # default: libldap's default which is usually 'never'. + # + # LDAP_OPT_DEREF is set to this value. +# dereference = 'always' + + # + # The following two configuration items control whether the + # server follows references returned by LDAP directory. + # They are mostly for Active Directory compatibility. + # If you set these to 'no', then searches will likely return + # 'operations error', instead of a useful result. + # + # 'rebind' causes any connections being established to follow + # referrals to be bound using the admin credentials defined + # for this module. If it is set to 'no' libldap will bind + # to those connections anonymously. + # + chase_referrals = yes + rebind = yes + + # SASL Security Properties (see SASL_SECPROPS in ldap.conf man page). + # Note - uncomment when using GSS-API sasl mechanism along with TLS + # encryption against Active-Directory LDAP servers (this disables + # sealing and signing at the GSS level as required by AD). + #sasl_secprops = 'noanonymous,noplain,maxssf=0' + + # Seconds to wait for LDAP query to finish. default: 20 + res_timeout = 10 + + # Seconds LDAP server has to process the query (server-side + # time limit). default: 20 + # + # LDAP_OPT_TIMELIMIT is set to this value. + srv_timelimit = 3 + + # Seconds to wait for response of the server. (network + # failures) default: 10 + # + # LDAP_OPT_NETWORK_TIMEOUT is set to this value. + net_timeout = 1 + + # LDAP_OPT_X_KEEPALIVE_IDLE + idle = 60 + + # LDAP_OPT_X_KEEPALIVE_PROBES + probes = 3 + + # LDAP_OPT_X_KEEPALIVE_INTERVAL + interval = 3 + + # ldap_debug: debug flag for LDAP SDK + # (see OpenLDAP documentation). Set this to enable + # huge amounts of LDAP debugging on the screen. + # You should only use this if you are an LDAP expert. + # + # default: 0x0000 (no debugging messages) + # Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS) + ldap_debug = 0x0028 + } + + # + # This subsection configures the tls related items + # that control how FreeRADIUS connects to an LDAP + # server. It contains all of the 'tls_*' configuration + # entries used in older versions of FreeRADIUS. Those + # configuration entries can still be used, but we recommend + # using these. + # + # Note that some distributions use NSS for libldap instead + # of OpenSSL. + # + # If you see something like this in the debug output: + # + # TLSMC: MozNSS compatibility interception begins. + # + # Then there is a problem. + # + # THIS LDAP INSTALLATION WILL NOT WORK WITH FREERADIUS. + # + # You MUST install fixed LDAP libraries which use OpenSSL. + # + # For more details, see: + # + # http://packages.networkradius.com + # + tls { + # Set this to 'yes' to use TLS encrypted connections + # to the LDAP database by using the StartTLS extended + # operation. + # + # The StartTLS operation is supposed to be + # used with normal ldap connections instead of + # using ldaps (port 636) connections +# start_tls = yes + +# ca_file = ${certdir}/cacert.pem + +# ca_path = ${certdir} +# certificate_file = /path/to/radius.crt +# private_key_file = /path/to/radius.key +# random_file = /dev/urandom + + # Certificate Verification requirements. Can be: + # 'never' (do not even bother trying) + # 'allow' (try, but don't fail if the certificate + # cannot be verified) + # 'demand' (fail if the certificate does not verify) + # 'hard' (similar to 'demand' but fails if TLS + # cannot negotiate) + # + # The default is libldap's default, which varies based + # on the contents of ldap.conf. + +# require_cert = 'demand' + + # + # Minimum TLS version to accept. We STRONGLY recommend + # setting this to "1.2" + # +# tls_min_version = "1.2" + } + + # As of v3, the 'pool' section has replaced the + # following v2 configuration items: + # + # ldap_connections_number + + # + # The connection pool is used to pool outgoing connections. + # + # When the server is not threaded, the connection pool + # limits are ignored, and only one connection is used. + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # directory being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + retry_delay = 30 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # Idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of 'idle_timeout', + # 'uses', or 'lifetime', then the total number of + # connections MAY fall below 'min'. When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the 'min' connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/raddb/mods-available/ldap_google b/raddb/mods-available/ldap_google new file mode 100644 index 0000000..03c98d3 --- /dev/null +++ b/raddb/mods-available/ldap_google @@ -0,0 +1,262 @@ +# -*- text -*- +# +# $Id$ + +# +# This file contains an instance of the ldap module which has been +# configured for the G Suite / Google Workspace Secure LDAP server. +# There are a few steps which still need to be taken, but they are +# documented clearly below. +# +# In order to use the Google LDAP server, a client must first be +# created. See Google's documentation for doing this: +# +# https://support.google.com/a/answer/9048434?hl=en&ref_topic=9173976 +# +# Google LDAP requires that any system connecting to it use a client +# certificate. However, FreeRADIUS also requires a username and +# password in the "ldap" module configuration. Therere before +# downloading the client certificate from Google, you should choose +# the option to generate access credentials in order to obtain a +# username and password. That username and password should be used +# below. +# +# Ensure the Goolge client configuration which is used for FreeRADIUS +# has sufficient permissions to read user information, and, if group +# membership is part of the FreeRADIUS policy, ensure that the client +# can read group information. This configuration is done on Google's +# systems. Please see the Google documentation for more information. +# +# NOTE: The Google LDAP database does NOT return user passwords in +# the search results! +# +# Therefore, if Google LDAP is being used for authentication, it will +# ONLY work when using "LDAP bind as user". The authentication +# method used there MUST also provide the user password in plain +# text. This limits the use of Google LDAP to PAP, and TTLS+PAP. +# Anything else simply will not work, and nothing you do will ever +# make it work. +# +# The Google LDAP service has been observed to have poor +# performance compared to a dedicated / local LDAP server like +# OpenLDAP. In order to improve performance, we simply bypass it +# completely by caching things associated with accept and reject. +# See mods-available/cache_auth for the cache configuration, and +# sites-available/google-ldap-auth for a sample virtual server which +# uses this module, and the cache. +# +# In addition, if you are using Google LDAP service as part of WiFi +# authentication (remember, only TTLS+PAP will work!), then we also +# recommend enabling the "cache" configuration in mods-available/eap. +# That cache is a separate one from mods-available/cache_auth, and +# both caches can be used at the same time. +# +# +# The comments in this file are specific to using the Google Secure +# LDAP service. For more general LDAP module configuration, see the +# mods-available/ldap. +# +ldap ldap_google { + # The standard Google LDAP server URL + server = 'ldaps://ldap.google.com:636/' + + # Google LDAP client username and password as generated during + # client creation. +# identity = 'myuser' +# password = 'mypass' + + # Base dn for your organisation. + base_dn = 'dc=example,dc=org' + + # + # The default Google LDAP schema can be seen here + # + # https://support.google.com/a/answer/9188164 + # + # Custom attributes can be added to user profiles, and those + # custom attributes can then be accessed in the LDAP + # directory: + # + # https://support.google.com/a/answer/6208725 + # + # You can run the 'ldapsearch' command line tool using the + # parameters from this module's configuration. + # + # LDAPTLS_REQCERT=ALLOW \ + # LDAPTLS_CERT="<Google certificate file>" \ + # LDAPTLS_KEY="<Google key file>" \ + # ldapsearch -H ${server} -b '${base_dn}' '(uid=user)' + # + # That command will return the LDAP information for 'user'. + # + # Group membership can be queried by using the above "ldapsearch" string, + # and adding "memberof" qualifiers. + # + +# valuepair_attribute = 'radiusAttribute' + + update { +# reply:Reply-Message := 'radiusReplyMessage' +# reply:Tunnel-Type := 'radiusTunnelType' +# reply:Tunnel-Medium-Type := 'radiusTunnelMediumType' +# reply:Tunnel-Private-Group-ID := 'radiusTunnelPrivategroupId' + + control: += 'radiusControlAttribute' + request: += 'radiusRequestAttribute' + reply: += 'radiusReplyAttribute' + } + + # + # In order to use LDAP "bind as user" authentication, you + # should add following "if" statement to the authorize {} + # section of the virtual server, after the "ldap" module. + # For example: + # + # ... + # ldap_google + # if ((ok || updated) && User-Password && !control:Auth-Type) { + # update { + # &control:Auth-Type := ldap + # } + # } + # ... + # + # You will also need to uncomment the "Auth-Type LDAP" block in the + # "authenticate" section. + # + # Note that these configuration steps have already been done + # in the sample virtual server, in + # sites-available/google-ldap-auth. + # + + # + # If you change this, you will also need to update the + # "cache_ldap_user_dn" module in mods-available/cache_auth. + # + user_dn = "LDAP-UserDn" + + # + # User object identification. + # + user { + # The typical Google LDAP configuration has users under "ou=Users..." + base_dn = "ou=Users,${..base_dn}" + + filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" + + scope = 'sub' + +# sort_by = '-uid' + +# access_attribute = 'dialupAccess' + +# access_positive = yes + } + + # + # User membership checking. + # + group { + # The typical Google LDAP configuration has groups under "ou=Groups..." + base_dn = "ou=Groups,${..base_dn}" + + filter = '(objectClass=posixGroup)' + + scope = 'sub' + + name_attribute = cn + + # + # Google Secure LDAP supports the "memberOf" + # attribute, which is more efficient than using this + # filter. + # + # You should also check the permissions of the client + # in Google's systems to ensure that it is allowed to + # read group information. + # +# membership_filter = "(|(member=%{control:${..user_dn}})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))" + + membership_attribute = 'memberOf' + + # + # If the "memberOf" attribute is used for retrieving group membership, + # then you should also use "cacheable_dn", in orser to cache the group details. + # "memberOf" is a list of fully quallified group DNs which the user belongs to, + # so using the DN for the cache avoids further lookups to retrieve group names. + # +# cacheable_name = 'no' +# cacheable_dn = 'no' + +# cache_attribute = 'LDAP-Cached-Membership' + +# allow_dangling_group_ref = 'no' + } + + options { +# dereference = 'always' + + # Google Secure LDAP does not appear to do referrals, so we might as well + # turn this off. + chase_referrals = no +# rebind = yes + + # Some reasonable defaults for use with Google Secure LDAP + # + # See mods-available/ldap for a complete description + # of what these configuration options mean. + # + res_timeout = 10 + srv_timelimit = 3 + net_timeout = 3 + idle = 60 + probes = 3 + interval = 3 + + ldap_debug = 0x0000 + } + + tls { + + # + # The certificate and key which were downloaded from the Google + # client tools are configured here. + # + # By default ${certdir} is raddb/certs/. You can + # please these files anywhere you want. The only + # requirement is that they are readable by + # FreeRADIUS, and NOT readable by anyone else on the + # system! + # +# certificate_file = ${certdir}/google/certificate.crt +# private_key_file = ${certdir}/google/key.key +# random_file = /dev/urandom + + # + # Google Secure LDAP uses a self signed certificate + # so this configuration needs to be set to 'allow' + # + require_cert = 'allow' + + # + # We recommend not using TLS 1.0 or 1.1. + # +# tls_min_version = "1.2" + } + + # + # See mods-available/ldap for documentation on the "pool" + # section and its configuration items. + # + pool { + start = ${thread[pool].start_servers} + min = ${thread[pool].min_spare_servers} + max = ${thread[pool].max_servers} + spare = ${thread[pool].max_spare_servers} + + uses = 0 + retry_delay = 30 + lifetime = 0 + idle_timeout = 60 + } +} diff --git a/raddb/mods-available/linelog b/raddb/mods-available/linelog new file mode 100644 index 0000000..4357b74 --- /dev/null +++ b/raddb/mods-available/linelog @@ -0,0 +1,164 @@ +# -*- text -*- +# +# $Id$ + +# +# The "linelog" module will log one line of text to a file. +# Both the filename and the line of text are dynamically expanded. +# +# We STRONGLY suggest that you do not use data from the +# packet as part of the filename. +# +linelog { + # + # The file where the logs will go. + # + # If the filename is "syslog", then the log messages will + # go to syslog. + # + # The output can be directed to stdout by using /dev/stdout + # + filename = ${logdir}/linelog + + # + # Most file systems can handly nearly the full range of UTF-8 + # characters. Ones that can deal with a limited range should + # set this to "yes". + # + escape_filenames = no + + # + # The Unix-style permissions on the log file. + # + # Depending on format string, the log file may contain secret or + # private information about users. Keep the file permissions as + # restrictive as possible. + permissions = 0600 + + # The Unix group which owns the log file. + # + # The user that freeradius runs as must be in the specified + # group, otherwise it will not be possible to set the group. +# group = ${security.group} + + # Syslog facility (if logging via syslog). + # Defaults to the syslog_facility config item in radiusd.conf. + # Standard facilities are: + # - kern Messages generated by the kernel. These cannot + # be generated by any user processes. + # - user Messages generated by random user processes. + # This is the default facility identifier if + # none is specified. + # - mail The mail system. + # - daemon System daemons, such as routed(8), that are not + # provided for explicitly by other facilities. + # - auth The authorization system: login(1), su(1), + # getty(8), etc. + # - lpr The line printer spooling system: cups-lpd(8), + # cupsd(8), etc. + # - news The network news system. + # - uucp The uucp system. + # - cron The cron daemon: cron(8). + # - authpriv The same as LOG_AUTH, but logged to a file + # readable only by selected individuals. + # - ftp The file transfer protocol daemons: ftpd(8), + # tftpd(8). + # - local[0-7] Reserved for local use. +# syslog_facility = daemon + + # Syslog severity (if logging via syslog). Defaults to info. + # Possible values are: + # - emergency A panic condition. This is normally broadcast + # to all users. + # - alert A condition that should be corrected immediately, + # such as a corrupted system database. + # - critical Critical conditions, e.g., hard device errors. + # - error Errors. + # - warning Warning messages. + # - notice Conditions that are not error conditions, but + # should possibly be handled specially. + # - info Informational messages. + # - debug Messages that contain information normally of use + # only when debugging a program. +# syslog_severity = info + + # If logging via syslog, the severity can be set here. + # Defaults to info. + # + # The default format string. + format = "This is a log message for %{User-Name}" + + # + # This next line can be omitted. If it is omitted, then + # the log message is static, and is always given by "format", + # above. + # + # If it is defined, then the string is dynamically expanded, + # and the result is used to find another configuration entry + # here, with the given name. That name is then used as the + # format string. + # + # If the configuration entry cannot be found, then no log + # message is printed. + # + # i.e. You can have many log messages in one "linelog" module. + # If this two-step expansion did not exist, you would have + # needed to configure one "linelog" module for each log message. + + # + # Reference the Packet-Type (Access-Accept, etc.) If it doesn't + # exist, reference the "default" entry. + # + # This is for "linelog" being used in the post-auth section + # If you want to use it in "authorize", you need to change + # the reference to "messages.%{%{Packet-Type}:-default}", + # and then add the appropriate messages. + # + reference = "messages.%{%{reply:Packet-Type}:-default}" + + # + # The messages defined here are taken from the "reference" + # expansion, above. + # + messages { + default = "Unknown packet type %{Packet-Type}" + + Access-Accept = "Accepted user: %{User-Name}" + Access-Reject = "Rejected user: %{User-Name}" + Access-Challenge = "Sent challenge: %{User-Name}" + } +} + +# +# Another example, for accounting packets. +# +linelog log_accounting { + # + # Used if the expansion of "reference" fails. + # + format = "" + + filename = ${logdir}/linelog-accounting + + permissions = 0600 + + reference = "Accounting-Request.%{%{Acct-Status-Type}:-unknown}" + + # + # Another example: + # + # + Accounting-Request { + Start = "Connect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address})" + Stop = "Disconnect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address}) %{Acct-Session-Time} seconds" + + # Don't log anything for these packets. + Alive = "" + + Accounting-On = "NAS %{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) just came online" + Accounting-Off = "NAS %{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) just went offline" + + # don't log anything for other Acct-Status-Types. + unknown = "NAS %{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) sent unknown Acct-Status-Type %{Acct-Status-Type}" + } +} diff --git a/raddb/mods-available/logintime b/raddb/mods-available/logintime new file mode 100644 index 0000000..2534452 --- /dev/null +++ b/raddb/mods-available/logintime @@ -0,0 +1,23 @@ +# -*- text -*- +# +# $Id$ + +# The logintime module. This handles the Login-Time, +# Current-Time, and Time-Of-Day attributes. It should be +# included in the *end* of the authorize section in order to +# handle Login-Time checks. It should also be included in the +# instantiate section in order to register the Current-Time +# and Time-Of-Day comparison functions. +# +# When the Login-Time attribute is set to some value, and the +# user has been permitted to log in, a Session-Timeout is +# calculated based on the remaining time. See "doc/README". +# +logintime { + # The minimum timeout (in seconds) a user is allowed + # to have. If the calculated timeout is lower we don't + # allow the login. Some NAS do not handle values + # lower than 60 seconds well. + minimum_timeout = 60 +} + diff --git a/raddb/mods-available/mac2ip b/raddb/mods-available/mac2ip new file mode 100644 index 0000000..a4ead1d --- /dev/null +++ b/raddb/mods-available/mac2ip @@ -0,0 +1,25 @@ +# -*- text -*- +# +# $Id$ + +###################################################################### +# +# This next section is a sample configuration for the "passwd" +# module, that reads flat-text files. +# +# The file is in the format <mac>,<ip> +# +# 00:01:02:03:04:05,192.0.2.100 +# 01:01:02:03:04:05,192.0.2.101 +# 02:01:02:03:04:05,192.0.2.102 +# +# This lets you perform simple static IP assignments from a flat-text +# file. You will have to define lease times yourself. +# +###################################################################### + +passwd mac2ip { + filename = ${modconfdir}/${.:name}/${.:instance} + format = "*DHCP-Client-Hardware-Address:=DHCP-Your-IP-Address" + delimiter = "," +} diff --git a/raddb/mods-available/mac2vlan b/raddb/mods-available/mac2vlan new file mode 100644 index 0000000..a1db803 --- /dev/null +++ b/raddb/mods-available/mac2vlan @@ -0,0 +1,18 @@ +# -*- text -*- +# +# $Id$ + +# A simple file to map a MAC address to a VLAN. +# +# The file should be in the format MAC,VLAN +# the VLAN name cannot have spaces in it, for example: +# +# 00:01:02:03:04:05,VLAN1 +# 03:04:05:06:07:08,VLAN2 +# ... +# +passwd mac2vlan { + filename = ${modconfdir}/${.:name}/${.:instance} + format = "*VMPS-Mac:=VMPS-VLAN-Name" + delimiter = "," +} diff --git a/raddb/mods-available/moonshot-targeted-ids b/raddb/mods-available/moonshot-targeted-ids new file mode 100644 index 0000000..1b27b44 --- /dev/null +++ b/raddb/mods-available/moonshot-targeted-ids @@ -0,0 +1,57 @@ +# -*- text -*- +# +# $Id$ + +# +# Write Moonshot-*-TargetedId (MSTID) to the database. +# +# Schema raddb/mods-config/sql/moonshot-targeted-ids/<DB>/schema.sql +# Queries raddb/mods-config/sql/moonshot-targeted-ids/<DB>/queries.conf +# +sql moonshot_tid_sql { + + # The dialect of SQL you want to use, this should usually match + # the driver below. + # + # If you're using rlm_sql_null, then it should be the type of + # database the logged queries are going to be executed against. + dialect = "sqlite" + + # The sub-module to use to execute queries. This should match + # the database you're attempting to connect to. + # + # There are MSTID queries available for: + # * rlm_sql_mysql + # * rlm_sql_postgresql + # * rlm_sql_sqlite + # * rlm_sql_null (log queries to disk) + # + driver = "rlm_sql_${dialect}" + + sqlite { + filename = ${radacctdir}/moonshot-targeted-ids.sqlite + bootstrap = ${modconfdir}/${..:name}/moonshot-targeted-ids/sqlite/schema.sql + } + + # Write MSTID queries to a logfile. Useful for debugging. +# logfile = ${logdir}/moonshot-targeted-id-log.sql + + pool { + start = 5 + min = 4 + max = 10 + spare = 3 + uses = 0 + lifetime = 0 + idle_timeout = 60 + } + + # If you adjust the table name here, you must also modify the table name in + # the moonshot_get_targeted_id.post-auth policy in policy.d/moonshot-targeted-ids + # and the schema.sql files in the mods-config/sql/moonshot-targeted-ids tree. + # + moonshot_tid_table = "moonshot_targeted_ids" + sql_user_name = "%{User-Name}" + + $INCLUDE ${modconfdir}/${.:name}/moonshot-targeted-ids/${dialect}/queries.conf +} diff --git a/raddb/mods-available/mschap b/raddb/mods-available/mschap new file mode 100644 index 0000000..1748d57 --- /dev/null +++ b/raddb/mods-available/mschap @@ -0,0 +1,253 @@ +# -*- text -*- +# +# $Id$ + +# +# Microsoft CHAP authentication +# +# This module supports MS-CHAP and MS-CHAPv2 authentication. +# It also enforces the SMB-Account-Ctrl attribute. +# +mschap { + # + # If you are using /etc/smbpasswd, see the 'passwd' + # module for an example of how to use /etc/smbpasswd + # + + # + # If use_mppe is not set to no mschap, will + # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and + # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2 + # +# use_mppe = no + + # + # If MPPE is enabled, require_encryption makes + # encryption moderate + # +# require_encryption = yes + + # + # require_strong always requires 128 bit key + # encryption + # +# require_strong = yes + + # + # This module can perform authentication itself, OR + # use a Windows Domain Controller. This configuration + # directive tells the module to call the ntlm_auth + # program, which will do the authentication, and return + # the NT-Key. Note that you MUST have "winbindd" and + # "nmbd" running on the local machine for ntlm_auth + # to work. See the ntlm_auth program documentation + # for details. + # + # If ntlm_auth is configured below, then the mschap + # module will call ntlm_auth for every MS-CHAP + # authentication request. If there is a cleartext + # or NT hashed password available, you can set + # "MS-CHAP-Use-NTLM-Auth := No" in the control items, + # and the mschap module will do the authentication itself, + # without calling ntlm_auth. + # + # Be VERY careful when editing the following line! + # + # You can also try setting the user name as: + # + # ... --username=%{mschap:User-Name} ... + # + # In that case, the mschap module will look at the User-Name + # attribute, and do prefix/suffix checks in order to obtain + # the "best" user name for the request. + # + # For Samba 4, you should also set the "ntlm auth" parameter + # in the Samba configuration: + # + # ntlm auth = yes + # + # or + # + # ntlm auth = mschapv2-and-ntlmv2-only + # + # This will let Samba 4 accept the MS-CHAP authentication + # method that is needed by FreeRADIUS. + # + # Depending on the Samba version, you may also need to add: + # + # --allow-mschapv2 + # + # to the command-line parameters. + # +# ntlm_auth = "/path/to/ntlm_auth --request-nt-key --allow-mschapv2 --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}" + + # + # The default is to wait 10 seconds for ntlm_auth to + # complete. This is a long time, and if it's taking that + # long then you likely have other problems in your domain. + # The length of time can be decreased with the following + # option, which can save clients waiting if your ntlm_auth + # usually finishes quicker. Range 1 to 10 seconds. + # +# ntlm_auth_timeout = 10 + + # + # An alternative to using ntlm_auth is to connect to the + # winbind daemon directly for authentication. This option + # is likely to be faster and may be useful on busy systems, + # but is less well tested. + # + # Using this option requires libwbclient from Samba 4.2.1 + # or later to be installed. Make sure that ntlm_auth above is + # commented out. + # +# winbind_username = "%{mschap:User-Name}" +# winbind_domain = "%{mschap:NT-Domain}" + + # + # When using single sign-on with a winbind connection and the + # client uses a different casing for the username than the + # casing is according to the backend, reauth may fail because + # of some Windows internals. This switch tries to find the + # user in the correct casing in the backend, and retry + # authentication with that username. + # +# winbind_retry_with_normalised_username = no + + # + # Information for the winbind connection pool. The configuration + # items below are the same for all modules which use the new + # connection pool. + # + pool { + # + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # winbind daemon being available. + # + start = ${thread[pool].start_servers} + + # + # Minimum number of connections to keep open + # + min = ${thread[pool].min_spare_servers} + + # + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + # + max = ${thread[pool].max_servers} + + # + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + # + spare = ${thread[pool].max_spare_servers} + + # + # Number of uses before the connection is closed + # + # 0 means "infinite" + # + uses = 0 + + # + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + # + retry_delay = 30 + + # + # The lifetime (in seconds) of the connection + # + # NOTE: A setting of 0 means infinite (no limit). + # + lifetime = 86400 + + # + # The pool is checked for free connections every + # "cleanup_interval". If there are free connections, + # then one of them is closed. + # + cleanup_interval = 300 + + # + # The idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + # + # NOTE: A setting of 0 means infinite (no timeout). + # + idle_timeout = 600 + + # + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + # + } + + passchange { + # + # This support MS-CHAPv2 (not v1) password change + # requests. See doc/mschap.rst for more IMPORTANT + # information. + # + # Samba/ntlm_auth - if you are using ntlm_auth to + # validate passwords, you will need to use ntlm_auth + # to change passwords. Uncomment the three lines + # below, and change the path to ntlm_auth. + # +# ntlm_auth = "/usr/bin/ntlm_auth --helper-protocol=ntlm-change-password-1" +# ntlm_auth_username = "username: %{mschap:User-Name}" +# ntlm_auth_domain = "nt-domain: %{mschap:NT-Domain}" + + # + # To implement a local password change, you need to + # supply a string which is then expanded, so that the + # password can be placed somewhere. e.g. passed to a + # script (exec), or written to SQL (UPDATE/INSERT). + # We give both examples here, but only one will be + # used. + # +# local_cpw = "%{exec:/path/to/script %{mschap:User-Name} %{MS-CHAP-New-Cleartext-Password}}" + # +# local_cpw = "%{sql:UPDATE radcheck set value='%{MS-CHAP-New-NT-Password}' where username='%{SQL-User-Name}' and attribute='NT-Password'}" + } + + # + # For Apple Server, when running on the same machine as + # Open Directory. It has no effect on other systems. + # +# use_open_directory = yes + + # + # On failure, set (or not) the MS-CHAP error code saying + # "retries allowed". + # +# allow_retry = yes + + # + # An optional retry message. + # +# retry_msg = "Re-enter (or reset) the password" +} diff --git a/raddb/mods-available/ntlm_auth b/raddb/mods-available/ntlm_auth new file mode 100644 index 0000000..ab0017c --- /dev/null +++ b/raddb/mods-available/ntlm_auth @@ -0,0 +1,18 @@ +# +# For testing ntlm_auth authentication with PAP. +# +# If you have problems with authentication failing, even when the +# password is good, it may be a bug in Samba: +# +# https://bugzilla.samba.org/show_bug.cgi?id=6563 +# +# Depending on the AD / Samba configuration, you may also need to add: +# +# --allow-mschapv2 +# +# to the list of command-line options. +# +exec ntlm_auth { + wait = yes + program = "/path/to/ntlm_auth --request-nt-key --domain=MYDOMAIN --username=%{mschap:User-Name} --password=%{User-Password}" +} diff --git a/raddb/mods-available/opendirectory b/raddb/mods-available/opendirectory new file mode 100644 index 0000000..443d74d --- /dev/null +++ b/raddb/mods-available/opendirectory @@ -0,0 +1,26 @@ +# -*- text -*- +# +# $Id$ + +# This module is only used when the server is running on the same +# system as OpenDirectory. The configuration of the module is hard-coded +# by Apple, and cannot be changed here. +# +# There are no configuration entries for this module. +# +# The MS-CHAP module will automatically talk to OpenDirectory, if the +# server is built on an OSX machine. However, you must also set +# dsAttrTypeNative:apple-enabled-auth-mech attribute in the +# /config/dirserv OpenDirectory record. You will probably also need +# to change the user passwords in order to re-generate the +# appropriate hashes. +# +# Complete OSX configuration information is available on Apple's web site: +# +# https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf +# +# See also https://discussions.apple.com/thread/6053980?tstart=0 +# +opendirectory { + +} diff --git a/raddb/mods-available/pam b/raddb/mods-available/pam new file mode 100644 index 0000000..f4a91a9 --- /dev/null +++ b/raddb/mods-available/pam @@ -0,0 +1,26 @@ +# -*- text -*- +# +# $Id$ + + +# Pluggable Authentication Modules +# +# For Linux, see: +# http://www.kernel.org/pub/linux/libs/pam/index.html +# +# WARNING: On many systems, the system PAM libraries have +# memory leaks! We STRONGLY SUGGEST that you do not +# use PAM for authentication, due to those memory leaks. +# +pam { + # + # The name to use for PAM authentication. + # PAM looks in /etc/pam.d/${pam_auth_name} + # for it's configuration. See 'redhat/radiusd-pam' + # for a sample PAM configuration file. + # + # Note that any Pam-Auth attribute set in the 'authorize' + # section will over-ride this one. + # + pam_auth = radiusd +} diff --git a/raddb/mods-available/pap b/raddb/mods-available/pap new file mode 100644 index 0000000..0038ecd --- /dev/null +++ b/raddb/mods-available/pap @@ -0,0 +1,18 @@ +# -*- text -*- +# +# $Id$ + +# PAP module to authenticate users based on their stored password +# +# Supports multiple encryption/hash schemes. See "man rlm_pap" +# for details. +# +# For instructions on creating the various types of passwords, see: +# +# http://www.openldap.org/faq/data/cache/347.html +pap { + # By default the server will use heuristics to try and automatically + # handle base64 or hex encoded passwords. This behaviour can be + # stopped by setting the following to "no". +# normalise = yes +} diff --git a/raddb/mods-available/passwd b/raddb/mods-available/passwd new file mode 100644 index 0000000..11bd224 --- /dev/null +++ b/raddb/mods-available/passwd @@ -0,0 +1,55 @@ +# -*- text -*- +# +# $Id$ + +# passwd module allows to do authorization via any passwd-like +# file and to extract any attributes from these files. +# +# See the "smbpasswd" and "etc_group" files for more examples. +# +# parameters are: +# filename - path to file +# +# format - format for filename record. This parameters +# correlates record in the passwd file and RADIUS +# attributes. +# +# Field marked as '*' is a key field. That is, the parameter +# with this name from the request is used to search for +# the record from passwd file +# +# Attributes marked as '=' are added to reply_items instead +# of default configure_items +# +# Attributes marked as '~' are added to request_items +# +# Field marked as ',' may contain a comma separated list +# of attributes. +# +# hash_size - hashtable size. Setting it to 0 is no longer permitted +# A future version of the server will have the module +# automatically determine the hash size. Having it set +# manually should not be necessary. +# +# allow_multiple_keys - if many records for a key are allowed +# +# ignore_nislike - ignore NIS-related records +# +# delimiter - symbol to use as a field separator in passwd file, +# for format ':' symbol is always used. '\0', '\n' are +# not allowed +# + +# An example configuration for using /etc/passwd. +# +# This is an example which will NOT WORK if you have shadow passwords, +# NIS, etc. The "unix" module is normally responsible for reading +# system passwords. You should use it instead of this example. +# +passwd etc_passwd { + filename = /etc/passwd + format = "*User-Name:Crypt-Password:" + hash_size = 100 + ignore_nislike = no + allow_multiple_keys = no +} diff --git a/raddb/mods-available/perl b/raddb/mods-available/perl new file mode 100644 index 0000000..99215b8 --- /dev/null +++ b/raddb/mods-available/perl @@ -0,0 +1,94 @@ +# -*- text -*- +# +# $Id$ + +# Persistent, embedded Perl interpreter. +# +perl { + # + # The Perl script to execute on authorize, authenticate, + # accounting, xlat, etc. This is very similar to using + # 'rlm_exec' module, but it is persistent, and therefore + # faster. + # + filename = ${modconfdir}/${.:instance}/example.pl + + # + # Options which are passed to the Perl interpreter. + # These are (mostly) the same options as are passed + # to the "perl" command line. + # + # The most useful flag is "-T". This sets tainting on, which + # makes it impossible to leverage bad User-Names into local + # command execution. + # + perl_flags = "-T" + + # + # The following hashes are given to the module and + # filled with value-pairs (Attribute names and values) + # + # %RAD_CHECK Check items + # %RAD_REQUEST Attributes from the request + # %RAD_REPLY Attributes for the reply + # %RAD_REQUEST_PROXY Attributes from the proxied request + # %RAD_REQUEST_PROXY_REPLY Attributes from the proxy reply + # + # The interface between FreeRADIUS and Perl is strings. + # That is, attributes of type "octets" are converted to + # printable strings, such as "0xabcdef". If you want to + # access the binary values of the attributes, you should + # call the Perl "pack" function. Then to send any binary + # data back to FreeRADIUS, call the Perl "unpack" function, + # so that the contents of the hashes are printable strings. + # + # IP addresses are sent as strings, e.g. "192.0.2.25", and + # not as a 4-byte binary value. The same applies to other + # attribute data types. + # + # Attributes of type "string" are copied to Perl as-is. + # They are not escaped or interpreted. + # + # The return codes from functions in the perl_script + # are passed directly back to the server. These + # codes are defined in mods-config/example.pl + # + + # You can define configuration items (and nested sub-sections) in perl "config" section. + # These items will be accessible in the perl script through %RAD_PERLCONF hash. + # For instance: $RAD_PERLCONF{'name'} $RAD_PERLCONF{'sub-config'}->{'name'} + # + #config { + # name = "value" + # sub-config { + # name = "value of name from config.sub-config" + # } + #} + + # + # List of functions in the module to call. + # Uncomment and change if you want to use function + # names other than the defaults. + # + #func_authenticate = authenticate + #func_authorize = authorize + #func_preacct = preacct + #func_accounting = accounting + #func_checksimul = checksimul + #func_pre_proxy = pre_proxy + #func_post_proxy = post_proxy + #func_post_auth = post_auth + #func_recv_coa = recv_coa + #func_send_coa = send_coa + #func_xlat = xlat + #func_detach = detach + + # + # Uncomment the following lines if you wish + # to use separate functions for Start and Stop + # accounting packets. In that case, the + # func_accounting function is not called. + # + #func_start_accounting = accounting_start + #func_stop_accounting = accounting_stop +} diff --git a/raddb/mods-available/preprocess b/raddb/mods-available/preprocess new file mode 100644 index 0000000..8baec79 --- /dev/null +++ b/raddb/mods-available/preprocess @@ -0,0 +1,62 @@ +# -*- text -*- +# +# $Id$ + +# Preprocess the incoming RADIUS request, before handing it off +# to other modules. +# +# This module processes the 'huntgroups' and 'hints' files. +# In addition, it re-writes some weird attributes created +# by some NAS, and converts the attributes into a form which +# is a little more standard. +# +preprocess { + # Search for files in a subdirectory of mods-config which + # matches this instance of the preprocess module. + moddir = ${modconfdir}/${.:instance} + + huntgroups = ${moddir}/huntgroups + hints = ${moddir}/hints + + # This hack changes Ascend's weird port numbering + # to standard 0-??? port numbers so that the "+" works + # for IP address assignments. + with_ascend_hack = no + ascend_channels_per_line = 23 + + # Windows NT machines often authenticate themselves as + # NT_DOMAIN\username + # + # If this is set to 'yes', then the NT_DOMAIN portion + # of the user-name is silently discarded. + # + # This configuration entry SHOULD NOT be used. + # See the "realms" module for a better way to handle + # NT domains. + with_ntdomain_hack = no + + # Specialix Jetstream 8500 24 port access server. + # + # If the user name is 10 characters or longer, a "/" + # and the excess characters after the 10th are + # appended to the user name. + # + # If you're not running that NAS, you don't need + # this hack. + with_specialix_jetstream_hack = no + + # Cisco (and Quintum in Cisco mode) sends it's VSA attributes + # with the attribute name *again* in the string, like: + # + # H323-Attribute = "h323-attribute=value". + # + # If this configuration item is set to 'yes', then + # the redundant data in the the attribute text is stripped + # out. The result is: + # + # H323-Attribute = "value" + # + # If you're not running a Cisco or Quintum NAS, you don't + # need this hack. + with_cisco_vsa_hack = no +} diff --git a/raddb/mods-available/python b/raddb/mods-available/python new file mode 100644 index 0000000..371a56d --- /dev/null +++ b/raddb/mods-available/python @@ -0,0 +1,65 @@ +# +# Make sure the PYTHONPATH environmental variable contains the +# directory(s) for the modules listed below. +# +# Uncomment any func_* which are included in your module. If +# rlm_python is called for a section which does not have +# a function defined, it will return NOOP. +# +python { + # Path to the python modules + # + # Note that due to limitations on Python, this configuration + # item is GLOBAL TO THE SERVER. That is, you cannot have two + # instances of the python module, each with a different path. + # +# python_path="${modconfdir}/${.:name}:/path/to/python/files:/another_path/to/python_files/" + + module = example + + # Pass all VPS lists as a 6-tuple to the callbacks + # (request, reply, config, state, proxy_req, proxy_reply) +# pass_all_vps = no + + # Pass all VPS lists as a dictionary to the callbacks + # Keys: "request", "reply", "config", "session-state", "proxy-request", + # "proxy-reply" + # This option prevales over "pass_all_vps" +# pass_all_vps_dict = no + +# mod_instantiate = ${.module} +# func_instantiate = instantiate + +# mod_detach = ${.module} +# func_detach = detach + +# mod_authorize = ${.module} +# func_authorize = authorize + +# mod_authenticate = ${.module} +# func_authenticate = authenticate + +# mod_preacct = ${.module} +# func_preacct = preacct + +# mod_accounting = ${.module} +# func_accounting = accounting + +# mod_checksimul = ${.module} +# func_checksimul = checksimul + +# mod_pre_proxy = ${.module} +# func_pre_proxy = pre_proxy + +# mod_post_proxy = ${.module} +# func_post_proxy = post_proxy + +# mod_post_auth = ${.module} +# func_post_auth = post_auth + +# mod_recv_coa = ${.module} +# func_recv_coa = recv_coa + +# mod_send_coa = ${.module} +# func_send_coa = send_coa +} diff --git a/raddb/mods-available/python3 b/raddb/mods-available/python3 new file mode 100644 index 0000000..f0e0424 --- /dev/null +++ b/raddb/mods-available/python3 @@ -0,0 +1,65 @@ +# +# Make sure the PYTHONPATH environmental variable contains the +# directory(s) for the modules listed below. +# +# Uncomment any func_* which are included in your module. If +# rlm_python is called for a section which does not have +# a function defined, it will return NOOP. +# +python3 { + # Path to the python modules + # + # Note that due to limitations on Python, this configuration + # item is GLOBAL TO THE SERVER. That is, you cannot have two + # instances of the python module, each with a different path. + # +# python_path="${modconfdir}/${.:name}:/another_path/to/python_files" + + module = example + + # Pass all VPS lists as a 6-tuple to the callbacks + # (request, reply, config, state, proxy_req, proxy_reply) +# pass_all_vps = no + + # Pass all VPS lists as a dictionary to the callbacks + # Keys: "request", "reply", "config", "session-state", "proxy-request", + # "proxy-reply" + # This option prevales over "pass_all_vps" +# pass_all_vps_dict = no + +# mod_instantiate = ${.module} +# func_instantiate = instantiate + +# mod_detach = ${.module} +# func_detach = detach + +# mod_authorize = ${.module} +# func_authorize = authorize + +# mod_authenticate = ${.module} +# func_authenticate = authenticate + +# mod_preacct = ${.module} +# func_preacct = preacct + +# mod_accounting = ${.module} +# func_accounting = accounting + +# mod_checksimul = ${.module} +# func_checksimul = checksimul + +# mod_pre_proxy = ${.module} +# func_pre_proxy = pre_proxy + +# mod_post_proxy = ${.module} +# func_post_proxy = post_proxy + +# mod_post_auth = ${.module} +# func_post_auth = post_auth + +# mod_recv_coa = ${.module} +# func_recv_coa = recv_coa + +# mod_send_coa = ${.module} +# func_send_coa = send_coa +} diff --git a/raddb/mods-available/radutmp b/raddb/mods-available/radutmp new file mode 100644 index 0000000..82319c0 --- /dev/null +++ b/raddb/mods-available/radutmp @@ -0,0 +1,53 @@ +# -*- text -*- +# +# $Id$ + +# Write a 'utmp' style file, of which users are currently +# logged in, and where they've logged in from. +# +# This file is used mainly for Simultaneous-Use checking, +# and also 'radwho', to see who's currently logged in. +# +radutmp { + # Where the file is stored. It's not a log file, + # so it doesn't need rotating. + # + filename = ${logdir}/radutmp + + # The field in the packet to key on for the + # 'user' name, If you have other fields which you want + # to use to key on to control Simultaneous-Use, + # then you can use them here. + # + # Note, however, that the size of the field in the + # 'utmp' data structure is small, around 32 + # characters, so that will limit the possible choices + # of keys. + # + # You may want instead: %{%{Stripped-User-Name}:-%{User-Name}} + username = %{User-Name} + + + # Whether or not we want to treat "user" the same + # as "USER", or "User". Some systems have problems + # with case sensitivity, so this should be set to + # 'no' to enable the comparisons of the key attribute + # to be case insensitive. + # + case_sensitive = yes + + # Accounting information may be lost, so the user MAY + # have logged off of the NAS, but we haven't noticed. + # If so, we can verify this information with the NAS, + # + # If we want to believe the 'utmp' file, then this + # configuration entry can be set to 'no'. + # + check_with_nas = yes + + # Set the file permissions, as the contents of this file + # are usually private. + permissions = 0600 + + caller_id = "yes" +} diff --git a/raddb/mods-available/realm b/raddb/mods-available/realm new file mode 100644 index 0000000..947a42d --- /dev/null +++ b/raddb/mods-available/realm @@ -0,0 +1,80 @@ +# -*- text -*- +# +# $Id$ + +# Realm module, for proxying. +# +# You can have multiple instances of the realm module to +# support multiple realm syntaxes at the same time. The +# search order is defined by the order that the modules are listed +# in the authorize and preacct sections. +# +# Four config options: +# format - must be "prefix" or "suffix" +# The special cases of "DEFAULT" +# and "NULL" are allowed, too. +# delimiter - must be a single character + +# +# For dynamic home servers, see doc/configuration/dynamic_home_servers.md, +# and the script in mods-config/realm/freeradius-naptr-to-home-server.sh +# + +# 'realm/username' +# +# Using this entry, IPASS users have their realm set to "IPASS". +realm IPASS { + format = prefix + delimiter = "/" +} + +# 'username@realm' +# +realm suffix { + format = suffix + delimiter = "@" + + # The next configuration items are valid ONLY for a trust-router. + # For all other realms, they are ignored. +# trust_router = "localhost" +# tr_port = 12309 +# rp_realm = "realm.example.com" +# default_community = "apc.communities.example.com" +# # if rekey_enabled is enabled, dynamic realms are automatically rekeyed +# # before they expire to avoid having to recreate them from scrach on +# # demand (implying lengthy authentications) +# rekey_enabled = no +# # if realm_lifetime is > 0, the rekey is scheduled to happen the +# # specified number of seconds after its creation or rekeying. Otherwise, +# # the key material expiration timestamp is used +# realm_lifetime = 0 +} + +# 'realm!username' +# +realm bangpath { + format = prefix + delimiter = "!" + +# trust_router = "localhost" +# tr_port = 12309 +# rp_realm = "realm.example.com" +# default_community = "apc.communities.example.com" +# rekey_enabled = no +# realm_lifetime = 0 +} + +# 'username%realm' +# +realm realmpercent { + format = suffix + delimiter = "%" +} + +# +# 'domain\user' +# +realm ntdomain { + format = prefix + delimiter = "\\" +} diff --git a/raddb/mods-available/redis b/raddb/mods-available/redis new file mode 100644 index 0000000..64789f5 --- /dev/null +++ b/raddb/mods-available/redis @@ -0,0 +1,99 @@ +# -*- text -*- +# +# $Id$ + +# +# Configuration file for the "redis" module. This module does nothing +# Other than provide connections to a redis database, and a %{redis: ...} +# expansion. +# +redis { + # Host where the redis server is located. + # We recommend using ONLY 127.0.0.1 ! + server = 127.0.0.1 + + # Select the Redis logical database having the specified zero-based numeric index. +# database = 0 + + # The default port. + port = 6379 + + # The password used to authenticate to the server. + # We recommend using a strong password. +# password = thisisreallysecretandhardtoguess + + # Set connection and query timeout for rlm_redis + query_timeout = 5 + + # + # Information for the connection pool. The configuration items + # below are the same for all modules which use the new + # connection pool. + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # web service being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + retry_delay = 30 + + # The lifetime (in seconds) of the connection + # + # NOTE: A setting of 0 means infinite (no limit). + lifetime = 86400 + + # The pool is checked for free connections every + # "cleanup_interval". If there are free connections, + # then one of them is closed. + cleanup_interval = 300 + + # The idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + # + # NOTE: A setting of 0 means infinite (no timeout). + idle_timeout = 600 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/raddb/mods-available/rediswho b/raddb/mods-available/rediswho new file mode 100644 index 0000000..d303550 --- /dev/null +++ b/raddb/mods-available/rediswho @@ -0,0 +1,52 @@ +# -*- text -*- +# +# $Id$ + +# +# Configuration file for the "rediswho" module. +# +# This module tracks the last set of login sessions for a user. +# +rediswho { + # REDIS instance to use (from mods-available/redis) + # + # If you have multiple redis instances, such as "redis redis1 {...}", + # use the *instance* name here: redis1. +# redis_module_instance = redis + + # How many sessions to keep track of per user. + # If there are more than this number, older sessions are deleted. + trim_count = 15 + + # Expiry time in seconds. Any sessions which have not received + # an update in this time will be automatically expired. + expire_time = 86400 + + # + # Each subsection contains insert / trim / expire queries. + # The subsections are named after the contents of the + # Acct-Status-Type attribute. See dictionary.rfc2866 for names + # of the various Acct-Status-Type values, or look at the output + # of debug mode. + # + # This module supports *any* Acct-Status-Type. Just add a subsection + # of the appropriate name, along with insert / trim / expire queries. + # + Start { + insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{NAS-IP-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}" + trim = "LTRIM %{User-Name} 0 ${..trim_count}" + expire = "EXPIRE %{User-Name} ${..expire_time}" + } + + Interim-Update { + insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{NAS-IP-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}" + trim = "LTRIM %{User-Name} 0 ${..trim_count}" + expire = "EXPIRE %{User-Name} ${..expire_time}" + } + + Stop { + insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{NAS-IP-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}" + trim = "LTRIM %{User-Name} 0 ${..trim_count}" + expire = "EXPIRE %{User-Name} ${..expire_time}" + } +} diff --git a/raddb/mods-available/replicate b/raddb/mods-available/replicate new file mode 100644 index 0000000..3ba88c1 --- /dev/null +++ b/raddb/mods-available/replicate @@ -0,0 +1,42 @@ +# Replicate packet(s) to a home server. +# +# This module will open a new socket for each packet, and "clone" +# the incoming packet to the destination realm (i.e. home server). +# These packets are only sent to UDP home servers. TCP and TLS +# are not supported. +# +# Use it by setting "Replicate-To-Realm = name" in the control list, +# just like Proxy-To-Realm. The configurations for the two attributes +# are identical. The realm must exist, the home_server_pool must exist, +# and the home_server must exist. +# +# The only difference is that the "replicate" module sends requests +# and does not expect a reply. Any reply is ignored. +# +# Both Replicate-To-Realm and Proxy-To-Realm can be used at the same time. +# +# To use this module, list "replicate" in the "authorize" or +# "accounting" section. Then, ensure that Replicate-To-Realm is set. +# The contents of the "packet" attribute list will be sent to the +# home server. The usual load-balancing, etc. features of the home +# server will be used. +# +# "radmin" can be used to mark home servers alive/dead, in order to +# enable/disable replication to specific servers. +# +# Packets can be replicated to multiple destinations. Just set +# Replicate-To-Realm multiple times. One packet will be sent for +# each of the Replicate-To-Realm attribute in the "control" list. +# +# If no packets are sent, the module returns "noop". If at least one +# packet is sent, the module returns "ok". If an error occurs, the +# module returns "fail" +# +# Note that replication does NOT change any of the packet statistics. +# If you use "radmin" to look at the statistics for a home server, +# the replicated packets will cause NO counters to increment. This +# is not a bug, this is how replication works. +# +replicate { + +} diff --git a/raddb/mods-available/rest b/raddb/mods-available/rest new file mode 100644 index 0000000..2860aa3 --- /dev/null +++ b/raddb/mods-available/rest @@ -0,0 +1,289 @@ +rest { + # + # This subsection configures the tls related items + # that control how FreeRADIUS connects to a HTTPS + # server. + # + tls { + # Certificate Authorities: + # "ca_file" (libcurl option CURLOPT_ISSUERCERT). + # File containing a single CA, which is the issuer of the server + # certificate. + # "ca_info_file" (libcurl option CURLOPT_CAINFO). + # File containing a bundle of certificates, which allow to handle + # certificate chain validation. + # "ca_path" (libcurl option CURLOPT_CAPATH). + # Directory holding CA certificates to verify the peer with. +# ca_file = ${certdir}/cacert.pem +# ca_info_file = ${certdir}/cacert_bundle.pem +# ca_path = ${certdir} + +# certificate_file = /path/to/radius.crt +# private_key_file = /path/to/radius.key +# private_key_password = "supersecret" +# random_file = /dev/urandom + + # Server certificate verification requirements. Can be: + # "no" (don't even bother trying) + # "yes" (verify the cert was issued by one of the + # trusted CAs) + # + # The default is "yes" +# check_cert = yes + + # Server certificate CN verification requirements. Can be: + # "no" (don't even bother trying) + # "yes" (verify the CN in the certificate matches the host + # in the URI) + # + # The default is "yes" +# check_cert_cn = yes + } + + # rlm_rest will open a connection to the server specified in connect_uri + # to populate the connection cache, ready for the first request. + # The server will not start if the server specified is unreachable. + # + # If you wish to disable this pre-caching and reachability check, + # comment out the configuration item below. + connect_uri = "http://127.0.0.1/" + + # + # How long before new connection attempts timeout, defaults to 4.0 seconds. + # +# connect_timeout = 4.0 + + # + # Specify HTTP protocol version to use. one of '1.0', '1.1', '2.0', '2.0+auto', + # '2.0+tls' or 'default'. (libcurl option CURLOPT_HTTP_VERSION) + # +# http_negotiation = 1.1 + + # + # The following config items can be used in each of the sections. + # The sections themselves reflect the sections in the server. + # For example if you list rest in the authorize section of a virtual server, + # the settings from the authorize section here will be used. + # + # The following config items may be listed in any of the sections: + # uri - to send the request to. + # method - HTTP method to use, one of 'get', 'post', 'put', 'patch', + # 'delete' or any custom HTTP method. + # body - The format of the HTTP body sent to the remote server. + # May be 'none', 'post' or 'json', defaults to 'none'. + # attr_num - If true, the attribute number is supplied for each attribute. + # Defaults to false. + # raw_value - If true, enumerated attribute values are provided as numeric + # values. Defaults to false. + # data - Send custom freeform data in the HTTP body. Content-type + # may be specified with 'body'. Will be expanded. + # Values from expansion will not be escaped, this should be + # done using the appropriate xlat method e.g. %{urlencode:<attr>}. + # force_to - Force the response to be decoded with this decoder. + # May be 'plain' (creates reply:REST-HTTP-Body), 'post' + # or 'json'. + # tls - TLS settings for HTTPS. + # auth - HTTP auth method to use, one of 'none', 'srp', 'basic', + # 'digest', 'digest-ie', 'gss-negotiate', 'ntlm', + # 'ntlm-winbind', 'any', 'safe'. defaults to 'none'. + # username - User to authenticate as, will be expanded. + # password - Password to use for authentication, will be expanded. + # require_auth - Require HTTP authentication. + # timeout - HTTP request timeout in seconds, defaults to 4.0. + # chunk - Chunk size to use. If set, HTTP chunked encoding is used to + # send data to the REST server. Make sure that this is large + # enough to fit your largest attribute value's text + # representation. + # A number like 8192 is good. + # + # Additional HTTP headers may be specified with control:REST-HTTP-Header. + # The values of those attributes should be in the format: + # + # control:REST-HTTP-Header := "<HTTP attribute>: <value>" + # + # The control:REST-HTTP-Header attributes will be consumed + # (i.e. deleted) after each call to the rest module, and each + # %{rest:} expansion. This is so that headers from one REST + # call do not affect headers from a different REST call. + # + # Body encodings are the same for requests and responses + # + # POST - All attributes and values are urlencoded + # [outer.][<list>:]<attribute0>=<value0>&[outer.][<list>:]<attributeN>=<valueN> + # + # JSON - All attributes and values are escaped according to the JSON specification + # - attribute Name of the attribute. + # - attr_num Number of the attribute. Only available if the configuration item + # 'attr_num' is enabled. + # - type Type of the attribute (e.g. "integer", "string", "ipaddr", "octets", ...). + # - value Attribute value, for enumerated attributes the human readable value is + # provided and not the numeric value (Depends on the 'raw_value' config item). + # { + # "<attribute0>":{ + # "attr_num":<attr_num0>, + # "type":"<type0>", + # "value":[<value0>,<value1>,<valueN>] + # }, + # "<attribute1>":{ + # "attr_num":<attr_num1>, + # "type":"<type1>", + # "value":[...] + # }, + # "<attributeN>":{ + # "attr_num":<attr_numN>, + # "type":"<typeN>", + # "value":[...] + # }, + # } + # + # The response format adds three optional fields: + # - do_xlat If true, any values will be xlat expanded. Defaults to true. + # - is_json If true, any nested JSON data will be copied to the attribute + # in string form. Defaults to true. + # - op Controls how the attribute is inserted into the target list. + # Defaults to ':='. To create multiple attributes from multiple + # values, this should be set to '+=', otherwise only the last + # value will be used, and it will be assigned to a single + # attribute. + # { + # "<attribute0>":{ + # "is_json":<bool>, + # "do_xlat":<bool>, + # "op":"<operator>", + # "value":[<value0>,<value1>,<valueN>] + # }, + # "<attribute1>":"value", + # "<attributeN>":{ + # "value":[<value0>,<value1>,<valueN>], + # "op":"+=" + # } + # } + + # + # Module return codes are determined by HTTP response codes. These vary depending on the + # section. + # + # If the body is processed and found to be malformed or unsupported fail will be returned. + # If the body is processed and found to contain attribute updated will be returned, + # except in the case of a 401 code. + # + + # Authorize/Authenticate + # + # Code Meaning Process body Module code + # 404 not found no notfound + # 410 gone no notfound + # 403 forbidden no userlock + # 401 unauthorized yes reject + # 204 no content no ok + # 2xx successful yes ok/updated + # 5xx server error no fail + # xxx - no invalid + # + # The status code is held in %{reply:REST-HTTP-Status-Code}. + # + authorize { + uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=authorize" + method = 'get' + tls = ${..tls} + } + authenticate { + uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=authenticate" + method = 'get' + tls = ${..tls} + } + + # Preacct/Accounting/Post-auth/Pre-Proxy/Post-Proxy + # + # Code Meaning Process body Module code + # 204 no content no ok + # 2xx successful yes ok/updated + # 5xx server error no fail + # xxx - no invalid + preacct { + uri = "${..connect_uri}/user/%{User-Name}/sessions/%{Acct-Unique-Session-ID}?action=preacct" + method = 'post' + tls = ${..tls} + } + accounting { + uri = "${..connect_uri}/user/%{User-Name}/sessions/%{Acct-Unique-Session-ID}?action=accounting" + method = 'post' + tls = ${..tls} + } + post-auth { + uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=post-auth" + method = 'post' + tls = ${..tls} + } + pre-proxy { + uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=pre-proxy" + method = 'post' + tls = ${..tls} + } + post-proxy { + uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=post-proxy" + method = 'post' + tls = ${..tls} + } + + # + # The connection pool is used to pool outgoing connections. + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # web service being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + retry_delay = 30 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/raddb/mods-available/smbpasswd b/raddb/mods-available/smbpasswd new file mode 100644 index 0000000..d5ad2a0 --- /dev/null +++ b/raddb/mods-available/smbpasswd @@ -0,0 +1,16 @@ +# -*- text -*- +# +# $Id$ + +# An example configuration for using /etc/smbpasswd. +# +# See the "passwd" file for documentation on the configuration items +# for this module. +# +passwd smbpasswd { + filename = /etc/smbpasswd + format = "*User-Name::LM-Password:NT-Password:SMB-Account-CTRL-TEXT::" + hash_size = 100 + ignore_nislike = no + allow_multiple_keys = no +} diff --git a/raddb/mods-available/smsotp b/raddb/mods-available/smsotp new file mode 100644 index 0000000..3be32b8 --- /dev/null +++ b/raddb/mods-available/smsotp @@ -0,0 +1,94 @@ +# -*- text -*- +# +# $Id$ + +# SMS One-time Password system. +# +# This module will extend FreeRadius with a socks interface to create and +# validate One-Time-Passwords. The program for that creates the socket +# and interacts with this module is not included here. +# +# The module does not check the User-Password, this should be done with +# the "pap" module. See the example below. +# +# The module must be used in the "authorize" section to set +# Auth-Type properly. The first time through, the module is called +# in the "authenticate" section to authenticate the user password, and +# to send the challenge. The second time through, it authenticates +# the response to the challenge. e.g.: +# +# authorize { +# ... +# smsotp +# ... +# } +# +# authenticate { +# ... +# Auth-Type smsotp { +# pap +# smsotp +# } +# +# Auth-Type smsotp-reply { +# smsotp +# } +# ... +# } +# +smsotp { + # The location of the socket. + socket = "/var/run/smsotp_socket" + + # Defines the challenge message that will be send to the + # NAS. Default is "Enter Mobile PIN" } + challenge_message = "Enter Mobile PIN:" + + # Defines the Auth-Type section that is run for the response to + # the challenge. Default is "smsotp-reply". + challenge_type = "smsotp-reply" + + # Control how many sockets are used to talk to the SMSOTPd + # + pool { + # Number of connections to start + start = 5 + + # Minimum number of connections to keep open + min = 4 + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + max = 10 + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. + spare = 3 + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/raddb/mods-available/soh b/raddb/mods-available/soh new file mode 100644 index 0000000..d125ce4 --- /dev/null +++ b/raddb/mods-available/soh @@ -0,0 +1,4 @@ +# SoH module +soh { + dhcp = yes +} diff --git a/raddb/mods-available/sometimes b/raddb/mods-available/sometimes new file mode 100644 index 0000000..3a96622 --- /dev/null +++ b/raddb/mods-available/sometimes @@ -0,0 +1,12 @@ +# -*- text -*- +# +# $Id$ + +# +# The "sometimes" module is here for debugging purposes. Each instance +# randomly returns the configured result, or "noop". +# +# It is based on the "always" module. +sometimes { + rcode = fail +} diff --git a/raddb/mods-available/sql b/raddb/mods-available/sql new file mode 100644 index 0000000..7bcb664 --- /dev/null +++ b/raddb/mods-available/sql @@ -0,0 +1,371 @@ +# -*- text -*- +## +## mods-available/sql -- SQL modules +## +## $Id$ + +###################################################################### +# +# Configuration for the SQL module +# +# The database schemas and queries are located in subdirectories: +# +# sql/<DB>/main/schema.sql Schema +# sql/<DB>/main/queries.conf Authorisation and Accounting queries +# +# Where "DB" is mysql, mssql, oracle, or postgresql. +# +# The name used to query SQL is sql_user_name, which is set in the file +# +# raddb/mods-config/sql/main/${dialect}/queries.conf +# +# If you are using realms, that configuration should be changed to use +# the Stripped-User-Name attribute. See the comments around sql_user_name +# for more information. +# + +sql { + # + # The dialect of SQL being used. + # + # Allowed dialects are: + # + # mssql + # mysql + # oracle + # postgresql + # sqlite + # mongo + # + dialect = "sqlite" + + # + # The driver module used to execute the queries. Since we + # don't know which SQL drivers are being used, the default is + # "rlm_sql_null", which just logs the queries to disk via the + # "logfile" directive, below. + # + # In order to talk to a real database, delete the next line, + # and uncomment the one after it. + # + # If the dialect is "mssql", then the driver should be set to + # one of the following values, depending on your system: + # + # rlm_sql_db2 + # rlm_sql_firebird + # rlm_sql_freetds + # rlm_sql_iodbc + # rlm_sql_unixodbc + # + driver = "rlm_sql_null" +# driver = "rlm_sql_${dialect}" + + # + # Driver-specific subsections. They will only be loaded and + # used if "driver" is something other than "rlm_sql_null". + # When a real driver is used, the relevant driver + # configuration section is loaded, and all other driver + # configuration sections are ignored. + # + sqlite { + # Path to the sqlite database + filename = "/tmp/freeradius.db" + + # How long to wait for write locks on the database to be + # released (in ms) before giving up. + busy_timeout = 200 + + # If the file above does not exist and bootstrap is set + # a new database file will be created, and the SQL statements + # contained within the bootstrap file will be executed. + bootstrap = "${modconfdir}/${..:name}/main/sqlite/schema.sql" + } + + mysql { + # If any of the files below are set, TLS encryption is enabled + tls { + ca_file = "/etc/ssl/certs/my_ca.crt" + ca_path = "/etc/ssl/certs/" + certificate_file = "/etc/ssl/certs/private/client.crt" + private_key_file = "/etc/ssl/certs/private/client.key" + cipher = "DHE-RSA-AES256-SHA:AES128-SHA" + + tls_required = yes + tls_check_cert = no + tls_check_cert_cn = no + } + + # If yes, (or auto and libmysqlclient reports warnings are + # available), will retrieve and log additional warnings from + # the server if an error has occured. Defaults to 'auto' + warnings = auto + } + + postgresql { + + # unlike MySQL, which has a tls{} connection configuration, postgresql + # uses its connection parameters - see the radius_db option below in + # this file + + # Send application_name to the postgres server + # Only supported in PG 9.0 and greater. Defaults to no. + send_application_name = yes + + # + # The default application name is "FreeRADIUS - .." with the current version. + # The application name can be customized here to any non-zero value. + # +# application_name = "" + } + + # + # Configuration for Mongo. + # + # Note that the Mongo driver is experimental. The FreeRADIUS developers + # are unable to help with the syntax of the Mongo queries. Please see + # the Mongo documentation for that syntax. + # + # The Mongo driver supports only the following methods: + # + # aggregate + # findAndModify + # findOne + # insert + # + # For examples, see the query files: + # + # raddb/mods-config/sql/main/mongo/queries.conf + # raddb/mods-config/sql/main/ippool/queries.conf + # + # In order to use findAndModify with an aggretation pipleline, make + # sure that you are running MongoDB version 4.2 or greater. FreeRADIUS + # assumes that the paramaters passed to the methods are supported by the + # version of MongoDB which it is connected to. + # + mongo { + # + # The application name to use. + # + appname = "freeradius" + + # + # The TLS parameters here map directly to the Mongo TLS configuration + # + tls { + certificate_file = /path/to/file + certificate_password = "password" + ca_file = /path/to/file + ca_dir = /path/to/directory + crl_file = /path/to/file + weak_cert_validation = false + allow_invalid_hostname = false + } + } + + # Connection info: + # +# server = "localhost" +# port = 3306 +# login = "radius" +# password = "radpass" + + # Connection info for Mongo + # Authentication Without SSL + # server = "mongodb://USER:PASSWORD@192.16.0.2:PORT/DATABASE?authSource=admin&ssl=false" + + # Authentication With SSL + # server = "mongodb://USER:PASSWORD@192.16.0.2:PORT/DATABASE?authSource=admin&ssl=true" + + # Authentication with Certificate + # Use this command for retrieve Derived username: + # openssl x509 -in mycert.pem -inform PEM -subject -nameopt RFC2253 + # server = mongodb://<DERIVED USERNAME>@192.168.0.2:PORT/DATABASE?authSource=$external&ssl=true&authMechanism=MONGODB-X509 + + # Database table configuration for everything except Oracle + radius_db = "radius" + + # If you are using Oracle then use this instead +# radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))" + + # If you're using postgresql this can also be used instead of the connection info parameters +# radius_db = "dbname=radius host=localhost user=radius password=raddpass" + + # Postgreql doesn't take tls{} options in its module config like mysql does - if you want to + # use SSL connections then use this form of connection info parameter +# radius_db = "host=localhost port=5432 dbname=radius user=radius password=raddpass sslmode=verify-full sslcert=/etc/ssl/client.crt sslkey=/etc/ssl/client.key sslrootcert=/etc/ssl/ca.crt" + + # If you want both stop and start records logged to the + # same SQL table, leave this as is. If you want them in + # different tables, put the start table in acct_table1 + # and stop table in acct_table2 + acct_table1 = "radacct" + acct_table2 = "radacct" + + # Allow for storing data after authentication + postauth_table = "radpostauth" + + # Tables containing 'check' items + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + + # Tables containing 'reply' items + authreply_table = "radreply" + groupreply_table = "radgroupreply" + + # Table to keep group info + usergroup_table = "radusergroup" + + # If set to 'yes' (default) we read the group tables unless Fall-Through = no in the reply table. + # If set to 'no' we do not read the group tables unless Fall-Through = yes in the reply table. +# read_groups = yes + + # If set to 'yes' (default) we read profiles unless Fall-Through = no in the groupreply table. + # If set to 'no' we do not read profiles unless Fall-Through = yes in the groupreply table. +# read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + # Write SQL queries to a logfile. This is potentially useful for tracing + # issues with authorization queries. See also "logfile" directives in + # mods-config/sql/main/*/queries.conf. You can enable per-section logging + # by enabling "logfile" there, or global logging by enabling "logfile" here. + # + # Per-section logging can be disabled by setting "logfile = ''" +# logfile = ${logdir}/sqllog.sql + + # Set the maximum query duration and connection timeout + # for rlm_sql_mysql. +# query_timeout = 5 + + # As of v3, the "pool" section has replaced the + # following v2 configuration items: + # + # num_sql_socks + # connect_failure_retry_delay + # lifetime + # max_queries + + # + # The connection pool is used to pool outgoing connections. + # + # When the server is not threaded, the connection pool + # limits are ignored, and only one connection is used. + # + # If you want to have multiple SQL modules re-use the same + # connection pool, use "pool = name" instead of a "pool" + # section. e.g. + # + # sql sql1 { + # ... + # pool { + # ... + # } + # } + # + # # sql2 will use the connection pool from sql1 + # sql sql2 { + # ... + # pool = sql1 + # } + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # database being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + retry_delay = 30 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. + # + # A client can be link to a virtual server via the SQL + # module. This link is done via the following process: + # + # If there is no listener in a virtual server, SQL clients + # are added to the global list for that virtual server. + # + # If there is a listener, and the first listener does not + # have a "clients=..." configuration item, SQL clients are + # added to the global list. + # + # If there is a listener, and the first one does have a + # "clients=..." configuration item, SQL clients are added to + # that list. The client { ...} ` configured in that list are + # also added for that listener. + # + # The only issue is if you have multiple listeners in a + # virtual server, each with a different client list, then + # the SQL clients are added only to the first listener. + # +# read_clients = yes + + # Table to keep radius client info + client_table = "nas" + + # + # The group attribute specific to this instance of rlm_sql + # + + # This entry should be used for additional instances (sql foo {}) + # of the SQL module. +# group_attribute = "${.:instance}-SQL-Group" + + # This entry should be used for the default instance (sql {}) + # of the SQL module. + group_attribute = "SQL-Group" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} diff --git a/raddb/mods-available/sql_map b/raddb/mods-available/sql_map new file mode 100644 index 0000000..93b2636 --- /dev/null +++ b/raddb/mods-available/sql_map @@ -0,0 +1,49 @@ +# Configuration for the SQL based Map (rlm_sql_map) +sql_map { + # SQL instance to use (from mods-available/sql) + # + # If you have multiple sql instances, such as "sql sql1 {...}", + # use the *instance* name here: sql1. + sql_module_instance = "sql" + + # This is duplicative of info available in the SQL module, but + # we have to list it here as we do not yet support nested + # reference expansions. + dialect = "mysql" + + # Name of the check item attribute to be used as a key in the SQL queries + query = "SELECT ... FROM ... " + + # + # Mapping of SQL columns to RADIUS dictionary attributes. + # + + # WARNING: Although this format is almost identical to the unlang + # update section format, it does *NOT* mean that you can use other + # unlang constructs in module configuration files. + # + # Configuration items are in the format: + # <radius attr> <op> <sql column number> + # + # Where: + # <radius attr>: Is the destination RADIUS attribute + # with any valid list and request qualifiers. + # <op>: Is any assignment attribute (=, :=, +=, -=). + # <column num>: The column number (not name), starting from 0 + # + # Request and list qualifiers may also be placed after the 'update' + # section name to set defaults destination requests/lists + # for unqualified RADIUS attributes. + # + update { + control:Password-With-Header += 0 +# control:NT-Password := 1 +# reply:Reply-Message := 2 +# reply:Tunnel-Type := 3 +# reply:Tunnel-Medium-Type := 4 +# reply:Tunnel-Private-Group-ID := 5 + } + + # If the 'query' results in multiple rows, it creates the <radius attr>[*] array entry. +# multiple_rows = yes +} diff --git a/raddb/mods-available/sqlcounter b/raddb/mods-available/sqlcounter new file mode 100644 index 0000000..a2b206e --- /dev/null +++ b/raddb/mods-available/sqlcounter @@ -0,0 +1,122 @@ +# Rather than maintaining separate (GDBM) databases of +# accounting info for each counter, this module uses the data +# stored in the raddacct table by the sql modules. This +# module NEVER does any database INSERTs or UPDATEs. It is +# totally dependent on the SQL module to process Accounting +# packets. +# +# The sql-module-instance' parameter holds the instance of the sql +# module to use when querying the SQL database. Normally it +# is just "sql". If you define more and one SQL module +# instance (usually for failover situations), you can +# specify which module has access to the Accounting Data +# (radacct table). +# +# The 'reset' parameter defines when the counters are all +# reset to zero. It can be hourly, daily, weekly, monthly or +# never. It can also be user defined. It should be of the +# form: +# num[hdwm] where: +# h: hours, d: days, w: weeks, m: months +# If the letter is ommited days will be assumed. In example: +# reset = 10h (reset every 10 hours) +# reset = 12 (reset every 12 days) +# +# The 'reset_day' parameter defines which day of the month the +# 'monthly' counter should be reset; valid values are 1 to 28. +# +# The 'key' parameter specifies the unique identifier for the +# counter records (usually 'User-Name'). +# +# The 'query' parameter specifies the SQL query used to get +# the current Counter value from the database. There are four +# parameters that can be used in the query: +# +# %%b unix time value of beginning of reset period. +# %%e unix time value of end of reset period. +# %%k value of 'key' parameter. +# %%r day of month the counter should be reset. +# +# The 'check_name' parameter is the name of the 'check' +# attribute to use to access the counter in the 'users' file +# or SQL radcheck or radgroupcheck tables. +# +# DEFAULT Max-Daily-Session > 3600, Auth-Type = Reject +# Reply-Message = "You've used up more than one hour today" +# +# The "dailycounter" (or any other sqlcounter module) should be added +# to "post-auth" section. It will then update the Session-Timeout +# attribute in the reply. If there is no Session-Timeout attribute, +# the module will add one. If there is an attribute, the sqlcounter +# module will make sure that the value is no higher than the limit. +# +sqlcounter dailycounter { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + + counter_name = Daily-Session-Time + check_name = Max-Daily-Session + reply_name = Session-Timeout + + key = User-Name + reset = daily + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf +} + +sqlcounter weeklycounter { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + + counter_name = Weekly-Session-Time + check_name = Max-Weekly-Session + reply_name = Session-Timeout + + key = User-Name + reset = weekly + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf +} + +sqlcounter monthlycounter { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + + counter_name = Monthly-Session-Time + check_name = Max-Monthly-Session + reply_name = Session-Timeout + key = User-Name + reset = monthly + reset_day = 1 + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf +} + +sqlcounter noresetcounter { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + + counter_name = Max-All-Session-Time + check_name = Max-All-Session + key = User-Name + reset = never + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf +} + +# +# Set an account to expire T seconds after first login. +# Requires the Expire-After attribute to be set, in seconds. +# You may need to edit raddb/dictionary to add the Expire-After +# attribute. +sqlcounter expire_on_login { + sql_module_instance = sql + dialect = ${modules.sql.dialect} + + counter_name = Expire-After-Initial-Login + check_name = Expire-After + key = User-Name + reset = never + + $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf +} diff --git a/raddb/mods-available/sqlippool b/raddb/mods-available/sqlippool new file mode 100644 index 0000000..f17a989 --- /dev/null +++ b/raddb/mods-available/sqlippool @@ -0,0 +1,109 @@ +# Configuration for the SQL based IP Pool module (rlm_sqlippool) +# +# The database schemas are available at: +# +# raddb/mods-config/sql/ippool/<DB>/schema.sql +# +# $Id$ + +sqlippool { + # SQL instance to use (from mods-available/sql) + # + # If you have multiple sql instances, such as "sql sql1 {...}", + # use the *instance* name here: sql1. + sql_module_instance = "sql" + + # This is duplicative of info available in the SQL module, but + # we have to list it here as we do not yet support nested + # reference expansions. + dialect = "mysql" + + # Name of the check item attribute to be used as a key in the SQL queries + pool_name = "Pool-Name" + + # SQL table to use for ippool range and lease info + ippool_table = "radippool" + + # IP lease duration. (Leases expire even if Acct Stop packet is lost) + # + # Note that you SHOULD also set Session-Timeout to this value! + # That way the NAS will automatically kick the user offline when the + # lease expires. + # + lease_duration = 3600 + + # + # Timeout between each consecutive 'allocate_clear' queries (default: 1s) + # This will avoid having too many deadlock issues, especially on MySQL backend. + # + allocate_clear_timeout = 1 + + # + # The attribute to use for IP address assignment. The + # default is Framed-IP-Address. You can change this to any + # attribute which is IPv4 or IPv6. + # + # e.g. Framed-IPv6-Prefix, or Delegated-IPv6-Prefix. + # + # All of the default queries use this attribute_name. So you + # can do IPv6 address assignment simply by putting IPv6 + # addresses into the pool, and changing the following line to + # "Framed-IPv6-Prefix" + # + # Note that you MUST use separate pools for each attribute. i.e. one pool + # for Framed-IP-Address, a different one for Framed-IPv6-prefix, etc. + # + # This means configuring separate "sqlippool" instances, and different + # "ippool_table" in SQL. Then, populate the pool with addresses and + # it will all just work. + # + attribute_name = Framed-IP-Address + + # + # Assign the IP address, even if the above attribute already exists + # in the reply. + # +# allow_duplicates = no + + # The attribute in which an IP address hint may be supplied + req_attribute_name = Framed-IP-Address + + # Attribute which should be considered unique per NAS + # + # Using NAS-Port gives behaviour similar to rlm_ippool. (And ACS) + # Using Calling-Station-Id works for NAS that send fixed NAS-Port + # ONLY change this if you know what you are doing! + pool_key = "%{NAS-Port}" + # pool_key = "%{Calling-Station-Id}" + + ################################################################ + # + # WARNING: MySQL (MyISAM) has certain limitations that means it can + # hand out the same IP address to 2 different users. + # + # We suggest using an SQL DB with proper transaction + # support, such as PostgreSQL, or using MySQL + # with InnoDB. + # + ################################################################ + + # These messages are added to the "control" items, as + # Module-Success-Message. They are not logged anywhere else, + # unlike previous versions. If you want to have them logged + # to a file, see the "linelog" module, and create an entry + # which writes Module-Success-Message message. + # + messages { + exists = "Existing IP: %{reply:${..attribute_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" + + success = "Allocated IP: %{reply:${..attribute_name}} from %{control:${..pool_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" + + clear = "Released IP %{request:${..attribute_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})" + + failed = "IP Allocation FAILED from %{control:${..pool_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" + + nopool = "No ${..pool_name} defined (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" + } + + $INCLUDE ${modconfdir}/sql/ippool/${dialect}/queries.conf +} diff --git a/raddb/mods-available/sradutmp b/raddb/mods-available/sradutmp new file mode 100644 index 0000000..3a2a0e5 --- /dev/null +++ b/raddb/mods-available/sradutmp @@ -0,0 +1,16 @@ +# -*- text -*- +# +# $Id$ + +# "Safe" radutmp - does not contain caller ID, so it can be +# world-readable, and radwho can work for normal users, without +# exposing any information that isn't already exposed by who(1). +# +# This is another 'instance' of the radutmp module, but it is given +# then name "sradutmp" to identify it later in the "accounting" +# section. +radutmp sradutmp { + filename = ${logdir}/sradutmp + permissions = 0644 + caller_id = "no" +} diff --git a/raddb/mods-available/totp b/raddb/mods-available/totp new file mode 100644 index 0000000..695365f --- /dev/null +++ b/raddb/mods-available/totp @@ -0,0 +1,40 @@ +# -*- text -*- +# +# $Id$ + +# +# Time-based One-Time Passwords (TOTP) +# +# Defined in RFC 6238, and used in Google Authenticator. +# +# This module can only be used in the "authenticate" section. +# +# The Base32-encoded secret should be placed into: +# +# &control:TOTP-Secret +# +# The TOTP password entered by the user should be placed into: +# +# &request:TOTP-Password +# +# The module will return "ok" if the passwords match, and "fail" +# if the passwords do not match. +# +# Note that this module will NOT interact with Google. The module is +# intended to be used where the local administrator knows the TOTP +# secret key, and user has an authenticator app on their phone. +# +# Note also that while you can use the Google "chart" APIs to +# generate a QR code, doing this will give the secret to Google! +# +# Administrators should instead install a tool such as "qrcode" +# +# https://linux.die.net/man/1/qrencode +# +# and then run that locally to get an image. +# +# +# The module takes no configuration items. +# +totp { +} diff --git a/raddb/mods-available/unbound b/raddb/mods-available/unbound new file mode 100644 index 0000000..43fbce5 --- /dev/null +++ b/raddb/mods-available/unbound @@ -0,0 +1,13 @@ +unbound dns { + # Configuration for libunbound + # filename = "${raddbdir}/mods-config/unbound/default.conf" + + # File to load resolver details from. + # Without this set unbound will query root servers + # resolvconf = "/etc/resolv.conf" + + # Hosts entries to load + # hosts = "/etc/hosts" + + # timeout = 3000 +} diff --git a/raddb/mods-available/unix b/raddb/mods-available/unix new file mode 100644 index 0000000..5165139 --- /dev/null +++ b/raddb/mods-available/unix @@ -0,0 +1,25 @@ +# -*- text -*- +# +# $Id$ + +# Unix /etc/passwd style authentication +# +# This module calls the system functions to get the "known good" +# password. This password is usually in the "crypt" form, and is +# incompatible with CHAP, MS-CHAP, PEAP, etc. +# +# If passwords are in /etc/shadow, you will need to set the "group" +# configuration in radiusd.conf. Look for "shadow", and follow the +# instructions there. +# +unix { + # + # The location of the "wtmp" file. + # The only use for 'radlast'. If you don't use + # 'radlast', then you can comment out this item. + # + # Note that the radwtmp file may get large! You should + # rotate it (cp /dev/null radwtmp), or just not use it. + # + radwtmp = ${logdir}/radwtmp +} diff --git a/raddb/mods-available/unpack b/raddb/mods-available/unpack new file mode 100644 index 0000000..89ef169 --- /dev/null +++ b/raddb/mods-available/unpack @@ -0,0 +1,105 @@ +# -*- text -*- +# +# $Id$ + +# +# This module is useful only for 'xlat'. +# To use it, add it to the raddb/mods-enabled/ directory. +# +# Two xlat functions are provided by this module: +# - unpack +# - substring +# +# Both are for use on the right-hand side of a variable assignment. +# +# unpack +# ====== +# +# ... = "%{unpack:data 1 integer}" +# +# The arguments are three fields: +# +# data +# Either &Attribute-Name +# the name of the attribute to unpack. +# MUST be a "string" or "octets" type. +# +# or 0xabcdef +# e.g. hex data. +# +# 1 +# The offset into the string from which +# it starts unpacking. The offset starts +# at zero, for the first attribute. +# +# integer +# the data type to unpack at that offset. +# e.g. integer, ipaddr, byte, short, etc. +# +# e.g. if we have Class = 0x0000000102030405, then +# +# %{unpack:&Class 4 short} +# +# will unpack octets 4 and 5 as a "short", which has +# value 0x0304. +# +# This module is used when vendors put multiple fields +# into one attribute of type "octets". +# +# The module can also be used to unpack substrings, by specifing a +# data type of "string(len)" or "octets(len)". Where "len" is an +# actual number. For example: +# +# %{unpack:&User-Name 1 string(2)} +# +# When given a User-Name of "hello", it will start taking the +# substring at offset 1 (i.e. "e"), and it will take two characters +# from that offset, i.e. "el". +# +# As a special case, you can unpack an entire string by specifying +# the offset, and nothing for the length: +# +# %{unpack:&User-Name 1 string()} +# +# When "octets(len)" is used, the output is printed as hex. e.g. for +# the above example with Class: +# +# %{unpack:&Class 4 octets(4)} +# +# Will return the hex string "02030405" +# +# +# substring +# ========= +# +# substring will return a substring of a string or attribute using +# the syntax +# +# %{substring:data start len} +# +# data +# Either an attribute name or string data. String data +# can have leading or trailing spaces. Only a single +# space before "start" is taken as the separator. +# +# start +# the zero based offset for the start of the substring. +# A negative value will count in from the end of the +# string. +# +# len +# the number of characters to return. A Negative value +# will remove that number of characters from the end. +# If len is more than the available number of characters +# then only the available number will be returned. +# +# Examples: +# +# "%{substring:foobar 2 3}" == "oba" +# "%{substring:foobar -3 2}" == "ba" +# "%{substring:foobar 1 -1}" == "ooba" +# if User-Name is "foobar" "%{substring:&User-Name 1 -2}" == "oob" +# + +unpack { +} diff --git a/raddb/mods-available/utf8 b/raddb/mods-available/utf8 new file mode 100644 index 0000000..00812fa --- /dev/null +++ b/raddb/mods-available/utf8 @@ -0,0 +1,14 @@ +# +# Enforces UTF-8 on strings coming in from the NAS. +# +# An attribute of type "string" containing UTF-8 makes +# the module return NOOP. +# +# An attribute of type "string" containing non-UTF-8 data +# makes the module return FAIL. +# +# This module takes no configuration. +# +utf8 { + +} diff --git a/raddb/mods-available/wimax b/raddb/mods-available/wimax new file mode 100644 index 0000000..3add59e --- /dev/null +++ b/raddb/mods-available/wimax @@ -0,0 +1,165 @@ +# +# The WiMAX module currently takes no configuration. +# +# ## Instructions for v1 and v2.0 WiMAX +# +# It should be listed in the "authorize" and "preacct" sections. +# This enables the module to fix the horrible binary version +# of Calling-Station-Id to the normal format, as specified in +# RFC 3580, Section 3.21. +# +# In order to calculate the various WiMAX keys, the module should +# be listed in the "post-auth" section. If EAP authentication +# has been used, AND the EAP method derives MSK and EMSK, then +# the various WiMAX keys can be calculated. +# +# Some useful things to remember: +# +# WiMAX-MSK = EAP MSK, but is 64 octets. +# +# MIP-RK-1 = HMAC-SHA256(ESMK, "miprk@wimaxforum.org" | 0x00020001) +# MIP-RK-2 = HMAC-SHA256(ESMK, MIP-RK-1 | "miprk@wimaxforum.org" | 0x00020002) +# MIP-RK = MIP-RK-1 | MIP-RK-2 +# +# MIP-SPI = first 4 octets of HMAC-SHA256(MIP-RK, "SPI CMIP PMIP") +# plus some magic... you've got to track *all* MIP-SPI's +# on your system! +# +# SPI-CMIP4 = MIP-SPI +# SPI-PMIP4 = MIP-SPI + 1 +# SPI-CMIP6 = MIP-SPI + 2 +# +# MN-NAI is the Mobile node NAI. You have to create it, and put +# it into the request or reply as something like: +# +# WiMAX-MN-NAI = "%{User-Name}" +# +# You will also have to have the appropriate IP address (v4 or v6) +# in order to calculate the keys below. +# +# Lifetimes are derived from Session-Timeout. It needs to be set +# to some useful number. +# +# The hash function below H() is HMAC-SHA1. +# +# +# MN-HA-CMIP4 = H(MIP-RK, "CMIP4 MN HA" | HA-IPv4 | MN-NAI) +# +# Where HA-IPv4 is WiMAX-hHA-IP-MIP4 +# or maybe WiMAX-vHA-IP-MIP4 +# +# Which goes into WiMAX-MN-hHA-MIP4-Key +# or maybe WiMAX-RRQ-MN-HA-Key +# or maybe even WiMAX-vHA-MIP4-Key +# +# The corresponding SPI is SPI-CMIP4, which is MIP-SPI, +# +# which goes into WiMAX-MN-hHA-MIP4-SPI +# or maybe WiMAX-RRQ-MN-HA-SPI +# or even WiMAX-MN-vHA-MIP4-SPI +# +# MN-HA-PMIP4 = H(MIP-RK, "PMIP4 MN HA" | HA-IPv4 | MN-NAI) +# MN-HA-CMIP6 = H(MIP-RK, "CMIP6 MN HA" | HA-IPv6 | MN-NAI) +# +# both with similar comments to above for MN-HA-CMIP4. +# +# In order to tell which one to use (CMIP4, PMIP4, or CMIP6), +# you have to set WiMAX-IP-Technology in the reply to one of +# the appropriate values. +# +# +# FA-RK = H(MIP-RK, "FA-RK") +# +# MN-FA = H(FA-RK, "MN FA" | FA-IP | MN-NAI) +# +# Where does the FA-IP come from? No idea... +# +# +# The next two keys (HA-RK and FA-HA) are not generated +# for every authentication request, but only on demand. +# +# HA-RK = 160-bit random number assigned by the AAA server +# to a specific HA. +# +# FA-HA = H(HA-RK, "FA-HA" | HA-IPv4 | FA-CoAv4 | SPI) +# +# where HA-IPv4 is as above. +# and FA-CoAv4 address of the FA as seen by the HA +# and SPI is the relevant SPI for the HA-RK. +# +# DHCP-RK = 160-bit random number assigned by the AAA server +# to a specific DHCP server. vDHCP-RK is the same +# thing. +# +# +# +# ## Instructions for v2.1 (LTE) WiMAX: +# +# When called from the "authorize" this module will detect the +# presence of the following attributes: +# +# request:WiMAX-Re-synchronization-Info +# control:WiMAX-SIM-Ki +# control:WiMAX-SIM-OPc +# +# If all attributes are present, (i.e. a known SIM is requesting a +# resync) then the module will attempt to extract the new SQN and +# save it in control:WiMAX-SIM-SQN. It will also save a copy of +# RAND from the request in control:WiMAX-SIM-RAND. +# +# The resulting value of SQN can then be saved in a database +# e.g. via a call to the sql module using some unlang +# +# When called in the "post_auth" section it looks for: +# +# control:WiMAX-SIM-Ki +# control:WiMAX-SIM-OPc +# control:WiMAX-SIM-AMF +# control:WiMAX-SIM-SQN +# request:WiMAX-Visited-PLMN-ID +# +# If all these are present then it will attempt to generate the +# keys for EPS AKA. +# +# First it checks for the presence of control:WiMAX-SIM-RAND and +# if it is not present it generates a new RAND value which is +# stored in reply:WiMAX-E-UTRAN-Vector-RAND. If it is present then +# the value is simply copied to the reply attribute. +# +# Then it calls the Milenage algorithm to generate: +# +# reply:WiMAX-E-UTRAN-Vector-XRES +# reply:WiMAX-E-UTRAN-Vector-AUTN +# +# And finally generates KASME which is stored in: +# reply:WiMAX-E-UTRAN-Vector-KASME +# +# +# NOTE: It is up to the system administrator to make sure that all +# the necessary "control" attributes are populated with the +# required values. The IMSI is likely to be found in User-Name in +# the request and this can be used as the key to grab the values +# from a database. +# +# +wimax { + # + # Some WiMAX equipment requires that the MS-MPPE-*-Key + # attributes are sent in the Access-Accept, in addition to + # the WiMAX-MSK attribute. + # + # Other WiMAX equipment request that the MS-MPPE-*-Key + # attributes are NOT sent in the Access-Accept. + # + # By default, the EAP modules sends MS-MPPE-*-Key attributes. + # The default virtual server (raddb/sites-available/default) + # contains examples of adding the WiMAX-MSK. + # + # This configuration option makes the WiMAX module delete + # the MS-MPPE-*-Key attributes. The default is to leave + # them in place. + # + # If the keys are deleted (by setting this to "yes"), then + # the WiMAX-MSK attribute is automatically added to the reply. + delete_mppe_keys = no +} diff --git a/raddb/mods-available/yubikey b/raddb/mods-available/yubikey new file mode 100644 index 0000000..9ba61ef --- /dev/null +++ b/raddb/mods-available/yubikey @@ -0,0 +1,158 @@ +# +# This module decrypts and validates Yubikey static and dynamic +# OTP tokens. +# +yubikey { + # + # The length (number of ASCII bytes) of the Public-ID portion + # of the OTP string. + # + # Yubikey defaults to a 6 byte ID (2 * 6 = 12) +# id_length = 12 + + # + # If true, the authorize method of rlm_yubikey will attempt to split the + # value of User-Password, into the user's password, and the OTP token. + # + # If enabled and successful, the value of &request:User-Password will be + # truncated and &request:Yubikey-OTP will be added. + # +# split = yes + + # + # Decrypt mode - Tokens will be decrypted and processed locally + # + # The module itself does not provide persistent storage as this + # would be duplicative of functionality already in the server. + # + # Yubikey authentication needs two attributes retrieved from + # persistent storage: + # * &control:Yubikey-Key - The AES key used to decrypt the OTP data. + # The Yubikey-Public-Id and/or User-Name + # attributes may be used to retrieve the key. + # * &control:Yubikey-Counter - This is compared with the counter in the OTP + # data and used to prevent replay attacks. + # This attribute will also be available in + # the request list after successful + # decryption. + # + # Yubikey-Counter isn't strictly required, but the server will + # generate warnings if it's not present when yubikey.authenticate + # is called. + # + # These attributes are available after authorization: + # * &request:Yubikey-Public-ID - The public portion of the OTP string. + # and additionally if 'split' is set: + # * &request:Yubikey-OTP - The OTP portion of User-Password. + # + # These attributes are available after authentication (if successful): + # * &request:Yubikey-Private-ID - The encrypted ID included in OTP data, + # must be verified if tokens share keys. + # * &request:Yubikey-Counter - The last counter value (should be recorded). + # * &request:Yubikey-Timestamp - Token's internal clock (mainly useful for + # debugging). + # * &request:Yubikey-Random - Randomly generated value from the token. + # + decrypt = no + + # + # Validation mode - Tokens will be validated against a Yubicloud server + # + validate = no + + # + # Settings for validation mode. + # + validation { + # + # URL of validation server, multiple URL config items may be used + # to list multiple servers. + # + # - %d is a placeholder for public ID of the token + # - %s is a placeholder for the token string itself + # + # If no URLs are listed, will default to the default URLs in the + # ykclient library, which point to the yubico validation servers. + servers { +# uri = 'https://api.yubico.com/wsapi/2.0/verify?id=%d&otp=%s' +# uri = 'https://api2.yubico.com/wsapi/2.0/verify?id=%d&otp=%s' + } + + # + # API Client ID + # + # Must be set to your client id for the validation server. + # +# client_id = 00000 + + # + # API Secret key (Base64 encoded) + # + # Must be set to your API key for the validation server. + # +# api_key = '000000000000000000000000' + + # + # Connection pool parameters + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the + # yubikey server being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Number of uses before the connection is closed + # + # NOTE: A setting of 0 means infinite (no limit). + uses = 0 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + retry_delay = 30 + + # The lifetime (in seconds) of the connection + # + # NOTE: A setting of 0 means infinite (no limit). + lifetime = 0 + + # The idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + # + # NOTE: A setting of 0 means infinite (no timeout). + idle_timeout = 60 + + # Cycle over all connections in a pool instead of concentrating + # connection use on a few connections. + spread = yes + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } + } +} |