Merge tag 'release_3_0_15' into tr-integ moonshot_release_3.0.15 moonshot_release_3.0.15+moonshot1 moonshot_release_3.0.15+moonshot1-1 moonshot_release_3.0.15+moonshot2
authorDan Breslau <dbreslau@painless-security.com>
Mon, 17 Jul 2017 18:05:09 +0000 (14:05 -0400)
committerDan Breslau <dbreslau@painless-security.com>
Mon, 17 Jul 2017 18:05:09 +0000 (14:05 -0400)
39 files changed:
Make.inc.in
VERSION
configure
configure.ac
debian/changelog
doc/ChangeLog
raddb/certs/bootstrap
raddb/mods-available/eap
raddb/radiusd.conf.in
redhat/freeradius.spec-renamed
redhat/radiusd.service
scripts/jlibtool.c
share/dictionary.cisco.vpn3000
share/dictionary.ruckus
share/dictionary.starent
src/lib/net.c
src/lib/radius.c
src/lib/value.c
src/main/auth.c
src/main/conffile.c
src/main/process.c
src/main/realms.c
src/main/tls.c
src/modules/proto_dhcp/all.mk
src/modules/proto_dhcp/dhcp.c
src/modules/proto_dhcp/dhcpclient.c
src/modules/proto_vmps/vmps.c
src/modules/rlm_eap/libeap/eap_chbind.c
src/modules/rlm_perl/rlm_perl.c
src/modules/rlm_preprocess/rlm_preprocess.c
src/modules/rlm_python/rlm_python.c
src/modules/rlm_soh/rlm_soh.c
src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c
src/tests/dictionary.test
src/tests/runtests.sh
src/tests/unit/extended.txt
src/tests/unit/rfc.txt
src/tests/unit/wimax.txt
suse/freeradius.spec-renamed

index 7a77625..a69292e 100644 (file)
@@ -108,6 +108,8 @@ bm_static_libs  = @USE_STATIC_LIBS@
 STATIC_MODULES = @STATIC_MODULES@
 LIBREADLINE    = @LIBREADLINE@
 
+WITH_DHCP      = @WITH_DHCP@
+
 #
 #  Version to use for packaging and other Make related things
 #
diff --git a/VERSION b/VERSION
index 9bbe651..e265a8c 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.14
+3.0.15
index 05860f8..4fa37f7 100755 (executable)
--- a/configure
+++ b/configure
@@ -654,6 +654,7 @@ SNMPWALK
 SNMPGET
 PERL
 openssl_version_check_config
+WITH_DHCP
 modconfdir
 dictdir
 raddbdir
@@ -5304,6 +5305,7 @@ $as_echo "#define WITH_DHCP 1" >>confdefs.h
 
 fi
 
+
 STATIC_MODULES=
 
 # Check whether --with-static_modules was given.
