Updated version 3.0.15+dfsg from 'upstream/3.0.15+dfsg'
with Debian dir 1f7396038d12480deebf223400dd8d248cfa0916
Michael Stapelberg
6 years ago
107 | 107 | STATIC_MODULES = @STATIC_MODULES@ |
108 | 108 | LIBREADLINE = @LIBREADLINE@ |
109 | 109 | |
110 | WITH_DHCP = @WITH_DHCP@ | |
111 | ||
110 | 112 | # |
111 | 113 | # Version to use for packaging and other Make related things |
112 | 114 | # |
653 | 653 | SNMPGET |
654 | 654 | PERL |
655 | 655 | openssl_version_check_config |
656 | WITH_DHCP | |
656 | 657 | modconfdir |
657 | 658 | dictdir |
658 | 659 | raddbdir |
5303 | 5304 | |
5304 | 5305 | fi |
5305 | 5306 | |
5307 | ||
5306 | 5308 | STATIC_MODULES= |
5307 | 5309 | |
5308 | 5310 | # Check whether --with-static_modules was given. |
429 | 429 | if test "x$WITH_DHCP" = "xyes"; then |
430 | 430 | AC_DEFINE(WITH_DHCP, [1], [define if you want DHCP support]) |
431 | 431 | fi |
432 | AC_SUBST(WITH_DHCP) | |
432 | 433 | |
433 | 434 | dnl # |
434 | 435 | dnl # Allow the user to specify a list of modules to be linked |
0 | FreeRADIUS 3.0.14 Mon 06 Mar 2017 13:00:00 EDT urgency=medium | |
0 | FreeRADIUS 3.0.15 Mon 17 Jul 2017 09:00:00 EDT urgency=high | |
1 | Feature improvements | |
2 | * Provide HOSTNAME in default systemd files. | |
3 | * Incorporate RedHat specific files | |
4 | * Update dictionary.starent, dictionary.ruckus | |
5 | * Allow builds without TCP or DHCP | |
6 | ||
7 | Bug fixes | |
8 | * Fix multiple issues. See this web page for details: | |
9 | http://freeradius.org/security/fuzzer-2017.html | |
10 | * Pass correct statement length into sqlite3_prepare[_v2] | |
11 | * Bind the lifetime of program name and python path to the module | |
12 | * Check input / output length in make_secret(). | |
13 | FR-GV-201 | |
14 | * Fix read overflow when decoding DHCP option 63 | |
15 | FR-GV-206 | |
16 | * Fix write overflow in data2vp_wimax() | |
17 | FR-GV-301 | |
18 | * Fix infinite loop and memory exhaustion with 'concat' attributes | |
19 | FR-GV-302 | |
20 | * Fix infinite read in dhcp_attr2vp() | |
21 | FR-GV-303 | |
22 | * Fix buffer over-read in fr_dhcp_decode_suboptions() | |
23 | FR-GV-304 | |
24 | * Decode 'signed' attributes correctly. | |
25 | FR-GV-305 | |
26 | * use strncmp() instead of memcmp() for bounded data | |
27 | FR-AD-001 | |
28 | * print messages when we see deprecated configuration | |
29 | items | |
30 | * show reasons why we couldn't parse a certificate | |
31 | expiry time | |
32 | * be more accepting about truncated ASN1 times. | |
33 | * Fix OpenSSL API issue which could leak small amounts | |
34 | of memory. Issue reported by Guido Vranken. | |
35 | * For Access-Reject, call rad_authlog() after running | |
36 | the post-auth section, just like for Access-Accept. | |
37 | * don't crash when reading corrupted data from session | |
38 | resumption cache. Fixes #1999. | |
39 | * Parse port in dhcpclient. Fixes #2000. | |
40 | * Don't leak memory for OpenSSL. | |
41 | Patch from Guido Vranken. | |
42 | * Portability fixes taken from OpenBSD port collection. | |
43 | * run rad_authlog after post-auth for Access-Reject. | |
44 | * Don't process VMPS packets twice. | |
45 | * Fix attribute truncation in rlm_perl | |
46 | * Fix bug when processing huntgroups. | |
47 | ||
48 | FreeRADIUS 3.0.14 Fri 26 May 2017 13:00:00 EDT urgency=medium | |
1 | 49 | Feature improvements |
2 | 50 | * Enforce TLS client certificate expiration on |
3 | 51 | session resumption, and Session-Timeout. |
31 | 31 | # re-generate these commands. |
32 | 32 | # |
33 | 33 | if [ ! -f dh ]; then |
34 | openssl dhparam -out dh 1024 || exit 1 | |
34 | openssl dhparam -out dh 2048 || exit 1 | |
35 | 35 | if [ -e /dev/urandom ] ; then |
36 | 36 | ln -sf /dev/urandom random |
37 | 37 | else |
420 | 420 | # state and the cached VPs. This will persist session |
421 | 421 | # across server restarts. |
422 | 422 | # |
423 | # The default directory is ${logdir}, for historical | |
424 | # reasons. You should ${db_dir} instead. And check | |
425 | # the value of db_dir in the main radiusd.conf file. | |
426 | # It should not point to ${raddb} | |
427 | # | |
423 | 428 | # The server will need write perms, and the directory |
424 | 429 | # should be secured from anyone else. You might want |
425 | 430 | # a script to remove old files from here periodically: |
284 | 284 | file = ${logdir}/radius.log |
285 | 285 | |
286 | 286 | # |
287 | # If this configuration parameter is set, then log messages for | |
288 | # a *request* go to this file, rather than to radius.log. | |
289 | # | |
290 | # i.e. This is a log file per request, once the server has accepted | |
291 | # the request as being from a valid client. Messages that are | |
292 | # not associated with a request still go to radius.log. | |
293 | # | |
294 | # Not all log messages in the server core have been updated to use | |
295 | # this new internal API. As a result, some messages will still | |
296 | # go to radius.log. Please submit patches to fix this behavior. | |
297 | # | |
298 | # The file name is expanded dynamically. You should ONLY user | |
299 | # server-side attributes for the filename (e.g. things you control). | |
300 | # Using this feature MAY also slow down the server substantially, | |
301 | # especially if you do thinks like SQL calls as part of the | |
302 | # expansion of the filename. | |
303 | # | |
304 | # The name of the log file should use attributes that don't change | |
305 | # over the lifetime of a request, such as User-Name, | |
306 | # Virtual-Server or Packet-Src-IP-Address. Otherwise, the log | |
307 | # messages will be distributed over multiple files. | |
308 | # | |
309 | # Logging can be enabled for an individual request by a special | |
310 | # dynamic expansion macro: %{debug: 1}, where the debug level | |
311 | # for this request is set to '1' (or 2, 3, etc.). e.g. | |
312 | # | |
313 | # ... | |
314 | # update control { | |
315 | # Tmp-String-0 = "%{debug:1}" | |
316 | # } | |
317 | # ... | |
318 | # | |
319 | # The attribute that the value is assigned to is unimportant, | |
320 | # and should be a "throw-away" attribute with no side effects. | |
321 | # | |
322 | #requests = ${logdir}/radiusd-%{%{Virtual-Server}:-DEFAULT}-%Y%m%d.log | |
323 | ||
324 | # | |
325 | 287 | # Which syslog facility to use, if ${destination} == "syslog" |
326 | 288 | # |
327 | 289 | # The exact values permitted here are OS-dependent. You probably |
25 | 25 | |
26 | 26 | Summary: High-performance and highly configurable free RADIUS server |
27 | 27 | Name: freeradius |
28 | Version: 3.0.14 | |
28 | Version: 3.0.15 | |
29 | 29 | Release: 2%{?dist} |
30 | 30 | License: GPLv2+ and LGPLv2+ |
31 | 31 | Group: System Environment/Daemons |
32 | 32 | URL: http://www.freeradius.org/ |
33 | 33 | |
34 | 34 | Source0: ftp://ftp.freeradius.org/pub/radius/freeradius-server-%{version}.tar.bz2 |
35 | %if %{?_unitdir:1}%{!?_unitdir:0} | |
36 | Source100: radiusd.service | |
37 | %else | |
35 | 38 | Source100: freeradius-radiusd-init |
39 | %define initddir %{?_initddir:%{_initddir}}%{!?_initddir:%{_initrddir}} | |
40 | %endif | |
41 | ||
36 | 42 | Source102: freeradius-logrotate |
37 | 43 | Source103: freeradius-pam-conf |
38 | Source104: radiusd.service | |
39 | 44 | |
40 | 45 | Obsoletes: freeradius-devel |
41 | 46 | Obsoletes: freeradius-libs |
49 | 54 | BuildRequires: gdbm-devel |
50 | 55 | BuildRequires: libtool |
51 | 56 | BuildRequires: libtool-ltdl-devel |
52 | BuildRequires: openssl-devel | |
57 | BuildRequires: openssl, openssl-devel | |
53 | 58 | BuildRequires: pam-devel |
54 | 59 | BuildRequires: zlib-devel |
55 | 60 | BuildRequires: net-snmp-devel |
381 | 386 | |
382 | 387 | # For systemd based systems, that define _unitdir, install the radiusd unit |
383 | 388 | %if %{?_unitdir:1}%{!?_unitdir:0} |
384 | install -D -m 755 %{SOURCE104} $RPM_BUILD_ROOT/%{_unitdir}/radiusd.service | |
389 | install -D -m 755 redhat/radiusd.service $RPM_BUILD_ROOT/%{_unitdir}/radiusd.service | |
385 | 390 | # For SystemV install the init script |
386 | 391 | %else |
387 | install -D -m 755 %{SOURCE100} $RPM_BUILD_ROOT/%{initddir}/radiusd | |
388 | %endif | |
389 | ||
390 | install -D -m 644 %{SOURCE102} $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/radiusd | |
391 | install -D -m 644 %{SOURCE103} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/radiusd | |
392 | install -D -m 755 redhat/freeradius-radiusd-init $RPM_BUILD_ROOT/%{initddir}/radiusd | |
393 | %endif | |
394 | ||
395 | install -D -m 644 redhat/freeradius-logrotate $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/radiusd | |
396 | install -D -m 644 redhat/freeradius-pam-conf $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/radiusd | |
392 | 397 | |
393 | 398 | # remove unneeded stuff |
394 | 399 | rm -rf doc/00-OLD |
472 | 477 | |
473 | 478 | %preun |
474 | 479 | if [ $1 = 0 ]; then |
475 | /sbin/service radiusd stop > /dev/null 2>&1 | |
480 | %if %{?_unitdir:1}%{!?_unitdir:0} | |
481 | /bin/systemctl disable radiusd | |
482 | %else | |
476 | 483 | /sbin/chkconfig --del radiusd |
484 | %endif | |
477 | 485 | fi |
478 | ||
479 | 486 | |
480 | 487 | %postun |
481 | 488 | if [ $1 -ge 1 ]; then |
6 | 6 | Type=forking |
7 | 7 | PIDFile=/var/run/radiusd/radiusd.pid |
8 | 8 | EnvironmentFile=-/etc/sysconfig/radiusd |
9 | ||
10 | # FreeRADIUS can do static evaluation of policy language rules based | |
11 | # on environmental variables which is very useful for doing per-host | |
12 | # customization. | |
13 | # Unfortunately systemd does not allow variable substitutions such | |
14 | # as %H or $(hostname) in the EnvironmentFile. | |
15 | # We provide HOSTNAME here for convenience. | |
16 | Environment=HOSTNAME=%H | |
17 | ||
18 | RuntimeDirectory=/var/run/radiusd | |
19 | RuntimeDirectoryMode=0775 | |
9 | 20 | ExecStartPre=/usr/sbin/radiusd $FREERADIUS_OPTIONS -Cxm -lstdout |
21 | ExecStartPre=/usr/bin/chown radiusd:radiusd /var/run/radiusd | |
10 | 22 | ExecStart=/usr/sbin/radiusd $FREERADIUS_OPTIONS -m |
11 | 23 | Restart=on-failure |
12 | 24 | RestartSec=5 |
78 | 78 | # define LD_LIBRARY_PATH_LOCAL "DYLD_FALLBACK_LIBRARY_PATH" |
79 | 79 | #endif |
80 | 80 | |
81 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || (defined(__sun) && defined(__GNUC__)) | |
81 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || (defined(__sun) && defined(__GNUC__)) | |
82 | 82 | # define SHELL_CMD "/bin/sh" |
83 | 83 | # define DYNAMIC_LIB_EXT "so" |
84 | 84 | # define MODULE_LIB_EXT "so" |
102 | 102 | ATTRIBUTE Cisco-VPN3000-WebVPN-File-Server-Browsing-Enable 96 integer |
103 | 103 | ATTRIBUTE Cisco-VPN3000-WebVPN-Port-Forwarding-Enable 97 integer |
104 | 104 | ATTRIBUTE Cisco-VPN3000-WebVPN-Outlook-Exchange-Proxy-Enable 98 integer |
105 | ATTRIBUTE Cisco-VPN3000-WebVPN-Outlook-Exchange-Proxy-Enable 99 integer | |
105 | ATTRIBUTE Cisco-VPN3000-WebVPN-HTTP-Proxy-Enable 99 integer | |
106 | 106 | ATTRIBUTE Cisco-VPN3000-WebVPN-Auto-Applet-Download-Enable 100 integer |
107 | 107 | ATTRIBUTE Cisco-VPN3000-WebVPN-Citrix-MetaFrame-Enable 101 integer |
108 | 108 | ATTRIBUTE Cisco-VPN3000-WebVPN-Apply-ACL 102 integer |
62 | 62 | ATTRIBUTE Ruckus-Zone-Name 134 string |
63 | 63 | ATTRIBUTE Ruckus-Wlan-Name 135 string |
64 | 64 | |
65 | ATTRIBUTE Ruckus-Read-Preference 137 octets | |
66 | ATTRIBUTE Ruckus-Client-Host-Name 138 string | |
67 | ATTRIBUTE Ruckus-Client-Os-Type 139 string | |
68 | ATTRIBUTE Ruckus-Client-Os-Class 140 string | |
69 | ATTRIBUTE Ruckus-Vlan-Pool 141 string | |
70 | ||
65 | 71 | # |
66 | 72 | # Integer Translations |
67 | 73 | # |
287 | 287 | ATTRIBUTE SN-TrafficSelector-Class 307 integer |
288 | 288 | ATTRIBUTE SN-DHCP-Options 309 octets |
289 | 289 | ATTRIBUTE SN-Handoff-Indicator 310 integer |
290 | ATTRIBUTE SN-User-Privilege 313 integer | |
291 | ATTRIBUTE SN-IPv6-Alloc-Method 314 integer | |
292 | ATTRIBUTE SN-Congestion-Mgmt-Policy 315 string | |
293 | ATTRIBUTE SN-WSG-MIP-Required 316 integer | |
294 | ATTRIBUTE SN-WSG-MIP-Release-TIA 317 integer | |
295 | ATTRIBUTE SN-WSG-MIP-Simple-IP-Fallback 318 integer | |
296 | ATTRIBUTE SN-WLAN-AP-Identifier 319 octets | |
297 | ATTRIBUTE SN-WLAN-UE-Identifier 320 octets | |
298 | ||
290 | 299 | |
291 | 300 | ATTRIBUTE SNA-PPP-Ctrl-Input-Octets 1001 integer |
292 | 301 | ATTRIBUTE SNA-PPP-Ctrl-Output-Octets 1002 integer |
1350 | 1359 | VALUE SN-WiMAX-Auth-Only Disabled 0 |
1351 | 1360 | VALUE SN-WiMAX-Auth-Only Enabled 1 |
1352 | 1361 | |
1362 | VALUE SN-User-Privilege Administrative 6 | |
1363 | VALUE SN-User-Privilege NAS_Prompt 7 | |
1364 | VALUE SN-User-Privilege Inspector 19650516 | |
1365 | VALUE SN-User-Privilege Security_Admin 19660618 | |
1366 | ||
1367 | VALUE SN-IPv6-Alloc-Method Alloc_Local_Pool 0 | |
1368 | VALUE SN-IPv6-Alloc-Method Alloc_Dhcp_Client 1 | |
1369 | VALUE SN-IPv6-Alloc-Method Alloc_No_Alloc 2 | |
1370 | VALUE SN-IPv6-Alloc-Method Alloc_Static_Alloc 3 | |
1371 | ||
1372 | VALUE SN-WSG-MIP-Required No 0 | |
1373 | VALUE SN-WSG-MIP-Required Yes 1 | |
1374 | ||
1375 | VALUE SN-WSG-MIP-Release-TIA No 0 | |
1376 | VALUE SN-WSG-MIP-Release-TIA Yes 1 | |
1377 | ||
1378 | VALUE SN-WSG-MIP-Simple-IP-Fallback No 0 | |
1379 | VALUE SN-WSG-MIP-Simple-IP-Fallback Yes 1 | |
1380 | ||
1353 | 1381 | END-VENDOR Starent |
35 | 35 | case DLT_RAW: |
36 | 36 | case DLT_NULL: |
37 | 37 | case DLT_LOOP: |
38 | #ifdef DLT_LINUX_SLL | |
38 | 39 | case DLT_LINUX_SLL: |
40 | #endif | |
39 | 41 | case DLT_PFLOG: |
40 | 42 | return true; |
41 | 43 | |
118 | 120 | return -1; |
119 | 121 | } |
120 | 122 | |
123 | #ifdef DLT_LINUX_SLL | |
121 | 124 | case DLT_LINUX_SLL: |
122 | 125 | p += 16; |
123 | 126 | if (((size_t)(p - data)) > len) { |
124 | 127 | goto ood; |
125 | 128 | } |
126 | 129 | break; |
130 | #endif | |
127 | 131 | |
128 | 132 | case DLT_PFLOG: |
129 | 133 | p += 28; |
541 | 541 | * encrypting passwords to RADIUS. |
542 | 542 | */ |
543 | 543 | static void make_secret(uint8_t *digest, uint8_t const *vector, |
544 | char const *secret, uint8_t const *value) | |
544 | char const *secret, uint8_t const *value, size_t length) | |
545 | 545 | { |
546 | 546 | FR_MD5_CTX context; |
547 | int i; | |
547 | size_t i; | |
548 | 548 | |
549 | 549 | fr_md5_init(&context); |
550 | 550 | fr_md5_update(&context, vector, AUTH_VECTOR_LEN); |
551 | 551 | fr_md5_update(&context, (uint8_t const *) secret, strlen(secret)); |
552 | 552 | fr_md5_final(digest, &context); |
553 | 553 | |
554 | for ( i = 0; i < AUTH_VECTOR_LEN; i++ ) { | |
554 | for ( i = 0; i < length; i++ ) { | |
555 | 555 | digest[i] ^= value[i]; |
556 | 556 | } |
557 | 557 | } |
1009 | 1009 | * always fits. |
1010 | 1010 | */ |
1011 | 1011 | case FLAG_ENCRYPT_ASCEND_SECRET: |
1012 | if (len != 16) return 0; | |
1013 | make_secret(ptr, packet->vector, secret, data); | |
1012 | if (len > AUTH_VECTOR_LEN) len = AUTH_VECTOR_LEN; | |
1013 | make_secret(ptr, packet->vector, secret, data, len); | |
1014 | 1014 | len = AUTH_VECTOR_LEN; |
1015 | 1015 | break; |
1016 | 1016 | |
2951 | 2951 | * don't care about walking off of the end of it. |
2952 | 2952 | */ |
2953 | 2953 | while (ptr < end) { |
2954 | if (ptr[1] < 2) return -1; | |
2955 | if ((ptr + ptr[1]) > end) return -1; | |
2956 | ||
2954 | 2957 | total += ptr[1] - 2; |
2955 | 2958 | |
2956 | 2959 | ptr += ptr[1]; |
2957 | 2960 | |
2961 | if (ptr == end) break; | |
2962 | ||
2958 | 2963 | /* |
2959 | 2964 | * Attributes MUST be consecutive. |
2960 | 2965 | */ |
2961 | 2966 | if (ptr[0] != attr) break; |
2962 | 2967 | } |
2968 | ||
2969 | end = ptr; | |
2963 | 2970 | |
2964 | 2971 | vp = fr_pair_afrom_da(ctx, da); |
2965 | 2972 | if (!vp) return -1; |
2973 | 2980 | |
2974 | 2981 | total = 0; |
2975 | 2982 | ptr = start; |
2976 | while (total < vp->vp_length) { | |
2983 | while (ptr < end) { | |
2977 | 2984 | memcpy(p, ptr + 2, ptr[1] - 2); |
2978 | 2985 | p += ptr[1] - 2; |
2979 | 2986 | total += ptr[1] - 2; |
2981 | 2988 | } |
2982 | 2989 | |
2983 | 2990 | *pvp = vp; |
2991 | ||
2984 | 2992 | return ptr - start; |
2985 | 2993 | } |
2986 | 2994 | |
3152 | 3160 | VALUE_PAIR **pvp) |
3153 | 3161 | { |
3154 | 3162 | ssize_t rcode; |
3155 | size_t fraglen; | |
3163 | size_t ext_len; | |
3164 | bool more; | |
3156 | 3165 | uint8_t *head, *tail; |
3157 | uint8_t const *frag, *end; | |
3158 | uint8_t const *attr; | |
3159 | int fragments; | |
3160 | bool last_frag; | |
3161 | ||
3162 | if (attrlen < 3) return -1; | |
3166 | uint8_t const *attr, *end; | |
3167 | DICT_ATTR const *child; | |
3168 | ||
3169 | /* | |
3170 | * data = Ext-Attr Flag ... | |
3171 | */ | |
3172 | ||
3173 | /* | |
3174 | * Not enough room for Ext-Attr + Flag + data, it's a bad | |
3175 | * attribute. | |
3176 | */ | |
3177 | if (attrlen < 3) { | |
3178 | raw: | |
3179 | /* | |
3180 | * It's not an Extended attribute, it's unknown... | |
3181 | */ | |
3182 | child = dict_unknown_afrom_fields(ctx, (da->vendor/ FR_MAX_VENDOR) & 0xff, 0); | |
3183 | if (!child) { | |
3184 | fr_strerror_printf("Internal sanity check %d", __LINE__); | |
3185 | return -1; | |
3186 | } | |
3187 | ||
3188 | rcode = data2vp(ctx, packet, original, secret, child, | |
3189 | data, attrlen, attrlen, pvp); | |
3190 | if (rcode < 0) return rcode; | |
3191 | return attrlen; | |
3192 | } | |
3193 | ||
3194 | /* | |
3195 | * No continued data, just decode the attribute in place. | |
3196 | */ | |
3197 | if ((data[1] & 0x80) == 0) { | |
3198 | rcode = data2vp(ctx, packet, original, secret, da, | |
3199 | data + 2, attrlen - 2, attrlen - 2, | |
3200 | pvp); | |
3201 | ||
3202 | if ((rcode < 0) || (((size_t) rcode + 2) != attrlen)) goto raw; /* didn't decode all of the data */ | |
3203 | return attrlen; | |
3204 | } | |
3205 | ||
3206 | /* | |
3207 | * It's continued, but there are no subsequent fragments, | |
3208 | * it's bad. | |
3209 | */ | |
3210 | if (attrlen >= packetlen) goto raw; | |
3163 | 3211 | |
3164 | 3212 | /* |
3165 | 3213 | * Calculate the length of all of the fragments. For |
3166 | 3214 | * now, they MUST be contiguous in the packet, and they |
3167 | * MUST be all of the same TYPE and EXTENDED-TYPE | |
3168 | */ | |
3169 | attr = data - 2; | |
3170 | fraglen = attrlen - 2; | |
3171 | frag = data + attrlen; | |
3215 | * MUST be all of the same Type and Ext-Type | |
3216 | * | |
3217 | * We skip the first fragment, which doesn't have a | |
3218 | * RADIUS attribute header. | |
3219 | */ | |
3220 | ext_len = attrlen - 2; | |
3221 | attr = data + attrlen; | |
3172 | 3222 | end = data + packetlen; |
3173 | fragments = 1; | |
3174 | last_frag = false; | |
3175 | ||
3176 | while (frag < end) { | |
3177 | if (last_frag || | |
3178 | (frag[0] != attr[0]) || | |
3179 | (frag[1] < 4) || /* too short for long-extended */ | |
3180 | (frag[2] != attr[2]) || | |
3181 | ((frag + frag[1]) > end)) { /* overflow */ | |
3182 | end = frag; | |
3183 | break; | |
3184 | } | |
3185 | ||
3186 | last_frag = ((frag[3] & 0x80) == 0); | |
3187 | ||
3188 | fraglen += frag[1] - 4; | |
3189 | frag += frag[1]; | |
3190 | fragments++; | |
3191 | } | |
3192 | ||
3193 | head = tail = malloc(fraglen); | |
3194 | if (!head) return -1; | |
3195 | ||
3196 | VP_TRACE("Fragments %d, total length %d\n", fragments, (int) fraglen); | |
3197 | ||
3198 | /* | |
3199 | * And again, but faster and looser. | |
3200 | * | |
3201 | * We copy the first fragment, followed by the rest of | |
3202 | * the fragments. | |
3203 | */ | |
3204 | frag = attr; | |
3205 | ||
3206 | while (fragments > 0) { | |
3207 | memcpy(tail, frag + 4, frag[1] - 4); | |
3208 | tail += frag[1] - 4; | |
3209 | frag += frag[1]; | |
3210 | fragments--; | |
3211 | } | |
3212 | ||
3213 | VP_HEXDUMP("long-extended fragments", head, fraglen); | |
3223 | ||
3224 | while (attr < end) { | |
3225 | /* | |
3226 | * Not enough room for Attr + length + Ext-Attr | |
3227 | * continuation, it's bad. | |
3228 | */ | |
3229 | if ((end - attr) < 4) goto raw; | |
3230 | ||
3231 | if (attr[1] < 4) goto raw; | |
3232 | ||
3233 | /* | |
3234 | * If the attribute overflows the packet, it's | |
3235 | * bad. | |
3236 | */ | |
3237 | if ((attr + attr[1]) > end) goto raw; | |
3238 | ||
3239 | if (attr[0] != ((da->vendor / FR_MAX_VENDOR) & 0xff)) goto raw; /* not the same Extended-Attribute-X */ | |
3240 | ||
3241 | if (attr[2] != data[0]) goto raw; /* Not the same Ext-Attr */ | |
3242 | ||
3243 | /* | |
3244 | * Check the continuation flag. | |
3245 | */ | |
3246 | more = ((attr[2] & 0x80) != 0); | |
3247 | ||
3248 | /* | |
3249 | * Or, there's no more data, in which case we | |
3250 | * shorten "end" to finish at this attribute. | |
3251 | */ | |
3252 | if (!more) end = attr + attr[1]; | |
3253 | ||
3254 | /* | |
3255 | * There's more data, but we're at the end of the | |
3256 | * packet. The attribute is malformed! | |
3257 | */ | |
3258 | if (more && ((attr + attr[1]) == end)) goto raw; | |
3259 | ||
3260 | /* | |
3261 | * Add in the length of the data we need to | |
3262 | * concatenate together. | |
3263 | */ | |
3264 | ext_len += attr[1] - 4; | |
3265 | ||
3266 | /* | |
3267 | * Go to the next attribute, and stop if there's | |
3268 | * no more. | |
3269 | */ | |
3270 | attr += attr[1]; | |
3271 | if (!more) break; | |
3272 | } | |
3273 | ||
3274 | if (!ext_len) goto raw; | |
3275 | ||
3276 | head = tail = malloc(ext_len); | |
3277 | if (!head) goto raw; | |
3278 | ||
3279 | /* | |
3280 | * Copy the data over, this time trusting the attribute | |
3281 | * contents. | |
3282 | */ | |
3283 | attr = data; | |
3284 | memcpy(tail, attr + 2, attrlen - 2); | |
3285 | tail += attrlen - 2; | |
3286 | attr += attrlen; | |
3287 | ||
3288 | while (attr < end) { | |
3289 | memcpy(tail, attr + 4, attr[1] - 4); | |
3290 | tail += attr[1] - 4; | |
3291 | attr += attr[1]; /* skip VID+WiMax header */ | |
3292 | } | |
3293 | ||
3294 | VP_HEXDUMP("long-extended fragments", head, ext_len); | |
3214 | 3295 | |
3215 | 3296 | rcode = data2vp(ctx, packet, original, secret, da, |
3216 | head, fraglen, fraglen, pvp); | |
3297 | head, ext_len, ext_len, pvp); | |
3217 | 3298 | free(head); |
3218 | if (rcode < 0) return rcode; | |
3299 | if (rcode < 0) goto raw; | |
3219 | 3300 | |
3220 | 3301 | return end - data; |
3221 | 3302 | } |
3222 | 3303 | |
3223 | /** Convert a Vendor-Specific WIMAX to vps | |
3304 | /** Convert a Vendor-Specific WIMAX to VPs | |
3224 | 3305 | * |
3225 | 3306 | * @note Called ONLY for Vendor-Specific |
3226 | 3307 | */ |
3232 | 3313 | VALUE_PAIR **pvp) |
3233 | 3314 | { |
3234 | 3315 | ssize_t rcode; |
3235 | size_t fraglen; | |
3236 | bool last_frag; | |
3316 | size_t wimax_len; | |
3317 | bool more; | |
3237 | 3318 | uint8_t *head, *tail; |
3238 | uint8_t const *frag, *end; | |
3319 | uint8_t const *attr, *end; | |
3239 | 3320 | DICT_ATTR const *child; |
3240 | 3321 | |
3241 | if (attrlen < 8) return -1; | |
3242 | ||
3243 | if (((size_t) (data[5] + 4)) != attrlen) return -1; | |
3322 | /* | |
3323 | * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ... | |
3324 | */ | |
3325 | ||
3326 | /* | |
3327 | * Not enough room for WiMAX Vendor + Wimax attr + length | |
3328 | * + continuation, it's a bad attribute. | |
3329 | */ | |
3330 | if (attrlen < 8) { | |
3331 | raw: | |
3332 | /* | |
3333 | * It's not a Vendor-Specific, it's unknown... | |
3334 | */ | |
3335 | child = dict_unknown_afrom_fields(ctx, PW_VENDOR_SPECIFIC, 0); | |
3336 | if (!child) { | |
3337 | fr_strerror_printf("Internal sanity check %d", __LINE__); | |
3338 | return -1; | |
3339 | } | |
3340 | ||
3341 | rcode = data2vp(ctx, packet, original, secret, child, | |
3342 | data, attrlen, attrlen, pvp); | |
3343 | if (rcode < 0) return rcode; | |
3344 | return attrlen; | |
3345 | } | |
3346 | ||
3347 | if (data[5] < 3) goto raw; /* WiMAX-Length is too small */ | |
3244 | 3348 | |
3245 | 3349 | child = dict_attrbyvalue(data[4], vendor); |
3246 | if (!child) return -1; | |
3247 | ||
3350 | if (!child) goto raw; | |
3351 | ||
3352 | /* | |
3353 | * No continued data, just decode the attribute in place. | |
3354 | */ | |
3248 | 3355 | if ((data[6] & 0x80) == 0) { |
3356 | if ((data[5] + 4) != attrlen) goto raw; /* WiMAX attribute doesn't fill Vendor-Specific */ | |
3357 | ||
3249 | 3358 | rcode = data2vp(ctx, packet, original, secret, child, |
3250 | 3359 | data + 7, data[5] - 3, data[5] - 3, |
3251 | 3360 | pvp); |
3252 | if (rcode < 0) return -1; | |
3253 | return 7 + rcode; | |
3361 | ||
3362 | if ((rcode < 0) || (((size_t) rcode + 7) != attrlen)) goto raw; /* didn't decode all of the data */ | |
3363 | return attrlen; | |
3254 | 3364 | } |
3255 | 3365 | |
3256 | 3366 | /* |
3259 | 3369 | * MUST be all of the same VSA, WiMAX, and WiMAX-attr. |
3260 | 3370 | * |
3261 | 3371 | * The first fragment doesn't have a RADIUS attribute |
3262 | * header, so it needs to be treated a little special. | |
3263 | */ | |
3264 | fraglen = data[5] - 3; | |
3265 | frag = data + attrlen; | |
3372 | * header. | |
3373 | */ | |
3374 | wimax_len = 0; | |
3375 | attr = data + 4; | |
3266 | 3376 | end = data + packetlen; |
3267 | last_frag = false; | |
3268 | ||
3269 | while (frag < end) { | |
3270 | if (last_frag || | |
3271 | (frag[0] != PW_VENDOR_SPECIFIC) || | |
3272 | (frag[1] < 9) || /* too short for wimax */ | |
3273 | ((frag + frag[1]) > end) || /* overflow */ | |
3274 | (memcmp(frag + 2, data, 4) != 0) || /* not wimax */ | |
3275 | (frag[6] != data[4]) || /* not the same wimax attr */ | |
3276 | ((frag[7] + 6) != frag[1])) { /* doesn't fill the attr */ | |
3277 | end = frag; | |
3278 | break; | |
3279 | } | |
3280 | ||
3281 | last_frag = ((frag[8] & 0x80) == 0); | |
3282 | ||
3283 | fraglen += frag[7] - 3; | |
3284 | frag += frag[1]; | |
3285 | } | |
3286 | ||
3287 | head = tail = malloc(fraglen); | |
3377 | ||
3378 | while (attr < end) { | |
3379 | /* | |
3380 | * Not enough room for Attribute + length + | |
3381 | * continuation, it's bad. | |
3382 | */ | |
3383 | if ((end - attr) < 3) goto raw; | |
3384 | ||
3385 | /* | |
3386 | * Must have non-zero data in the attribute. | |
3387 | */ | |
3388 | if (attr[1] <= 3) goto raw; | |
3389 | ||
3390 | /* | |
3391 | * If the WiMAX attribute overflows the packet, | |
3392 | * it's bad. | |
3393 | */ | |
3394 | if ((attr + attr[1]) > end) goto raw; | |
3395 | ||
3396 | /* | |
3397 | * Check the continuation flag. | |
3398 | */ | |
3399 | more = ((attr[2] & 0x80) != 0); | |
3400 | ||
3401 | /* | |
3402 | * Or, there's no more data, in which case we | |
3403 | * shorten "end" to finish at this attribute. | |
3404 | */ | |
3405 | if (!more) end = attr + attr[1]; | |
3406 | ||
3407 | /* | |
3408 | * There's more data, but we're at the end of the | |
3409 | * packet. The attribute is malformed! | |
3410 | */ | |
3411 | if (more && ((attr + attr[1]) == end)) goto raw; | |
3412 | ||
3413 | /* | |
3414 | * Add in the length of the data we need to | |
3415 | * concatenate together. | |
3416 | */ | |
3417 | wimax_len += attr[1] - 3; | |
3418 | ||
3419 | /* | |
3420 | * Go to the next attribute, and stop if there's | |
3421 | * no more. | |
3422 | */ | |
3423 | attr += attr[1]; | |
3424 | if (!more) break; | |
3425 | ||
3426 | /* | |
3427 | * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ... | |
3428 | * | |
3429 | * attr = Vendor-Specific VSA-Length VID VID VID VID WiMAX-Attr WimAX-Len Continuation ... | |
3430 | * | |
3431 | */ | |
3432 | ||
3433 | /* | |
3434 | * No room for Vendor-Specific + length + | |
3435 | * Vendor(4) + attr + length + continuation + data | |
3436 | */ | |
3437 | if ((end - attr) < 9) goto raw; | |
3438 | ||
3439 | if (attr[0] != PW_VENDOR_SPECIFIC) goto raw; | |
3440 | if (attr[1] < 9) goto raw; | |
3441 | if ((attr + attr[1]) > end) goto raw; | |
3442 | if (memcmp(data, attr + 2, 4) != 0) goto raw; /* not WiMAX Vendor ID */ | |
3443 | ||
3444 | if (attr[1] != (attr[7] + 6)) goto raw; /* WiMAX attr doesn't exactly fill the VSA */ | |
3445 | ||
3446 | if (data[4] != attr[6]) goto raw; /* different WiMAX attribute */ | |
3447 | ||
3448 | /* | |
3449 | * Skip over the Vendor-Specific header, and | |
3450 | * continue with the WiMAX attributes. | |
3451 | */ | |
3452 | attr += 6; | |
3453 | } | |
3454 | ||
3455 | /* | |
3456 | * No data in the WiMAX attribute, make a "raw" one. | |
3457 | */ | |
3458 | if (!wimax_len) goto raw; | |
3459 | ||
3460 | head = tail = malloc(wimax_len); | |
3288 | 3461 | if (!head) return -1; |
3289 | 3462 | |
3290 | 3463 | /* |
3291 | * And again, but faster and looser. | |
3292 | * | |
3293 | * We copy the first fragment, followed by the rest of | |
3294 | * the fragments. | |
3295 | */ | |
3296 | frag = data; | |
3297 | ||
3298 | memcpy(tail, frag + 4 + 3, frag[4 + 1] - 3); | |
3299 | tail += frag[4 + 1] - 3; | |
3300 | frag += attrlen; /* should be frag[1] - 7 */ | |
3301 | ||
3302 | /* | |
3303 | * frag now points to RADIUS attributes | |
3304 | */ | |
3305 | do { | |
3306 | memcpy(tail, frag + 2 + 4 + 3, frag[2 + 4 + 1] - 3); | |
3307 | tail += frag[2 + 4 + 1] - 3; | |
3308 | frag += frag[1]; | |
3309 | } while (frag < end); | |
3310 | ||
3311 | VP_HEXDUMP("wimax fragments", head, fraglen); | |
3464 | * Copy the data over, this time trusting the attribute | |
3465 | * contents. | |
3466 | */ | |
3467 | attr = data; | |
3468 | while (attr < end) { | |
3469 | memcpy(tail, attr + 4 + 3, attr[4 + 1] - 3); | |
3470 | tail += attr[4 + 1] - 3; | |
3471 | attr += 4 + attr[4 + 1]; /* skip VID+WiMax header */ | |
3472 | attr += 2; /* skip Vendor-Specific header */ | |
3473 | } | |
3474 | ||
3475 | VP_HEXDUMP("wimax fragments", head, wimax_len); | |
3312 | 3476 | |
3313 | 3477 | rcode = data2vp(ctx, packet, original, secret, child, |
3314 | head, fraglen, fraglen, pvp); | |
3478 | head, wimax_len, wimax_len, pvp); | |
3315 | 3479 | free(head); |
3316 | if (rcode < 0) return rcode; | |
3480 | if (rcode < 0) goto raw; | |
3317 | 3481 | |
3318 | 3482 | return end - data; |
3319 | 3483 | } |
3604 | 3768 | goto raw; |
3605 | 3769 | } else { |
3606 | 3770 | uint8_t my_digest[AUTH_VECTOR_LEN]; |
3771 | size_t secret_len; | |
3772 | ||
3773 | secret_len = datalen; | |
3774 | if (secret_len > AUTH_VECTOR_LEN) secret_len = AUTH_VECTOR_LEN; | |
3775 | ||
3607 | 3776 | make_secret(my_digest, |
3608 | 3777 | original->vector, |
3609 | secret, data); | |
3778 | secret, data, secret_len); | |
3610 | 3779 | memcpy(buffer, my_digest, |
3611 | 3780 | AUTH_VECTOR_LEN ); |
3612 | 3781 | buffer[AUTH_VECTOR_LEN] = '\0'; |
3735 | 3904 | } |
3736 | 3905 | |
3737 | 3906 | /* |
3738 | * If there no more fragments, then the contents | |
3739 | * have to be a well-known data type. | |
3740 | * | |
3741 | */ | |
3742 | if ((data[1] & 0x80) == 0) { | |
3743 | rcode = data2vp(ctx, packet, original, secret, child, | |
3744 | data + 2, attrlen - 2, attrlen - 2, | |
3745 | pvp); | |
3746 | if (rcode < 0) goto raw; | |
3747 | return 2 + rcode; | |
3748 | } | |
3749 | ||
3750 | /* | |
3751 | 3907 | * This requires a whole lot more work. |
3752 | 3908 | */ |
3753 | 3909 | return data2vp_extended(ctx, packet, original, secret, child, |
3929 | 4085 | break; |
3930 | 4086 | |
3931 | 4087 | case PW_TYPE_SIGNED: /* overloaded with vp_integer */ |
3932 | memcpy(&vp->vp_integer, buffer, 4); | |
4088 | memcpy(&vp->vp_integer, data, 4); | |
3933 | 4089 | vp->vp_integer = ntohl(vp->vp_integer); |
3934 | 4090 | break; |
3935 | 4091 |
1737 | 1737 | case PW_TYPE_OCTETS: |
1738 | 1738 | case PW_TYPE_TLV: |
1739 | 1739 | { |
1740 | size_t max; | |
1741 | ||
1742 | /* Return the number of bytes we would have written */ | |
1743 | len = (inlen * 2) + 2; | |
1744 | if (freespace <= 1) { | |
1745 | return len; | |
1746 | } | |
1747 | ||
1748 | *out++ = '0'; | |
1749 | freespace--; | |
1750 | ||
1751 | if (freespace <= 1) { | |
1752 | *out = '\0'; | |
1753 | return len; | |
1754 | } | |
1755 | *out++ = 'x'; | |
1756 | freespace--; | |
1757 | ||
1758 | if (freespace <= 2) { | |
1759 | *out = '\0'; | |
1760 | return len; | |
1761 | } | |
1762 | ||
1763 | /* Get maximum number of bytes we can encode given freespace */ | |
1764 | max = ((freespace % 2) ? freespace - 1 : freespace - 2) / 2; | |
1765 | fr_bin2hex(out, data->octets, ((size_t)inlen > max) ? max : (size_t)inlen); | |
1766 | } | |
1767 | return len; | |
1740 | size_t binlen; | |
1741 | size_t hexlen; | |
1742 | ||
1743 | binlen = inlen; | |
1744 | hexlen = (binlen * 2) + 2; /* NOT accounting for trailing NUL */ | |
1745 | ||
1746 | /* | |
1747 | * If the buffer is too small, put something into | |
1748 | * it, and return how much we should have written | |
1749 | * | |
1750 | * 0 + x + H + H + NUL = 5 | |
1751 | */ | |
1752 | if (freespace < 5) { | |
1753 | switch (freespace) { | |
1754 | case '4': | |
1755 | case '3': | |
1756 | out[0] = '0'; | |
1757 | out[1] = 'x'; | |
1758 | out[2] = '\0'; | |
1759 | return hexlen; | |
1760 | ||
1761 | case 2: | |
1762 | *out = '0'; | |
1763 | out++; | |
1764 | /* FALL-THROUGH */ | |
1765 | ||
1766 | case 1: | |
1767 | *out = '\0'; | |
1768 | break; | |
1769 | ||
1770 | case 0: | |
1771 | break; | |
1772 | } | |
1773 | ||
1774 | return hexlen; | |
1775 | } | |
1776 | ||
1777 | /* | |
1778 | * The output buffer is at least 5 bytes, we haev | |
1779 | * room for '0xHH' plus a trailing NUL byte. | |
1780 | */ | |
1781 | out[0] = '0'; | |
1782 | out[1] = 'x'; | |
1783 | ||
1784 | /* | |
1785 | * Get maximum number of bytes we can encode | |
1786 | * given freespace, ensuring we account for '0', | |
1787 | * 'x', and the trailing NUL in the buffer. | |
1788 | * | |
1789 | * Note that we can't have "freespace = 0" after | |
1790 | * this, as 'freespace' has to be at least 5. | |
1791 | */ | |
1792 | freespace -= 3; | |
1793 | freespace /= 2; | |
1794 | if (binlen > freespace) { | |
1795 | binlen = freespace; | |
1796 | } | |
1797 | ||
1798 | fr_bin2hex(out + 2, data->octets, binlen); | |
1799 | return hexlen; | |
1800 | } | |
1768 | 1801 | |
1769 | 1802 | case PW_TYPE_IFID: |
1770 | 1803 | a = ifid_ntoa(buf, sizeof(buf), data->ifid); |
375 | 375 | request->reply->code = PW_CODE_ACCESS_REJECT; |
376 | 376 | } |
377 | 377 | |
378 | if (request->reply->code == PW_CODE_ACCESS_REJECT) { | |
379 | if ((vp = fr_pair_find_by_num(request->packet->vps, PW_MODULE_FAILURE_MESSAGE, 0, TAG_ANY)) != NULL) { | |
380 | char msg[MAX_STRING_LEN+19]; | |
381 | ||
382 | snprintf(msg, sizeof(msg), "Login incorrect (%s)", | |
383 | vp->vp_strvalue); | |
384 | rad_authlog(msg, request, 0); | |
385 | } else { | |
386 | rad_authlog("Login incorrect", request, 0); | |
387 | } | |
388 | } | |
389 | ||
378 | 390 | /* |
379 | 391 | * If we're still accepting the user, say so. |
380 | 392 | */ |
585 | 597 | RDEBUG2("Failed to authenticate the user"); |
586 | 598 | request->reply->code = PW_CODE_ACCESS_REJECT; |
587 | 599 | |
588 | if ((module_msg = fr_pair_find_by_num(request->packet->vps, PW_MODULE_FAILURE_MESSAGE, 0, TAG_ANY)) != NULL){ | |
589 | char msg[MAX_STRING_LEN+19]; | |
590 | ||
591 | snprintf(msg, sizeof(msg), "Login incorrect (%s)", | |
592 | module_msg->vp_strvalue); | |
593 | rad_authlog(msg, request, 0); | |
594 | } else { | |
595 | rad_authlog("Login incorrect", request, 0); | |
596 | } | |
597 | ||
598 | 600 | if (request->password) { |
599 | 601 | VERIFY_VP(request->password); |
600 | 602 | /* double check: maybe the secret is wrong? */ |
1198 | 1198 | ERROR("%s[%d]: Reference \"%s\" type is invalid", cf, *lineno, input); |
1199 | 1199 | return NULL; |
1200 | 1200 | } |
1201 | } else if (memcmp(ptr, "$ENV{", 5) == 0) { | |
1201 | } else if (strncmp(ptr, "$ENV{", 5) == 0) { | |
1202 | 1202 | char *env; |
1203 | 1203 | |
1204 | 1204 | ptr += 5; |
1927 | 1927 | (variables[i + 1].data == variables[i].data)) { |
1928 | 1928 | cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", variables[i].name, |
1929 | 1929 | variables[i + 1].name); |
1930 | } else { | |
1931 | cf_log_err(&(cs->item), "Cannot use deprecated configuration item \"%s\"", variables[i].name); | |
1930 | 1932 | } |
1931 | 1933 | goto finish; |
1932 | 1934 | } |
5320 | 5320 | if (check_config) return; |
5321 | 5321 | if (!main_config.proxy_requests) return; |
5322 | 5322 | if (!head) return; |
5323 | #ifdef WITH_TCP | |
5323 | 5324 | if (!home_servers_udp) return; |
5325 | #endif | |
5324 | 5326 | |
5325 | 5327 | /* |
5326 | 5328 | * We passed "-i" on the command line. Use that address |
432 | 432 | FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, <=, 120); |
433 | 433 | |
434 | 434 | FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, >=, 0, 1000); |
435 | FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0); | |
436 | 435 | FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, |
437 | 436 | main_config.max_request_time, 0); |
437 | FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0); | |
438 | 438 | |
439 | 439 | FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, >=, 1); |
440 | 440 | FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, <=, 1000); |
766 | 766 | |
767 | 767 | switch (proto) { |
768 | 768 | case IPPROTO_UDP: |
769 | #ifdef WITH_TCP | |
769 | 770 | home_servers_udp = true; |
771 | #endif | |
770 | 772 | break; |
771 | 773 | |
772 | 774 | case IPPROTO_TCP: |
1453 | 1453 | |
1454 | 1454 | memset(&t, 0, sizeof(t)); |
1455 | 1455 | |
1456 | if ((end - p) <= 12) { | |
1456 | if ((end - p) <= 13) { | |
1457 | 1457 | if ((end - p) < 2) { |
1458 | 1458 | fr_strerror_printf("ASN1 date string too short, expected 2 additional bytes, got %zu bytes", |
1459 | 1459 | end - p); |
1471 | 1471 | t.tm_year -= 1900; |
1472 | 1472 | } |
1473 | 1473 | |
1474 | if ((end - p) < 10) { | |
1474 | if ((end - p) < 4) { | |
1475 | 1475 | fr_strerror_printf("ASN1 string too short, expected 10 additional bytes, got %zu bytes", |
1476 | 1476 | end - p); |
1477 | 1477 | return -1; |
1481 | 1481 | t.tm_mon += (*(p++) - '0') - 1; // -1 since January is 0 not 1. |
1482 | 1482 | t.tm_mday = (*(p++) - '0') * 10; |
1483 | 1483 | t.tm_mday += (*(p++) - '0'); |
1484 | ||
1485 | if ((end - p) < 2) goto done; | |
1484 | 1486 | t.tm_hour = (*(p++) - '0') * 10; |
1485 | 1487 | t.tm_hour += (*(p++) - '0'); |
1488 | ||
1489 | if ((end - p) < 2) goto done; | |
1486 | 1490 | t.tm_min = (*(p++) - '0') * 10; |
1487 | 1491 | t.tm_min += (*(p++) - '0'); |
1492 | ||
1493 | if ((end - p) < 2) goto done; | |
1488 | 1494 | t.tm_sec = (*(p++) - '0') * 10; |
1489 | 1495 | t.tm_sec += (*(p++) - '0'); |
1490 | 1496 | |
1491 | 1497 | /* Apparently OpenSSL converts all timestamps to UTC? Maybe? */ |
1498 | done: | |
1492 | 1499 | *out = timegm(&t); |
1493 | 1500 | return 0; |
1494 | 1501 | } |
1604 | 1611 | /* not safe to un-persist a session w/o VPs */ |
1605 | 1612 | RWDEBUG("Failed loading persisted VPs for session %s", buffer); |
1606 | 1613 | SSL_SESSION_free(sess); |
1614 | sess = NULL; | |
1607 | 1615 | goto error; |
1608 | 1616 | } |
1609 | 1617 | |
1615 | 1623 | time_t expires; |
1616 | 1624 | |
1617 | 1625 | if (ocsp_asn1time_to_epoch(&expires, vp->vp_strvalue) < 0) { |
1618 | RDEBUG2("Failed getting certificate expiration, removing cache entry for session %s", buffer); | |
1626 | RDEBUG2("Failed getting certificate expiration, removing cache entry for session %s - %s", buffer, fr_strerror()); | |
1619 | 1627 | SSL_SESSION_free(sess); |
1628 | sess = NULL; | |
1620 | 1629 | goto error; |
1621 | 1630 | } |
1622 | 1631 | |
1623 | 1632 | if (expires <= request->timestamp) { |
1624 | 1633 | RDEBUG2("Certificate has expired, removing cache entry for session %s", buffer); |
1625 | 1634 | SSL_SESSION_free(sess); |
1635 | sess = NULL; | |
1626 | 1636 | goto error; |
1627 | 1637 | } |
1628 | 1638 | |
2030 | 2040 | char cn_str[1024]; |
2031 | 2041 | char buf[64]; |
2032 | 2042 | X509 *client_cert; |
2033 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
2043 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) | |
2034 | 2044 | const STACK_OF(X509_EXTENSION) *ext_list; |
2035 | 2045 | #else |
2036 | 2046 | STACK_OF(X509_EXTENSION) *ext_list; |
2211 | 2221 | } |
2212 | 2222 | } |
2213 | 2223 | if (names != NULL) |
2214 | sk_GENERAL_NAME_free(names); | |
2224 | GENERAL_NAMES_free(names); | |
2215 | 2225 | } |
2216 | 2226 | |
2217 | 2227 | /* |
3037 | 3047 | SSL_CTX_set_verify_depth(ctx, conf->verify_depth); |
3038 | 3048 | } |
3039 | 3049 | |
3050 | #ifndef LIBRESSL_VERSION_NUMBER | |
3040 | 3051 | /* Load randomness */ |
3041 | 3052 | if (conf->random_file) { |
3042 | 3053 | if (!(RAND_load_file(conf->random_file, 1024*10))) { |
3044 | 3055 | return NULL; |
3045 | 3056 | } |
3046 | 3057 | } |
3058 | #endif | |
3047 | 3059 | |
3048 | 3060 | /* |
3049 | 3061 | * Set the cipher list if we were told to |
3165 | 3177 | * Only check for certificate things if we don't have a |
3166 | 3178 | * PSK query. |
3167 | 3179 | */ |
3180 | #ifdef PSK_MAX_IDENTITY_LEN | |
3168 | 3181 | if (conf->psk_identity) { |
3169 | 3182 | if (conf->private_key_file) { |
3170 | 3183 | WARN(LOG_PREFIX ": Ignoring private key file due to psk_identity being used"); |
3174 | 3187 | WARN(LOG_PREFIX ": Ignoring certificate file due to psk_identity being used"); |
3175 | 3188 | } |
3176 | 3189 | |
3177 | } else { | |
3190 | } else | |
3191 | #endif | |
3192 | { | |
3178 | 3193 | if (!conf->private_key_file) { |
3179 | 3194 | ERROR(LOG_PREFIX ": TLS Server requires a private key file"); |
3180 | 3195 | goto error; |
0 | ifneq "$(WITH_DHCP)" "no" | |
0 | 1 | SUBMAKEFILES := libfreeradius-dhcp.mk proto_dhcp.mk rlm_dhcp.mk dhcpclient.mk |
2 | endif |
628 | 628 | uint32_t attr; |
629 | 629 | |
630 | 630 | /* |
631 | * Not enough room for the option header, it's a | |
632 | * bad packet. | |
633 | */ | |
634 | if ((p + 2) > (data + len)) { | |
635 | fr_pair_list_free(&head); | |
636 | return -1; | |
637 | } | |
638 | ||
639 | /* | |
640 | * Not enough room for the option header + data, | |
641 | * it's a bad packet. | |
642 | */ | |
643 | if ((p + 2 + p[1]) > (data + len)) { | |
644 | fr_pair_list_free(&head); | |
645 | return -1; | |
646 | } | |
647 | ||
648 | /* | |
631 | 649 | * The initial OID string looks like: |
632 | 650 | * <iana>.0 |
633 | 651 | * |
773 | 791 | * multiple additional VPs |
774 | 792 | */ |
775 | 793 | fr_cursor_init(&cursor, vp_p); |
776 | for (;;) { | |
777 | q = memchr(p, '\0', q - p); | |
794 | while (p < end) { | |
795 | q = memchr(p, '\0', end - p); | |
778 | 796 | /* Malformed but recoverable */ |
779 | 797 | if (!q) q = end; |
780 | 798 | |
781 | 799 | fr_pair_value_bstrncpy(vp, (char const *)p, q - p); |
782 | 800 | p = q + 1; |
783 | 801 | |
802 | if (p >= end) break; | |
803 | ||
784 | 804 | /* Need another VP for the next round */ |
785 | if (p < end) { | |
786 | vp = fr_pair_afrom_da(ctx, vp->da); | |
787 | if (!vp) { | |
788 | fr_pair_list_free(vp_p); | |
789 | return -1; | |
790 | } | |
791 | fr_cursor_insert(&cursor, vp); | |
792 | continue; | |
805 | vp = fr_pair_afrom_da(ctx, vp->da); | |
806 | if (!vp) { | |
807 | fr_pair_list_free(vp_p); | |
808 | return -1; | |
793 | 809 | } |
794 | break; | |
810 | fr_cursor_insert(&cursor, vp); | |
795 | 811 | } |
796 | 812 | } |
797 | 813 | break; |
1096 | 1112 | /* |
1097 | 1113 | * Vendor is "MSFT 98" |
1098 | 1114 | */ |
1099 | vp = fr_pair_find_by_num(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY); | |
1100 | if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) { | |
1115 | vp = fr_pair_find_by_num(head, 60, DHCP_MAGIC_VENDOR, TAG_ANY); | |
1116 | if (vp && (vp->vp_length >= 7) && (memcmp(vp->vp_octets, "MSFT 98", 7) == 0)) { | |
1101 | 1117 | vp = fr_pair_find_by_num(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY); |
1102 | 1118 | |
1103 | 1119 | /* |
412 | 412 | */ |
413 | 413 | server_ipaddr.af = AF_INET; |
414 | 414 | if (strcmp(argv[1], "-") != 0) { |
415 | if (ip_hton(&server_ipaddr, AF_INET, argv[1], false) < 0) { | |
416 | fr_perror("dhcpclient"); | |
417 | fr_exit_now(1); | |
418 | } | |
415 | if (fr_pton_port(&server_ipaddr, &server_port, argv[1], -1, AF_INET, true) < 0) { | |
416 | fprintf(stderr, "dhcpclient: Failed parsing IP:port - %s", fr_strerror()); | |
417 | exit(1); | |
418 | } | |
419 | ||
419 | 420 | client_ipaddr.af = server_ipaddr.af; |
420 | 421 | } |
421 | 422 |
36 | 36 | process_post_auth(0, request); |
37 | 37 | DEBUG2("Done VMPS"); |
38 | 38 | |
39 | request->packet->code = 0; /* hack for VMPS */ | |
39 | 40 | request->reply->code = PW_CODE_ACCESS_ACCEPT; |
40 | 41 | |
41 | 42 | return 0; |
118 | 118 | } |
119 | 119 | |
120 | 120 | ptr = (uint8_t const *) packet; |
121 | end = ptr + talloc_array_length(packet); | |
121 | end = ptr + talloc_array_length((uint8_t const *) packet); | |
122 | 122 | |
123 | 123 | ptr++; /* skip the code at the start of the packet */ |
124 | 124 | while (ptr < end) { |
181 | 181 | /* Add the channel binding attributes to the fake packet */ |
182 | 182 | data_len = chbind_get_data(chbind->request, CHBIND_NSID_RADIUS, &attr_data); |
183 | 183 | if (data_len) { |
184 | rad_assert(data_len <= talloc_array_length(chbind->request)); | |
184 | rad_assert(data_len <= talloc_array_length((uint8_t const *) chbind->request)); | |
185 | 185 | |
186 | 186 | while (data_len > 0) { |
187 | 187 | int attr_len = rad_attr2vp(fake->packet, NULL, NULL, NULL, attr_data, data_len, &vp); |
653 | 653 | const char *hash_name, const char *list_name) |
654 | 654 | { |
655 | 655 | VALUE_PAIR *vp; |
656 | char *tbuff; | |
657 | size_t tbufflen = 1024; | |
656 | 658 | |
657 | 659 | hv_undef(rad_hv); |
658 | 660 | |
659 | 661 | vp_cursor_t cursor; |
662 | ||
663 | /* | |
664 | * Find out how much room to allocate. | |
665 | */ | |
666 | for (vp = fr_cursor_init(&cursor, vps); | |
667 | vp; | |
668 | vp = fr_cursor_next(&cursor)) { | |
669 | if (((vp->length * 2) + 3) > tbufflen) { | |
670 | tbufflen = (vp->vp_length * 2) + 3; | |
671 | } | |
672 | } | |
673 | tbuff = talloc_array(request, char, tbufflen); | |
660 | 674 | |
661 | 675 | RINDENT(); |
662 | 676 | fr_pair_list_sort(vps, fr_pair_cmp_by_da_tag); |
664 | 678 | vp; |
665 | 679 | vp = fr_cursor_next(&cursor)) { |
666 | 680 | VALUE_PAIR *next; |
667 | ||
668 | 681 | char const *name; |
682 | size_t len; | |
669 | 683 | char namebuf[256]; |
670 | char buffer[1024]; | |
671 | ||
672 | size_t len; | |
673 | 684 | |
674 | 685 | /* |
675 | 686 | * Tagged attributes are added to the hash with name |
714 | 725 | break; |
715 | 726 | |
716 | 727 | default: |
717 | len = vp_prints_value(buffer, sizeof(buffer), vp, 0); | |
728 | len = vp_prints_value(tbuff, tbufflen, vp, 0); | |
718 | 729 | RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hash_name, vp->da->name, |
719 | list_name, vp->da->name, buffer); | |
730 | list_name, vp->da->name, tbuff); | |
720 | 731 | (void)hv_store(rad_hv, name, strlen(name), |
721 | newSVpvn(buffer, truncate_len(len, sizeof(buffer))), 0); | |
732 | newSVpvn(tbuff, truncate_len(len, tbufflen)), 0); | |
722 | 733 | break; |
723 | 734 | } |
724 | 735 | } |
725 | 736 | REXDENT(); |
737 | ||
738 | talloc_free(tbuff); | |
726 | 739 | } |
727 | 740 | |
728 | 741 | /* |
356 | 356 | /* FIXME: fr_pair_list_copy should be removed once VALUE_PAIRs are no longer in linked lists */ |
357 | 357 | tmp = fr_pair_copy(request, check_item); |
358 | 358 | tmp->op = check_item->op; |
359 | result = paircompare(req, request, check_item, NULL); | |
359 | result = paircompare(req, request, tmp, NULL); | |
360 | 360 | fr_pair_list_free(&tmp); |
361 | 361 | } |
362 | 362 |
119 | 119 | return 0; |
120 | 120 | } |
121 | 121 | |
122 | #ifdef WITH_DHCP | |
122 | 123 | static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *request) |
123 | 124 | { |
124 | #ifdef WITH_DHCP | |
125 | 125 | int rcode; |
126 | 126 | VALUE_PAIR *vp; |
127 | 127 | rlm_soh_t *inst = instance; |
182 | 182 | } |
183 | 183 | return RLM_MODULE_OK; |
184 | 184 | } |
185 | return RLM_MODULE_NOOP; | |
186 | } | |
185 | 187 | #endif |
186 | return RLM_MODULE_NOOP; | |
187 | } | |
188 | 188 | |
189 | 189 | static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void * instance, REQUEST *request) |
190 | 190 | { |
218 | 218 | .bootstrap = mod_bootstrap, |
219 | 219 | .methods = { |
220 | 220 | [MOD_AUTHORIZE] = mod_authorize, |
221 | #ifdef WITH_DHCP | |
221 | 222 | [MOD_POST_AUTH] = mod_post_auth |
223 | #endif | |
222 | 224 | }, |
223 | 225 | }; |
6 | 6 | ATTRIBUTE Test-Name 1 string |
7 | 7 | ATTRIBUTE Test-Number 2 integer |
8 | 8 | ATTRIBUTE Test-Server-Port 3 integer |
9 | ATTRIBUTE Test-Signed 4 signed | |
9 | 10 | END-VENDOR TEST |
79 | 79 | |
80 | 80 | # again, but the second one attr is not an extended attr |
81 | 81 | 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 |
82 | data Attr-245.26.1.6 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, User-Name = "bob" | |
82 | data Attr-245 = 0x1a800000000106aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, User-Name = "bob" | |
83 | 83 | |
84 | 84 | # No data means that the attribute is an "invalid attribute" |
85 | 85 | decode f5 04 01 00 |
177 | 177 | attribute PMIP6-Home-IPv4-HoA = bob/8 |
178 | 178 | data Failed to parse IPv4 address string "bob/8" |
179 | 179 | |
180 | # | |
181 | # A "concat" attribute, with no data | |
182 | # | |
183 | decode 89 02 | |
184 | data PKM-SS-Cert = 0x | |
185 | ||
186 | # | |
187 | # Or with weirdly formatted data | |
188 | # | |
189 | decode 89 03 ff 89 02 89 03 fe | |
190 | data PKM-SS-Cert = 0xfffe | |
191 | ||
180 | 192 | $INCLUDE tunnel.txt |
181 | 193 | $INCLUDE errors.txt |
182 | 194 | $INCLUDE extended.txt |
5 | 5 | |
6 | 6 | decode - |
7 | 7 | data WiMAX-Release = "1.0" |
8 | ||
9 | decode 1a 08 00 00 60 b5 01 02 | |
10 | data Attr-26 = 0x000060b50102 | |
11 | ||
12 | decode 1a 0a 00 00 60 b5 01 04 00 01 | |
13 | data Attr-26.24757.1 = 0x01 | |
8 | 14 | |
9 | 15 | encode WiMAX-Accounting-Capabilities = 1 |
10 | 16 | data 1a 0c 00 00 60 b5 01 06 00 02 03 01 |
142 | 148 | |
143 | 149 | decode - |
144 | 150 | data WiMAX-Release = "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE", WiMAX-Idle-Mode-Notification-Cap = Supported |
151 | ||
152 | # | |
153 | # Continuation is set, but there's no continued data. | |
154 | decode 1a 0b 00 00 60 b5 31 05 80 00 00 | |
155 | data Attr-26 = 0x000060b53105800000 | |
156 | ||
157 | encode WiMAX-GMT-Timezone-offset = -1 | |
158 | data 1a 0d 00 00 60 b5 03 07 00 ff ff ff ff | |
159 | ||
160 | decode - | |
161 | data WiMAX-GMT-Timezone-offset = -1 | |
162 |