+freeradius (3.0.14+git) unstable; urgency=medium
+
+ * New upstream version.
+
+ -- Alan DeKok <aland@freeradius.org> Tue, 07 Mar 2017 12:00:00 -0400
+
freeradius (3.0.13+moonshot3-6) unstable; urgency=medium
* Disabled session caching in EAP in response to CVE-2017-9148.
}
#
-# Session database modules
-#
-/var/log/freeradius/radutmp /var/log/freeradius/radwtmp {
- nocreate
-}
-
-#
# SQL log files
#
/var/log/freeradius/sqllog.sql {
+FreeRADIUS 3.0.14 Mon 06 Mar 2017 13:00:00 EDT urgency=medium
+ Feature improvements
+ * Enforce TLS client certificate expiration on
+ session resumption, and Session-Timeout.
+ See CVE-2017-9148.
+ * Updated dictionary.cisco.vpn3000, dictionary.patton
+ * Added dictionary.dellemc
+ * Lowered the log output for failed PEAP sessions.
+ * ALlow utc in rlm_date. Patch from
+ Peter Lambrechtsen.
+ * The internal OpenSSL session cache has been
+ disabled. Please see mods-available/eap
+ * Update detail reader documentation.
+ Patch from Matthew Newton. Fixes #1973.
+ * Make outgoing RadSec connections non-blocking.
+ * Add SQL backing to Moonshot-*-TargetedId
+ generation. Patch from Stefan Paetow.
+
+ Bug fixes
+ * radtest uses Cleartext-Password for EAP, not
+ User-Password.
+ * Update documentation for mods-enabled/ linking.
+ * Enhanced checks for moonshot salt. Fixes #1933.
+ * Allow session resumption for RadSec connections.
+ Fixes #1936.
+ * Update "huntgroups" file to note that port ranges
+ are not supported.
+ * Fix OpenSSL permissions issues on default key files.
+ Fixes #1941.
+ * Certificates are not required when PSK is used.
+ * Allow SubjectAltName as first extension in cert.
+ Fixes #1946.
+ * Fixed talloc issue with TLS session resumption.
+ Fixes #1980.
+ * "&Attr-26 := 0x01" now produces useful error messages.
+ * Handle connection error in rlm_ldap_cacheable_groupobj.
+ Fixes #1951.
+ * Fix endian issues in DHCP.
+ * Multiple minor fixes for Coverity complaints.
+ * Handle unexpected regex. Fixes #1959.
+ * Fix minor issues in dictionaries.
+ * Fix typos and grammar. Patches from Alan Buxey.
+ * Fix erroneous VP creation in rlm_preproces.
+ * Fix MIB. Patch from Jeff Gehlbach.
+ * Trust router updates from Alejandro Perez.
+ * Allow build with LibreSSL. Fixes #1989
+ * Use correct packet for channel bindings. Fixes #1990.
+ * Many fixes found by PVS-Studio. Thanks to PVS-Studio
+ for giving us a test license. Please see the git commit
+ history for more information.
+ * Fix incorrect length check in EAP-PWD. This may
+ be exploitable.
+
FreeRADIUS 3.0.13 Mon 06 Mar 2017 13:00:00 EDT urgency=medium
Feature improvements
* Add dictionary.rfc7930. Note that we do not implement
OBJECT-IDENTITY
FROM SNMPv2-SMI
freeRadiusMgmt
- FROM FREERADIUS-SMI;
+ FROM FREERADIUS-SMI
+ SnmpAdminString
+ FROM SNMP-FRAMEWORK-MIB;
freeradiusObjects MODULE-IDENTITY
LAST-UPDATED "200712170000Z"
"Generic objects used by notification MIBs"
::= { freeRadiusMgmt 1 }
-radiusObject OBJECT-IDENTITY
+radiusObject OBJECT-TYPE
+ SYNTAX SnmpAdminString
+ MAX-ACCESS accessible-for-notify
STATUS current
DESCRIPTION
"A generic object"
Modules can be enabled by creating a soft link. For module ``foo``, do::
- $ cd raddb
- $ ln -s mods-available/foo mods-enabled/foo
+ $ cd raddb/mods-enabled
+ $ ln -s ../mods-available/foo
To create "local" versions of the modules, we suggest copying the file
instead. This leaves the original file (with documentation) in the
@[ -f serial ] || $(MAKE) serial
$(OPENSSL) req -new -x509 -keyout ca.key -out ca.pem \
-days $(CA_DEFAULT_DAYS) -config ./ca.cnf
+ chmod g+r ca.key
ca.der: ca.pem
$(OPENSSL) x509 -inform PEM -outform DER -in ca.pem -out ca.der
######################################################################
server.csr server.key: server.cnf
$(OPENSSL) req -new -out server.csr -keyout server.key -config ./server.cnf
+ chmod g+r server.key
server.crt: server.csr ca.key ca.pem
$(OPENSSL) ca -batch -keyfile ca.key -cert ca.pem -in server.csr -key $(PASSWORD_CA) -out server.crt -extensions xpserver_ext -extfile xpextensions -config ./server.cnf
server.p12: server.crt
$(OPENSSL) pkcs12 -export -in server.crt -inkey server.key -out server.p12 -passin pass:$(PASSWORD_SERVER) -passout pass:$(PASSWORD_SERVER)
+ chmod g+r server.p12
server.pem: server.p12
$(OPENSSL) pkcs12 -in server.p12 -out server.pem -passin pass:$(PASSWORD_SERVER) -passout pass:$(PASSWORD_SERVER)
+ chmod g+r server.pem
.PHONY: server.vrfy
server.vrfy: ca.pem
######################################################################
client.csr client.key: client.cnf
$(OPENSSL) req -new -out client.csr -keyout client.key -config ./client.cnf
+ chmod g+r client.key
client.crt: client.csr ca.pem ca.key
$(OPENSSL) ca -batch -keyfile ca.key -cert ca.pem -in client.csr -key $(PASSWORD_CA) -out client.crt -extensions xpclient_ext -extfile xpextensions -config ./client.cnf
client.p12: client.crt
$(OPENSSL) pkcs12 -export -in client.crt -inkey client.key -out client.p12 -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT)
+ chmod g+r client.p12
client.pem: client.p12
$(OPENSSL) pkcs12 -in client.p12 -out client.pem -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT)
+ chmod g+r client.pem
cp client.pem $(USER_NAME).pem
.PHONY: client.vrfy
#
date {
format = "%b %e %Y %H:%M:%S %Z"
+
+ # Use UTC instead of local time.
+ #
+ # default = no
+# utc = yes
}
# Enable it. The default is "no". Deleting the entire "cache"
# subsection also disables caching.
#
+ # As of version 3.0.14, 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:
#
# If "enable = no" below, you CANNOT enable resumption for just one
# user by setting the above attribute to "yes".
#
- enable = yes
+ enable = no
#
# Lifetime of the cached entries, in hours. The sessions will be
lifetime = 24 # hours
#
- # The maximum number of entries in the
- # cache. Set to "0" for "infinite".
- #
- # This could be set to the number of users
- # who are logged in... which can be a LOT.
- #
- max_entries = 255
-
- #
# Internal "name" of the session cache. Used to
# distinguish which TLS context sessions belong to.
#
--- /dev/null
+# -*- text -*-
+#
+# $Id$
+
+#
+# Write Moonshot-*-TargetedId (MSTID) to the database.
+#
+# Schema raddb/sql/moonshot-targeted-ids/<DB>/schema.sql
+# Queries raddb/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
+}
# It works in conjunction with otpd, which implements token
# management and OTP verification functions; and lsmd or gsmd,
# which implements synchronous state management functions.
-# otpd, lsmd and gsmd are available from TRI-D Systems:
-# <http://www.tri-dsystems.com/>
# You must list this module in BOTH the authorize and authenticate
# sections in order to use it.
# Realm, the Huntgroup-Name or any combinaison of the attribute/value
# pairs contained in an accounting packet.
#
-#DEFAULT Realm == "foo.net", Acct-Type := sql_log.foo
+# You will need to add an "Acct-Type foo {...}" subsection to the
+# main "accounting" section in order for these sample configurations
+# to work.
#
-#DEFAULT Huntgroup-Name == "wifi", Acct-Type := sql_log.wifi
+#DEFAULT Realm == "foo.net", Acct-Type := foo
#
-#DEFAULT Client-IP-Address == 10.0.0.1, Acct-Type := sql_log.other
+#DEFAULT Huntgroup-Name == "wifi", Acct-Type := wifi
#
-#DEFAULT Acct-Status-Type == Start, Acct-Type := sql_log.start
+#DEFAULT Client-IP-Address == 10.0.0.1, Acct-Type := other
+#
+#DEFAULT Acct-Status-Type == Start, Acct-Type := start
# Replace the User-Name with the Stripped-User-Name, if it exists.
#
#
# huntgroups This file defines the `huntgroups' that you have. A
# huntgroup is defined by specifying the IP address of
-# the NAS and possibly a port range. Port can be identified
-# as just one port, or a range (from-to), and multiple ports
-# or ranges of ports must be separated by a comma. For
-# example: 1,2,3-8
+# the NAS and possibly a port.
#
# Matching is done while RADIUS scans the user file; if it
-# includes the selection criterium "Huntgroup-Name == XXX"
+# includes the selection criteria "Huntgroup-Name == XXX"
# the huntgroup is looked up in this file to see if it
# matches. There can be multiple definitions of the same
# huntgroup; the first one that matches will be used.
#delft NAS-IP-Address == 198.51.100.5
#
-# Ports 0-7 on the first terminal server in Alphen are connected to
+# Port 0 on the first terminal server in Alphen are connected to
# a huntgroup that is for business users only. Note that only one
# of the username or groupname has to match to get access (OR/OR).
#
# Note that this huntgroup is a subset of the "alphen" huntgroup.
#
-#business NAS-IP-Address == 198.51.100.5, NAS-Port-Id == 0-7
-# User-Name = rogerl,
-# User-Name = henks,
-# Group = business,
-# Group = staff
+#business NAS-IP-Address == 198.51.100.5, NAS-Port-Id == 0
+# User-Name == rogerl,
+# User-Name == henks,
+# Group == business,
+# Group == staff
--- /dev/null
+# -*- text -*-
+#
+# moonshot-targeted-ids/mysql/queries.conf -- Queries to update a MySQL Moonshot-Targeted-Ids table.
+#
+# $Id$
+
+post-auth {
+ # Query to store the Moonshot-*-TargetedId
+ query = "\
+ INSERT IGNORE INTO ${..moonshot_tid_table} \
+ (gss_acceptor, namespace, username, targeted_id) \
+ VALUES \
+ ('%{control:Moonshot-MSTID-GSS-Acceptor}', '%{control:Moonshot-MSTID-Namespace}', \
+ '%{tolower:%{User-Name}}', '%{control:Moonshot-MSTID-TargetedId}')"
+}
--- /dev/null
+CREATE TABLE `moonshot_targeted_ids` (
+ `gss_acceptor` varchar(254) NOT NULL default '',
+ `namespace` varchar(36) NOT NULL default '',
+ `username` varchar(64) NOT NULL default '',
+ `targeted_id` varchar(128) NOT NULL default '',
+ `creationdate` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ PRIMARY KEY (`username`,`gss_acceptor`,`namespace`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--- /dev/null
+# -*- text -*-
+#
+# moonshot-targeted-ids/postgresql/queries.conf -- Queries to update a PostgreSQL Moonshot-*-Targeted-Ids table.
+#
+# $Id$
+
+post-auth {
+ # Query to store the Moonshot-*-TargetedId
+ query = "\
+ INSERT INTO ${..moonshot_tid_table} \
+ (gss_acceptor, namespace, username, targeted_id) \
+ VALUES \
+ ('%{control:Moonshot-MSTID-GSS-Acceptor}', '%{control:Moonshot-MSTID-Namespace}', \
+ '%{tolower:%{User-Name}}', '%{control:Moonshot-MSTID-TargetedId}')"
+}
--- /dev/null
+CREATE TABLE moonshot_targeted_ids (
+ gss_acceptor varchar(254) NOT NULL DEFAULT '',
+ namespace varchar(36) NOT NULL DEFAULT '',
+ username varchar(64) NOT NULL DEFAULT '',
+ targeted_id varchar(128) NOT NULL DEFAULT '',
+ creationdate TIMESTAMP with time zone NOT NULL default 'now()',
+ PRIMARY KEY (username, gss_acceptor, namespace)
+);
--- /dev/null
+# -*- text -*-
+#
+# moonshot-targeted-ids/sqlite/queries.conf -- Queries to update a sqlite Moonshot-*-Targeted-Ids table.
+#
+# $Id$
+
+post-auth {
+ # Query to store the Moonshot-*-TargetedId
+ query = "\
+ INSERT INTO ${..moonshot_tid_table} \
+ (gss_acceptor, namespace, username, targeted_id) \
+ VALUES \
+ ('%{control:Moonshot-MSTID-GSS-Acceptor}', '%{control:Moonshot-MSTID-Namespace}', \
+ '%{tolower:%{User-Name}}', '%{control:Moonshot-MSTID-TargetedId}')"
+}
--- /dev/null
+CREATE TABLE `moonshot_targeted_ids` (
+ `gss_acceptor` varchar(254) NOT NULL default '',
+ `namespace` varchar(36) NOT NULL default '',
+ `username` varchar(64) NOT NULL default '',
+ `targeted_id` varchar(128) NOT NULL default '',
+ `creationdate` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ PRIMARY KEY (`username`,`gss_acceptor`,`namespace`)
+);
# Moonshot-Host-TargetedId (138)
# Moonshot-Realm-TargetedId (139)
# Moonshot-TR-COI-TargetedId (140)
+# Moonshot-MSTID-GSS-Acceptor (141)
+# Moonshot-MSTID-Namespace (142)
+# Moonshot-MSTID-TargetedId (143)
#
# These attributes should also be listed in the attr_filter policies
# post-proxy and pre-proxy when you use attribute filtering:
# dictionary attacks, therefore should be chosen as a "random"
# string and kept secret.
#
-targeted_id_salt = "changeme"
+# If you use special characters %, { and }, escape them with a \ first
+#
+targeted_id_salt = 'changeme'
+
#
# Moonshot namespaces
# These namespaces are used for UUID generation.
# They should not be changed by implementors
#
-moonshot_host_namespace = "a574a04e-b7ff-4850-aa24-a8599c7de1c6"
-moonshot_realm_namespace = "dea5f26d-a013-4444-977d-d09fc990d2e6"
-moonshot_coi_namespace = "145d7e7e-7d54-43ee-bbcb-3c6ad9428247"
-
-# This policy generates a host-specific targeted ID
+moonshot_host_namespace = 'a574a04e-b7ff-4850-aa24-a8599c7de1c6'
+moonshot_realm_namespace = 'dea5f26d-a013-4444-977d-d09fc990d2e6'
+moonshot_coi_namespace = '145d7e7e-7d54-43ee-bbcb-3c6ad9428247'
+
+
+# This policy generates a host-specific TargetedId
#
moonshot_host_tid.post-auth {
- # generate a UUID for Moonshot-Host-TargetedId
- # targeted id = (uuid -v 5 [namespace] [username][salt][RP host name])@[IdP realm name]
+ # retrieve or generate a UUID for Moonshot-Host-TargetedId
if (&outer.request:GSS-Acceptor-Host-Name) {
- if ("%{echo:/usr/bin/uuid -v 5 ${policy.moonshot_host_namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{tolower:%{outer.request:GSS-Acceptor-Host-Name}}}" =~ /^([^ ]+)([ ]*)$/) {
+ # prep some variables (used regardless of SQL backing or not!)
+ update control {
+ Moonshot-MSTID-GSS-Acceptor := "%{tolower:%{outer.request:GSS-Acceptor-Host-Name}}"
+ Moonshot-MSTID-Namespace := "${policy.moonshot_host_namespace}"
+ }
+
+ # if you want to use SQL-based backing, remove the comment from
+ # this line. You also have to configure and enable the
+ # moonshot-targeted-ids sql module in mods-enabled.
+ #
+# moonshot_get_targeted_id
+
+ # generate a UUID for Moonshot-Host-TargetedId
+ if (!&control:Moonshot-MSTID-TargetedId) {
+ # generate the TID
+ moonshot_make_targeted_id
+
+ # if you want to store your TargetedId in SQL-based backing,
+ # remove the comment from this line. You also have to configure
+ # and enable the moonshot-targeted-ids sql module in mods-enabled.
+ #
+# moonshot_tid_sql
+ }
+
+ # set the actual TargetedId in the session-state list
+ if (&control:Moonshot-MSTID-TargetedId) {
update outer.session-state {
- Moonshot-Host-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ Moonshot-Host-TargetedId := &control:Moonshot-MSTID-TargetedId
+ }
+ update control {
+ Moonshot-MSTID-TargetedId !* ANY
}
}
}
}
-# This policy generates a realm-specific targeted ID
+
+# This policy generates a realm-specific TargetedId
#
moonshot_realm_tid.post-auth {
- # generate a UUID for Moonshot-Realm-TargetedId
- # targeted id = (uuid -v 5 [namespace] [username][salt][RP realm name])@[IdP realm name]
+ # retrieve or generate a UUID for Moonshot-Realm-TargetedId
if (&outer.request:GSS-Acceptor-Realm-Name) {
- if ("%{echo:/usr/bin/uuid -v 5 ${policy.moonshot_realm_namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{tolower:%{outer.request:GSS-Acceptor-Realm-Name}}}" =~ /^([^ ]+)([ ]*)$/) {
+ # prep some variables (used regardless of SQL backing or not!)
+ update control {
+ Moonshot-MSTID-GSS-Acceptor := "%{tolower:%{outer.request:GSS-Acceptor-Realm-Name}}"
+ Moonshot-MSTID-Namespace := "${policy.moonshot_realm_namespace}"
+ }
+
+ # if you want to use SQL-based backing, remove the comment from
+ # this line. You also have to configure and enable the
+ # moonshot-targeted-ids sql module in mods-enabled.
+ #
+# moonshot_get_targeted_id
+
+ # generate a UUID for Moonshot-Realm-TargetedId
+ if (!&control:Moonshot-MSTID-TargetedId) {
+ # generate the TID
+ moonshot_make_targeted_id
+
+ # if you want to store your TargetedId in SQL-based backing,
+ # remove the comment from this line. You also have to configure
+ # and enable the moonshot-targeted-ids sql module in mods-enabled.
+ #
+# moonshot_tid_sql
+ }
+
+ # set the actual TargetedId in the session-state list
+ if (&control:Moonshot-MSTID-TargetedId) {
update outer.session-state {
- Moonshot-Realm-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ Moonshot-Realm-TargetedId := &control:Moonshot-MSTID-TargetedId
+ }
+ update control {
+ Moonshot-MSTID-TargetedId !* ANY
}
}
}
}
+
# This policy generates a COI-specific targeted ID
#
moonshot_coi_tid.post-auth {
- # generate a UUID for Moonshot-TR-COI-TargetedId
- # targeted id = (uuid -v 5 [namespace] [username][salt][RP COI name])@[IdP realm name]
+ # retrieve or generate a UUID for Moonshot-TR-COI-TargetedId
if (&outer.request:Trust-Router-COI) {
- if ("%{echo:/usr/bin/uuid -v 5 ${policy.moonshot_coi_namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{tolower:%{outer.request:Trust-Router-COI}}}" =~ /^([^ ]+)([ ]*)$/) {
+ # prep some variables (used regardless of SQL backing or not!)
+ update control {
+ Moonshot-MSTID-GSS-Acceptor := "%{tolower:%{outer.request:Trust-Router-COI}}"
+ Moonshot-MSTID-Namespace := "${policy.moonshot_coi_namespace}"
+ }
+
+ # if you want to use SQL-based backing, remove the comment from
+ # this line. You also have to configure and enable the
+ # moonshot-targeted-ids sql module in mods-enabled.
+ #
+# moonshot_get_targeted_id
+
+ # generate a UUID for Moonshot-TR-COI-TargetedId
+ if (!&control:Moonshot-MSTID-TargetedId) {
+ # generate the TID
+ moonshot_make_targeted_id
+
+ # if you want to store your TargetedId in SQL-based backing,
+ # remove the comment from this line. You also have to configure
+ # and enable the moonshot-targeted-ids sql module in mods-enabled.
+ #
+# moonshot_tid_sql
+ }
+
+ # set the actual TargetedId in the session-state list
+ if (&control:Moonshot-MSTID-TargetedId) {
update outer.session-state {
- Moonshot-TR-COI-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ Moonshot-TR-COI-TargetedId := &control:Moonshot-MSTID-TargetedId
+ }
+ update control {
+ Moonshot-MSTID-TargetedId !* ANY
+ }
+ }
+ }
+}
+
+# This is the generic generation policy. It requires moonshot_host_tid, moonshot_realm_tid, or moonshot_coi_tid to set variables
+#
+moonshot_make_targeted_id.post-auth {
+ # uses variables set in the control list
+ #
+ if (&control:Moonshot-MSTID-Namespace && &control:Moonshot-MSTID-GSS-Acceptor) {
+ # targeted id = (uuid -v 5 [namespace] [username][salt][GSS acceptor value])@[IdP realm name]
+ #
+ if ("%{echo:/usr/bin/uuid -v 5 %{control:Moonshot-MSTID-Namespace} %{tolower:%{User-Name}}${policy.targeted_id_salt}%{control:Moonshot-MSTID-GSS-Acceptor}}" =~ /^([^ ]+)([ ]*)$/) {
+ update control {
+ Moonshot-MSTID-TargetedId := "%{1}@%{tolower:%{request:Realm}}"
+ }
+ if (&control:Moonshot-MSTID-TargetedId =~ /([\%\{\}]+)/) {
+ update control {
+ Moonshot-MSTID-TargetedId !* ANY
+ }
+ update outer.session-state {
+ Module-Failure-Message = 'Invalid TargetedId generated, check your targeted_id_salt!'
+ }
+ reject
+ }
+ }
+ else {
+ # we simply return the 'echo' error message as the Module-Failure-Message, usually a lack of 'uuid'
+ reject
+ }
+ }
+ else {
+ # Our variables were not set, so we'll throw an error because there's no point in continuing!
+ update outer.session-state {
+ Module-Failure-Message = 'Required variables for moonshot_make_targeted_id not set!'
+ }
+ reject
+ }
+}
+
+# This is the generic retrieval policy. It requires moonshot_host_tid, moonshot_realm_tid, or moonshot_coi_tid to set variables
+#
+moonshot_get_targeted_id.post-auth {
+ # uses variables set in the control list
+ #
+ if (&control:Moonshot-MSTID-Namespace && &control:Moonshot-MSTID-GSS-Acceptor) {
+ # retrieve the TargetedId
+ #
+ update control {
+ Moonshot-MSTID-TargetedId := "%{moonshot_tid_sql:\
+ SELECT targeted_id FROM moonshot_targeted_ids \
+ WHERE gss_acceptor = '%{control:Moonshot-MSTID-GSS-Acceptor}' \
+ AND namespace = '%{control:Moonshot-MSTID-Namespace}' \
+ AND username = '%{tolower:%{User-Name}}'}"
+ }
+
+ # if the value is empty, there's no point in setting it and delete it from the control list!
+ if (&control:Moonshot-MSTID-TargetedId == '') {
+ update control {
+ Moonshot-MSTID-TargetedId !* ANY
}
}
}
+ else {
+ # Our variables were not set, so we'll throw an error because there's no point in continuing!
+ update outer.session-state {
+ Module-Failure-Message = 'Required variables for moonshot_get_targeted_id not set!'
+ }
+ reject
+ }
}
cache {
enable = no
lifetime = 24 # hours
- max_entries = 255
+ name = "abfab-tls"
+# persist_dir = ${logdir}/abfab-tls
}
require_client_cert = yes
-sql
#
- # Instead of sending the query to the SQL server,
- # write it into a log file.
- #
-# sql_log
-
- #
# Un-comment the following if you want to modify the user's object
# in LDAP after a successful login.
#
# The location where the detail file is located.
# This should be on local disk, and NOT on an NFS
# mounted location!
+ #
+ # On most systems, this should support file globbing
+ # e.g. "${radacctdir}/detail-*:*"
+ # This lets you write many smaller detail files as in
+ # the example in radiusd.conf: ".../detail-%Y%m%d:%H"
+ # Writing many small files is often better than writing
+ # one large file. File globbing also means that with
+ # a common naming scheme for detail files, then you can
+ # have many detail file writers, and only one reader.
+ #
filename = "${radacctdir}/detail-*"
#
# wake up, and poll for it every N seconds.
#
# Useful range of values: 1 to 60
+ #
poll_interval = 1
#
# home server responds.
#
# Useful range of values: 5 to 30
+ #
retry_interval = 30
#
# have already been processed. The default is "no".
#
# track = yes
+
+ #
+ # In some circumstances it may be desirable for the
+ # server to start up, process a detail file, and
+ # immediately quit. To do this enable the "one_shot"
+ # option below.
+ #
+ # Do not enable this for normal server operation. The
+ # default is "no".
+ #
+ # one_shot = no
}
#
listen {
type = detail
+ #
+ # See sites-available/buffered-sql for more details on
+ # all the options available for the detail reader.
+ #
+
######################################################
#
# !!!! WARNING !!!!
# one large file. File globbing also means that with
# a common naming scheme for detail files, then you can
# have many detail file writers, and only one reader.
+ #
filename = ${radacctdir}/detail
#
# See "Accounting queries" in sql.conf
# sql
- #
- # Instead of sending the query to the SQL server,
- # write it into a log file.
- #
-# sql_log
-
# Cisco VoIP specific bulk accounting
# pgsql-voip
#
# update request {
-# FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}"
+# &FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}"
# }
# ok
# }
- #
- # Instead of sending the query to the SQL server,
- # write it into a log file.
- #
-# sql_log
-
# Cisco VoIP specific bulk accounting
# pgsql-voip
-sql
#
- # Instead of sending the query to the SQL server,
- # write it into a log file.
- #
-# sql_log
-
- #
# Un-comment the following if you want to modify the user's object
# in LDAP after a successful login.
#
-sql
#
- # Instead of sending the query to the SQL server,
- # write it into a log file.
- #
-# sql_log
-
- #
# Un-comment the following if you have set
# 'edir_account_policy_check = yes' in the ldap module sub-section of
# the 'modules' section.
#
# Un-comment the following if you want to generate Moonshot (ABFAB) TargetedIds
- # IMPORTANT: This requires the UUID package to be installed!
+ #
+ # IMPORTANT: This requires the UUID package to be installed, and a targeted_id_salt
+ # to be configured.
+ #
+ # This functionality also supports SQL backing. To use this functionality, enable
+ # and configure the moonshot-targeted-ids SQL module in the mods-enabled directory.
+ # Then remove the comments from the appropriate lines in each of the below
+ # policies in the policy.d/moonshot-targeted-ids file.
#
# moonshot_host_tid
# moonshot_realm_tid
# Deleting the entire "cache" subsection
# Also disables caching.
#
+ #
+ # As of version 3.0.14, 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:
lifetime = 24 # hours
#
- # The maximum number of entries in the
- # cache. Set to "0" for "infinite".
- #
- # This could be set to the number of users
- # who are logged in... which can be a LOT.
- #
- max_entries = 255
-
- #
# Internal "name" of the session cache.
# Used to distinguish which TLS context
# sessions belong to.
}
#
-# Session database modules
-#
-/var/log/radius/radutmp /var/log/radius/radwtmp {
- nocreate
-}
-
-#
# SQL log files
#
/var/log/radius/sqllog.sql {
Summary: High-performance and highly configurable free RADIUS server
Name: freeradius
-Version: 3.0.13
+Version: 3.0.14
Release: 2%{?dist}
License: GPLv2+ and LGPLv2+
Group: System Environment/Daemons
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/main/mysql/*
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/main/ndb
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/main/ndb/*
+%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/moonshot-targeted-ids/mysql
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/moonshot-targeted-ids/mysql/*
# postgres
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/counter/postgresql
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/counter/postgresql/*
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/ippool/postgresql/*
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/main/postgresql
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/main/postgresql/*
+%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/moonshot-targeted-ids/postgresql
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/moonshot-targeted-ids/postgresql/*
# sqlite
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/counter/sqlite
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/counter/sqlite/*
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/ippool/sqlite/*
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/main/sqlite
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/main/sqlite/*
+%dir %attr(750,root,radiusd) /etc/raddb/mods-config/sql/moonshot-targeted-ids/sqlite
+%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-config/sql/moonshot-targeted-ids/sqlite/*
# ruby
%if %{?_with_rlm_ruby:1}%{!?_with_rlm_ruby:0}
%dir %attr(750,root,radiusd) /etc/raddb/mods-config/ruby
}
#
-# Session database modules
-#
-/var/log/radius/radutmp /var/log/radius/radwtmp {
- nocreate
-}
-
-#
# SQL log files
#
/var/log/radius/sqllog.sql {
$INCLUDE dictionary.compatible
$INCLUDE dictionary.cosine
$INCLUDE dictionary.dante
+$INCLUDE dictionary.dellemc
$INCLUDE dictionary.dlink
$INCLUDE dictionary.digium
$INCLUDE dictionary.dragonwave
# -*- text -*-
-# Copyright (C) 2015 The FreeRADIUS Server project and contributors
+# Copyright (C) 2017 The FreeRADIUS Server project and contributors
#
# Cisco VPN 3000 Concentrator Dictionary
#
ATTRIBUTE CVPN3000-LEAP-Bypass 75 integer
ATTRIBUTE CVPN3000-WebVPN-Exchange-NETBIOS-name 78 string
ATTRIBUTE CVPN3000-Port-Forwarding-Name 79 string
+ATTRIBUTE CVPN3000-IE-Proxy-Server 80 string
+ATTRIBUTE CVPN3000-IE-Proxy-Server-Policy 81 integer
+ATTRIBUTE CVPN3000-IE-Proxy-Exception-List 82 string
+ATTRIBUTE CVPN3000-IE-Proxy-Bypass-Local 83 integer
+ATTRIBUTE CVPN3000-IKE-Keepalive-Retry-Interval 84 integer
+ATTRIBUTE CVPN3000-Tunnel-Group-Lock 85 string
+ATTRIBUTE Cisco-VPN3000-Access-List-Inbound 86 string
+ATTRIBUTE Cisco-VPN3000-Access-List-Outbound 87 string
+ATTRIBUTE Cisco-VPN3000-Perfect-Forward-Secrecy-Enable 88 integer
+ATTRIBUTE Cisco-VPN3000-NAC-Enable 89 integer
+ATTRIBUTE Cisco-VPN3000-NAC-Status-Query-Timer 90 integer
+ATTRIBUTE Cisco-VPN3000-NAC-Revalidation-Timer 91 integer
+ATTRIBUTE Cisco-VPN3000-NAC-Default-ACL 92 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-URL-Entry-Enable 93 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-File-Access-Enable 94 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-File-Server-Entry-Enable 95 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-File-Server-Browsing-Enable 96 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-Port-Forwarding-Enable 97 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-Outlook-Exchange-Proxy-Enable 98 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-Outlook-Exchange-Proxy-Enable 99 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-Auto-Applet-Download-Enable 100 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-Citrix-MetaFrame-Enable 101 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-Apply-ACL 102 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-SSL-VPN-Client-Enable 103 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-SSL-VPN-Client-Required 104 integer
+ATTRIBUTE Cisco-VPN3000-WebVPN-SSL-VPN-Client-Keep-Installation 105 integer
+
ATTRIBUTE CVPN3000-Partition-Primary-DHCP 128 ipaddr
ATTRIBUTE CVPN3000-Partition-Secondary-DHCP 129 ipaddr
ATTRIBUTE CVPN3000-Partition-Premise-Router 131 ipaddr
--- /dev/null
+# -*- text -*-
+# Copyright (C) 2017 The FreeRADIUS Server project and contributors
+#
+# Dell Inc.
+#
+# DellEMC-AVpair Attribute-Value Pair.
+# DellEMC-Group-Name The Linux primary group name associated with the user.
+# This must be an existing group in /etc/groups.
+
+VENDOR DellEMC 674
+
+BEGIN-VENDOR DellEMC
+
+ATTRIBUTE DellEMC-AVpair 1 string
+ATTRIBUTE DellEMC-Group-Name 2 string
+
+END-VENDOR DellEMC
+
ATTRIBUTE DHCP-Ethernet-Interface 130 octets
ATTRIBUTE DHCP-Vendor-Discrimination-Str 130 octets
ATTRIBUTE DHCP-Remote-Stats-Svr-IP-Address 131 octets
-ATTRIBUTE DHCP-IEEE-802.1P-VLAN-ID 132 octets
-ATTRIBUTE DHCP-IEEE-802.1Q-L2-Priority 133 octets
+ATTRIBUTE DHCP-IEEE-802.1Q-VLAN-ID 132 octets
+ATTRIBUTE DHCP-IEEE-802.1P-L2-Priority 133 octets
ATTRIBUTE DHCP-Diffserv-Code-Point 134 octets
ATTRIBUTE DHCP-HTTP-Proxy 135 octets
ATTRIBUTE ERX-Secondary-Dns 5 ipaddr
ATTRIBUTE ERX-Primary-Wins 6 ipaddr
ATTRIBUTE ERX-Secondary-Wins 7 ipaddr
-ATTRIBUTE ERX-Tunnel-Virtual-Router 8 string
-ATTRIBUTE ERX-Tunnel-Password 9 string
+ATTRIBUTE ERX-Tunnel-Virtual-Router 8 string has_tag
+ATTRIBUTE ERX-Tunnel-Password 9 string has_tag
ATTRIBUTE ERX-Ingress-Policy-Name 10 string
ATTRIBUTE ERX-Egress-Policy-Name 11 string
ATTRIBUTE ERX-Ingress-Statistics 12 integer
VALUE EAP-Type Notification 2
VALUE EAP-Type NAK 3
VALUE EAP-Type MD5-Challenge 4
+VALUE EAP-Type EAP-MD5 4
VALUE EAP-Type MD5 4
VALUE EAP-Type One-Time-Password 5
VALUE EAP-Type OTP 5
VALUE EAP-Type Generic-Token-Card 6
+VALUE EAP-Type EAP-GTC 6
VALUE EAP-Type GTC 6
VALUE EAP-Type RSA-Public-Key 9
VALUE EAP-Type DSS-Unilateral 10
VALUE EAP-Type KEA 11
VALUE EAP-Type KEA-Validate 12
+VALUE EAP-Type EAP-TLS 13
VALUE EAP-Type TLS 13
VALUE EAP-Type Defender-Token 14
VALUE EAP-Type RSA-SecurID-EAP 15
VALUE EAP-Type Cisco-LEAP 17
VALUE EAP-Type LEAP 17
VALUE EAP-Type Nokia-IP-Smart-Card 18
+VALUE EAP-Type EAP-SIM 18
VALUE EAP-Type SIM 18
VALUE EAP-Type SRP-SHA1 19
# 20 is unassigned
+VALUE EAP-Type EAP-TTLS 21
VALUE EAP-Type TTLS 21
VALUE EAP-Type Remote-Access-Service 22
+VALUE EAP-Type EAP-AKA 23
VALUE EAP-Type AKA 23
VALUE EAP-Type 3Com-Wireless 24
VALUE EAP-Type PEAP 25
VALUE EAP-Type DeviceConnect-EAP 40
VALUE EAP-Type SPEKE 41
VALUE EAP-Type MOBAC 42
+VALUE EAP-Type EAP-FAST 43
VALUE EAP-Type FAST 43
VALUE EAP-Type Zonelabs 44
VALUE EAP-Type Link 45
VALUE EAP-Type PAX 46
VALUE EAP-Type PSK 47
VALUE EAP-Type SAKE 48
+VALUE EAP-Type EAP-IKEv2 49
VALUE EAP-Type IKEv2 49
VALUE EAP-Type AKA2 50
VALUE EAP-Type GPSK 51
#
# And this is what most people mean by MS-CHAPv2
#
+VALUE EAP-Type EAP-MSCHAPv2 26
VALUE EAP-Type MSCHAPv2 26
#
BEGIN-VENDOR Patton
+ATTRIBUTE Patton-Protocol 16 string
ATTRIBUTE Patton-Setup-Time 32 string
ATTRIBUTE Patton-Connect-Time 33 string
ATTRIBUTE Patton-Disconnect-Time 34 string
ATTRIBUTE Patton-Called-Numbering-Plan 50 string
ATTRIBUTE Patton-Called-Type-Of-Number 51 string
ATTRIBUTE Patton-Called-Name 52 string
+ATTRIBUTE Patton-Called-Station-Id 53 string
ATTRIBUTE Patton-Called-Rx-Octets 64 integer
ATTRIBUTE Patton-Called-Tx-Octets 65 integer
ATTRIBUTE Patton-Called-Rx-Packets 66 integer
ATTRIBUTE Patton-Called-Rx-Jitter 70 integer
ATTRIBUTE Patton-Called-Tx-Jitter 71 integer
ATTRIBUTE Patton-Called-Codec 72 string
+ATTRIBUTE Patton-Called-Remote-Ip 73 integer
+ATTRIBUTE Patton-Called-Remote-Udp-Port 74 integer
+ATTRIBUTE Patton-Called-Local-Udp-Port 75 integer
+ATTRIBUTE Patton-Called-Qos 76 integer
ATTRIBUTE Patton-Called-MOS 77 integer
ATTRIBUTE Patton-Called-Round-Trip-Time 78 integer
ATTRIBUTE Patton-Calling-Unique-Id 80 string
ATTRIBUTE Patton-Calling-Presentation-Indicator 88 string
ATTRIBUTE Patton-Calling-Screening-Indicator 89 string
ATTRIBUTE Patton-Calling-Name 84 string
+ATTRIBUTE Patton-Calling-Station-Id 85 string
ATTRIBUTE Patton-Calling-Rx-Octets 96 integer
ATTRIBUTE Patton-Calling-Tx-Octets 97 integer
ATTRIBUTE Patton-Calling-Rx-Packets 98 integer
ATTRIBUTE Patton-Calling-Rx-Jitter 102 integer
ATTRIBUTE Patton-Calling-Tx-Jitter 103 integer
ATTRIBUTE Patton-Calling-Codec 104 string
+ATTRIBUTE Patton-Calling-Remote-Ip 105 integer
+ATTRIBUTE Patton-Calling-Remote-Udp-Port 106 integer
+ATTRIBUTE Patton-Calling-Local-Udp-Port 107 integer
+ATTRIBUTE Patton-Calling-Qos 108 integer
ATTRIBUTE Patton-Calling-MOS 109 integer
ATTRIBUTE Patton-Calling-Round-Trip-Time 110 integer
ATTRIBUTE Moonshot-Host-TargetedId 138 string
ATTRIBUTE Moonshot-Realm-TargetedId 139 string
ATTRIBUTE Moonshot-TR-COI-TargetedId 140 string
+ATTRIBUTE Moonshot-MSTID-GSS-Acceptor 141 string
+ATTRIBUTE Moonshot-MSTID-Namespace 142 string
+ATTRIBUTE Moonshot-MSTID-TargetedId 143 string
END-VENDOR UKERNA
ATTRIBUTE ZTE-TCP-Limit-Mode 96 integer
ATTRIBUTE ZTE-IGMP-Service-Profile-Num 97 integer
ATTRIBUTE ZTE-PPP-Sservice-Type 101 integer
+ATTRIBUTE ZTE-SW-Privilege 104 integer
ATTRIBUTE ZTE-Access-Domain 151 string
ATTRIBUTE ZTE-VPN-ID 190 string
unsigned int (*record_minus)(record_t *buf, void *ptr, unsigned int size);
bool invalid_hb_used; //!< Whether heartbleed attack was detected.
+ bool connected; //!< whether the outgoing socket is connected
/*
* Framed-MTU attribute in RADIUS, if present, can also be used to set this
tls_session_t *tls_new_client_session(TALLOC_CTX *ctx, fr_tls_server_conf_t *conf, int fd);
fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs);
fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs);
+fr_tls_server_conf_t *tls_server_conf_alloc(TALLOC_CTX *ctx);
SSL_CTX *tls_init_ctx(fr_tls_server_conf_t *conf, int client);
int tls_handshake_recv(REQUEST *, tls_session_t *ssn);
int tls_handshake_send(REQUEST *, tls_session_t *ssn);
void fr_cbuff_rp_insert(fr_cbuff_t *cbuff, void *obj)
{
#ifdef HAVE_PTHREAD_H
- if (cbuff->lock) PTHREAD_MUTEX_LOCK(cbuff);
+ PTHREAD_MUTEX_LOCK(cbuff);
#endif
if (cbuff->elem[cbuff->in]) {
}
#ifdef HAVE_PTHREAD_H
- if (cbuff->lock) PTHREAD_MUTEX_UNLOCK(cbuff);
+ PTHREAD_MUTEX_UNLOCK(cbuff);
#endif
}
void *obj = NULL;
#ifdef HAVE_PTHREAD_H
- if (cbuff->lock) PTHREAD_MUTEX_LOCK(cbuff);
+ PTHREAD_MUTEX_LOCK(cbuff);
#endif
/* Buffer is empty */
done:
#ifdef HAVE_PTHREAD_H
- if (cbuff->lock) PTHREAD_MUTEX_UNLOCK(cbuff);
+ PTHREAD_MUTEX_UNLOCK(cbuff);
#endif
return obj;
}
*/
int fr_get_time(char const *date_str, time_t *date)
{
- int i;
+ int i, j;
time_t t;
struct tm *tm, s_tm;
char buf[64];
f[0] = f[i];
f[i] = p;
- for (i = 0; i < 12; i++) {
- if (strncasecmp(months[i], f[0], 3) == 0) {
- tm->tm_mon = i;
+ for (j = 0; j < 12; j++) {
+ if (strncasecmp(months[j], f[0], 3) == 0) {
+ tm->tm_mon = j;
break;
}
}
{
HMAC_CTX *ctx;
ctx = OPENSSL_malloc(sizeof(*ctx));
+ if (!ctx) return NULL;
+
memset(ctx, 0, sizeof(*ctx));
- if (ctx == NULL) {
- return NULL;
- }
HMAC_CTX_init(ctx);
return ctx;
}
/*
* Message-Authenticator is hard-coded.
*/
- if (!vp->da->vendor && (vp->da->attr == PW_MESSAGE_AUTHENTICATOR)) {
+ if (vp->da->attr == PW_MESSAGE_AUTHENTICATOR) {
if (room < 18) return -1;
ptr[0] = PW_MESSAGE_AUTHENTICATOR;
* Warn if more than one Auth-Type was found, because only the last
* one found will actually be used.
*/
- if ((auth_type_count > 1) && (rad_debug_lvl)) {
+ if ((auth_type_count > 1) && (rad_debug_lvl) && request->username) {
RERROR("Warning: Found %d auth-types on request for user '%s'",
auth_type_count, request->username->vp_strvalue);
}
*/
static int fr_server_domain_socket_perm(char const *path, uid_t uid, gid_t gid)
{
- int dir_fd = -1, path_fd = -1, sock_fd = -1, parent_fd = -1;
+ int dir_fd = -1, sock_fd = -1, parent_fd = -1;
char const *name;
char *buff = NULL, *dir = NULL, *p;
fr_strerror_printf("Failed determining parent directory");
error:
talloc_free(dir);
- close(dir_fd);
- close(path_fd);
+ if (sock_fd >= 0) close(sock_fd);
+ if (dir_fd >= 0) close(dir_fd);
+ if (parent_fd >= 0) close(parent_fd);
return -1;
}
if (ret < 0) {
fr_strerror_printf("Failed changing ownership of control socket directory: %s",
fr_syserror(errno));
- return -1;
+ goto error;
}
/*
* Control socket dir already exists, but we still need to
if (client_fd >= 0) {
fr_strerror_printf("Control socket '%s' is already in use", path);
close(client_fd);
- return -1;
+ goto error;
}
}
if (uid != (uid_t)-1) rad_seuid(euid);
if (gid != (gid_t)-1) rad_segid(egid);
- close(dir_fd);
- close(path_fd);
+ if (dir_fd >= 0) close(dir_fd);
+ if (parent_fd >= 0) close(parent_fd);
return sock_fd;
}
CONF_PAIR *cp = NULL;
fr_ipaddr_t *ipaddr;
char buffer[8192];
- CONF_ITEM *c_item = &cs->item;
+ CONF_ITEM *c_item;
if (!cs) return -1;
+ c_item = &cs->item;
+
deprecated = (type & PW_TYPE_DEPRECATED);
required = (type & PW_TYPE_REQUIRED);
attribute = (type & PW_TYPE_ATTRIBUTE);
if (!value) {
if (required) {
- is_required:
cf_log_err(c_item, "Configuration item \"%s\" must have a value", name);
return -1;
}
}
- if (required && !value) goto is_required;
if (cant_be_empty && (value[0] == '\0')) goto cant_be_empty;
if (attribute) {
rcode = read(data->master_pipe[0], &packet, sizeof(packet));
if (rcode <= 0) return rcode;
+ rad_assert(packet != NULL);
+
if (DEBUG_ENABLED2) {
VALUE_PAIR *vp;
vp_cursor_t cursor;
debug_pair(vp);
}
}
- rad_assert(packet != NULL);
switch (packet->code) {
case PW_CODE_ACCOUNTING_REQUEST:
regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; /* +1 for %{0} (whole match) capture group */
size_t nmatch = sizeof(rxmatch) / sizeof(regmatch_t);
- rad_assert(lhs_type == PW_TYPE_STRING);
- rad_assert(lhs != NULL);
+ if (!lhs || (lhs_type != PW_TYPE_STRING)) return -1;
EVAL_DEBUG("CMP WITH REGEX %s %s",
map->rhs->tmpl_iflag ? "CASE INSENSITIVE" : "CASE SENSITIVE",
case '[': /* we don't list close braces */
case '{':
case '(':
- if (outlen < 3) goto done;
-
*(p++) = '\\';
outlen--;
/* FALL-THROUGH */
}
}
-done:
*(p++) = '\0';
return p - out;
}
VALUE_PAIR *input_pairs, bool shell_escape)
{
#ifndef __MINGW32__
- char *p;
VALUE_PAIR *vp;
int n;
int to_child[2] = {-1, -1};
*/
snprintf(buffer, sizeof(buffer), "%s=", vp->da->name);
if (shell_escape) {
+ char *p;
+
for (p = buffer; *p != '='; p++) {
if (*p == '-') {
*p = '_';
#ifdef WITH_TCP
if (sock->proto == IPPROTO_TCP) {
/*
- * If there are hard-coded worker threads, OR
- * it's a TLS connection, it's blocking.
+ * Woker threads are blocking.
*
* Otherwise, they're non-blocking.
*/
- if (!this->workers
-#ifdef WITH_PROXY
-#ifdef WITH_TLS
- && (this->type == RAD_LISTEN_PROXY) && !this->tls
-#endif
-#endif
- ) {
+ if (!this->workers) {
if (fr_nonblock(this->fd) < 0) {
close(this->fd);
ERROR("Failed setting non-blocking on socket: %s",
if (!map_cast_from_hex(map, T_BARE_WORD, vpt->name)) {
map->rhs = vpt;
- cf_log_err(map->ci, "%s", fr_strerror());
+ cf_log_err(map->ci, "Cannot parse RHS hex as the data type of the attribute %s", map->lhs->tmpl_da->name);
return -1;
}
talloc_free(vpt);
da = dict_attrbytype(map->lhs->tmpl_da->attr, map->lhs->tmpl_da->vendor,
map->rhs->tmpl_data_type);
if (!da) {
- fr_strerror_printf("Cannot find %s variant of attribute \"%s\"",
- fr_int2str(dict_attr_types, map->rhs->tmpl_data_type,
- "<INVALID>"), map->lhs->tmpl_da->name);
+ cf_log_err(map->ci, "Cannot find %s variant of attribute \"%s\"",
+ fr_int2str(dict_attr_types, map->rhs->tmpl_data_type,
+ "<INVALID>"), map->lhs->tmpl_da->name);
return -1;
}
map->lhs->tmpl_da = da;
memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
sizeof(csingle->actions));
- mx->xlat_name = strdup(fmt);
+ mx->xlat_name = talloc_strdup(mx, fmt);
+ if (!mx->xlat_name) {
+ talloc_free(mx);
+ return NULL;
+ }
+
if (fmt[0] != '%') {
char *p;
mx->exec = true;
if (!map_cast_from_hex(map, T_BARE_WORD, vpt->name)) {
map->rhs = vpt;
- cf_log_err(map->ci, "%s", fr_strerror());
+ cf_log_err(map->ci, "Cannot parse RHS hex as the data type of the attribute %s", map->lhs->tmpl_da->name);
return -1;
}
talloc_free(vpt);
*/
if (node->entry->module->inst_size) {
*handle = talloc_zero_array(node, uint8_t, node->entry->module->inst_size);
- rad_assert(handle);
+ rad_assert(*handle);
talloc_set_name(*handle, "rlm_%s_t",
node->entry->module->name ? node->entry->module->name : "config");
static int load_byserver(CONF_SECTION *cs)
{
- rlm_components_t comp, found;
+ rlm_components_t comp;
+ bool found;
char const *name = cf_section_name2(cs);
rbtree_t *components;
virtual_server_t *server = NULL;
* Loop over all of the known components, finding their
* configuration section, and loading it.
*/
- found = 0;
+ found = false;
for (comp = 0; comp < MOD_COUNT; ++comp) {
CONF_SECTION *subcs;
server->subcs[comp] = subcs;
- found = 1;
+ found = true;
} /* loop over components */
/*
char *expr = NULL, *value = NULL;
char const *expr_p, *value_p;
+ if (!vp) return -2;
+
if (check->da->type == PW_TYPE_STRING) {
expr_p = check->vp_strvalue;
} else {
{
VERIFY_REQUEST(request);
+ rad_assert(request->home_server != NULL);
+
if (request->client) {
/*
* The client hasn't set the response window. Return
}
}
- rad_assert(request->home_server != NULL);
return &request->home_server->response_window;
}
}
#ifdef WITH_TCP
- rad_assert(request->proxy_listener != NULL);
- request->proxy_listener->count--;
+ if (request->proxy_listener) {
+ request->proxy_listener->count--;
+ }
#endif
request->proxy_listener = NULL;
#ifdef WITH_ACCOUNTING
case PW_CODE_ACCOUNTING_REQUEST:
- proxy_acct_stats.last_packet = packet->timestamp.tv_sec;
-
request->proxy_listener->stats.total_responses++;
proxy_acct_stats.last_packet = packet->timestamp.tv_sec;
break;
PASSWORD="MS-CHAP-Password"
;;
eap-md5)
- PASSWORD="User-Password"
+ PASSWORD="Cleartext-Password"
if [ ! -x "$radeapclient" ]
then
echo "radtest: No 'radeapclient' program was found. Cannot perform EAP-MD5." >&1
}
this->next = NULL;
- this->when = now + 60;
+ this->when = now + 300;
this->pool = pool;
pthread_mutex_unlock(&pool_free_mutex);
}
PTHREAD_MUTEX_UNLOCK(&state->mutex);
- rad_assert(request->state == NULL);
VERIFY_REQUEST(request);
return true;
}
talloc_set_destructor(ssn, _tls_session_free);
ssn->ctx = conf->ctx;
+ ssn->mtu = conf->fragment_size;
SSL_CTX_set_mode(ssn->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY);
SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_SSN, (void *)ssn);
SSL_set_fd(ssn->ssl, fd);
ret = SSL_connect(ssn->ssl);
+
+ if (ret < 0) {
+ switch (SSL_get_error(ssn->ssl, ret)) {
+ default:
+ break;
+
+
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ ssn->connected = false;
+ return ssn;
+ }
+ }
+
if (ret <= 0) {
tls_error_io_log(NULL, ssn, ret, "Failed in " STRINGIFY(__FUNCTION__) " (SSL_connect)");
talloc_free(ssn);
return NULL;
}
- ssn->mtu = conf->fragment_size;
-
+ ssn->connected = true;
return ssn;
}
static void session_close(tls_session_t *ssn)
{
- SSL_set_quiet_shutdown(ssn->ssl, 1);
- SSL_shutdown(ssn->ssl);
-
if (ssn->ssl) {
+ SSL_set_quiet_shutdown(ssn->ssl, 1);
+ SSL_shutdown(ssn->ssl);
+
SSL_free(ssn->ssl);
ssn->ssl = NULL;
}
blob_len = i2d_SSL_SESSION(sess, NULL);
if (blob_len < 1) {
/* something went wrong */
- RWDEBUG("Session serialisation failed, couldn't determine required buffer length");
+ if (request) RWDEBUG("Session serialisation failed, couldn't determine required buffer length");
return 0;
}
p = sess_blob;
rv = i2d_SSL_SESSION(sess, &p);
if (rv != blob_len) {
- RWDEBUG("Session serialisation failed");
+ if (request) RWDEBUG("Session serialisation failed");
goto error;
}
/* open output file */
snprintf(filename, sizeof(filename), "%s%c%s.asn1",
conf->session_cache_path, FR_DIR_SEP, buffer);
- fd = open(filename, O_RDWR|O_CREAT|O_EXCL, 0600);
+ fd = open(filename, O_RDWR|O_CREAT|O_EXCL, S_IWUSR);
if (fd < 0) {
- RERROR("Session serialisation failed, failed opening session file %s: %s",
- filename, fr_syserror(errno));
+ if (request) RERROR("Session serialisation failed, failed opening session file %s: %s",
+ filename, fr_syserror(errno));
goto error;
}
fr_pair_value_strcpy(vp, filename);
fr_pair_add(&request->state, vp);
}
-
- (void) fchmod(fd, S_IWUSR);
}
todo = blob_len;
while (todo > 0) {
rv = write(fd, p, todo);
if (rv < 1) {
- RWDEBUG("Failed writing session: %s", fr_syserror(errno));
+ if (request) RWDEBUG("Failed writing session: %s", fr_syserror(errno));
close(fd);
goto error;
}
todo -= rv;
}
close(fd);
- RWDEBUG("Wrote session %s to %s (%d bytes)", buffer, filename, blob_len);
+ if (request) RWDEBUG("Wrote session %s to %s (%d bytes)", buffer, filename, blob_len);
}
error:
return 0;
}
+/** Convert OpenSSL's ASN1_TIME to an epoch time
+ *
+ * @param[out] out Where to write the time_t.
+ * @param[in] asn1 The ASN1_TIME to convert.
+ * @return
+ * - 0 success.
+ * - -1 on failure.
+ */
+static int ocsp_asn1time_to_epoch(time_t *out, char const *asn1)
+{
+ struct tm t;
+ char const *p = asn1, *end = p + strlen(p);
+
+ memset(&t, 0, sizeof(t));
+
+ if ((end - p) <= 12) {
+ if ((end - p) < 2) {
+ fr_strerror_printf("ASN1 date string too short, expected 2 additional bytes, got %zu bytes",
+ end - p);
+ return -1;
+ }
+
+ t.tm_year = (*(p++) - '0') * 10;
+ t.tm_year += (*(p++) - '0');
+ if (t.tm_year < 70) t.tm_year += 100;
+ } else {
+ t.tm_year = (*(p++) - '0') * 1000;
+ t.tm_year += (*(p++) - '0') * 100;
+ t.tm_year += (*(p++) - '0') * 10;
+ t.tm_year += (*(p++) - '0');
+ t.tm_year -= 1900;
+ }
+
+ if ((end - p) < 10) {
+ fr_strerror_printf("ASN1 string too short, expected 10 additional bytes, got %zu bytes",
+ end - p);
+ return -1;
+ }
+
+ t.tm_mon = (*(p++) - '0') * 10;
+ t.tm_mon += (*(p++) - '0') - 1; // -1 since January is 0 not 1.
+ t.tm_mday = (*(p++) - '0') * 10;
+ t.tm_mday += (*(p++) - '0');
+ t.tm_hour = (*(p++) - '0') * 10;
+ t.tm_hour += (*(p++) - '0');
+ t.tm_min = (*(p++) - '0') * 10;
+ t.tm_min += (*(p++) - '0');
+ t.tm_sec = (*(p++) - '0') * 10;
+ t.tm_sec += (*(p++) - '0');
+
+ /* Apparently OpenSSL converts all timestamps to UTC? Maybe? */
+ *out = timegm(&t);
+ return 0;
+}
+
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
static SSL_SESSION *cbtls_get_session(SSL *ssl, unsigned char *data, int len, int *copy)
#else
struct stat st;
VALUE_PAIR *vps = NULL;
+ VALUE_PAIR *vp;
/* load the actual SSL session */
snprintf(filename, sizeof(filename), "%s%c%s.asn1", conf->session_cache_path, FR_DIR_SEP, buffer);
fd = open(filename, O_RDONLY);
if (fd < 0) {
RWDEBUG("No persisted session file %s: %s", filename, fr_syserror(errno));
- goto err;
+ goto error;
}
rv = fstat(fd, &st);
if (rv < 0) {
RWDEBUG("Failed stating persisted session file %s: %s", filename, fr_syserror(errno));
close(fd);
- goto err;
+ goto error;
}
sess_data = talloc_array(NULL, unsigned char, st.st_size);
if (!sess_data) {
RWDEBUG("Failed allocating buffer for persisted session (%d bytes)", (int) st.st_size);
close(fd);
- goto err;
+ goto error;
}
q = sess_data;
if (rv < 1) {
RWDEBUG("Failed reading persisted session: %s", fr_syserror(errno));
close(fd);
- goto err;
+ goto error;
}
todo -= rv;
q += rv;
sess = d2i_SSL_SESSION(NULL, o, st.st_size);
if (!sess) {
RWDEBUG("Failed loading persisted session: %s", ERR_error_string(ERR_get_error(), NULL));
- goto err;
+ goto error;
}
/* read in the cached VPs from the .vps file */
if (rv < 0) {
/* not safe to un-persist a session w/o VPs */
RWDEBUG("Failed loading persisted VPs for session %s", buffer);
- goto err;
+ SSL_SESSION_free(sess);
+ goto error;
+ }
+
+ /*
+ * Enforce client certificate expiration.
+ */
+ vp = fr_pair_find_by_num(pairlist->reply, PW_TLS_CLIENT_CERT_EXPIRATION, 0, TAG_ANY);
+ if (vp) {
+ time_t expires;
+
+ if (ocsp_asn1time_to_epoch(&expires, vp->vp_strvalue) < 0) {
+ RDEBUG2("Failed getting certificate expiration, removing cache entry for session %s", buffer);
+ SSL_SESSION_free(sess);
+ goto error;
+ }
+
+ if (expires <= request->timestamp) {
+ RDEBUG2("Certificate has expired, removing cache entry for session %s", buffer);
+ SSL_SESSION_free(sess);
+ goto error;
+ }
+
+ /*
+ * Account for Session-Timeout, if it's available.
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_SESSION_TIMEOUT, 0, TAG_ANY);
+ if (vp) {
+ if ((request->timestamp + vp->vp_integer) > expires) {
+ vp->vp_integer = expires - request->timestamp;
+ RWDEBUG2("Updating Session-Timeout to %u, due to impending certificate expiration",
+ vp->vp_integer);
+ }
+ }
}
/* move the cached VPs into the session */
RWDEBUG("Successfully restored session %s", buffer);
rdebug_pair_list(L_DBG_LVL_2, request, vps, "reply:");
}
-err:
+error:
if (sess_data) talloc_free(sess_data);
if (pairlist) pairlist_free(&pairlist);
/*
* Get the RFC822 Subject Alternative Name
*/
- loc = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, 0);
+ loc = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, -1);
if (certs && (lookup <= 1) && (loc >= 0)) {
X509_EXTENSION *ext = NULL;
GENERAL_NAMES *names = NULL;
}
if (lookup == 0) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
ext_list = X509_get0_extensions(client_cert);
#else
X509_CINF *client_inf;
true, true, EXEC_TIMEOUT) != 0) {
AUTH(LOG_PREFIX ": Certificate CN (%s) fails external verification!", common_name);
my_ok = 0;
- } else {
+
+ } else if (request) {
RDEBUG("Client certificate CN %s passed external validation", common_name);
}
#endif
#endif
+/*
+ * DIE OPENSSL DIE DIE DIE
+ *
+ * What a palaver, just to free some data attached the
+ * session. We need to do this because the "remove" callback
+ * is called when refcount > 0 sometimes, if another thread
+ * is using the session
+ */
+static void sess_free_vps(UNUSED void *parent, void *data_ptr,
+ UNUSED CRYPTO_EX_DATA *ad, UNUSED int idx,
+ UNUSED long argl, UNUSED void *argp)
+{
+ VALUE_PAIR *vp = data_ptr;
+ if (!vp) return;
+
+ DEBUG2(LOG_PREFIX ": Freeing cached session VPs");
+
+ fr_pair_list_free(&vp);
+}
+
+static void sess_free_certs(UNUSED void *parent, void *data_ptr,
+ UNUSED CRYPTO_EX_DATA *ad, UNUSED int idx,
+ UNUSED long argl, UNUSED void *argp)
+{
+ VALUE_PAIR **certs = data_ptr;
+ if (!certs) return;
+
+ DEBUG2(LOG_PREFIX ": Freeing cached session Certificates");
+
+ fr_pair_list_free(certs);
+}
+
/** Add all the default ciphers and message digests reate our context.
*
* This should be called exactly once from main, before reading the main config
/*
* Initialize the index for the certificates.
*/
- fr_tls_ex_index_certs = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ fr_tls_ex_index_certs = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, sess_free_certs);
}
#ifdef ENABLE_OPENSSL_VERSION_CHECK
SSL_CTX_set_quiet_shutdown(ctx, 1);
if (fr_tls_ex_index_vps < 0)
- fr_tls_ex_index_vps = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ fr_tls_ex_index_vps = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, sess_free_vps);
}
/*
}
/*
- * Cache it, and DON'T auto-clear it.
+ * Cache it, DON'T auto-clear it, and disable the internal OpenSSL session cache.
*/
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR);
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR | SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_set_session_id_context(ctx,
(unsigned char *) conf->session_context_id,
return 0;
}
-static fr_tls_server_conf_t *tls_server_conf_alloc(TALLOC_CTX *ctx)
+fr_tls_server_conf_t *tls_server_conf_alloc(TALLOC_CTX *ctx)
{
fr_tls_server_conf_t *conf;
*/
if (conf->fragment_size < 100) conf->fragment_size = 100;
- if (!conf->private_key_file) {
- ERROR(LOG_PREFIX ": TLS Server requires a private key file");
- goto error;
- }
+ /*
+ * Only check for certificate things if we don't have a
+ * PSK query.
+ */
+ if (conf->psk_identity) {
+ if (conf->private_key_file) {
+ WARN(LOG_PREFIX ": Ignoring private key file due to psk_identity being used");
+ }
- if (!conf->certificate_file) {
- ERROR(LOG_PREFIX ": TLS Server requires a certificate file");
- goto error;
+ if (conf->certificate_file) {
+ WARN(LOG_PREFIX ": Ignoring certificate file due to psk_identity being used");
+ }
+
+ } else {
+ if (!conf->private_key_file) {
+ ERROR(LOG_PREFIX ": TLS Server requires a private key file");
+ goto error;
+ }
+
+ if (!conf->certificate_file) {
+ ERROR(LOG_PREFIX ": TLS Server requires a certificate file");
+ goto error;
+ }
}
/*
return conf;
}
+
int tls_success(tls_session_t *ssn, REQUEST *request)
{
VALUE_PAIR *vp, *vps = NULL;
* Save the certs in the packet, so that we can see them.
*/
fr_pair_add(&request->packet->vps, fr_pair_list_copy(request->packet, *certs));
+
+ vp = fr_pair_find_by_num(request->packet->vps, PW_TLS_CLIENT_CERT_EXPIRATION, 0, TAG_ANY);
+ if (vp) {
+ time_t expires;
+
+ if (ocsp_asn1time_to_epoch(&expires, vp->vp_strvalue) < 0) {
+ RDEBUG2("Failed getting certificate expiration, removing cache entry for session %s", buffer);
+ SSL_CTX_remove_session(ssn->ctx, ssn->ssl_session);
+ return -1;
+ }
+
+ if (expires <= request->timestamp) {
+ RDEBUG2("Certificate has expired, removing cache entry for session %s", buffer);
+ SSL_CTX_remove_session(ssn->ctx, ssn->ssl_session);
+ return -1;
+ }
+
+ /*
+ * Account for Session-Timeout, if it's available.
+ */
+ vp = fr_pair_find_by_num(request->reply->vps, PW_SESSION_TIMEOUT, 0, TAG_ANY);
+ if (vp) {
+ if ((request->timestamp + vp->vp_integer) > expires) {
+ vp->vp_integer = expires - request->timestamp;
+ RWDEBUG2("Updating Session-Timeout to %u, due to impending certificate expiration",
+ vp->vp_integer);
+ }
+ }
+ }
}
if (vps) {
rad_assert(sock->packet != NULL);
request->packet = talloc_steal(request, sock->packet);
- request->component = "<core>";
request->component = "<tls-connect>";
request->reply = rad_alloc(request, false);
SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
SSL_set_ex_data(sock->ssn->ssl, fr_tls_ex_index_certs, (void *) &sock->certs);
- SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_TALLOC, sock);
+ SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_TALLOC, NULL);
doing_init = true;
}
return 0;
}
+static int try_connect(tls_session_t *ssn)
+{
+ int ret;
+ ret = SSL_connect(ssn->ssl);
+ if (ret < 0) {
+ switch (SSL_get_error(ssn->ssl, ret)) {
+ default:
+ break;
+
+
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ ssn->connected = false;
+ return 0;
+ }
+ }
+
+ if (ret <= 0) {
+ tls_error_io_log(NULL, ssn, ret, "Failed in " STRINGIFY(__FUNCTION__) " (SSL_connect)");
+ talloc_free(ssn);
+
+ return -1;
+ }
+
+ return 1;
+}
+
#ifdef WITH_PROXY
/*
uint8_t *data;
listen_socket_t *sock = listener->data;
+ if (!sock->ssn->connected) {
+ rcode = try_connect(sock->ssn);
+ if (rcode == 0) return 0;
+
+ if (rcode < 0) {
+ SSL_shutdown(sock->ssn->ssl);
+ return -1;
+ }
+
+ sock->ssn->connected = true;
+ }
+
/*
* Get the maximum size of data to receive.
*/
request);
}
+ if (!sock->ssn->connected) {
+ PTHREAD_MUTEX_LOCK(&sock->mutex);
+ rcode = try_connect(sock->ssn);
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+ if (rcode == 0) return 0;
+
+ if (rcode < 0) {
+ SSL_shutdown(sock->ssn->ssl);
+ return -1;
+ }
+
+ sock->ssn->connected = true;
+ }
+
DEBUG3("Proxy is writing %u bytes to SSL",
(unsigned int) request->proxy->data_len);
PTHREAD_MUTEX_LOCK(&sock->mutex);
* much faster.
*/
tokens = talloc_typed_strdup(request, fmt);
- if (!tokens) return -1;
+ if (!tokens) {
+ error = "Out of memory";
+ return -1;
+ }
slen = xlat_tokenize_literal(request, tokens, head, false, &error);
*/
if (slen < 0) {
talloc_free(tokens);
- rad_assert(error != NULL);
+
+ if (!error) error = "Unknown error";
REMARKER(fmt, -slen, error);
return slen;
case 'S': /* request timestamp in SQL format*/
if (!localtime_r(&when, &ts)) goto error;
- nl = str + strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
- rad_assert(((str + freespace) - nl) >= 8);
- snprintf(nl, (str + freespace) - nl, ".%06d", usec);
+ strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
break;
case 'T': /* request timestamp */
if (!localtime_r(&when, &ts)) goto error;
- strftime(str, freespace, "%Y-%m-%d-%H.%M.%S", &ts);
-
+ nl = str + strftime(str, freespace, "%Y-%m-%d-%H.%M.%S", &ts);
+ rad_assert(((str + freespace) - nl) >= 8);
+ snprintf(nl, (str + freespace) - nl, ".%06d", usec);
break;
case 'Y': /* request year */
}
vp = fr_pair_find_by_num(request->packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Hop-Count */
rad_assert(vp != NULL);
- if (vp->vp_integer > maxhops) {
+ if (vp->vp_byte > maxhops) {
DEBUG("DHCP: Number of hops is greater than %d: not relaying\n", maxhops);
return 1;
} else {
- /* Increment hop count */
- vp->vp_integer++;
+ /* Increment hop count */
+ vp->vp_byte++;
}
sock = request->listener->data;
vp = fr_pair_find_by_num(request->packet->vps, 53, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Message-Type */
if (vp) {
- DICT_VALUE *dv = dict_valbyattr(53, DHCP_MAGIC_VENDOR, vp->vp_integer);
+ DICT_VALUE *dv = dict_valbyattr(53, DHCP_MAGIC_VENDOR, vp->vp_byte);
DEBUG("Trying sub-section dhcp %s {...}",
dv ? dv->name : "<unknown>");
- rcode = process_post_auth(vp->vp_integer, request);
+ rcode = process_post_auth(vp->vp_byte, request);
} else {
DEBUG("DHCP: Failed to find DHCP-Message-Type in packet!");
rcode = RLM_MODULE_FAIL;
vp = fr_pair_find_by_num(request->reply->vps, 53, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Message-Type */
if (vp) {
- request->reply->code = vp->vp_integer;
+ request->reply->code = vp->vp_byte;
if ((request->reply->code != 0) &&
(request->reply->code < PW_DHCP_OFFSET)) {
request->reply->code += PW_DHCP_OFFSET;
}
/* BOOTREPLY received on port 67 (i.e. from a server) */
- if (vp->vp_integer == 2) {
+ if (vp->vp_byte == 2) {
return dhcprelay_process_server_reply(request);
}
}
/* else it's a packet from a client, without relaying */
- rad_assert(vp->vp_integer == 1); /* BOOTREQUEST */
+ rad_assert(vp->vp_byte == 1); /* BOOTREQUEST */
sock = request->listener->data;
vp = fr_pair_find_by_num(request->reply->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Opcode */
rad_assert(vp != NULL);
- vp->vp_integer = 2; /* BOOTREPLY */
+ vp->vp_byte = 2; /* BOOTREPLY */
/*
* Allow NAKs to be delayed for a short period of time.
typedef struct rlm_date_t {
char const *xlat_name;
char const *fmt;
+ bool utc;
} rlm_date_t;
static const CONF_PARSER module_config[] = {
{ "format", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_date_t, fmt), "%b %e %Y %H:%M:%S %Z" },
+ { "utc", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_date_t, utc), "no" },
CONF_PARSER_TERMINATOR
};
date = (time_t) vp->vp_integer;
encode:
- if (localtime_r(&date, &tminfo) == NULL) {
- REDEBUG("Failed converting time string to localtime");
- goto error;
+ if (!inst->utc) {
+ if (localtime_r(&date, &tminfo) == NULL) {
+ REDEBUG("Failed converting time string to localtime");
+ goto error;
+ }
+ } else {
+ if (gmtime_r(&date, &tminfo) == NULL) {
+ REDEBUG("Failed converting time string to gmtime");
+ goto error;
+ }
}
return strftime(out, outlen, inst->fmt, &tminfo);
fake->server = "channel_bindings";
fake->packet->code = PW_CODE_ACCESS_REQUEST;
- rcode = rad_virtual_server(fake);
-
- switch (rcode) {
+ switch (rad_virtual_server(fake)) {
/* If rad_authenticate succeeded, build a reply */
case RLM_MODULE_OK:
case RLM_MODULE_HANDLED:
return packet;
}
-VALUE_PAIR *eap_chbind_packet2vp(REQUEST *request, chbind_packet_t *packet)
+VALUE_PAIR *eap_chbind_packet2vp(RADIUS_PACKET *packet, chbind_packet_t *chbind)
{
VALUE_PAIR *vp;
- if (!packet) return NULL; /* don't produce garbage */
+ if (!chbind) return NULL; /* don't produce garbage */
- vp = fr_pair_afrom_num(request->packet, PW_UKERNA_CHBIND, VENDORPEC_UKERNA);
+ vp = fr_pair_afrom_num(packet, VENDORPEC_UKERNA, PW_UKERNA_CHBIND);
if (!vp) return NULL;
- fr_pair_value_memcpy(vp, (uint8_t *) packet, talloc_array_length((uint8_t *)packet));
+ fr_pair_value_memcpy(vp, (uint8_t *) chbind, talloc_array_length((uint8_t *)chbind));
return vp;
}
/* Channel binding function prototypes */
PW_CODE chbind_process(REQUEST *request, CHBIND_REQ *chbind_req);
-VALUE_PAIR *eap_chbind_packet2vp(REQUEST *request, chbind_packet_t *packet);
+VALUE_PAIR *eap_chbind_packet2vp(RADIUS_PACKET *packet, chbind_packet_t *chbind);
chbind_packet_t *eap_chbind_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps);
#endif /*_EAP_CHBIND_H*/
SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_STORE, (void *)tls_conf->ocsp_store);
#endif
SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_SSN, (void *)ssn);
- SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_TALLOC, handler);
+ SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_TALLOC, NULL);
return talloc_steal(handler, ssn); /* ssn */
}
if (prev_eap_ds && prev_eap_ds->response)
eaptls_prev = (eaptls_packet_t *)prev_eap_ds->response->type.data;
- /*
- * First output the flags (for debugging)
- */
- RDEBUG3("Peer sent flags %c%c%c",
- TLS_START(eaptls_packet->flags) ? 'S' : '-',
- TLS_MORE_FRAGMENTS(eaptls_packet->flags) ? 'M' : '-',
- TLS_LENGTH_INCLUDED(eaptls_packet->flags) ? 'L' : '-');
+ if (eaptls_packet) {
+ /*
+ * First output the flags (for debugging)
+ */
+ RDEBUG3("Peer sent flags %c%c%c",
+ TLS_START(eaptls_packet->flags) ? 'S' : '-',
+ TLS_MORE_FRAGMENTS(eaptls_packet->flags) ? 'M' : '-',
+ TLS_LENGTH_INCLUDED(eaptls_packet->flags) ? 'L' : '-');
+ }
/*
* check for ACK
/*
* Keep a copy of the the password attribute.
*/
+ case PW_CLEARTEXT_PASSWORD:
case PW_USER_PASSWORD:
case PW_CHAP_PASSWORD:
case PW_MS_CHAP_PASSWORD:
/*
* Cisco AP1230 has a bug and needs a zero
- * terminated string in Access-Accept.
+ * terminated string in Access-Accept. This
+ * means it requires 2 trailing zeros. One to
+ * send in the RADIUS packet, and the other to
+ * convince the rest of the server that
+ * vp->vp_strvalue is still a NUL-terminated C
+ * string.
*/
if (inst->mod_accounting_username_bug) {
char const *old = vp->vp_strvalue;
- char *new = talloc_zero_array(vp, char, vp->vp_length + 1);
+ char *new;
+
+ vp->vp_length++; /* account for an additional zero */
+
+ new = talloc_array(vp, char, vp->vp_length + 1);
memcpy(new, old, vp->vp_length);
+ new[vp->length] = '\0';
+ new[vp->length + 1] = '\0';
vp->vp_strvalue = new;
- vp->vp_length++;
rad_const_free(old);
+ VERIFY_VP(vp);
}
}
eap_fast_append_result(tls_session, code);
- if (code == PW_CODE_ACCESS_REJECT)
- break;
-
if (t->pac.send) {
RDEBUG("Peer requires new PAC");
eap_fast_send_pac_tunnel(request, tls_session);
* Verify the tunneled EAP message.
*/
static int eapmessage_verify(REQUEST *request,
- uint8_t const *data, unsigned int data_len)
+ uint8_t const *data, unsigned int data_len, int peap_version)
{
eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
eap_type_t eap_method;
/*
+ * Hack for now.
+ */
+ if (peap_version == 1) return 1;
+
+ /*
* No data, OR only 1 byte of EAP type.
*/
if (!data || (data_len == 0) ||
RDEBUG2("Received EAP-TLV response");
return 1;
}
- RDEBUG2("Got something weird");
+ RDEBUG2("Received unexpected EAP-Response, rejecting the session.");
break;
*/
static VALUE_PAIR *eap2vp(UNUSED REQUEST *request, RADIUS_PACKET *packet,
EAP_DS *eap_ds,
- uint8_t const *data, size_t data_len)
+ uint8_t const *data, size_t data_len, int peap_version)
{
size_t total;
uint8_t *p;
total = data_len;
if (total > 249) total = 249;
- /*
- * Hand-build an EAP packet from the crap in PEAP version 0.
- */
- vp->vp_length = EAP_HEADER_LEN + total;
- vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
+ if (peap_version == 0) {
+ /*
+ * Hand-build an EAP packet from the crap in PEAP version 0.
+ */
+ vp->vp_length = EAP_HEADER_LEN + total;
+ vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
+
+ p[0] = PW_EAP_RESPONSE;
+ p[1] = eap_ds->response->id;
+ p[2] = (data_len + EAP_HEADER_LEN) >> 8;
+ p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
- p[0] = PW_EAP_RESPONSE;
- p[1] = eap_ds->response->id;
- p[2] = (data_len + EAP_HEADER_LEN) >> 8;
- p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
+ memcpy(p + EAP_HEADER_LEN, data, total);
- memcpy(p + EAP_HEADER_LEN, data, total);
+ } else { /* peapv1 */
+ vp->vp_length = total;
+ vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
+ memcpy(p, data, total);
+ }
fr_cursor_init(&cursor, &head);
fr_cursor_insert(&cursor, vp);
rad_assert(vp != NULL);
VALUE_PAIR *this;
vp_cursor_t cursor;
+ size_t header = EAP_HEADER_LEN;
+
+ if (tls_session->peap_flag > 0) header = 0;
/*
* Skip the id, code, and length. Just write the EAP
*/
#ifndef NDEBUG
if ((rad_debug_lvl > 2) && fr_log_fp) {
- size_t i, total, start = EAP_HEADER_LEN;
+ size_t i, total, start = header;
total = 0;
for (this = fr_cursor_init(&cursor, &vp); this; this = fr_cursor_next(&cursor)) {
* Send the EAP data in the first attribute, WITHOUT the
* header.
*/
- (tls_session->record_plus)(&tls_session->clean_in, vp->vp_octets + EAP_HEADER_LEN, vp->vp_length - EAP_HEADER_LEN);
+ (tls_session->record_plus)(&tls_session->clean_in, vp->vp_octets + header, vp->vp_length - header);
/*
* Send the rest of the EAP data, but skipping the first VP.
rlm_rcode_t rcode = RLM_MODULE_REJECT;
uint8_t const *data;
unsigned int data_len;
+ size_t header = 0;
REQUEST *request = handler->request;
EAP_DS *eap_ds = handler->eap_ds;
RDEBUG2("PEAP state %s", peap_state(t));
if ((t->status != PEAP_STATUS_TUNNEL_ESTABLISHED) &&
- !eapmessage_verify(request, data, data_len)) {
+ !eapmessage_verify(request, data, data_len, tls_session->peap_flag)) {
REDEBUG("Tunneled data is invalid");
if (rad_debug_lvl > 2) print_tunneled_data(data, data_len);
return RLM_MODULE_REJECT;
}
+ if (tls_session->peap_flag > 0) header = EAP_HEADER_LEN;
+
switch (t->status) {
case PEAP_STATUS_TUNNEL_ESTABLISHED:
/* FIXME: should be no data in the buffer here, check & assert? */
case PEAP_STATUS_INNER_IDENTITY_REQ_SENT:
/* we're expecting an identity response */
- if (data[0] != PW_EAP_IDENTITY) {
+ if (data[header] != PW_EAP_IDENTITY) {
REDEBUG("Expected EAP-Identity, got something else");
return RLM_MODULE_REJECT;
}
t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
rad_assert(t->username != NULL);
- fr_pair_value_bstrncpy(t->username, data + 1, data_len - 1);
+ fr_pair_value_bstrncpy(t->username, data + header + 1, data_len - header - 1);
RDEBUG("Got inner identity '%s'", t->username->vp_strvalue);
if (t->soh) {
case PEAP_STATUS_WAIT_FOR_SOH_RESPONSE:
fake = request_alloc_fake(request);
rad_assert(!fake->packet->vps);
- eapsoh_verify(fake, fake->packet, data, data_len);
+ eapsoh_verify(fake, fake->packet, data + header, data_len - header);
setup_fake_request(request, fake, t);
if (t->soh_virtual_server) {
* If we authenticated the user, then it's OK.
*/
case PEAP_STATUS_SENT_TLV_SUCCESS:
- if (eappeap_check_tlv(request, data, data_len)) {
+ if (eappeap_check_tlv(request, data + header, data_len - header)) {
RDEBUG2("Success");
return RLM_MODULE_OK;
}
case PEAP_STATUS_PHASE2:
fake->packet->vps = eap2vp(request, fake->packet,
- eap_ds, data, data_len);
+ eap_ds, data, data_len, tls_session->peap_flag);
if (!fake->packet->vps) {
talloc_free(fake);
RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
* so we add one here, by pulling it out of the
* EAP-Identity packet.
*/
- if ((data[0] == PW_EAP_IDENTITY) && (data_len > 1)) {
+ if ((data[header] == PW_EAP_IDENTITY) && (data_len > (1 + header))) {
t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
rad_assert(t->username != NULL);
- fr_pair_value_bstrncpy(t->username, data + 1, data_len - 1);
+ fr_pair_value_bstrncpy(t->username, data + header + 1, data_len - header - 1);
RDEBUG2("Got tunneled identity of %s", t->username->vp_strvalue);
peap = tls_session->opaque = peap_alloc(tls_session, inst);
}
+ /*
+ * Negotiate PEAP versions down.
+ */
+ if ((handler->eap_ds->response->type.data[0] & 0x03) < tls_session->peap_flag) {
+ tls_session->peap_flag = handler->eap_ds->response->type.data[0] & 0x03;
+ }
+
status = eaptls_process(handler);
if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
REDEBUG("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
}
packet = (pwd_id_packet_t *) in;
- if (in_len < sizeof(packet)) {
- RDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(packet));
+ if (in_len < sizeof(*packet)) {
+ RDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(*packet));
return 0;
}
if (req->response) {
RDEBUG("sending chbind response");
fr_pair_add(&fake->reply->vps,
- eap_chbind_packet2vp(fake, req->response));
+ eap_chbind_packet2vp(fake->reply, req->response));
} else {
RDEBUG("no chbind response");
}
/*
* Will do the xlat for us
*/
- return radius_compare_vps(request, check, NULL);
+ return radius_compare_vps(request, check, req);
}
static int generic_attrs[] = {
case LDAP_PROC_NO_RESULT:
RDEBUG2("No cacheable group memberships found in group objects");
+ goto finish;
default:
+ rcode = RLM_MODULE_FAIL;
goto finish;
}
break;
default:
- rad_assert(0);
+ return RLM_MODULE_FAIL;
}
mschap_add_reply(request, ident, "MS-CHAP-Error", buffer, strlen(buffer));
int i;
if (!ht) return;
- for (i = 0; i < ht->tablesize; i++)
- if (ht->table[i])
- destroy_password(ht->table[i]);
if (ht->table) {
+ for (i = 0; i < ht->tablesize; i++) {
+ if (ht->table[i])
+ destroy_password(ht->table[i]);
+ }
free(ht->table);
ht->table = NULL;
}
char *hexbuf = NULL;
DH *aaa_server_dh;
- tls = talloc_zero( hs, fr_tls_server_conf_t);
+ tls = tls_server_conf_alloc(hs);
if (!tls) return NULL;
aaa_server_dh = tid_srvr_get_dh(server);
hs->secret = talloc_strdup(hs, "radsec");
hs->response_window.tv_sec = 30;
hs->last_packet_recv = time(NULL);
-
+ /*
+ * We want sockets using these servers to close as soon as possible,
+ * to make sure that whenever a pool is replaced, sockets using old ones
+ * will not last long (hopefully less than 300s).
+ */
+ hs->limit.idle_timeout = 5;
hs->tls = construct_tls(inst, hs, blk);
if (!hs->tls) goto error;
}
/*
- * This server has received a packet in the last
- * 5 minutes. It doesn't need an update.
- */
- if ((now - server->last_packet_recv) < 300) {
- return false;
- }
-
- /*
* If we've opened in the last 10 minutes, then
* open rather than update.
*/
conn->row = NULL;
SQLFreeStmt(conn->stmt, SQL_DROP);
+ conn->stmt = NULL;
return 0;
}
/*
* sql groupcmp function. That way we can do group comparisons (in the users file for example)
- * with the group memberships reciding in sql
+ * with the group memberships residing in sql
* The group membership query should only return one element which is the username. The returned
* username will then be checked with the passed check string.
*/
}
/*
- * Neither group checks or profiles will work without
+ * Neither group checks nor profiles will work without
* a group membership query.
*/
if (!inst->config->groupmemb_query) goto release;
}
/*
- * At this point the key (user) hasn't be found in the check table, the reply table
+ * At this point the key (user) hasn't been found in the check table, the reply table
* or the group mapping table, and there was no matching profile.
*/
release:
case RLM_SQL_ERROR:
/*
* If we get RLM_SQL_RECONNECT it means all connections in the pool
- * were exhausted, and we couldn't create a new connection,
+ * were exhausted and we couldn't create a new connection,
* so we do not need to call fr_connection_release.
*/
case RLM_SQL_RECONNECT:
(inst->module->sql_finish_query)(handle, inst->config);
RDEBUG("%i record(s) updated", numaffected);
- if (numaffected > 0) break; /* A query succeeded, were done! */
+ if (numaffected > 0) break; /* A query succeeded, we're done! */
next:
/*
* We assume all entries with the same name form a redundant
CONF_PARSER_TERMINATOR
};
-static int find_next_reset(rlm_sqlcounter_t *inst, time_t timeval)
+static int find_next_reset(rlm_sqlcounter_t *inst, REQUEST *request, time_t timeval)
{
int ret = 0;
size_t len;
char sCurrentTime[40], sNextTime[40];
tm = localtime_r(&timeval, &s_tm);
- len = strftime(sCurrentTime, sizeof(sCurrentTime), "%Y-%m-%d %H:%M:%S", tm);
- if (len == 0) *sCurrentTime = '\0';
tm->tm_sec = tm->tm_min = 0;
rad_assert(inst->reset != NULL);
+ /*
+ * Reset every N hours, days, weeks, months.
+ */
if (isdigit((int) inst->reset[0])){
len = strlen(inst->reset);
- if (len == 0)
- return -1;
+ if (len == 0) return -1;
+
last = inst->reset[len - 1];
- if (!isalpha((int) last))
+ if (!isalpha((int) last)) {
last = 'd';
+ }
+
num = atoi(inst->reset);
DEBUG("rlm_sqlcounter: num=%d, last=%c",num,last);
}
+
if (strcmp(inst->reset, "hourly") == 0 || last == 'h') {
/*
* Round up to the next nearest hour.
*/
tm->tm_hour += num;
inst->reset_time = mktime(tm);
+
} else if (strcmp(inst->reset, "daily") == 0 || last == 'd') {
/*
* Round up to the next nearest day.
tm->tm_hour = 0;
tm->tm_mday += num;
inst->reset_time = mktime(tm);
+
} else if (strcmp(inst->reset, "weekly") == 0 || last == 'w') {
/*
* Round up to the next nearest week.
tm->tm_hour = 0;
tm->tm_mday += (7 - tm->tm_wday) +(7*(num-1));
inst->reset_time = mktime(tm);
+
} else if (strcmp(inst->reset, "monthly") == 0 || last == 'm') {
tm->tm_hour = 0;
tm->tm_mday = 1;
tm->tm_mon += num;
inst->reset_time = mktime(tm);
+
} else if (strcmp(inst->reset, "never") == 0) {
inst->reset_time = 0;
+
} else {
return -1;
}
+ if (!request || (rad_debug_lvl < 2)) return ret;
+
+ len = strftime(sCurrentTime, sizeof(sCurrentTime), "%Y-%m-%d %H:%M:%S", tm);
+ if (len == 0) *sCurrentTime = '\0';
+
len = strftime(sNextTime, sizeof(sNextTime),"%Y-%m-%d %H:%M:%S",tm);
if (len == 0) *sNextTime = '\0';
- DEBUG2("rlm_sqlcounter: Current Time: %" PRId64 " [%s], Next reset %" PRId64 " [%s]",
- (int64_t) timeval, sCurrentTime, (int64_t) inst->reset_time, sNextTime);
+ RDEBUG2("rlm_sqlcounter: Current Time: %" PRId64 " [%s], Next reset %" PRId64 " [%s]",
+ (int64_t) timeval, sCurrentTime, (int64_t) inst->reset_time, sNextTime);
return ret;
}
*/
tm->tm_hour -= num - 1;
inst->last_reset = mktime(tm);
+
} else if (strcmp(inst->reset, "daily") == 0 || last == 'd') {
/*
* Round down to the prev nearest day.
tm->tm_hour = 0;
tm->tm_mday -= num - 1;
inst->last_reset = mktime(tm);
+
} else if (strcmp(inst->reset, "weekly") == 0 || last == 'w') {
/*
* Round down to the prev nearest week.
tm->tm_hour = 0;
tm->tm_mday -= tm->tm_wday +(7*(num-1));
inst->last_reset = mktime(tm);
+
} else if (strcmp(inst->reset, "monthly") == 0 || last == 'm') {
tm->tm_hour = 0;
tm->tm_mday = 1;
tm->tm_mon -= num - 1;
inst->last_reset = mktime(tm);
+
} else if (strcmp(inst->reset, "never") == 0) {
inst->reset_time = 0;
+
} else {
return -1;
}
now = time(NULL);
inst->reset_time = 0;
- if (find_next_reset(inst, now) == -1) {
+ if (find_next_reset(inst, NULL, now) < 0) {
cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset);
return -1;
}
* Re-set the next time and prev_time for this counters range
*/
inst->last_reset = inst->reset_time;
- find_next_reset(inst,request->timestamp);
+ find_next_reset(inst, request, request->timestamp);
}
/*
Name: freeradius-server
-Version: 3.0.13
+Version: 3.0.14
Release: 0
License: GPLv2 ; LGPLv2.1
Group: Productivity/Networking/Radius/Servers
}
#
-# Session database modules
-#
-/var/log/radius/radutmp /var/log/radius/radwtmp {
- nocreate
- size=+2048k
-}
-
-#
# SQL log files
#
/var/log/radius/sqllog.sql {