index 9ead51d..72f0425 100644 (file)
@@ -430,6 +430,7 @@ AC_ARG_WITH(dhcp,
 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
index cf9c86d..02d02d7 100644 (file)
@@ -1,3 +1,15 @@
+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
index a26a7d1..c42aace 100644 (file)
@@ -1,4 +1,56 @@
-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.
index c9d939b..0f719aa 100755 (executable)
@@ -32,7 +32,7 @@ fi
 #  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
index 04698ce..2621e18 100644 (file)
@@ -421,6 +421,11 @@ eap {
                        #  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:
index c62f4ff..a83c1f6 100644 (file)
@@ -285,44 +285,6 @@ log {
        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
index eb32165..8ed9652 100644 (file)
 
 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
@@ -50,7 +55,7 @@ BuildRequires: autoconf
 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
@@ -382,14 +387,14 @@ touch $RPM_BUILD_ROOT/var/log/radius/{radutmp,radius.log}
 
 # 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
@@ -473,11 +478,13 @@ fi
 
 %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 || :
index 5639757..1631bec 100644 (file)
@@ -7,7 +7,19 @@ Documentation=man:radiusd(8) man:radiusd.conf(5) http://wiki.freeradius.org/ htt
 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
index c04390d..e4f908c 100644 (file)
@@ -79,7 +79,7 @@
 #  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"
index 1d9dfbf..e2dae38 100644 (file)
@@ -103,7 +103,7 @@ 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-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
index 82d63c3..8da9927 100644 (file)
@@ -63,6 +63,12 @@ ATTRIBUTE       Ruckus-Eth-Profile-Id              133    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
 #
index 12f6405..9898cc0 100644 (file)
@@ -288,6 +288,15 @@ ATTRIBUTE  SN-WiMAX-Auth-Only                      306     integer
 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
@@ -1351,4 +1360,23 @@ VALUE    SN-Visiting-Sub-Use-GGSN        Accept                  1
 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
index 2981bc1..e84072b 100644 (file)
@@ -36,7 +36,9 @@ bool fr_link_layer_supported(int link_layer)
        case DLT_RAW:
        case DLT_NULL:
        case DLT_LOOP:
+#ifdef DLT_LINUX_SLL
        case DLT_LINUX_SLL:
+#endif
        case DLT_PFLOG:
                return true;
 
@@ -119,12 +121,14 @@ ssize_t fr_link_layer_offset(uint8_t const *data, size_t len, int link_layer)
                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;
index 245b86c..2ecaabf 100644 (file)
@@ -542,17 +542,17 @@ static ssize_t rad_recvfrom(int sockfd, RADIUS_PACKET *packet, int flags,
  * 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];
        }
 }
@@ -1010,8 +1010,8 @@ static ssize_t vp2data_any(RADIUS_PACKET const *packet,
                 *      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;
 
@@ -2952,16 +2952,23 @@ static ssize_t data2vp_concat(TALLOC_CTX *ctx,
         *      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;
 
@@ -2974,7 +2981,7 @@ static ssize_t data2vp_concat(TALLOC_CTX *ctx,
 
        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;
@@ -2982,6 +2989,7 @@ static ssize_t data2vp_concat(TALLOC_CTX *ctx,
        }
 
        *pvp = vp;
+
        return ptr - start;
 }
 
@@ -3153,75 +3161,148 @@ static ssize_t data2vp_extended(TALLOC_CTX *ctx, RADIUS_PACKET *packet,
                                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
  */
@@ -3233,25 +3314,54 @@ static ssize_t data2vp_wimax(TALLOC_CTX *ctx,
                             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;
        }
 
        /*
@@ -3260,61 +3370,115 @@ static ssize_t data2vp_wimax(TALLOC_CTX *ctx,
         *      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;
 }
@@ -3605,9 +3769,14 @@ ssize_t data2vp(TALLOC_CTX *ctx,
                                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';
@@ -3736,19 +3905,6 @@ ssize_t data2vp(TALLOC_CTX *ctx,
                }
 
                /*
-                *      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,
@@ -3930,7 +4086,7 @@ ssize_t data2vp(TALLOC_CTX *ctx,
                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;
 
index 888ca8a..ca18327 100644 (file)
@@ -1738,34 +1738,67 @@ print_int:
        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);
index 79e639e..4776b3a 100644 (file)
@@ -376,6 +376,18 @@ int rad_postauth(REQUEST *request)
                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.
         */
@@ -586,16 +598,6 @@ authenticate:
                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? */
index 5f4c722..fb2c48b 100644 (file)
@@ -1199,7 +1199,7 @@ static char const *cf_expand_variables(char const *cf, int *lineno,
                                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;
@@ -1928,6 +1928,8 @@ int cf_section_parse(CONF_SECTION *cs, void *base, CONF_PARSER const *variables)
                            (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;
                }
index e3e32f4..016f8ba 100644 (file)
@@ -5321,7 +5321,9 @@ static void check_proxy(rad_listen_t *head)
        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
index d1fafcf..4f3c6b8 100644 (file)
@@ -433,9 +433,9 @@ void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs)
        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);
@@ -767,7 +767,9 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
 
                switch (proto) {
                case IPPROTO_UDP:
+#ifdef WITH_TCP
                        home_servers_udp = true;
+#endif
                        break;
 
                case IPPROTO_TCP:
index 753bf2d..5ac8fc1 100644 (file)
@@ -1453,7 +1453,7 @@ static int ocsp_asn1time_to_epoch(time_t *out, char const *asn1)
 
        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);
@@ -1471,7 +1471,7 @@ static int ocsp_asn1time_to_epoch(time_t *out, char const *asn1)
                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;
@@ -1481,14 +1481,21 @@ static int ocsp_asn1time_to_epoch(time_t *out, char const *asn1)
        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;
 }
@@ -1604,6 +1611,7 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l
                        /* 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;
                }
 
@@ -1615,14 +1623,16 @@ static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int l
                        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;
                        }
 
@@ -2030,7 +2040,7 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx)
        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;
@@ -2211,7 +2221,7 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx)
                        }
                }
                if (names != NULL)
-                       sk_GENERAL_NAME_free(names);
+                       GENERAL_NAMES_free(names);
        }
 
        /*
@@ -3037,6 +3047,7 @@ post_ca:
                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))) {
@@ -3044,6 +3055,7 @@ post_ca:
                        return NULL;
                }
        }
+#endif
 
        /*
         * Set the cipher list if we were told to
@@ -3165,6 +3177,7 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs)
         *      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");
@@ -3174,7 +3187,9 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs)
                        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;
index d098a8a..12242b6 100644 (file)
@@ -1 +1,3 @@
+ifneq "$(WITH_DHCP)" "no"
 SUBMAKEFILES := libfreeradius-dhcp.mk proto_dhcp.mk rlm_dhcp.mk dhcpclient.mk
+endif
index 98d8750..5fd922d 100644 (file)
@@ -629,6 +629,24 @@ static int fr_dhcp_decode_suboption(TALLOC_CTX *ctx, VALUE_PAIR **tlv, uint8_t c
                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
                 *
@@ -774,25 +792,23 @@ static int fr_dhcp_attr2vp(TALLOC_CTX *ctx, VALUE_PAIR **vp_p, uint8_t const *da
                 *      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;
@@ -1097,8 +1113,8 @@ int fr_dhcp_decode(RADIUS_PACKET *packet)
                        /*
                         *      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);
 
                                /*
index 5c923f1..adbcb8c 100644 (file)
@@ -413,10 +413,11 @@ int main(int argc, char **argv)
         */
        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;
        }
 
index f1df128..1fc0a19 100644 (file)
@@ -37,6 +37,7 @@ static int vmps_process(REQUEST *request)
        process_post_auth(0, request);
        DEBUG2("Done VMPS");
 
+       request->packet->code = 0; /* hack for VMPS */
        request->reply->code = PW_CODE_ACCESS_ACCEPT;
 
        return 0;
index a8ecb51..e4d7ed8 100644 (file)
@@ -119,7 +119,7 @@ static size_t chbind_get_data(chbind_packet_t const *packet,
        }
 
        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) {
@@ -182,7 +182,7 @@ PW_CODE chbind_process(REQUEST *request, CHBIND_REQ *chbind)
        /* 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);
index b1191ab..80db218 100644 (file)
@@ -654,23 +654,34 @@ static void perl_store_vps(UNUSED TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR
                           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
@@ -715,15 +726,17 @@ static void perl_store_vps(UNUSED TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR
                        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);
 }
 
 /*
index ce75ac8..b6d3a5d 100644 (file)
@@ -357,7 +357,7 @@ static int hunt_paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check)
                /* 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);
        }
 
index c52cec5..8261cfd 100644 (file)
@@ -67,6 +67,11 @@ typedef struct rlm_python_t {
        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
@@ -855,19 +860,15 @@ static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf)
 
 #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
 
@@ -903,23 +904,23 @@ static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf)
 
                /*
                 *      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
                }
@@ -1087,8 +1088,14 @@ static int mod_detach(void *instance)
                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;
 }
 
index b0e0dfb..11ab67b 100644 (file)
@@ -120,9 +120,9 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance)
        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;
@@ -183,9 +183,9 @@ static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *reque
                }
                return RLM_MODULE_OK;
        }
-#endif
        return RLM_MODULE_NOOP;
 }
+#endif
 
 static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void * instance, REQUEST *request)
 {
@@ -219,6 +219,8 @@ module_t rlm_soh = {
        .bootstrap      = mod_bootstrap,
        .methods = {
                [MOD_AUTHORIZE]         = mod_authorize,
+#ifdef WITH_DHCP
                [MOD_POST_AUTH]         = mod_post_auth
+#endif
        },
 };
index c94831d..9cf1aff 100644 (file)
@@ -233,7 +233,7 @@ static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db, char const *filename)
        ssize_t         len;
        int             statement_cnt = 0;
        char            *buffer;
-       char            *p, *q, *s;
+       char            *p, *q;
        int             cl;
        FILE            *f;
        struct stat     finfo;
@@ -321,20 +321,18 @@ static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db, char const *filename)
        /*
         *      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) {
@@ -359,7 +357,7 @@ static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db, char const *filename)
                }
 
                statement_cnt++;
-               p = s = q + 1;
+               p = q + 1;
        }
 
        talloc_free(buffer);
index af84f2c..1b3130f 100644 (file)
@@ -7,4 +7,5 @@ BEGIN-VENDOR TEST
 ATTRIBUTE      Test-Name               1 string
 ATTRIBUTE      Test-Number             2 integer
 ATTRIBUTE      Test-Server-Port        3 integer
+ATTRIBUTE      Test-Signed             4 signed
 END-VENDOR TEST
index d9276b9..cc403c6 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 : ${BIN_PATH=./}
 : ${PORT=12340}
index 8b0e3a2..9810b19 100644 (file)
@@ -80,7 +80,7 @@ data Attr-245.26.1.6 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 
 # 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
index 0024794..d870975 100644 (file)
@@ -178,6 +178,18 @@ data Failed to parse IPv4 address string "256/8"
 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
index 191b37e..f9d416a 100644 (file)
@@ -7,6 +7,12 @@ data 1a 0e 00 00 60 b5 01 08 00 01 05 31 2e 30
 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
 
@@ -143,3 +149,15 @@ data 1a ff 00 00 60 b5 01 f9 80 01 ff 45 45 45 45 45 45 45 45 45 45 45 45 45 45
 
 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
+
index 1fb3c14..21c2142 100644 (file)
@@ -1,5 +1,5 @@
 Name:         freeradius-server
-Version: 3.0.14
+Version: 3.0.15
 Release:      0
 License:      GPLv2 ; LGPLv2.1
 Group:        Productivity/Networking/Radius/Servers