STATIC_MODULES = @STATIC_MODULES@
LIBREADLINE = @LIBREADLINE@
+WITH_DHCP = @WITH_DHCP@
+
#
# Version to use for packaging and other Make related things
#
SNMPGET
PERL
openssl_version_check_config
+WITH_DHCP
modconfdir
dictdir
raddbdir
fi
+
STATIC_MODULES=
# Check whether --with-static_modules was given.
if test "x$WITH_DHCP" = "xyes"; then
AC_DEFINE(WITH_DHCP, [1], [define if you want DHCP support])
fi
+AC_SUBST(WITH_DHCP)
dnl #
dnl # Allow the user to specify a list of modules to be linked
+freeradius (3.0.15+moonshot1-0) unstable; urgency=medium
+
+ * Merged from upstream release_3.0.15
+
+ -- Painless Security <build@painless-security.com> Mon, 17 Jul 2017 18:54:00 -0500
+
+freeradius (3.0.15+git) unstable; urgency=medium
+
+ * New upstream version.
+
+ -- Alan DeKok <aland@freeradius.org> Mon, 29 May 2017 12:00:00 -0400
+
freeradius (3.0.14+moonshot4-1) unstable; urgency=medium
* Merged from release_3.0.14
-FreeRADIUS 3.0.14 Mon 06 Mar 2017 13:00:00 EDT urgency=medium
+FreeRADIUS 3.0.15 Mon 17 Jul 2017 09:00:00 EDT urgency=high
+ Feature improvements
+ * Provide HOSTNAME in default systemd files.
+ * Incorporate RedHat specific files
+ * Update dictionary.starent, dictionary.ruckus
+ * Allow builds without TCP or DHCP
+
+ Bug fixes
+ * Fix multiple issues. See this web page for details:
+ http://freeradius.org/security/fuzzer-2017.html
+ * Pass correct statement length into sqlite3_prepare[_v2]
+ * Bind the lifetime of program name and python path to the module
+ * Check input / output length in make_secret().
+ FR-GV-201
+ * Fix read overflow when decoding DHCP option 63
+ FR-GV-206
+ * Fix write overflow in data2vp_wimax()
+ FR-GV-301
+ * Fix infinite loop and memory exhaustion with 'concat' attributes
+ FR-GV-302
+ * Fix infinite read in dhcp_attr2vp()
+ FR-GV-303
+ * Fix buffer over-read in fr_dhcp_decode_suboptions()
+ FR-GV-304
+ * Decode 'signed' attributes correctly.
+ FR-GV-305
+ * use strncmp() instead of memcmp() for bounded data
+ FR-AD-001
+ * Bind the lifetime of program name and python path to the module
+ FR-AD-002
+ * Pass correct statement length into sqlite3_prepare[_v2]
+ FR-AD-003
+ * print messages when we see deprecated configuration
+ items
+ * show reasons why we couldn't parse a certificate
+ expiry time
+ * be more accepting about truncated ASN1 times.
+ * Fix OpenSSL API issue which could leak small amounts
+ of memory. Issue reported by Guido Vranken.
+ * For Access-Reject, call rad_authlog() after running
+ the post-auth section, just like for Access-Accept.
+ * don't crash when reading corrupted data from session
+ resumption cache. Fixes #1999.
+ * Parse port in dhcpclient. Fixes #2000.
+ * Don't leak memory for OpenSSL.
+ Patch from Guido Vranken.
+ * Portability fixes taken from OpenBSD port collection.
+ * run rad_authlog after post-auth for Access-Reject.
+ * Don't process VMPS packets twice.
+ * Fix attribute truncation in rlm_perl
+ * Fix bug when processing huntgroups.
+
+FreeRADIUS 3.0.14 Fri 26 May 2017 13:00:00 EDT urgency=medium
Feature improvements
* Enforce TLS client certificate expiration on
session resumption, and Session-Timeout.
# re-generate these commands.
#
if [ ! -f dh ]; then
- openssl dhparam -out dh 1024 || exit 1
+ openssl dhparam -out dh 2048 || exit 1
if [ -e /dev/urandom ] ; then
ln -sf /dev/urandom random
else
# 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:
file = ${logdir}/radius.log
#
- # If this configuration parameter is set, then log messages for
- # a *request* go to this file, rather than to radius.log.
- #
- # i.e. This is a log file per request, once the server has accepted
- # the request as being from a valid client. Messages that are
- # not associated with a request still go to radius.log.
- #
- # Not all log messages in the server core have been updated to use
- # this new internal API. As a result, some messages will still
- # go to radius.log. Please submit patches to fix this behavior.
- #
- # The file name is expanded dynamically. You should ONLY user
- # server-side attributes for the filename (e.g. things you control).
- # Using this feature MAY also slow down the server substantially,
- # especially if you do thinks like SQL calls as part of the
- # expansion of the filename.
- #
- # The name of the log file should use attributes that don't change
- # over the lifetime of a request, such as User-Name,
- # Virtual-Server or Packet-Src-IP-Address. Otherwise, the log
- # messages will be distributed over multiple files.
- #
- # Logging can be enabled for an individual request by a special
- # dynamic expansion macro: %{debug: 1}, where the debug level
- # for this request is set to '1' (or 2, 3, etc.). e.g.
- #
- # ...
- # update control {
- # Tmp-String-0 = "%{debug:1}"
- # }
- # ...
- #
- # The attribute that the value is assigned to is unimportant,
- # and should be a "throw-away" attribute with no side effects.
- #
- #requests = ${logdir}/radiusd-%{%{Virtual-Server}:-DEFAULT}-%Y%m%d.log
-
- #
# Which syslog facility to use, if ${destination} == "syslog"
#
# The exact values permitted here are OS-dependent. You probably
Summary: High-performance and highly configurable free RADIUS server
Name: freeradius
-Version: 3.0.14
+Version: 3.0.15
Release: 2%{?dist}
License: GPLv2+ and LGPLv2+
Group: System Environment/Daemons
URL: http://www.freeradius.org/
Source0: ftp://ftp.freeradius.org/pub/radius/freeradius-server-%{version}.tar.bz2
+%if %{?_unitdir:1}%{!?_unitdir:0}
+Source100: radiusd.service
+%else
Source100: freeradius-radiusd-init
+%define initddir %{?_initddir:%{_initddir}}%{!?_initddir:%{_initrddir}}
+%endif
+
Source102: freeradius-logrotate
Source103: freeradius-pam-conf
-Source104: radiusd.service
Obsoletes: freeradius-devel
Obsoletes: freeradius-libs
BuildRequires: gdbm-devel
BuildRequires: libtool
BuildRequires: libtool-ltdl-devel
-BuildRequires: openssl-devel
+BuildRequires: openssl, openssl-devel
BuildRequires: pam-devel
BuildRequires: zlib-devel
BuildRequires: net-snmp-devel
# For systemd based systems, that define _unitdir, install the radiusd unit
%if %{?_unitdir:1}%{!?_unitdir:0}
-install -D -m 755 %{SOURCE104} $RPM_BUILD_ROOT/%{_unitdir}/radiusd.service
+install -D -m 755 redhat/radiusd.service $RPM_BUILD_ROOT/%{_unitdir}/radiusd.service
# For SystemV install the init script
%else
-install -D -m 755 %{SOURCE100} $RPM_BUILD_ROOT/%{initddir}/radiusd
+install -D -m 755 redhat/freeradius-radiusd-init $RPM_BUILD_ROOT/%{initddir}/radiusd
%endif
-install -D -m 644 %{SOURCE102} $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/radiusd
-install -D -m 644 %{SOURCE103} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/radiusd
+install -D -m 644 redhat/freeradius-logrotate $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/radiusd
+install -D -m 644 redhat/freeradius-pam-conf $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/radiusd
# remove unneeded stuff
rm -rf doc/00-OLD
%preun
if [ $1 = 0 ]; then
- /sbin/service radiusd stop > /dev/null 2>&1
+%if %{?_unitdir:1}%{!?_unitdir:0}
+ /bin/systemctl disable radiusd
+%else
/sbin/chkconfig --del radiusd
+%endif
fi
-
%postun
if [ $1 -ge 1 ]; then
/sbin/service radiusd condrestart >/dev/null 2>&1 || :
Type=forking
PIDFile=/var/run/radiusd/radiusd.pid
EnvironmentFile=-/etc/sysconfig/radiusd
+
+# FreeRADIUS can do static evaluation of policy language rules based
+# on environmental variables which is very useful for doing per-host
+# customization.
+# Unfortunately systemd does not allow variable substitutions such
+# as %H or $(hostname) in the EnvironmentFile.
+# We provide HOSTNAME here for convenience.
+Environment=HOSTNAME=%H
+
+RuntimeDirectory=/var/run/radiusd
+RuntimeDirectoryMode=0775
ExecStartPre=/usr/sbin/radiusd $FREERADIUS_OPTIONS -Cxm -lstdout
+ExecStartPre=/usr/bin/chown radiusd:radiusd /var/run/radiusd
ExecStart=/usr/sbin/radiusd $FREERADIUS_OPTIONS -m
Restart=on-failure
RestartSec=5
# define LD_LIBRARY_PATH_LOCAL "DYLD_FALLBACK_LIBRARY_PATH"
#endif
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || (defined(__sun) && defined(__GNUC__))
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || (defined(__sun) && defined(__GNUC__))
# define SHELL_CMD "/bin/sh"
# define DYNAMIC_LIB_EXT "so"
# define MODULE_LIB_EXT "so"
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-HTTP-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 Ruckus-Zone-Name 134 string
ATTRIBUTE Ruckus-Wlan-Name 135 string
+ATTRIBUTE Ruckus-Read-Preference 137 octets
+ATTRIBUTE Ruckus-Client-Host-Name 138 string
+ATTRIBUTE Ruckus-Client-Os-Type 139 string
+ATTRIBUTE Ruckus-Client-Os-Class 140 string
+ATTRIBUTE Ruckus-Vlan-Pool 141 string
+
#
# Integer Translations
#
ATTRIBUTE SN-TrafficSelector-Class 307 integer
ATTRIBUTE SN-DHCP-Options 309 octets
ATTRIBUTE SN-Handoff-Indicator 310 integer
+ATTRIBUTE SN-User-Privilege 313 integer
+ATTRIBUTE SN-IPv6-Alloc-Method 314 integer
+ATTRIBUTE SN-Congestion-Mgmt-Policy 315 string
+ATTRIBUTE SN-WSG-MIP-Required 316 integer
+ATTRIBUTE SN-WSG-MIP-Release-TIA 317 integer
+ATTRIBUTE SN-WSG-MIP-Simple-IP-Fallback 318 integer
+ATTRIBUTE SN-WLAN-AP-Identifier 319 octets
+ATTRIBUTE SN-WLAN-UE-Identifier 320 octets
+
ATTRIBUTE SNA-PPP-Ctrl-Input-Octets 1001 integer
ATTRIBUTE SNA-PPP-Ctrl-Output-Octets 1002 integer
VALUE SN-WiMAX-Auth-Only Disabled 0
VALUE SN-WiMAX-Auth-Only Enabled 1
+VALUE SN-User-Privilege Administrative 6
+VALUE SN-User-Privilege NAS_Prompt 7
+VALUE SN-User-Privilege Inspector 19650516
+VALUE SN-User-Privilege Security_Admin 19660618
+
+VALUE SN-IPv6-Alloc-Method Alloc_Local_Pool 0
+VALUE SN-IPv6-Alloc-Method Alloc_Dhcp_Client 1
+VALUE SN-IPv6-Alloc-Method Alloc_No_Alloc 2
+VALUE SN-IPv6-Alloc-Method Alloc_Static_Alloc 3
+
+VALUE SN-WSG-MIP-Required No 0
+VALUE SN-WSG-MIP-Required Yes 1
+
+VALUE SN-WSG-MIP-Release-TIA No 0
+VALUE SN-WSG-MIP-Release-TIA Yes 1
+
+VALUE SN-WSG-MIP-Simple-IP-Fallback No 0
+VALUE SN-WSG-MIP-Simple-IP-Fallback Yes 1
+
END-VENDOR Starent
case DLT_RAW:
case DLT_NULL:
case DLT_LOOP:
+#ifdef DLT_LINUX_SLL
case DLT_LINUX_SLL:
+#endif
case DLT_PFLOG:
return true;
return -1;
}
+#ifdef DLT_LINUX_SLL
case DLT_LINUX_SLL:
p += 16;
if (((size_t)(p - data)) > len) {
goto ood;
}
break;
+#endif
case DLT_PFLOG:
p += 28;
* encrypting passwords to RADIUS.
*/
static void make_secret(uint8_t *digest, uint8_t const *vector,
- char const *secret, uint8_t const *value)
+ char const *secret, uint8_t const *value, size_t length)
{
FR_MD5_CTX context;
- int i;
+ size_t i;
fr_md5_init(&context);
fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
fr_md5_update(&context, (uint8_t const *) secret, strlen(secret));
fr_md5_final(digest, &context);
- for ( i = 0; i < AUTH_VECTOR_LEN; i++ ) {
+ for ( i = 0; i < length; i++ ) {
digest[i] ^= value[i];
}
}
* always fits.
*/
case FLAG_ENCRYPT_ASCEND_SECRET:
- if (len != 16) return 0;
- make_secret(ptr, packet->vector, secret, data);
+ if (len > AUTH_VECTOR_LEN) len = AUTH_VECTOR_LEN;
+ make_secret(ptr, packet->vector, secret, data, len);
len = AUTH_VECTOR_LEN;
break;
* don't care about walking off of the end of it.
*/
while (ptr < end) {
+ if (ptr[1] < 2) return -1;
+ if ((ptr + ptr[1]) > end) return -1;
+
total += ptr[1] - 2;
ptr += ptr[1];
+ if (ptr == end) break;
+
/*
* Attributes MUST be consecutive.
*/
if (ptr[0] != attr) break;
}
+ end = ptr;
+
vp = fr_pair_afrom_da(ctx, da);
if (!vp) return -1;
total = 0;
ptr = start;
- while (total < vp->vp_length) {
+ while (ptr < end) {
memcpy(p, ptr + 2, ptr[1] - 2);
p += ptr[1] - 2;
total += ptr[1] - 2;
}
*pvp = vp;
+
return ptr - start;
}
VALUE_PAIR **pvp)
{
ssize_t rcode;
- size_t fraglen;
+ size_t ext_len;
+ bool more;
uint8_t *head, *tail;
- uint8_t const *frag, *end;
- uint8_t const *attr;
- int fragments;
- bool last_frag;
+ uint8_t const *attr, *end;
+ DICT_ATTR const *child;
- if (attrlen < 3) return -1;
+ /*
+ * data = Ext-Attr Flag ...
+ */
+
+ /*
+ * Not enough room for Ext-Attr + Flag + data, it's a bad
+ * attribute.
+ */
+ if (attrlen < 3) {
+ raw:
+ /*
+ * It's not an Extended attribute, it's unknown...
+ */
+ child = dict_unknown_afrom_fields(ctx, (da->vendor/ FR_MAX_VENDOR) & 0xff, 0);
+ if (!child) {
+ fr_strerror_printf("Internal sanity check %d", __LINE__);
+ return -1;
+ }
+
+ rcode = data2vp(ctx, packet, original, secret, child,
+ data, attrlen, attrlen, pvp);
+ if (rcode < 0) return rcode;
+ return attrlen;
+ }
+
+ /*
+ * No continued data, just decode the attribute in place.
+ */
+ if ((data[1] & 0x80) == 0) {
+ rcode = data2vp(ctx, packet, original, secret, da,
+ data + 2, attrlen - 2, attrlen - 2,
+ pvp);
+
+ if ((rcode < 0) || (((size_t) rcode + 2) != attrlen)) goto raw; /* didn't decode all of the data */
+ return attrlen;
+ }
+
+ /*
+ * It's continued, but there are no subsequent fragments,
+ * it's bad.
+ */
+ if (attrlen >= packetlen) goto raw;
/*
* Calculate the length of all of the fragments. For
* now, they MUST be contiguous in the packet, and they
- * MUST be all of the same TYPE and EXTENDED-TYPE
+ * MUST be all of the same Type and Ext-Type
+ *
+ * We skip the first fragment, which doesn't have a
+ * RADIUS attribute header.
*/
- attr = data - 2;
- fraglen = attrlen - 2;
- frag = data + attrlen;
+ ext_len = attrlen - 2;
+ attr = data + attrlen;
end = data + packetlen;
- fragments = 1;
- last_frag = false;
-
- while (frag < end) {
- if (last_frag ||
- (frag[0] != attr[0]) ||
- (frag[1] < 4) || /* too short for long-extended */
- (frag[2] != attr[2]) ||
- ((frag + frag[1]) > end)) { /* overflow */
- end = frag;
- break;
- }
- last_frag = ((frag[3] & 0x80) == 0);
+ while (attr < end) {
+ /*
+ * Not enough room for Attr + length + Ext-Attr
+ * continuation, it's bad.
+ */
+ if ((end - attr) < 4) goto raw;
+
+ if (attr[1] < 4) goto raw;
+
+ /*
+ * If the attribute overflows the packet, it's
+ * bad.
+ */
+ if ((attr + attr[1]) > end) goto raw;
+
+ if (attr[0] != ((da->vendor / FR_MAX_VENDOR) & 0xff)) goto raw; /* not the same Extended-Attribute-X */
+
+ if (attr[2] != data[0]) goto raw; /* Not the same Ext-Attr */
- fraglen += frag[1] - 4;
- frag += frag[1];
- fragments++;
+ /*
+ * Check the continuation flag.
+ */
+ more = ((attr[2] & 0x80) != 0);
+
+ /*
+ * Or, there's no more data, in which case we
+ * shorten "end" to finish at this attribute.
+ */
+ if (!more) end = attr + attr[1];
+
+ /*
+ * There's more data, but we're at the end of the
+ * packet. The attribute is malformed!
+ */
+ if (more && ((attr + attr[1]) == end)) goto raw;
+
+ /*
+ * Add in the length of the data we need to
+ * concatenate together.
+ */
+ ext_len += attr[1] - 4;
+
+ /*
+ * Go to the next attribute, and stop if there's
+ * no more.
+ */
+ attr += attr[1];
+ if (!more) break;
}
- head = tail = malloc(fraglen);
- if (!head) return -1;
+ if (!ext_len) goto raw;
- VP_TRACE("Fragments %d, total length %d\n", fragments, (int) fraglen);
+ head = tail = malloc(ext_len);
+ if (!head) goto raw;
/*
- * And again, but faster and looser.
- *
- * We copy the first fragment, followed by the rest of
- * the fragments.
+ * Copy the data over, this time trusting the attribute
+ * contents.
*/
- frag = attr;
+ attr = data;
+ memcpy(tail, attr + 2, attrlen - 2);
+ tail += attrlen - 2;
+ attr += attrlen;
- while (fragments > 0) {
- memcpy(tail, frag + 4, frag[1] - 4);
- tail += frag[1] - 4;
- frag += frag[1];
- fragments--;
+ while (attr < end) {
+ memcpy(tail, attr + 4, attr[1] - 4);
+ tail += attr[1] - 4;
+ attr += attr[1]; /* skip VID+WiMax header */
}
- VP_HEXDUMP("long-extended fragments", head, fraglen);
+ VP_HEXDUMP("long-extended fragments", head, ext_len);
rcode = data2vp(ctx, packet, original, secret, da,
- head, fraglen, fraglen, pvp);
+ head, ext_len, ext_len, pvp);
free(head);
- if (rcode < 0) return rcode;
+ if (rcode < 0) goto raw;
return end - data;
}
-/** Convert a Vendor-Specific WIMAX to vps
+/** Convert a Vendor-Specific WIMAX to VPs
*
* @note Called ONLY for Vendor-Specific
*/
VALUE_PAIR **pvp)
{
ssize_t rcode;
- size_t fraglen;
- bool last_frag;
+ size_t wimax_len;
+ bool more;
uint8_t *head, *tail;
- uint8_t const *frag, *end;
+ uint8_t const *attr, *end;
DICT_ATTR const *child;
- if (attrlen < 8) return -1;
+ /*
+ * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
+ */
- if (((size_t) (data[5] + 4)) != attrlen) return -1;
+ /*
+ * Not enough room for WiMAX Vendor + Wimax attr + length
+ * + continuation, it's a bad attribute.
+ */
+ if (attrlen < 8) {
+ raw:
+ /*
+ * It's not a Vendor-Specific, it's unknown...
+ */
+ child = dict_unknown_afrom_fields(ctx, PW_VENDOR_SPECIFIC, 0);
+ if (!child) {
+ fr_strerror_printf("Internal sanity check %d", __LINE__);
+ return -1;
+ }
+
+ rcode = data2vp(ctx, packet, original, secret, child,
+ data, attrlen, attrlen, pvp);
+ if (rcode < 0) return rcode;
+ return attrlen;
+ }
+
+ if (data[5] < 3) goto raw; /* WiMAX-Length is too small */
child = dict_attrbyvalue(data[4], vendor);
- if (!child) return -1;
+ if (!child) goto raw;
+ /*
+ * No continued data, just decode the attribute in place.
+ */
if ((data[6] & 0x80) == 0) {
+ if ((data[5] + 4) != attrlen) goto raw; /* WiMAX attribute doesn't fill Vendor-Specific */
+
rcode = data2vp(ctx, packet, original, secret, child,
data + 7, data[5] - 3, data[5] - 3,
pvp);
- if (rcode < 0) return -1;
- return 7 + rcode;
+
+ if ((rcode < 0) || (((size_t) rcode + 7) != attrlen)) goto raw; /* didn't decode all of the data */
+ return attrlen;
}
/*
* MUST be all of the same VSA, WiMAX, and WiMAX-attr.
*
* The first fragment doesn't have a RADIUS attribute
- * header, so it needs to be treated a little special.
+ * header.
*/
- fraglen = data[5] - 3;
- frag = data + attrlen;
+ wimax_len = 0;
+ attr = data + 4;
end = data + packetlen;
- last_frag = false;
-
- while (frag < end) {
- if (last_frag ||
- (frag[0] != PW_VENDOR_SPECIFIC) ||
- (frag[1] < 9) || /* too short for wimax */
- ((frag + frag[1]) > end) || /* overflow */
- (memcmp(frag + 2, data, 4) != 0) || /* not wimax */
- (frag[6] != data[4]) || /* not the same wimax attr */
- ((frag[7] + 6) != frag[1])) { /* doesn't fill the attr */
- end = frag;
- break;
- }
- last_frag = ((frag[8] & 0x80) == 0);
+ while (attr < end) {
+ /*
+ * Not enough room for Attribute + length +
+ * continuation, it's bad.
+ */
+ if ((end - attr) < 3) goto raw;
- fraglen += frag[7] - 3;
- frag += frag[1];
- }
+ /*
+ * Must have non-zero data in the attribute.
+ */
+ if (attr[1] <= 3) goto raw;
- head = tail = malloc(fraglen);
- if (!head) return -1;
+ /*
+ * If the WiMAX attribute overflows the packet,
+ * it's bad.
+ */
+ if ((attr + attr[1]) > end) goto raw;
+
+ /*
+ * Check the continuation flag.
+ */
+ more = ((attr[2] & 0x80) != 0);
+
+ /*
+ * Or, there's no more data, in which case we
+ * shorten "end" to finish at this attribute.
+ */
+ if (!more) end = attr + attr[1];
+
+ /*
+ * There's more data, but we're at the end of the
+ * packet. The attribute is malformed!
+ */
+ if (more && ((attr + attr[1]) == end)) goto raw;
+
+ /*
+ * Add in the length of the data we need to
+ * concatenate together.
+ */
+ wimax_len += attr[1] - 3;
+
+ /*
+ * Go to the next attribute, and stop if there's
+ * no more.
+ */
+ attr += attr[1];
+ if (!more) break;
+
+ /*
+ * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
+ *
+ * attr = Vendor-Specific VSA-Length VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
+ *
+ */
+
+ /*
+ * No room for Vendor-Specific + length +
+ * Vendor(4) + attr + length + continuation + data
+ */
+ if ((end - attr) < 9) goto raw;
+
+ if (attr[0] != PW_VENDOR_SPECIFIC) goto raw;
+ if (attr[1] < 9) goto raw;
+ if ((attr + attr[1]) > end) goto raw;
+ if (memcmp(data, attr + 2, 4) != 0) goto raw; /* not WiMAX Vendor ID */
+
+ if (attr[1] != (attr[7] + 6)) goto raw; /* WiMAX attr doesn't exactly fill the VSA */
+
+ if (data[4] != attr[6]) goto raw; /* different WiMAX attribute */
+
+ /*
+ * Skip over the Vendor-Specific header, and
+ * continue with the WiMAX attributes.
+ */
+ attr += 6;
+ }
/*
- * And again, but faster and looser.
- *
- * We copy the first fragment, followed by the rest of
- * the fragments.
+ * No data in the WiMAX attribute, make a "raw" one.
*/
- frag = data;
+ if (!wimax_len) goto raw;
- memcpy(tail, frag + 4 + 3, frag[4 + 1] - 3);
- tail += frag[4 + 1] - 3;
- frag += attrlen; /* should be frag[1] - 7 */
+ head = tail = malloc(wimax_len);
+ if (!head) return -1;
/*
- * frag now points to RADIUS attributes
+ * Copy the data over, this time trusting the attribute
+ * contents.
*/
- do {
- memcpy(tail, frag + 2 + 4 + 3, frag[2 + 4 + 1] - 3);
- tail += frag[2 + 4 + 1] - 3;
- frag += frag[1];
- } while (frag < end);
+ attr = data;
+ while (attr < end) {
+ memcpy(tail, attr + 4 + 3, attr[4 + 1] - 3);
+ tail += attr[4 + 1] - 3;
+ attr += 4 + attr[4 + 1]; /* skip VID+WiMax header */
+ attr += 2; /* skip Vendor-Specific header */
+ }
- VP_HEXDUMP("wimax fragments", head, fraglen);
+ VP_HEXDUMP("wimax fragments", head, wimax_len);
rcode = data2vp(ctx, packet, original, secret, child,
- head, fraglen, fraglen, pvp);
+ head, wimax_len, wimax_len, pvp);
free(head);
- if (rcode < 0) return rcode;
+ if (rcode < 0) goto raw;
return end - data;
}
goto raw;
} else {
uint8_t my_digest[AUTH_VECTOR_LEN];
+ size_t secret_len;
+
+ secret_len = datalen;
+ if (secret_len > AUTH_VECTOR_LEN) secret_len = AUTH_VECTOR_LEN;
+
make_secret(my_digest,
original->vector,
- secret, data);
+ secret, data, secret_len);
memcpy(buffer, my_digest,
AUTH_VECTOR_LEN );
buffer[AUTH_VECTOR_LEN] = '\0';
}
/*
- * If there no more fragments, then the contents
- * have to be a well-known data type.
- *
- */
- if ((data[1] & 0x80) == 0) {
- rcode = data2vp(ctx, packet, original, secret, child,
- data + 2, attrlen - 2, attrlen - 2,
- pvp);
- if (rcode < 0) goto raw;
- return 2 + rcode;
- }
-
- /*
* This requires a whole lot more work.
*/
return data2vp_extended(ctx, packet, original, secret, child,
break;
case PW_TYPE_SIGNED: /* overloaded with vp_integer */
- memcpy(&vp->vp_integer, buffer, 4);
+ memcpy(&vp->vp_integer, data, 4);
vp->vp_integer = ntohl(vp->vp_integer);
break;
case PW_TYPE_OCTETS:
case PW_TYPE_TLV:
{
- size_t max;
+ size_t binlen;
+ size_t hexlen;
- /* Return the number of bytes we would have written */
- len = (inlen * 2) + 2;
- if (freespace <= 1) {
- return len;
- }
+ binlen = inlen;
+ hexlen = (binlen * 2) + 2; /* NOT accounting for trailing NUL */
- *out++ = '0';
- freespace--;
+ /*
+ * If the buffer is too small, put something into
+ * it, and return how much we should have written
+ *
+ * 0 + x + H + H + NUL = 5
+ */
+ if (freespace < 5) {
+ switch (freespace) {
+ case '4':
+ case '3':
+ out[0] = '0';
+ out[1] = 'x';
+ out[2] = '\0';
+ return hexlen;
+
+ case 2:
+ *out = '0';
+ out++;
+ /* FALL-THROUGH */
+
+ case 1:
+ *out = '\0';
+ break;
+
+ case 0:
+ break;
+ }
- if (freespace <= 1) {
- *out = '\0';
- return len;
+ return hexlen;
}
- *out++ = 'x';
- freespace--;
- if (freespace <= 2) {
- *out = '\0';
- return len;
+ /*
+ * The output buffer is at least 5 bytes, we haev
+ * room for '0xHH' plus a trailing NUL byte.
+ */
+ out[0] = '0';
+ out[1] = 'x';
+
+ /*
+ * Get maximum number of bytes we can encode
+ * given freespace, ensuring we account for '0',
+ * 'x', and the trailing NUL in the buffer.
+ *
+ * Note that we can't have "freespace = 0" after
+ * this, as 'freespace' has to be at least 5.
+ */
+ freespace -= 3;
+ freespace /= 2;
+ if (binlen > freespace) {
+ binlen = freespace;
}
- /* Get maximum number of bytes we can encode given freespace */
- max = ((freespace % 2) ? freespace - 1 : freespace - 2) / 2;
- fr_bin2hex(out, data->octets, ((size_t)inlen > max) ? max : (size_t)inlen);
+ fr_bin2hex(out + 2, data->octets, binlen);
+ return hexlen;
}
- return len;
case PW_TYPE_IFID:
a = ifid_ntoa(buf, sizeof(buf), data->ifid);
request->reply->code = PW_CODE_ACCESS_REJECT;
}
+ if (request->reply->code == PW_CODE_ACCESS_REJECT) {
+ if ((vp = fr_pair_find_by_num(request->packet->vps, PW_MODULE_FAILURE_MESSAGE, 0, TAG_ANY)) != NULL) {
+ char msg[MAX_STRING_LEN+19];
+
+ snprintf(msg, sizeof(msg), "Login incorrect (%s)",
+ vp->vp_strvalue);
+ rad_authlog(msg, request, 0);
+ } else {
+ rad_authlog("Login incorrect", request, 0);
+ }
+ }
+
/*
* If we're still accepting the user, say so.
*/
RDEBUG2("Failed to authenticate the user");
request->reply->code = PW_CODE_ACCESS_REJECT;
- if ((module_msg = fr_pair_find_by_num(request->packet->vps, PW_MODULE_FAILURE_MESSAGE, 0, TAG_ANY)) != NULL){
- char msg[MAX_STRING_LEN+19];
-
- snprintf(msg, sizeof(msg), "Login incorrect (%s)",
- module_msg->vp_strvalue);
- rad_authlog(msg, request, 0);
- } else {
- rad_authlog("Login incorrect", request, 0);
- }
-
if (request->password) {
VERIFY_VP(request->password);
/* double check: maybe the secret is wrong? */
ERROR("%s[%d]: Reference \"%s\" type is invalid", cf, *lineno, input);
return NULL;
}
- } else if (memcmp(ptr, "$ENV{", 5) == 0) {
+ } else if (strncmp(ptr, "$ENV{", 5) == 0) {
char *env;
ptr += 5;
(variables[i + 1].data == variables[i].data)) {
cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", variables[i].name,
variables[i + 1].name);
+ } else {
+ cf_log_err(&(cs->item), "Cannot use deprecated configuration item \"%s\"", variables[i].name);
}
goto finish;
}
if (check_config) return;
if (!main_config.proxy_requests) return;
if (!head) return;
+#ifdef WITH_TCP
if (!home_servers_udp) return;
+#endif
/*
* We passed "-i" on the command line. Use that address
FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, <=, 120);
FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, >=, 0, 1000);
- FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0);
FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=,
main_config.max_request_time, 0);
+ FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0);
FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, >=, 1);
FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, <=, 1000);
switch (proto) {
case IPPROTO_UDP:
+#ifdef WITH_TCP
home_servers_udp = true;
+#endif
break;
case IPPROTO_TCP:
memset(&t, 0, sizeof(t));
- if ((end - p) <= 12) {
+ if ((end - p) <= 13) {
if ((end - p) < 2) {
fr_strerror_printf("ASN1 date string too short, expected 2 additional bytes, got %zu bytes",
end - p);
t.tm_year -= 1900;
}
- if ((end - p) < 10) {
+ if ((end - p) < 4) {
fr_strerror_printf("ASN1 string too short, expected 10 additional bytes, got %zu bytes",
end - p);
return -1;
t.tm_mon += (*(p++) - '0') - 1; // -1 since January is 0 not 1.
t.tm_mday = (*(p++) - '0') * 10;
t.tm_mday += (*(p++) - '0');
+
+ if ((end - p) < 2) goto done;
t.tm_hour = (*(p++) - '0') * 10;
t.tm_hour += (*(p++) - '0');
+
+ if ((end - p) < 2) goto done;
t.tm_min = (*(p++) - '0') * 10;
t.tm_min += (*(p++) - '0');
+
+ if ((end - p) < 2) goto done;
t.tm_sec = (*(p++) - '0') * 10;
t.tm_sec += (*(p++) - '0');
/* Apparently OpenSSL converts all timestamps to UTC? Maybe? */
+done:
*out = timegm(&t);
return 0;
}
/* not safe to un-persist a session w/o VPs */
RWDEBUG("Failed loading persisted VPs for session %s", buffer);
SSL_SESSION_free(sess);
+ sess = NULL;
goto error;
}
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);
+ RDEBUG2("Failed getting certificate expiration, removing cache entry for session %s - %s", buffer, fr_strerror());
SSL_SESSION_free(sess);
+ sess = NULL;
goto error;
}
if (expires <= request->timestamp) {
RDEBUG2("Certificate has expired, removing cache entry for session %s", buffer);
SSL_SESSION_free(sess);
+ sess = NULL;
goto error;
}
char cn_str[1024];
char buf[64];
X509 *client_cert;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
const STACK_OF(X509_EXTENSION) *ext_list;
#else
STACK_OF(X509_EXTENSION) *ext_list;
}
}
if (names != NULL)
- sk_GENERAL_NAME_free(names);
+ GENERAL_NAMES_free(names);
}
/*
SSL_CTX_set_verify_depth(ctx, conf->verify_depth);
}
+#ifndef LIBRESSL_VERSION_NUMBER
/* Load randomness */
if (conf->random_file) {
if (!(RAND_load_file(conf->random_file, 1024*10))) {
return NULL;
}
}
+#endif
/*
* Set the cipher list if we were told to
* Only check for certificate things if we don't have a
* PSK query.
*/
+#ifdef PSK_MAX_IDENTITY_LEN
if (conf->psk_identity) {
if (conf->private_key_file) {
WARN(LOG_PREFIX ": Ignoring private key file due to psk_identity being used");
WARN(LOG_PREFIX ": Ignoring certificate file due to psk_identity being used");
}
- } else {
+ } else
+#endif
+ {
if (!conf->private_key_file) {
ERROR(LOG_PREFIX ": TLS Server requires a private key file");
goto error;
+ifneq "$(WITH_DHCP)" "no"
SUBMAKEFILES := libfreeradius-dhcp.mk proto_dhcp.mk rlm_dhcp.mk dhcpclient.mk
+endif
uint32_t attr;
/*
+ * Not enough room for the option header, it's a
+ * bad packet.
+ */
+ if ((p + 2) > (data + len)) {
+ fr_pair_list_free(&head);
+ return -1;
+ }
+
+ /*
+ * Not enough room for the option header + data,
+ * it's a bad packet.
+ */
+ if ((p + 2 + p[1]) > (data + len)) {
+ fr_pair_list_free(&head);
+ return -1;
+ }
+
+ /*
* The initial OID string looks like:
* <iana>.0
*
* multiple additional VPs
*/
fr_cursor_init(&cursor, vp_p);
- for (;;) {
- q = memchr(p, '\0', q - p);
+ while (p < end) {
+ q = memchr(p, '\0', end - p);
/* Malformed but recoverable */
if (!q) q = end;
fr_pair_value_bstrncpy(vp, (char const *)p, q - p);
p = q + 1;
+ if (p >= end) break;
+
/* Need another VP for the next round */
- if (p < end) {
- vp = fr_pair_afrom_da(ctx, vp->da);
- if (!vp) {
- fr_pair_list_free(vp_p);
- return -1;
- }
- fr_cursor_insert(&cursor, vp);
- continue;
+ vp = fr_pair_afrom_da(ctx, vp->da);
+ if (!vp) {
+ fr_pair_list_free(vp_p);
+ return -1;
}
- break;
+ fr_cursor_insert(&cursor, vp);
}
}
break;
/*
* Vendor is "MSFT 98"
*/
- vp = fr_pair_find_by_num(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
- if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
+ vp = fr_pair_find_by_num(head, 60, DHCP_MAGIC_VENDOR, TAG_ANY);
+ if (vp && (vp->vp_length >= 7) && (memcmp(vp->vp_octets, "MSFT 98", 7) == 0)) {
vp = fr_pair_find_by_num(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
/*
*/
server_ipaddr.af = AF_INET;
if (strcmp(argv[1], "-") != 0) {
- if (ip_hton(&server_ipaddr, AF_INET, argv[1], false) < 0) {
- fr_perror("dhcpclient");
- fr_exit_now(1);
+ if (fr_pton_port(&server_ipaddr, &server_port, argv[1], -1, AF_INET, true) < 0) {
+ fprintf(stderr, "dhcpclient: Failed parsing IP:port - %s", fr_strerror());
+ exit(1);
}
+
client_ipaddr.af = server_ipaddr.af;
}
process_post_auth(0, request);
DEBUG2("Done VMPS");
+ request->packet->code = 0; /* hack for VMPS */
request->reply->code = PW_CODE_ACCESS_ACCEPT;
return 0;
}
ptr = (uint8_t const *) packet;
- end = ptr + talloc_array_length(packet);
+ end = ptr + talloc_array_length((uint8_t const *) packet);
ptr++; /* skip the code at the start of the packet */
while (ptr < end) {
/* Add the channel binding attributes to the fake packet */
data_len = chbind_get_data(chbind->request, CHBIND_NSID_RADIUS, &attr_data);
if (data_len) {
- rad_assert(data_len <= talloc_array_length(chbind->request));
+ rad_assert(data_len <= talloc_array_length((uint8_t const *) chbind->request));
while (data_len > 0) {
int attr_len = rad_attr2vp(fake->packet, NULL, NULL, NULL, attr_data, data_len, &vp);
const char *hash_name, const char *list_name)
{
VALUE_PAIR *vp;
+ char *tbuff;
+ size_t tbufflen = 1024;
hv_undef(rad_hv);
vp_cursor_t cursor;
+ /*
+ * Find out how much room to allocate.
+ */
+ for (vp = fr_cursor_init(&cursor, vps);
+ vp;
+ vp = fr_cursor_next(&cursor)) {
+ if (((vp->length * 2) + 3) > tbufflen) {
+ tbufflen = (vp->vp_length * 2) + 3;
+ }
+ }
+ tbuff = talloc_array(request, char, tbufflen);
+
RINDENT();
fr_pair_list_sort(vps, fr_pair_cmp_by_da_tag);
for (vp = fr_cursor_init(&cursor, vps);
vp;
vp = fr_cursor_next(&cursor)) {
VALUE_PAIR *next;
-
char const *name;
- char namebuf[256];
- char buffer[1024];
-
size_t len;
+ char namebuf[256];
/*
* Tagged attributes are added to the hash with name
break;
default:
- len = vp_prints_value(buffer, sizeof(buffer), vp, 0);
+ len = vp_prints_value(tbuff, tbufflen, vp, 0);
RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hash_name, vp->da->name,
- list_name, vp->da->name, buffer);
+ list_name, vp->da->name, tbuff);
(void)hv_store(rad_hv, name, strlen(name),
- newSVpvn(buffer, truncate_len(len, sizeof(buffer))), 0);
+ newSVpvn(tbuff, truncate_len(len, tbufflen)), 0);
break;
}
}
REXDENT();
+
+ talloc_free(tbuff);
}
/*
/* FIXME: fr_pair_list_copy should be removed once VALUE_PAIRs are no longer in linked lists */
tmp = fr_pair_copy(request, check_item);
tmp->op = check_item->op;
- result = paircompare(req, request, check_item, NULL);
+ result = paircompare(req, request, tmp, NULL);
fr_pair_list_free(&tmp);
}
char const *name; //!< Name of the module instance
PyThreadState *sub_interpreter; //!< The main interpreter/thread used for this instance.
char const *python_path; //!< Path to search for python files in.
+
+#if PY_VERSION_HEX > 0x03050000
+ wchar_t *wide_name; //!< Special wide char encoding of radiusd name.
+ wchar_t *wide_path; //!< Special wide char encoding of radiusd path.
+#endif
PyObject *module; //!< Local, interpreter specific module, containing
//!< FreeRADIUS functions.
bool cext_compat; //!< Whether or not to create sub-interpreters per module
#if PY_VERSION_HEX > 0x03050000
{
- wchar_t *name;
-
- wide_name = Py_DecodeLocale(main_config.name, strlen(main_config.name));
+ inst->wide_name = Py_DecodeLocale(main_config.name, strlen(main_config.name));
Py_SetProgramName(name); /* The value of argv[0] as a wide char string */
- PyMem_RawFree(name);
}
#else
{
char *name;
- name = talloc_strdup(NULL, main_config.name);
+ memcpy(&name, &main_config.name, sizeof(name));
Py_SetProgramName(name); /* The value of argv[0] as a wide char string */
- talloc_free(name);
}
#endif
/*
* Set the python search path
+ *
+ * The path buffer does not appear to be dup'd
+ * so its lifetime should really be bound to
+ * the lifetime of the module.
*/
if (inst->python_path) {
#if PY_VERSION_HEX > 0x03050000
{
- wchar_t *name;
-
- path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path));
+ inst->wide_path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path));
PySys_SetPath(path);
- PyMem_RawFree(path);
}
#else
{
char *path;
- path = talloc_strdup(NULL, inst->python_path);
+ memcpy(&path, inst->python_path, sizeof(path));
PySys_SetPath(path);
- talloc_free(path);
}
#endif
}
PyThreadState_Swap(main_interpreter); /* Swap to the main thread */
Py_Finalize();
dlclose(python_dlhandle);
+
+#if PY_VERSION_HEX > 0x03050000
+ if (inst->wide_name) PyMem_RawFree(inst->wide_name);
+ if (inst->wide_path) PyMem_RawFree(inst->wide_path);
+#endif
}
+
return ret;
}
return 0;
}
+#ifdef WITH_DHCP
static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *request)
{
-#ifdef WITH_DHCP
int rcode;
VALUE_PAIR *vp;
rlm_soh_t *inst = instance;
}
return RLM_MODULE_OK;
}
-#endif
return RLM_MODULE_NOOP;
}
+#endif
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void * instance, REQUEST *request)
{
.bootstrap = mod_bootstrap,
.methods = {
[MOD_AUTHORIZE] = mod_authorize,
+#ifdef WITH_DHCP
[MOD_POST_AUTH] = mod_post_auth
+#endif
},
};
ssize_t len;
int statement_cnt = 0;
char *buffer;
- char *p, *q, *s;
+ char *p, *q;
int cl;
FILE *f;
struct stat finfo;
/*
* Statement delimiter is ;\n
*/
- s = p = buffer;
+ p = buffer;
while ((q = strchr(p, ';'))) {
- if (q[1] != '\n') {
+ if ((q[1] != '\n') && (q[1] != '\0')) {
p = q + 1;
statement_cnt++;
continue;
}
- *q = '\0';
-
#ifdef HAVE_SQLITE3_PREPARE_V2
- status = sqlite3_prepare_v2(db, s, len, &statement, &z_tail);
+ status = sqlite3_prepare_v2(db, p, q - p, &statement, &z_tail);
#else
- status = sqlite3_prepare(db, s, len, &statement, &z_tail);
+ status = sqlite3_prepare(db, p, q - p, &statement, &z_tail);
#endif
if (sql_check_error(db, status) != RLM_SQL_OK) {
}
statement_cnt++;
- p = s = q + 1;
+ p = q + 1;
}
talloc_free(buffer);
ATTRIBUTE Test-Name 1 string
ATTRIBUTE Test-Number 2 integer
ATTRIBUTE Test-Server-Port 3 integer
+ATTRIBUTE Test-Signed 4 signed
END-VENDOR TEST
-#!/bin/bash
+#!/bin/sh
: ${BIN_PATH=./}
: ${PORT=12340}
# again, but the second one attr is not an extended attr
decode f5 ff 1a 80 00 00 00 01 06 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa ab bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb 01 05 62 6f 62
-data Attr-245.26.1.6 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, User-Name = "bob"
+data Attr-245 = 0x1a800000000106aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, User-Name = "bob"
# No data means that the attribute is an "invalid attribute"
decode f5 04 01 00
attribute PMIP6-Home-IPv4-HoA = bob/8
data Failed to parse IPv4 address string "bob/8"
+#
+# A "concat" attribute, with no data
+#
+decode 89 02
+data PKM-SS-Cert = 0x
+
+#
+# Or with weirdly formatted data
+#
+decode 89 03 ff 89 02 89 03 fe
+data PKM-SS-Cert = 0xfffe
+
$INCLUDE tunnel.txt
$INCLUDE errors.txt
$INCLUDE extended.txt
decode -
data WiMAX-Release = "1.0"
+decode 1a 08 00 00 60 b5 01 02
+data Attr-26 = 0x000060b50102
+
+decode 1a 0a 00 00 60 b5 01 04 00 01
+data Attr-26.24757.1 = 0x01
+
encode WiMAX-Accounting-Capabilities = 1
data 1a 0c 00 00 60 b5 01 06 00 02 03 01
decode -
data WiMAX-Release = "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE", WiMAX-Idle-Mode-Notification-Cap = Supported
+
+#
+# Continuation is set, but there's no continued data.
+decode 1a 0b 00 00 60 b5 31 05 80 00 00
+data Attr-26 = 0x000060b53105800000
+
+encode WiMAX-GMT-Timezone-offset = -1
+data 1a 0d 00 00 60 b5 03 07 00 ff ff ff ff
+
+decode -
+data WiMAX-GMT-Timezone-offset = -1
+
Name: freeradius-server
-Version: 3.0.14
+Version: 3.0.15
Release: 0
License: GPLv2 ; LGPLv2.1
Group: Productivity/Networking/Radius/Servers