Update upstream source from tag 'upstream/3.0.16+dfsg'
Update to upstream version '3.0.16+dfsg'
with Debian dir 3077756fa153371dd34d6817c16349e7059ec7b3
Michael Stapelberg
6 years ago
18 | 18 | .error GNU Make is required to build FreeRADIUS |
19 | 19 | endif |
20 | 20 | |
21 | # | |
22 | # We require Make.inc, UNLESS the target is "make deb" | |
23 | # | |
24 | # Since "make deb" re-runs configure... there's no point in | |
25 | # requiring the developer to run configure *before* making | |
26 | # the debian packages. | |
27 | # | |
28 | ifneq "$(MAKECMDGOALS)" "deb" | |
21 | 29 | $(if $(wildcard Make.inc),,$(error Missing 'Make.inc' Run './configure [options]' and retry)) |
22 | 30 | |
23 | 31 | include Make.inc |
32 | endif | |
24 | 33 | |
25 | 34 | MFLAGS += --no-print-directory |
26 | 35 | |
33 | 42 | export DESTDIR := $(R) |
34 | 43 | |
35 | 44 | # And over-ride all of the other magic. |
45 | ifneq "$(MAKECMDGOALS)" "deb" | |
36 | 46 | include scripts/boiler.mk |
47 | endif | |
37 | 48 | |
38 | 49 | # |
39 | 50 | # To work around OpenSSL issues with travis. |
757 | 757 | with_openssl_lib_dir |
758 | 758 | with_openssl_include_dir |
759 | 759 | enable_openssl_version_check |
760 | enable_reproducible_builds | |
760 | 761 | with_talloc_lib_dir |
761 | 762 | with_talloc_include_dir |
762 | 763 | with_pcap_lib_dir |
1405 | 1406 | --disable-openssl-version-check |
1406 | 1407 | disable vulnerable OpenSSL version check |
1407 | 1408 | |
1409 | --enable-reproducible-builds | |
1410 | ensure the build does not change each time | |
1408 | 1411 | |
1409 | 1412 | Optional Packages: |
1410 | 1413 | --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] |
2418 | 2421 | |
2419 | 2422 | |
2420 | 2423 | |
2424 | ||
2425 | ||
2426 | ||
2427 | ||
2421 | 2428 | RADIUSD_MAJOR_VERSION=`cat VERSION | cut -f1 -d.` |
2422 | 2429 | RADIUSD_MINOR_VERSION=`cat VERSION | cut -f2 -d.` |
2423 | 2430 | RADIUSD_INCRM_VERSION=`cat VERSION | cut -f3 -d. | sed 's/[\.-].*$//'` |
4321 | 4328 | fi |
4322 | 4329 | |
4323 | 4330 | |
4331 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking or the compiler flag \"-Wno-unknown-warning-option\"" >&5 | |
4332 | $as_echo_n "checking or the compiler flag \"-Wno-unknown-warning-option\"... " >&6; } | |
4333 | if ${ax_cv_cc_no_unknown_warning_option_flag+:} false; then : | |
4334 | $as_echo_n "(cached) " >&6 | |
4335 | else | |
4336 | ||
4337 | ||
4338 | CFLAGS_SAVED=$CFLAGS | |
4339 | CFLAGS="-Werror -Wno-unknown-warning-option" | |
4340 | ||
4341 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
4342 | /* end confdefs.h. */ | |
4343 | ||
4344 | int | |
4345 | main () | |
4346 | { | |
4347 | ||
4348 | /* | |
4349 | * gcc will happily accept -Wno-unknown-warning-option | |
4350 | * only emitting an error about it, if an error ocurrs in the source file. | |
4351 | */ | |
4352 | #if defined(__GNUC__) && !defined(__clang__) | |
4353 | gcc sucks | |
4354 | #endif | |
4355 | ||
4356 | return 0; | |
4357 | ||
4358 | ; | |
4359 | return 0; | |
4360 | } | |
4361 | _ACEOF | |
4362 | if ac_fn_c_try_compile "$LINENO"; then : | |
4363 | ax_cv_cc_no_unknown_warning_option_flag=yes | |
4364 | else | |
4365 | ax_cv_cc_no_unknown_warning_option_flag=no | |
4366 | fi | |
4367 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
4368 | ||
4369 | CFLAGS="$CFLAGS_SAVED" | |
4370 | ||
4371 | fi | |
4372 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cc_no_unknown_warning_option_flag" >&5 | |
4373 | $as_echo "$ax_cv_cc_no_unknown_warning_option_flag" >&6; } | |
4374 | ||
4375 | if test "x$ax_cv_cc_no_unknown_warning_option_flag" = "xyes"; then | |
4376 | CFLAGS="$CFLAGS -Wno-unknown-warning-option" | |
4377 | fi | |
4378 | ||
4379 | ||
4324 | 4380 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the compiler flag \"-Qunused-arguments\"" >&5 |
4325 | 4381 | $as_echo_n "checking for the compiler flag \"-Qunused-arguments\"... " >&6; } |
4326 | 4382 | if ${ax_cv_cc_qunused_arguments_flag+:} false; then : |
5468 | 5524 | fi |
5469 | 5525 | |
5470 | 5526 | |
5527 | # Check whether --enable-reproducible-builds was given. | |
5528 | if test "${enable_reproducible_builds+set}" = set; then : | |
5529 | enableval=$enable_reproducible_builds; case "$enableval" in | |
5530 | yes) | |
5531 | ||
5532 | $as_echo "#define ENABLE_REPRODUCIBLE_BUILDS 1" >>confdefs.h | |
5533 | ||
5534 | reproducible_builds=yes | |
5535 | ;; | |
5536 | *) | |
5537 | reproducible_builds=no | |
5538 | esac | |
5539 | ||
5540 | fi | |
5541 | ||
5542 | ||
5471 | 5543 | |
5472 | 5544 | |
5473 | 5545 | CHECKRAD=checkrad |
7968 | 8040 | grp.h \ |
7969 | 8041 | inttypes.h \ |
7970 | 8042 | limits.h \ |
8043 | linux/if_packet.h \ | |
7971 | 8044 | malloc.h \ |
7972 | 8045 | netdb.h \ |
7973 | 8046 | netinet/in.h \ |
9046 | 9119 | |
9047 | 9120 | smart_prefix= |
9048 | 9121 | |
9049 | if test "x$ac_cv_header_pcap_h" == "xyes"; then | |
9122 | if test "x$ac_cv_header_pcap_h" = "xyes"; then | |
9050 | 9123 | |
9051 | 9124 | $as_echo "#define HAVE_PCAP_H 1" >>confdefs.h |
9052 | 9125 | |
9289 | 9362 | |
9290 | 9363 | smart_prefix= |
9291 | 9364 | |
9292 | if test "x$ac_cv_header_collectd_client_h" == "xyes"; then | |
9365 | if test "x$ac_cv_header_collectd_client_h" = "xyes"; then | |
9293 | 9366 | |
9294 | 9367 | $as_echo "#define HAVE_COLLECTDC_H 1" >>confdefs.h |
9295 | 9368 | |
9532 | 9605 | |
9533 | 9606 | smart_prefix= |
9534 | 9607 | |
9535 | if test "x$ac_cv_header_sys_capability_h" == "xyes"; then | |
9608 | if test "x$ac_cv_header_sys_capability_h" = "xyes"; then | |
9536 | 9609 | |
9537 | 9610 | $as_echo "#define HAVE_CAPABILITY_H 1" >>confdefs.h |
9538 | 9611 | |
12655 | 12728 | |
12656 | 12729 | |
12657 | 12730 | |
12658 | if test "x$werror" == "xyes"; then | |
12731 | if test "x$reproducible_builds" != "xyes"; then | |
12732 | CFLAGS="-Wno-date-time $CFLAGS" | |
12733 | fi | |
12734 | ||
12735 | if test "x$werror" = "xyes"; then | |
12659 | 12736 | CFLAGS="-Werror $CFLAGS" |
12660 | 12737 | fi |
12661 | 12738 |
141 | 141 | dnl # |
142 | 142 | if test "x$GCC" = "xyes"; then |
143 | 143 | CFLAGS="$CFLAGS -Wall -std=c99 -D_GNU_SOURCE" |
144 | fi | |
145 | ||
146 | dnl # | |
147 | dnl # -Wno-unknown-warning-option means the compiler doesn't complain about diag pragmas | |
148 | dnl # for warnings it doesn't understand. This may sound like a bad idea, but consider | |
149 | dnl # the number of different compiler versions we build under, and the fact that the | |
150 | dnl # more anally retentive warnings are likely to be added in later versions. | |
151 | dnl # | |
152 | AX_CC_NO_UNKNOWN_WARNING_OPTION_FLAG | |
153 | if test "x$ax_cv_cc_no_unknown_warning_option_flag" = "xyes"; then | |
154 | CFLAGS="$CFLAGS -Wno-unknown-warning-option" | |
144 | 155 | fi |
145 | 156 | |
146 | 157 | dnl # |
596 | 607 | openssl_version_check_config= |
597 | 608 | fi |
598 | 609 | AC_SUBST([openssl_version_check_config]) |
610 | ||
611 | dnl # | |
612 | dnl # extra argument: --enable-reproducible-builds | |
613 | dnl # | |
614 | AC_ARG_ENABLE(reproducible-builds, | |
615 | [AS_HELP_STRING([--enable-reproducible-builds], | |
616 | [ensure the build does not change each time])], | |
617 | [ case "$enableval" in | |
618 | yes) | |
619 | AC_DEFINE(ENABLE_REPRODUCIBLE_BUILDS, [1], | |
620 | [Define to ensure each build is the same]) | |
621 | reproducible_builds=yes | |
622 | ;; | |
623 | *) | |
624 | reproducible_builds=no | |
625 | esac ] | |
626 | ) | |
599 | 627 | |
600 | 628 | |
601 | 629 | dnl ############################################################# |
1004 | 1032 | grp.h \ |
1005 | 1033 | inttypes.h \ |
1006 | 1034 | limits.h \ |
1035 | linux/if_packet.h \ | |
1007 | 1036 | malloc.h \ |
1008 | 1037 | netdb.h \ |
1009 | 1038 | netinet/in.h \ |
1212 | 1241 | dnl # |
1213 | 1242 | smart_try_dir="$pcap_include_dir" |
1214 | 1243 | FR_SMART_CHECK_INCLUDE([pcap.h]) |
1215 | if test "x$ac_cv_header_pcap_h" == "xyes"; then | |
1244 | if test "x$ac_cv_header_pcap_h" = "xyes"; then | |
1216 | 1245 | AC_DEFINE(HAVE_PCAP_H, 1, [Define to 1 if you have the <pcap.h> header file.]) |
1217 | 1246 | AC_SUBST(PCAP_LIBS) |
1218 | 1247 | AC_SUBST(PCAP_LDFLAGS) |
1230 | 1259 | dnl # |
1231 | 1260 | smart_try_dir="$collectdclient_include_dir" |
1232 | 1261 | FR_SMART_CHECK_INCLUDE([collectd/client.h]) |
1233 | if test "x$ac_cv_header_collectd_client_h" == "xyes"; then | |
1262 | if test "x$ac_cv_header_collectd_client_h" = "xyes"; then | |
1234 | 1263 | AC_DEFINE(HAVE_COLLECTDC_H, 1, [Define to 1 if you have the `collectdclient' library (-lcollectdclient).]) |
1235 | 1264 | AC_SUBST(COLLECTDC_LIBS) |
1236 | 1265 | AC_SUBST(COLLECTDC_LDFLAGS) |
1250 | 1279 | dnl # |
1251 | 1280 | smart_try_dir="$cap_include_dir" |
1252 | 1281 | FR_SMART_CHECK_INCLUDE([sys/capability.h]) |
1253 | if test "x$ac_cv_header_sys_capability_h" == "xyes"; then | |
1282 | if test "x$ac_cv_header_sys_capability_h" = "xyes"; then | |
1254 | 1283 | AC_DEFINE(HAVE_CAPABILITY_H, 1, [Define to 1 if you have the <sys/capability.h> header file.]) |
1255 | 1284 | else |
1256 | 1285 | AC_MSG_WARN([cap headers not found, will not perform debugger checks. Use --with-cap-include-dir=<path>.]) |
1497 | 1526 | dnl # |
1498 | 1527 | dnl # Check if we have utmpx.h |
1499 | 1528 | dnl # if so, check if struct utmpx has entry ut_xtime |
1500 | dnl # if not, set it to define ut_xtime == ut_tv.tv_sec | |
1529 | dnl # if not, set it to define ut_xtime = ut_tv.tv_sec | |
1501 | 1530 | dnl # |
1502 | 1531 | if test "x$ac_cv_header_utmpx_h" = "xyes"; then |
1503 | 1532 | FR_CHECK_STRUCT_HAS_MEMBER([#include <utmpx.h>], [struct utmpx], ut_xtime) |
2210 | 2239 | AC_CONFIG_SUBDIRS($mysubdirs) |
2211 | 2240 | AC_SUBST(MODULES) |
2212 | 2241 | |
2242 | dnl # | |
2243 | dnl # If reproducible builds are not enabled, disable | |
2244 | dnl # -Wdate-time so the compiler doesn't croak. | |
2245 | dnl # | |
2246 | if test "x$reproducible_builds" != "xyes"; then | |
2247 | CFLAGS="-Wno-date-time $CFLAGS" | |
2248 | fi | |
2249 | ||
2213 | 2250 | dnl ############################################################# |
2214 | 2251 | dnl # |
2215 | 2252 | dnl # Add -Werror last, so it doesn't interfere with autoconf's |
2216 | 2253 | dnl # test programs. |
2217 | 2254 | dnl # |
2218 | 2255 | dnl ############################################################# |
2219 | if test "x$werror" == "xyes"; then | |
2256 | if test "x$werror" = "xyes"; then | |
2220 | 2257 | CFLAGS="-Werror $CFLAGS" |
2221 | 2258 | fi |
2222 | 2259 |
0 | FreeRADIUS 3.0.16 Thu 11 Jan 2018 12:00:00 EST urgency=low | |
1 | Feature improvements | |
2 | * rlm_python now supports multiple lists. From #2031. | |
3 | * Add trust router re-keying. From #2007. | |
4 | * Add support for Samba / AD LDAP schema. | |
5 | See doc/schemas/ldap/samba/README.txt and | |
6 | doc/schemas/ldap/samba/ | |
7 | * Add "tls_min_version" and "tls_max_version" to EAP module | |
8 | for Debian OpenSSL issues. | |
9 | * Better documentation for client certificates in PEAP and TTLS: | |
10 | it usually doesn't work. Fixes #2068. | |
11 | * Distinguish login failure from AD unavailable. Fixes #2069. | |
12 | * Update RH spec files. Fixes #2070. | |
13 | * Run Post-Proxy-Type if all home servers are dead. | |
14 | Fixes #2072. | |
15 | * Print offending IP addresses when EAP sessions come from | |
16 | two upstream home servers, and rate-limit the messages. | |
17 | * Minor packaging updates. | |
18 | * Better documentation for rlm_rest. | |
19 | * EAP-FAST now has it's own "cipher_list", so that it is | |
20 | easier to configure. | |
21 | * EAP-FAST now forcibly disables TLS1.2, until such time | |
22 | as we implement the new keying mechanism from TLS1.2. | |
23 | * Add documentation for allow_expired_crl. | |
24 | * Update Debian logrotation. #2093 and #2101. | |
25 | * DHCP relay can now drop responses. #2095. | |
26 | * rlm_sqlippool can now assign Delegated-IPv6-Prefix. | |
27 | It also now can assign any IPv4 or IPv6 address. | |
28 | Based on patches from maximumG. #2094. | |
29 | See raddb/mods-available/sqlippool for changes. | |
30 | * radeapclient can now use EAP-SIM-Ki to dynamically | |
31 | create the necessary triplets. | |
32 | * Explain why many LDAP connections are closed. | |
33 | Fixes #1969. | |
34 | * Debian build / package issues fixed by Matthew Newton. | |
35 | * dictionary.patton updates from Brice Schaffner. Fixes #2137. | |
36 | * Added scripts to build "inner-server.pem", and updated | |
37 | mods-config/inner-eap and certs/README to match. | |
38 | * Added provisions for using an external CA. See raddb/certs/ | |
39 | * Include dhcpclient binary in freeradius-dhcp debian packge. | |
40 | ||
41 | Bug fixes | |
42 | * Bind the lifetime of program name and python path to the module | |
43 | FR-AD-002 (redone) | |
44 | * Pass correct statement length into sqlite3_prepare[_v2] | |
45 | FR-AD-003 (redone) | |
46 | * Allow 100-Continue responses with additional headers in rlm_rest. | |
47 | * fix corner case where detail files were not being locked | |
48 | correctly. | |
49 | * Fix (SQL-Group == "%{...}") checks, and same for LDAP-Group. | |
50 | Fixes #1947 | |
51 | * Clean up exfile code. Which should help to avoid issues | |
52 | with reading / writing 100's of detail files. | |
53 | * Fix build for winbind. Patch from Alex Clouter. | |
54 | * Fix checkrad for Mikrotik. Patch from Muchael Ducharme. | |
55 | * Fix home server stats lookup. Patch from Phil Mayers. | |
56 | * Add libjson-c3 as an optional dependency. | |
57 | * Require LTB OpenLDAP on CentOS / Redhat, to avoid linking | |
58 | against NSS, which breaks the server. Fixes #2040. | |
59 | * rlm_python fixes. Fixes #2041 | |
60 | * Typos in "man" pages. Fixes #2045 | |
61 | * Expand "next" in %{%{...}:-%{...}}. Fixes #2048 | |
62 | * Don't add TLS attributes twice. Fixes #2050. | |
63 | * Fix memory allocation in rlm_rest. Fixes #2051. | |
64 | * Update trustrouter for new API. Fixes #2059. | |
65 | * Fix SQLite issues on FreeBSD. Fixes #2060 | |
66 | * Don't do debug logging of bad passwords. Fixes #2064. | |
67 | * More graceful handling of "die" in rlm_perl. Fixes #2073. | |
68 | * Fix occasional crash when using | |
69 | cisco_accounting_username_bug = yes | |
70 | * EAP-FAST fixes from Isaac Boukris. | |
71 | #2078, #2076, and #2082, #2126. | |
72 | * DHCP fixes, relay, #2092, add run-time check, #2028 | |
73 | * Decode multiple RADIUS packets at a time in highly loaded | |
74 | RadSec connections. Patch from Jan Tomasek. #2106. | |
75 | * TunnelPassword is not "single value" in LDAP schema. | |
76 | Fixes #2061. | |
77 | * sql log now opens the expanded filename, not the input one. | |
78 | This was a regression introduced in 3.0.15. | |
79 | * Remove unnecessary UNIQUE constrain in Oracle schemas. | |
80 | * Fix SSL thread and locking issues when modules also use SSL. | |
81 | Fixes #2125 and #2129. | |
82 | * Re-add dhcpclient "raw packet" changes. Patches from | |
83 | Nicolas Chaigne and Matthew Newton. Fixes #2155. | |
84 | ||
0 | 85 | FreeRADIUS 3.0.15 Mon 17 Jul 2017 09:00:00 EDT urgency=high |
1 | 86 | Feature improvements |
2 | 87 | * Provide HOSTNAME in default systemd files. |
25 | 110 | FR-GV-305 |
26 | 111 | * use strncmp() instead of memcmp() for bounded data |
27 | 112 | FR-AD-001 |
113 | * Bind the lifetime of program name and python path to the module | |
114 | FR-AD-002 | |
115 | * Pass correct statement length into sqlite3_prepare[_v2] | |
116 | FR-AD-003 | |
28 | 117 | * print messages when we see deprecated configuration |
29 | 118 | items |
30 | 119 | * show reasons why we couldn't parse a certificate |
559 | 648 | |
560 | 649 | FreeRADIUS 3.0.8 Wed 22 Apr 2015 13:30:00 EDT urgency=medium |
561 | 650 | Feature improvements |
562 | * Allow syslog_severity to be set in rlm_linelog. | |
651 | * Allow syslog_severity to be set in rlm_linelog. | |
563 | 652 | * Allow defaults to be set for bulk clients in LDAP and couchbase. |
564 | 653 | * Updates to dhcpclient. Patches from Nicolas C. |
565 | 654 | * rlm_mschap now supports direct connections to winbind, which |
1452 | 1541 | * Added EAP-PWD implementation from Dan Harkins |
1453 | 1542 | * Added connection pools for modules. This unifies connection |
1454 | 1543 | management which was previously different for different modules. |
1455 | * SQL now uses the connection pool. See mods-available/sql | |
1544 | * SQL now uses the connection pool. See mods-available/sql | |
1456 | 1545 | * SQL now supports arbitrary Acct-Status-Types. |
1457 | 1546 | These changes are not compatible with 2.x. |
1458 | 1547 | * SQL now has full support for SQLite. See raddb/sql/main/sqlite/ |
1625 | 1625 | ++++++++++ |
1626 | 1626 | |
1627 | 1627 | * _`FreeRADIUS`: http://www.freeradius.org |
1628 | * _`FreeRADIUS Documentation`: http://www.freeradius.org/radiusd/doc | |
1628 | * _`FreeRADIUS Documentation`: http://freeradius.org/documentation/ | |
1629 | 1629 | * _`FreeRADIUS Wiki`: http://wiki.freeradius.org/ |
1630 | 1630 | |
1631 | 1631 | OPENLDAP |
1637 | 1637 | RFCs |
1638 | 1638 | ++++ |
1639 | 1639 | |
1640 | * _`RFC2865: RADIUS Authentication`: http://www.freeradius.org/radiusd/doc/rfc/rfc2865.txt | |
1641 | * _`RFC2866: RADIUS Accounting`: http://www.freeradius.org/radiusd/doc/rfc/rfc2866.txt | |
1642 | * _`RFC2869: RADIUS Extentions`: http://www.freeradius.org/radiusd/doc/rfc/rfc2869.txt | |
1640 | * _`RFC2865: RADIUS Authentication`: http://freeradius.org/rfc/rfc2865.txt | |
1641 | * _`RFC2866: RADIUS Accounting`: http://freeradius.org/rfc/rfc2866.txt | |
1642 | * _`RFC2869: RADIUS Extentions`: http://freeradius.org/rfc/rfc2869.txt | |
1643 | 1643 | * _`RFC2251: LDAP v3`: http://www.ietf.org/rfc/rfc2251.txt |
1644 | 1644 | * _`RFC2252: LDAP v3 Attribute Syntax Definitions`: http://www.ietf.org/rfc/rfc2252.txt |
1645 | 1645 | * _`RFC2253: LDAP UTF-8 String Representation of Distinguishe d Names (DNs)`: http://www.ietf.org/rfc/rfc2252.txt |
336 | 336 | NAME 'radiusTunnelPassword' |
337 | 337 | EQUALITY caseIgnoreIA5Match |
338 | 338 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 |
339 | SINGLE-VALUE | |
340 | 339 | ) |
341 | 340 | |
342 | 341 | attributetype ( 1.3.6.1.4.1.11344.4.3.1.38 |
0 | Change "dc=samba4,dc=internal" to your LDAP base DN, | |
1 | then install with: | |
2 | ||
3 | ldbmodify -H /usr/local/samba/private/sam.ldb freeradius-attrs.ldif \ | |
4 | --option="dsdb:schema update allowed"=true | |
5 | ldbmodify -H /usr/local/samba/private/sam.ldb freeradius-classes.ldif \ | |
6 | --option="dsdb:schema update allowed"=true | |
7 | ||
8 | These files were created by scripts/ldap/schema_to_samba.py, then | |
9 | split into two because the attributes must be loaded in a separate | |
10 | operation to the classes which use them. |
0 | dn: CN=radiusArapFeatures,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
1 | changetype: add | |
2 | objectClass: top | |
3 | objectClass: attributeSchema | |
4 | attributeID: 1.3.6.1.4.1.11344.4.3.1.1 | |
5 | isSingleValued: TRUE | |
6 | cn: radiusArapFeatures | |
7 | name: radiusArapFeatures | |
8 | lDAPDisplayName: radiusArapFeatures | |
9 | attributeSyntax: 2.5.5.5 | |
10 | oMSyntax: 22 | |
11 | ||
12 | dn: CN=radiusArapSecurity,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
13 | changetype: add | |
14 | objectClass: top | |
15 | objectClass: attributeSchema | |
16 | attributeID: 1.3.6.1.4.1.11344.4.3.1.2 | |
17 | isSingleValued: TRUE | |
18 | cn: radiusArapSecurity | |
19 | name: radiusArapSecurity | |
20 | lDAPDisplayName: radiusArapSecurity | |
21 | attributeSyntax: 2.5.5.5 | |
22 | oMSyntax: 22 | |
23 | ||
24 | dn: CN=radiusArapZoneAccess,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
25 | changetype: add | |
26 | objectClass: top | |
27 | objectClass: attributeSchema | |
28 | attributeID: 1.3.6.1.4.1.11344.4.3.1.3 | |
29 | isSingleValued: TRUE | |
30 | cn: radiusArapZoneAccess | |
31 | name: radiusArapZoneAccess | |
32 | lDAPDisplayName: radiusArapZoneAccess | |
33 | attributeSyntax: 2.5.5.5 | |
34 | oMSyntax: 22 | |
35 | ||
36 | dn: CN=radiusAuthType,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
37 | changetype: add | |
38 | objectClass: top | |
39 | objectClass: attributeSchema | |
40 | attributeID: 1.3.6.1.4.1.11344.4.3.1.44 | |
41 | isSingleValued: TRUE | |
42 | cn: radiusAuthType | |
43 | name: radiusAuthType | |
44 | lDAPDisplayName: radiusAuthType | |
45 | description: controlItem: Auth-Type | |
46 | attributeSyntax: 2.5.5.5 | |
47 | oMSyntax: 22 | |
48 | ||
49 | dn: CN=radiusCallbackId,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
50 | changetype: add | |
51 | objectClass: top | |
52 | objectClass: attributeSchema | |
53 | attributeID: 1.3.6.1.4.1.11344.4.3.1.4 | |
54 | isSingleValued: TRUE | |
55 | cn: radiusCallbackId | |
56 | name: radiusCallbackId | |
57 | lDAPDisplayName: radiusCallbackId | |
58 | description: replyItem: Callback-Id | |
59 | attributeSyntax: 2.5.5.5 | |
60 | oMSyntax: 22 | |
61 | ||
62 | dn: CN=radiusCallbackNumber,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
63 | changetype: add | |
64 | objectClass: top | |
65 | objectClass: attributeSchema | |
66 | attributeID: 1.3.6.1.4.1.11344.4.3.1.5 | |
67 | isSingleValued: TRUE | |
68 | cn: radiusCallbackNumber | |
69 | name: radiusCallbackNumber | |
70 | lDAPDisplayName: radiusCallbackNumber | |
71 | description: replyItem: Callback-Number | |
72 | attributeSyntax: 2.5.5.5 | |
73 | oMSyntax: 22 | |
74 | ||
75 | dn: CN=radiusCalledStationId,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
76 | changetype: add | |
77 | objectClass: top | |
78 | objectClass: attributeSchema | |
79 | attributeID: 1.3.6.1.4.1.11344.4.3.1.6 | |
80 | isSingleValued: TRUE | |
81 | cn: radiusCalledStationId | |
82 | name: radiusCalledStationId | |
83 | lDAPDisplayName: radiusCalledStationId | |
84 | description: controlItem: Called-Station-Id | |
85 | attributeSyntax: 2.5.5.5 | |
86 | oMSyntax: 22 | |
87 | ||
88 | dn: CN=radiusCallingStationId,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
89 | changetype: add | |
90 | objectClass: top | |
91 | objectClass: attributeSchema | |
92 | attributeID: 1.3.6.1.4.1.11344.4.3.1.7 | |
93 | isSingleValued: TRUE | |
94 | cn: radiusCallingStationId | |
95 | name: radiusCallingStationId | |
96 | lDAPDisplayName: radiusCallingStationId | |
97 | description: controlItem: Calling-Station-Id | |
98 | attributeSyntax: 2.5.5.5 | |
99 | oMSyntax: 22 | |
100 | ||
101 | dn: CN=radiusClass,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
102 | changetype: add | |
103 | objectClass: top | |
104 | objectClass: attributeSchema | |
105 | attributeID: 1.3.6.1.4.1.11344.4.3.1.8 | |
106 | isSingleValued: FALSE | |
107 | cn: radiusClass | |
108 | name: radiusClass | |
109 | lDAPDisplayName: radiusClass | |
110 | description: replyItem: Class | |
111 | attributeSyntax: 2.5.5.5 | |
112 | oMSyntax: 22 | |
113 | ||
114 | dn: CN=radiusClientIPAddress,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
115 | changetype: add | |
116 | objectClass: top | |
117 | objectClass: attributeSchema | |
118 | attributeID: 1.3.6.1.4.1.11344.4.3.1.45 | |
119 | isSingleValued: TRUE | |
120 | cn: radiusClientIPAddress | |
121 | name: radiusClientIPAddress | |
122 | lDAPDisplayName: radiusClientIPAddress | |
123 | attributeSyntax: 2.5.5.5 | |
124 | oMSyntax: 22 | |
125 | ||
126 | dn: CN=radiusFilterId,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
127 | changetype: add | |
128 | objectClass: top | |
129 | objectClass: attributeSchema | |
130 | attributeID: 1.3.6.1.4.1.11344.4.3.1.9 | |
131 | isSingleValued: FALSE | |
132 | cn: radiusFilterId | |
133 | name: radiusFilterId | |
134 | lDAPDisplayName: radiusFilterId | |
135 | description: replyItem: Filter-Id | |
136 | attributeSyntax: 2.5.5.5 | |
137 | oMSyntax: 22 | |
138 | ||
139 | dn: CN=radiusFramedAppleTalkLink,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
140 | changetype: add | |
141 | objectClass: top | |
142 | objectClass: attributeSchema | |
143 | attributeID: 1.3.6.1.4.1.11344.4.3.1.10 | |
144 | isSingleValued: TRUE | |
145 | cn: radiusFramedAppleTalkLink | |
146 | name: radiusFramedAppleTalkLink | |
147 | lDAPDisplayName: radiusFramedAppleTalkLink | |
148 | description: replyItem: Framed-AppleTalk-Link | |
149 | attributeSyntax: 2.5.5.5 | |
150 | oMSyntax: 22 | |
151 | ||
152 | dn: CN=radiusFramedAppleTalkNetwork,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
153 | changetype: add | |
154 | objectClass: top | |
155 | objectClass: attributeSchema | |
156 | attributeID: 1.3.6.1.4.1.11344.4.3.1.11 | |
157 | isSingleValued: FALSE | |
158 | cn: radiusFramedAppleTalkNetwork | |
159 | name: radiusFramedAppleTalkNetwork | |
160 | lDAPDisplayName: radiusFramedAppleTalkNetwork | |
161 | description: replyItem: Framed-AppleTalk-Network | |
162 | attributeSyntax: 2.5.5.5 | |
163 | oMSyntax: 22 | |
164 | ||
165 | dn: CN=radiusFramedAppleTalkZone,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
166 | changetype: add | |
167 | objectClass: top | |
168 | objectClass: attributeSchema | |
169 | attributeID: 1.3.6.1.4.1.11344.4.3.1.12 | |
170 | isSingleValued: TRUE | |
171 | cn: radiusFramedAppleTalkZone | |
172 | name: radiusFramedAppleTalkZone | |
173 | lDAPDisplayName: radiusFramedAppleTalkZone | |
174 | description: replyItem: Framed-AppleTalk-Zone | |
175 | attributeSyntax: 2.5.5.5 | |
176 | oMSyntax: 22 | |
177 | ||
178 | dn: CN=radiusFramedCompression,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
179 | changetype: add | |
180 | objectClass: top | |
181 | objectClass: attributeSchema | |
182 | attributeID: 1.3.6.1.4.1.11344.4.3.1.13 | |
183 | isSingleValued: FALSE | |
184 | cn: radiusFramedCompression | |
185 | name: radiusFramedCompression | |
186 | lDAPDisplayName: radiusFramedCompression | |
187 | description: replyItem: Framed-Compression | |
188 | attributeSyntax: 2.5.5.5 | |
189 | oMSyntax: 22 | |
190 | ||
191 | dn: CN=radiusFramedIPAddress,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
192 | changetype: add | |
193 | objectClass: top | |
194 | objectClass: attributeSchema | |
195 | attributeID: 1.3.6.1.4.1.11344.4.3.1.14 | |
196 | isSingleValued: TRUE | |
197 | cn: radiusFramedIPAddress | |
198 | name: radiusFramedIPAddress | |
199 | lDAPDisplayName: radiusFramedIPAddress | |
200 | description: replyItem: Framed-IP-Address | |
201 | attributeSyntax: 2.5.5.5 | |
202 | oMSyntax: 22 | |
203 | ||
204 | dn: CN=radiusFramedIPNetmask,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
205 | changetype: add | |
206 | objectClass: top | |
207 | objectClass: attributeSchema | |
208 | attributeID: 1.3.6.1.4.1.11344.4.3.1.15 | |
209 | isSingleValued: TRUE | |
210 | cn: radiusFramedIPNetmask | |
211 | name: radiusFramedIPNetmask | |
212 | lDAPDisplayName: radiusFramedIPNetmask | |
213 | description: replyItem: Framed-IP-Netmask | |
214 | attributeSyntax: 2.5.5.5 | |
215 | oMSyntax: 22 | |
216 | ||
217 | dn: CN=radiusFramedIPXNetwork,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
218 | changetype: add | |
219 | objectClass: top | |
220 | objectClass: attributeSchema | |
221 | attributeID: 1.3.6.1.4.1.11344.4.3.1.16 | |
222 | isSingleValued: TRUE | |
223 | cn: radiusFramedIPXNetwork | |
224 | name: radiusFramedIPXNetwork | |
225 | lDAPDisplayName: radiusFramedIPXNetwork | |
226 | description: replyItem: Framed-IPX-Network | |
227 | attributeSyntax: 2.5.5.5 | |
228 | oMSyntax: 22 | |
229 | ||
230 | dn: CN=radiusFramedMTU,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
231 | changetype: add | |
232 | objectClass: top | |
233 | objectClass: attributeSchema | |
234 | attributeID: 1.3.6.1.4.1.11344.4.3.1.17 | |
235 | isSingleValued: TRUE | |
236 | cn: radiusFramedMTU | |
237 | name: radiusFramedMTU | |
238 | lDAPDisplayName: radiusFramedMTU | |
239 | description: replyItem: Framed-MTU | |
240 | attributeSyntax: 2.5.5.5 | |
241 | oMSyntax: 22 | |
242 | ||
243 | dn: CN=radiusFramedProtocol,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
244 | changetype: add | |
245 | objectClass: top | |
246 | objectClass: attributeSchema | |
247 | attributeID: 1.3.6.1.4.1.11344.4.3.1.18 | |
248 | isSingleValued: TRUE | |
249 | cn: radiusFramedProtocol | |
250 | name: radiusFramedProtocol | |
251 | lDAPDisplayName: radiusFramedProtocol | |
252 | description: replyItem: Framed-Protocol | |
253 | attributeSyntax: 2.5.5.5 | |
254 | oMSyntax: 22 | |
255 | ||
256 | dn: CN=radiusFramedRoute,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
257 | changetype: add | |
258 | objectClass: top | |
259 | objectClass: attributeSchema | |
260 | attributeID: 1.3.6.1.4.1.11344.4.3.1.19 | |
261 | isSingleValued: FALSE | |
262 | cn: radiusFramedRoute | |
263 | name: radiusFramedRoute | |
264 | lDAPDisplayName: radiusFramedRoute | |
265 | description: replyItem: Framed-Route | |
266 | attributeSyntax: 2.5.5.5 | |
267 | oMSyntax: 22 | |
268 | ||
269 | dn: CN=radiusFramedRouting,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
270 | changetype: add | |
271 | objectClass: top | |
272 | objectClass: attributeSchema | |
273 | attributeID: 1.3.6.1.4.1.11344.4.3.1.20 | |
274 | isSingleValued: TRUE | |
275 | cn: radiusFramedRouting | |
276 | name: radiusFramedRouting | |
277 | lDAPDisplayName: radiusFramedRouting | |
278 | description: replyItem: Framed-Routing | |
279 | attributeSyntax: 2.5.5.5 | |
280 | oMSyntax: 22 | |
281 | ||
282 | dn: CN=radiusGroupName,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
283 | changetype: add | |
284 | objectClass: top | |
285 | objectClass: attributeSchema | |
286 | attributeID: 1.3.6.1.4.1.11344.4.3.1.46 | |
287 | isSingleValued: FALSE | |
288 | cn: radiusGroupName | |
289 | name: radiusGroupName | |
290 | lDAPDisplayName: radiusGroupName | |
291 | attributeSyntax: 2.5.5.5 | |
292 | oMSyntax: 22 | |
293 | ||
294 | dn: CN=radiusHint,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
295 | changetype: add | |
296 | objectClass: top | |
297 | objectClass: attributeSchema | |
298 | attributeID: 1.3.6.1.4.1.11344.4.3.1.47 | |
299 | isSingleValued: TRUE | |
300 | cn: radiusHint | |
301 | name: radiusHint | |
302 | lDAPDisplayName: radiusHint | |
303 | attributeSyntax: 2.5.5.5 | |
304 | oMSyntax: 22 | |
305 | ||
306 | dn: CN=radiusHuntgroupName,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
307 | changetype: add | |
308 | objectClass: top | |
309 | objectClass: attributeSchema | |
310 | attributeID: 1.3.6.1.4.1.11344.4.3.1.48 | |
311 | isSingleValued: FALSE | |
312 | cn: radiusHuntgroupName | |
313 | name: radiusHuntgroupName | |
314 | lDAPDisplayName: radiusHuntgroupName | |
315 | attributeSyntax: 2.5.5.5 | |
316 | oMSyntax: 22 | |
317 | ||
318 | dn: CN=radiusIdleTimeout,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
319 | changetype: add | |
320 | objectClass: top | |
321 | objectClass: attributeSchema | |
322 | attributeID: 1.3.6.1.4.1.11344.4.3.1.21 | |
323 | isSingleValued: TRUE | |
324 | cn: radiusIdleTimeout | |
325 | name: radiusIdleTimeout | |
326 | lDAPDisplayName: radiusIdleTimeout | |
327 | description: replyItem: Idle-Timeout | |
328 | attributeSyntax: 2.5.5.5 | |
329 | oMSyntax: 22 | |
330 | ||
331 | dn: CN=radiusLoginIPHost,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
332 | changetype: add | |
333 | objectClass: top | |
334 | objectClass: attributeSchema | |
335 | attributeID: 1.3.6.1.4.1.11344.4.3.1.22 | |
336 | isSingleValued: FALSE | |
337 | cn: radiusLoginIPHost | |
338 | name: radiusLoginIPHost | |
339 | lDAPDisplayName: radiusLoginIPHost | |
340 | description: replyItem: Login-IP-Host | |
341 | attributeSyntax: 2.5.5.5 | |
342 | oMSyntax: 22 | |
343 | ||
344 | dn: CN=radiusLoginLATGroup,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
345 | changetype: add | |
346 | objectClass: top | |
347 | objectClass: attributeSchema | |
348 | attributeID: 1.3.6.1.4.1.11344.4.3.1.23 | |
349 | isSingleValued: TRUE | |
350 | cn: radiusLoginLATGroup | |
351 | name: radiusLoginLATGroup | |
352 | lDAPDisplayName: radiusLoginLATGroup | |
353 | description: replyItem: Login-LAT-Group | |
354 | attributeSyntax: 2.5.5.5 | |
355 | oMSyntax: 22 | |
356 | ||
357 | dn: CN=radiusLoginLATNode,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
358 | changetype: add | |
359 | objectClass: top | |
360 | objectClass: attributeSchema | |
361 | attributeID: 1.3.6.1.4.1.11344.4.3.1.24 | |
362 | isSingleValued: TRUE | |
363 | cn: radiusLoginLATNode | |
364 | name: radiusLoginLATNode | |
365 | lDAPDisplayName: radiusLoginLATNode | |
366 | description: replyItem: Login-LAT-Node | |
367 | attributeSyntax: 2.5.5.5 | |
368 | oMSyntax: 22 | |
369 | ||
370 | dn: CN=radiusLoginLATPort,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
371 | changetype: add | |
372 | objectClass: top | |
373 | objectClass: attributeSchema | |
374 | attributeID: 1.3.6.1.4.1.11344.4.3.1.25 | |
375 | isSingleValued: TRUE | |
376 | cn: radiusLoginLATPort | |
377 | name: radiusLoginLATPort | |
378 | lDAPDisplayName: radiusLoginLATPort | |
379 | description: replyItem: Login-LAT-Port | |
380 | attributeSyntax: 2.5.5.5 | |
381 | oMSyntax: 22 | |
382 | ||
383 | dn: CN=radiusLoginLATService,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
384 | changetype: add | |
385 | objectClass: top | |
386 | objectClass: attributeSchema | |
387 | attributeID: 1.3.6.1.4.1.11344.4.3.1.26 | |
388 | isSingleValued: TRUE | |
389 | cn: radiusLoginLATService | |
390 | name: radiusLoginLATService | |
391 | lDAPDisplayName: radiusLoginLATService | |
392 | description: replyItem: Login-LAT-Service | |
393 | attributeSyntax: 2.5.5.5 | |
394 | oMSyntax: 22 | |
395 | ||
396 | dn: CN=radiusLoginService,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
397 | changetype: add | |
398 | objectClass: top | |
399 | objectClass: attributeSchema | |
400 | attributeID: 1.3.6.1.4.1.11344.4.3.1.27 | |
401 | isSingleValued: TRUE | |
402 | cn: radiusLoginService | |
403 | name: radiusLoginService | |
404 | lDAPDisplayName: radiusLoginService | |
405 | description: replyItem: Login-Service | |
406 | attributeSyntax: 2.5.5.5 | |
407 | oMSyntax: 22 | |
408 | ||
409 | dn: CN=radiusLoginTCPPort,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
410 | changetype: add | |
411 | objectClass: top | |
412 | objectClass: attributeSchema | |
413 | attributeID: 1.3.6.1.4.1.11344.4.3.1.28 | |
414 | isSingleValued: TRUE | |
415 | cn: radiusLoginTCPPort | |
416 | name: radiusLoginTCPPort | |
417 | lDAPDisplayName: radiusLoginTCPPort | |
418 | description: replyItem: Login-TCP-Port | |
419 | attributeSyntax: 2.5.5.5 | |
420 | oMSyntax: 22 | |
421 | ||
422 | dn: CN=radiusPasswordRetry,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
423 | changetype: add | |
424 | objectClass: top | |
425 | objectClass: attributeSchema | |
426 | attributeID: 1.3.6.1.4.1.11344.4.3.1.29 | |
427 | isSingleValued: TRUE | |
428 | cn: radiusPasswordRetry | |
429 | name: radiusPasswordRetry | |
430 | lDAPDisplayName: radiusPasswordRetry | |
431 | attributeSyntax: 2.5.5.5 | |
432 | oMSyntax: 22 | |
433 | ||
434 | dn: CN=radiusPortLimit,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
435 | changetype: add | |
436 | objectClass: top | |
437 | objectClass: attributeSchema | |
438 | attributeID: 1.3.6.1.4.1.11344.4.3.1.30 | |
439 | isSingleValued: TRUE | |
440 | cn: radiusPortLimit | |
441 | name: radiusPortLimit | |
442 | lDAPDisplayName: radiusPortLimit | |
443 | description: replyItem: Port-Limit | |
444 | attributeSyntax: 2.5.5.5 | |
445 | oMSyntax: 22 | |
446 | ||
447 | dn: CN=radiusProfileDN,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
448 | changetype: add | |
449 | objectClass: top | |
450 | objectClass: attributeSchema | |
451 | attributeID: 1.3.6.1.4.1.11344.4.3.1.49 | |
452 | isSingleValued: FALSE | |
453 | cn: radiusProfileDN | |
454 | name: radiusProfileDN | |
455 | lDAPDisplayName: radiusProfileDN | |
456 | attributeSyntax: 2.5.5.1 | |
457 | oMSyntax: 127 | |
458 | ||
459 | dn: CN=radiusPrompt,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
460 | changetype: add | |
461 | objectClass: top | |
462 | objectClass: attributeSchema | |
463 | attributeID: 1.3.6.1.4.1.11344.4.3.1.31 | |
464 | isSingleValued: TRUE | |
465 | cn: radiusPrompt | |
466 | name: radiusPrompt | |
467 | lDAPDisplayName: radiusPrompt | |
468 | attributeSyntax: 2.5.5.5 | |
469 | oMSyntax: 22 | |
470 | ||
471 | dn: CN=radiusProxyToRealm,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
472 | changetype: add | |
473 | objectClass: top | |
474 | objectClass: attributeSchema | |
475 | attributeID: 1.3.6.1.4.1.11344.4.3.1.50 | |
476 | isSingleValued: TRUE | |
477 | cn: radiusProxyToRealm | |
478 | name: radiusProxyToRealm | |
479 | lDAPDisplayName: radiusProxyToRealm | |
480 | attributeSyntax: 2.5.5.5 | |
481 | oMSyntax: 22 | |
482 | ||
483 | dn: CN=radiusReplicateToRealm,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
484 | changetype: add | |
485 | objectClass: top | |
486 | objectClass: attributeSchema | |
487 | attributeID: 1.3.6.1.4.1.11344.4.3.1.51 | |
488 | isSingleValued: TRUE | |
489 | cn: radiusReplicateToRealm | |
490 | name: radiusReplicateToRealm | |
491 | lDAPDisplayName: radiusReplicateToRealm | |
492 | description: control:Replicate-To-Realm | |
493 | attributeSyntax: 2.5.5.5 | |
494 | oMSyntax: 22 | |
495 | ||
496 | dn: CN=radiusRealm,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
497 | changetype: add | |
498 | objectClass: top | |
499 | objectClass: attributeSchema | |
500 | attributeID: 1.3.6.1.4.1.11344.4.3.1.52 | |
501 | isSingleValued: TRUE | |
502 | cn: radiusRealm | |
503 | name: radiusRealm | |
504 | lDAPDisplayName: radiusRealm | |
505 | attributeSyntax: 2.5.5.5 | |
506 | oMSyntax: 22 | |
507 | ||
508 | dn: CN=radiusServiceType,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
509 | changetype: add | |
510 | objectClass: top | |
511 | objectClass: attributeSchema | |
512 | attributeID: 1.3.6.1.4.1.11344.4.3.1.32 | |
513 | isSingleValued: TRUE | |
514 | cn: radiusServiceType | |
515 | name: radiusServiceType | |
516 | lDAPDisplayName: radiusServiceType | |
517 | description: replyItem: Service-Type | |
518 | attributeSyntax: 2.5.5.5 | |
519 | oMSyntax: 22 | |
520 | ||
521 | dn: CN=radiusSessionTimeout,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
522 | changetype: add | |
523 | objectClass: top | |
524 | objectClass: attributeSchema | |
525 | attributeID: 1.3.6.1.4.1.11344.4.3.1.33 | |
526 | isSingleValued: TRUE | |
527 | cn: radiusSessionTimeout | |
528 | name: radiusSessionTimeout | |
529 | lDAPDisplayName: radiusSessionTimeout | |
530 | description: replyItem: Session-Timeout | |
531 | attributeSyntax: 2.5.5.5 | |
532 | oMSyntax: 22 | |
533 | ||
534 | dn: CN=radiusTerminationAction,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
535 | changetype: add | |
536 | objectClass: top | |
537 | objectClass: attributeSchema | |
538 | attributeID: 1.3.6.1.4.1.11344.4.3.1.34 | |
539 | isSingleValued: TRUE | |
540 | cn: radiusTerminationAction | |
541 | name: radiusTerminationAction | |
542 | lDAPDisplayName: radiusTerminationAction | |
543 | description: replyItem: Termination-Action | |
544 | attributeSyntax: 2.5.5.5 | |
545 | oMSyntax: 22 | |
546 | ||
547 | dn: CN=radiusTunnelAssignmentId,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
548 | changetype: add | |
549 | objectClass: top | |
550 | objectClass: attributeSchema | |
551 | attributeID: 1.3.6.1.4.1.11344.4.3.1.35 | |
552 | isSingleValued: FALSE | |
553 | cn: radiusTunnelAssignmentId | |
554 | name: radiusTunnelAssignmentId | |
555 | lDAPDisplayName: radiusTunnelAssignmentId | |
556 | attributeSyntax: 2.5.5.5 | |
557 | oMSyntax: 22 | |
558 | ||
559 | dn: CN=radiusTunnelMediumType,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
560 | changetype: add | |
561 | objectClass: top | |
562 | objectClass: attributeSchema | |
563 | attributeID: 1.3.6.1.4.1.11344.4.3.1.36 | |
564 | isSingleValued: FALSE | |
565 | cn: radiusTunnelMediumType | |
566 | name: radiusTunnelMediumType | |
567 | lDAPDisplayName: radiusTunnelMediumType | |
568 | attributeSyntax: 2.5.5.5 | |
569 | oMSyntax: 22 | |
570 | ||
571 | dn: CN=radiusTunnelPassword,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
572 | changetype: add | |
573 | objectClass: top | |
574 | objectClass: attributeSchema | |
575 | attributeID: 1.3.6.1.4.1.11344.4.3.1.37 | |
576 | isSingleValued: TRUE | |
577 | cn: radiusTunnelPassword | |
578 | name: radiusTunnelPassword | |
579 | lDAPDisplayName: radiusTunnelPassword | |
580 | attributeSyntax: 2.5.5.5 | |
581 | oMSyntax: 22 | |
582 | ||
583 | dn: CN=radiusTunnelPreference,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
584 | changetype: add | |
585 | objectClass: top | |
586 | objectClass: attributeSchema | |
587 | attributeID: 1.3.6.1.4.1.11344.4.3.1.38 | |
588 | isSingleValued: FALSE | |
589 | cn: radiusTunnelPreference | |
590 | name: radiusTunnelPreference | |
591 | lDAPDisplayName: radiusTunnelPreference | |
592 | attributeSyntax: 2.5.5.5 | |
593 | oMSyntax: 22 | |
594 | ||
595 | dn: CN=radiusTunnelPrivateGroupId,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
596 | changetype: add | |
597 | objectClass: top | |
598 | objectClass: attributeSchema | |
599 | attributeID: 1.3.6.1.4.1.11344.4.3.1.39 | |
600 | isSingleValued: FALSE | |
601 | cn: radiusTunnelPrivateGroupId | |
602 | name: radiusTunnelPrivateGroupId | |
603 | lDAPDisplayName: radiusTunnelPrivateGroupId | |
604 | attributeSyntax: 2.5.5.5 | |
605 | oMSyntax: 22 | |
606 | ||
607 | dn: CN=radiusTunnelServerEndpoint,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
608 | changetype: add | |
609 | objectClass: top | |
610 | objectClass: attributeSchema | |
611 | attributeID: 1.3.6.1.4.1.11344.4.3.1.40 | |
612 | isSingleValued: FALSE | |
613 | cn: radiusTunnelServerEndpoint | |
614 | name: radiusTunnelServerEndpoint | |
615 | lDAPDisplayName: radiusTunnelServerEndpoint | |
616 | attributeSyntax: 2.5.5.5 | |
617 | oMSyntax: 22 | |
618 | ||
619 | dn: CN=radiusTunnelType,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
620 | changetype: add | |
621 | objectClass: top | |
622 | objectClass: attributeSchema | |
623 | attributeID: 1.3.6.1.4.1.11344.4.3.1.41 | |
624 | isSingleValued: FALSE | |
625 | cn: radiusTunnelType | |
626 | name: radiusTunnelType | |
627 | lDAPDisplayName: radiusTunnelType | |
628 | attributeSyntax: 2.5.5.5 | |
629 | oMSyntax: 22 | |
630 | ||
631 | dn: CN=radiusVSA,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
632 | changetype: add | |
633 | objectClass: top | |
634 | objectClass: attributeSchema | |
635 | attributeID: 1.3.6.1.4.1.11344.4.3.1.42 | |
636 | isSingleValued: FALSE | |
637 | cn: radiusVSA | |
638 | name: radiusVSA | |
639 | lDAPDisplayName: radiusVSA | |
640 | attributeSyntax: 2.5.5.5 | |
641 | oMSyntax: 22 | |
642 | ||
643 | dn: CN=radiusTunnelClientEndpoint,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
644 | changetype: add | |
645 | objectClass: top | |
646 | objectClass: attributeSchema | |
647 | attributeID: 1.3.6.1.4.1.11344.4.3.1.43 | |
648 | isSingleValued: FALSE | |
649 | cn: radiusTunnelClientEndpoint | |
650 | name: radiusTunnelClientEndpoint | |
651 | lDAPDisplayName: radiusTunnelClientEndpoint | |
652 | attributeSyntax: 2.5.5.5 | |
653 | oMSyntax: 22 | |
654 | ||
655 | dn: CN=radiusSimultaneousUse,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
656 | changetype: add | |
657 | objectClass: top | |
658 | objectClass: attributeSchema | |
659 | attributeID: 1.3.6.1.4.1.11344.4.3.1.53 | |
660 | isSingleValued: TRUE | |
661 | cn: radiusSimultaneousUse | |
662 | name: radiusSimultaneousUse | |
663 | lDAPDisplayName: radiusSimultaneousUse | |
664 | description: controlItem: Simultaneous-Use | |
665 | attributeSyntax: 2.5.5.9 | |
666 | oMSyntax: 10 | |
667 | ||
668 | dn: CN=radiusLoginTime,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
669 | changetype: add | |
670 | objectClass: top | |
671 | objectClass: attributeSchema | |
672 | attributeID: 1.3.6.1.4.1.11344.4.3.1.54 | |
673 | isSingleValued: TRUE | |
674 | cn: radiusLoginTime | |
675 | name: radiusLoginTime | |
676 | lDAPDisplayName: radiusLoginTime | |
677 | attributeSyntax: 2.5.5.5 | |
678 | oMSyntax: 22 | |
679 | ||
680 | dn: CN=radiusUserCategory,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
681 | changetype: add | |
682 | objectClass: top | |
683 | objectClass: attributeSchema | |
684 | attributeID: 1.3.6.1.4.1.11344.4.3.1.55 | |
685 | isSingleValued: TRUE | |
686 | cn: radiusUserCategory | |
687 | name: radiusUserCategory | |
688 | lDAPDisplayName: radiusUserCategory | |
689 | attributeSyntax: 2.5.5.5 | |
690 | oMSyntax: 22 | |
691 | ||
692 | dn: CN=radiusStripUserName,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
693 | changetype: add | |
694 | objectClass: top | |
695 | objectClass: attributeSchema | |
696 | attributeID: 1.3.6.1.4.1.11344.4.3.1.56 | |
697 | isSingleValued: TRUE | |
698 | cn: radiusStripUserName | |
699 | name: radiusStripUserName | |
700 | lDAPDisplayName: radiusStripUserName | |
701 | attributeSyntax: 2.5.5.8 | |
702 | oMSyntax: 1 | |
703 | ||
704 | dn: CN=dialupAccess,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
705 | changetype: add | |
706 | objectClass: top | |
707 | objectClass: attributeSchema | |
708 | attributeID: 1.3.6.1.4.1.11344.4.3.1.57 | |
709 | isSingleValued: TRUE | |
710 | cn: dialupAccess | |
711 | name: dialupAccess | |
712 | lDAPDisplayName: dialupAccess | |
713 | attributeSyntax: 2.5.5.5 | |
714 | oMSyntax: 22 | |
715 | ||
716 | dn: CN=radiusExpiration,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
717 | changetype: add | |
718 | objectClass: top | |
719 | objectClass: attributeSchema | |
720 | attributeID: 1.3.6.1.4.1.11344.4.3.1.58 | |
721 | isSingleValued: TRUE | |
722 | cn: radiusExpiration | |
723 | name: radiusExpiration | |
724 | lDAPDisplayName: radiusExpiration | |
725 | description: controlItem: Expiration | |
726 | attributeSyntax: 2.5.5.5 | |
727 | oMSyntax: 22 | |
728 | ||
729 | dn: CN=radiusAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
730 | changetype: add | |
731 | objectClass: top | |
732 | objectClass: attributeSchema | |
733 | attributeID: 1.3.6.1.4.1.11344.4.3.1.59 | |
734 | isSingleValued: FALSE | |
735 | cn: radiusAttribute | |
736 | name: radiusAttribute | |
737 | lDAPDisplayName: radiusAttribute | |
738 | description: controlItem: $GENERIC$ | |
739 | attributeSyntax: 2.5.5.5 | |
740 | oMSyntax: 22 | |
741 | ||
742 | dn: CN=radiusNASIpAddress,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
743 | changetype: add | |
744 | objectClass: top | |
745 | objectClass: attributeSchema | |
746 | attributeID: 1.3.6.1.4.1.11344.4.3.1.61 | |
747 | isSingleValued: TRUE | |
748 | cn: radiusNASIpAddress | |
749 | name: radiusNASIpAddress | |
750 | lDAPDisplayName: radiusNASIpAddress | |
751 | attributeSyntax: 2.5.5.5 | |
752 | oMSyntax: 22 | |
753 | ||
754 | dn: CN=radiusReplyMessage,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
755 | changetype: add | |
756 | objectClass: top | |
757 | objectClass: attributeSchema | |
758 | attributeID: 1.3.6.1.4.1.11344.4.3.1.62 | |
759 | isSingleValued: FALSE | |
760 | cn: radiusReplyMessage | |
761 | name: radiusReplyMessage | |
762 | lDAPDisplayName: radiusReplyMessage | |
763 | description: replyItem: Reply-Message | |
764 | attributeSyntax: 2.5.5.5 | |
765 | oMSyntax: 22 | |
766 | ||
767 | dn: CN=radiusControlAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
768 | changetype: add | |
769 | objectClass: top | |
770 | objectClass: attributeSchema | |
771 | attributeID: 1.3.6.1.4.1.11344.4.3.1.63 | |
772 | isSingleValued: FALSE | |
773 | cn: radiusControlAttribute | |
774 | name: radiusControlAttribute | |
775 | lDAPDisplayName: radiusControlAttribute | |
776 | description: controlItem: $GENERIC$ | |
777 | attributeSyntax: 2.5.5.5 | |
778 | oMSyntax: 22 | |
779 | ||
780 | dn: CN=radiusReplyAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
781 | changetype: add | |
782 | objectClass: top | |
783 | objectClass: attributeSchema | |
784 | attributeID: 1.3.6.1.4.1.11344.4.3.1.64 | |
785 | isSingleValued: FALSE | |
786 | cn: radiusReplyAttribute | |
787 | name: radiusReplyAttribute | |
788 | lDAPDisplayName: radiusReplyAttribute | |
789 | description: replyItem: $GENERIC$ | |
790 | attributeSyntax: 2.5.5.5 | |
791 | oMSyntax: 22 | |
792 | ||
793 | dn: CN=radiusRequestAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
794 | changetype: add | |
795 | objectClass: top | |
796 | objectClass: attributeSchema | |
797 | attributeID: 1.3.6.1.4.1.11344.4.3.1.65 | |
798 | isSingleValued: FALSE | |
799 | cn: radiusRequestAttribute | |
800 | name: radiusRequestAttribute | |
801 | lDAPDisplayName: radiusRequestAttribute | |
802 | description: requestItem: $GENERIC$ | |
803 | attributeSyntax: 2.5.5.5 | |
804 | oMSyntax: 22 | |
805 |
0 | dn: CN=radiusprofile,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
1 | changetype: add | |
2 | objectClass: top | |
3 | objectClass: classSchema | |
4 | governsID: 1.3.6.1.4.1.11344.4.3.2.1 | |
5 | cn: radiusprofile | |
6 | name: radiusprofile | |
7 | lDAPDisplayName: radiusprofile | |
8 | subClassOf: top | |
9 | objectClassCategory: 3 | |
10 | mayContain: radiusArapFeatures | |
11 | mayContain: radiusArapSecurity | |
12 | mayContain: radiusArapZoneAccess | |
13 | mayContain: radiusAuthType | |
14 | mayContain: radiusCallbackId | |
15 | mayContain: radiusCallbackNumber | |
16 | mayContain: radiusCalledStationId | |
17 | mayContain: radiusCallingStationId | |
18 | mayContain: radiusClass | |
19 | mayContain: radiusClientIPAddress | |
20 | mayContain: radiusFilterId | |
21 | mayContain: radiusFramedAppleTalkLink | |
22 | mayContain: radiusFramedAppleTalkNetwork | |
23 | mayContain: radiusFramedAppleTalkZone | |
24 | mayContain: radiusFramedCompression | |
25 | mayContain: radiusFramedIPAddress | |
26 | mayContain: radiusFramedIPNetmask | |
27 | mayContain: radiusFramedIPXNetwork | |
28 | mayContain: radiusFramedMTU | |
29 | mayContain: radiusFramedProtocol | |
30 | mayContain: radiusAttribute | |
31 | mayContain: radiusFramedRoute | |
32 | mayContain: radiusFramedRouting | |
33 | mayContain: radiusIdleTimeout | |
34 | mayContain: radiusGroupName | |
35 | mayContain: radiusHint | |
36 | mayContain: radiusHuntgroupName | |
37 | mayContain: radiusLoginIPHost | |
38 | mayContain: radiusLoginLATGroup | |
39 | mayContain: radiusLoginLATNode | |
40 | mayContain: radiusLoginLATPort | |
41 | mayContain: radiusLoginLATService | |
42 | mayContain: radiusLoginService | |
43 | mayContain: radiusLoginTCPPort | |
44 | mayContain: radiusLoginTime | |
45 | mayContain: radiusPasswordRetry | |
46 | mayContain: radiusPortLimit | |
47 | mayContain: radiusPrompt | |
48 | mayContain: radiusProxyToRealm | |
49 | mayContain: radiusRealm | |
50 | mayContain: radiusReplicateToRealm | |
51 | mayContain: radiusServiceType | |
52 | mayContain: radiusSessionTimeout | |
53 | mayContain: radiusStripUserName | |
54 | mayContain: radiusTerminationAction | |
55 | mayContain: radiusTunnelClientEndpoint | |
56 | mayContain: radiusProfileDN | |
57 | mayContain: radiusSimultaneousUse | |
58 | mayContain: radiusTunnelAssignmentId | |
59 | mayContain: radiusTunnelMediumType | |
60 | mayContain: radiusTunnelPassword | |
61 | mayContain: radiusTunnelPreference | |
62 | mayContain: radiusTunnelPrivateGroupId | |
63 | mayContain: radiusTunnelServerEndpoint | |
64 | mayContain: radiusTunnelType | |
65 | mayContain: radiusUserCategory | |
66 | mayContain: radiusVSA | |
67 | mayContain: radiusExpiration | |
68 | mayContain: dialupAccess | |
69 | mayContain: radiusNASIpAddress | |
70 | mayContain: radiusReplyMessage | |
71 | mayContain: radiusControlAttribute | |
72 | mayContain: radiusReplyAttribute | |
73 | mayContain: radiusRequestAttribute | |
74 | ||
75 | dn: CN=radiusObjectProfile,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
76 | changetype: add | |
77 | objectClass: top | |
78 | objectClass: classSchema | |
79 | governsID: 1.3.6.1.4.1.11344.4.3.2.2 | |
80 | cn: radiusObjectProfile | |
81 | name: radiusObjectProfile | |
82 | lDAPDisplayName: radiusObjectProfile | |
83 | description: A Container Objectclass to be used for creating radius profile object | |
84 | subClassOf: top | |
85 | objectClassCategory: 1 | |
86 | mustContain: cn | |
87 | mayContain: uid | |
88 | mayContain: userPassword | |
89 | mayContain: description | |
90 |
0 | dn: CN=radiusClientIdentifier,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
1 | changetype: add | |
2 | objectClass: top | |
3 | objectClass: attributeSchema | |
4 | attributeID: 1.3.6.1.4.1.11344.1.100.2.1 | |
5 | isSingleValued: TRUE | |
6 | cn: radiusClientIdentifier | |
7 | name: radiusClientIdentifier | |
8 | lDAPDisplayName: radiusClientIdentifier | |
9 | description: Client Identifier | |
10 | attributeSyntax: 2.5.5.3 | |
11 | oMSyntax: 27 | |
12 | ||
13 | dn: CN=radiusClientSecret,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
14 | changetype: add | |
15 | objectClass: top | |
16 | objectClass: attributeSchema | |
17 | attributeID: 1.3.6.1.4.1.11344.1.100.2.2 | |
18 | isSingleValued: TRUE | |
19 | cn: radiusClientSecret | |
20 | name: radiusClientSecret | |
21 | lDAPDisplayName: radiusClientSecret | |
22 | description: Client Secret | |
23 | attributeSyntax: 2.5.5.3 | |
24 | oMSyntax: 27 | |
25 | ||
26 | dn: CN=radiusClientShortname,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
27 | changetype: add | |
28 | objectClass: top | |
29 | objectClass: attributeSchema | |
30 | attributeID: 1.3.6.1.4.1.11344.1.100.2.3 | |
31 | isSingleValued: TRUE | |
32 | cn: radiusClientShortname | |
33 | name: radiusClientShortname | |
34 | lDAPDisplayName: radiusClientShortname | |
35 | description: Client Shortname | |
36 | attributeSyntax: 2.5.5.3 | |
37 | oMSyntax: 27 | |
38 | ||
39 | dn: CN=radiusClientVirtualServer,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
40 | changetype: add | |
41 | objectClass: top | |
42 | objectClass: attributeSchema | |
43 | attributeID: 1.3.6.1.4.1.11344.1.100.2.4 | |
44 | isSingleValued: TRUE | |
45 | cn: radiusClientVirtualServer | |
46 | name: radiusClientVirtualServer | |
47 | lDAPDisplayName: radiusClientVirtualServer | |
48 | description: VirtualServer | |
49 | attributeSyntax: 2.5.5.3 | |
50 | oMSyntax: 27 | |
51 | ||
52 | dn: CN=radiusClientType,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
53 | changetype: add | |
54 | objectClass: top | |
55 | objectClass: attributeSchema | |
56 | attributeID: 1.3.6.1.4.1.11344.1.100.2.5 | |
57 | isSingleValued: TRUE | |
58 | cn: radiusClientType | |
59 | name: radiusClientType | |
60 | lDAPDisplayName: radiusClientType | |
61 | description: Client Type | |
62 | attributeSyntax: 2.5.5.3 | |
63 | oMSyntax: 27 | |
64 | ||
65 | dn: CN=radiusClientRequireMa,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
66 | changetype: add | |
67 | objectClass: top | |
68 | objectClass: attributeSchema | |
69 | attributeID: 1.3.6.1.4.1.11344.1.100.2.6 | |
70 | isSingleValued: TRUE | |
71 | cn: radiusClientRequireMa | |
72 | name: radiusClientRequireMa | |
73 | lDAPDisplayName: radiusClientRequireMa | |
74 | description: Require Message Authenticator | |
75 | attributeSyntax: 2.5.5.8 | |
76 | oMSyntax: 1 | |
77 | ||
78 | dn: CN=radiusClientComment,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
79 | changetype: add | |
80 | objectClass: top | |
81 | objectClass: attributeSchema | |
82 | attributeID: 1.3.6.1.4.1.11344.1.100.2.7 | |
83 | isSingleValued: TRUE | |
84 | cn: radiusClientComment | |
85 | name: radiusClientComment | |
86 | lDAPDisplayName: radiusClientComment | |
87 | description: Client comment | |
88 | attributeSyntax: 2.5.5.3 | |
89 | oMSyntax: 27 | |
90 |
0 | dn: CN=radiusClient,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
1 | changetype: add | |
2 | objectClass: top | |
3 | objectClass: classSchema | |
4 | governsID: 1.3.6.1.4.1.11344.1.100.1.1 | |
5 | cn: radiusClient | |
6 | name: radiusClient | |
7 | lDAPDisplayName: radiusClient | |
8 | description: radiusClient object class | |
9 | subClassOf: top | |
10 | objectClassCategory: 1 | |
11 | mustContain: radiusClientIdentifier | |
12 | mustContain: radiusClientSecret | |
13 | mayContain: radiusClientShortname | |
14 | mayContain: radiusClientVirtualServer | |
15 | mayContain: radiusClientType | |
16 | mayContain: radiusClientRequireMa | |
17 | mayContain: radiusClientComment | |
18 |
0 | # Use this if you want to be able to apply radiusprofile | |
1 | # Auxiliary class directly to Users in the directory. | |
2 | # Install with: | |
3 | # ldbmodify -H /usr/local/samba/private/sam.ldb \ | |
4 | # user.ldif \ | |
5 | # --option="dsdb:schema update allowed"=true | |
6 | dn: CN=User,CN=Schema,CN=Configuration,dc=samba4,dc=internal | |
7 | changetype: modify | |
8 | add: auxiliaryClass | |
9 | auxiliaryClass: radiusprofile |
31 | 31 | CFLAGS="$CFLAGS_SAVED" |
32 | 32 | ]) |
33 | 33 | ]) |
34 | ||
35 | AC_DEFUN([AX_CC_NO_UNKNOWN_WARNING_OPTION_FLAG],[ | |
36 | AC_CACHE_CHECK([or the compiler flag "-Wno-unknown-warning-option"], [ax_cv_cc_no_unknown_warning_option_flag],[ | |
37 | ||
38 | CFLAGS_SAVED=$CFLAGS | |
39 | CFLAGS="-Werror -Wno-unknown-warning-option" | |
40 | ||
41 | AC_COMPILE_IFELSE( | |
42 | [AC_LANG_PROGRAM([], [[ | |
43 | /* | |
44 | * gcc will happily accept -Wno-unknown-warning-option | |
45 | * only emitting an error about it, if an error ocurrs in the source file. | |
46 | */ | |
47 | #if defined(__GNUC__) && !defined(__clang__) | |
48 | gcc sucks | |
49 | #endif | |
50 | ||
51 | return 0; | |
52 | ]])], | |
53 | [ax_cv_cc_no_unknown_warning_option_flag=yes], | |
54 | [ax_cv_cc_no_unknown_warning_option_flag=no]) | |
55 | ||
56 | CFLAGS="$CFLAGS_SAVED" | |
57 | ]) | |
58 | ]) | |
59 | ||
60 | ||
34 | 61 | |
35 | 62 | AC_DEFUN([AX_CC_WEVERYTHING_FLAG],[ |
36 | 63 | AC_CACHE_CHECK([for the compiler flag "-Weverything"], [ax_cv_cc_weverything_flag],[ |
47 | 47 | .br |
48 | 48 | ------ --------- ----------- |
49 | 49 | .br |
50 | {clear} Cleartext-Password clear-text passwords | |
50 | {clear} Cleartext-Password Clear-text passwords | |
51 | 51 | .br |
52 | {cleartext} Cleartext-Password clear-text passwords | |
52 | {cleartext} Cleartext-Password Clear-text passwords | |
53 | 53 | .br |
54 | 54 | {crypt} Crypt-Password Unix-style "crypt"ed passwords |
55 | 55 | .br |
65 | 65 | .br |
66 | 66 | {ssha} SSHA-Password SHA1 hashed passwords, with a salt |
67 | 67 | .br |
68 | SSHA1-Password SHA1 hashed passwords, with a salt | |
68 | {sha2} SHA2-Password SHA2 hashed passwords | |
69 | 69 | .br |
70 | {ssh2} SHA2-Password SHA2 hashed passwords | |
70 | {sha224} SHA2-Password SHA2 hashed passwords | |
71 | 71 | .br |
72 | {ssh256} SHA2-Password SHA2 hashed passwords | |
72 | {sha256} SHA2-Password SHA2 hashed passwords | |
73 | 73 | .br |
74 | {ssh512} SHA2-Password SHA2 hashed passwords | |
74 | {sha384} SHA2-Password SHA2 hashed passwords | |
75 | .br | |
76 | {sha512} SHA2-Password SHA2 hashed passwords | |
77 | .br | |
78 | {ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt | |
79 | .br | |
80 | {ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt | |
81 | .br | |
82 | {ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt | |
83 | .br | |
84 | {ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt | |
75 | 85 | .br |
76 | 86 | {nt} NT-Password Windows NT hashed passwords |
77 | 87 | .br |
78 | 88 | {nthash} NT-Password Windows NT hashed passwords |
89 | .br | |
90 | {md4} NT-Password Windows NT hashed passwords | |
79 | 91 | .br |
80 | 92 | {x-nthash} NT-Password Windows NT hashed passwords |
81 | 93 | .br |
83 | 95 | .br |
84 | 96 | {x- orcllmv} LM-Password Windows LANMAN hashed passwords |
85 | 97 | .br |
86 | {X- orclntv} LM-Password Windows LANMAN hashed passwords | |
98 | {X- orclntv} NT-Password Windows NT hashed passwords | |
87 | 99 | .DE |
88 | 100 | |
89 | 101 | The module tries to be flexible when handling the various password |
9 | 9 | .RE |
10 | 10 | .sp |
11 | 11 | .. |
12 | .TH unlang 5 "02 January 2016" "" "FreeRADIUS Processing un-language" | |
12 | .TH unlang 5 "06 December 2017" "" "FreeRADIUS Processing un-language" | |
13 | 13 | .SH NAME |
14 | 14 | unlang \- FreeRADIUS Processing un\-language |
15 | 15 | .SH DESCRIPTION |
164 | 164 | .br |
165 | 165 | } |
166 | 166 | .DE |
167 | ||
168 | 167 | A default entry can be defined by omitting the argument, as given |
169 | 168 | below. This entry will be used if no other "case" entry matches. |
170 | 169 | Only one default entry can exist in a "switch" section. |
190 | 189 | .br |
191 | 190 | } |
192 | 191 | .DE |
193 | ||
194 | 192 | The <list> can be one of "request", "reply", "proxy-request", |
195 | 193 | "proxy-reply", "coa", "disconnect", "session-state", or "control". As |
196 | 194 | of Version 3, the <list> can be omitted, in which case "request" is |
271 | 269 | .br |
272 | 270 | } |
273 | 271 | .DE |
274 | ||
275 | 272 | In general, we recommend using "redundant-load-balance" instead of |
276 | 273 | "load-balance". |
277 | 274 | .IP redundant-load-balance |
301 | 298 | .br |
302 | 299 | } |
303 | 300 | .DE |
304 | ||
305 | 301 | .IP return |
306 | 302 | .br |
307 | 303 | Returns from the current top-level section, e.g. "authorize" or |
396 | 392 | .DS |
397 | 393 | (foo) |
398 | 394 | .DE |
399 | ||
400 | 395 | Evalutes to true if 'foo' is a non-empty string (single quotes, double |
401 | 396 | quotes, or back-quoted). Also evaluates to true if 'foo' is a |
402 | 397 | non-zero number. Note that the language is poorly typed, so the |
418 | 413 | .DS |
419 | 414 | (!foo) |
420 | 415 | .DE |
421 | ||
422 | 416 | Evalutes to true if 'foo' evaluates to false, and vice-versa. |
423 | 417 | .PP |
424 | 418 | Short-circuit operators |
429 | 423 | .br |
430 | 424 | (foo && bar) |
431 | 425 | .DE |
432 | ||
433 | 426 | "&&" and "||" are short-circuit operators. "&&" evaluates the first |
434 | 427 | condition, and evaluates the second condition if and only if the |
435 | 428 | result of the first condition is true. "||" is similar, but executes |
440 | 433 | .DS |
441 | 434 | (foo == bar) |
442 | 435 | .DE |
443 | ||
444 | 436 | Compares 'foo' to 'bar', and evaluates to true if the comparison holds |
445 | 437 | true. Valid comparison operators are "==", "!=", "<", "<=", ">", |
446 | ">=", "=~", and "!~", all with their usual meanings. Invalid | |
447 | comparison operators are ":=" and "=". | |
438 | ">=", "=~", and "!~", all with their usual meanings. The operators | |
439 | ":=" and "=" are assignment operators, and are not allowed for | |
440 | comparisons. | |
441 | ||
442 | The operators "<", "<=", ">", and ">=" are also allowed for checking | |
443 | that an IP address is contained within a network. For example: | |
444 | .DS | |
445 | if (<ipaddr>192.0.2.1 < 192.0.2.0/24) { | |
446 | .DE | |
447 | This comparison succeeds, because the address 192.0.2.1 is contained | |
448 | within the network 192.0.2.0/24. | |
448 | 449 | .RE |
449 | 450 | .IP "Attribute Comparisons" |
451 | When doing attribute comparisons, the data type of the attribute is | |
452 | used to determine the data type of the right-hand side argument. | |
450 | 453 | .DS |
451 | 454 | (&User-Name == "foo") |
452 | 455 | .DE |
453 | ||
454 | 456 | Compares the value of the User-Name attribute to the string 'foo', and |
455 | evaluates to true if the comparison holds true. The comparison is | |
456 | done by printing the attribute to a string, and then doing a string | |
457 | comparison of the two sides of the condition. | |
457 | evaluates to true if the comparison holds true. | |
458 | ||
459 | Similarly, | |
460 | .DS | |
461 | (&Framed-IP-Address == 192.0.2.1) | |
462 | .DE | |
463 | Compares the value of the Framed-IP-Address attribute to the IP | |
464 | address 192.0.2.1. This IP address does not need to be quoted. | |
458 | 465 | .RE |
459 | 466 | .IP "Inter-Attribute Comparisons" |
460 | 467 | .DS |
461 | 468 | (&User-Name == &Filter-Id) |
462 | 469 | .DE |
463 | ||
464 | 470 | Compares the value of the User-Name attribute to the contents of the |
465 | 471 | Filter-Id attribute, and evaluates to true if the comparison holds |
466 | 472 | true. Unlike the previous example, this comparison is done in a |
487 | 493 | .DS |
488 | 494 | (&Attribute-Name[*] == "foo") |
489 | 495 | .DE |
490 | ||
491 | 496 | Using the "[*]" syntax means that it checks all of the instances of |
492 | 497 | the named attribute. If one attribute matches, the condition |
493 | 498 | succeeds. If none match, the condition fails. |
497 | 502 | .DS |
498 | 503 | (<type>foo == bar) |
499 | 504 | .DE |
500 | ||
501 | 505 | The left-hand-side of a condition can be "cast" to a specific data |
502 | 506 | type. The data type must be one which is valid for the dictionaries. |
503 | 507 | e.g. "integer", "ipaddr", etc. |
0 | 0 | #! /bin/sh |
1 | # Common stub for a few missing GNU programs while installing. | |
2 | # Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. | |
3 | # Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. | |
1 | # Common wrapper for a few potentially missing GNU programs. | |
2 | ||
3 | scriptversion=2013-10-28.13; # UTC | |
4 | ||
5 | # Copyright (C) 1996-2013 Free Software Foundation, Inc. | |
6 | # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. | |
4 | 7 | |
5 | 8 | # This program is free software; you can redistribute it and/or modify |
6 | 9 | # it under the terms of the GNU General Public License as published by |
13 | 16 | # GNU General Public License for more details. |
14 | 17 | |
15 | 18 | # You should have received a copy of the GNU General Public License |
16 | # along with this program; if not, write to the Free Software | |
17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
18 | # 02111-1307, USA. | |
19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | 20 | |
20 | 21 | # As a special exception to the GNU General Public License, if you |
21 | 22 | # distribute this file as part of a program that contains a |
23 | 24 | # the same distribution terms that you use for the rest of that program. |
24 | 25 | |
25 | 26 | if test $# -eq 0; then |
26 | echo 1>&2 "Try \`$0 --help' for more information" | |
27 | echo 1>&2 "Try '$0 --help' for more information" | |
27 | 28 | exit 1 |
28 | 29 | fi |
29 | 30 | |
30 | run=: | |
31 | ||
32 | # In the cases where this matters, `missing' is being run in the | |
33 | # srcdir already. | |
34 | if test -f configure.ac; then | |
35 | configure_ac=configure.ac | |
36 | else | |
37 | configure_ac=configure.ac | |
38 | fi | |
39 | ||
40 | case "$1" in | |
41 | --run) | |
42 | # Try to run requested program, and just exit if it succeeds. | |
43 | run= | |
44 | shift | |
45 | "$@" && exit 0 | |
46 | ;; | |
47 | esac | |
48 | ||
49 | # If it does not exist, or fails to run (possibly an outdated version), | |
50 | # try to emulate it. | |
51 | case "$1" in | |
31 | case $1 in | |
32 | ||
33 | --is-lightweight) | |
34 | # Used by our autoconf macros to check whether the available missing | |
35 | # script is modern enough. | |
36 | exit 0 | |
37 | ;; | |
38 | ||
39 | --run) | |
40 | # Back-compat with the calling convention used by older automake. | |
41 | shift | |
42 | ;; | |
52 | 43 | |
53 | 44 | -h|--h|--he|--hel|--help) |
54 | 45 | echo "\ |
55 | 46 | $0 [OPTION]... PROGRAM [ARGUMENT]... |
56 | 47 | |
57 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an | |
58 | error status if there is no known handling for PROGRAM. | |
48 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due | |
49 | to PROGRAM being missing or too old. | |
59 | 50 | |
60 | 51 | Options: |
61 | 52 | -h, --help display this help and exit |
62 | 53 | -v, --version output version information and exit |
63 | --run try to run the given command, and emulate it if it fails | |
64 | 54 | |
65 | 55 | Supported PROGRAM values: |
66 | aclocal touch file \`aclocal.m4' | |
67 | autoconf touch file \`configure' | |
68 | autoheader touch file \`config.h.in' | |
69 | automake touch all \`Makefile.in' files | |
70 | bison create \`y.tab.[ch]', if possible, from existing .[ch] | |
71 | flex create \`lex.yy.c', if possible, from existing .c | |
72 | help2man touch the output file | |
73 | lex create \`lex.yy.c', if possible, from existing .c | |
74 | makeinfo touch the output file | |
75 | tar try tar, gnutar, gtar, then tar without non-portable flags | |
76 | yacc create \`y.tab.[ch]', if possible, from existing .[ch]" | |
56 | aclocal autoconf autoheader autom4te automake makeinfo | |
57 | bison yacc flex lex help2man | |
58 | ||
59 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and | |
60 | 'g' are ignored when checking the name. | |
61 | ||
62 | Send bug reports to <bug-automake@gnu.org>." | |
63 | exit $? | |
77 | 64 | ;; |
78 | 65 | |
79 | 66 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) |
80 | echo "missing 0.4 - GNU automake" | |
67 | echo "missing $scriptversion (GNU Automake)" | |
68 | exit $? | |
81 | 69 | ;; |
82 | 70 | |
83 | 71 | -*) |
84 | echo 1>&2 "$0: Unknown \`$1' option" | |
85 | echo 1>&2 "Try \`$0 --help' for more information" | |
72 | echo 1>&2 "$0: unknown '$1' option" | |
73 | echo 1>&2 "Try '$0 --help' for more information" | |
86 | 74 | exit 1 |
87 | 75 | ;; |
88 | 76 | |
89 | aclocal*) | |
90 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |
91 | # We have it, but it failed. | |
92 | exit 1 | |
93 | fi | |
94 | ||
95 | echo 1>&2 "\ | |
96 | WARNING: \`$1' is missing on your system. You should only need it if | |
97 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want | |
98 | to install the \`Automake' and \`Perl' packages. Grab them from | |
99 | any GNU archive site." | |
100 | touch aclocal.m4 | |
101 | ;; | |
102 | ||
103 | autoconf) | |
104 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |
105 | # We have it, but it failed. | |
106 | exit 1 | |
107 | fi | |
108 | ||
109 | echo 1>&2 "\ | |
110 | WARNING: \`$1' is missing on your system. You should only need it if | |
111 | you modified \`${configure_ac}'. You might want to install the | |
112 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU | |
113 | archive site." | |
114 | touch configure | |
115 | ;; | |
116 | ||
117 | autoheader) | |
118 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |
119 | # We have it, but it failed. | |
120 | exit 1 | |
121 | fi | |
122 | ||
123 | echo 1>&2 "\ | |
124 | WARNING: \`$1' is missing on your system. You should only need it if | |
125 | you modified \`acconfig.h' or \`${configure_ac}'. You might want | |
126 | to install the \`Autoconf' and \`GNU m4' packages. Grab them | |
127 | from any GNU archive site." | |
128 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` | |
129 | test -z "$files" && files="config.h" | |
130 | touch_files= | |
131 | for f in $files; do | |
132 | case "$f" in | |
133 | *:*) touch_files="$touch_files "`echo "$f" | | |
134 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; | |
135 | *) touch_files="$touch_files $f.in";; | |
136 | esac | |
137 | done | |
138 | touch $touch_files | |
139 | ;; | |
140 | ||
141 | automake*) | |
142 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |
143 | # We have it, but it failed. | |
144 | exit 1 | |
145 | fi | |
146 | ||
147 | echo 1>&2 "\ | |
148 | WARNING: \`$1' is missing on your system. You should only need it if | |
149 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. | |
150 | You might want to install the \`Automake' and \`Perl' packages. | |
151 | Grab them from any GNU archive site." | |
152 | find . -type f -name Makefile.am -print | | |
153 | sed 's/\.am$/.in/' | | |
154 | while read f; do touch "$f"; done | |
155 | ;; | |
156 | ||
157 | autom4te) | |
158 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |
159 | # We have it, but it failed. | |
160 | exit 1 | |
161 | fi | |
162 | ||
163 | echo 1>&2 "\ | |
164 | WARNING: \`$1' is needed, and you do not seem to have it handy on your | |
165 | system. You might have modified some files without having the | |
166 | proper tools for further handling them. | |
167 | You can get \`$1Help2man' as part of \`Autoconf' from any GNU | |
168 | archive site." | |
169 | ||
170 | file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` | |
171 | test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` | |
172 | if test -f "$file"; then | |
173 | touch $file | |
174 | else | |
175 | test -z "$file" || exec >$file | |
176 | echo "#! /bin/sh" | |
177 | echo "# Created by GNU Automake missing as a replacement of" | |
178 | echo "# $ $@" | |
179 | echo "exit 0" | |
180 | chmod +x $file | |
181 | exit 1 | |
182 | fi | |
183 | ;; | |
184 | ||
185 | bison|yacc) | |
186 | echo 1>&2 "\ | |
187 | WARNING: \`$1' is missing on your system. You should only need it if | |
188 | you modified a \`.y' file. You may need the \`Bison' package | |
189 | in order for those modifications to take effect. You can get | |
190 | \`Bison' from any GNU archive site." | |
191 | rm -f y.tab.c y.tab.h | |
192 | if [ $# -ne 1 ]; then | |
193 | eval LASTARG="\${$#}" | |
194 | case "$LASTARG" in | |
195 | *.y) | |
196 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` | |
197 | if [ -f "$SRCFILE" ]; then | |
198 | cp "$SRCFILE" y.tab.c | |
199 | fi | |
200 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` | |
201 | if [ -f "$SRCFILE" ]; then | |
202 | cp "$SRCFILE" y.tab.h | |
203 | fi | |
204 | ;; | |
205 | esac | |
206 | fi | |
207 | if [ ! -f y.tab.h ]; then | |
208 | echo >y.tab.h | |
209 | fi | |
210 | if [ ! -f y.tab.c ]; then | |
211 | echo 'main() { return 0; }' >y.tab.c | |
212 | fi | |
213 | ;; | |
214 | ||
215 | lex|flex) | |
216 | echo 1>&2 "\ | |
217 | WARNING: \`$1' is missing on your system. You should only need it if | |
218 | you modified a \`.l' file. You may need the \`Flex' package | |
219 | in order for those modifications to take effect. You can get | |
220 | \`Flex' from any GNU archive site." | |
221 | rm -f lex.yy.c | |
222 | if [ $# -ne 1 ]; then | |
223 | eval LASTARG="\${$#}" | |
224 | case "$LASTARG" in | |
225 | *.l) | |
226 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` | |
227 | if [ -f "$SRCFILE" ]; then | |
228 | cp "$SRCFILE" lex.yy.c | |
229 | fi | |
230 | ;; | |
231 | esac | |
232 | fi | |
233 | if [ ! -f lex.yy.c ]; then | |
234 | echo 'main() { return 0; }' >lex.yy.c | |
235 | fi | |
236 | ;; | |
237 | ||
238 | help2man) | |
239 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |
240 | # We have it, but it failed. | |
241 | exit 1 | |
242 | fi | |
243 | ||
244 | echo 1>&2 "\ | |
245 | WARNING: \`$1' is missing on your system. You should only need it if | |
246 | you modified a dependency of a manual page. You may need the | |
247 | \`Help2man' package in order for those modifications to take | |
248 | effect. You can get \`Help2man' from any GNU archive site." | |
249 | ||
250 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` | |
251 | if test -z "$file"; then | |
252 | file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` | |
253 | fi | |
254 | if [ -f "$file" ]; then | |
255 | touch $file | |
256 | else | |
257 | test -z "$file" || exec >$file | |
258 | echo ".ab help2man is required to generate this page" | |
259 | exit 1 | |
260 | fi | |
261 | ;; | |
262 | ||
263 | makeinfo) | |
264 | if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then | |
265 | # We have makeinfo, but it failed. | |
266 | exit 1 | |
267 | fi | |
268 | ||
269 | echo 1>&2 "\ | |
270 | WARNING: \`$1' is missing on your system. You should only need it if | |
271 | you modified a \`.texi' or \`.texinfo' file, or any other file | |
272 | indirectly affecting the aspect of the manual. The spurious | |
273 | call might also be the consequence of using a buggy \`make' (AIX, | |
274 | DU, IRIX). You might want to install the \`Texinfo' package or | |
275 | the \`GNU make' package. Grab either from any GNU archive site." | |
276 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` | |
277 | if test -z "$file"; then | |
278 | file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` | |
279 | file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` | |
280 | fi | |
281 | touch $file | |
282 | ;; | |
283 | ||
284 | tar) | |
285 | shift | |
286 | if test -n "$run"; then | |
287 | echo 1>&2 "ERROR: \`tar' requires --run" | |
288 | exit 1 | |
289 | fi | |
290 | ||
291 | # We have already tried tar in the generic part. | |
292 | # Look for gnutar/gtar before invocation to avoid ugly error | |
293 | # messages. | |
294 | if (gnutar --version > /dev/null 2>&1); then | |
295 | gnutar "$@" && exit 0 | |
296 | fi | |
297 | if (gtar --version > /dev/null 2>&1); then | |
298 | gtar "$@" && exit 0 | |
299 | fi | |
300 | firstarg="$1" | |
301 | if shift; then | |
302 | case "$firstarg" in | |
303 | *o*) | |
304 | firstarg=`echo "$firstarg" | sed s/o//` | |
305 | tar "$firstarg" "$@" && exit 0 | |
306 | ;; | |
307 | esac | |
308 | case "$firstarg" in | |
309 | *h*) | |
310 | firstarg=`echo "$firstarg" | sed s/h//` | |
311 | tar "$firstarg" "$@" && exit 0 | |
312 | ;; | |
313 | esac | |
314 | fi | |
315 | ||
316 | echo 1>&2 "\ | |
317 | WARNING: I can't seem to be able to run \`tar' with the given arguments. | |
318 | You may want to install GNU tar or Free paxutils, or check the | |
319 | command line arguments." | |
320 | exit 1 | |
321 | ;; | |
322 | ||
323 | *) | |
324 | echo 1>&2 "\ | |
325 | WARNING: \`$1' is needed, and you do not seem to have it handy on your | |
326 | system. You might have modified some files without having the | |
327 | proper tools for further handling them. Check the \`README' file, | |
328 | it often tells you about the needed prerequirements for installing | |
329 | this package. You may also peek at any GNU archive site, in case | |
330 | some other package would contain this missing \`$1' program." | |
331 | exit 1 | |
332 | ;; | |
333 | 77 | esac |
334 | 78 | |
335 | exit 0 | |
79 | # Run the given program, remember its exit status. | |
80 | "$@"; st=$? | |
81 | ||
82 | # If it succeeded, we are done. | |
83 | test $st -eq 0 && exit 0 | |
84 | ||
85 | # Also exit now if we it failed (or wasn't found), and '--version' was | |
86 | # passed; such an option is passed most likely to detect whether the | |
87 | # program is present and works. | |
88 | case $2 in --version|--help) exit $st;; esac | |
89 | ||
90 | # Exit code 63 means version mismatch. This often happens when the user | |
91 | # tries to use an ancient version of a tool on a file that requires a | |
92 | # minimum version. | |
93 | if test $st -eq 63; then | |
94 | msg="probably too old" | |
95 | elif test $st -eq 127; then | |
96 | # Program was missing. | |
97 | msg="missing on your system" | |
98 | else | |
99 | # Program was found and executed, but failed. Give up. | |
100 | exit $st | |
101 | fi | |
102 | ||
103 | perl_URL=http://www.perl.org/ | |
104 | flex_URL=http://flex.sourceforge.net/ | |
105 | gnu_software_URL=http://www.gnu.org/software | |
106 | ||
107 | program_details () | |
108 | { | |
109 | case $1 in | |
110 | aclocal|automake) | |
111 | echo "The '$1' program is part of the GNU Automake package:" | |
112 | echo "<$gnu_software_URL/automake>" | |
113 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" | |
114 | echo "<$gnu_software_URL/autoconf>" | |
115 | echo "<$gnu_software_URL/m4/>" | |
116 | echo "<$perl_URL>" | |
117 | ;; | |
118 | autoconf|autom4te|autoheader) | |
119 | echo "The '$1' program is part of the GNU Autoconf package:" | |
120 | echo "<$gnu_software_URL/autoconf/>" | |
121 | echo "It also requires GNU m4 and Perl in order to run:" | |
122 | echo "<$gnu_software_URL/m4/>" | |
123 | echo "<$perl_URL>" | |
124 | ;; | |
125 | esac | |
126 | } | |
127 | ||
128 | give_advice () | |
129 | { | |
130 | # Normalize program name to check for. | |
131 | normalized_program=`echo "$1" | sed ' | |
132 | s/^gnu-//; t | |
133 | s/^gnu//; t | |
134 | s/^g//; t'` | |
135 | ||
136 | printf '%s\n' "'$1' is $msg." | |
137 | ||
138 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" | |
139 | case $normalized_program in | |
140 | autoconf*) | |
141 | echo "You should only need it if you modified 'configure.ac'," | |
142 | echo "or m4 files included by it." | |
143 | program_details 'autoconf' | |
144 | ;; | |
145 | autoheader*) | |
146 | echo "You should only need it if you modified 'acconfig.h' or" | |
147 | echo "$configure_deps." | |
148 | program_details 'autoheader' | |
149 | ;; | |
150 | automake*) | |
151 | echo "You should only need it if you modified 'Makefile.am' or" | |
152 | echo "$configure_deps." | |
153 | program_details 'automake' | |
154 | ;; | |
155 | aclocal*) | |
156 | echo "You should only need it if you modified 'acinclude.m4' or" | |
157 | echo "$configure_deps." | |
158 | program_details 'aclocal' | |
159 | ;; | |
160 | autom4te*) | |
161 | echo "You might have modified some maintainer files that require" | |
162 | echo "the 'autom4te' program to be rebuilt." | |
163 | program_details 'autom4te' | |
164 | ;; | |
165 | bison*|yacc*) | |
166 | echo "You should only need it if you modified a '.y' file." | |
167 | echo "You may want to install the GNU Bison package:" | |
168 | echo "<$gnu_software_URL/bison/>" | |
169 | ;; | |
170 | lex*|flex*) | |
171 | echo "You should only need it if you modified a '.l' file." | |
172 | echo "You may want to install the Fast Lexical Analyzer package:" | |
173 | echo "<$flex_URL>" | |
174 | ;; | |
175 | help2man*) | |
176 | echo "You should only need it if you modified a dependency" \ | |
177 | "of a man page." | |
178 | echo "You may want to install the GNU Help2man package:" | |
179 | echo "<$gnu_software_URL/help2man/>" | |
180 | ;; | |
181 | makeinfo*) | |
182 | echo "You should only need it if you modified a '.texi' file, or" | |
183 | echo "any other file indirectly affecting the aspect of the manual." | |
184 | echo "You might want to install the Texinfo package:" | |
185 | echo "<$gnu_software_URL/texinfo/>" | |
186 | echo "The spurious makeinfo call might also be the consequence of" | |
187 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" | |
188 | echo "want to install GNU make:" | |
189 | echo "<$gnu_software_URL/make/>" | |
190 | ;; | |
191 | *) | |
192 | echo "You might have modified some files without having the proper" | |
193 | echo "tools for further handling them. Check the 'README' file, it" | |
194 | echo "often tells you about the needed prerequisites for installing" | |
195 | echo "this package. You may also peek at any GNU archive site, in" | |
196 | echo "case some other package contains this missing '$1' program." | |
197 | ;; | |
198 | esac | |
199 | } | |
200 | ||
201 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ | |
202 | -e '2,$s/^/ /' >&2 | |
203 | ||
204 | # Propagate the correct exit status (expected to be 127 for a program | |
205 | # not found, 63 for a program that failed due to version mismatch). | |
206 | exit $st | |
207 | ||
208 | # Local variables: | |
209 | # eval: (add-hook 'write-file-hooks 'time-stamp) | |
210 | # time-stamp-start: "scriptversion=" | |
211 | # time-stamp-format: "%:y-%02m-%02d.%02H" | |
212 | # time-stamp-time-zone: "UTC" | |
213 | # time-stamp-end: "; # UTC" | |
214 | # End: |
7 | 7 | LOCAL_SITES := $(addprefix raddb/sites-enabled/,$(DEFAULT_SITES)) |
8 | 8 | |
9 | 9 | DEFAULT_MODULES := always attr_filter cache_eap chap date \ |
10 | detail detail.log digest dhcp dynamic_clients eap \ | |
10 | detail detail.log digest dynamic_clients eap \ | |
11 | 11 | echo exec expiration expr files linelog logintime \ |
12 | 12 | mschap ntlm_auth pap passwd preprocess radutmp realm \ |
13 | 13 | replicate soh sradutmp unix unpack utf8 |
15 | 15 | LOCAL_MODULES := $(addprefix raddb/mods-enabled/,$(DEFAULT_MODULES)) |
16 | 16 | |
17 | 17 | LOCAL_CERT_FILES := Makefile README xpextensions \ |
18 | ca.cnf server.cnf client.cnf bootstrap | |
18 | ca.cnf server.cnf inner-server.cnf \ | |
19 | client.cnf bootstrap | |
19 | 20 | |
20 | 21 | # |
21 | 22 | # We don't create the installed certs if we're building a package, |
10 | 10 | |
11 | 11 | DH_KEY_SIZE = 2048 |
12 | 12 | OPENSSL = openssl |
13 | EXTERNAL_CA = $(wildcard external_ca.*) | |
14 | ||
15 | ifneq "$(EXTERNAL_CA)" "" | |
16 | PARTIAL = -partial_chain | |
17 | endif | |
13 | 18 | |
14 | 19 | # |
15 | 20 | # Set the passwords |
16 | 21 | # |
17 | -include passwords.mk | |
22 | include passwords.mk | |
18 | 23 | |
19 | 24 | ###################################################################### |
20 | 25 | # |
33 | 38 | .PHONY: server |
34 | 39 | server: server.pem server.vrfy |
35 | 40 | |
41 | .PHONY: inner-server | |
42 | inner-server: inner-server.pem inner-server.vrfy | |
43 | ||
36 | 44 | .PHONY: verify |
37 | 45 | verify: server.vrfy client.vrfy |
38 | 46 | |
39 | passwords.mk: server.cnf ca.cnf client.cnf | |
47 | passwords.mk: server.cnf ca.cnf client.cnf inner-server.cnf | |
40 | 48 | @echo "PASSWORD_SERVER = '$(shell grep output_password server.cnf | sed 's/.*=//;s/^ *//')'" > $@ |
49 | @echo "PASSWORD_INNER = '$(shell grep output_password inner-server.cnf | sed 's/.*=//;s/^ *//')'" >> $@ | |
41 | 50 | @echo "PASSWORD_CA = '$(shell grep output_password ca.cnf | sed 's/.*=//;s/^ *//')'" >> $@ |
42 | 51 | @echo "PASSWORD_CLIENT = '$(shell grep output_password client.cnf | sed 's/.*=//;s/^ *//')'" >> $@ |
43 | 52 | @echo "USER_NAME = '$(shell grep emailAddress client.cnf | grep '@' | sed 's/.*=//;s/^ *//')'" >> $@ |
88 | 97 | |
89 | 98 | .PHONY: server.vrfy |
90 | 99 | server.vrfy: ca.pem |
91 | @$(OPENSSL) verify -CAfile ca.pem server.pem | |
100 | @$(OPENSSL) verify $(PARTIAL) -CAfile ca.pem server.pem | |
92 | 101 | |
93 | 102 | ###################################################################### |
94 | 103 | # |
119 | 128 | |
120 | 129 | ###################################################################### |
121 | 130 | # |
131 | # Create a new inner-server certificate, signed by the above CA. | |
132 | # | |
133 | ###################################################################### | |
134 | inner-server.csr inner-server.key: inner-server.cnf | |
135 | $(OPENSSL) req -new -out inner-server.csr -keyout inner-server.key -config ./inner-server.cnf | |
136 | chmod g+r inner-server.key | |
137 | ||
138 | inner-server.crt: inner-server.csr ca.key ca.pem | |
139 | $(OPENSSL) ca -batch -keyfile ca.key -cert ca.pem -in inner-server.csr -key $(PASSWORD_CA) -out inner-server.crt -extensions xpserver_ext -extfile xpextensions -config ./inner-server.cnf | |
140 | ||
141 | inner-server.p12: inner-server.crt | |
142 | $(OPENSSL) pkcs12 -export -in inner-server.crt -inkey inner-server.key -out inner-server.p12 -passin pass:$(PASSWORD_INNER) -passout pass:$(PASSWORD_INNER) | |
143 | chmod g+r inner-server.p12 | |
144 | ||
145 | inner-server.pem: inner-server.p12 | |
146 | $(OPENSSL) pkcs12 -in inner-server.p12 -out inner-server.pem -passin pass:$(PASSWORD_INNER) -passout pass:$(PASSWORD_INNER) | |
147 | chmod g+r inner-server.pem | |
148 | ||
149 | .PHONY: inner-server.vrfy | |
150 | inner-server.vrfy: ca.pem | |
151 | @$(OPENSSL) verify $(PARTIAL) -CAfile ca.pem inner-server.pem | |
152 | ||
153 | ###################################################################### | |
154 | # | |
122 | 155 | # Miscellaneous rules. |
123 | 156 | # |
124 | 157 | ###################################################################### |
93 | 93 | MAKING A SERVER CERTIFICATE |
94 | 94 | |
95 | 95 | |
96 | The following steps will let you create a server certificate for use | |
97 | with TLS-based EAP methods, such as EAP-TLS, PEAP, and TTLS. Follow | |
98 | similar steps to create an "inner-server.pem" file, for use with | |
99 | EAP-TLS that is tunneled inside of another TLS-based EAP method. | |
100 | ||
96 | 101 | $ vi server.cnf |
97 | 102 | |
98 | 103 | Edit the "input_password" and "output_password" fields to be the |
114 | 119 | |
115 | 120 | You will have to ensure that the certificate contains the XP |
116 | 121 | extensions needed by Microsoft clients. |
122 | ||
117 | 123 | |
118 | 124 | |
119 | 125 | MAKING A CLIENT CERTIFICATE |
0 | [ ca ] | |
1 | default_ca = CA_default | |
2 | ||
3 | [ CA_default ] | |
4 | dir = ./ | |
5 | certs = $dir | |
6 | crl_dir = $dir/crl | |
7 | database = $dir/index.txt | |
8 | new_certs_dir = $dir | |
9 | certificate = $dir/server.pem | |
10 | serial = $dir/serial | |
11 | crl = $dir/crl.pem | |
12 | private_key = $dir/server.key | |
13 | RANDFILE = $dir/.rand | |
14 | name_opt = ca_default | |
15 | cert_opt = ca_default | |
16 | default_days = 60 | |
17 | default_crl_days = 30 | |
18 | default_md = sha256 | |
19 | preserve = no | |
20 | policy = policy_match | |
21 | ||
22 | [ policy_match ] | |
23 | countryName = match | |
24 | stateOrProvinceName = match | |
25 | organizationName = match | |
26 | organizationalUnitName = optional | |
27 | commonName = supplied | |
28 | emailAddress = optional | |
29 | ||
30 | [ policy_anything ] | |
31 | countryName = optional | |
32 | stateOrProvinceName = optional | |
33 | localityName = optional | |
34 | organizationName = optional | |
35 | organizationalUnitName = optional | |
36 | commonName = supplied | |
37 | emailAddress = optional | |
38 | ||
39 | [ req ] | |
40 | prompt = no | |
41 | distinguished_name = server | |
42 | default_bits = 2048 | |
43 | input_password = whatever | |
44 | output_password = whatever | |
45 | ||
46 | [server] | |
47 | countryName = FR | |
48 | stateOrProvinceName = Radius | |
49 | localityName = Somewhere | |
50 | organizationName = Example Inc. | |
51 | emailAddress = admin@example.org | |
52 | commonName = "Example Inner Server Certificate" | |
53 |
0 | [ ca ] | |
1 | default_ca = CA_default | |
2 | ||
3 | [ CA_default ] | |
4 | dir = ./ | |
5 | certs = $dir | |
6 | crl_dir = $dir/crl | |
7 | database = $dir/index.txt | |
8 | new_certs_dir = $dir | |
9 | certificate = $dir/server.pem | |
10 | serial = $dir/serial | |
11 | crl = $dir/crl.pem | |
12 | private_key = $dir/server.key | |
13 | RANDFILE = $dir/.rand | |
14 | name_opt = ca_default | |
15 | cert_opt = ca_default | |
16 | default_days = 60 | |
17 | default_crl_days = 30 | |
18 | default_md = sha256 | |
19 | preserve = no | |
20 | policy = policy_match | |
21 | unique_subject = no | |
22 | x509_extensions = v3_ocsp | |
23 | ||
24 | [ policy_match ] | |
25 | countryName = match | |
26 | stateOrProvinceName = match | |
27 | organizationName = match | |
28 | organizationalUnitName = optional | |
29 | commonName = supplied | |
30 | emailAddress = optional | |
31 | ||
32 | [ policy_anything ] | |
33 | countryName = optional | |
34 | stateOrProvinceName = optional | |
35 | localityName = optional | |
36 | organizationName = optional | |
37 | organizationalUnitName = optional | |
38 | commonName = supplied | |
39 | emailAddress = optional | |
40 | ||
41 | [ req ] | |
42 | prompt = no | |
43 | distinguished_name = server | |
44 | default_bits = 2048 | |
45 | input_password = whatever | |
46 | output_password = whatever | |
47 | ||
48 | [ server ] | |
49 | countryName = FR | |
50 | stateOrProvinceName = Radius | |
51 | localityName = Somewhere | |
52 | organizationName = Example Inc. | |
53 | emailAddress = admin@example.org | |
54 | commonName = "Example OCSP Responder Certificate" | |
55 | subjectAltName = ocsp.example.org | |
56 | ||
57 | [ v3_ocsp ] | |
58 | basicConstraints = CA:FALSE | |
59 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment | |
60 | extendedKeyUsage = OCSPSigning |
88 | 88 | # <list>:<attribute> <op> <value> |
89 | 89 | |
90 | 90 | # Cache all instances of Reply-Message in the reply list |
91 | &reply:Reply-Message += &reply:Reply-Message | |
91 | &reply:Reply-Message += &reply:Reply-Message[*] | |
92 | 92 | |
93 | 93 | # Add our own to show when the cache was last updated |
94 | 94 | &reply:Reply-Message += "Cache last updated at %t" |
28 | 28 | # |
29 | 29 | # Element names should be single quoted. |
30 | 30 | # |
31 | # Note: Atrributes not in this map will not be recorded. | |
31 | # Note: Attributes not in this map will not be recorded. | |
32 | 32 | # |
33 | 33 | update { |
34 | 34 | Acct-Session-Id = 'sessionId' |
284 | 284 | |
285 | 285 | ca_path = ${cadir} |
286 | 286 | |
287 | # Accept an expired Certificate Revocation List | |
288 | # | |
289 | # allow_expired_crl = no | |
290 | ||
287 | 291 | # |
288 | 292 | # If check_cert_issuer is set, the value will |
289 | 293 | # be checked against the DN of the issuer in |
291 | 295 | # match, the certificate verification will fail, |
292 | 296 | # rejecting the user. |
293 | 297 | # |
294 | # In 2.1.10 and later, this check can be done | |
295 | # more generally by checking the value of the | |
296 | # TLS-Client-Cert-Issuer attribute. This check | |
297 | # can be done via any mechanism you choose. | |
298 | # This check can be done more generally by checking | |
299 | # the value of the TLS-Client-Cert-Issuer attribute. | |
300 | # This check can be done via any mechanism you | |
301 | # choose. | |
298 | 302 | # |
299 | 303 | # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" |
300 | 304 | |
332 | 336 | # for TLS |
333 | 337 | cipher_server_preference = no |
334 | 338 | |
335 | # Work-arounds for OpenSSL nonsense | |
336 | # OpenSSL 1.0.1f and 1.0.1g do not calculate | |
337 | # the EAP keys correctly. The fix is to upgrade | |
338 | # OpenSSL, or disable TLS 1.2 here. | |
339 | # | |
340 | # For EAP-FAST, this MUST be set to "yes". | |
339 | # | |
340 | # You can selectively disable TLS versions for | |
341 | # compatability with old client devices. | |
342 | # | |
343 | # If your system has OpenSSL 1.1.0 or greater, do NOT | |
344 | # use these. Instead, set tls_min_version and | |
345 | # tls_max_version. | |
341 | 346 | # |
342 | 347 | # disable_tlsv1_2 = no |
343 | ||
344 | # | |
348 | # disable_tlsv1_1 = no | |
349 | # disable_tlsv1 = no | |
350 | ||
351 | # | |
352 | # Set min / max TLS version. Mainly for Debian | |
353 | # "trusty", which disables older versions of TLS, and | |
354 | # requires the application to manually enable them. | |
355 | # | |
356 | # If you are running Debian trusty, you should set | |
357 | # these options, otherwise older clients will not be | |
358 | # able to connect. | |
359 | # | |
360 | # Allowed values are "1.0", "1.1", and "1.2". | |
361 | # | |
362 | # The values must be in quotes. | |
363 | # | |
364 | # tls_min_version = "1.0" | |
365 | # tls_max_version = "1.2" | |
366 | ||
345 | 367 | |
346 | 368 | # |
347 | 369 | # Elliptical cryptography configuration |
672 | 694 | # |
673 | 695 | # in the control items for a request. |
674 | 696 | # |
697 | # Note that the majority of supplicants do not support using a | |
698 | # client certificate with EAP-TTLS, so this option is unlikely | |
699 | # to be usable for most people. | |
700 | # | |
675 | 701 | # require_client_cert = yes |
676 | 702 | } |
677 | 703 | |
797 | 823 | # EAP-TLS-Require-Client-Cert = Yes |
798 | 824 | # |
799 | 825 | # in the control items for a request. |
826 | # | |
827 | # Note that the majority of supplicants do not support using a | |
828 | # client certificate with PEAP, so this option is unlikely to | |
829 | # be usable for most people. | |
800 | 830 | # |
801 | 831 | # require_client_cert = yes |
802 | 832 | } |
848 | 878 | # fast { |
849 | 879 | # Point to the common TLS configuration |
850 | 880 | # |
851 | # cipher_list though must include "ADH" for anonymous provisioning. | |
852 | # This is not as straight forward as appending "ADH" alongside | |
853 | # "DEFAULT" as "DEFAULT" contains "!aNULL" so instead it is | |
854 | # recommended "ALL:!EXPORT:!eNULL:!SSLv2" is used | |
855 | # | |
856 | 881 | # tls = tls-common |
882 | ||
883 | # | |
884 | # If 'cipher_list' is set here, it will over-ride the | |
885 | # 'cipher_list' configuration from the 'tls-common' | |
886 | # configuration. The EAP-FAST module has it's own | |
887 | # over-ride for 'cipher_list' because the | |
888 | # specifications mandata a different set of ciphers | |
889 | # than are used by the other EAP methods. | |
890 | # | |
891 | # cipher_list though must include "ADH" for anonymous provisioning. | |
892 | # This is not as straight forward as appending "ADH" alongside | |
893 | # "DEFAULT" as "DEFAULT" contains "!aNULL" so instead it is | |
894 | # recommended "ALL:!EXPORT:!eNULL:!SSLv2" is used | |
895 | # | |
896 | # Note - for OpenSSL 1.1.0 and above you may need | |
897 | # to add ":@SECLEVEL=0" | |
898 | # | |
899 | # cipher_list = "ALL:!EXPORT:!eNULL:!SSLv2" | |
857 | 900 | |
858 | 901 | # PAC lifetime in seconds (default: seven days) |
859 | 902 | # |
44 | 44 | # You SHOULD use different certificates than are used |
45 | 45 | # for the outer EAP configuration! |
46 | 46 | # |
47 | # You can create the "inner-server.pem" file by doing: | |
48 | # | |
49 | # cd raddb/certs | |
50 | # vi inner-server.cnf | |
51 | # make inner-server | |
52 | # | |
53 | # The certificate MUST be different from the "server.cnf" | |
54 | # file. | |
55 | # | |
47 | 56 | # Support for PEAP/TLS and RFC 5176 TLS/TLS is experimental. |
48 | 57 | # It might work, or it might not. |
49 | 58 | # |
85 | 94 | # check_crl = yes |
86 | 95 | # ca_path = /path/to/directory/with/ca_certs/and/crls/ |
87 | 96 | |
97 | # Accept an expired Certificate Revocation List | |
98 | # | |
99 | # allow_expired_crl = no | |
100 | ||
88 | 101 | # |
89 | 102 | # The session resumption / fast re-authentication |
90 | 103 | # cache CANNOT be used for inner sessions. |
17 | 17 | # The password used to authenticate to the server. |
18 | 18 | # We recommend using a strong password. |
19 | 19 | # password = thisisreallysecretandhardtoguess |
20 | ||
21 | # Set connection and query timeout for rlm_redis | |
22 | query_timeout = 5 | |
20 | 23 | |
21 | 24 | # |
22 | 25 | # Information for the connection pool. The configuration items |
104 | 104 | # - is_json If true, any nested JSON data will be copied to the attribute |
105 | 105 | # in string form. Defaults to true. |
106 | 106 | # - op Controls how the attribute is inserted into the target list. |
107 | # Defaults to ':='. | |
107 | # Defaults to ':='. To create multiple attributes from multiple | |
108 | # values, this should be set to '+=', otherwise only the last | |
109 | # value will be used, and it will be assigned to a single | |
110 | # attribute. | |
108 | 111 | # { |
109 | 112 | # "<attribute0>":{ |
110 | 113 | # "is_json":<bool>, |
113 | 116 | # "value":[<value0>,<value1>,<valueN>] |
114 | 117 | # }, |
115 | 118 | # "<attribute1>":"value", |
116 | # "<attributeN>":[<value0>,<value1>,<valueN>] | |
119 | # "<attributeN>":{ | |
120 | # "value":[<value0>,<value1>,<valueN>], | |
121 | # "op":"+=" | |
122 | # } | |
117 | 123 | # } |
118 | 124 | |
119 | 125 | # |
23 | 23 | # IP lease duration. (Leases expire even if Acct Stop packet is lost) |
24 | 24 | lease_duration = 3600 |
25 | 25 | |
26 | # protocol to use. The default is IPv4. | |
27 | # ipv6 = yes | |
26 | # | |
27 | # As of 3.0.16, the 'ipv6 = yes' configuration is deprecated. | |
28 | # You should use the "attribute_name" configuration item | |
29 | # below, instead. | |
30 | # | |
31 | ||
32 | # | |
33 | # The attribute to use for IP address assignment. The | |
34 | # default is Framed-IP-Address. You can change this to any | |
35 | # attribute which is IPv4 or IPv6. | |
36 | # | |
37 | # e.g. Framed-IPv6-Prefix, or Delegated-IPv6-Prefix. | |
38 | # | |
39 | # As of 3.0.16, all of the default queries have been updated to use | |
40 | # this attribute_name. So you can do IPv6 address assignment simply | |
41 | # by putting IPv6 addresses into the pool, and changing the following | |
42 | # line to "Framed-IPv6-Prefix" | |
43 | # | |
44 | attribute_name = Framed-IP-Address | |
45 | ||
46 | # | |
47 | # Assign the IP address, even if the attribute already exists | |
48 | # | |
49 | # allow_duplicates = no | |
28 | 50 | |
29 | 51 | # Attribute which should be considered unique per NAS |
30 | 52 | # |
52 | 74 | # which writes Module-Success-Message message. |
53 | 75 | # |
54 | 76 | messages { |
55 | exists = "Existing IP: %{reply:Framed-IP-Address} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" | |
77 | exists = "Existing IP: %{reply:${..attribute_name}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" | |
56 | 78 | |
57 | success = "Allocated IP: %{reply:Framed-IP-Address} from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" | |
79 | success = "Allocated IP: %{reply:${..attribute_name}} from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" | |
58 | 80 | |
59 | clear = "Released IP %{Framed-IP-Address} (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})" | |
81 | clear = "Released IP ${..attribute_name} (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})" | |
60 | 82 | |
61 | 83 | failed = "IP Allocation FAILED from %{control:Pool-Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})" |
62 | 84 |
19 | 19 | # |
20 | 20 | # This series of queries allocates an IP address |
21 | 21 | # (Note: If your pool_key is set to Calling-Station-Id and not NAS-Port |
22 | # then you may wish to delete the "AND nasipaddress = '%{Nas-IP-Address}' | |
22 | # then you may wish to delete the "AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' | |
23 | 23 | # from the WHERE clause) |
24 | 24 | # |
25 | 25 | allocate_clear = "\ |
31 | 31 | username = '', \ |
32 | 32 | expiry_time = NULL \ |
33 | 33 | WHERE expiry_time <= NOW() - INTERVAL 1 SECOND \ |
34 | AND nasipaddress = '%{Nas-IP-Address}'" | |
34 | AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
35 | 35 | |
36 | 36 | # |
37 | 37 | # The ORDER BY clause of this query tries to allocate the same IP-address |
95 | 95 | AND pool_key = '${pool_key}' \ |
96 | 96 | AND username = '%{User-Name}' \ |
97 | 97 | AND callingstationid = '%{Calling-Station-Id}' \ |
98 | AND framedipaddress = '%{Framed-IP-Address}'" | |
98 | AND framedipaddress = '%{${attribute_name}}'" | |
99 | 99 | |
100 | 100 | # |
101 | 101 | # This series of queries frees an IP number when an accounting STOP record arrives. |
108 | 108 | callingstationid = '', \ |
109 | 109 | username = '', \ |
110 | 110 | expiry_time = NULL \ |
111 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
111 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
112 | 112 | AND pool_key = '${pool_key}' \ |
113 | 113 | AND username = '%{User-Name}' \ |
114 | 114 | AND callingstationid = '%{Calling-Station-Id}' \ |
115 | AND framedipaddress = '%{Framed-IP-Address}'" | |
115 | AND framedipaddress = '%{${attribute_name}}'" | |
116 | 116 | |
117 | 117 | # |
118 | 118 | # This series of queries frees an IP number when an accounting ALIVE record arrives. |
121 | 121 | UPDATE ${ippool_table} \ |
122 | 122 | SET \ |
123 | 123 | expiry_time = NOW() + INTERVAL ${lease_duration} SECOND \ |
124 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
124 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
125 | 125 | AND pool_key = '${pool_key}' \ |
126 | 126 | AND username = '%{User-Name}' \ |
127 | 127 | AND callingstationid = '%{Calling-Station-Id}' \ |
128 | AND framedipaddress = '%{Framed-IP-Address}'" | |
128 | AND framedipaddress = '%{${attribute_name}}'" | |
129 | 129 | |
130 | 130 | # |
131 | 131 | # This series of queries frees the IP numbers allocate to a |
139 | 139 | callingstationid = '', \ |
140 | 140 | username = '', \ |
141 | 141 | expiry_time = NULL \ |
142 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
142 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
143 | 143 | |
144 | 144 | # |
145 | 145 | # This series of queries frees the IP numbers allocate to a |
153 | 153 | callingstationid = '', \ |
154 | 154 | username = '', \ |
155 | 155 | expiry_time = NULL \ |
156 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
156 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
82 | 82 | # as your "pool_key" and your users are able to reconnect before your NAS |
83 | 83 | # has timed out their previous session. (Generally on wireless networks) |
84 | 84 | # (Note: If your pool_key is set to Calling-Station-Id and not NAS-Port |
85 | # then you may wish to delete the "AND nasipaddress = '%{Nas-IP-Address}' | |
85 | # then you may wish to delete the "AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' | |
86 | 86 | # from the WHERE clause) |
87 | 87 | # |
88 | 88 | allocate_clear = "\ |
115 | 115 | pool_key = 0, \ |
116 | 116 | callingstationid = '', \ |
117 | 117 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ |
118 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
118 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
119 | 119 | AND pool_key = '${pool_key}' \ |
120 | 120 | AND username = '%{SQL-User-Name}' \ |
121 | 121 | AND callingstationid = '%{Calling-Station-Id}'" |
128 | 128 | UPDATE ${ippool_table} \ |
129 | 129 | SET \ |
130 | 130 | expiry_time = current_timestamp + INTERVAL '${lease_duration}' second(1) \ |
131 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
131 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
132 | 132 | AND pool_key = '${pool_key}' \ |
133 | AND framedipaddress = '%{Framed-IP-Address}' \ | |
133 | AND framedipaddress = '%{${attribute_name}}' \ | |
134 | 134 | AND username = '%{SQL-User-Name}' \ |
135 | 135 | AND callingstationid = '%{Calling-Station-Id}'" |
136 | 136 | |
145 | 145 | pool_key = 0, \ |
146 | 146 | callingstationid = '', \ |
147 | 147 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ |
148 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
148 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
149 | 149 | |
150 | 150 | # |
151 | 151 | # This query frees all IP addresses allocated to a NAS when an |
158 | 158 | pool_key = 0, \ |
159 | 159 | callingstationid = '', \ |
160 | 160 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ |
161 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
161 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
63 | 63 | # as your "pool_key" and your users are able to reconnect before your NAS |
64 | 64 | # has timed out their previous session. (Generally on wireless networks) |
65 | 65 | # (Note: If your pool_key is set to Calling-Station-Id and not NAS-Port |
66 | # then you may wish to delete the "AND nasipaddress = '%{Nas-IP-Address}' | |
66 | # then you may wish to delete the "AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' | |
67 | 67 | # from the WHERE clause) |
68 | 68 | # |
69 | 69 | allocate_clear = "\ |
98 | 98 | pool_key = 0, \ |
99 | 99 | callingstationid = '', \ |
100 | 100 | expiry_time = 'now'::timestamp(0) - '1 second'::interval \ |
101 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
101 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
102 | 102 | AND pool_key = '${pool_key}' \ |
103 | 103 | AND username = '%{SQL-User-Name}' \ |
104 | 104 | AND callingstationid = '%{Calling-Station-Id}' \ |
105 | AND framedipaddress = '%{Framed-IP-Address}'" | |
105 | AND framedipaddress = '%{${attribute_name}}'" | |
106 | 106 | |
107 | 107 | # |
108 | 108 | # This query extends an IP address lease by "lease_duration" when an accounting |
112 | 112 | UPDATE ${ippool_table} \ |
113 | 113 | SET \ |
114 | 114 | expiry_time = 'now'::timestamp(0) + '${lease_duration} seconds'::interval \ |
115 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
115 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
116 | 116 | AND pool_key = '${pool_key}' \ |
117 | AND framedipaddress = '%{Framed-IP-Address}' \ | |
117 | AND framedipaddress = '%{${attribute_name}}' \ | |
118 | 118 | AND username = '%{SQL-User-Name}' \ |
119 | 119 | AND callingstationid = '%{Calling-Station-Id}'" |
120 | 120 | |
129 | 129 | pool_key = 0, \ |
130 | 130 | callingstationid = '', \ |
131 | 131 | expiry_time = 'now'::timestamp(0) - '1 second'::interval \ |
132 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
132 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
133 | 133 | |
134 | 134 | # |
135 | 135 | # This query frees all IP addresses allocated to a NAS when an |
142 | 142 | pool_key = 0, \ |
143 | 143 | callingstationid = '', \ |
144 | 144 | expiry_time = 'now'::timestamp(0) - '1 second'::interval \ |
145 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
145 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
17 | 17 | # |
18 | 18 | # This series of queries allocates an IP address |
19 | 19 | # (Note: If your pool_key is set to Calling-Station-Id and not NAS-Port |
20 | # then you may wish to delete the "AND nasipaddress = '%{Nas-IP-Address}' | |
20 | # then you may wish to delete the "AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' | |
21 | 21 | # from the WHERE clause) |
22 | 22 | # |
23 | 23 | allocate_clear = "\ |
29 | 29 | username = '', \ |
30 | 30 | expiry_time = NULL \ |
31 | 31 | WHERE expiry_time <= datetime(strftime('%%s', 'now') - 1, 'unixepoch') \ |
32 | AND nasipaddress = '%{Nas-IP-Address}'" | |
32 | AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
33 | 33 | |
34 | 34 | # |
35 | 35 | # The ORDER BY clause of this query tries to allocate the same IP-address |
98 | 98 | AND pool_key = '${pool_key}' \ |
99 | 99 | AND username = '%{User-Name}' \ |
100 | 100 | AND callingstationid = '%{Calling-Station-Id}' \ |
101 | AND framedipaddress = '%{Framed-IP-Address}'" | |
101 | AND framedipaddress = '%{${attribute_name}}'" | |
102 | 102 | |
103 | 103 | # |
104 | 104 | # This series of queries frees an IP number when an accounting STOP record arrives |
111 | 111 | callingstationid = '', \ |
112 | 112 | username = '', \ |
113 | 113 | expiry_time = NULL \ |
114 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
114 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
115 | 115 | AND pool_key = '${pool_key}' \ |
116 | 116 | AND username = '%{User-Name}' \ |
117 | 117 | AND callingstationid = '%{Calling-Station-Id}' \ |
118 | AND framedipaddress = '%{Framed-IP-Address}'" | |
118 | AND framedipaddress = '%{${attribute_name}}'" | |
119 | 119 | |
120 | 120 | # |
121 | 121 | # This series of queries frees an IP number when an accounting |
125 | 125 | UPDATE ${ippool_table} \ |
126 | 126 | SET \ |
127 | 127 | expiry_time = datetime(strftime('%%s', 'now') + ${lease_duration}, 'unixepoch') \ |
128 | WHERE nasipaddress = '%{Nas-IP-Address}' \ | |
128 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
129 | 129 | AND pool_key = '${pool_key}' \ |
130 | 130 | AND username = '%{User-Name}' \ |
131 | 131 | AND callingstationid = '%{Calling-Station-Id}' \ |
132 | AND framedipaddress = '%{Framed-IP-Address}'" | |
132 | AND framedipaddress = '%{${attribute_name}}'" | |
133 | 133 | |
134 | 134 | # |
135 | 135 | # This series of queries frees the IP numbers allocate to a |
143 | 143 | callingstationid = '', \ |
144 | 144 | username = '', \ |
145 | 145 | expiry_time = NULL \ |
146 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
146 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
147 | 147 | |
148 | 148 | # |
149 | 149 | # This series of queries frees the IP numbers allocate to a |
157 | 157 | callingstationid = '', \ |
158 | 158 | username = '', \ |
159 | 159 | expiry_time = NULL \ |
160 | WHERE nasipaddress = '%{Nas-IP-Address}'" | |
160 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
161 | 161 |
18 | 18 | [AcctSessionId] [varchar] (64) DEFAULT ('') FOR [AcctSessionId], |
19 | 19 | [AcctUniqueId] [varchar] (32) DEFAULT ('') FOR [AcctUniqueId], |
20 | 20 | [UserName] [varchar] (64) DEFAULT ('') FOR [UserName], |
21 | [GroupName] [varchar] (64) DEFAULT ('') FOR [GroupName], | |
22 | 21 | [Realm] [varchar] (64) DEFAULT ('') FOR [Realm], |
23 | 22 | [NASIPAddress] [varchar] (15) DEFAULT ('') FOR [NASIPAddress], |
24 | 23 | [NASPortId] [varchar] (15) NULL , |
18 | 18 | acctsessionid varchar(64) NOT NULL default '', |
19 | 19 | acctuniqueid varchar(32) NOT NULL default '', |
20 | 20 | username varchar(64) NOT NULL default '', |
21 | groupname varchar(64) NOT NULL default '', | |
22 | 21 | realm varchar(64) default '', |
23 | 22 | nasipaddress varchar(15) NOT NULL default '', |
24 | 23 | nasportid varchar(15) default NULL, |
20 | 20 | acctsessionid varchar(64) NOT NULL default '', |
21 | 21 | acctuniqueid varchar(32) NOT NULL default '', |
22 | 22 | username varchar(64) NOT NULL default '', |
23 | groupname varchar(64) NOT NULL default '', | |
24 | 23 | realm varchar(64) default '', |
25 | 24 | nasipaddress varchar(15) NOT NULL default '', |
26 | 25 | nasportid varchar(15) default NULL, |
14 | 14 | acctsessionid VARCHAR(96) NOT NULL, |
15 | 15 | acctuniqueid VARCHAR(32), |
16 | 16 | username VARCHAR(64) NOT NULL, |
17 | groupname VARCHAR(32), | |
18 | 17 | realm VARCHAR(30), |
19 | 18 | nasipaddress VARCHAR(15) NOT NULL, |
20 | 19 | nasportid VARCHAR(32), |
85 | 84 | */ |
86 | 85 | CREATE TABLE radgroupcheck ( |
87 | 86 | id INT PRIMARY KEY, |
88 | groupname VARCHAR(20) UNIQUE NOT NULL, | |
87 | groupname VARCHAR(20) NOT NULL, | |
89 | 88 | attribute VARCHAR(64), |
90 | 89 | op CHAR(2) NOT NULL, |
91 | 90 | value VARCHAR(40) |
97 | 96 | */ |
98 | 97 | CREATE TABLE radgroupreply ( |
99 | 98 | id INT PRIMARY KEY, |
100 | GroupName VARCHAR(20) UNIQUE NOT NULL, | |
99 | GroupName VARCHAR(20) NOT NULL, | |
101 | 100 | Attribute VARCHAR(64), |
102 | 101 | op CHAR(2) NOT NULL, |
103 | 102 | Value VARCHAR(40) |
133 | 132 | */ |
134 | 133 | CREATE TABLE radusergroup ( |
135 | 134 | id INT PRIMARY KEY, |
136 | UserName VARCHAR(30) UNIQUE NOT NULL, | |
135 | UserName VARCHAR(30) NOT NULL, | |
137 | 136 | GroupName VARCHAR(30) |
138 | 137 | ); |
139 | 138 | CREATE SEQUENCE radusergroup_seq START WITH 1 INCREMENT BY 1; |
149 | 148 | END; |
150 | 149 | / |
151 | 150 | |
152 | ||
153 | /* | |
154 | * Table structure for table 'realmgroup' | |
155 | */ | |
156 | CREATE TABLE realmgroup ( | |
157 | id INT PRIMARY KEY, | |
158 | RealmName VARCHAR(30) UNIQUE NOT NULL, | |
159 | GroupName VARCHAR(30) | |
160 | ); | |
161 | CREATE SEQUENCE realmgroup_seq START WITH 1 INCREMENT BY 1; | |
162 | ||
163 | CREATE TABLE realms ( | |
164 | id INT PRIMARY KEY, | |
165 | realmname VARCHAR(64), | |
166 | nas VARCHAR(128), | |
167 | authport INT, | |
168 | options VARCHAR(128) | |
169 | ); | |
170 | CREATE SEQUENCE realms_seq START WITH 1 INCREMENT BY 1; | |
171 | ||
172 | CREATE TABLE radhuntgroup ( | |
173 | id INT PRIMARY KEY, | |
174 | GroupName VARCHAR(64) NOT NULL, | |
175 | Nasipaddress VARCHAR(15) UNIQUE NOT NULL, | |
176 | NASPortID VARCHAR(15) | |
177 | ); | |
178 | ||
179 | CREATE SEQUENCE radhuntgroup_seq START WITH 1 INCREMENT BY 1; | |
180 | ||
181 | CREATE OR REPLACE TRIGGER radhuntgroup_serialnumber | |
182 | BEFORE INSERT OR UPDATE OF id ON radhuntgroup | |
183 | FOR EACH ROW | |
184 | BEGIN | |
185 | if ( :new.id = 0 or :new.id is null ) then | |
186 | SELECT radhuntgroup_seq.nextval into :new.id from dual; | |
187 | end if; | |
188 | END; | |
189 | 151 | |
190 | 152 | CREATE TABLE radpostauth ( |
191 | 153 | id INT PRIMARY KEY, |
0 | /* | |
1 | * $Id$ | |
2 | * | |
3 | * OPTIONAL Postgresql trigger for FreeRADIUS | |
4 | * | |
5 | * This trigger updates fills in the groupname field (which doesnt come in Accounting packets) | |
6 | * by querying the radusergroup table. | |
7 | * This makes it easier to do group summary reports, however note that it does add some extra | |
8 | * database load to 50% of your SQL accounting queries. If you dont care about group summary | |
9 | * reports then you dont need to install this. | |
10 | * | |
11 | */ | |
12 | ||
13 | ||
14 | CREATE OR REPLACE FUNCTION upd_radgroups() RETURNS trigger AS' | |
15 | ||
16 | DECLARE | |
17 | v_groupname varchar; | |
18 | ||
19 | BEGIN | |
20 | SELECT INTO v_groupname GroupName FROM radusergroup WHERE CalledStationId = NEW.CalledStationId AND UserName = NEW.UserName; | |
21 | IF FOUND THEN | |
22 | UPDATE radacct SET GroupName = v_groupname WHERE RadAcctId = NEW.RadAcctId; | |
23 | END IF; | |
24 | ||
25 | RETURN NEW; | |
26 | END | |
27 | ||
28 | 'LANGUAGE plpgsql; | |
29 | ||
30 | ||
31 | DROP TRIGGER upd_radgroups ON radacct; | |
32 | ||
33 | CREATE TRIGGER upd_radgroups AFTER INSERT ON radacct | |
34 | FOR EACH ROW EXECUTE PROCEDURE upd_radgroups(); | |
35 | ||
36 |
17 | 17 | AcctSessionId text NOT NULL, |
18 | 18 | AcctUniqueId text NOT NULL UNIQUE, |
19 | 19 | UserName text, |
20 | GroupName text, | |
21 | 20 | Realm text, |
22 | 21 | NASIPAddress inet NOT NULL, |
23 | 22 | NASPortId text, |
14 | 14 | acctsessionid varchar(64) NOT NULL default '', |
15 | 15 | acctuniqueid varchar(32) NOT NULL default '', |
16 | 16 | username varchar(64) NOT NULL default '', |
17 | groupname varchar(64) NOT NULL default '', | |
18 | 17 | realm varchar(64) default '', |
19 | 18 | nasipaddress varchar(15) NOT NULL default '', |
20 | 19 | nasportid varchar(15) default NULL, |
15 | 15 | if (&User-Name && (&User-Name =~ /${policy.nai_regexp}/)) { |
16 | 16 | update request { |
17 | 17 | &Stripped-User-Name := "%{1}" |
18 | &Stripped-User-Domain = "%{3}" | |
18 | } | |
19 | ||
20 | # Only add the Stripped-User-Domain attribute if | |
21 | # we have a domain. This means presence checks | |
22 | # for Stripped-User-Domain work. | |
23 | if ("%{3}" != '') { | |
24 | update request { | |
25 | &Stripped-User-Domain = "%{3}" | |
26 | } | |
19 | 27 | } |
20 | 28 | |
21 | 29 | # If any of the expansions result in a null |
35 | 43 | if (&proxy-reply:User-Name && (&proxy-reply:User-Name =~ /${policy.nai_regexp}/)) { |
36 | 44 | update proxy-reply { |
37 | 45 | &Stripped-User-Name := "%{1}" |
38 | &Stripped-User-Domain = "%{3}" | |
46 | } | |
47 | ||
48 | # Only add the Stripped-User-Domain attribute if | |
49 | # we have a domain. This means presence checks | |
50 | # for Stripped-User-Domain work. | |
51 | if ("%{3}" != '') { | |
52 | update proxy-reply { | |
53 | &Stripped-User-Domain = "%{3}" | |
54 | } | |
39 | 55 | } |
40 | 56 | updated |
41 | 57 | } |
575 | 575 | # |
576 | 576 | # max_queue_size = 65536 |
577 | 577 | |
578 | # There may be memory leaks or resource allocation problems with | |
579 | # the server. If so, set this value to 300 or so, so that the | |
580 | # resources will be cleaned up periodically. | |
581 | # | |
582 | # This should only be necessary if there are serious bugs in the | |
583 | # server which have not yet been fixed. | |
578 | # Clean up old threads periodically. For no reason other than | |
579 | # it might be useful. | |
584 | 580 | # |
585 | 581 | # '0' is a special value meaning 'infinity', or 'the servers never |
586 | 582 | # exit' |
82 | 82 | tls { |
83 | 83 | private_key_password = whatever |
84 | 84 | private_key_file = ${certdir}/server.pem |
85 | ||
86 | # Accept an expired Certificate Revocation List | |
87 | # | |
88 | # allow_expired_crl = no | |
85 | 89 | |
86 | 90 | # If Private key & Certificate are located in |
87 | 91 | # the same file, then private_key_file & |
168 | 172 | # match, the certificate verification will fail, |
169 | 173 | # rejecting the user. |
170 | 174 | # |
171 | # In 2.1.10 and later, this check can be done | |
172 | # more generally by checking the value of the | |
173 | # TLS-Client-Cert-Issuer attribute. This check | |
174 | # can be done via any mechanism you choose. | |
175 | # This check can be done more generally by checking | |
176 | # the value of the TLS-Client-Cert-Issuer attribute. | |
177 | # This check can be done via any mechanism you choose. | |
175 | 178 | # |
176 | 179 | # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" |
177 | 180 |
25 | 25 | |
26 | 26 | Summary: High-performance and highly configurable free RADIUS server |
27 | 27 | Name: freeradius |
28 | Version: 3.0.15 | |
28 | Version: 3.0.16 | |
29 | 29 | Release: 2%{?dist} |
30 | 30 | License: GPLv2+ and LGPLv2+ |
31 | 31 | Group: System Environment/Daemons |
52 | 52 | |
53 | 53 | BuildRequires: autoconf |
54 | 54 | BuildRequires: gdbm-devel |
55 | BuildRequires: libtool | |
56 | BuildRequires: libtool-ltdl-devel | |
57 | 55 | BuildRequires: openssl, openssl-devel |
58 | 56 | BuildRequires: pam-devel |
59 | 57 | BuildRequires: zlib-devel |
60 | 58 | BuildRequires: net-snmp-devel |
61 | 59 | BuildRequires: net-snmp-utils |
60 | %{?el7:BuildRequires: samba-winbind-devel} | |
61 | %{?el6:BuildRequires: samba4-devel} | |
62 | 62 | BuildRequires: readline-devel |
63 | 63 | BuildRequires: libpcap-devel |
64 | 64 | BuildRequires: libtalloc-devel |
73 | 73 | Requires: readline |
74 | 74 | Requires: libtalloc |
75 | 75 | Requires: net-snmp |
76 | %{?el7:Requires: samba-libs} | |
77 | %{?el7:Requires: samba-winbind-clients} | |
78 | %{?el6:Requires: samba4-libs} | |
79 | %{?el6:Requires: samba4-winbind-clients} | |
76 | 80 | Requires: zlib |
77 | 81 | Requires: pam |
78 | 82 | |
142 | 146 | Summary: LDAP support for FreeRADIUS |
143 | 147 | Group: System Environment/Daemons |
144 | 148 | Requires: %{name} = %{version}-%{release} |
145 | Requires: openldap | |
146 | BuildRequires: openldap-devel | |
149 | Requires: openldap-ltb | |
150 | BuildRequires: openldap-ltb | |
147 | 151 | |
148 | 152 | %description ldap |
149 | 153 | This plugin provides LDAP support for the FreeRADIUS server project. |
321 | 325 | |
322 | 326 | %configure \ |
323 | 327 | --libdir=%{_libdir}/freeradius \ |
324 | --with-system-libtool \ | |
325 | 328 | --disable-ltdl-install \ |
326 | 329 | --with-gnu-ld \ |
327 | 330 | --with-threads \ |
328 | 331 | --with-thread-pool \ |
329 | 332 | --with-docdir=%{docdir} \ |
333 | --with-rlm-ldap-include-dir=/usr/local/openldap/include \ | |
334 | --with-rlm-ldap-lib-dir=/usr/local/openldap/lib64 \ | |
330 | 335 | --with-rlm-sql_postgresql-include-dir=/usr/include/pgsql \ |
331 | 336 | --with-rlm-sql-postgresql-lib-dir=%{_libdir} \ |
332 | 337 | --with-rlm-sql_mysql-include-dir=/usr/include/mysql \ |
340 | 345 | --without-rlm_sql_db2 \ |
341 | 346 | --with-jsonc-lib-dir=%{_libdir} \ |
342 | 347 | --with-jsonc-include-dir=/usr/include/json \ |
348 | --with-winbind-include-dir=/usr/include/samba-4.0 \ | |
349 | --with-winbind-lib-dir=/usr/lib64/samba \ | |
343 | 350 | %{?_with_rlm_yubikey} \ |
344 | 351 | %{?_without_rlm_yubikey} \ |
345 | 352 | %{?_with_rlm_sql_oracle} \ |
362 | 369 | %{?_without_rlm_cache_memcached} \ |
363 | 370 | # --with-modules="rlm_wimax" \ |
364 | 371 | |
365 | %if "%{_lib}" == "lib64" | |
366 | perl -pi -e 's:sys_lib_search_path_spec=.*:sys_lib_search_path_spec="/lib64 /usr/lib64 /usr/local/lib64":' libtool | |
367 | %endif | |
368 | ||
369 | make | |
370 | ||
372 | make %_smp_mflags | |
371 | 373 | |
372 | 374 | %install |
373 | 375 | rm -rf $RPM_BUILD_ROOT |
374 | 376 | mkdir -p $RPM_BUILD_ROOT/var/run/radiusd |
375 | 377 | mkdir -p $RPM_BUILD_ROOT/var/lib/radiusd |
376 | # fix for bad libtool bug - can not rebuild dependent libs and bins | |
377 | #FIXME export LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir} | |
378 | 378 | make install R=$RPM_BUILD_ROOT |
379 | 379 | # modify default configuration |
380 | 380 | RADDB=$RPM_BUILD_ROOT%{_sysconfdir}/raddb |
600 | 600 | %{_libdir}/freeradius/rlm_sql_sqlite.so |
601 | 601 | %{_libdir}/freeradius/rlm_sqlcounter.so |
602 | 602 | %{_libdir}/freeradius/rlm_sqlippool.so |
603 | ||
604 | %if %{?_with_developer:1}%{!?_with_developer:0} | |
605 | %{_libdir}/freeradius/rlm_sqlhpwippool.so | |
606 | %endif | |
607 | ||
603 | 608 | %{_libdir}/freeradius/rlm_unpack.so |
604 | 609 | %{_libdir}/freeradius/rlm_unix.so |
605 | 610 | %{_libdir}/freeradius/rlm_utf8.so |
804 | 809 | %{_libdir}/freeradius/rlm_yubikey.so |
805 | 810 | %endif |
806 | 811 | |
807 | ||
808 | 812 | %changelog |
809 | 813 | * Wed Sep 25 2013 Alan DeKok <aland@freeradius.org> - 3.0.0 |
810 | 814 | - upgrade to latest upstream release |
0 | # This is a quick hack to convert an openldap schema file to a form which | |
1 | # can be loaded into Samba4/AD. | |
2 | # | |
3 | # Inspired by: | |
4 | # http://david-latham.blogspot.co.uk/2012/12/extending-ad-schema-on-samba4-part-2.html | |
5 | # https://github.com/linuxplayground/yubikey-ldap/tree/master/samba4-schema | |
6 | # | |
7 | # (c) 2017 Brian Candler <b.candler@pobox.com> | |
8 | # ------------------------------------------------------------------------- | |
9 | # This program is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; either version 2 of the License, or | |
12 | # (at your option) any later version. | |
13 | # | |
14 | # This program is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | # GNU General Public License for more details. | |
18 | # | |
19 | # You should have received a copy of the GNU General Public License | |
20 | # along with this program; if not, write to the Free Software | |
21 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
22 | # ----------------------------------------------------------------------- | |
23 | ||
24 | from __future__ import print_function | |
25 | import sys | |
26 | import re | |
27 | from collections import OrderedDict | |
28 | ||
29 | BASEDN = 'dc=samba4,dc=internal' | |
30 | ||
31 | # RFC 2252 to https://technet.microsoft.com/en-us/library/cc961740.aspx | |
32 | SYNTAX_MAP = { | |
33 | '1.3.6.1.4.1.1466.115.121.1.7': ('2.5.5.8', 1), # boolean | |
34 | '1.3.6.1.4.1.1466.115.121.1.12': ('2.5.5.1', 127), # DN | |
35 | '1.3.6.1.4.1.1466.115.121.1.15': ('2.5.5.3', 27), # DirectoryString | |
36 | '1.3.6.1.4.1.1466.115.121.1.26': ('2.5.5.5', 22), # IA5String | |
37 | '1.3.6.1.4.1.1466.115.121.1.27': ('2.5.5.9', 10), # Integer | |
38 | } | |
39 | obj = None | |
40 | for line in sys.stdin: | |
41 | if re.match(r'^\s*(#|$)', line): continue | |
42 | m = re.match(r'^attributetype\s+\(\s+(\S+)', line) | |
43 | if m: | |
44 | obj = OrderedDict([ | |
45 | ('objectClass', ['top', 'attributeSchema']), | |
46 | ('attributeID', m.group(1)), | |
47 | ('isSingleValued', 'FALSE'), | |
48 | ]) | |
49 | continue | |
50 | m = re.match(r'^objectclass\s+\(\s+(\S+)', line) | |
51 | if m: | |
52 | obj = OrderedDict([ | |
53 | ('objectClass', ['top', 'classSchema']), | |
54 | ('governsID', m.group(1)), | |
55 | ]) | |
56 | continue | |
57 | m = re.match(r'^\s*NAME\s+[\'"](.+)[\'"]', line) | |
58 | if m: | |
59 | obj.update([ | |
60 | ('cn', m.group(1)), | |
61 | ('name', m.group(1)), | |
62 | ('lDAPDisplayName', m.group(1)), | |
63 | ]) | |
64 | continue | |
65 | m = re.match(r'^\s*DESC\s+[\'"](.+)[\'"]', line) | |
66 | if m: | |
67 | obj.update([ | |
68 | ('description', m.group(1)), | |
69 | ]) | |
70 | continue | |
71 | m = re.match(r'^\s*(EQUALITY|SUBSTR)\s+(\S+)', line) | |
72 | if m: | |
73 | # Not supported by AD? | |
74 | # https://technet.microsoft.com/en-us/library/cc961575.aspx | |
75 | continue | |
76 | m = re.match(r'^\s*SYNTAX\s+(\S+)', line) | |
77 | if m: | |
78 | obj.update([ | |
79 | ('attributeSyntax', SYNTAX_MAP[m.group(1)][0]), | |
80 | ('oMSyntax', SYNTAX_MAP[m.group(1)][1]), | |
81 | ]) | |
82 | continue | |
83 | if re.match(r'^\s*SINGLE-VALUE', line): | |
84 | obj.update([ | |
85 | ('isSingleValued', 'TRUE'), | |
86 | ]) | |
87 | continue | |
88 | if re.match(r'^\s*AUXILIARY', line): | |
89 | # https://msdn.microsoft.com/en-us/library/ms679014(v=vs.85).aspx | |
90 | # https://technet.microsoft.com/en-us/library/2008.05.schema.aspx | |
91 | obj.update([ | |
92 | ('objectClassCategory', '3'), | |
93 | ]) | |
94 | continue | |
95 | if re.match(r'^\s*STRUCTURAL', line): | |
96 | obj.update([ | |
97 | ('objectClassCategory', '1'), | |
98 | ]) | |
99 | continue | |
100 | m = re.match(r'^\s*SUP\s+(\S+)', line) | |
101 | if m: | |
102 | obj.update([ | |
103 | ('subClassOf', m.group(1)), | |
104 | ]) | |
105 | continue | |
106 | m = re.match(r'^\s*(MAY|MUST)\s+\((.*)\)\s*$', line) | |
107 | if m: | |
108 | attrs = m.group(2).split('$') | |
109 | obj.update([ | |
110 | ('%sContain' % m.group(1).lower(), [v.strip() for v in attrs]), | |
111 | ]) | |
112 | continue | |
113 | m = re.match(r'^\s*(MAY|MUST)\s+(\w+)\s*$', line) | |
114 | if m: | |
115 | obj.update([ | |
116 | ('%sContain' % m.group(1).lower(), m.group(2)), | |
117 | ]) | |
118 | continue | |
119 | if re.match(r'^\s*\)', line) and obj: | |
120 | print("dn: CN=%s,CN=Schema,CN=Configuration,%s" % (obj['cn'], BASEDN)) | |
121 | print("changetype: add") | |
122 | for k in obj: | |
123 | if type(obj[k]) == list: | |
124 | for v in obj[k]: | |
125 | print("%s: %s" % (k, v)) | |
126 | else: | |
127 | print("%s: %s" % (k, obj[k])) | |
128 | print() | |
129 | obj = None | |
130 | continue | |
131 | print("??? %s" % line, file=sys.stderr) |
4 | 4 | # |
5 | 5 | |
6 | 6 | # |
7 | # Global options for all files | |
8 | # | |
9 | daily | |
10 | rotate 14 | |
11 | missingok | |
12 | compress | |
13 | delaycompress | |
14 | notifempty | |
15 | ||
16 | # | |
17 | 7 | # The main server log |
18 | 8 | # |
19 | 9 | /var/log/radius/radius.log { |
10 | # common options | |
11 | daily | |
12 | rotate 14 | |
13 | missingok | |
14 | compress | |
15 | delaycompress | |
16 | notifempty | |
17 | ||
20 | 18 | copytruncate |
21 | 19 | } |
22 | 20 | |
23 | # | |
21 | # (in order) | |
24 | 22 | # Session monitoring utilities |
25 | # | |
26 | /var/log/radius/checkrad.log /var/log/radius/radwatch.log { | |
27 | nocreate | |
28 | } | |
23 | # SQL log files | |
24 | /var/log/freeradius/checkrad.log /var/log/freeradius/radwatch.log | |
25 | /var/log/freeradius/sqllog.sql | |
26 | { | |
27 | # common options | |
28 | daily | |
29 | rotate 14 | |
30 | missingok | |
31 | compress | |
32 | delaycompress | |
33 | notifempty | |
29 | 34 | |
30 | # | |
31 | # SQL log files | |
32 | # | |
33 | /var/log/radius/sqllog.sql { | |
34 | 35 | nocreate |
35 | 36 | } |
36 | 37 | |
42 | 43 | # second technique, you will need another cron job that removes old |
43 | 44 | # detail files. You do not need to comment out the below for method #2. |
44 | 45 | /var/log/radius/radacct/*/detail { |
46 | # common options | |
47 | daily | |
48 | rotate 14 | |
49 | missingok | |
50 | compress | |
51 | delaycompress | |
52 | notifempty | |
53 | ||
45 | 54 | nocreate |
46 | 55 | } |
223 | 223 | ATTRIBUTE Acme-Custom-VSA-229 229 string |
224 | 224 | ATTRIBUTE Acme-Custom-VSA-230 230 string |
225 | 225 | |
226 | ATTRIBUTE Acme-Flow-Calling-Media-Stop-Time-FS1 231 string | |
227 | ATTRIBUTE Acme-Flow-Called-Media-Stop-Time-FS1 232 string | |
228 | ATTRIBUTE Acme-Flow-Calling-Media-Stop-Time-FS2 233 string | |
229 | ATTRIBUTE Acme-Flow-Called-Media-Stop-Time-FS2 234 string | |
230 | ATTRIBUTE Acme-SIP-Method-Type 235 string | |
231 | ATTRIBUTE Acme-Domain-Name 236 string | |
232 | ATTRIBUTE Acme-SIP-Contact 237 string | |
233 | ATTRIBUTE Acme-SIP-Expires 238 integer | |
234 | ATTRIBUTE Acme-Reason-Phrase 239 string | |
235 | ||
236 | ATTRIBUTE Acme-User-Privilege 253 string | |
237 | ||
226 | 238 | ATTRIBUTE Acme-User-Class 254 string |
227 | 239 | |
228 | 240 | END-VENDOR Acme |
182 | 182 | ATTRIBUTE FreeRADIUS-EAP-FAST-Request-Action 186.19 short |
183 | 183 | ATTRIBUTE FreeRADIUS-EAP-FAST-PKCS 186.20 octets |
184 | 184 | |
185 | ATTRIBUTE FreeRADIUS-Stats-Error 187 string | |
186 | ||
185 | 187 | END-VENDOR FreeRADIUS |
21 | 21 | ATTRIBUTE Juniper-Configuration-Change 9 string |
22 | 22 | ATTRIBUTE Juniper-User-Permissions 10 string |
23 | 23 | ATTRIBUTE Juniper-Junosspace-Profile 11 String |
24 | ATTRIBUTE Juniper-Junosspace-Profiles 11 String | |
24 | 25 | |
25 | 26 | ATTRIBUTE Juniper-CTP-Group 21 integer |
26 | 27 | ATTRIBUTE Juniper-CTPView-APP-Group 22 integer |
13 | 13 | |
14 | 14 | BEGIN-VENDOR Patton |
15 | 15 | |
16 | ATTRIBUTE Patton-Protocol 16 string | |
16 | ATTRIBUTE Patton-Protocol 16 string | |
17 | ATTRIBUTE Patton-Group 17 string | |
18 | ATTRIBUTE Patton-Web-Privilege-Level 18 string | |
17 | 19 | ATTRIBUTE Patton-Setup-Time 32 string |
18 | 20 | ATTRIBUTE Patton-Connect-Time 33 string |
19 | 21 | ATTRIBUTE Patton-Disconnect-Time 34 string |
20 | 22 | ATTRIBUTE Patton-Disconnect-Cause 35 integer |
21 | 23 | ATTRIBUTE Patton-Disconnect-Source 36 string |
24 | ATTRIBUTE Patton-Disconnect-Reason 37 string | |
22 | 25 | ATTRIBUTE Patton-Called-Unique-Id 48 string |
23 | 26 | ATTRIBUTE Patton-Called-IP-Address 49 ipaddr |
24 | 27 | ATTRIBUTE Patton-Called-Numbering-Plan 50 string |
25 | 28 | ATTRIBUTE Patton-Called-Type-Of-Number 51 string |
26 | 29 | ATTRIBUTE Patton-Called-Name 52 string |
27 | ATTRIBUTE Patton-Called-Station-Id 53 string | |
30 | ATTRIBUTE Patton-Called-Station-Id 53 string | |
28 | 31 | ATTRIBUTE Patton-Called-Rx-Octets 64 integer |
29 | 32 | ATTRIBUTE Patton-Called-Tx-Octets 65 integer |
30 | 33 | ATTRIBUTE Patton-Called-Rx-Packets 66 integer |
35 | 38 | ATTRIBUTE Patton-Called-Tx-Jitter 71 integer |
36 | 39 | ATTRIBUTE Patton-Called-Codec 72 string |
37 | 40 | ATTRIBUTE Patton-Called-Remote-Ip 73 integer |
38 | ATTRIBUTE Patton-Called-Remote-Udp-Port 74 integer | |
39 | ATTRIBUTE Patton-Called-Local-Udp-Port 75 integer | |
41 | ATTRIBUTE Patton-Called-Remote-Udp-Port 74 integer | |
42 | ATTRIBUTE Patton-Called-Local-Udp-Port 75 integer | |
40 | 43 | ATTRIBUTE Patton-Called-Qos 76 integer |
41 | 44 | ATTRIBUTE Patton-Called-MOS 77 integer |
42 | 45 | ATTRIBUTE Patton-Called-Round-Trip-Time 78 integer |
47 | 50 | ATTRIBUTE Patton-Calling-Presentation-Indicator 88 string |
48 | 51 | ATTRIBUTE Patton-Calling-Screening-Indicator 89 string |
49 | 52 | ATTRIBUTE Patton-Calling-Name 84 string |
50 | ATTRIBUTE Patton-Calling-Station-Id 85 string | |
53 | ATTRIBUTE Patton-Calling-Station-Id 85 string | |
51 | 54 | ATTRIBUTE Patton-Calling-Rx-Octets 96 integer |
52 | 55 | ATTRIBUTE Patton-Calling-Tx-Octets 97 integer |
53 | 56 | ATTRIBUTE Patton-Calling-Rx-Packets 98 integer |
57 | 60 | ATTRIBUTE Patton-Calling-Rx-Jitter 102 integer |
58 | 61 | ATTRIBUTE Patton-Calling-Tx-Jitter 103 integer |
59 | 62 | ATTRIBUTE Patton-Calling-Codec 104 string |
60 | ATTRIBUTE Patton-Calling-Remote-Ip 105 integer | |
61 | ATTRIBUTE Patton-Calling-Remote-Udp-Port 106 integer | |
62 | ATTRIBUTE Patton-Calling-Local-Udp-Port 107 integer | |
63 | ATTRIBUTE Patton-Calling-Remote-Ip 105 integer | |
64 | ATTRIBUTE Patton-Calling-Remote-Udp-Port 106 integer | |
65 | ATTRIBUTE Patton-Calling-Local-Udp-Port 107 integer | |
63 | 66 | ATTRIBUTE Patton-Calling-Qos 108 integer |
64 | 67 | ATTRIBUTE Patton-Calling-MOS 109 integer |
65 | 68 | ATTRIBUTE Patton-Calling-Round-Trip-Time 110 integer |
10 | 10 | |
11 | 11 | /* Define to 1 to have OpenSSL version check enabled */ |
12 | 12 | #undef ENABLE_OPENSSL_VERSION_CHECK |
13 | ||
14 | /* Define to ensure each build is the same */ | |
15 | #undef ENABLE_REPRODUCIBLE_BUILDS | |
13 | 16 | |
14 | 17 | /* Define if your processor stores words with the most significant byte first |
15 | 18 | */ |
55 | 58 | |
56 | 59 | /* Define to 1 if you have the <sys/capability.h> header file. */ |
57 | 60 | #undef HAVE_CAPABILITY_H |
61 | ||
62 | /* Define to 1 if you have the <linux/if_packet.h> header file. */ | |
63 | #undef HAVE_LINUX_IF_PACKET_H | |
58 | 64 | |
59 | 65 | /* Define to 1 if you have the `clock_gettime' function. */ |
60 | 66 | #undef HAVE_CLOCK_GETTIME |
108 | 108 | |
109 | 109 | void *fr_connection_reconnect(fr_connection_pool_t *pool, void *conn); |
110 | 110 | |
111 | int fr_connection_close(fr_connection_pool_t *pool, void *conn); | |
111 | int fr_connection_close(fr_connection_pool_t *pool, void *conn, char const *msg); | |
112 | 112 | |
113 | 113 | #ifdef __cplusplus |
114 | 114 | } |
35 | 35 | typedef struct exfile_t exfile_t; |
36 | 36 | |
37 | 37 | exfile_t *exfile_init(TALLOC_CTX *ctx, uint32_t entries, uint32_t idle, bool locking); |
38 | int exfile_open(exfile_t *lf, char const *filename, mode_t permissions, bool append); | |
38 | int exfile_open(exfile_t *lf, char const *filename, mode_t permissions); | |
39 | 39 | int exfile_close(exfile_t *lf, int fd); |
40 | int exfile_unlock(exfile_t *lf, int fd); | |
41 | 40 | |
42 | 41 | #ifdef __cplusplus |
43 | 42 | } |
43 | 43 | # define MAGIC_COMMIT(_x) ((uint32_t) 0x00000000) |
44 | 44 | #else |
45 | 45 | # ifdef RADIUSD_VERSION_COMMIT |
46 | # define RADIUSD_MAGIC_NUMBER ((uint64_t) HEXIFY4(f4, RADIUSD_VERSION, RADIUSD_VERSION_COMMIT, 0)) | |
46 | # define RADIUSD_MAGIC_NUMBER ((uint64_t) HEXIFY3(f, RADIUSD_VERSION, RADIUSD_VERSION_COMMIT)) | |
47 | 47 | # else |
48 | # define RADIUSD_MAGIC_NUMBER ((uint64_t) HEXIFY3(f4, RADIUSD_VERSION, 00000000)) | |
48 | # define RADIUSD_MAGIC_NUMBER ((uint64_t) HEXIFY3(f, RADIUSD_VERSION, 00000)) | |
49 | 49 | # endif |
50 | 50 | # define MAGIC_PREFIX(_x) ((uint8_t) (_x >> 56)) |
51 | 51 | # define MAGIC_VERSION(_x) ((uint32_t) ((_x >> 32) & 0x00ffffff)) |
713 | 713 | int fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, int af, bool resolve); |
714 | 714 | int fr_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af, |
715 | 715 | bool resolve); |
716 | int fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr); | |
716 | int fr_ntop(char *out, size_t outlen, fr_ipaddr_t const *addr); | |
717 | 717 | char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid); |
718 | 718 | uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid); |
719 | 719 | int rad_lockfd(int fd, int lock_len); |
509 | 509 | #endif |
510 | 510 | |
511 | 511 | /* |
512 | * NetBSD doesn't have O_DIRECTORY. | |
513 | */ | |
514 | #ifndef O_DIRECTORY | |
515 | #define O_DIRECTORY 0 | |
516 | #endif | |
517 | ||
518 | /* | |
512 | 519 | * Not really missing, but may be submitted as patches |
513 | 520 | * to the talloc project at some point in the future. |
514 | 521 | */ |
129 | 129 | |
130 | 130 | fr_stats_ema_t ema; |
131 | 131 | #endif |
132 | #ifdef HAVE_TRUST_ROUTER_TR_DH_H | |
133 | time_t expiration; | |
134 | #endif | |
135 | ||
132 | 136 | } home_server_t; |
133 | 137 | |
134 | 138 |
293 | 293 | void *arg); |
294 | 294 | int cbtls_verify(int ok, X509_STORE_CTX *ctx); |
295 | 295 | |
296 | /* threads.c */ | |
297 | int tls_mutexes_init(void); | |
298 | ||
296 | 299 | /* TLS */ |
297 | void tls_global_init(void); | |
300 | int tls_global_init(bool spawn_flag, bool check); | |
298 | 301 | #ifdef ENABLE_OPENSSL_VERSION_CHECK |
299 | 302 | int tls_global_version_check(char const *acknowledged); |
300 | 303 | #endif |
356 | 359 | bool disable_tlsv1_1; |
357 | 360 | bool disable_tlsv1_2; |
358 | 361 | |
362 | char const *tls_min_version; | |
363 | char const *tls_max_version; | |
364 | ||
359 | 365 | /* |
360 | 366 | * Always < 4096 (due to radius limit), 0 by default = 1024 |
361 | 367 | */ |
102 | 102 | */ |
103 | 103 | void fr_cbuff_rp_insert(fr_cbuff_t *cbuff, void *obj) |
104 | 104 | { |
105 | #ifdef HAVE_PTHREAD_H | |
106 | 105 | PTHREAD_MUTEX_LOCK(cbuff); |
107 | #endif | |
108 | 106 | |
109 | 107 | if (cbuff->elem[cbuff->in]) { |
110 | 108 | TALLOC_FREE(cbuff->elem[cbuff->in]); |
119 | 117 | cbuff->out = (cbuff->out + 1) & cbuff->size; |
120 | 118 | } |
121 | 119 | |
122 | #ifdef HAVE_PTHREAD_H | |
123 | 120 | PTHREAD_MUTEX_UNLOCK(cbuff); |
124 | #endif | |
125 | 121 | } |
126 | 122 | |
127 | 123 | /** Remove an item from the buffer, and reparent to ctx |
134 | 130 | { |
135 | 131 | void *obj = NULL; |
136 | 132 | |
137 | #ifdef HAVE_PTHREAD_H | |
138 | 133 | PTHREAD_MUTEX_LOCK(cbuff); |
139 | #endif | |
140 | 134 | |
141 | 135 | /* Buffer is empty */ |
142 | 136 | if (cbuff->out == cbuff->in) goto done; |
145 | 139 | cbuff->out = (cbuff->out + 1) & cbuff->size; |
146 | 140 | |
147 | 141 | done: |
148 | #ifdef HAVE_PTHREAD_H | |
149 | 142 | PTHREAD_MUTEX_UNLOCK(cbuff); |
150 | #endif | |
151 | 143 | return obj; |
152 | 144 | } |
43 | 43 | |
44 | 44 | #ifdef HAVE_SYS_PTRACE_H |
45 | 45 | # include <sys/ptrace.h> |
46 | # if !defined(PTRACE_ATTACH) && defined(PT_ATTACH) | |
47 | # define PTRACE_ATTACH PT_ATTACH | |
46 | # if !defined(PT_ATTACH) && defined(PTRACE_ATTACH) | |
47 | # define PT_ATTACH PTRACE_ATTACH | |
48 | 48 | # endif |
49 | # if !defined(PTRACE_DETACH) && defined(PT_DETACH) | |
50 | # define PTRACE_DETACH PT_DETACH | |
49 | # if !defined(PT_DETACH) && defined(PTRACE_DETACH) | |
50 | # define PT_DETACH PTRACE_DETACH | |
51 | 51 | # endif |
52 | 52 | #endif |
53 | 53 | |
195 | 195 | * If we don't do it in that order the read in the parent triggers |
196 | 196 | * a SIGKILL. |
197 | 197 | */ |
198 | if (_PTRACE(PTRACE_ATTACH, ppid) == 0) { | |
198 | if (_PTRACE(PT_ATTACH, ppid) == 0) { | |
199 | 199 | /* Wait for the parent to stop */ |
200 | 200 | waitpid(ppid, NULL, 0); |
201 | 201 | |
205 | 205 | } |
206 | 206 | |
207 | 207 | /* Detach */ |
208 | _PTRACE(PTRACE_DETACH, ppid); | |
208 | _PTRACE(PT_DETACH, ppid); | |
209 | 209 | exit(0); |
210 | 210 | } |
211 | 211 |
41 | 41 | * |
42 | 42 | * Non-POSIX macros may be added, but you must check they're defined. |
43 | 43 | */ |
44 | char const *fr_errno_macro_names[] = { | |
44 | static char const *fr_errno_macro_names[] = { | |
45 | 45 | [E2BIG] = "E2BIG", |
46 | 46 | [EACCES] = "EACCES", |
47 | 47 | [EADDRINUSE] = "EADDRINUSE", |
78 | 78 | * @param sig to set handler for. |
79 | 79 | * @param func handler to set. |
80 | 80 | */ |
81 | DIAG_OPTIONAL | |
82 | DIAG_OFF(disabled-macro-expansion) | |
81 | 83 | int fr_set_signal(int sig, sig_t func) |
82 | 84 | { |
83 | 85 | #ifdef HAVE_SIGACTION |
100 | 102 | #endif |
101 | 103 | return 0; |
102 | 104 | } |
105 | DIAG_ON(disabled-macro-expansion) | |
103 | 106 | |
104 | 107 | /** Uninstall a signal for a specific handler |
105 | 108 | * |
107 | 110 | * |
108 | 111 | * @param sig SIGNAL |
109 | 112 | */ |
113 | DIAG_OPTIONAL | |
114 | DIAG_OFF(disabled-macro-expansion) | |
110 | 115 | int fr_unset_signal(int sig) |
111 | 116 | { |
112 | 117 | #ifdef HAVE_SIGACTION |
122 | 127 | return signal(sig, SIG_DFL); |
123 | 128 | #endif |
124 | 129 | } |
130 | DIAG_ON(disabled-macro-expansion) | |
125 | 131 | |
126 | 132 | static int _fr_trigger_talloc_ctx_free(fr_talloc_link_t *trigger) |
127 | 133 | { |
646 | 652 | return 0; |
647 | 653 | } |
648 | 654 | |
649 | int fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr) | |
655 | int fr_ntop(char *out, size_t outlen, fr_ipaddr_t const *addr) | |
650 | 656 | { |
651 | 657 | char buffer[INET6_ADDRSTRLEN]; |
652 | 658 |
335 | 335 | freespace = 0; |
336 | 336 | |
337 | 337 | } else if (freespace > utf8) { /* room for char AND trailing zero */ |
338 | memcpy(out + used, p, utf8); | |
338 | if (out) memcpy(out + used, p, utf8); | |
339 | 339 | freespace -= utf8; |
340 | 340 | } |
341 | 341 |
3353 | 3353 | * No continued data, just decode the attribute in place. |
3354 | 3354 | */ |
3355 | 3355 | if ((data[6] & 0x80) == 0) { |
3356 | if ((data[5] + 4) != attrlen) goto raw; /* WiMAX attribute doesn't fill Vendor-Specific */ | |
3356 | if (((size_t) (data[5] + 4)) != attrlen) goto raw; /* WiMAX attribute doesn't fill Vendor-Specific */ | |
3357 | 3357 | |
3358 | 3358 | rcode = data2vp(ctx, packet, original, secret, child, |
3359 | 3359 | data + 7, data[5] - 3, data[5] - 3, |
1250 | 1250 | } |
1251 | 1251 | } |
1252 | 1252 | |
1253 | # We want interface descriptions | |
1254 | $oid = "ifDescr"; | |
1253 | # We want mtxrInterfaceStatsName from MIKROTIK-MIB | |
1254 | $oid = "1.3.6.1.4.1.14988.1.1.14.1.1.2"; | |
1255 | 1255 | |
1256 | 1256 | # Mikrotik doesnt give port IDs correctly to RADIUS :( |
1257 | 1257 | # practically this would limit us to a simple only-one user limit for |
748 | 748 | c->created = time(NULL); |
749 | 749 | c->longname = talloc_typed_strdup(c, c->shortname); |
750 | 750 | |
751 | INFO("Adding client %s/%i with shared secret \"%s\"", | |
752 | ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->secret); | |
753 | ||
751 | if (rad_debug_lvl <= 2) { | |
752 | INFO("Adding client %s/%i", | |
753 | ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix); | |
754 | } else { | |
755 | INFO("Adding client %s/%i with shared secret \"%s\"", | |
756 | ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->secret); | |
757 | } | |
754 | 758 | return true; |
755 | 759 | |
756 | 760 | error: |
1164 | 1168 | { |
1165 | 1169 | RADCLIENT *c; |
1166 | 1170 | char buffer[128]; |
1167 | ||
1168 | rad_assert(identifier); | |
1169 | rad_assert(secret); | |
1170 | 1171 | |
1171 | 1172 | c = talloc_zero(ctx, RADCLIENT); |
1172 | 1173 | |
1353 | 1354 | for (parse = client_config; parse->name; parse++) { |
1354 | 1355 | if (parse->offset == dynamic_config[i].offset) break; |
1355 | 1356 | } |
1356 | rad_assert(parse); | |
1357 | ||
1358 | if (!parse) break; | |
1357 | 1359 | |
1358 | 1360 | cp = cf_pair_alloc(c->cs, parse->name, strvalue, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING); |
1359 | 1361 | } |
1372 | 1374 | for (parse = client_config; parse->name; parse++) { |
1373 | 1375 | if (parse->offset == dynamic_config[i].offset) break; |
1374 | 1376 | } |
1375 | rad_assert(parse); | |
1377 | if (!parse) break; | |
1376 | 1378 | |
1377 | 1379 | cp = cf_pair_alloc(c->cs, parse->name, strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD); |
1378 | 1380 | } |
1435 | 1435 | * |
1436 | 1436 | * @param[in,out] pool Connection pool to modify. |
1437 | 1437 | * @param[in] conn to delete. |
1438 | * @param[in] msg why the connection was closed. | |
1438 | 1439 | * @return |
1439 | 1440 | * - 0 If the connection could not be found. |
1440 | 1441 | * - 1 if the connection was deleted. |
1441 | 1442 | */ |
1442 | int fr_connection_close(fr_connection_pool_t *pool, void *conn) | |
1443 | int fr_connection_close(fr_connection_pool_t *pool, void *conn, char const *msg) | |
1443 | 1444 | { |
1444 | 1445 | fr_connection_t *this; |
1445 | 1446 | |
1446 | 1447 | this = fr_connection_find(pool, conn); |
1447 | 1448 | if (!this) return 0; |
1448 | 1449 | |
1449 | INFO("%s: Deleting connection (%" PRIu64 ")", pool->log_prefix, this->number); | |
1450 | if (!msg) { | |
1451 | INFO("%s: Deleting connection (%" PRIu64 ")", pool->log_prefix, this->number); | |
1452 | } else { | |
1453 | INFO("%s: Deleting connection (%" PRIu64 ") - %s", pool->log_prefix, this->number, msg); | |
1454 | } | |
1450 | 1455 | |
1451 | 1456 | fr_connection_close_internal(pool, this); |
1452 | 1457 | fr_connection_pool_check(pool); |
30 | 30 | |
31 | 31 | typedef struct exfile_entry_t { |
32 | 32 | int fd; //!< File descriptor associated with an entry. |
33 | int dup; | |
34 | 33 | uint32_t hash; //!< Hash for cheap comparison. |
35 | 34 | time_t last_used; //!< Last time the entry was used. |
36 | 35 | char *filename; //!< Filename. |
102 | 101 | ef = talloc_zero(ctx, exfile_t); |
103 | 102 | if (!ef) return NULL; |
104 | 103 | |
104 | ef->max_entries = max_entries; | |
105 | ef->max_idle = max_idle; | |
106 | ef->locking = locking; | |
107 | ||
108 | /* | |
109 | * If we're not locking the files, just return the | |
110 | * handle. Each call to exfile_open() will just open a | |
111 | * new file descriptor. | |
112 | */ | |
113 | if (!locking) return ef; | |
114 | ||
105 | 115 | ef->entries = talloc_zero_array(ef, exfile_entry_t, max_entries); |
106 | 116 | if (!ef->entries) { |
107 | 117 | talloc_free(ef); |
115 | 125 | } |
116 | 126 | #endif |
117 | 127 | |
118 | ef->max_entries = max_entries; | |
119 | ef->max_idle = max_idle; | |
120 | ef->locking = locking; | |
121 | ||
122 | 128 | talloc_set_destructor(ef, _exfile_free); |
123 | 129 | |
124 | 130 | return ef; |
129 | 135 | { |
130 | 136 | TALLOC_FREE(entry->filename); |
131 | 137 | |
132 | close(entry->fd); | |
138 | if (entry->fd >= 0) close(entry->fd); | |
133 | 139 | entry->hash = 0; |
134 | 140 | entry->fd = -1; |
135 | entry->dup = -1; | |
136 | } | |
141 | } | |
142 | ||
143 | ||
144 | /* | |
145 | * Try to open the file. It it doesn't exist, try to | |
146 | * create it's parent directories. | |
147 | */ | |
148 | static int exfile_open_mkdir(exfile_t *ef, char const *filename, mode_t permissions) | |
149 | { | |
150 | int fd; | |
151 | ||
152 | fd = open(filename, O_RDWR | O_CREAT, permissions); | |
153 | if (fd < 0) { | |
154 | mode_t dirperm; | |
155 | char *p, *dir; | |
156 | ||
157 | /* | |
158 | * Maybe the directory doesn't exist. Try to | |
159 | * create it. | |
160 | */ | |
161 | dir = talloc_strdup(ef, filename); | |
162 | if (!dir) return -1; | |
163 | p = strrchr(dir, FR_DIR_SEP); | |
164 | if (!p) { | |
165 | fr_strerror_printf("No '/' in '%s'", filename); | |
166 | return -1; | |
167 | } | |
168 | *p = '\0'; | |
169 | ||
170 | /* | |
171 | * Ensure that the 'x' bit is set, so that we can | |
172 | * read the directory. | |
173 | */ | |
174 | dirperm = permissions; | |
175 | if ((dirperm & 0600) != 0) dirperm |= 0100; | |
176 | if ((dirperm & 0060) != 0) dirperm |= 0010; | |
177 | if ((dirperm & 0006) != 0) dirperm |= 0001; | |
178 | ||
179 | if (rad_mkdir(dir, dirperm, -1, -1) < 0) { | |
180 | fr_strerror_printf("Failed to create directory %s: %s", | |
181 | dir, strerror(errno)); | |
182 | talloc_free(dir); | |
183 | return -1; | |
184 | } | |
185 | talloc_free(dir); | |
186 | ||
187 | fd = open(filename, O_RDWR | O_CREAT, permissions); | |
188 | if (fd < 0) { | |
189 | fr_strerror_printf("Failed to open file %s: %s", | |
190 | filename, strerror(errno)); | |
191 | return -1; | |
192 | } | |
193 | } | |
194 | ||
195 | return fd; | |
196 | } | |
197 | ||
137 | 198 | |
138 | 199 | /** Open a new log file, or maybe an existing one. |
139 | 200 | * |
143 | 204 | * @param ef The logfile context returned from exfile_init(). |
144 | 205 | * @param filename the file to open. |
145 | 206 | * @param permissions to use. |
146 | * @param append If true seek to the end of the file. | |
147 | 207 | * @return an FD used to write to the file, or -1 on error. |
148 | 208 | */ |
149 | int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, bool append) | |
150 | { | |
151 | int i, tries, unused, oldest; | |
209 | int exfile_open(exfile_t *ef, char const *filename, mode_t permissions) | |
210 | { | |
211 | int i, found, tries, unused, oldest; | |
152 | 212 | uint32_t hash; |
153 | time_t now = time(NULL); | |
213 | time_t now; | |
154 | 214 | struct stat st; |
155 | 215 | |
156 | 216 | if (!ef || !filename) return -1; |
157 | 217 | |
218 | /* | |
219 | * No locking: just return a new FD. | |
220 | */ | |
221 | if (!ef->locking) { | |
222 | found = exfile_open_mkdir(ef, filename, permissions); | |
223 | if (found < 0) return -1; | |
224 | ||
225 | (void) lseek(found, 0, SEEK_END); | |
226 | return found; | |
227 | } | |
228 | ||
229 | /* | |
230 | * It's faster to do hash comparisons of a string than | |
231 | * full string comparisons. | |
232 | */ | |
158 | 233 | hash = fr_hash_string(filename); |
159 | unused = -1; | |
234 | now = time(NULL); | |
160 | 235 | |
161 | 236 | PTHREAD_MUTEX_LOCK(&ef->mutex); |
162 | 237 | |
185 | 260 | * Also track which entry is the oldest, in case there |
186 | 261 | * are no unused entries. |
187 | 262 | */ |
188 | oldest = -1; | |
263 | found = oldest = unused = -1; | |
189 | 264 | for (i = 0; i < (int) ef->max_entries; i++) { |
190 | 265 | if (!ef->entries[i].filename) { |
191 | 266 | if (unused < 0) unused = i; |
211 | 286 | */ |
212 | 287 | if (strcmp(ef->entries[i].filename, filename) != 0) continue; |
213 | 288 | |
214 | goto do_return; | |
215 | } | |
216 | ||
217 | /* | |
218 | * There are no unused entries, free the oldest one. | |
219 | */ | |
220 | if (unused < 0) { | |
221 | exfile_cleanup_entry(&ef->entries[oldest]); | |
222 | unused = oldest; | |
223 | } | |
224 | ||
225 | /* | |
226 | * Create a new entry. | |
227 | */ | |
228 | i = unused; | |
229 | ||
230 | ef->entries[i].hash = hash; | |
231 | ef->entries[i].filename = talloc_strdup(ef->entries, filename); | |
232 | ef->entries[i].fd = -1; | |
233 | ef->entries[i].dup = -1; | |
234 | ||
235 | ef->entries[i].fd = open(filename, O_RDWR | O_APPEND | O_CREAT, permissions); | |
236 | if (ef->entries[i].fd < 0) { | |
237 | mode_t dirperm; | |
238 | char *p, *dir; | |
239 | ||
240 | /* | |
241 | * Maybe the directory doesn't exist. Try to | |
242 | * create it. | |
243 | */ | |
244 | dir = talloc_strdup(ef, filename); | |
245 | if (!dir) goto error; | |
246 | p = strrchr(dir, FR_DIR_SEP); | |
247 | if (!p) { | |
248 | fr_strerror_printf("No '/' in '%s'", filename); | |
289 | found = i; | |
290 | break; | |
291 | } | |
292 | ||
293 | /* | |
294 | * If it wasn't found, create a new entry. | |
295 | */ | |
296 | if (found < 0) { | |
297 | /* | |
298 | * There are no unused entries. Clean up the | |
299 | * oldest one. | |
300 | */ | |
301 | if (unused < 0) { | |
302 | exfile_cleanup_entry(&ef->entries[oldest]); | |
303 | unused = oldest; | |
304 | } | |
305 | ||
306 | /* | |
307 | * Create a new entry. | |
308 | */ | |
309 | i = unused; | |
310 | ||
311 | ef->entries[i].hash = hash; | |
312 | ef->entries[i].filename = talloc_strdup(ef->entries, filename); | |
313 | ef->entries[i].fd = -1; | |
314 | ||
315 | /* | |
316 | * We've just created the entry. Open the file | |
317 | * and cache the FD. | |
318 | */ | |
319 | reopen: | |
320 | ef->entries[i].fd = exfile_open_mkdir(ef, filename, permissions); | |
321 | if (ef->entries[i].fd < 0) { | |
322 | error: | |
323 | exfile_cleanup_entry(&ef->entries[i]); | |
324 | PTHREAD_MUTEX_UNLOCK(&(ef->mutex)); | |
325 | return -1; | |
326 | } | |
327 | } else { | |
328 | i = found; | |
329 | } | |
330 | ||
331 | /* | |
332 | * Try to lock it. If we can't lock it, it's because | |
333 | * some reader has re-named the file to "foo.work" and | |
334 | * locked it. So, we close the current file, re-open it, | |
335 | * and try again. | |
336 | */ | |
337 | ||
338 | /* | |
339 | * Lock from the start of the file. It's the | |
340 | * only point in the file which is guaranteed to | |
341 | * exist, and to be consistent across all threads | |
342 | * and processes. | |
343 | */ | |
344 | if (lseek(ef->entries[i].fd, 0, SEEK_SET) < 0) { | |
345 | fr_strerror_printf("Failed to seek in file %s: %s", filename, strerror(errno)); | |
346 | goto error; | |
347 | } | |
348 | ||
349 | /* | |
350 | * Busy-loop trying to lock the file. | |
351 | */ | |
352 | for (tries = 0; tries < MAX_TRY_LOCK; tries++) { | |
353 | if (rad_lockfd_nonblock(ef->entries[i].fd, 0) >= 0) break; | |
354 | ||
355 | if (errno != EAGAIN) { | |
356 | fr_strerror_printf("Failed to lock file %s: %s", filename, strerror(errno)); | |
249 | 357 | goto error; |
250 | 358 | } |
251 | *p = '\0'; | |
252 | ||
253 | /* | |
254 | * Ensure that the 'x' bit is set, so that we can | |
255 | * read the directory. | |
256 | */ | |
257 | dirperm = permissions; | |
258 | if ((dirperm & 0600) != 0) dirperm |= 0100; | |
259 | if ((dirperm & 0060) != 0) dirperm |= 0010; | |
260 | if ((dirperm & 0006) != 0) dirperm |= 0001; | |
261 | ||
262 | if (rad_mkdir(dir, dirperm, -1, -1) < 0) { | |
263 | fr_strerror_printf("Failed to create directory %s: %s", | |
264 | dir, strerror(errno)); | |
265 | talloc_free(dir); | |
266 | goto error; | |
267 | } | |
268 | talloc_free(dir); | |
269 | ||
270 | ef->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions); | |
359 | ||
360 | /* | |
361 | * Close the file and re-open it. It may | |
362 | * have been deleted. If it was deleted, | |
363 | * then the new file should now be unlocked. | |
364 | */ | |
365 | close(ef->entries[i].fd); | |
366 | ef->entries[i].fd = open(filename, O_RDWR | O_CREAT, permissions); | |
271 | 367 | if (ef->entries[i].fd < 0) { |
272 | 368 | fr_strerror_printf("Failed to open file %s: %s", |
273 | 369 | filename, strerror(errno)); |
274 | 370 | goto error; |
275 | } /* else fall through to creating the rest of the entry */ | |
276 | } /* else the file was already opened */ | |
277 | ||
278 | do_return: | |
279 | /* | |
280 | * Lock from the start of the file. | |
281 | */ | |
282 | if (lseek(ef->entries[i].fd, 0, SEEK_SET) < 0) { | |
283 | fr_strerror_printf("Failed to seek in file %s: %s", filename, strerror(errno)); | |
284 | ||
285 | error: | |
286 | exfile_cleanup_entry(&ef->entries[i]); | |
287 | ||
288 | PTHREAD_MUTEX_UNLOCK(&(ef->mutex)); | |
289 | return -1; | |
290 | } | |
291 | ||
292 | /* | |
293 | * Try to lock it. If we can't lock it, it's because | |
294 | * some reader has re-named the file to "foo.work" and | |
295 | * locked it. So, we close the current file, re-open it, | |
296 | * and try again. | |
297 | */ | |
298 | if (ef->locking) { | |
299 | for (tries = 0; tries < MAX_TRY_LOCK; tries++) { | |
300 | if (rad_lockfd_nonblock(ef->entries[i].fd, 0) >= 0) break; | |
301 | ||
302 | if (errno != EAGAIN) { | |
303 | fr_strerror_printf("Failed to lock file %s: %s", filename, strerror(errno)); | |
304 | goto error; | |
305 | } | |
306 | ||
307 | close(ef->entries[i].fd); | |
308 | ef->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions); | |
309 | if (ef->entries[i].fd < 0) { | |
310 | fr_strerror_printf("Failed to open file %s: %s", | |
311 | filename, strerror(errno)); | |
312 | goto error; | |
313 | } | |
314 | } | |
315 | ||
316 | if (tries >= MAX_TRY_LOCK) { | |
317 | fr_strerror_printf("Failed to lock file %s: too many tries", filename); | |
318 | goto error; | |
319 | } | |
371 | } | |
372 | } | |
373 | ||
374 | if (tries >= MAX_TRY_LOCK) { | |
375 | fr_strerror_printf("Failed to lock file %s: too many tries", filename); | |
376 | goto error; | |
320 | 377 | } |
321 | 378 | |
322 | 379 | /* |
328 | 385 | goto error; |
329 | 386 | } |
330 | 387 | |
388 | /* | |
389 | * It's unlinked from the file system, close the FD and | |
390 | * try to re-open it. | |
391 | */ | |
331 | 392 | if (st.st_nlink == 0) { |
332 | 393 | close(ef->entries[i].fd); |
333 | ef->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions); | |
334 | if (ef->entries[i].fd < 0) { | |
335 | fr_strerror_printf("Failed to open file %s: %s", | |
336 | filename, strerror(errno)); | |
337 | goto error; | |
338 | } | |
339 | } | |
340 | ||
341 | /* | |
342 | * Seek to the end of the file before returning the FD to | |
343 | * the caller. | |
344 | */ | |
345 | if (append) lseek(ef->entries[i].fd, 0, SEEK_END); | |
394 | goto reopen; | |
395 | } | |
396 | ||
397 | /* | |
398 | * If we're appending, eek to the end of the file before | |
399 | * returning the FD to the caller. | |
400 | */ | |
401 | (void) lseek(ef->entries[i].fd, 0, SEEK_END); | |
346 | 402 | |
347 | 403 | /* |
348 | 404 | * Return holding the mutex for the entry. |
349 | 405 | */ |
350 | 406 | ef->entries[i].last_used = now; |
351 | ef->entries[i].dup = dup(ef->entries[i].fd); | |
352 | if (ef->entries[i].dup < 0) { | |
353 | fr_strerror_printf("Failed calling dup(): %s", strerror(errno)); | |
354 | goto error; | |
355 | } | |
356 | ||
357 | return ef->entries[i].dup; | |
407 | ||
408 | return ef->entries[i].fd; | |
358 | 409 | } |
359 | 410 | |
360 | 411 | /** Close the log file. Really just return it to the pool. |
371 | 422 | { |
372 | 423 | uint32_t i; |
373 | 424 | |
425 | /* | |
426 | * No locking: just close the file. | |
427 | */ | |
428 | if (!ef->locking) { | |
429 | close(fd); | |
430 | return 0; | |
431 | } | |
432 | ||
433 | /* | |
434 | * Unlock the bytes that we had previously locked. | |
435 | */ | |
374 | 436 | for (i = 0; i < ef->max_entries; i++) { |
375 | if (!ef->entries[i].filename) continue; | |
376 | ||
377 | /* | |
378 | * Unlock the bytes that we had previously locked. | |
379 | */ | |
380 | if (ef->entries[i].dup == fd) { | |
381 | if (ef->locking) (void) rad_unlockfd(ef->entries[i].dup, 0); | |
382 | close(ef->entries[i].dup); /* releases the fcntl lock */ | |
383 | ef->entries[i].dup = -1; | |
437 | if (ef->entries[i].fd == fd) { | |
438 | (void) lseek(ef->entries[i].fd, 0, SEEK_SET); | |
439 | (void) rad_unlockfd(ef->entries[i].fd, 0); | |
384 | 440 | |
385 | 441 | PTHREAD_MUTEX_UNLOCK(&(ef->mutex)); |
386 | 442 | return 0; |
392 | 448 | fr_strerror_printf("Attempt to unlock file which is not tracked"); |
393 | 449 | return -1; |
394 | 450 | } |
395 | ||
396 | int exfile_unlock(exfile_t *ef, int fd) | |
397 | { | |
398 | uint32_t i; | |
399 | ||
400 | for (i = 0; i < ef->max_entries; i++) { | |
401 | if (!ef->entries[i].filename) continue; | |
402 | ||
403 | if (ef->entries[i].dup == fd) { | |
404 | ef->entries[i].dup = -1; | |
405 | PTHREAD_MUTEX_UNLOCK(&(ef->mutex)); | |
406 | return 0; | |
407 | } | |
408 | } | |
409 | ||
410 | PTHREAD_MUTEX_UNLOCK(&(ef->mutex)); | |
411 | ||
412 | fr_strerror_printf("Attempt to unlock file which does not exist"); | |
413 | return -1; | |
414 | } |
629 | 629 | uint8_t indent; |
630 | 630 | va_list aq; |
631 | 631 | |
632 | rad_assert(request); | |
633 | ||
634 | 632 | /* |
635 | 633 | * Debug messages get treated specially. |
636 | 634 | */ |
781 | 779 | { |
782 | 780 | va_list ap; |
783 | 781 | |
784 | rad_assert(request); | |
785 | ||
786 | 782 | if (!request->log.func && !(type & L_DBG)) return; |
787 | 783 | |
788 | 784 | va_start(ap, msg); |
810 | 806 | void radlog_request_error(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...) |
811 | 807 | { |
812 | 808 | va_list ap; |
813 | ||
814 | rad_assert(request); | |
815 | 809 | |
816 | 810 | va_start(ap, msg); |
817 | 811 | if (request->log.func) request->log.func(type, lvl, request, msg, ap); |
835 | 829 | char const *prefix = ""; |
836 | 830 | uint8_t indent; |
837 | 831 | |
838 | rad_assert(request); | |
839 | ||
840 | 832 | if (idx >= sizeof(spaces)) { |
841 | 833 | size_t offset = (idx - (sizeof(spaces) - 1)) + (sizeof(spaces) * 0.75); |
842 | 834 | idx -= offset; |
3478 | 3478 | |
3479 | 3479 | if (!radius_find_compare(map->lhs->tmpl_da)) return true; |
3480 | 3480 | |
3481 | if (map->rhs->type == TMPL_TYPE_ATTR) { | |
3482 | cf_log_err(map->ci, "Cannot compare virtual attribute %s to another attribute", | |
3483 | map->lhs->name); | |
3484 | return false; | |
3485 | } | |
3486 | ||
3487 | 3481 | if (map->rhs->type == TMPL_TYPE_REGEX) { |
3488 | 3482 | cf_log_err(map->ci, "Cannot compare virtual attribute %s via a regex", |
3489 | 3483 | map->lhs->name); |
1195 | 1195 | * and do no parsing until after all of the modules |
1196 | 1196 | * are loaded. But that has issues, too. |
1197 | 1197 | */ |
1198 | if ((c->data.map->lhs->type == TMPL_TYPE_LITERAL) && | |
1199 | (lhs_type == T_BARE_WORD) && | |
1200 | (c->data.map->rhs->type == TMPL_TYPE_LITERAL)) { | |
1198 | if ((c->data.map->lhs->type == TMPL_TYPE_LITERAL) && (lhs_type == T_BARE_WORD)) { | |
1201 | 1199 | int hyphens = 0; |
1202 | 1200 | bool may_be_attr = true; |
1203 | 1201 | size_t i; |
365 | 365 | static void remove_from_proxy_hash(REQUEST *request) CC_HINT(nonnull); |
366 | 366 | static void remove_from_proxy_hash_nl(REQUEST *request, bool yank) CC_HINT(nonnull); |
367 | 367 | static int insert_into_proxy_hash(REQUEST *request) CC_HINT(nonnull); |
368 | static int setup_post_proxy_fail(REQUEST *request); | |
368 | 369 | #endif |
369 | 370 | |
370 | 371 | static REQUEST *request_setup(TALLOC_CTX *ctx, rad_listen_t *listener, RADIUS_PACKET *packet, |
1538 | 1539 | /* |
1539 | 1540 | * We may need to send a proxied request. |
1540 | 1541 | */ |
1541 | if ((action == FR_ACTION_RUN) && | |
1542 | request_will_proxy(request)) { | |
1542 | if (request_will_proxy(request)) { | |
1543 | 1543 | #ifdef DEBUG_STATE_MACHINE |
1544 | 1544 | if (rad_debug_lvl) printf("(%u) ********\tWill Proxy\t********\n", request->number); |
1545 | 1545 | #endif |
1549 | 1549 | * up the post proxy fail |
1550 | 1550 | * handler. |
1551 | 1551 | */ |
1552 | if (request_proxy(request) < 0) goto req_finished; | |
1552 | if (request_proxy(request) < 0) { | |
1553 | (void) setup_post_proxy_fail(request); | |
1554 | process_proxy_reply(request, NULL); | |
1555 | goto req_finished; | |
1556 | } | |
1553 | 1557 | } else |
1554 | 1558 | #endif |
1555 | 1559 | { |
2286 | 2290 | /* |
2287 | 2291 | * There may be a proxy reply, but it may be too late. |
2288 | 2292 | */ |
2289 | if (!request->home_server->server && !request->proxy_listener) return 0; | |
2293 | if ((request->home_server && !request->home_server->server) && !request->proxy_listener) return 0; | |
2290 | 2294 | |
2291 | 2295 | /* |
2292 | 2296 | * Delete any reply we had accumulated until now. |
2385 | 2389 | } |
2386 | 2390 | |
2387 | 2391 | #ifdef WITH_COA |
2388 | if (request->packet->code == request->proxy->code) { | |
2392 | if (request->proxy && request->packet->code == request->proxy->code) { | |
2389 | 2393 | /* |
2390 | 2394 | * Don't run the next bit if we originated a CoA |
2391 | 2395 | * packet, after receiving an Access-Request or |
2618 | 2622 | { |
2619 | 2623 | DICT_VALUE const *dval = NULL; |
2620 | 2624 | VALUE_PAIR *vp; |
2625 | RADIUS_PACKET *packet; | |
2621 | 2626 | |
2622 | 2627 | VERIFY_REQUEST(request); |
2623 | 2628 | |
2624 | if (request->proxy->code == PW_CODE_ACCESS_REQUEST) { | |
2629 | packet = request->proxy ? request->proxy : request->packet; | |
2630 | ||
2631 | if (packet->code == PW_CODE_ACCESS_REQUEST) { | |
2625 | 2632 | dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, |
2626 | 2633 | "Fail-Authentication"); |
2627 | 2634 | #ifdef WITH_ACCOUNTING |
2628 | } else if (request->proxy->code == PW_CODE_ACCOUNTING_REQUEST) { | |
2635 | } else if (packet->code == PW_CODE_ACCOUNTING_REQUEST) { | |
2629 | 2636 | dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, |
2630 | 2637 | "Fail-Accounting"); |
2631 | 2638 | #endif |
2632 | 2639 | |
2633 | 2640 | #ifdef WITH_COA |
2634 | } else if (request->proxy->code == PW_CODE_COA_REQUEST) { | |
2641 | } else if (packet->code == PW_CODE_COA_REQUEST) { | |
2635 | 2642 | dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail-CoA"); |
2636 | 2643 | |
2637 | } else if (request->proxy->code == PW_CODE_DISCONNECT_REQUEST) { | |
2644 | } else if (packet->code == PW_CODE_DISCONNECT_REQUEST) { | |
2638 | 2645 | dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail-Disconnect"); |
2639 | 2646 | #endif |
2640 | 2647 | } else { |
2816 | 2823 | * Figure out which pool to use. |
2817 | 2824 | */ |
2818 | 2825 | if (request->packet->code == PW_CODE_ACCESS_REQUEST) { |
2826 | DEBUG3("Using home pool auth for realm %s", realm->name); | |
2819 | 2827 | pool = realm->auth_pool; |
2820 | 2828 | |
2821 | 2829 | #ifdef WITH_ACCOUNTING |
2822 | 2830 | } else if (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) { |
2831 | DEBUG3("Using home pool acct for realm %s", realm->name); | |
2823 | 2832 | pool = realm->acct_pool; |
2824 | 2833 | #endif |
2825 | 2834 | |
2826 | 2835 | #ifdef WITH_COA |
2827 | 2836 | } else if ((request->packet->code == PW_CODE_COA_REQUEST) || |
2828 | 2837 | (request->packet->code == PW_CODE_DISCONNECT_REQUEST)) { |
2838 | DEBUG3("Using home pool coa for realm %s", realm->name); | |
2829 | 2839 | pool = realm->coa_pool; |
2830 | 2840 | #endif |
2831 | 2841 | |
2835 | 2845 | |
2836 | 2846 | } else if ((vp = fr_pair_find_by_num(request->config, PW_HOME_SERVER_POOL, 0, TAG_ANY)) != NULL) { |
2837 | 2847 | int pool_type; |
2848 | ||
2849 | DEBUG3("Using Home-Server-Pool %s", vp->vp_strvalue); | |
2838 | 2850 | |
2839 | 2851 | switch (request->packet->code) { |
2840 | 2852 | case PW_CODE_ACCESS_REQUEST: |
2910 | 2922 | if (!home) { |
2911 | 2923 | char buffer[256]; |
2912 | 2924 | |
2913 | WARN("No such home server %s port %u", | |
2914 | inet_ntop(dst_ipaddr.af, &dst_ipaddr.ipaddr, buffer, sizeof(buffer)), | |
2915 | (unsigned int) dst_port); | |
2925 | RWDEBUG("No such home server %s port %u", | |
2926 | inet_ntop(dst_ipaddr.af, &dst_ipaddr.ipaddr, buffer, sizeof(buffer)), | |
2927 | (unsigned int) dst_port); | |
2916 | 2928 | return 0; |
2917 | 2929 | } |
2918 | 2930 | |
2950 | 2962 | |
2951 | 2963 | if (!home) { |
2952 | 2964 | REDEBUG2("Failed to find live home server: Cancelling proxy"); |
2953 | return 0; | |
2965 | return 1; | |
2954 | 2966 | } |
2955 | 2967 | |
2956 | 2968 | do_home: |
3166 | 3178 | VERIFY_REQUEST(request); |
3167 | 3179 | |
3168 | 3180 | rad_assert(request->parent == NULL); |
3169 | rad_assert(request->home_server != NULL); | |
3170 | 3181 | |
3171 | 3182 | if (request->master_state == REQUEST_STOP_PROCESSING) return 0; |
3172 | 3183 | |
3176 | 3187 | request_done(request->coa, FR_ACTION_DONE); |
3177 | 3188 | } |
3178 | 3189 | #endif |
3190 | ||
3191 | if (!request->home_server) { | |
3192 | RWDEBUG("No home server selected"); | |
3193 | return -1; | |
3194 | } | |
3179 | 3195 | |
3180 | 3196 | /* |
3181 | 3197 | * The request may need sending to a virtual server. |
43 | 43 | extern log_lvl_t rad_debug_lvl; |
44 | 44 | |
45 | 45 | #include <sys/wait.h> |
46 | #ifdef HAVE_PTHREAD_H | |
46 | 47 | pid_t rad_fork(void); |
47 | 48 | pid_t rad_waitpid(pid_t pid, int *status); |
48 | 49 | |
55 | 56 | { |
56 | 57 | return waitpid(pid, status, 0); |
57 | 58 | } |
59 | #endif | |
58 | 60 | |
59 | 61 | static ssize_t xlat_test(UNUSED void *instance, UNUSED REQUEST *request, |
60 | 62 | UNUSED char const *fmt, UNUSED char *out, UNUSED size_t outlen) |
0 | 0 | TARGET := radattr |
1 | 1 | SOURCES := radattr.c |
2 | 2 | |
3 | TGT_PREREQS := libfreeradius-server.a libfreeradius-radius.a libfreeradius-dhcp.a | |
3 | TGT_PREREQS := libfreeradius-server.a libfreeradius-radius.a | |
4 | ||
5 | ifneq "$(WITH_DHCP)" "no" | |
6 | TGT_PREREQS += libfreeradius-dhcp.a | |
7 | endif | |
8 | ||
4 | 9 | TGT_LDLIBS := $(LIBS) |
76 | 76 | #ifdef RADIUSD_VERSION_COMMIT |
77 | 77 | " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")" |
78 | 78 | #endif |
79 | ", built on " __DATE__ " at " __TIME__; | |
79 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
80 | ", built on " __DATE__ " at " __TIME__ | |
81 | #endif | |
82 | ; | |
80 | 83 | |
81 | 84 | static void NEVER_RETURNS usage(void) |
82 | 85 | { |
62 | 62 | #ifdef RADIUSD_VERSION_COMMIT |
63 | 63 | " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")" |
64 | 64 | #endif |
65 | ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__; | |
65 | ", for host " HOSTINFO | |
66 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
67 | ", built on " __DATE__ " at " __TIME__ | |
68 | #endif | |
69 | ; | |
66 | 70 | |
67 | 71 | static pid_t radius_pid; |
68 | 72 | |
332 | 336 | * Initialising OpenSSL once, here, is safer than having individual modules do it. |
333 | 337 | */ |
334 | 338 | #ifdef HAVE_OPENSSL_CRYPTO_H |
335 | tls_global_init(); | |
339 | if (tls_global_init(spawn_flag, check_config) < 0) exit(EXIT_FAILURE); | |
336 | 340 | #endif |
337 | 341 | |
338 | 342 | /* |
69 | 69 | #ifdef RADIUSD_VERSION_COMMIT |
70 | 70 | " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")" |
71 | 71 | #endif |
72 | ", built on " __DATE__ " at " __TIME__; | |
72 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
73 | ", built on " __DATE__ " at " __TIME__ | |
74 | #endif | |
75 | ; | |
73 | 76 | |
74 | 77 | |
75 | 78 | /* |
83 | 86 | static char const *secret = "testing123"; |
84 | 87 | |
85 | 88 | #include <sys/wait.h> |
89 | ||
90 | #ifdef HAVE_PTHREAD_H | |
86 | 91 | pid_t rad_fork(void) |
87 | 92 | { |
88 | 93 | return fork(); |
89 | 94 | } |
90 | ||
91 | #ifdef HAVE_PTHREAD_H | |
92 | 95 | pid_t rad_waitpid(pid_t pid, int *status) |
93 | 96 | { |
94 | 97 | return waitpid(pid, status, 0); |
59 | 59 | #ifdef RADIUSD_VERSION_COMMIT |
60 | 60 | " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")" |
61 | 61 | #endif |
62 | ", built on " __DATE__ " at " __TIME__; | |
62 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
63 | ", built on " __DATE__ " at " __TIME__ | |
64 | #endif | |
65 | ; | |
63 | 66 | |
64 | 67 | static int rs_useful_codes[] = { |
65 | 68 | PW_CODE_ACCESS_REQUEST, //!< RFC2865 - Authentication request |
61 | 61 | main_config_t main_config; |
62 | 62 | |
63 | 63 | #include <sys/wait.h> |
64 | #ifdef HAVE_PTHREAD_H | |
64 | 65 | pid_t rad_fork(void) |
65 | 66 | { |
66 | 67 | return fork(); |
67 | 68 | } |
68 | 69 | |
69 | #ifdef HAVE_PTHREAD_H | |
70 | 70 | pid_t rad_waitpid(pid_t pid, int *status) |
71 | 71 | { |
72 | 72 | return waitpid(pid, status, 0); |
867 | 867 | rad_assert(0); |
868 | 868 | /* FALL-THROUGH */ |
869 | 869 | |
870 | /* | |
871 | * One is added to get the accounting port | |
872 | * for home->dual. | |
873 | */ | |
874 | case HOME_TYPE_AUTH_ACCT: | |
870 | 875 | case HOME_TYPE_AUTH: |
871 | 876 | home->port = PW_AUTH_UDP_PORT; |
872 | 877 | break; |
448 | 448 | fr_state_t *state = &global_state; |
449 | 449 | |
450 | 450 | if (!request->state) { |
451 | size_t i; | |
452 | uint32_t x; | |
453 | VALUE_PAIR *vp; | |
454 | uint8_t buffer[16]; | |
455 | ||
451 | 456 | RDEBUG3("session-state: Nothing to cache"); |
457 | ||
458 | if (packet->code != PW_CODE_ACCESS_CHALLENGE) return true; | |
459 | ||
460 | vp = fr_pair_find_by_num(packet->vps, PW_STATE, 0, TAG_ANY); | |
461 | if (vp) return true; | |
462 | ||
463 | /* | |
464 | * | |
465 | */ | |
466 | for (i = 0; i < sizeof(buffer) / sizeof(x); i++) { | |
467 | x = fr_rand(); | |
468 | memcpy(buffer + (i * 4), &x, sizeof(x)); | |
469 | } | |
470 | ||
471 | vp = fr_pair_afrom_num(packet, PW_STATE, 0); | |
472 | fr_pair_value_memcpy(vp, buffer, sizeof(buffer)); | |
473 | fr_pair_add(&packet->vps, vp); | |
474 | ||
452 | 475 | return true; |
453 | 476 | } |
454 | 477 |
476 | 476 | } |
477 | 477 | } |
478 | 478 | |
479 | static void stats_error(REQUEST *request, char const *msg) | |
480 | { | |
481 | VALUE_PAIR *vp; | |
482 | ||
483 | vp = radius_pair_create(request->reply, &request->reply->vps, | |
484 | PW_FREERADIUS_STATS_ERROR, VENDORPEC_FREERADIUS); | |
485 | if (!vp) return; | |
486 | ||
487 | fr_pair_value_strcpy(vp, msg); | |
488 | } | |
489 | ||
479 | 490 | |
480 | 491 | void request_stats_reply(REQUEST *request) |
481 | 492 | { |
660 | 671 | &client->acct); |
661 | 672 | } |
662 | 673 | #endif |
663 | } /* else client wasn't found, don't echo it back */ | |
674 | } else { | |
675 | /* | |
676 | * No such client. | |
677 | */ | |
678 | stats_error(request, "No such client"); | |
679 | } | |
664 | 680 | } |
665 | 681 | |
666 | 682 | /* |
691 | 707 | /* |
692 | 708 | * Not found: don't do anything |
693 | 709 | */ |
694 | if (!this) return; | |
710 | if (!this) { | |
711 | stats_error(request, "No such listener"); | |
712 | return; | |
713 | } | |
695 | 714 | |
696 | 715 | fr_pair_add(&request->reply->vps, |
697 | 716 | fr_pair_copy(request->reply, server_ip)); |
698 | 717 | fr_pair_add(&request->reply->vps, |
699 | 718 | fr_pair_copy(request->reply, server_port)); |
700 | 719 | |
701 | if (((flag->vp_integer & 0x01) != 0) && | |
702 | ((request->listener->type == RAD_LISTEN_AUTH) || | |
703 | (request->listener->type == RAD_LISTEN_NONE))) { | |
704 | request_stats_addvp(request, authvp, &this->stats); | |
705 | } | |
706 | ||
707 | #ifdef WITH_ACCOUNTING | |
708 | if (((flag->vp_integer & 0x02) != 0) && | |
709 | ((request->listener->type == RAD_LISTEN_ACCT) || | |
710 | (request->listener->type == RAD_LISTEN_NONE))) { | |
711 | request_stats_addvp(request, acctvp, &this->stats); | |
720 | if ((flag->vp_integer & 0x01) != 0) { | |
721 | if ((request->listener->type == RAD_LISTEN_AUTH) || | |
722 | (request->listener->type == RAD_LISTEN_NONE)) { | |
723 | request_stats_addvp(request, authvp, &this->stats); | |
724 | } else { | |
725 | stats_error(request, "Listener is not auth"); | |
726 | } | |
727 | } | |
728 | ||
729 | #ifdef WITH_ACCOUNTING | |
730 | if ((flag->vp_integer & 0x02) != 0) { | |
731 | if ((request->listener->type == RAD_LISTEN_ACCT) || | |
732 | (request->listener->type == RAD_LISTEN_NONE)) { | |
733 | request_stats_addvp(request, acctvp, &this->stats); | |
734 | } else { | |
735 | stats_error(request, "Listener is not acct"); | |
736 | } | |
712 | 737 | } |
713 | 738 | #endif |
714 | 739 | } |
728 | 753 | * socket. |
729 | 754 | */ |
730 | 755 | server_ip = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_IP_ADDRESS, VENDORPEC_FREERADIUS, TAG_ANY); |
731 | if (!server_ip) return; | |
756 | if (!server_ip) { | |
757 | stats_error(request, "No home server IP supplied"); | |
758 | return; | |
759 | } | |
732 | 760 | |
733 | 761 | server_port = fr_pair_find_by_num(request->packet->vps, PW_FREERADIUS_STATS_SERVER_PORT, VENDORPEC_FREERADIUS, TAG_ANY); |
734 | if (!server_port) return; | |
762 | if (!server_port) { | |
763 | stats_error(request, "No home server port supplied"); | |
764 | return; | |
765 | } | |
735 | 766 | |
736 | 767 | #ifndef NDEBUG |
737 | 768 | memset(&ipaddr, 0, sizeof(ipaddr)); |
738 | 769 | #endif |
739 | 770 | ipaddr.af = AF_INET; |
771 | ipaddr.prefix = 32; | |
740 | 772 | ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr; |
741 | 773 | home = home_server_find(&ipaddr, server_port->vp_integer, |
742 | 774 | IPPROTO_UDP); |
744 | 776 | /* |
745 | 777 | * Not found: don't do anything |
746 | 778 | */ |
747 | if (!home) return; | |
779 | if (!home) { | |
780 | stats_error(request, "Failed to find home server IP"); | |
781 | return; | |
782 | } | |
748 | 783 | |
749 | 784 | fr_pair_add(&request->reply->vps, |
750 | 785 | fr_pair_copy(request->reply, server_ip)); |
802 | 837 | PW_FREERADIUS_STATS_LAST_PACKET_SENT, VENDORPEC_FREERADIUS); |
803 | 838 | if (vp) vp->vp_date = home->last_packet_sent; |
804 | 839 | |
805 | if (((flag->vp_integer & 0x01) != 0) && | |
806 | (home->type == HOME_TYPE_AUTH)) { | |
807 | request_stats_addvp(request, proxy_authvp, | |
808 | &home->stats); | |
809 | } | |
810 | ||
811 | #ifdef WITH_ACCOUNTING | |
812 | if (((flag->vp_integer & 0x02) != 0) && | |
813 | (home->type == HOME_TYPE_ACCT)) { | |
814 | request_stats_addvp(request, proxy_acctvp, | |
815 | &home->stats); | |
840 | if ((flag->vp_integer & 0x01) != 0) { | |
841 | if (home->type == HOME_TYPE_AUTH) { | |
842 | request_stats_addvp(request, proxy_authvp, | |
843 | &home->stats); | |
844 | } else { | |
845 | stats_error(request, "Home server is not auth"); | |
846 | } | |
847 | } | |
848 | ||
849 | #ifdef WITH_ACCOUNTING | |
850 | if ((flag->vp_integer & 0x02) != 0) { | |
851 | if (home->type == HOME_TYPE_ACCT) { | |
852 | request_stats_addvp(request, proxy_acctvp, | |
853 | &home->stats); | |
854 | } else { | |
855 | stats_error(request, "Home server is not acct"); | |
856 | } | |
816 | 857 | } |
817 | 858 | #endif |
818 | 859 | } |
222 | 222 | static pthread_mutex_t *ssl_mutexes = NULL; |
223 | 223 | |
224 | 224 | #ifdef HAVE_CRYPTO_SET_ID_CALLBACK |
225 | static unsigned long ssl_id_function(void) | |
225 | static unsigned long get_ssl_id(void) | |
226 | 226 | { |
227 | 227 | unsigned long ret; |
228 | 228 | pthread_t thread = pthread_self(); |
235 | 235 | |
236 | 236 | return ret; |
237 | 237 | } |
238 | ||
239 | /* | |
240 | * Use preprocessor magic to get the right function and argument | |
241 | * to use. This avoids ifdef's through the rest of the code. | |
242 | */ | |
243 | #if OPENSSL_VERSION_NUMBER < 0x10000000L | |
244 | #define ssl_id_function get_ssl_id | |
245 | #define set_id_callback CRYPTO_set_id_callback | |
246 | ||
247 | #else | |
248 | static void ssl_id_function(CRYPTO_THREADID *id) | |
249 | { | |
250 | CRYPTO_THREADID_set_numeric(id, get_ssl_id()); | |
251 | } | |
252 | #define set_id_callback CRYPTO_THREADID_set_callback | |
253 | #endif | |
238 | 254 | #endif |
239 | 255 | |
240 | 256 | #ifdef HAVE_CRYPTO_SET_LOCKING_CALLBACK |
248 | 264 | } |
249 | 265 | #endif |
250 | 266 | |
251 | static int setup_ssl_mutexes(void) | |
267 | /* | |
268 | * Create the TLS mutexes. | |
269 | */ | |
270 | int tls_mutexes_init(void) | |
252 | 271 | { |
253 | 272 | int i; |
254 | 273 | |
255 | 274 | ssl_mutexes = rad_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); |
256 | 275 | if (!ssl_mutexes) { |
257 | 276 | ERROR("Error allocating memory for SSL mutexes!"); |
258 | return 0; | |
277 | return -1; | |
259 | 278 | } |
260 | 279 | |
261 | 280 | for (i = 0; i < CRYPTO_num_locks(); i++) { |
263 | 282 | } |
264 | 283 | |
265 | 284 | #ifdef HAVE_CRYPTO_SET_ID_CALLBACK |
266 | CRYPTO_set_id_callback(ssl_id_function); | |
285 | set_id_callback(ssl_id_function); | |
267 | 286 | #endif |
268 | 287 | #ifdef HAVE_CRYPTO_SET_LOCKING_CALLBACK |
269 | 288 | CRYPTO_set_locking_callback(ssl_locking_function); |
270 | 289 | #endif |
271 | 290 | |
272 | return 1; | |
291 | return 0; | |
273 | 292 | } |
274 | 293 | #endif |
275 | 294 | |
1027 | 1046 | } |
1028 | 1047 | #endif |
1029 | 1048 | |
1030 | #ifdef HAVE_OPENSSL_CRYPTO_H | |
1031 | /* | |
1032 | * If we're linking with OpenSSL too, then we need | |
1033 | * to set up the mutexes and enable the thread callbacks. | |
1034 | */ | |
1035 | if (!setup_ssl_mutexes()) { | |
1036 | ERROR("FATAL: Failed to set up SSL mutexes"); | |
1037 | return -1; | |
1038 | } | |
1039 | #endif | |
1040 | ||
1041 | ||
1042 | 1049 | #ifndef WITH_GCD |
1043 | 1050 | /* |
1044 | 1051 | * Create a number of waiting threads. |
1113 | 1120 | * the memory. |
1114 | 1121 | */ |
1115 | 1122 | #ifdef HAVE_CRYPTO_SET_ID_CALLBACK |
1116 | CRYPTO_set_id_callback(NULL); | |
1123 | set_id_callback(NULL); | |
1117 | 1124 | #endif |
1118 | 1125 | #ifdef HAVE_CRYPTO_SET_LOCKING_CALLBACK |
1119 | 1126 | CRYPTO_set_locking_callback(NULL); |
1225 | 1225 | { "disable_tlsv1_2", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, disable_tlsv1_2), NULL }, |
1226 | 1226 | #endif |
1227 | 1227 | |
1228 | { "tls_max_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_max_version), "" }, | |
1229 | ||
1230 | { "tls_min_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_min_version), "1.0" }, | |
1231 | ||
1228 | 1232 | { "cache", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) cache_config }, |
1229 | 1233 | |
1230 | 1234 | { "verify", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) verify_config }, |
1270 | 1274 | #ifdef SSL_OP_NO_TLSv1_2 |
1271 | 1275 | { "disable_tlsv1_2", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_tls_server_conf_t, disable_tlsv1_2), NULL }, |
1272 | 1276 | #endif |
1277 | ||
1278 | { "tls_max_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_max_version), "" }, | |
1279 | ||
1280 | { "tls_min_version", FR_CONF_OFFSET(PW_TYPE_STRING, fr_tls_server_conf_t, tls_min_version), "1.0" }, | |
1281 | ||
1273 | 1282 | CONF_PARSER_TERMINATOR |
1274 | 1283 | }; |
1275 | 1284 | |
1730 | 1739 | BIO *cbio, *bio_out; |
1731 | 1740 | ocsp_status_t ocsp_status = OCSP_STATUS_FAILED; |
1732 | 1741 | int status; |
1733 | ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; | |
1742 | ASN1_GENERALIZEDTIME *rev = NULL, *thisupd, *nextupd; | |
1734 | 1743 | int reason; |
1735 | 1744 | #if OPENSSL_VERSION_NUMBER >= 0x1000003f |
1736 | 1745 | OCSP_REQ_CTX *ctx; |
1882 | 1891 | goto ocsp_end; |
1883 | 1892 | } |
1884 | 1893 | bresp = OCSP_response_get1_basic(resp); |
1894 | if (!bresp) { | |
1895 | RDEBUG("ocsp: Failed parsing response"); | |
1896 | goto ocsp_end; | |
1897 | } | |
1898 | ||
1885 | 1899 | if (conf->ocsp_use_nonce && OCSP_check_nonce(req, bresp)!=1) { |
1886 | 1900 | REDEBUG("ocsp: Response has wrong nonce value"); |
1887 | 1901 | goto ocsp_end; |
1929 | 1943 | REDEBUG("ocsp: Cert status: %s", OCSP_cert_status_str(status)); |
1930 | 1944 | if (reason != -1) REDEBUG("ocsp: Reason: %s", OCSP_crl_reason_str(reason)); |
1931 | 1945 | |
1932 | if (bio_out) { | |
1946 | if (bio_out && rev) { | |
1933 | 1947 | BIO_puts(bio_out, "\tRevocation Time: "); |
1934 | 1948 | ASN1_GENERALIZEDTIME_print(bio_out, rev); |
1935 | 1949 | BIO_puts(bio_out, "\n"); |
2585 | 2599 | * This should be called exactly once from main, before reading the main config |
2586 | 2600 | * or initialising any modules. |
2587 | 2601 | */ |
2588 | void tls_global_init(void) | |
2602 | int tls_global_init(bool spawn_flag, bool check) | |
2589 | 2603 | { |
2590 | 2604 | SSL_load_error_strings(); /* readable error messages (examples show call before library_init) */ |
2591 | 2605 | SSL_library_init(); /* initialize library */ |
2596 | 2610 | * Initialize the index for the certificates. |
2597 | 2611 | */ |
2598 | 2612 | fr_tls_ex_index_certs = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, sess_free_certs); |
2613 | ||
2614 | /* | |
2615 | * If we're linking with OpenSSL too, then we need | |
2616 | * to set up the mutexes and enable the thread callbacks. | |
2617 | * | |
2618 | * 'check' and not 'check_config' because it's a global, | |
2619 | * and we don't want to have tls.c depend on globals. | |
2620 | */ | |
2621 | if (spawn_flag && !check && (tls_mutexes_init() < 0)) { | |
2622 | ERROR("FATAL: Failed to set up SSL mutexes"); | |
2623 | return -1; | |
2624 | } | |
2625 | ||
2626 | return 0; | |
2599 | 2627 | } |
2600 | 2628 | |
2601 | 2629 | #ifdef ENABLE_OPENSSL_VERSION_CHECK |
2663 | 2691 | EVP_cleanup(); |
2664 | 2692 | CRYPTO_cleanup_all_ex_data(); |
2665 | 2693 | } |
2694 | ||
2695 | ||
2696 | /* | |
2697 | * Map version strings to OpenSSL macros. | |
2698 | */ | |
2699 | static const FR_NAME_NUMBER version2int[] = { | |
2700 | { "1.0", TLS1_VERSION }, | |
2701 | #ifdef TLS1_1_VERSION | |
2702 | { "1.1", TLS1_1_VERSION }, | |
2703 | #endif | |
2704 | #ifdef TLS1_2_VERSION | |
2705 | { "1.2", TLS1_2_VERSION }, | |
2706 | #endif | |
2707 | #ifdef TLS1_3_VERSION | |
2708 | { "1.3", TLS1_3_VERSION }, | |
2709 | #endif | |
2710 | #ifdef TLS1_4_VERSION | |
2711 | { "1.4", TLS1_4_VERSION }, | |
2712 | #endif | |
2713 | { NULL, 0 } | |
2714 | }; | |
2715 | ||
2666 | 2716 | |
2667 | 2717 | /** Create SSL context |
2668 | 2718 | * |
2899 | 2949 | ctx_options |= SSL_OP_NO_SSLv3; |
2900 | 2950 | |
2901 | 2951 | /* |
2902 | * As of 3.0.5, we always allow TLSv1.1 and TLSv1.2. | |
2903 | * Though they can be *globally* disabled if necessary.x | |
2952 | * SSL_CTX_set_(min|max)_proto_version was included in OpenSSL 1.1.0 | |
2953 | * | |
2954 | * This version already defines macros for TLS1_2_VERSION and | |
2955 | * below, so we don't need to check for them explicitly. | |
2956 | * | |
2957 | * TLS1_3_VERSION is available in OpenSSL 1.1.1. | |
2958 | * | |
2959 | * TLS1_4_VERSION in speculative. | |
2960 | */ | |
2961 | { | |
2962 | int min_version = 0; | |
2963 | int max_version = 0; | |
2964 | ||
2965 | /* | |
2966 | * Get the max version. | |
2967 | */ | |
2968 | if (conf->tls_max_version && *conf->tls_max_version) { | |
2969 | max_version = fr_str2int(version2int, conf->tls_max_version, 0); | |
2970 | if (!max_version) { | |
2971 | ERROR("Invalid value for tls_max_version '%s'", conf->tls_max_version); | |
2972 | return NULL; | |
2973 | } | |
2974 | } else { | |
2975 | /* | |
2976 | * Pick the maximum one we know about. | |
2977 | */ | |
2978 | #ifdef TLS1_4_VERSION | |
2979 | max_version = TLS1_4_VERSION; | |
2980 | #elif defined(TLS1_3_VERSION) | |
2981 | max_version = TLS1_3_VERSION; | |
2982 | #elif defined(TLS1_2_VERSION) | |
2983 | max_version = TLS1_2_VERSION; | |
2984 | #elif defined(TLS1_1_VERSION) | |
2985 | max_version = TLS1_1_VERSION; | |
2986 | #else | |
2987 | max_version = TLS1_VERSION; | |
2988 | #endif | |
2989 | } | |
2990 | ||
2991 | /* | |
2992 | * Set these for the rest of the code. | |
2993 | */ | |
2994 | if (max_version < TLS1_2_VERSION) { | |
2995 | conf->disable_tlsv1_2 = true; | |
2996 | } | |
2997 | if (max_version < TLS1_1_VERSION) { | |
2998 | conf->disable_tlsv1_1 = true; | |
2999 | } | |
3000 | ||
3001 | /* | |
3002 | * Get the min version. | |
3003 | */ | |
3004 | if (conf->tls_min_version && *conf->tls_min_version) { | |
3005 | min_version = fr_str2int(version2int, conf->tls_min_version, 0); | |
3006 | if (!min_version) { | |
3007 | ERROR("Unknown or unsupported value for tls_min_version '%s'", conf->tls_min_version); | |
3008 | return NULL; | |
3009 | } | |
3010 | } else { | |
3011 | min_version = TLS1_VERSION; | |
3012 | } | |
3013 | ||
3014 | /* | |
3015 | * Compare the two. | |
3016 | */ | |
3017 | if (min_version > max_version) { | |
3018 | ERROR("tls_min_version '%s' must be <= tls_max_version '%s'", | |
3019 | conf->tls_min_version, conf->tls_max_version); | |
3020 | return NULL; | |
3021 | } | |
3022 | ||
3023 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
3024 | if (!SSL_CTX_set_max_proto_version(ctx, max_version)) { | |
3025 | ERROR("Failed setting TLS maximum version"); | |
3026 | return NULL; | |
3027 | } | |
3028 | ||
3029 | if (!SSL_CTX_set_min_proto_version(ctx, min_version)) { | |
3030 | ERROR("Failed setting TLS minimum version"); | |
3031 | return NULL; | |
3032 | } | |
3033 | #endif /* OpenSSL version >1.1.0 */ | |
3034 | } | |
3035 | ||
3036 | /* | |
3037 | * For historical config compatibility, we also allow | |
3038 | * these, but complain if the admin uses them. | |
2904 | 3039 | */ |
2905 | 3040 | #ifdef SSL_OP_NO_TLSv1 |
2906 | if (conf->disable_tlsv1) ctx_options |= SSL_OP_NO_TLSv1; | |
3041 | if (conf->disable_tlsv1) { | |
3042 | ctx_options |= SSL_OP_NO_TLSv1; | |
3043 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
3044 | WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1"); | |
3045 | #endif | |
3046 | } | |
2907 | 3047 | |
2908 | 3048 | ctx_tls_versions |= SSL_OP_NO_TLSv1; |
2909 | 3049 | #endif |
2910 | 3050 | #ifdef SSL_OP_NO_TLSv1_1 |
2911 | if (conf->disable_tlsv1_1) ctx_options |= SSL_OP_NO_TLSv1_1; | |
3051 | if (conf->disable_tlsv1_1) { | |
3052 | ctx_options |= SSL_OP_NO_TLSv1_1; | |
3053 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
3054 | WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1_2"); | |
3055 | #endif | |
3056 | } | |
2912 | 3057 | |
2913 | 3058 | ctx_tls_versions |= SSL_OP_NO_TLSv1_1; |
2914 | 3059 | #endif |
2915 | 3060 | #ifdef SSL_OP_NO_TLSv1_2 |
2916 | 3061 | |
2917 | if (conf->disable_tlsv1_2) ctx_options |= SSL_OP_NO_TLSv1_2; | |
3062 | if (conf->disable_tlsv1_2) { | |
3063 | ctx_options |= SSL_OP_NO_TLSv1_2; | |
3064 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
3065 | WARN("Please use tls_min_version and tls_max_version instead of disable_tlsv1_2"); | |
3066 | #endif | |
3067 | } | |
2918 | 3068 | |
2919 | 3069 | ctx_tls_versions |= SSL_OP_NO_TLSv1_2; |
2920 | 3070 | |
3377 | 3527 | */ |
3378 | 3528 | fr_pair_add(&vps, fr_pair_list_copy(talloc_ctx, *certs)); |
3379 | 3529 | |
3380 | /* | |
3381 | * Save the certs in the packet, so that we can see them. | |
3382 | */ | |
3383 | fr_pair_add(&request->packet->vps, fr_pair_list_copy(request->packet, *certs)); | |
3384 | ||
3385 | vp = fr_pair_find_by_num(request->packet->vps, PW_TLS_CLIENT_CERT_EXPIRATION, 0, TAG_ANY); | |
3530 | vp = fr_pair_find_by_num(vps, PW_TLS_CLIENT_CERT_EXPIRATION, 0, TAG_ANY); | |
3386 | 3531 | if (vp) { |
3387 | 3532 | time_t expires; |
3388 | 3533 |
187 | 187 | |
188 | 188 | RDEBUG3("Reading from socket %d", request->packet->sockfd); |
189 | 189 | PTHREAD_MUTEX_LOCK(&sock->mutex); |
190 | ||
191 | /* | |
192 | * If there is pending application data, as set up by | |
193 | * SSL_peek(), read that before reading more data from | |
194 | * the socket. | |
195 | */ | |
196 | if (SSL_pending(sock->ssn->ssl)) { | |
197 | RDEBUG3("Reading pending buffered data"); | |
198 | sock->ssn->dirty_in.used = 0; | |
199 | goto get_application_data; | |
200 | } | |
201 | ||
190 | 202 | rcode = read(request->packet->sockfd, |
191 | 203 | sock->ssn->dirty_in.data, |
192 | 204 | sizeof(sock->ssn->dirty_in.data)); |
248 | 260 | /* |
249 | 261 | * Try to get application data. |
250 | 262 | */ |
263 | get_application_data: | |
251 | 264 | status = tls_application_data(sock->ssn, request); |
252 | 265 | RDEBUG("Application data status %d", status); |
253 | 266 | |
331 | 344 | RAD_REQUEST_FUNP fun = NULL; |
332 | 345 | listen_socket_t *sock = listener->data; |
333 | 346 | RADCLIENT *client = sock->client; |
347 | BIO *rbio; | |
334 | 348 | |
335 | 349 | if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0; |
336 | 350 | |
351 | redo: | |
337 | 352 | if (!tls_socket_recv(listener)) { |
338 | 353 | return 0; |
339 | 354 | } |
399 | 414 | FR_STATS_INC(auth, total_packets_dropped); |
400 | 415 | rad_free(&packet); |
401 | 416 | return 0; |
417 | } | |
418 | ||
419 | /* | |
420 | * Check for more application data. | |
421 | * | |
422 | * If there is pending SSL data, "peek" at the | |
423 | * application data. If we get at least one byte of | |
424 | * application data, go back to tls_socket_recv(). | |
425 | * SSL_peek() will set SSL_pending(), and | |
426 | * tls_socket_recv() will read another packet. | |
427 | */ | |
428 | rbio = SSL_get_rbio(sock->ssn->ssl); | |
429 | if (BIO_ctrl_pending(rbio)) { | |
430 | char buf[1]; | |
431 | int peek = SSL_peek(sock->ssn->ssl, buf, 1); | |
432 | ||
433 | if (peek > 0) { | |
434 | DEBUG("more TLS records after dual_tls_recv"); | |
435 | goto redo; | |
436 | } | |
402 | 437 | } |
403 | 438 | |
404 | 439 | return 1; |
1675 | 1675 | case TMPL_TYPE_LIST: |
1676 | 1676 | out[0] = '&'; |
1677 | 1677 | if (vpt->tmpl_request == REQUEST_CURRENT) { |
1678 | snprintf(out + 1, outlen - 1, "%s", | |
1678 | snprintf(out + 1, outlen - 1, "%s:", | |
1679 | 1679 | fr_int2str(pair_lists, vpt->tmpl_list, "")); |
1680 | 1680 | } else { |
1681 | snprintf(out + 1, outlen - 1, "%s.%s", | |
1681 | snprintf(out + 1, outlen - 1, "%s.%s:", | |
1682 | 1682 | fr_int2str(request_refs, vpt->tmpl_request, ""), |
1683 | 1683 | fr_int2str(pair_lists, vpt->tmpl_list, "")); |
1684 | 1684 | } |
47 | 47 | #ifdef RADIUSD_VERSION_COMMIT |
48 | 48 | " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")" |
49 | 49 | #endif |
50 | ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__; | |
50 | ", for host " HOSTINFO | |
51 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
52 | ", built on " __DATE__ " at " __TIME__ | |
53 | #endif | |
54 | ; | |
51 | 55 | |
52 | 56 | /* |
53 | 57 | * Static functions. |
747 | 751 | * Initialising OpenSSL once, here, is safer than having individual modules do it. |
748 | 752 | */ |
749 | 753 | #ifdef HAVE_OPENSSL_CRYPTO_H |
750 | tls_global_init(); | |
754 | tls_global_init(false, false); | |
751 | 755 | #endif |
752 | 756 | |
753 | 757 | if (xlat_register("poke", xlat_poke, NULL, NULL) < 0) { |
1372 | 1372 | return -(p - fmt); |
1373 | 1373 | } |
1374 | 1374 | |
1375 | /* | |
1376 | * Might be a list, too... | |
1377 | */ | |
1375 | 1378 | node->type = XLAT_ATTRIBUTE; |
1376 | 1379 | p += slen; |
1377 | 1380 | |
1664 | 1667 | *(p++) = '%'; |
1665 | 1668 | *(p++) = '{'; |
1666 | 1669 | |
1667 | if (node->attr.tmpl_request != REQUEST_CURRENT) { | |
1668 | strlcpy(p, fr_int2str(request_refs, node->attr.tmpl_request, "??"), end - p); | |
1669 | p += strlen(p); | |
1670 | *(p++) = '.'; | |
1670 | /* | |
1671 | * The node MAY NOT be an attribute. It | |
1672 | * may be a list. | |
1673 | */ | |
1674 | tmpl_prints(p, end - p, &node->attr, NULL); | |
1675 | if (*p == '&') { | |
1676 | memmove(p, p + 1, strlen(p + 1) + 1); | |
1671 | 1677 | } |
1672 | ||
1673 | if ((node->attr.tmpl_request != REQUEST_CURRENT) || | |
1674 | (node->attr.tmpl_list != PAIR_LIST_REQUEST)) { | |
1675 | strlcpy(p, fr_int2str(pair_lists, node->attr.tmpl_list, "??"), end - p); | |
1676 | p += strlen(p); | |
1677 | *(p++) = ':'; | |
1678 | } | |
1679 | ||
1680 | strlcpy(p, node->attr.tmpl_da->name, end - p); | |
1681 | 1678 | p += strlen(p); |
1682 | ||
1683 | if (node->attr.tmpl_tag != TAG_ANY) { | |
1684 | *(p++) = ':'; | |
1685 | snprintf(p, end - p, "%u", node->attr.tmpl_tag); | |
1686 | p += strlen(p); | |
1687 | } | |
1688 | ||
1689 | if (node->attr.tmpl_num != NUM_ANY) { | |
1690 | *(p++) = '['; | |
1691 | switch (node->attr.tmpl_num) { | |
1692 | case NUM_COUNT: | |
1693 | *(p++) = '#'; | |
1694 | break; | |
1695 | ||
1696 | case NUM_ALL: | |
1697 | *(p++) = '*'; | |
1698 | break; | |
1699 | ||
1700 | default: | |
1701 | snprintf(p, end - p, "%i", node->attr.tmpl_num); | |
1702 | p += strlen(p); | |
1703 | } | |
1704 | *(p++) = ']'; | |
1705 | } | |
1706 | 1679 | *(p++) = '}'; |
1707 | 1680 | break; |
1708 | 1681 | #ifdef HAVE_REGEX |
2107 | 2080 | #endif |
2108 | 2081 | |
2109 | 2082 | static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * const node, |
2110 | xlat_escape_t escape, void *escape_ctx, int lvl) | |
2083 | xlat_escape_t escape, void *escape_ctx, | |
2084 | #ifndef DEBUG_XLAT | |
2085 | UNUSED | |
2086 | #endif | |
2087 | int lvl) | |
2111 | 2088 | { |
2112 | 2089 | ssize_t rcode; |
2113 | 2090 | char *str = NULL, *child; |
2347 | 2324 | rad_assert(node->alternate != NULL); |
2348 | 2325 | |
2349 | 2326 | /* |
2350 | * If there are no "next" nodes, call ourselves | |
2351 | * recursively, which is fast. | |
2352 | * | |
2353 | * If there are "next" nodes, call xlat_process() | |
2354 | * which does a ton more work. | |
2327 | * Call xlat_process recursively. The child / | |
2328 | * alternate nodes may have "next" pointers, and | |
2329 | * those need to be expanded. | |
2355 | 2330 | */ |
2356 | if (!node->next) { | |
2357 | str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl); | |
2358 | if (str) { | |
2359 | XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str); | |
2360 | } else { | |
2361 | str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl); | |
2362 | XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str); | |
2363 | } | |
2331 | if (xlat_process(&str, request, node->child, escape, escape_ctx) > 0) { | |
2332 | XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str); | |
2364 | 2333 | } else { |
2365 | ||
2366 | if (xlat_process(&str, request, node->child, escape, escape_ctx) > 0) { | |
2367 | XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str); | |
2368 | } else { | |
2369 | (void) xlat_process(&str, request, node->alternate, escape, escape_ctx); | |
2370 | XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str); | |
2371 | } | |
2334 | (void) xlat_process(&str, request, node->alternate, escape, escape_ctx); | |
2335 | XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str); | |
2372 | 2336 | } |
2373 | 2337 | break; |
2374 | 2338 | } |
17 | 17 | endif |
18 | 18 | |
19 | 19 | SUBMAKEFILES += $(wildcard ${top_srcdir}/src/modules/proto_*/all.mk) |
20 | ||
21 | ifeq "$(MAKECMDGOALS)" "reconfig" | |
22 | src/modules/%/configure: src/modules/%/configure.ac | |
23 | @echo AUTOCONF $(dir $@) | |
24 | cd $(dir $@) && $(AUTOCONF) -I $(top_builddir) -I $(top_builddir)/m4 -I $(top_builddir)/$(dir $@)m4 | |
25 | endif |
1105 | 1105 | memcpy(&giaddr, packet->data + 24, sizeof(giaddr)); |
1106 | 1106 | if (giaddr == htonl(INADDR_ANY)) { |
1107 | 1107 | /* |
1108 | * DHCP Opcode is request | |
1108 | * DHCP-Message-Type is request | |
1109 | 1109 | */ |
1110 | vp = fr_pair_find_by_num(head, 256, DHCP_MAGIC_VENDOR, TAG_ANY); | |
1111 | if (vp && vp->vp_integer == 3) { | |
1110 | vp = fr_pair_find_by_num(head, 53, DHCP_MAGIC_VENDOR, TAG_ANY); | |
1111 | if (vp && vp->vp_byte == 3) { | |
1112 | 1112 | /* |
1113 | 1113 | * Vendor is "MSFT 98" |
1114 | 1114 | */ |
1941 | 1941 | /* |
1942 | 1942 | * print an ethernet address in a buffer |
1943 | 1943 | */ |
1944 | char * ether_addr_print(const uint8_t *addr, char *buf) | |
1944 | static char * ether_addr_print(const uint8_t *addr, char *buf) | |
1945 | 1945 | { |
1946 | 1946 | sprintf (buf, "%02x:%02x:%02x:%02x:%02x:%02x", |
1947 | 1947 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); |
1970 | 1970 | uint16_t udp_src_port; |
1971 | 1971 | uint16_t udp_dst_port; |
1972 | 1972 | size_t dhcp_data_len; |
1973 | int retval; | |
1974 | 1973 | socklen_t sock_len; |
1975 | fd_set read_fd; | |
1976 | 1974 | |
1977 | 1975 | packet = rad_alloc(NULL, false); |
1978 | 1976 | if (!packet) { |
2053 | 2051 | /* d. Check DHCP layer data */ |
2054 | 2052 | dhcp_data_len = data_len - data_offset; |
2055 | 2053 | |
2056 | if (dhcp_data_len < MIN_PACKET_SIZE) DISCARD_RP("DHCP packet is too small (%d < %d)", dhcp_data_len, MIN_PACKET_SIZE); | |
2057 | if (dhcp_data_len > MAX_PACKET_SIZE) DISCARD_RP("DHCP packet is too large (%d > %d)", dhcp_data_len, MAX_PACKET_SIZE); | |
2054 | if (dhcp_data_len < MIN_PACKET_SIZE) DISCARD_RP("DHCP packet is too small (%zu < %d)", dhcp_data_len, MIN_PACKET_SIZE); | |
2055 | if (dhcp_data_len > MAX_PACKET_SIZE) DISCARD_RP("DHCP packet is too large (%zu > %d)", dhcp_data_len, MAX_PACKET_SIZE); | |
2058 | 2056 | |
2059 | 2057 | dhcp_hdr = (dhcp_packet_t *)(raw_packet + ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE); |
2060 | 2058 |
46 | 46 | |
47 | 47 | static int sockfd; |
48 | 48 | |
49 | #ifdef HAVE_LINUX_IF_PACKET_H | |
50 | struct sockaddr_ll ll; /* Socket address structure */ | |
49 | 51 | static char *iface = NULL; |
50 | 52 | static int iface_ind = -1; |
53 | ||
54 | # define DEBUG if (fr_debug_lvl && fr_log_fp) fr_printf_log | |
55 | #endif | |
51 | 56 | |
52 | 57 | static RADIUS_PACKET *reply = NULL; |
53 | 58 | |
61 | 66 | #ifdef RADIUSD_VERSION_COMMIT |
62 | 67 | " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")" |
63 | 68 | #endif |
64 | ", built on " __DATE__ " at " __TIME__; | |
69 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
70 | ", built on " __DATE__ " at " __TIME__ | |
71 | #endif | |
72 | ; | |
65 | 73 | |
66 | 74 | /* structure to keep track of offered IP addresses */ |
67 | 75 | typedef struct dc_offer { |
89 | 97 | fprintf(stderr, " -d <directory> Set the directory where the dictionaries are stored (defaults to " RADDBDIR ").\n"); |
90 | 98 | fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n"); |
91 | 99 | fprintf(stderr, " -f <file> Read packets from file, not stdin.\n"); |
100 | #ifdef HAVE_LINUX_IF_PACKET_H | |
92 | 101 | fprintf(stderr, " -i <interface> Use this interface to send/receive at packet level on a raw socket.\n"); |
102 | #endif | |
93 | 103 | fprintf(stderr, " -t <timeout> Wait 'timeout' seconds for a reply (may be a floating point number).\n"); |
94 | 104 | fprintf(stderr, " -v Show program version information.\n"); |
95 | 105 | fprintf(stderr, " -x Debugging mode.\n"); |
288 | 298 | |
289 | 299 | static void send_with_socket(RADIUS_PACKET *request) |
290 | 300 | { |
291 | sockfd = fr_socket(&request->src_ipaddr, request->src_port); | |
292 | if (sockfd < 0) { | |
293 | fprintf(stderr, "dhcpclient: socket: %s\n", fr_strerror()); | |
294 | fr_exit_now(1); | |
295 | } | |
296 | ||
297 | /* | |
298 | * Set option 'receive timeout' on socket. | |
299 | * Note: in case of a timeout, the error will be "Resource temporarily unavailable". | |
300 | */ | |
301 | if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout,sizeof(struct timeval)) == -1) { | |
302 | fprintf(stderr, "dhcpclient: failed setting socket timeout: %s\n", | |
303 | fr_syserror(errno)); | |
304 | fr_exit_now(1); | |
305 | } | |
306 | ||
307 | 301 | request->sockfd = sockfd; |
308 | 302 | |
309 | 303 | if (fr_dhcp_send(request) < 0) { |
319 | 313 | fprintf(stderr, "dhcpclient: Error receiving reply: %s\n", fr_strerror()); |
320 | 314 | fr_exit_now(1); |
321 | 315 | } |
316 | ||
317 | ||
318 | if (fr_debug_lvl) print_hex(reply); | |
319 | ||
320 | if (fr_dhcp_decode(reply) < 0) { | |
321 | fprintf(stderr, "dhcpclient: failed decoding\n"); | |
322 | fr_exit_now(1); | |
323 | } | |
322 | 324 | } |
325 | ||
326 | ||
327 | #ifdef HAVE_LINUX_IF_PACKET_H | |
328 | /* | |
329 | * Loop waiting for DHCP replies until timer expires. | |
330 | * Note that there may be more than one reply: multiple DHCP servers can respond to a broadcast discover. | |
331 | * A real client would pick one of the proposed replies. | |
332 | * We'll just return the first eligible reply, and display the others. | |
333 | */ | |
334 | static RADIUS_PACKET *fr_dhcp_recv_raw_loop(int sockfd_r, struct sockaddr_ll *p_ll, RADIUS_PACKET *request_p) | |
335 | { | |
336 | struct timeval tval; | |
337 | RADIUS_PACKET *reply_p = NULL; | |
338 | RADIUS_PACKET *cur_reply_p = NULL; | |
339 | int num_replies = 0; | |
340 | int num_offers = 0; | |
341 | dc_offer_t *offer_list = NULL; | |
342 | fd_set read_fd; | |
343 | int retval; | |
344 | ||
345 | memcpy(&tval, &tv_timeout, sizeof(struct timeval)); | |
346 | ||
347 | /* Loop waiting for DHCP replies until timer expires */ | |
348 | while (timerisset(&tval)) { | |
349 | if ((!reply_p) || (cur_reply_p)) { // only debug at start and each time we get a valid DHCP reply on raw socket | |
350 | DEBUG("Waiting for%sDHCP replies for: %d.%06d\n", | |
351 | (num_replies>0)?" additional ":" ", (int)tval.tv_sec, (int)tval.tv_usec); | |
352 | } | |
353 | ||
354 | cur_reply_p = NULL; | |
355 | FD_ZERO(&read_fd); | |
356 | FD_SET(sockfd_r, &read_fd); | |
357 | retval = select(sockfd_r + 1, &read_fd, NULL, NULL, &tval); | |
358 | ||
359 | if (retval < 0) { | |
360 | fr_strerror_printf("Select on DHCP socket failed: %s", fr_syserror(errno)); | |
361 | return NULL; | |
362 | } | |
363 | ||
364 | if ( retval > 0 && FD_ISSET(sockfd_r, &read_fd)) { | |
365 | /* There is something to read on our socket */ | |
366 | cur_reply_p = fr_dhcp_recv_raw_packet(sockfd_r, p_ll, request_p); | |
367 | } | |
368 | ||
369 | if (cur_reply_p) { | |
370 | num_replies ++; | |
371 | ||
372 | if (fr_debug_lvl) print_hex(cur_reply_p); | |
373 | ||
374 | if (fr_dhcp_decode(cur_reply_p) < 0) { | |
375 | fprintf(stderr, "dhcpclient: failed decoding reply\n"); | |
376 | return NULL; | |
377 | } | |
378 | ||
379 | if (!reply_p) reply_p = cur_reply_p; | |
380 | ||
381 | if (cur_reply_p->code == PW_DHCP_OFFER) { | |
382 | VALUE_PAIR *vp1 = fr_pair_find_by_num(cur_reply_p->vps, 54, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-DHCP-Server-Identifier */ | |
383 | VALUE_PAIR *vp2 = fr_pair_find_by_num(cur_reply_p->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-address */ | |
384 | ||
385 | if (vp1 && vp2) { | |
386 | num_offers ++; | |
387 | offer_list = talloc_realloc(request_p, offer_list, dc_offer_t, num_offers); | |
388 | offer_list[num_offers-1].server_addr = vp1->vp_ipaddr; | |
389 | offer_list[num_offers-1].offered_addr = vp2->vp_ipaddr; | |
390 | } | |
391 | } | |
392 | } | |
393 | } | |
394 | ||
395 | if (!num_replies) { | |
396 | fr_strerror_printf("No valid DHCP reply received"); | |
397 | return NULL; | |
398 | } | |
399 | ||
400 | /* display offer(s) received */ | |
401 | if (num_offers > 0 ) { | |
402 | DEBUG("Received %d DHCP Offer(s):\n", num_offers); | |
403 | int i; | |
404 | for (i = 0; i < num_replies; i++) { | |
405 | char server_addr_buf[INET6_ADDRSTRLEN]; | |
406 | char offered_addr_buf[INET6_ADDRSTRLEN]; | |
407 | ||
408 | DEBUG("IP address: %s offered by DHCP server: %s\n", | |
409 | inet_ntop(AF_INET, &offer_list[i].offered_addr, offered_addr_buf, sizeof(offered_addr_buf)), | |
410 | inet_ntop(AF_INET, &offer_list[i].server_addr, server_addr_buf, sizeof(server_addr_buf)) | |
411 | ); | |
412 | } | |
413 | } | |
414 | ||
415 | return reply_p; | |
416 | } | |
417 | #endif | |
418 | ||
323 | 419 | |
324 | 420 | int main(int argc, char **argv) |
325 | 421 | { |
326 | ||
327 | 422 | static uint16_t server_port = 0; |
328 | 423 | static int packet_code = 0; |
329 | 424 | static fr_ipaddr_t server_ipaddr; |
336 | 431 | DICT_ATTR const *da; |
337 | 432 | RADIUS_PACKET *request = NULL; |
338 | 433 | |
434 | #ifdef HAVE_LINUX_IF_PACKET_H | |
435 | bool raw_mode = false; | |
436 | #endif | |
437 | ||
339 | 438 | fr_debug_lvl = 0; |
340 | 439 | |
341 | while ((c = getopt(argc, argv, "d:D:f:hr:t:vxi:")) != EOF) switch(c) { | |
440 | while ((c = getopt(argc, argv, "d:D:f:hr:t:vx" | |
441 | #ifdef HAVE_LINUX_IF_PACKET_H | |
442 | "i:" | |
443 | #endif | |
444 | )) != EOF) switch(c) { | |
342 | 445 | case 'D': |
343 | 446 | dict_dir = optarg; |
344 | 447 | break; |
349 | 452 | case 'f': |
350 | 453 | filename = optarg; |
351 | 454 | break; |
455 | #ifdef HAVE_LINUX_IF_PACKET_H | |
352 | 456 | case 'i': |
353 | 457 | iface = optarg; |
354 | 458 | break; |
459 | #endif | |
355 | 460 | case 'r': |
356 | 461 | if (!isdigit((int) *optarg)) |
357 | 462 | usage(); |
436 | 541 | } |
437 | 542 | if (!server_port) server_port = 67; |
438 | 543 | |
544 | #ifdef HAVE_LINUX_IF_PACKET_H | |
439 | 545 | /* |
440 | 546 | * set "raw mode" if an interface is specified and if destination |
441 | 547 | * IP address is the broadcast address. |
448 | 554 | } |
449 | 555 | |
450 | 556 | if (server_ipaddr.ipaddr.ip4addr.s_addr == 0xFFFFFFFF) { |
451 | fprintf(stderr, "dhcpclient: Sending broadcast packets is not supported\n"); | |
452 | exit(1); | |
453 | } | |
557 | DEBUG("dhcpclient: Using interface: %s (index: %d) in raw packet mode\n", iface, iface_ind); | |
558 | raw_mode = true; | |
559 | } | |
560 | } | |
561 | ||
562 | if (raw_mode) { | |
563 | sockfd = fr_socket_packet(iface_ind, &ll); | |
564 | } else | |
565 | #endif | |
566 | { | |
567 | sockfd = fr_socket(&client_ipaddr, server_port + 1); | |
568 | } | |
569 | ||
570 | if (sockfd < 0) { | |
571 | fprintf(stderr, "dhcpclient: socket: %s\n", fr_strerror()); | |
572 | fr_exit_now(1); | |
573 | } | |
574 | ||
575 | /* | |
576 | * Set option 'receive timeout' on socket. | |
577 | * Note: in case of a timeout, the error will be "Resource temporarily unavailable". | |
578 | */ | |
579 | if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout,sizeof(struct timeval)) == -1) { | |
580 | fprintf(stderr, "dhcpclient: failed setting socket timeout: %s\n", | |
581 | fr_syserror(errno)); | |
582 | fr_exit_now(1); | |
454 | 583 | } |
455 | 584 | |
456 | 585 | request = request_init(filename); |
481 | 610 | /* These kind of packets do not get a reply, so don't wait for one. */ |
482 | 611 | reply_expected = false; |
483 | 612 | } |
613 | ||
484 | 614 | /* |
485 | 615 | * Encode the packet |
486 | 616 | */ |
490 | 620 | } |
491 | 621 | if (fr_debug_lvl) print_hex(request); |
492 | 622 | |
493 | send_with_socket(request); | |
494 | ||
495 | if (reply && fr_debug_lvl) print_hex(reply); | |
496 | ||
497 | if (reply && fr_dhcp_decode(reply) < 0) { | |
498 | fprintf(stderr, "dhcpclient: failed decoding\n"); | |
499 | return 1; | |
623 | #ifdef HAVE_LINUX_IF_PACKET_H | |
624 | if (raw_mode) { | |
625 | if (fr_dhcp_send_raw_packet(sockfd, &ll, request) < 0) { | |
626 | fprintf(stderr, "dhcpclient: failed sending (fr_dhcp_send_raw_packet): %s\n", | |
627 | fr_syserror(errno)); | |
628 | fr_exit_now(1); | |
629 | } | |
630 | ||
631 | if (reply_expected) { | |
632 | reply = fr_dhcp_recv_raw_loop(sockfd, &ll, request); | |
633 | if (!reply) { | |
634 | fprintf(stderr, "dhcpclient: Error receiving reply (fr_dhcp_recv_raw_loop)\n"); | |
635 | fr_exit_now(1); | |
636 | } | |
637 | } | |
638 | } else | |
639 | #endif | |
640 | { | |
641 | send_with_socket(request); | |
500 | 642 | } |
501 | 643 | |
502 | 644 | dict_free(); |
73 | 73 | #ifdef WITH_UDPFROMTO |
74 | 74 | static int dhcprelay_process_client_request(REQUEST *request) |
75 | 75 | { |
76 | int rcode; | |
76 | 77 | uint8_t maxhops = 16; |
77 | 78 | VALUE_PAIR *vp, *giaddr; |
78 | 79 | dhcp_socket_t *sock; |
80 | RADIUS_PACKET *packet; | |
79 | 81 | |
80 | 82 | rad_assert(request->packet->data[0] == 1); |
81 | 83 | |
115 | 117 | sock = request->listener->data; |
116 | 118 | |
117 | 119 | /* |
120 | * Don't muck with the original request packet. That's | |
121 | * bad form. Plus, dhcp_encode() does nothing if | |
122 | * packet->data is already set. | |
123 | */ | |
124 | packet = rad_alloc(request, false); | |
125 | ||
126 | /* | |
118 | 127 | * Forward the request to the next server using the |
119 | 128 | * incoming request as a template. |
120 | 129 | */ |
130 | packet->code = request->packet->code; | |
131 | packet->sockfd = request->packet->sockfd; | |
132 | ||
133 | /* | |
134 | * Forward the request to the next server using the | |
135 | * incoming request as a template. | |
136 | */ | |
121 | 137 | /* set SRC ipaddr/port to the listener ipaddr/port */ |
122 | request->packet->src_ipaddr.af = AF_INET; | |
123 | request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = sock->lsock.my_ipaddr.ipaddr.ip4addr.s_addr; | |
124 | request->packet->src_port = sock->lsock.my_port; | |
138 | packet->src_ipaddr.af = AF_INET; | |
139 | packet->src_ipaddr.ipaddr.ip4addr.s_addr = sock->lsock.my_ipaddr.ipaddr.ip4addr.s_addr; | |
140 | packet->src_port = sock->lsock.my_port; | |
125 | 141 | |
126 | 142 | vp = fr_pair_find_by_num(request->config, 270, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Relay-To-IP-Address */ |
127 | 143 | rad_assert(vp != NULL); |
128 | 144 | |
129 | 145 | /* set DEST ipaddr/port to the next server ipaddr/port */ |
130 | request->packet->dst_ipaddr.af = AF_INET; | |
131 | request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
132 | request->packet->dst_port = sock->lsock.my_port; | |
133 | ||
134 | if (fr_dhcp_encode(request->packet) < 0) { | |
146 | packet->dst_ipaddr.af = AF_INET; | |
147 | packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
148 | packet->dst_port = sock->lsock.my_port; | |
149 | ||
150 | packet->vps = request->packet->vps; /* hackity hack */ | |
151 | ||
152 | if (fr_dhcp_encode(packet) < 0) { | |
153 | packet->vps = NULL; | |
154 | talloc_free(packet); | |
135 | 155 | DEBUG("dhcprelay_process_client_request: ERROR in fr_dhcp_encode\n"); |
136 | 156 | return -1; |
137 | 157 | } |
138 | 158 | |
139 | return fr_dhcp_send(request->packet); | |
159 | rcode = fr_dhcp_send(packet); | |
160 | packet->vps = NULL; | |
161 | talloc_free(packet); | |
162 | ||
163 | return rcode; | |
140 | 164 | } |
141 | 165 | |
142 | 166 | |
146 | 170 | */ |
147 | 171 | static int dhcprelay_process_server_reply(REQUEST *request) |
148 | 172 | { |
173 | int rcode; | |
149 | 174 | VALUE_PAIR *vp, *giaddr; |
150 | 175 | dhcp_socket_t *sock; |
176 | RADIUS_PACKET *packet; | |
151 | 177 | |
152 | 178 | rad_assert(request->packet->data[0] == 2); |
153 | 179 | |
170 | 196 | return 1; |
171 | 197 | } |
172 | 198 | |
199 | /* | |
200 | * Don't muck with the original request packet. That's | |
201 | * bad form. Plus, dhcp_encode() does nothing if | |
202 | * packet->data is already set. | |
203 | */ | |
204 | packet = rad_alloc(request, false); | |
205 | rcode = -1; | |
206 | ||
207 | /* | |
208 | * Forward the request to the next server using the | |
209 | * incoming request as a template. | |
210 | */ | |
211 | packet->code = request->packet->code; | |
212 | packet->sockfd = request->packet->sockfd; | |
213 | ||
173 | 214 | /* set SRC ipaddr/port to the listener ipaddr/port */ |
174 | request->packet->src_ipaddr.af = AF_INET; | |
175 | request->packet->src_port = sock->lsock.my_port; | |
215 | packet->src_ipaddr.af = AF_INET; | |
216 | packet->src_port = sock->lsock.my_port; | |
176 | 217 | |
177 | 218 | /* set DEST ipaddr/port to clientip/68 or broadcast in specific cases */ |
178 | request->packet->dst_ipaddr.af = AF_INET; | |
179 | ||
180 | /* | |
181 | * We're a relay, and send the reply to giaddr. | |
182 | */ | |
183 | request->reply->dst_ipaddr.ipaddr.ip4addr.s_addr = giaddr->vp_ipaddr; | |
184 | request->reply->dst_port = request->packet->dst_port; /* server port */ | |
185 | ||
186 | if ((request->packet->code == PW_DHCP_NAK) || | |
219 | packet->dst_ipaddr.af = AF_INET; | |
220 | ||
221 | /* | |
222 | * We're a relay, figure out where to send the packet. | |
223 | */ | |
224 | packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST); | |
225 | packet->dst_port = request->packet->dst_port; /* server port */ | |
226 | ||
227 | /* | |
228 | * Unicast the response to another relay if requested. | |
229 | */ | |
230 | vp = fr_pair_find_by_num(request->config, 270, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Relay-To-IP-Address */ | |
231 | if (vp) { | |
232 | RDEBUG("DHCP: response will be relayed to previous gateway"); | |
233 | packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
234 | giaddr->vp_ipaddr = vp->vp_ipaddr; | |
235 | ||
236 | } else if ((packet->code == PW_DHCP_NAK) || | |
187 | 237 | !sock->src_interface || |
188 | 238 | ((vp = fr_pair_find_by_num(request->packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Flags */ && |
189 | 239 | (vp->vp_integer & 0x8000) && |
197 | 247 | * or |
198 | 248 | * - Broadcast flag is set up and ciaddr == NULL |
199 | 249 | */ |
200 | RDEBUG("DHCP: response will be broadcast"); | |
201 | request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST); | |
202 | } else { | |
250 | RDEBUG("DHCP: response will be broadcast"); | |
251 | packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST); | |
252 | ||
253 | } else if ((vp = fr_pair_find_by_num(request->packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Client-IP-Address */ && | |
254 | (vp->vp_ipaddr != htonl(INADDR_ANY))) { | |
203 | 255 | /* |
204 | 256 | * RFC 2131, page 23 |
205 | 257 | * |
207 | 259 | * - ciaddr if present |
208 | 260 | * otherwise to yiaddr |
209 | 261 | */ |
210 | if ((vp = fr_pair_find_by_num(request->packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Client-IP-Address */ && | |
211 | (vp->vp_ipaddr != htonl(INADDR_ANY))) { | |
212 | request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
213 | } else { | |
214 | vp = fr_pair_find_by_num(request->packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-Address */ | |
215 | if (!vp) { | |
216 | DEBUG("DHCP: Failed to find IP Address for request"); | |
217 | return -1; | |
262 | packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
263 | } else { | |
264 | vp = fr_pair_find_by_num(request->packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-Address */ | |
265 | if (!vp) { | |
266 | DEBUG("DHCP: Failed to find IP Address for request"); | |
267 | goto error; | |
268 | } | |
269 | ||
270 | RDEBUG("DHCP: response will be unicast to your-ip-address"); | |
271 | packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
272 | ||
273 | /* | |
274 | * When sending a DHCP_OFFER, make sure our ARP table | |
275 | * contains an entry for the client IP address, or else | |
276 | * packet may not be forwarded if it was the first time | |
277 | * the client was requesting an IP address. | |
278 | */ | |
279 | if (packet->code == PW_DHCP_OFFER) { | |
280 | VALUE_PAIR *hwvp = fr_pair_find_by_num(request->packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Client-Hardware-Address */ | |
281 | if (hwvp == NULL) { | |
282 | DEBUG("DHCP: DHCP_OFFER packet received with " | |
283 | "no Client Hardware Address. Discarding packet"); | |
284 | goto error; | |
218 | 285 | } |
219 | ||
220 | RDEBUG("DHCP: response will be unicast to your-ip-address"); | |
221 | request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; | |
222 | ||
223 | /* | |
224 | * When sending a DHCP_OFFER, make sure our ARP table | |
225 | * contains an entry for the client IP address, or else | |
226 | * packet may not be forwarded if it was the first time | |
227 | * the client was requesting an IP address. | |
228 | */ | |
229 | if (request->packet->code == PW_DHCP_OFFER) { | |
230 | VALUE_PAIR *hwvp = fr_pair_find_by_num(request->packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Client-Hardware-Address */ | |
231 | if (hwvp == NULL) { | |
232 | DEBUG("DHCP: DHCP_OFFER packet received with " | |
233 | "no Client Hardware Address. Discarding packet"); | |
234 | return 1; | |
235 | } | |
236 | if (fr_dhcp_add_arp_entry(request->packet->sockfd, sock->src_interface, hwvp, vp) < 0) { | |
237 | DEBUG("%s", fr_strerror()); | |
238 | return -1; | |
239 | } | |
286 | if (fr_dhcp_add_arp_entry(packet->sockfd, sock->src_interface, hwvp, vp) < 0) { | |
287 | DEBUG("Failed adding ARP entry: %s", fr_strerror()); | |
288 | goto error; | |
240 | 289 | } |
241 | 290 | } |
242 | 291 | } |
243 | 292 | |
244 | if (fr_dhcp_encode(request->packet) < 0) { | |
293 | packet->vps = request->packet->vps; /* hackity hack */ | |
294 | ||
295 | if (fr_dhcp_encode(packet) < 0) { | |
245 | 296 | DEBUG("dhcprelay_process_server_reply: ERROR in fr_dhcp_encode\n"); |
246 | return -1; | |
247 | } | |
248 | ||
249 | return fr_dhcp_send(request->packet); | |
297 | goto error; | |
298 | } | |
299 | ||
300 | rcode = fr_dhcp_send(packet); | |
301 | ||
302 | error: | |
303 | packet->vps = NULL; | |
304 | talloc_free(packet); | |
305 | return rcode; | |
250 | 306 | } |
251 | 307 | #else /* WITH_UDPFROMTO */ |
252 | 308 | static int dhcprelay_process_server_reply(UNUSED REQUEST *request) |
366 | 422 | |
367 | 423 | /* BOOTREPLY received on port 67 (i.e. from a server) */ |
368 | 424 | if (vp->vp_byte == 2) { |
425 | if (request->reply->code == 0) { | |
426 | return 1; | |
427 | } | |
369 | 428 | return dhcprelay_process_server_reply(request); |
429 | } | |
430 | ||
431 | /* | |
432 | * If it's not BOOTREQUEST, we ignore it. | |
433 | */ | |
434 | if (vp->vp_byte != 1) { | |
435 | REDEBUG("Ignoring invalid packet code %u", vp->vp_byte); | |
436 | return 1; | |
370 | 437 | } |
371 | 438 | |
372 | 439 | /* Packet from client, and we have DHCP-Relay-To-IP-Address */ |
373 | 440 | if (fr_pair_find_by_num(request->config, 270, DHCP_MAGIC_VENDOR, TAG_ANY)) { |
374 | 441 | return dhcprelay_process_client_request(request); |
375 | 442 | } |
376 | ||
377 | /* else it's a packet from a client, without relaying */ | |
378 | rad_assert(vp->vp_byte == 1); /* BOOTREQUEST */ | |
379 | 443 | |
380 | 444 | sock = request->listener->data; |
381 | 445 | |
598 | 662 | if (!hwvp) return -1; |
599 | 663 | |
600 | 664 | if (fr_dhcp_add_arp_entry(request->reply->sockfd, sock->src_interface, hwvp, vp) < 0) { |
601 | RDEBUG("Failed adding arp entry: %s", fr_strerror()); | |
665 | RDEBUG("Failed adding ARP entry: %s", fr_strerror()); | |
602 | 666 | return -1; |
603 | 667 | } |
604 | 668 | } |
660 | 724 | } |
661 | 725 | |
662 | 726 | if (setsockopt(this->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { |
663 | ERROR("Can't set re-use addres option: %s\n", | |
727 | ERROR("Can't set re-use address option: %s\n", | |
664 | 728 | fr_syserror(errno)); |
665 | 729 | return -1; |
666 | 730 | } |
156 | 156 | |
157 | 157 | /* get pair name (attribute name) */ |
158 | 158 | attribute = cf_pair_attr(cp); |
159 | ||
160 | if (!dict_attrbyname(attribute)) { | |
161 | ERROR("Unknown RADIUS attribute '%s'", attribute); | |
162 | return -1; | |
163 | } | |
159 | 164 | |
160 | 165 | /* get pair value (element name) */ |
161 | 166 | element = cf_pair_value(cp); |
347 | 347 | */ |
348 | 348 | static rlm_rcode_t CC_HINT(nonnull) detail_do(void *instance, REQUEST *request, RADIUS_PACKET *packet, bool compat) |
349 | 349 | { |
350 | int outfd; | |
350 | int outfd, dupfd; | |
351 | 351 | char buffer[DIRLEN]; |
352 | 352 | |
353 | 353 | FILE *outfp; |
387 | 387 | #endif |
388 | 388 | #endif |
389 | 389 | |
390 | outfd = exfile_open(inst->ef, buffer, inst->perm, true); | |
390 | outfd = exfile_open(inst->ef, buffer, inst->perm); | |
391 | 391 | if (outfd < 0) { |
392 | 392 | RERROR("Couldn't open file %s: %s", buffer, fr_strerror()); |
393 | 393 | return RLM_MODULE_FAIL; |
411 | 411 | /* |
412 | 412 | * Open the output fp for buffering. |
413 | 413 | */ |
414 | if ((outfp = fdopen(outfd, "a")) == NULL) { | |
414 | outfp = NULL; | |
415 | dupfd = dup(outfd); | |
416 | if (dupfd < 0) { | |
417 | RERROR("Failed to dup() file descriptor for detail file"); | |
418 | goto fail; | |
419 | } | |
420 | ||
421 | if ((outfp = fdopen(dupfd, "a")) == NULL) { | |
415 | 422 | RERROR("Couldn't open file %s: %s", buffer, fr_syserror(errno)); |
416 | 423 | fail: |
417 | 424 | if (outfp) fclose(outfp); |
418 | exfile_unlock(inst->ef, outfd); | |
425 | exfile_close(inst->ef, outfd); | |
419 | 426 | return RLM_MODULE_FAIL; |
420 | 427 | } |
421 | 428 | |
425 | 432 | * Flush everything |
426 | 433 | */ |
427 | 434 | fclose(outfp); |
428 | exfile_unlock(inst->ef, outfd); /* do NOT close outfd */ | |
435 | exfile_close(inst->ef, outfd); | |
429 | 436 | |
430 | 437 | /* |
431 | 438 | * And everything is fine. |
283 | 283 | |
284 | 284 | if (!chbind) return NULL; /* don't produce garbage */ |
285 | 285 | |
286 | vp = fr_pair_afrom_num(packet, VENDORPEC_UKERNA, PW_UKERNA_CHBIND); | |
286 | vp = fr_pair_afrom_num(packet, PW_UKERNA_CHBIND, VENDORPEC_UKERNA); | |
287 | 287 | if (!vp) return NULL; |
288 | 288 | fr_pair_value_memcpy(vp, (uint8_t *) chbind, talloc_array_length((uint8_t *)chbind)); |
289 | 289 |
148 | 148 | if (tls_session->prf_label) { |
149 | 149 | eaptls_gen_mppe_keys(handler->request, |
150 | 150 | tls_session->ssl, tls_session->prf_label); |
151 | } else { | |
151 | } else if (handler->type != PW_EAP_FAST) { | |
152 | 152 | RWDEBUG("Not adding MPPE keys because there is no PRF label"); |
153 | 153 | } |
154 | 154 |
99 | 99 | if (fr_debug_lvl && handler->tls && !handler->finished && |
100 | 100 | (time(NULL) > (handler->timestamp + 3))) { |
101 | 101 | WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); |
102 | WARN("!! EAP session with state 0x%02x%02x%02x%02x%02x%02x%02x%02x did not finish! !!", | |
102 | WARN("!! EAP session with state 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x did not finish! !!", | |
103 | 103 | handler->state[0], handler->state[1], |
104 | 104 | handler->state[2], handler->state[3], |
105 | 105 | handler->state[4], handler->state[5], |
106 | handler->state[6], handler->state[7]); | |
106 | handler->state[6], handler->state[7], | |
107 | handler->state[8], handler->state[9], | |
108 | handler->state[10], handler->state[11], | |
109 | handler->state[12], handler->state[13], | |
110 | handler->state[14], handler->state[15]); | |
107 | 111 | |
108 | 112 | WARN("!! Please read http://wiki.freeradius.org/guide/Certificate_Compatibility !!"); |
109 | 113 | WARN("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); |
38 | 38 | |
39 | 39 | #include "eap_types.h" |
40 | 40 | #include "eap_sim.h" |
41 | #include "comp128.h" | |
41 | 42 | |
42 | 43 | extern int sha1_data_problems; |
44 | ||
45 | #undef DEBUG | |
46 | #undef DEBUG2 | |
47 | #undef ERROR | |
48 | ||
49 | #define DEBUG if (fr_debug_lvl && fr_log_fp) fr_printf_log | |
50 | #define DEBUG2 if ((fr_debug_lvl >= 2) && fr_log_fp) fr_printf_log | |
51 | #define ERROR if (fr_debug_lvl && fr_log_fp) fr_printf_log | |
43 | 52 | |
44 | 53 | #define USEC 1000000 |
45 | 54 | |
85 | 94 | typedef struct rc_eap_context { |
86 | 95 | int eap_type; //!< contains the EAP-Type |
87 | 96 | char password[256]; //!< copy of User-Password (or CHAP-Password). |
97 | VALUE_PAIR *ki; | |
88 | 98 | union { |
89 | 99 | rc_eap_sim_context_t sim; |
90 | 100 | rc_eap_md5_context_t md5; |
136 | 146 | char password[256]; |
137 | 147 | char const *name; //!< Test name (as specified in the request). |
138 | 148 | }; |
149 | ||
150 | typedef struct eap_sim_server_state { | |
151 | enum eapsim_serverstates state; | |
152 | struct eapsim_keys keys; | |
153 | int sim_id; | |
154 | } eap_sim_state_t; | |
139 | 155 | |
140 | 156 | |
141 | 157 | static TALLOC_CTX *autofree; |
294 | 310 | |
295 | 311 | /* Determine where to read the VP's from. */ |
296 | 312 | if (filename && strcmp(filename, "-") != 0) { |
297 | DEBUG2("Opening input file: %s", filename); | |
313 | DEBUG2("Opening input file: %s\n", filename); | |
298 | 314 | file_in = fopen(filename, "r"); |
299 | 315 | if (!file_in) { |
300 | ERROR("Error opening %s: %s", filename, strerror(errno)); | |
316 | ERROR("Error opening %s: %s\n", filename, strerror(errno)); | |
301 | 317 | return 0; |
302 | 318 | } |
303 | 319 | input = filename; |
304 | 320 | } else { |
305 | DEBUG2("Reading input vps from stdin"); | |
321 | DEBUG2("Reading input vps from stdin\n"); | |
306 | 322 | file_in = stdin; |
307 | 323 | input = "stdin"; |
308 | 324 | } |
313 | 329 | MEM(request = talloc_zero(ctx, rc_input_vps_t)); |
314 | 330 | |
315 | 331 | if (fr_pair_list_afrom_file(request, &request->vps_in, file_in, &file_done) < 0) { |
316 | ERROR("Error parsing entry %u from input: %s", input_num, input); | |
332 | ERROR("Error parsing entry %u from input: %s\n", input_num, input); | |
317 | 333 | talloc_free(request); |
318 | 334 | break; |
319 | 335 | } |
337 | 353 | if (file_in != stdin) fclose(file_in); |
338 | 354 | |
339 | 355 | /* And we're done. */ |
340 | DEBUG("Read %d element(s) from input: %s", list->size, input); | |
356 | DEBUG("Read %d element(s) from input: %s\n", list->size, input); | |
341 | 357 | return 1; |
342 | 358 | } |
343 | 359 | |
398 | 414 | case PW_PACKET_SRC_PORT: |
399 | 415 | if ((vp->vp_integer < 1024) || |
400 | 416 | (vp->vp_integer > 65535)) { |
401 | DEBUG("Invalid value '%u' for Packet-Src-Port", vp->vp_integer); | |
417 | DEBUG("Invalid value '%u' for Packet-Src-Port\n", vp->vp_integer); | |
402 | 418 | } else { |
403 | 419 | packet->src_port = (vp->vp_integer & 0xffff); |
404 | 420 | } |
440 | 456 | |
441 | 457 | da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0); |
442 | 458 | if (!da) { |
443 | ERROR("Attribute 'Digest-Attributes' not found by value"); | |
459 | ERROR("Attribute 'Digest-Attributes' not found by value\n"); | |
444 | 460 | exit(1); |
445 | 461 | } |
446 | 462 | vp->da = da; |
484 | 500 | |
485 | 501 | if (packet->dst_ipaddr.af == AF_UNSPEC) { |
486 | 502 | if (!server_addr_init) { |
487 | DEBUG("No server was given, and input entry %u did not contain Packet-Dst-IP-Address, ignored.", trans->input_vps->num); | |
503 | DEBUG("No server was given, and input entry %u did not contain Packet-Dst-IP-Address, ignored.\n", trans->input_vps->num); | |
488 | 504 | return 0; |
489 | 505 | } |
490 | 506 | packet->dst_ipaddr = server_ipaddr; |
493 | 509 | /* Use the default set on the command line. */ |
494 | 510 | if (packet->code == PW_CODE_UNDEFINED) { |
495 | 511 | if (packet_code == PW_CODE_UNDEFINED) { |
496 | DEBUG("No packet type was given, and input entry %u did not contain Packet-Type, ignored.", trans->input_vps->num); | |
512 | DEBUG("No packet type was given, and input entry %u did not contain Packet-Type, ignored.\n", trans->input_vps->num); | |
497 | 513 | return 0; |
498 | 514 | } |
499 | 515 | packet->code = packet_code; |
503 | 519 | if (packet->dst_port == 0) { |
504 | 520 | rc_get_port(packet->code, &packet->dst_port); |
505 | 521 | if (packet->dst_port == 0) { |
506 | DEBUG("Can't determine destination port for input entry %u, ignored.", trans->input_vps->num); | |
522 | DEBUG("Can't determine destination port for input entry %u, ignored.\n", trans->input_vps->num); | |
507 | 523 | return 0; |
508 | 524 | } |
509 | 525 | } |
544 | 560 | if (vp) { |
545 | 561 | strlcpy(trans->eap_context->password, vp->vp_strvalue, sizeof(trans->eap_context->password)); |
546 | 562 | } |
547 | } | |
548 | } | |
563 | ||
564 | vp = fr_pair_find_by_num(packet->vps, PW_EAP_SIM_KI, 0, TAG_ANY); | |
565 | if (vp) trans->eap_context->ki = fr_pair_copy(autofree, vp); | |
566 | } | |
567 | } | |
568 | ||
549 | 569 | |
550 | 570 | /** Grab an element from the input list. Initialize a new transaction context, using this element. |
551 | 571 | */ |
604 | 624 | num_ongoing --; |
605 | 625 | num_finished ++; |
606 | 626 | |
607 | DEBUG4("pl: %d, ev: %d, in: %d", fr_packet_list_num_outgoing(pl), fr_event_list_num_elements(ev_list), rc_vps_list_in.size); | |
627 | DEBUG4("pl: %d, ev: %d, in: %d\n", fr_packet_list_num_outgoing(pl), fr_event_list_num_elements(ev_list), rc_vps_list_in.size); | |
608 | 628 | } |
609 | 629 | |
610 | 630 | |
648 | 668 | } |
649 | 669 | } |
650 | 670 | |
671 | ||
672 | static void generate_triplets(RADIUS_PACKET *packet, VALUE_PAIR *ki, uint8_t const *ch) | |
673 | { | |
674 | int i, idx; | |
675 | eap_sim_state_t ess; | |
676 | ||
677 | for (idx = 0; idx < 3; idx++) { | |
678 | VALUE_PAIR *vp; | |
679 | char *p; | |
680 | char buffer[33]; /* 32 hexits (16 bytes) + 1 */ | |
681 | ||
682 | for (i = 0; i < EAPSIM_RAND_SIZE; i++) { | |
683 | ess.keys.rand[idx][i] = ch[(idx * EAPSIM_RAND_SIZE) + i]; | |
684 | } | |
685 | ||
686 | /* | |
687 | * <sigh>, we always do version 1. | |
688 | */ | |
689 | switch (EAP_SIM_VERSION) { | |
690 | case 1: | |
691 | comp128v1(ess.keys.sres[idx], ess.keys.Kc[idx], ki->vp_octets, ess.keys.rand[idx]); | |
692 | break; | |
693 | ||
694 | case 2: | |
695 | comp128v23(ess.keys.sres[idx], ess.keys.Kc[idx], ki->vp_octets, ess.keys.rand[idx], | |
696 | true); | |
697 | break; | |
698 | ||
699 | case 3: | |
700 | comp128v23(ess.keys.sres[idx], ess.keys.Kc[idx], ki->vp_octets, ess.keys.rand[idx], | |
701 | false); | |
702 | break; | |
703 | ||
704 | case 4: | |
705 | DEBUG("Comp128-4 algorithm is not supported as details have not yet been published. " | |
706 | "If you have details of this algorithm please contact the FreeRADIUS " | |
707 | "maintainers\n"); | |
708 | break; | |
709 | ||
710 | default: | |
711 | DEBUG("Unknown/unsupported algorithm Comp128-4\n"); | |
712 | } | |
713 | ||
714 | ||
715 | DEBUG2("Generated following triplets for round %i:\n", idx); | |
716 | ||
717 | p = buffer; | |
718 | for (i = 0; i < EAPSIM_RAND_SIZE; i++) { | |
719 | p += sprintf(p, "%02x", ess.keys.rand[idx][i]); | |
720 | } | |
721 | DEBUG2("RAND%d : 0x%s\n", idx, buffer); | |
722 | vp = fr_pair_afrom_num(packet, PW_EAP_SIM_RAND1 + idx, 0); | |
723 | fr_pair_value_memcpy(vp, ess.keys.rand[idx], EAPSIM_RAND_SIZE); | |
724 | fr_pair_add(&packet->vps, vp); | |
725 | ||
726 | p = buffer; | |
727 | for (i = 0; i < EAPSIM_SRES_SIZE; i++) { | |
728 | p += sprintf(p, "%02x", ess.keys.sres[idx][i]); | |
729 | } | |
730 | DEBUG2("SRES%d : 0x%s\n", idx, buffer); | |
731 | vp = fr_pair_afrom_num(packet, PW_EAP_SIM_SRES1 + idx, 0); | |
732 | fr_pair_value_memcpy(vp, ess.keys.sres[idx], EAPSIM_SRES_SIZE); | |
733 | fr_pair_add(&packet->vps, vp); | |
734 | ||
735 | p = buffer; | |
736 | for (i = 0; i < EAPSIM_KC_SIZE; i++) { | |
737 | p += sprintf(p, "%02x", ess.keys.Kc[idx][i]); | |
738 | } | |
739 | DEBUG2("Kc%d : 0x%s\n", idx, buffer); | |
740 | vp = fr_pair_afrom_num(packet, PW_EAP_SIM_KC1 + idx, 0); | |
741 | fr_pair_value_memcpy(vp, ess.keys.Kc[idx], EAPSIM_KC_SIZE); | |
742 | fr_pair_add(&packet->vps, vp); | |
743 | } | |
744 | } | |
745 | ||
746 | ||
651 | 747 | /* |
652 | 748 | * we got an EAP-Request/Sim/Start message in a legal state. |
653 | 749 | * |
661 | 757 | uint16_t const *versions; |
662 | 758 | uint16_t selectedversion; |
663 | 759 | unsigned int i,versioncount; |
760 | VALUE_PAIR *ki; | |
664 | 761 | |
665 | 762 | /* form new response clear of any EAP stuff */ |
666 | 763 | rc_cleanresp(rep); |
667 | 764 | |
668 | 765 | if ((vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_VERSION_LIST, 0, TAG_ANY)) == NULL) { |
669 | ERROR("illegal start message has no VERSION_LIST"); | |
766 | ERROR("illegal start message has no VERSION_LIST\n"); | |
670 | 767 | return 0; |
671 | 768 | } |
672 | 769 | |
675 | 772 | /* verify that the attribute length is big enough for a length field */ |
676 | 773 | if (vp->vp_length < 4) |
677 | 774 | { |
678 | ERROR("start message has illegal VERSION_LIST. Too short: %u", (unsigned int) vp->vp_length); | |
775 | ERROR("start message has illegal VERSION_LIST. Too short: %u\n", (unsigned int) vp->vp_length); | |
679 | 776 | return 0; |
680 | 777 | } |
681 | 778 | |
685 | 782 | */ |
686 | 783 | if ((unsigned)vp->vp_length <= (versioncount*2 + 2)) |
687 | 784 | { |
688 | ERROR("start message is too short. Claimed %d versions does not fit in %u bytes", versioncount, (unsigned int) vp->vp_length); | |
785 | ERROR("start message is too short. Claimed %d versions does not fit in %u bytes\n", versioncount, (unsigned int) vp->vp_length); | |
689 | 786 | return 0; |
690 | 787 | } |
691 | 788 | |
710 | 807 | } |
711 | 808 | if (selectedversion == 0) |
712 | 809 | { |
713 | ERROR("eap-sim start message. No compatible version found. We need %d", EAP_SIM_VERSION); | |
810 | ERROR("eap-sim start message. No compatible version found. We need %d\n", EAP_SIM_VERSION); | |
714 | 811 | for (i=0; i < versioncount; i++) |
715 | 812 | { |
716 | ERROR("\tfound version %d", | |
813 | ERROR("\tfound version %d\n", | |
717 | 814 | ntohs(versions[i+1])); |
718 | 815 | } |
719 | 816 | } |
731 | 828 | if (!fullauthidreq_vp || |
732 | 829 | anyidreq_vp != NULL || |
733 | 830 | permanentidreq_vp != NULL) { |
734 | ERROR("start message has %sanyidreq, %sfullauthid and %spermanentid. Illegal combination.", | |
831 | ERROR("start message has %sanyidreq, %sfullauthid and %spermanentid. Illegal combination.\n", | |
735 | 832 | (anyidreq_vp != NULL ? "a ": "no "), |
736 | 833 | (fullauthidreq_vp != NULL ? "a ": "no "), |
737 | 834 | (permanentidreq_vp != NULL ? "a ": "no ")); |
795 | 892 | vp = fr_pair_find_by_num(rep->vps, PW_USER_NAME, 0, TAG_ANY); |
796 | 893 | if (!vp) |
797 | 894 | { |
798 | ERROR("eap-sim: We need to have a User-Name attribute!"); | |
895 | ERROR("eap-sim: We need to have a User-Name attribute!\n"); | |
799 | 896 | return 0; |
800 | 897 | } |
801 | 898 | newvp = fr_pair_afrom_num(rep, PW_EAP_SIM_IDENTITY, 0); |
814 | 911 | eap_context->eap.sim.keys.identitylen = idlen; |
815 | 912 | } |
816 | 913 | |
914 | ki = fr_pair_find_by_num(req->vps, PW_EAP_SIM_KI, 0, TAG_ANY); | |
915 | if (ki && !fr_pair_find_by_num(req->vps, PW_EAP_SIM_RAND1, 0, TAG_ANY)) { | |
916 | generate_triplets(req, ki, NULL); | |
917 | } | |
918 | ||
817 | 919 | return 1; |
818 | 920 | } |
921 | ||
819 | 922 | |
820 | 923 | /* |
821 | 924 | * we got an EAP-Request/Sim/Challenge message in a legal state. |
840 | 943 | mac = fr_pair_find_by_num(req->vps, PW_EAP_SIM_MAC, 0, TAG_ANY); |
841 | 944 | randvp= fr_pair_find_by_num(req->vps, PW_EAP_SIM_RAND, 0, TAG_ANY); |
842 | 945 | if (!mac || !randvp) { |
843 | ERROR("challenge message needs to contain RAND and MAC"); | |
946 | ERROR("challenge message needs to contain RAND and MAC\n"); | |
844 | 947 | return 0; |
845 | 948 | } |
846 | 949 | |
863 | 966 | if (!randcfgvp[0] || |
864 | 967 | !randcfgvp[1] || |
865 | 968 | !randcfgvp[2]) { |
866 | ERROR("needs to have rand1, 2 and 3 set."); | |
867 | return 0; | |
969 | int i; | |
970 | VALUE_PAIR *ki; | |
971 | ||
972 | /* | |
973 | * Generate a new RAND value, and derive Kc and SRES from | |
974 | * Ki, but only if we don't already have the random | |
975 | * numbers. | |
976 | */ | |
977 | ki = eap_context->ki; | |
978 | if (!ki) { | |
979 | ERROR("Need EAP-SIM-Rand1, EAP-SIM-Rand2, and EAP-SIM-Rand3\n"); | |
980 | return 0; | |
981 | } | |
982 | ||
983 | for (i = 0; i < 3; i++) { | |
984 | fr_pair_delete_by_num(&req->vps, PW_EAP_SIM_RAND1 + i, 0, TAG_ANY); | |
985 | fr_pair_delete_by_num(&req->vps, PW_EAP_SIM_SRES1 + i, 0, TAG_ANY); | |
986 | fr_pair_delete_by_num(&req->vps, PW_EAP_SIM_KC1 + i, 0, TAG_ANY); | |
987 | } | |
988 | ||
989 | generate_triplets(rep, ki, randvp->vp_octets + 2); | |
990 | ||
991 | randcfgvp[0] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND1, 0, TAG_ANY); | |
992 | randcfgvp[1] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND2, 0, TAG_ANY); | |
993 | randcfgvp[2] = fr_pair_find_by_num(rep->vps, PW_EAP_SIM_RAND3, 0, TAG_ANY); | |
994 | ||
995 | if (!randcfgvp[0] || | |
996 | !randcfgvp[1] || | |
997 | !randcfgvp[2]) { | |
998 | ERROR("Failed to create triplets\n"); | |
999 | return 0; | |
1000 | } | |
868 | 1001 | } |
869 | 1002 | |
870 | 1003 | if (memcmp(randcfg[0], randcfgvp[0]->vp_octets, EAPSIM_RAND_SIZE)!=0 || |
871 | memcmp(randcfg[1], randcfgvp[1]->vp_octets, EAPSIM_RAND_SIZE)!=0 || | |
872 | memcmp(randcfg[2], randcfgvp[2]->vp_octets, EAPSIM_RAND_SIZE)!=0) { | |
873 | int rnum,i,j; | |
874 | ||
875 | ERROR("one of rand 1,2,3 didn't match"); | |
876 | for (rnum = 0; rnum < 3; rnum++) { | |
877 | ERROR("received rand %d: ", rnum); | |
878 | j=0; | |
879 | for (i = 0; i < EAPSIM_RAND_SIZE; i++) { | |
880 | if (j==4) { | |
881 | DEBUG("_"); | |
882 | j=0; | |
883 | } | |
884 | j++; | |
885 | ||
886 | ERROR("%02x", randcfg[rnum][i]); | |
887 | } | |
888 | ERROR("configured rand %d: ", rnum); | |
889 | j=0; | |
890 | for (i = 0; i < EAPSIM_RAND_SIZE; i++) { | |
891 | if (j==4) { | |
892 | DEBUG("_"); | |
893 | j=0; | |
894 | } | |
895 | j++; | |
896 | ||
897 | ERROR("%02x", randcfgvp[rnum]->vp_octets[i]); | |
898 | } | |
899 | } | |
900 | return 0; | |
1004 | memcmp(randcfg[1], randcfgvp[1]->vp_octets, EAPSIM_RAND_SIZE)!=0 || | |
1005 | memcmp(randcfg[2], randcfgvp[2]->vp_octets, EAPSIM_RAND_SIZE)!=0) { | |
1006 | int rnum, i; | |
1007 | ||
1008 | ERROR("one of rand 1,2,3 didn't match\n"); | |
1009 | for (rnum = 0; rnum < 3; rnum++) { | |
1010 | ERROR("rand %d\trecv\tconfig\n", rnum); | |
1011 | for (i = 0; i < EAPSIM_RAND_SIZE; i++) { | |
1012 | fprintf(fr_log_fp, "\t%02x\t%02x\n", | |
1013 | randcfg[rnum][i], randcfgvp[rnum]->vp_octets[i]); | |
1014 | } | |
1015 | } | |
1016 | return 0; | |
901 | 1017 | } |
902 | 1018 | } |
903 | 1019 | |
915 | 1031 | if (!sres1 || |
916 | 1032 | !sres2 || |
917 | 1033 | !sres3) { |
918 | ERROR("needs to have sres1, 2 and 3 set."); | |
1034 | ERROR("needs to have sres1, 2 and 3 set.\n"); | |
919 | 1035 | return 0; |
920 | 1036 | } |
921 | 1037 | memcpy(eap_context->eap.sim.keys.sres[0], sres1->vp_strvalue, sizeof(eap_context->eap.sim.keys.sres[0])); |
929 | 1045 | if (!Kc1 || |
930 | 1046 | !Kc2 || |
931 | 1047 | !Kc3) { |
932 | ERROR("needs to have Kc1, 2 and 3 set."); | |
1048 | ERROR("needs to have Kc1, 2 and 3 set.\n"); | |
933 | 1049 | return 0; |
934 | 1050 | } |
935 | 1051 | memcpy(eap_context->eap.sim.keys.Kc[0], Kc1->vp_strvalue, sizeof(eap_context->eap.sim.keys.Kc[0])); |
939 | 1055 | /* all set, calculate keys */ |
940 | 1056 | eapsim_calculate_keys(&eap_context->eap.sim.keys); |
941 | 1057 | |
942 | if (rad_debug_lvl) { | |
1058 | if (rad_debug_lvl > 2) { | |
943 | 1059 | eapsim_dump_mk(&eap_context->eap.sim.keys); |
944 | 1060 | } |
945 | 1061 | |
947 | 1063 | if (eapsim_checkmac(NULL, req->vps, eap_context->eap.sim.keys.K_aut, |
948 | 1064 | eap_context->eap.sim.keys.nonce_mt, sizeof(eap_context->eap.sim.keys.nonce_mt), |
949 | 1065 | calcmac)) { |
950 | DEBUG("MAC check succeed"); | |
1066 | DEBUG2("MAC check succeed\n"); | |
951 | 1067 | } else { |
952 | 1068 | int i, j; |
953 | 1069 | j=0; |
954 | DEBUG("calculated MAC ("); | |
1070 | DEBUG("calculated MAC (\n"); | |
955 | 1071 | for (i = 0; i < 20; i++) { |
956 | 1072 | if (j==4) { |
957 | 1073 | printf("_"); |
959 | 1075 | } |
960 | 1076 | j++; |
961 | 1077 | |
962 | DEBUG("%02x", calcmac[i]); | |
963 | } | |
964 | DEBUG("did not match"); | |
1078 | DEBUG("%02x\n", calcmac[i]); | |
1079 | } | |
1080 | DEBUG("did not match\n"); | |
965 | 1081 | return 0; |
966 | 1082 | } |
967 | 1083 | |
1008 | 1124 | RADIUS_PACKET *req, RADIUS_PACKET *resp) |
1009 | 1125 | { |
1010 | 1126 | enum eapsim_clientstates state, newstate; |
1011 | enum eapsim_subtype subtype; | |
1127 | enum eapsim_subtype subtype, newsubtype; | |
1012 | 1128 | VALUE_PAIR *vp, *statevp, *radstate, *eapid; |
1013 | 1129 | char statenamebuf[32], subtypenamebuf[32]; |
1014 | 1130 | |
1046 | 1162 | } |
1047 | 1163 | subtype = vp->vp_integer; |
1048 | 1164 | |
1165 | DEBUG2("IN state %s subtype %s\n", | |
1166 | sim_state2name(state, statenamebuf, sizeof(statenamebuf)), | |
1167 | sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); | |
1168 | ||
1049 | 1169 | /* |
1050 | 1170 | * look for the appropriate state, and process incoming message |
1051 | 1171 | */ |
1060 | 1180 | case EAPSIM_NOTIFICATION: |
1061 | 1181 | case EAPSIM_REAUTH: |
1062 | 1182 | default: |
1063 | ERROR("sim in state %s message %s is illegal. Reply dropped.", | |
1064 | sim_state2name(state, statenamebuf, sizeof(statenamebuf)), | |
1065 | sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); | |
1183 | ERROR("sim in state %s message %s is illegal. Reply dropped.\n", | |
1184 | sim_state2name(state, statenamebuf, sizeof(statenamebuf)), | |
1185 | sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); | |
1066 | 1186 | /* invalid state, drop message */ |
1067 | 1187 | return 0; |
1068 | 1188 | } |
1080 | 1200 | break; |
1081 | 1201 | |
1082 | 1202 | default: |
1083 | ERROR("sim in state %s message %s is illegal. Reply dropped.", | |
1203 | ERROR("sim in state %s message %s is illegal. Reply dropped.\n", | |
1084 | 1204 | sim_state2name(state, statenamebuf, sizeof(statenamebuf)), |
1085 | 1205 | sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); |
1086 | 1206 | /* invalid state, drop message */ |
1090 | 1210 | |
1091 | 1211 | |
1092 | 1212 | default: |
1093 | ERROR("sim in illegal state %s", | |
1213 | ERROR("sim in illegal state %s\n", | |
1094 | 1214 | sim_state2name(state, statenamebuf, sizeof(statenamebuf))); |
1095 | 1215 | return 0; |
1096 | 1216 | } |
1103 | 1223 | |
1104 | 1224 | /* copy the radius state object in */ |
1105 | 1225 | fr_pair_replace(&(resp->vps), radstate); |
1226 | ||
1227 | vp = fr_pair_find_by_num(req->vps, PW_EAP_SIM_SUBTYPE, 0, TAG_ANY); | |
1228 | newsubtype = vp->vp_integer; | |
1229 | ||
1230 | ||
1231 | DEBUG2("MOVE from state %s subtype %s\n", | |
1232 | sim_state2name(state, statenamebuf, sizeof(statenamebuf)), | |
1233 | sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); | |
1234 | ||
1235 | DEBUG2(" to state %s subtype %s\n", | |
1236 | sim_state2name(newstate, statenamebuf, sizeof(statenamebuf)), | |
1237 | sim_subtype2name(newsubtype, subtypenamebuf, sizeof(subtypenamebuf))); | |
1106 | 1238 | |
1107 | 1239 | statevp->vp_integer = newstate; |
1108 | 1240 | return 1; |
1122 | 1254 | |
1123 | 1255 | if ((state = fr_pair_list_copy_by_num(NULL, req->vps, PW_STATE, 0, TAG_ANY)) == NULL) |
1124 | 1256 | { |
1125 | ERROR("no state attribute found"); | |
1257 | ERROR("no state attribute found\n"); | |
1126 | 1258 | return 0; |
1127 | 1259 | } |
1128 | 1260 | |
1129 | 1261 | if ((id = fr_pair_list_copy_by_num(NULL, req->vps, PW_EAP_ID, 0, TAG_ANY)) == NULL) |
1130 | 1262 | { |
1131 | ERROR("no EAP-ID attribute found"); | |
1263 | ERROR("no EAP-ID attribute found\n"); | |
1132 | 1264 | return 0; |
1133 | 1265 | } |
1134 | 1266 | identifier = id->vp_integer; |
1135 | 1267 | |
1136 | 1268 | if ((vp = fr_pair_find_by_num(req->vps, PW_EAP_TYPE_BASE+PW_EAP_MD5, 0, TAG_ANY)) == NULL) |
1137 | 1269 | { |
1138 | ERROR("no EAP-MD5 attribute found"); | |
1270 | ERROR("no EAP-MD5 attribute found\n"); | |
1139 | 1271 | return 0; |
1140 | 1272 | } |
1141 | 1273 | |
1146 | 1278 | /* sanitize items */ |
1147 | 1279 | if (valuesize > vp->vp_length) |
1148 | 1280 | { |
1149 | ERROR("md5 valuesize if too big (%u > %u)", | |
1281 | ERROR("md5 valuesize if too big (%u > %u)\n", | |
1150 | 1282 | (unsigned int) valuesize, (unsigned int) vp->vp_length); |
1151 | 1283 | return 0; |
1152 | 1284 | } |
1201 | 1333 | |
1202 | 1334 | mysockfd = fr_socket(src_ipaddr, src_port); |
1203 | 1335 | if (mysockfd < 0) { |
1204 | ERROR("Failed to create new socket: %s", fr_strerror()); | |
1336 | ERROR("Failed to create new socket: %s\n", fr_strerror()); | |
1205 | 1337 | exit(1); |
1206 | 1338 | } |
1207 | 1339 | |
1208 | 1340 | if (!fr_packet_list_socket_add(pl, mysockfd, ipproto, dst_ipaddr, dst_port, NULL)) { |
1209 | ERROR("Failed to add new socket: %s", fr_strerror()); | |
1341 | ERROR("Failed to add new socket: %s\n", fr_strerror()); | |
1210 | 1342 | exit(1); |
1211 | 1343 | } |
1212 | 1344 | |
1213 | 1345 | num_sockets ++; |
1214 | DEBUG("Added new socket: %d (num sockets: %d)", mysockfd, num_sockets); | |
1346 | DEBUG("Added new socket: %d (num sockets: %d)\n", mysockfd, num_sockets); | |
1215 | 1347 | } |
1216 | 1348 | |
1217 | 1349 | /** Send one packet for a transaction. |
1244 | 1376 | break; |
1245 | 1377 | } |
1246 | 1378 | if (nb_sock_add >= 1) { |
1247 | ERROR("Added %d new socket(s), but still could not get an ID (currently: %d outgoing requests).", | |
1379 | ERROR("Added %d new socket(s), but still could not get an ID (currently: %d outgoing requests).\n", | |
1248 | 1380 | nb_sock_add, fr_packet_list_num_outgoing(pl)); |
1249 | 1381 | exit(1); |
1250 | 1382 | } |
1266 | 1398 | /* |
1267 | 1399 | * Send the packet. |
1268 | 1400 | */ |
1269 | DEBUG("Transaction: %u, sending packet: %u (id: %u)...", trans->id, trans->num_packet, packet->id); | |
1401 | DEBUG2("Transaction: %u, sending packet: %u (id: %u)...\n", trans->id, trans->num_packet, packet->id); | |
1270 | 1402 | |
1271 | 1403 | gettimeofday(&packet->timestamp, NULL); /* set outgoing packet timestamp. */ |
1272 | 1404 | |
1273 | 1405 | if (rad_send(packet, NULL, secret) < 0) { |
1274 | ERROR("Failed to send packet (sockfd: %d, id: %d): %s", | |
1406 | ERROR("Failed to send packet (sockfd: %d, id: %d): %s\n", | |
1275 | 1407 | packet->sockfd, packet->id, fr_strerror()); |
1276 | 1408 | } |
1277 | 1409 | |
1310 | 1442 | |
1311 | 1443 | RADIUS_PACKET *packet = trans->packet; |
1312 | 1444 | |
1313 | DEBUG2("Deallocating (sockfd: %d, id: %d)", packet->sockfd, packet->id); | |
1445 | DEBUG2("Deallocating (sockfd: %d, id: %d)\n", packet->sockfd, packet->id); | |
1314 | 1446 | |
1315 | 1447 | /* |
1316 | 1448 | * One more unused RADIUS ID. |
1376 | 1508 | */ |
1377 | 1509 | reply = fr_packet_list_recv(pl, &set); |
1378 | 1510 | if (!reply) { |
1379 | ERROR("Received bad packet: %s", fr_strerror()); | |
1511 | ERROR("Received bad packet: %s\n", fr_strerror()); | |
1380 | 1512 | return -1; /* bad packet */ |
1381 | 1513 | } |
1382 | 1514 | |
1397 | 1529 | /* got reply to packet we didn't send. |
1398 | 1530 | * (or maybe we sent it, got no response, freed the ID. Then server responds to first request.) |
1399 | 1531 | */ |
1400 | DEBUG("No outstanding request was found for reply from %s, port %d (sockfd: %d, id: %d)", | |
1532 | DEBUG("No outstanding request was found for reply from %s, port %d (sockfd: %d, id: %d)\n", | |
1401 | 1533 | inet_ntop(reply->src_ipaddr.af, &reply->src_ipaddr.ipaddr, buffer, sizeof(buffer)), |
1402 | 1534 | reply->src_port, reply->sockfd, reply->id); |
1403 | 1535 | rad_free(&reply); |
1416 | 1548 | * (or maybe this is a response to another packet we sent, for which we got no response, |
1417 | 1549 | * freed the ID, then reused it. Then server responds to first packet.) |
1418 | 1550 | */ |
1419 | DEBUG("Conflicting response authenticator for reply from %s (sockfd: %d, id: %d)", | |
1551 | DEBUG("Conflicting response authenticator for reply from %s (sockfd: %d, id: %d)\n", | |
1420 | 1552 | inet_ntop(reply->src_ipaddr.af, &reply->src_ipaddr.ipaddr, buffer, sizeof(buffer)), |
1421 | 1553 | reply->sockfd, reply->id); |
1422 | 1554 | |
1432 | 1564 | |
1433 | 1565 | if (rad_decode(trans->reply, trans->packet, secret) != 0) { |
1434 | 1566 | /* This can fail if packet contains too many attributes. */ |
1435 | DEBUG("Failed decoding reply"); | |
1567 | DEBUG("Failed decoding reply\n"); | |
1436 | 1568 | goto packet_done; |
1437 | 1569 | } |
1438 | 1570 | |
1443 | 1575 | rc_unmap_eap_methods(trans->reply); |
1444 | 1576 | } |
1445 | 1577 | |
1446 | DEBUG("Transaction: %u, received packet (id: %u).", trans->id, trans->reply->id); | |
1578 | DEBUG2("Transaction: %u, received packet (id: %u).\n", trans->id, trans->reply->id); | |
1447 | 1579 | |
1448 | 1580 | if (fr_debug_lvl > 0) fr_packet_header_print(fr_log_fp, trans->reply, true); |
1449 | 1581 | if (fr_debug_lvl > 0) vp_printlist(fr_log_fp, trans->reply->vps); |
1483 | 1615 | } |
1484 | 1616 | } |
1485 | 1617 | |
1486 | goto eap_done; | |
1487 | ||
1488 | eap_done: | |
1489 | 1618 | /* EAP transaction ends here (no more requests from EAP server). */ |
1490 | 1619 | |
1491 | 1620 | /* |
1500 | 1629 | DEBUG("EAP transaction finished, but reply does not contain EAP-Code = Success"); |
1501 | 1630 | goto packet_done; |
1502 | 1631 | } |
1632 | ||
1503 | 1633 | goto packet_done; |
1504 | 1634 | |
1505 | 1635 | packet_done: |
1553 | 1683 | timeradd(&tv_event, &tv_timeout, &tv_event); |
1554 | 1684 | |
1555 | 1685 | if (!fr_event_insert(ev_list, rc_evcb_packet_timeout, (void *)trans, &tv_event, &trans->event)) { |
1556 | ERROR("Failed to insert event"); | |
1686 | ERROR("Failed to insert event\n"); | |
1557 | 1687 | exit(1); |
1558 | 1688 | } |
1559 | 1689 | } |
1737 | 1867 | } |
1738 | 1868 | |
1739 | 1869 | if (ip_hton(&server_ipaddr, force_af, hostname, false) < 0) { |
1740 | ERROR("%s: Failed to find IP address for host %s: %s", progname, hostname, strerror(errno)); | |
1870 | ERROR("%s: Failed to find IP address for host %s: %s\n", progname, hostname, strerror(errno)); | |
1741 | 1871 | exit(1); |
1742 | 1872 | } |
1743 | 1873 | server_addr_init = true; |
1833 | 1963 | timeout = atof(optarg); |
1834 | 1964 | break; |
1835 | 1965 | case 'v': |
1836 | printf("$Id$ built on "__DATE__ "at "__TIME__ ""); | |
1966 | printf("$Id$" | |
1967 | #ifndef ENABLE_REPRODUCIBLE_BUILDS | |
1968 | ", built on " __DATE__ " at " __TIME__ | |
1969 | #endif | |
1970 | "\n" | |
1971 | ); | |
1837 | 1972 | exit(0); |
1838 | 1973 | |
1839 | 1974 | case 'S': |
1840 | 1975 | fp = fopen(optarg, "r"); |
1841 | 1976 | if (!fp) { |
1842 | ERROR("Error opening %s: %s", | |
1977 | ERROR("Error opening %s: %s\n", | |
1843 | 1978 | optarg, fr_syserror(errno)); |
1844 | 1979 | exit(1); |
1845 | 1980 | } |
1846 | 1981 | if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { |
1847 | ERROR("Error reading %s: %s", | |
1982 | ERROR("Error reading %s: %s\n", | |
1848 | 1983 | optarg, fr_syserror(errno)); |
1849 | 1984 | exit(1); |
1850 | 1985 | } |
1859 | 1994 | } |
1860 | 1995 | |
1861 | 1996 | if (strlen(filesecret) < 2) { |
1862 | ERROR("Secret in %s is too short", optarg); | |
1997 | ERROR("Secret in %s is too short\n", optarg); | |
1863 | 1998 | exit(1); |
1864 | 1999 | } |
1865 | 2000 | secret = filesecret; |
1890 | 2025 | */ |
1891 | 2026 | DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, RADIUS_DICTIONARY); |
1892 | 2027 | if (dict_init(main_config.dictionary_dir, RADIUS_DICTIONARY) != 0) { |
1893 | ERROR("Errors reading dictionary: %s", fr_strerror()); | |
2028 | ERROR("Errors reading dictionary: %s\n", fr_strerror()); | |
1894 | 2029 | exit(1); |
1895 | 2030 | } |
1896 | 2031 | |
1899 | 2034 | */ |
1900 | 2035 | int rcode = dict_read(radius_dir, RADIUS_DICTIONARY); |
1901 | 2036 | if (rcode == -1) { |
1902 | ERROR("Errors reading %s/%s: %s", radius_dir, RADIUS_DICTIONARY, fr_strerror()); | |
2037 | ERROR("Errors reading %s/%s: %s\n", radius_dir, RADIUS_DICTIONARY, fr_strerror()); | |
1903 | 2038 | exit(1); |
1904 | 2039 | } |
1905 | 2040 | |
1918 | 2053 | if (!isdigit((int) argv[2][0])) { |
1919 | 2054 | packet_code = fr_str2int(rc_request_types, argv[2], -2); |
1920 | 2055 | if (packet_code == -2) { |
1921 | ERROR("Unrecognised request type \"%s\"", argv[2]); | |
2056 | ERROR("Unrecognised request type \"%s\"\n", argv[2]); | |
1922 | 2057 | usage(); |
1923 | 2058 | } |
1924 | 2059 | } else { |
1941 | 2076 | INFO("Loading input data..."); |
1942 | 2077 | if (!rc_load_input(autofree, filename, &rc_vps_list_in, 0) |
1943 | 2078 | || rc_vps_list_in.size == 0) { |
1944 | ERROR("No valid input. Nothing to send."); | |
2079 | ERROR("No valid input. Nothing to send.\n"); | |
1945 | 2080 | exit(EXIT_FAILURE); |
1946 | 2081 | } |
1947 | 2082 | INFO("Loaded: %d input element(s).", rc_vps_list_in.size); |
1952 | 2087 | /* Initialize the events list. */ |
1953 | 2088 | ev_list = fr_event_list_create(autofree, NULL); |
1954 | 2089 | if (!ev_list) { |
1955 | ERROR("Failed to create event list"); | |
2090 | ERROR("Failed to create event list\n"); | |
1956 | 2091 | exit(1); |
1957 | 2092 | } |
1958 | 2093 | |
2065 | 2200 | /* find eap message */ |
2066 | 2201 | e = eap_vp2packet(NULL, rep->vps); |
2067 | 2202 | if (!e) { |
2068 | ERROR("%s", fr_strerror()); | |
2203 | ERROR("failed decoding EAP: %s\n", fr_strerror()); | |
2069 | 2204 | return; |
2070 | 2205 | } |
2071 | 2206 | /* create EAP-ID and EAP-CODE attributes to start */ |
2147 | 2282 | |
2148 | 2283 | esvp = fr_pair_find_by_num(r->vps, PW_EAP_TYPE_BASE+PW_EAP_SIM, 0, TAG_ANY); |
2149 | 2284 | if (!esvp) { |
2150 | ERROR("eap: EAP-Sim attribute not found"); | |
2285 | ERROR("eap: EAP-Sim attribute not found\n"); | |
2151 | 2286 | return 0; |
2152 | 2287 | } |
2153 | 2288 |
83 | 83 | * EAP work. |
84 | 84 | */ |
85 | 85 | if (fr_ipaddr_cmp(&one->src_ipaddr, &two->src_ipaddr) != 0) { |
86 | WARN("EAP packets are arriving from two different upstream " | |
87 | "servers. Has there been a proxy fail-over?"); | |
86 | char src1[64], src2[64]; | |
87 | ||
88 | fr_ntop(src1, sizeof(src1), &one->src_ipaddr); | |
89 | fr_ntop(src2, sizeof(src2), &two->src_ipaddr); | |
90 | ||
91 | RATE_LIMIT(WARN("EAP packets for one session are arriving from two different upstream" | |
92 | "servers (%s and %s). Has there been a proxy fail-over?", | |
93 | src1, src2)); | |
88 | 94 | } |
89 | 95 | |
90 | 96 | return 0; |
469 | 475 | |
470 | 476 | memcpy(new, old, vp->vp_length); |
471 | 477 | new[vp->length] = '\0'; |
472 | new[vp->length + 1] = '\0'; | |
473 | 478 | vp->vp_strvalue = new; |
474 | 479 | |
475 | 480 | rad_const_free(old); |
0 | all.mk |
267 | 267 | { |
268 | 268 | eap_fast_tunnel_t *t = tls_session->opaque; |
269 | 269 | eap_tlv_crypto_binding_tlv_t binding; |
270 | memset(&binding, 0, sizeof(eap_tlv_crypto_binding_tlv_t)); | |
271 | 270 | const int len = sizeof(binding) - (&binding.reserved - (uint8_t *)&binding); |
272 | 271 | |
273 | 272 | RDEBUG("Sending Cryptobinding"); |
274 | 273 | |
274 | memset(&binding, 0, sizeof(eap_tlv_crypto_binding_tlv_t)); | |
275 | 275 | binding.tlv_type = htons(EAP_FAST_TLV_MANDATORY | EAP_FAST_TLV_CRYPTO_BINDING); |
276 | 276 | binding.length = htons(len); |
277 | 277 | binding.version = EAP_FAST_VERSION; |
281 | 281 | rad_assert(sizeof(binding.nonce) % sizeof(uint32_t) == 0); |
282 | 282 | RANDFILL(binding.nonce); |
283 | 283 | binding.nonce[sizeof(binding.nonce) - 1] &= ~0x01; /* RFC 4851 section 4.2.8 */ |
284 | ||
285 | 284 | |
286 | 285 | fr_hmac_sha1(binding.compound_mac, (uint8_t *)&binding, sizeof(binding), t->cmk, EAP_FAST_CMK_LEN); |
287 | 286 | |
1056 | 1055 | VALUE_PAIR *vp; |
1057 | 1056 | vp_cursor_t cursor; |
1058 | 1057 | eap_tlv_crypto_binding_tlv_t *binding = NULL; |
1058 | eap_tlv_crypto_binding_tlv_t my_binding; | |
1059 | 1059 | |
1060 | 1060 | for (vp = fr_cursor_init(&cursor, &fast_vps); vp; vp = fr_cursor_next(&cursor)) { |
1061 | 1061 | PW_CODE code = PW_CODE_ACCESS_REJECT; |
1084 | 1084 | t->stage = PROVISIONING; |
1085 | 1085 | break; |
1086 | 1086 | case EAP_FAST_TLV_CRYPTO_BINDING: |
1087 | if (!binding) { | |
1088 | binding = talloc_zero(request->packet, eap_tlv_crypto_binding_tlv_t); | |
1089 | memcpy(binding, vp->vp_octets, sizeof(*binding)); | |
1087 | if (!binding && (vp->vp_length >= sizeof(eap_tlv_crypto_binding_tlv_t))) { | |
1088 | binding = &my_binding; | |
1090 | 1089 | binding->tlv_type = htons(EAP_FAST_TLV_MANDATORY | EAP_FAST_TLV_CRYPTO_BINDING); |
1091 | 1090 | binding->length = htons(sizeof(*binding) - 2 * sizeof(uint16_t)); |
1091 | memcpy(&my_binding.reserved, vp->vp_octets, sizeof(my_binding) - 4); | |
1092 | 1092 | } |
1093 | 1093 | continue; |
1094 | 1094 | default: |
1135 | 1135 | |
1136 | 1136 | if (binding) { |
1137 | 1137 | PW_CODE code = eap_fast_crypto_binding(request, eap_session, tls_session, binding); |
1138 | if (code == PW_CODE_ACCESS_ACCEPT) | |
1138 | if (code == PW_CODE_ACCESS_ACCEPT) { | |
1139 | 1139 | t->stage = PROVISIONING; |
1140 | } | |
1141 | return code; | |
1140 | 1142 | } |
1141 | 1143 | |
1142 | 1144 | return PW_CODE_ACCESS_ACCEPT; |
42 | 42 | |
43 | 43 | char const *virtual_server; //!< Virtual server to use for processing |
44 | 44 | //!< inner EAP method. |
45 | char const *cipher_list; //!< cipher list specific to EAP-FAST | |
45 | 46 | bool req_client_cert; //!< Whether we require a client cert |
46 | 47 | //!< in the outer tunnel. |
47 | 48 | |
64 | 65 | { "default_eap_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, default_method_name), "mschapv2" }, |
65 | 66 | |
66 | 67 | { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED | PW_TYPE_NOT_EMPTY, rlm_eap_fast_t, virtual_server) , NULL}, |
68 | { "cipher_list", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_fast_t, cipher_list) , NULL}, | |
67 | 69 | |
68 | 70 | { "require_client_cert", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_fast_t, req_client_cert), "no" }, |
69 | 71 | |
120 | 122 | |
121 | 123 | if (talloc_array_length(inst->pac_opaque_key) - 1 != 32) { |
122 | 124 | ERROR("rlm_eap_fast.pac_opaque_key: Must be 32 bytes long"); |
123 | return -1; | |
124 | } | |
125 | ||
126 | // FIXME TLSv1.2 uses a different PRF and SSL_export_keying_material("key expansion") is forbidden | |
127 | if (!inst->tls_conf->disable_tlsv1_2) { | |
128 | ERROR("rlm_eap_fast.disable_tlsv1_2: require disable_tlsv1_2=yes"); | |
129 | 125 | return -1; |
130 | 126 | } |
131 | 127 | |
373 | 369 | static int mod_process(void *arg, eap_handler_t *handler) |
374 | 370 | { |
375 | 371 | int rcode; |
372 | int ret = 0; | |
376 | 373 | fr_tls_status_t status; |
377 | 374 | rlm_eap_fast_t *inst = (rlm_eap_fast_t *) arg; |
378 | 375 | tls_session_t *tls_session = (tls_session_t *) handler->opaque; |
397 | 394 | RDEBUG2("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>")); |
398 | 395 | } |
399 | 396 | |
397 | /* | |
398 | * Make request available to any SSL callbacks | |
399 | */ | |
400 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request); | |
400 | 401 | switch (status) { |
401 | 402 | /* |
402 | 403 | * EAP-TLS handshake was successful, tell the |
416 | 417 | * do nothing. |
417 | 418 | */ |
418 | 419 | case FR_TLS_HANDLED: |
419 | return 1; | |
420 | ret = 1; | |
421 | goto done; | |
420 | 422 | |
421 | 423 | /* |
422 | 424 | * Handshake is done, proceed with decoding tunneled |
429 | 431 | * Anything else: fail. |
430 | 432 | */ |
431 | 433 | default: |
432 | return 0; | |
434 | ret = 0; | |
435 | goto done; | |
433 | 436 | } |
434 | 437 | |
435 | 438 | /* |
447 | 450 | case PW_CODE_ACCESS_REJECT: |
448 | 451 | RDEBUG("Reject"); |
449 | 452 | eaptls_fail(handler, EAP_FAST_VERSION); |
450 | return 0; | |
453 | ret = 0; | |
454 | goto done; | |
451 | 455 | |
452 | 456 | /* |
453 | 457 | * Access-Challenge, continue tunneled conversation. |
456 | 460 | RDEBUG("Challenge"); |
457 | 461 | tls_handshake_send(request, tls_session); |
458 | 462 | eaptls_request(handler->eap_ds, tls_session); |
459 | return 1; | |
463 | ret = 1; | |
464 | goto done; | |
460 | 465 | |
461 | 466 | /* |
462 | 467 | * Success: Automatically return MPPE keys. |
463 | 468 | */ |
464 | 469 | case PW_CODE_ACCESS_ACCEPT: |
465 | RDEBUG("Note that the 'missing PRF label' message below is harmless. Please ignore it."); | |
466 | 470 | if (t->accept_vps) { |
467 | 471 | RDEBUG2("Using saved attributes from the original Access-Accept"); |
468 | 472 | rdebug_pair_list(L_DBG_LVL_2, request, t->accept_vps, NULL); |
472 | 476 | } else if (t->use_tunneled_reply) { |
473 | 477 | RDEBUG2("No saved attributes in the original Access-Accept"); |
474 | 478 | } |
475 | return eaptls_success(handler, EAP_FAST_VERSION); | |
479 | ret = eaptls_success(handler, EAP_FAST_VERSION); | |
480 | goto done; | |
476 | 481 | |
477 | 482 | /* |
478 | 483 | * No response packet, MUST be proxying it. |
484 | 489 | #ifdef WITH_PROXY |
485 | 490 | rad_assert(handler->request->proxy != NULL); |
486 | 491 | #endif |
487 | return 1; | |
492 | ret = 1; | |
493 | goto done; | |
488 | 494 | |
489 | 495 | default: |
490 | 496 | break; |
494 | 500 | * Something we don't understand: Reject it. |
495 | 501 | */ |
496 | 502 | eaptls_fail(handler, EAP_FAST_VERSION); |
497 | return 0; | |
503 | ||
504 | done: | |
505 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL); | |
506 | ||
507 | return ret; | |
498 | 508 | } |
499 | 509 | |
500 | 510 | static int eap_fast_tls_start(EAP_DS * eap_ds,tls_session_t *tls_session) |
545 | 555 | handler->opaque = tls_session = eaptls_session(handler, inst->tls_conf, client_cert); |
546 | 556 | |
547 | 557 | if (!tls_session) return 0; |
558 | ||
559 | if (inst->cipher_list) { | |
560 | RDEBUG("Over-riding main cipher list with '%s'", inst->cipher_list); | |
561 | ||
562 | if (!SSL_set_cipher_list(tls_session->ssl, inst->cipher_list)) { | |
563 | REDEBUG("Failed over-riding cipher list to '%s'. EAP-FAST will likely not work", | |
564 | inst->cipher_list); | |
565 | } | |
566 | } | |
567 | ||
568 | // FIXME TLSv1.2 uses a different PRF and SSL_export_keying_material("key expansion") is forbidden | |
569 | #ifdef SSL_OP_NO_TLSv1_2 | |
570 | /* | |
571 | * Forcibly disable TLSv1.2 | |
572 | */ | |
573 | SSL_set_options(tls_session->ssl, SSL_OP_NO_TLSv1_2); | |
574 | #endif | |
548 | 575 | |
549 | 576 | /* |
550 | 577 | * Push TLV of authority_identity into tls_record |
247 | 247 | static int mod_process(void *arg, eap_handler_t *handler) |
248 | 248 | { |
249 | 249 | int rcode; |
250 | int ret = 0; | |
250 | 251 | fr_tls_status_t status; |
251 | 252 | rlm_eap_peap_t *inst = (rlm_eap_peap_t *) arg; |
252 | 253 | tls_session_t *tls_session = (tls_session_t *) handler->opaque; |
275 | 276 | RDEBUG2("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>")); |
276 | 277 | } |
277 | 278 | |
279 | /* | |
280 | * Make request available to any SSL callbacks | |
281 | */ | |
282 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request); | |
278 | 283 | switch (status) { |
279 | 284 | /* |
280 | 285 | * EAP-TLS handshake was successful, tell the |
298 | 303 | * and EAP id from the inner tunnel, and update it with |
299 | 304 | * the expected EAP id! |
300 | 305 | */ |
301 | return 1; | |
302 | ||
306 | ret = 1; | |
307 | goto done; | |
303 | 308 | /* |
304 | 309 | * Handshake is done, proceed with decoding tunneled |
305 | 310 | * data. |
311 | 316 | * Anything else: fail. |
312 | 317 | */ |
313 | 318 | default: |
314 | return 0; | |
319 | ret = 0; | |
320 | goto done; | |
315 | 321 | } |
316 | 322 | |
317 | 323 | /* |
335 | 341 | switch (rcode) { |
336 | 342 | case RLM_MODULE_REJECT: |
337 | 343 | eaptls_fail(handler, 0); |
338 | return 0; | |
344 | ret = 0; | |
345 | goto done; | |
339 | 346 | |
340 | 347 | case RLM_MODULE_HANDLED: |
341 | 348 | eaptls_request(handler->eap_ds, tls_session); |
342 | return 1; | |
349 | ret = 1; | |
350 | goto done; | |
343 | 351 | |
344 | 352 | case RLM_MODULE_OK: |
345 | 353 | /* |
367 | 375 | /* |
368 | 376 | * Success: Automatically return MPPE keys. |
369 | 377 | */ |
370 | return eaptls_success(handler, 0); | |
378 | ret = eaptls_success(handler, 0); | |
379 | goto done; | |
371 | 380 | |
372 | 381 | /* |
373 | 382 | * No response packet, MUST be proxying it. |
379 | 388 | #ifdef WITH_PROXY |
380 | 389 | rad_assert(handler->request->proxy != NULL); |
381 | 390 | #endif |
382 | return 1; | |
391 | ret = 1; | |
392 | goto done; | |
383 | 393 | |
384 | 394 | default: |
385 | 395 | break; |
386 | 396 | } |
387 | 397 | |
388 | 398 | eaptls_fail(handler, 0); |
389 | return 0; | |
399 | ||
400 | done: | |
401 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL); | |
402 | ||
403 | return ret; | |
390 | 404 | } |
391 | 405 | |
392 | 406 |
129 | 129 | static int CC_HINT(nonnull) mod_process(void *type_arg, eap_handler_t *handler) |
130 | 130 | { |
131 | 131 | fr_tls_status_t status; |
132 | int ret; | |
132 | 133 | tls_session_t *tls_session = (tls_session_t *) handler->opaque; |
133 | 134 | REQUEST *request = handler->request; |
134 | 135 | rlm_eap_tls_t *inst; |
142 | 143 | RDEBUG2("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>")); |
143 | 144 | } |
144 | 145 | |
146 | ||
147 | /* | |
148 | * Make request available to any SSL callbacks | |
149 | */ | |
150 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request); | |
145 | 151 | switch (status) { |
146 | 152 | /* |
147 | 153 | * EAP-TLS handshake was successful, return an |
180 | 186 | RDEBUG2("Certificate rejected by the virtual server"); |
181 | 187 | talloc_free(fake); |
182 | 188 | eaptls_fail(handler, 0); |
183 | return 0; | |
189 | ret = 0; | |
190 | goto done; | |
184 | 191 | } |
185 | 192 | |
186 | 193 | talloc_free(fake); |
194 | 201 | * do nothing. |
195 | 202 | */ |
196 | 203 | case FR_TLS_HANDLED: |
197 | return 1; | |
204 | ret = 1; | |
205 | goto done; | |
198 | 206 | |
199 | 207 | /* |
200 | 208 | * Handshake is done, proceed with decoding tunneled |
222 | 230 | #endif |
223 | 231 | |
224 | 232 | eaptls_fail(handler, 0); |
225 | return 0; | |
233 | ret = 0; | |
234 | goto done; | |
226 | 235 | |
227 | 236 | /* |
228 | 237 | * Anything else: fail. |
233 | 242 | default: |
234 | 243 | tls_fail(tls_session); |
235 | 244 | |
236 | return 0; | |
245 | ret = 0; | |
246 | goto done; | |
237 | 247 | } |
238 | 248 | |
239 | 249 | /* |
240 | 250 | * Success: Automatically return MPPE keys. |
241 | 251 | */ |
242 | return eaptls_success(handler, 0); | |
252 | ret = eaptls_success(handler, 0); | |
253 | ||
254 | done: | |
255 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL); | |
256 | ||
257 | return ret; | |
243 | 258 | } |
244 | 259 | |
245 | 260 | /* |
219 | 219 | static int mod_process(void *arg, eap_handler_t *handler) |
220 | 220 | { |
221 | 221 | int rcode; |
222 | int ret = 0; | |
222 | 223 | fr_tls_status_t status; |
223 | 224 | rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg; |
224 | 225 | tls_session_t *tls_session = (tls_session_t *) handler->opaque; |
239 | 240 | RDEBUG2("[eaptls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>")); |
240 | 241 | } |
241 | 242 | |
243 | /* | |
244 | * Make request available to any SSL callbacks | |
245 | */ | |
246 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request); | |
242 | 247 | switch (status) { |
243 | 248 | /* |
244 | 249 | * EAP-TLS handshake was successful, tell the |
268 | 273 | /* |
269 | 274 | * Success: Automatically return MPPE keys. |
270 | 275 | */ |
271 | return eaptls_success(handler, 0); | |
276 | ret = eaptls_success(handler, 0); | |
277 | goto done; | |
272 | 278 | } else { |
273 | 279 | eaptls_request(handler->eap_ds, tls_session); |
274 | 280 | } |
275 | return 1; | |
281 | ret = 1; | |
282 | goto done; | |
276 | 283 | |
277 | 284 | /* |
278 | 285 | * The TLS code is still working on the TLS |
280 | 287 | * do nothing. |
281 | 288 | */ |
282 | 289 | case FR_TLS_HANDLED: |
283 | return 1; | |
290 | ret = 1; | |
291 | goto done; | |
284 | 292 | |
285 | 293 | /* |
286 | 294 | * Handshake is done, proceed with decoding tunneled |
293 | 301 | * Anything else: fail. |
294 | 302 | */ |
295 | 303 | default: |
296 | return 0; | |
304 | ret = 0; | |
305 | goto done; | |
297 | 306 | } |
298 | 307 | |
299 | 308 | /* |
317 | 326 | switch (rcode) { |
318 | 327 | case PW_CODE_ACCESS_REJECT: |
319 | 328 | eaptls_fail(handler, 0); |
320 | return 0; | |
329 | ret = 0; | |
330 | goto done; | |
321 | 331 | |
322 | 332 | /* |
323 | 333 | * Access-Challenge, continue tunneled conversation. |
324 | 334 | */ |
325 | 335 | case PW_CODE_ACCESS_CHALLENGE: |
326 | 336 | eaptls_request(handler->eap_ds, tls_session); |
327 | return 1; | |
337 | ret = 1; | |
338 | goto done; | |
328 | 339 | |
329 | 340 | /* |
330 | 341 | * Success: Automatically return MPPE keys. |
331 | 342 | */ |
332 | 343 | case PW_CODE_ACCESS_ACCEPT: |
333 | return eaptls_success(handler, 0); | |
344 | ret = eaptls_success(handler, 0); | |
345 | goto done; | |
334 | 346 | |
335 | 347 | /* |
336 | 348 | * No response packet, MUST be proxying it. |
342 | 354 | #ifdef WITH_PROXY |
343 | 355 | rad_assert(handler->request->proxy != NULL); |
344 | 356 | #endif |
345 | return 1; | |
357 | ret = 1; | |
358 | goto done; | |
346 | 359 | |
347 | 360 | default: |
348 | 361 | break; |
352 | 365 | * Something we don't understand: Reject it. |
353 | 366 | */ |
354 | 367 | eaptls_fail(handler, 0); |
355 | return 0; | |
368 | ||
369 | done: | |
370 | SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL); | |
371 | ||
372 | return ret; | |
356 | 373 | } |
357 | 374 | |
358 | 375 | /* |
445 | 445 | return; |
446 | 446 | } |
447 | 447 | |
448 | memset(&key, 0, sizeof(key)); /* -Winitialize */ | |
448 | 449 | memset(key_str, 0,17); |
449 | 450 | |
450 | 451 | key_datum = gdbm_firstkey(sessiondb); |
2938 | 2938 | krb5_version_raw=$($krb5_config --version) |
2939 | 2939 | |
2940 | 2940 | krb5_version=$(echo "$krb5_version_raw" | head -n 1 | \ |
2941 | awk '{split($(4),v,"."); if (v["3"] == "") v["3"] = "0"; print v["1"]v["2"]v["3"] }') | |
2941 | awk '{split($(4),v,"."); if (v["3"] = "") v["3"] = "0"; print v["1"]v["2"]v["3"] }') | |
2942 | 2942 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${krb5_version_raw} ($krb5_version)" >&5 |
2943 | 2943 | $as_echo "${krb5_version_raw} ($krb5_version)" >&6; } |
2944 | 2944 | |
3912 | 3912 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" |
3913 | 3913 | fi |
3914 | 3914 | |
3915 | if test "x$ac_cv_lib_krb5_krb5_verify_user_opt" == xyes; then | |
3915 | if test "x$ac_cv_lib_krb5_krb5_verify_user_opt" = xyes; then | |
3916 | 3916 | krb5_api_type='heimdal' |
3917 | 3917 | else |
3918 | 3918 | krb5_api_type='mit' |
4113 | 4113 | fi |
4114 | 4114 | done |
4115 | 4115 | |
4116 | if test "x$ac_cv_func_krb5_get_error_message" == xyes; then | |
4116 | if test "x$ac_cv_func_krb5_get_error_message" = xyes; then | |
4117 | 4117 | krb5mod_cflags="${krb5mod_cflags} -DHAVE_KRB5_GET_ERROR_MESSAGE" |
4118 | 4118 | fi |
4119 | if test "x$ac_cv_func_krb5_free_error_message" == xyes; then | |
4119 | if test "x$ac_cv_func_krb5_free_error_message" = xyes; then | |
4120 | 4120 | krb5mod_cflags="${krb5mod_cflags} -DHAVE_KRB5_FREE_ERROR_MESSAGE" |
4121 | 4121 | fi |
4122 | if test "x$ac_cv_func_krb5_free_error_string" == xyes; then | |
4122 | if test "x$ac_cv_func_krb5_free_error_string" = xyes; then | |
4123 | 4123 | krb5mod_cflags="${krb5mod_cflags} -DHAVE_KRB5_FREE_ERROR_STRING" |
4124 | 4124 | fi |
4125 | 4125 | |
4300 | 4300 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" |
4301 | 4301 | fi |
4302 | 4302 | |
4303 | if test "x$ac_cv_lib_krb5_krb5_is_thread_safe" == xyes; then | |
4303 | if test "x$ac_cv_lib_krb5_krb5_is_thread_safe" = xyes; then | |
4304 | 4304 | if test "$cross_compiling" = yes; then : |
4305 | 4305 | { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 |
4306 | 4306 | $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} |
4333 | 4333 | krb5threadsafe="" |
4334 | 4334 | fi |
4335 | 4335 | |
4336 | if test "$krb5_api_type" == "mit"; then | |
4336 | if test "$krb5_api_type" = "mit"; then | |
4337 | 4337 | |
4338 | 4338 | |
4339 | 4339 | ac_safe=`echo "com_err.h" | sed 'y%./+-%__pm%'` |
43 | 43 | |
44 | 44 | dnl # AWK originally from from https://github.com/hpc/lustre |
45 | 45 | krb5_version=$(echo "$krb5_version_raw" | head -n 1 | \ |
46 | awk '{split($(4),v,"."); if (v@<:@"3"@:>@ == "") v@<:@"3"@:>@ = "0"; print v@<:@"1"@:>@v@<:@"2"@:>@v@<:@"3"@:>@ }') | |
46 | awk '{split($(4),v,"."); if (v@<:@"3"@:>@ = "") v@<:@"3"@:>@ = "0"; print v@<:@"1"@:>@v@<:@"2"@:>@v@<:@"3"@:>@ }') | |
47 | 47 | AC_MSG_RESULT([${krb5_version_raw} ($krb5_version)]) |
48 | 48 | |
49 | 49 | AC_MSG_CHECKING([krb5-config reported vendor]) |
94 | 94 | dnl # Only the heimdal version of the library has this function |
95 | 95 | dnl # |
96 | 96 | FR_SMART_CHECK_LIB(krb5, krb5_verify_user_opt) |
97 | if test "x$ac_cv_lib_krb5_krb5_verify_user_opt" == xyes; then | |
97 | if test "x$ac_cv_lib_krb5_krb5_verify_user_opt" = xyes; then | |
98 | 98 | krb5_api_type='heimdal' |
99 | 99 | else |
100 | 100 | krb5_api_type='mit' |
117 | 117 | dnl # Check how to free things returned by krb5_get_error_message |
118 | 118 | dnl # |
119 | 119 | AC_CHECK_FUNCS([krb5_get_error_message krb5_free_error_string krb5_free_error_message]) |
120 | if test "x$ac_cv_func_krb5_get_error_message" == xyes; then | |
120 | if test "x$ac_cv_func_krb5_get_error_message" = xyes; then | |
121 | 121 | krb5mod_cflags="${krb5mod_cflags} -DHAVE_KRB5_GET_ERROR_MESSAGE" |
122 | 122 | fi |
123 | if test "x$ac_cv_func_krb5_free_error_message" == xyes; then | |
123 | if test "x$ac_cv_func_krb5_free_error_message" = xyes; then | |
124 | 124 | krb5mod_cflags="${krb5mod_cflags} -DHAVE_KRB5_FREE_ERROR_MESSAGE" |
125 | 125 | fi |
126 | if test "x$ac_cv_func_krb5_free_error_string" == xyes; then | |
126 | if test "x$ac_cv_func_krb5_free_error_string" = xyes; then | |
127 | 127 | krb5mod_cflags="${krb5mod_cflags} -DHAVE_KRB5_FREE_ERROR_STRING" |
128 | 128 | fi |
129 | 129 | |
134 | 134 | krb5threadsafe= |
135 | 135 | |
136 | 136 | FR_SMART_CHECK_LIB(krb5, krb5_is_thread_safe) |
137 | if test "x$ac_cv_lib_krb5_krb5_is_thread_safe" == xyes; then | |
137 | if test "x$ac_cv_lib_krb5_krb5_is_thread_safe" = xyes; then | |
138 | 138 | AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <krb5.h>]], [[return krb5_is_thread_safe() ? 0 : 1]])], |
139 | 139 | [krb5threadsafe="-DKRB5_IS_THREAD_SAFE"], [AC_MSG_WARN([[libkrb5 is not threadsafe]])]) |
140 | 140 | fi |
142 | 142 | krb5threadsafe="" |
143 | 143 | fi |
144 | 144 | |
145 | if test "$krb5_api_type" == "mit"; then | |
145 | if test "$krb5_api_type" = "mit"; then | |
146 | 146 | dnl # |
147 | 147 | dnl # This lives in different places depending on the distro |
148 | 148 | dnl # |
3384 | 3384 | $as_echo "#define WITH_SASL 1" >>confdefs.h |
3385 | 3385 | |
3386 | 3386 | SASL=sasl.c |
3387 | fi | |
3387 | fi | |
3388 | 3388 | fi |
3389 | 3389 | |
3390 | 3390 | targetname=rlm_ldap |
597 | 597 | goto error_string; |
598 | 598 | |
599 | 599 | case LDAP_OPERATIONS_ERROR: |
600 | *error = "Please set 'chase_referrals=yes' and 'rebind=yes'. See the ldap module configuration " | |
601 | "for details."; | |
600 | if (inst->chase_referrals) { | |
601 | *error = "Operations error with LDAP database. Please see the LDAP server configuration / documentation for more information."; | |
602 | } else { | |
603 | *error = "Please set 'chase_referrals=yes' and 'rebind=yes'. See the ldap module configuration " | |
604 | "for details."; | |
605 | } | |
602 | 606 | |
603 | 607 | /* FALL-THROUGH */ |
604 | 608 | default: |
697 | 701 | rad_assert(!retry || inst->pool); |
698 | 702 | |
699 | 703 | #ifndef WITH_SASL |
700 | rad_assert(!sasl->mech); | |
704 | if (sasl && sasl->mech) { | |
705 | REDEBUG("Server is built without SASL, but is being asked to do SASL."); | |
706 | return status; | |
707 | } | |
701 | 708 | #endif |
702 | 709 | |
703 | 710 | /* |
1330 | 1337 | { |
1331 | 1338 | int ldap_errno; |
1332 | 1339 | |
1333 | rad_assert(inst); /* clang scan */ | |
1334 | ||
1335 | 1340 | #define do_ldap_global_option(_option, _name, _value) \ |
1336 | 1341 | if (ldap_set_option(NULL, _option, _value) != LDAP_OPT_SUCCESS) { \ |
1337 | 1342 | ldap_get_option(NULL, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \ |
1597 | 1602 | * Instead, we let the next caller do the rebind. |
1598 | 1603 | */ |
1599 | 1604 | if (conn->referred) { |
1600 | fr_connection_close(inst->pool, conn); | |
1605 | fr_connection_close(inst->pool, conn, "Was referred to a different LDAP server"); | |
1601 | 1606 | return; |
1602 | 1607 | } |
1603 | 1608 |
247 | 247 | return RLM_MODULE_FAIL; |
248 | 248 | } |
249 | 249 | |
250 | fd = exfile_open(inst->ef, path, inst->permissions, true); | |
250 | fd = exfile_open(inst->ef, path, inst->permissions); | |
251 | 251 | if (fd < 0) { |
252 | 252 | ERROR("rlm_linelog: Failed to open %s: %s", path, fr_syserror(errno)); |
253 | 253 | return RLM_MODULE_FAIL; |
77 | 77 | * Returns: |
78 | 78 | * 0 success |
79 | 79 | * -1 auth failure |
80 | * -2 failed connecting to AD | |
80 | 81 | * -648 password expired |
81 | 82 | */ |
82 | 83 | int do_auth_wbclient(rlm_mschap_t *inst, REQUEST *request, |
211 | 212 | memcpy(nthashhash, info->user_session_key, NT_DIGEST_LENGTH); |
212 | 213 | break; |
213 | 214 | case WBC_ERR_WINBIND_NOT_AVAILABLE: |
215 | rcode = -2; | |
214 | 216 | RERROR("Unable to contact winbind!"); |
215 | 217 | RDEBUG2("Check that winbind is running and that FreeRADIUS has"); |
216 | 218 | RDEBUG2("permission to connect to the winbind privileged socket."); |
248 | 250 | * WBC_ERR_NO_MEMORY |
249 | 251 | * neither of which are particularly likely. |
250 | 252 | */ |
253 | rcode = -2; | |
251 | 254 | if (error && error->display_string) { |
252 | 255 | REDEBUG2("libwbclient error: wbcErr %d (%s)", err, error->display_string); |
253 | 256 | } else { |
1175 | 1175 | return -691; |
1176 | 1176 | } |
1177 | 1177 | |
1178 | if (strcasestr(buffer, "No logon servers") || | |
1179 | strcasestr(buffer, "0xC000005E")) { | |
1180 | REDEBUG2("%s", buffer); | |
1181 | return -2; | |
1182 | } | |
1183 | ||
1184 | if (strcasestr(buffer, "could not obtain winbind separator") || | |
1185 | strcasestr(buffer, "Reading winbind reply failed")) { | |
1186 | REDEBUG2("%s", buffer); | |
1187 | return -2; | |
1188 | } | |
1189 | ||
1178 | 1190 | RDEBUG2("External script failed"); |
1179 | 1191 | p = strchr(buffer, '\n'); |
1180 | 1192 | if (p) *p = '\0'; |
1445 | 1457 | retry = 0; |
1446 | 1458 | message = "Account locked out"; |
1447 | 1459 | rcode = RLM_MODULE_USERLOCK; |
1460 | } else if (mschap_result == -2) { | |
1461 | RDEBUG("Authentication failed"); | |
1462 | error = 691; | |
1463 | retry = inst->allow_retry; | |
1464 | message = "Authentication failed"; | |
1465 | rcode = RLM_MODULE_FAIL; | |
1448 | 1466 | |
1449 | 1467 | } else if (mschap_result < 0) { |
1450 | 1468 | REDEBUG("MS-CHAP2-Response is incorrect"); |
1451 | 1469 | error = 691; |
1452 | 1470 | retry = inst->allow_retry; |
1453 | message = "Authentication failed"; | |
1471 | message = "Authentication rejected"; | |
1454 | 1472 | rcode = RLM_MODULE_REJECT; |
1455 | 1473 | } |
1456 | 1474 | |
1868 | 1886 | } else if ((response = fr_pair_find_by_num(request->packet->vps, PW_MSCHAP2_RESPONSE, |
1869 | 1887 | VENDORPEC_MICROSOFT, TAG_ANY)) != NULL) { |
1870 | 1888 | uint8_t mschapv1_challenge[16]; |
1871 | VALUE_PAIR *name_attr, *response_name; | |
1889 | VALUE_PAIR *name_attr, *response_name, *peer_challenge_attr; | |
1872 | 1890 | rlm_rcode_t rcode; |
1891 | uint8_t const *peer_challenge; | |
1873 | 1892 | |
1874 | 1893 | mschap_version = 2; |
1875 | 1894 | |
1951 | 1970 | } |
1952 | 1971 | } |
1953 | 1972 | #endif |
1973 | peer_challenge = response->vp_octets + 2; | |
1974 | ||
1975 | peer_challenge_attr = fr_pair_find_by_num(request->config, PW_MS_CHAP_PEER_CHALLENGE, 0, TAG_ANY); | |
1976 | if (peer_challenge_attr) { | |
1977 | RDEBUG2("Overriding peer challenge"); | |
1978 | peer_challenge = peer_challenge_attr->vp_octets; | |
1979 | } | |
1980 | ||
1954 | 1981 | /* |
1955 | 1982 | * The old "mschapv2" function has been moved to |
1956 | 1983 | * here. |
1959 | 1986 | * MS-CHAPv1 challenge, and then does MS-CHAPv1. |
1960 | 1987 | */ |
1961 | 1988 | RDEBUG2("Creating challenge hash with username: %s", username_string); |
1962 | mschap_challenge_hash(response->vp_octets + 2, /* peer challenge */ | |
1989 | mschap_challenge_hash(peer_challenge, /* peer challenge */ | |
1963 | 1990 | challenge->vp_octets, /* our challenge */ |
1964 | 1991 | username_string, /* user name */ |
1965 | 1992 | mschapv1_challenge); /* resulting challenge */ |
1985 | 2012 | mschap_auth_response(username_string, /* without the domain */ |
1986 | 2013 | nthashhash, /* nt-hash-hash */ |
1987 | 2014 | response->vp_octets + 26, /* peer response */ |
1988 | response->vp_octets + 2, /* peer challenge */ | |
2015 | peer_challenge, /* peer challenge */ | |
1989 | 2016 | challenge->vp_octets, /* our challenge */ |
1990 | 2017 | msch2resp); /* calculated MPPE key */ |
1991 | 2018 | mschap_add_reply(request, *response->vp_octets, "MS-CHAP2-Success", msch2resp, 42); |
538 | 538 | (rad_digest_cmp(vp->vp_octets, |
539 | 539 | request->password->vp_octets, |
540 | 540 | vp->vp_length) != 0)) { |
541 | REDEBUG("Cleartext password \"%s\" does not match \"known good\" password", | |
542 | request->password->vp_strvalue); | |
541 | REDEBUG("Cleartext password does not match \"known good\" password"); | |
543 | 542 | return RLM_MODULE_REJECT; |
544 | 543 | } |
545 | 544 | return RLM_MODULE_OK; |
888 | 887 | FR_MD5_CTX md5_context; |
889 | 888 | uint8_t digest[128]; |
890 | 889 | uint8_t buff[MAX_STRING_LEN]; |
891 | char buff2[MAX_STRING_LEN + 50]; | |
890 | uint8_t buff2[MAX_STRING_LEN + 50]; | |
892 | 891 | |
893 | 892 | RDEBUG("Using NT-MTA-MD5-Password"); |
894 | 893 | |
919 | 918 | * Set up the algorithm. |
920 | 919 | */ |
921 | 920 | { |
922 | char *p = buff2; | |
921 | uint8_t *p = buff2; | |
923 | 922 | |
924 | 923 | memcpy(p, &vp->vp_octets[32], 32); |
925 | 924 | p += 32; |
926 | 925 | *(p++) = 89; |
927 | strcpy(p, request->password->vp_strvalue); | |
928 | p += strlen(p); | |
926 | memcpy(p, (uint8_t const *)request->password->vp_strvalue, request->password->vp_length); | |
927 | p += request->password->vp_length; | |
929 | 928 | *(p++) = 247; |
930 | 929 | memcpy(p, &vp->vp_octets[32], 32); |
931 | 930 | p += 32; |
932 | 931 | |
933 | 932 | fr_md5_init(&md5_context); |
934 | fr_md5_update(&md5_context, (uint8_t *) buff2, p - buff2); | |
933 | fr_md5_update(&md5_context, buff2, p - buff2); | |
935 | 934 | fr_md5_final(buff, &md5_context); |
936 | 935 | } |
937 | 936 |
3450 | 3450 | |
3451 | 3451 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINKS" >&5 |
3452 | 3452 | $as_echo "$LINKS" >&6; } |
3453 | if test "x$LINKS" == "xno"; then | |
3453 | if test "x$LINKS" = "xno"; then | |
3454 | 3454 | fail="$fail libperl.so" |
3455 | 3455 | targetname= |
3456 | 3456 | fi |
3481 | 3481 | |
3482 | 3482 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINKS" >&5 |
3483 | 3483 | $as_echo "$LINKS" >&6; } |
3484 | if test "x$LINKS" == "xno"; then | |
3484 | if test "x$LINKS" = "xno"; then | |
3485 | 3485 | fail="$fail libperl.so" |
3486 | 3486 | targetname= |
3487 | 3487 | fi |
75 | 75 | [LINKS="yes"], [LINKS="no"]) |
76 | 76 | |
77 | 77 | AC_MSG_RESULT($LINKS) |
78 | if test "x$LINKS" == "xno"; then | |
78 | if test "x$LINKS" = "xno"; then | |
79 | 79 | fail="$fail libperl.so" |
80 | 80 | targetname= |
81 | 81 | fi |
89 | 89 | [LINKS="yes"], [LINKS="no"]) |
90 | 90 | |
91 | 91 | AC_MSG_RESULT($LINKS) |
92 | if test "x$LINKS" == "xno"; then | |
92 | if test "x$LINKS" = "xno"; then | |
93 | 93 | fail="$fail libperl.so" |
94 | 94 | targetname= |
95 | 95 | fi |
921 | 921 | RDEBUG("perl_embed:: module = %s , func = %s exit status= %s\n", |
922 | 922 | inst->module, function_name, SvPV(ERRSV,n_a)); |
923 | 923 | (void)POPs; |
924 | count = 0; | |
925 | exitstatus = RLM_MODULE_FAIL; | |
924 | 926 | } |
925 | 927 | |
926 | 928 | if (count == 1) { |
22 | 22 | RLM_MODULE_UPDATED = 8 |
23 | 23 | RLM_MODULE_NUMCODES = 9 |
24 | 24 | |
25 | ||
26 | # from radiusd.h | |
27 | L_DBG = 1 | |
25 | # from log.h | |
28 | 26 | L_AUTH = 2 |
29 | 27 | L_INFO = 3 |
30 | 28 | L_ERR = 4 |
31 | L_PROXY = 5 | |
32 | L_CONS = 128 | |
29 | L_WARN = 5 | |
30 | L_PROXY = 6 | |
31 | L_ACCT = 7 | |
32 | ||
33 | L_DBG = 16 | |
34 | L_DBG_WARN = 17 | |
35 | L_DBG_ERR = 18 | |
36 | L_DBG_WARN_REQ = 19 | |
37 | L_DBG_ERR_REQ = 20 | |
33 | 38 | |
34 | 39 | # log function |
35 | 40 | def radlog(level, msg): |
66 | 66 | char const *name; //!< Name of the module instance |
67 | 67 | PyThreadState *sub_interpreter; //!< The main interpreter/thread used for this instance. |
68 | 68 | char const *python_path; //!< Path to search for python files in. |
69 | ||
70 | #if PY_VERSION_HEX > 0x03050000 | |
71 | wchar_t *wide_name; //!< Special wide char encoding of radiusd name. | |
72 | wchar_t *wide_path; //!< Special wide char encoding of radiusd path. | |
73 | #endif | |
69 | 74 | PyObject *module; //!< Local, interpreter specific module, containing |
70 | 75 | //!< FreeRADIUS functions. |
71 | 76 | bool cext_compat; //!< Whether or not to create sub-interpreters per module |
89 | 94 | |
90 | 95 | PyObject *pythonconf_dict; //!< Configuration parameters defined in the module |
91 | 96 | //!< made available to the python script. |
97 | bool pass_all_vps; //!< Pass all VPS lists (request, reply, config, state, proxy_req, proxy_reply) | |
92 | 98 | } rlm_python_t; |
93 | 99 | |
94 | 100 | /** Tracks a python module inst/thread state pair |
128 | 134 | |
129 | 135 | { "python_path", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, python_path), NULL }, |
130 | 136 | { "cext_compat", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_python_t, cext_compat), "yes" }, |
137 | { "pass_all_vps", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_python_t, pass_all_vps), "no" }, | |
131 | 138 | |
132 | 139 | CONF_PARSER_TERMINATOR |
133 | 140 | }; |
145 | 152 | A(L_INFO) |
146 | 153 | A(L_ERR) |
147 | 154 | A(L_PROXY) |
148 | A(L_WARN) | |
149 | 155 | A(L_ACCT) |
150 | 156 | A(L_DBG_WARN) |
151 | 157 | A(L_DBG_ERR) |
370 | 376 | return 0; |
371 | 377 | } |
372 | 378 | |
373 | static rlm_rcode_t do_python_single(REQUEST *request, PyObject *pFunc, char const *funcname) | |
374 | { | |
379 | /* | |
380 | * This function generates a tuple representing a given VPS and inserts it into | |
381 | * the indicated position in the tuple pArgs. | |
382 | * Returns false on error. | |
383 | */ | |
384 | static bool mod_populate_vps(PyObject* pArgs, const int pos, VALUE_PAIR *vps) | |
385 | { | |
386 | PyObject *vps_tuple = NULL; | |
387 | int tuplelen = 0; | |
388 | int i = 0; | |
375 | 389 | vp_cursor_t cursor; |
376 | VALUE_PAIR *vp; | |
377 | PyObject *pRet = NULL; | |
378 | PyObject *pArgs = NULL; | |
379 | int tuplelen; | |
380 | int ret; | |
381 | ||
382 | /* Default return value is "OK, continue" */ | |
383 | ret = RLM_MODULE_OK; | |
390 | VALUE_PAIR *vp; | |
391 | ||
392 | /* If vps is NULL, return None */ | |
393 | if (vps == NULL) { | |
394 | Py_INCREF(Py_None); | |
395 | PyTuple_SET_ITEM(pArgs, pos, Py_None); | |
396 | return true; | |
397 | } | |
384 | 398 | |
385 | 399 | /* |
386 | 400 | * We will pass a tuple containing (name, value) tuples |
387 | 401 | * We can safely use the Python function to build up a |
388 | 402 | * tuple, since the tuple is not used elsewhere. |
389 | 403 | * |
390 | * Determine the size of our tuple by walking through the packet. | |
391 | * If request is NULL, pass None. | |
392 | */ | |
393 | tuplelen = 0; | |
404 | * Determine the size of our tuple by walking through the vps. | |
405 | */ | |
406 | for (vp = fr_cursor_init(&cursor, &vps); vp; vp = fr_cursor_next(&cursor)) | |
407 | tuplelen++; | |
408 | ||
409 | if ((vps_tuple = PyTuple_New(tuplelen)) == NULL) goto error; | |
410 | ||
411 | for (vp = fr_cursor_init(&cursor, &vps); vp; vp = fr_cursor_next(&cursor), i++) { | |
412 | PyObject *pPair = NULL; | |
413 | ||
414 | /* The inside tuple has two only: */ | |
415 | if ((pPair = PyTuple_New(2)) == NULL) goto error; | |
416 | ||
417 | if (mod_populate_vptuple(pPair, vp) == 0) { | |
418 | /* Put the tuple inside the container */ | |
419 | PyTuple_SET_ITEM(vps_tuple, i, pPair); | |
420 | } else { | |
421 | Py_INCREF(Py_None); | |
422 | PyTuple_SET_ITEM(vps_tuple, i, Py_None); | |
423 | Py_DECREF(pPair); | |
424 | } | |
425 | } | |
426 | PyTuple_SET_ITEM(pArgs, pos, vps_tuple); | |
427 | return true; | |
428 | ||
429 | error: | |
430 | Py_XDECREF(vps_tuple); | |
431 | return false; | |
432 | } | |
433 | ||
434 | static rlm_rcode_t do_python_single(REQUEST *request, PyObject *pFunc, char const *funcname, bool pass_all_vps) | |
435 | { | |
436 | PyObject *pRet = NULL; | |
437 | PyObject *pArgs = NULL; | |
438 | int ret; | |
439 | int i; | |
440 | ||
441 | /* Default return value is "OK, continue" */ | |
442 | ret = RLM_MODULE_OK; | |
443 | ||
444 | /* | |
445 | * pArgs is a 6-tuple with (Request, Reply, Config, State, Proxy-Request, Proxy-Reply) | |
446 | * If some list is not available, NONE is used instead | |
447 | */ | |
448 | if ((pArgs = PyTuple_New(6)) == NULL) { | |
449 | ret = RLM_MODULE_FAIL; | |
450 | goto finish; | |
451 | } | |
452 | ||
453 | /* If there is a request, fill in the first 4 attribute lists */ | |
394 | 454 | if (request != NULL) { |
395 | for (vp = fr_cursor_init(&cursor, &request->packet->vps); | |
396 | vp; | |
397 | vp = fr_cursor_next(&cursor)) tuplelen++; | |
398 | } | |
399 | ||
400 | if (tuplelen == 0) { | |
401 | Py_INCREF(Py_None); | |
402 | pArgs = Py_None; | |
403 | } else { | |
404 | int i = 0; | |
405 | if ((pArgs = PyTuple_New(tuplelen)) == NULL) { | |
455 | if (!mod_populate_vps(pArgs, 0, request->packet->vps) || | |
456 | !mod_populate_vps(pArgs, 1, request->reply->vps) || | |
457 | !mod_populate_vps(pArgs, 2, request->config) || | |
458 | !mod_populate_vps(pArgs, 3, request->state)) { | |
406 | 459 | ret = RLM_MODULE_FAIL; |
407 | 460 | goto finish; |
408 | 461 | } |
409 | 462 | |
410 | for (vp = fr_cursor_init(&cursor, &request->packet->vps); | |
411 | vp; | |
412 | vp = fr_cursor_next(&cursor), i++) { | |
413 | PyObject *pPair; | |
414 | ||
415 | /* The inside tuple has two only: */ | |
416 | if ((pPair = PyTuple_New(2)) == NULL) { | |
463 | /* fill proxy vps */ | |
464 | if (request->proxy) { | |
465 | if (!mod_populate_vps(pArgs, 4, request->proxy->vps) || | |
466 | !mod_populate_vps(pArgs, 5, request->proxy_reply->vps)) { | |
417 | 467 | ret = RLM_MODULE_FAIL; |
418 | 468 | goto finish; |
419 | 469 | } |
420 | ||
421 | if (mod_populate_vptuple(pPair, vp) == 0) { | |
422 | /* Put the tuple inside the container */ | |
423 | PyTuple_SET_ITEM(pArgs, i, pPair); | |
424 | } else { | |
425 | Py_INCREF(Py_None); | |
426 | PyTuple_SET_ITEM(pArgs, i, Py_None); | |
427 | Py_DECREF(pPair); | |
428 | } | |
429 | } | |
430 | } | |
431 | ||
432 | /* Call Python function. */ | |
433 | pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL); | |
470 | } | |
471 | /* If there are no proxy lists */ | |
472 | else { | |
473 | mod_populate_vps(pArgs, 4, NULL); | |
474 | mod_populate_vps(pArgs, 5, NULL); | |
475 | } | |
476 | ||
477 | } | |
478 | /* If there is no request, set all the elements to None */ | |
479 | else for (i = 0; i < 6; i++) mod_populate_vps(pArgs, i, NULL); | |
480 | ||
481 | /* | |
482 | * Call Python function. If pass_all_vps is true, a 6-tuple representing | |
483 | * (Request, Reply, Config, State, Proxy-Request, Proxy-Reply) is passed | |
484 | * as argument to the module callback. | |
485 | * Otherwise, a tuple representing just the request is passed. | |
486 | */ | |
487 | if (pass_all_vps) | |
488 | pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL); | |
489 | else | |
490 | pRet = PyObject_CallFunctionObjArgs(pFunc, PyTuple_GET_ITEM(pArgs, 0), NULL); | |
491 | ||
434 | 492 | if (!pRet) { |
435 | 493 | ret = RLM_MODULE_FAIL; |
436 | 494 | goto finish; |
626 | 684 | RDEBUG3("Using thread state %p", this_thread->state); |
627 | 685 | |
628 | 686 | PyEval_RestoreThread(this_thread->state); /* Swap in our local thread state */ |
629 | ret = do_python_single(request, pFunc, funcname); | |
687 | ret = do_python_single(request, pFunc, funcname, inst->pass_all_vps); | |
630 | 688 | PyEval_SaveThread(); |
631 | 689 | |
632 | 690 | return ret; |
854 | 912 | |
855 | 913 | #if PY_VERSION_HEX > 0x03050000 |
856 | 914 | { |
857 | wchar_t *name; | |
858 | ||
859 | wide_name = Py_DecodeLocale(main_config.name, strlen(main_config.name)); | |
860 | Py_SetProgramName(name); /* The value of argv[0] as a wide char string */ | |
861 | PyMem_RawFree(name); | |
915 | inst->wide_name = Py_DecodeLocale(main_config.name, strlen(main_config.name)); | |
916 | Py_SetProgramName(inst->wide_name); /* The value of argv[0] as a wide char string */ | |
862 | 917 | } |
863 | 918 | #else |
864 | 919 | { |
865 | 920 | char *name; |
866 | 921 | |
867 | name = talloc_strdup(NULL, main_config.name); | |
922 | memcpy(&name, &main_config.name, sizeof(name)); | |
868 | 923 | Py_SetProgramName(name); /* The value of argv[0] as a wide char string */ |
869 | talloc_free(name); | |
870 | 924 | } |
871 | 925 | #endif |
872 | 926 | |
902 | 956 | |
903 | 957 | /* |
904 | 958 | * Set the python search path |
959 | * | |
960 | * The path buffer does not appear to be dup'd | |
961 | * so its lifetime should really be bound to | |
962 | * the lifetime of the module. | |
905 | 963 | */ |
906 | 964 | if (inst->python_path) { |
907 | 965 | #if PY_VERSION_HEX > 0x03050000 |
908 | 966 | { |
909 | wchar_t *name; | |
910 | ||
911 | path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path)); | |
912 | PySys_SetPath(path); | |
913 | PyMem_RawFree(path); | |
967 | inst->wide_path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path)); | |
968 | PySys_SetPath(inst->wide_path); | |
914 | 969 | } |
915 | 970 | #else |
916 | 971 | { |
917 | 972 | char *path; |
918 | 973 | |
919 | path = talloc_strdup(NULL, inst->python_path); | |
974 | memcpy(&path, &inst->python_path, sizeof(path)); | |
920 | 975 | PySys_SetPath(path); |
921 | talloc_free(path); | |
922 | 976 | } |
923 | 977 | #endif |
924 | 978 | } |
1030 | 1084 | /* |
1031 | 1085 | * Call the instantiate function. |
1032 | 1086 | */ |
1033 | code = do_python_single(NULL, inst->instantiate.function, "instantiate"); | |
1087 | code = do_python_single(NULL, inst->instantiate.function, "instantiate", inst->pass_all_vps); | |
1034 | 1088 | if (code < 0) { |
1035 | 1089 | error: |
1036 | 1090 | python_error_log(); /* Needs valid thread with GIL */ |
1052 | 1106 | */ |
1053 | 1107 | PyEval_RestoreThread(inst->sub_interpreter); |
1054 | 1108 | |
1055 | ret = do_python_single(NULL, inst->detach.function, "detach"); | |
1109 | ret = do_python_single(NULL, inst->detach.function, "detach", inst->pass_all_vps); | |
1056 | 1110 | |
1057 | 1111 | #define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x) |
1058 | 1112 | PYTHON_FUNC_DESTROY(instantiate); |
1086 | 1140 | PyThreadState_Swap(main_interpreter); /* Swap to the main thread */ |
1087 | 1141 | Py_Finalize(); |
1088 | 1142 | dlclose(python_dlhandle); |
1089 | } | |
1143 | ||
1144 | #if PY_VERSION_HEX > 0x03050000 | |
1145 | if (inst->wide_name) PyMem_RawFree(inst->wide_name); | |
1146 | if (inst->wide_path) PyMem_RawFree(inst->wide_path); | |
1147 | #endif | |
1148 | } | |
1149 | ||
1090 | 1150 | |
1091 | 1151 | return ret; |
1092 | 1152 | } |
2920 | 2920 | |
2921 | 2921 | |
2922 | 2922 | |
2923 | sm_lib_safe=`echo "tr_tid" | sed 'y%./+-%__p_%'` | |
2924 | sm_func_safe=`echo "tid_srvr_get_key_expiration" | sed 'y%./+-%__p_%'` | |
2925 | ||
2926 | old_LIBS="$LIBS" | |
2927 | old_CPPFLAGS="$CPPFLAGS" | |
2928 | smart_lib= | |
2929 | smart_ldflags= | |
2930 | smart_lib_dir= | |
2931 | ||
2932 | if test "x$smart_try_dir" != "x"; then | |
2933 | for try in $smart_try_dir; do | |
2934 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tid_srvr_get_key_expiration in -ltr_tid in $try" >&5 | |
2935 | $as_echo_n "checking for tid_srvr_get_key_expiration in -ltr_tid in $try... " >&6; } | |
2936 | LIBS="-ltr_tid $old_LIBS" | |
2937 | CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS" | |
2938 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
2939 | /* end confdefs.h. */ | |
2940 | extern char tid_srvr_get_key_expiration(); | |
2941 | int | |
2942 | main () | |
2943 | { | |
2944 | tid_srvr_get_key_expiration() | |
2945 | ; | |
2946 | return 0; | |
2947 | } | |
2948 | _ACEOF | |
2949 | if ac_fn_c_try_link "$LINENO"; then : | |
2950 | ||
2951 | smart_lib="-ltr_tid" | |
2952 | smart_ldflags="-L$try -Wl,-rpath,$try" | |
2953 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
2954 | $as_echo "yes" >&6; } | |
2955 | break | |
2956 | ||
2957 | else | |
2958 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
2959 | $as_echo "no" >&6; } | |
2960 | fi | |
2961 | rm -f core conftest.err conftest.$ac_objext \ | |
2962 | conftest$ac_exeext conftest.$ac_ext | |
2963 | done | |
2964 | LIBS="$old_LIBS" | |
2965 | CPPFLAGS="$old_CPPFLAGS" | |
2966 | fi | |
2967 | ||
2968 | if test "x$smart_lib" = "x"; then | |
2969 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tid_srvr_get_key_expiration in -ltr_tid" >&5 | |
2970 | $as_echo_n "checking for tid_srvr_get_key_expiration in -ltr_tid... " >&6; } | |
2971 | LIBS="-ltr_tid $old_LIBS" | |
2972 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
2973 | /* end confdefs.h. */ | |
2974 | extern char tid_srvr_get_key_expiration(); | |
2975 | int | |
2976 | main () | |
2977 | { | |
2978 | tid_srvr_get_key_expiration() | |
2979 | ; | |
2980 | return 0; | |
2981 | } | |
2982 | _ACEOF | |
2983 | if ac_fn_c_try_link "$LINENO"; then : | |
2984 | ||
2985 | smart_lib="-ltr_tid" | |
2986 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
2987 | $as_echo "yes" >&6; } | |
2988 | ||
2989 | else | |
2990 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
2991 | $as_echo "no" >&6; } | |
2992 | fi | |
2993 | rm -f core conftest.err conftest.$ac_objext \ | |
2994 | conftest$ac_exeext conftest.$ac_ext | |
2995 | LIBS="$old_LIBS" | |
2996 | fi | |
2997 | ||
2998 | if test "x$smart_lib" = "x"; then | |
2999 | ||
3000 | ||
3001 | if test "x$LOCATE" != "x"; then | |
3002 | DIRS= | |
3003 | file=libtr_tid${libltdl_cv_shlibext} | |
3004 | ||
3005 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3006 | base=`echo $x | sed "s%/${file}%%"` | |
3007 | if test "x$x" = "x$base"; then | |
3008 | continue; | |
3009 | fi | |
3010 | ||
3011 | dir=`${DIRNAME} $x 2>/dev/null` | |
3012 | exclude=`echo ${dir} | ${GREP} /home` | |
3013 | if test "x$exclude" != "x"; then | |
3014 | continue | |
3015 | fi | |
3016 | ||
3017 | already=`echo \$smart_lib_dir ${DIRS} | ${GREP} ${dir}` | |
3018 | if test "x$already" = "x"; then | |
3019 | DIRS="$DIRS $dir" | |
3020 | fi | |
3021 | done | |
3022 | fi | |
3023 | ||
3024 | eval "smart_lib_dir=\"\$smart_lib_dir $DIRS\"" | |
3025 | ||
3026 | ||
3027 | ||
3028 | if test "x$LOCATE" != "x"; then | |
3029 | DIRS= | |
3030 | file=libtr_tid.a | |
3031 | ||
3032 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3033 | base=`echo $x | sed "s%/${file}%%"` | |
3034 | if test "x$x" = "x$base"; then | |
3035 | continue; | |
3036 | fi | |
3037 | ||
3038 | dir=`${DIRNAME} $x 2>/dev/null` | |
3039 | exclude=`echo ${dir} | ${GREP} /home` | |
3040 | if test "x$exclude" != "x"; then | |
3041 | continue | |
3042 | fi | |
3043 | ||
3044 | already=`echo \$smart_lib_dir ${DIRS} | ${GREP} ${dir}` | |
3045 | if test "x$already" = "x"; then | |
3046 | DIRS="$DIRS $dir" | |
3047 | fi | |
3048 | done | |
3049 | fi | |
3050 | ||
3051 | eval "smart_lib_dir=\"\$smart_lib_dir $DIRS\"" | |
3052 | ||
3053 | ||
3054 | for try in $smart_lib_dir /usr/local/lib /opt/lib; do | |
3055 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tid_srvr_get_key_expiration in -ltr_tid in $try" >&5 | |
3056 | $as_echo_n "checking for tid_srvr_get_key_expiration in -ltr_tid in $try... " >&6; } | |
3057 | LIBS="-ltr_tid $old_LIBS" | |
3058 | CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS" | |
3059 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3060 | /* end confdefs.h. */ | |
3061 | extern char tid_srvr_get_key_expiration(); | |
3062 | int | |
3063 | main () | |
3064 | { | |
3065 | tid_srvr_get_key_expiration() | |
3066 | ; | |
3067 | return 0; | |
3068 | } | |
3069 | _ACEOF | |
3070 | if ac_fn_c_try_link "$LINENO"; then : | |
3071 | ||
3072 | smart_lib="-ltr_tid" | |
3073 | smart_ldflags="-L$try -Wl,-rpath,$try" | |
3074 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3075 | $as_echo "yes" >&6; } | |
3076 | break | |
3077 | ||
3078 | else | |
3079 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3080 | $as_echo "no" >&6; } | |
3081 | fi | |
3082 | rm -f core conftest.err conftest.$ac_objext \ | |
3083 | conftest$ac_exeext conftest.$ac_ext | |
3084 | done | |
3085 | LIBS="$old_LIBS" | |
3086 | CPPFLAGS="$old_CPPFLAGS" | |
3087 | fi | |
3088 | ||
3089 | if test "x$smart_lib" != "x"; then | |
3090 | eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes" | |
3091 | LIBS="$smart_ldflags $smart_lib $old_LIBS" | |
3092 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" | |
3093 | fi | |
3094 | ||
3095 | ||
3096 | ||
2923 | 3097 | ac_safe=`echo "trust_router/tr_dh.h" | sed 'y%./+-%__pm%'` |
2924 | 3098 | old_CPPFLAGS="$CPPFLAGS" |
2925 | 3099 | smart_include= |
3149 | 3323 | if test "x$ac_cv_header_trust_router_tr_dh_h" != "x"; then |
3150 | 3324 | SMART_CPPFLAGS="$SMART_CPPFLAGS -DHAVE_TRUST_ROUTER_TR_DH_H" |
3151 | 3325 | trustrouter=yes |
3326 | if test "x$ac_cv_lib_tr_tid_tid_srvr_get_key_expiration" != "x"; then | |
3327 | SMART_CPPFLAGS="$SMART_CPPFLAGS -DHAVE_TRUST_ROUTER_GET_KEY_EXP" | |
3328 | fi | |
3152 | 3329 | fi |
3153 | 3330 | fi |
3154 | 3331 |
7 | 7 | AC_PROG_CPP |
8 | 8 | |
9 | 9 | FR_SMART_CHECK_LIB(tr_tid, tidc_create) |
10 | FR_SMART_CHECK_LIB(tr_tid, tid_srvr_get_key_expiration) | |
10 | 11 | FR_SMART_CHECK_INCLUDE(trust_router/tr_dh.h) |
11 | 12 | |
12 | 13 | if test "x$ac_cv_lib_tr_tid_tidc_create" != "x"; then |
13 | 14 | if test "x$ac_cv_header_trust_router_tr_dh_h" != "x"; then |
14 | 15 | SMART_CPPFLAGS="$SMART_CPPFLAGS -DHAVE_TRUST_ROUTER_TR_DH_H" |
15 | 16 | trustrouter=yes |
17 | if test "x$ac_cv_lib_tr_tid_tid_srvr_get_key_expiration" != "x"; then | |
18 | SMART_CPPFLAGS="$SMART_CPPFLAGS -DHAVE_TRUST_ROUTER_GET_KEY_EXP" | |
19 | fi | |
16 | 20 | fi |
17 | 21 | fi |
18 | 22 |
42 | 42 | char const *rp_realm; |
43 | 43 | char const *trust_router; |
44 | 44 | uint32_t tr_port; |
45 | bool rekey_enabled; | |
46 | uint32_t realm_lifetime; | |
45 | 47 | #endif |
46 | 48 | } rlm_realm_t; |
47 | 49 | |
51 | 53 | { "ignore_default", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_realm_t, ignore_default), "no" }, |
52 | 54 | { "ignore_null", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_realm_t, ignore_null), "no" }, |
53 | 55 | #ifdef HAVE_TRUST_ROUTER_TR_DH_H |
54 | { "default_community", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_realm_t,default_community), "none" }, | |
55 | { "rp_realm", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_realm_t,rp_realm), "none" }, | |
56 | { "trust_router", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_realm_t,trust_router), "none" }, | |
57 | { "tr_port", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_realm_t,tr_port), "0" }, | |
56 | { "default_community", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_realm_t, default_community), "none" }, | |
57 | { "rp_realm", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_realm_t, rp_realm), "none" }, | |
58 | { "trust_router", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_realm_t, trust_router), "none" }, | |
59 | { "tr_port", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_realm_t, tr_port), "0" }, | |
60 | { "rekey_enabled", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_realm_t, rekey_enabled), "no" }, | |
61 | { "realm_lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_realm_t, realm_lifetime), "0" }, | |
58 | 62 | #endif |
59 | 63 | CONF_PARSER_TERMINATOR |
60 | 64 | }; |
171 | 175 | * Try querying for the dynamic realm. |
172 | 176 | */ |
173 | 177 | if (!realm && inst->trust_router) { |
174 | realm = tr_query_realm(request, realmname, inst->default_community, inst->rp_realm, inst->trust_router, inst->tr_port); | |
178 | realm = tr_query_realm(request, realmname, inst->default_community, inst->rp_realm, inst->trust_router, | |
179 | inst->tr_port); | |
175 | 180 | } else { |
176 | 181 | RDEBUG2("No trust router configured, skipping dynamic realm lookup"); |
177 | 182 | } |
387 | 392 | #ifdef HAVE_TRUST_ROUTER_TR_DH_H |
388 | 393 | /* initialize the trust router integration code */ |
389 | 394 | if (strcmp(inst->trust_router, "none") != 0) { |
390 | if (!tr_init()) return -1; | |
395 | if (!tr_init(inst->rekey_enabled, inst->realm_lifetime)) return -1; | |
391 | 396 | } else { |
392 | 397 | rad_const_free(inst->trust_router); |
393 | 398 | inst->trust_router = NULL; |
30 | 30 | #include "trustrouter.h" |
31 | 31 | |
32 | 32 | #include <trust_router/tr_dh.h> |
33 | ||
34 | /* This instance is supposed to be thread-safe as it is always used read-only (except in the initiation) */ | |
33 | 35 | static TIDC_INSTANCE *global_tidc = NULL; |
34 | 36 | |
35 | 37 | struct resp_opaque { |
40 | 42 | char *fr_realm_name; |
41 | 43 | }; |
42 | 44 | |
43 | ||
44 | bool tr_init(void) | |
45 | /* | |
46 | * This structure represents a rekey context. It is created once a new REALM is added to the REALM rbtree and it | |
47 | * contains the values required to recreate the TIDC request that originated that REALM. | |
48 | */ | |
49 | struct rekey_ctx { | |
50 | REALM *realm; | |
51 | char const *realm_name; | |
52 | char const *community; | |
53 | char const *rprealm; | |
54 | char const *trustrouter; | |
55 | unsigned int port; | |
56 | unsigned int times; | |
57 | unsigned int failed; | |
58 | fr_event_t *ev; | |
59 | }; | |
60 | ||
61 | /* Thread, event list, and mutexes to protect access to the event list */ | |
62 | static pthread_t rekeyer_thread_id; | |
63 | static fr_event_list_t *rekey_evl = NULL; | |
64 | static pthread_mutex_t evl_mutex; | |
65 | static pthread_mutexattr_t evl_mutex_attr; | |
66 | ||
67 | /* Simultaneous TIDC connections do not work well. We use this mutext to serialize them */ | |
68 | static pthread_mutex_t tidc_mutex; | |
69 | ||
70 | /* Constant declarations */ | |
71 | static uint MAX_FAILED_REKEYS = 5; // Max number of tolerable consecutive rekey errors | |
72 | static uint REKEY_ERROR_DELAY = 10; // Number of seconds we wait until we start a new rekey after a failure | |
73 | static uint REKEY_THRESHOLD = 120; // Number of seconds before the REALM expires to start a rekey | |
74 | ||
75 | /* Configuration parameters */ | |
76 | static uint32_t realm_lifetime = 0; // Number of seconds the REALM can be used | |
77 | static bool rekey_enabled = false; // Is the rekey functionality enabled? | |
78 | ||
79 | /* Forward declarations */ | |
80 | static void tr_response_func(TIDC_INSTANCE*, TID_REQ*, TID_RESP*, void*); | |
81 | static void _tr_do_rekey(void *); | |
82 | ||
83 | /* | |
84 | * Builds a rekey_ctx context using the given parameters. | |
85 | * Memory context is attached to the REALM object, whereas all the char* fields are copied. | |
86 | */ | |
87 | static struct rekey_ctx *build_rekey_ctx(REALM *realm, char const *realm_name, char const *community, | |
88 | char const *rprealm, const char *trustrouter, int port) | |
89 | { | |
90 | struct rekey_ctx *ctx = talloc_zero(realm, struct rekey_ctx); | |
91 | ctx->realm = realm; | |
92 | ctx->realm_name = talloc_strdup(ctx, realm_name); | |
93 | ctx->community = talloc_strdup(ctx, community); | |
94 | ctx->rprealm = talloc_strdup(ctx, rprealm); | |
95 | ctx->trustrouter = talloc_strdup(ctx, trustrouter); | |
96 | ctx->port = port; | |
97 | ctx->times = 0; | |
98 | ctx->ev = NULL; | |
99 | return ctx; | |
100 | } | |
101 | ||
102 | /* | |
103 | * Main function for the rekeyer thread, which implements the rekey event loop. | |
104 | * A recursive lock is used to protect access to the event list, which might receive insertions from | |
105 | * other threads (i.e. REQUESTS). | |
106 | * If there are no rekey events to be executed, it sleeps for 1 second. | |
107 | */ | |
108 | void *rekeyer_thread(UNUSED void* args) | |
109 | { | |
110 | struct timeval when; | |
111 | int rv = 0; | |
112 | while (true) { | |
113 | gettimeofday(&when, NULL); | |
114 | pthread_mutex_lock(&evl_mutex); | |
115 | rv = fr_event_run(rekey_evl, &when); | |
116 | // DEBUG2("REALMs to be rekeyed: %d. Next rekey event in %lu seconds", | |
117 | // fr_event_list_num_elements(rekey_evl), when.tv_sec - time(NULL)); | |
118 | pthread_mutex_unlock(&evl_mutex); | |
119 | if (!rv) sleep(1); | |
120 | } | |
121 | return NULL; | |
122 | } | |
123 | ||
124 | /* | |
125 | * Sends a TIDC request and fills up the provided cookie with the response. | |
126 | * Returns FALSE if a response cannot be obtained for some reason (e.g. cannot connect to the TR) | |
127 | */ | |
128 | static bool tidc_send_recv(const char *trustrouter, int port, const char *rprealm, const char *realm_name, | |
129 | const char *community, struct resp_opaque *cookie) | |
130 | { | |
131 | gss_ctx_id_t gssctx; | |
132 | int conn = 0; | |
133 | int rcode; | |
134 | ||
135 | /* Open TIDC connection */ | |
136 | DEBUG2("Opening TIDC connection to %s:%u", trustrouter, port); | |
137 | conn = tidc_open_connection(global_tidc, (char *) trustrouter, port, &gssctx); | |
138 | if (conn < 0) { | |
139 | DEBUG2("Error in tidc_open_connection."); | |
140 | return false; | |
141 | } | |
142 | ||
143 | /* Send TIDC request */ | |
144 | rcode = tidc_send_request(global_tidc, conn, gssctx, (char *) rprealm, (char *) realm_name, | |
145 | (char *) community, &tr_response_func, cookie); | |
146 | if (rcode > 0) { | |
147 | DEBUG2("Error in tidc_send_request, rc = %d.", rcode); | |
148 | return false; | |
149 | } | |
150 | ||
151 | return true; | |
152 | } | |
153 | ||
154 | /* | |
155 | * Gets the maximum expiration time of the realm's auth pool. | |
156 | */ | |
157 | static time_t get_realm_expiration(REALM const *realm) | |
158 | { | |
159 | time_t expiration = 0; | |
160 | for (int i = 0; i < realm->auth_pool->num_home_servers; i++) { | |
161 | home_server_t *server = realm->auth_pool->servers[i]; | |
162 | if (server->expiration > expiration) | |
163 | expiration = server->expiration; | |
164 | } | |
165 | return expiration; | |
166 | } | |
167 | ||
168 | /* | |
169 | * Schedules a rekey event with the indicated context by inserting a new event in the list. | |
170 | * It uses the evl_mutex to make no other thread accesses the event list at the same time. | |
171 | */ | |
172 | static int schedule_rekey(struct rekey_ctx *rekey_ctx) | |
173 | { | |
174 | int rv = 0; | |
175 | struct timeval when; | |
176 | gettimeofday(&when, NULL); | |
177 | pthread_mutex_lock(&evl_mutex); | |
178 | /* If last attempt was a failure, schedule a rekey in REKEY_ERROR_DELAY seconds. | |
179 | * Else, schedule the rekey for REKEY_THRESHOLD seconds before the actual REALM expiration. | |
180 | */ | |
181 | if (rekey_ctx->failed) | |
182 | when.tv_sec += REKEY_ERROR_DELAY; | |
183 | else | |
184 | when.tv_sec = get_realm_expiration(rekey_ctx->realm) - REKEY_THRESHOLD; | |
185 | ||
186 | rv = fr_event_insert(rekey_evl, _tr_do_rekey, rekey_ctx, &when, &rekey_ctx->ev); | |
187 | pthread_mutex_unlock(&evl_mutex); | |
188 | DEBUG2("Scheduled a rekey for realm %s in %lu seconds", rekey_ctx->realm_name, when.tv_sec - time(NULL)); | |
189 | return rv; | |
190 | } | |
191 | ||
192 | /* | |
193 | * Callback that performs the actual rekey of a REALM. It receives a rekey_ctx which is used to replicate the | |
194 | * original TIDC query. If the request is sucessful, a new rekey is scheduled based on the expiration lifetime and | |
195 | * the configured threshold (REKEY_THRESHOLD). | |
196 | * When a failure is found, a new rekey is scheduled in a shorter period of time (REKEY_ERROR_DELAY). | |
197 | */ | |
198 | static void _tr_do_rekey(void *ctx){ | |
199 | struct rekey_ctx *rekey_ctx = (struct rekey_ctx *) ctx; | |
200 | bool result; | |
201 | struct resp_opaque cookie; | |
202 | ||
203 | /* clear the cookie structure and copy values from the rekey context */ | |
204 | memset (&cookie, 0, sizeof(cookie)); | |
205 | cookie.fr_realm_name = (char*) rekey_ctx->realm->name; | |
206 | cookie.orig_realm = rekey_ctx->realm; | |
207 | ||
208 | DEBUG2("Rekeying realm %s for the %dth time", rekey_ctx->realm_name, ++rekey_ctx->times); | |
209 | ||
210 | /* send the TIDC request and get the response. Use GLOBAL mutext to protect global_tidc and the realm */ | |
211 | pthread_mutex_lock(&tidc_mutex); | |
212 | result = tidc_send_recv(rekey_ctx->trustrouter, rekey_ctx->port, rekey_ctx->rprealm, | |
213 | rekey_ctx->realm_name, rekey_ctx->community, &cookie); | |
214 | pthread_mutex_unlock(&tidc_mutex); | |
215 | ||
216 | /* If the rekey failed, schedule a new rekey in REKEY_ERROR_DELAY seconds, unless we have failed more | |
217 | than MAX_FAILED_REKEYS times in a row. In that case, return without scheduling a rekey */ | |
218 | if (!result || cookie.result != TID_SUCCESS) { | |
219 | if (++rekey_ctx->failed >= MAX_FAILED_REKEYS) { | |
220 | DEBUG2("Reached the maximum number of failed rekeys (%d) for realm %s. Giving up.", | |
221 | MAX_FAILED_REKEYS, rekey_ctx->realm_name); | |
222 | talloc_free(rekey_ctx); | |
223 | return; | |
224 | } | |
225 | DEBUG2("Rekey for realm %s failed for the %dth time.", rekey_ctx->realm_name, rekey_ctx->failed); | |
226 | } | |
227 | /* if rekey is successful, reset the failed counter */ | |
228 | else { | |
229 | rekey_ctx->failed = 0; | |
230 | } | |
231 | ||
232 | /* schedule the new rekey */ | |
233 | if (!schedule_rekey(rekey_ctx)){ | |
234 | DEBUG2("Error scheduling rekey event for realm %s!", rekey_ctx->realm_name); | |
235 | talloc_free(rekey_ctx); | |
236 | } | |
237 | } | |
238 | ||
239 | bool tr_init(bool cnf_rekey_enabled, uint32_t cnf_realm_lifetime) | |
45 | 240 | { |
46 | 241 | if (global_tidc) return true; |
47 | 242 | |
54 | 249 | if (!tidc_set_dh(global_tidc, tr_create_dh_params(NULL, 0))) { |
55 | 250 | DEBUG2( "tr_init: Error creating client DH params.\n"); |
56 | 251 | return false; |
252 | } | |
253 | ||
254 | realm_lifetime = cnf_realm_lifetime; | |
255 | rekey_enabled = cnf_rekey_enabled; | |
256 | ||
257 | /* create the TIDC mutex */ | |
258 | pthread_mutex_init(&tidc_mutex, NULL); | |
259 | ||
260 | /* If rekey is enabled, set up and create the rekeyer thread, event list and event mutex (recursive) */ | |
261 | if (rekey_enabled) { | |
262 | rekey_evl = fr_event_list_create(NULL, NULL); | |
263 | pthread_mutexattr_init(&evl_mutex_attr); | |
264 | pthread_mutexattr_settype(&evl_mutex_attr, PTHREAD_MUTEX_RECURSIVE); | |
265 | pthread_mutex_init(&evl_mutex, &evl_mutex_attr); | |
266 | pthread_create(&rekeyer_thread_id, NULL, rekeyer_thread, NULL); | |
57 | 267 | } |
58 | 268 | |
59 | 269 | return true; |
68 | 278 | ssize_t keylen; |
69 | 279 | char *hexbuf = NULL; |
70 | 280 | DH *aaa_server_dh; |
281 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
282 | const BIGNUM *dh_pubkey = NULL; | |
283 | #endif | |
71 | 284 | |
72 | 285 | tls = tls_server_conf_alloc(hs); |
73 | 286 | if (!tls) return NULL; |
74 | 287 | |
75 | 288 | aaa_server_dh = tid_srvr_get_dh(server); |
289 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
290 | DH_get0_key(aaa_server_dh, &dh_pubkey, NULL); | |
291 | if (NULL == dh_pubkey) { | |
292 | DEBUG2("DH error"); | |
293 | goto error; | |
294 | } | |
295 | ||
296 | keylen = tr_compute_dh_key(&key_buf, BN_dup(dh_pubkey), | |
297 | tidc_get_dh(inst)); | |
298 | #else | |
76 | 299 | keylen = tr_compute_dh_key(&key_buf, aaa_server_dh->pub_key, |
77 | 300 | tidc_get_dh(inst)); |
301 | #endif | |
78 | 302 | if (keylen <= 0) { |
79 | 303 | DEBUG2("DH error"); |
80 | 304 | goto error; |
107 | 331 | if (tls) talloc_free(tls); |
108 | 332 | return NULL; |
109 | 333 | } |
110 | ||
334 | ||
111 | 335 | static char *build_pool_name(TALLOC_CTX *ctx, TID_RESP *resp) |
112 | 336 | { |
113 | 337 | size_t index, sa_len, sl; |
149 | 373 | fr_ipaddr_t home_server_ip; |
150 | 374 | uint16_t port; |
151 | 375 | char nametemp[256]; |
376 | time_t now = time(NULL); | |
377 | struct timeval key_expiration; | |
152 | 378 | |
153 | 379 | rad_assert(blk != NULL); |
154 | 380 | tid_srvr_get_address(blk, &sa, &sa_len); |
155 | 381 | |
156 | 382 | fr_sockaddr2ipaddr((struct sockaddr_storage *) sa, sa_len, &home_server_ip, &port); |
157 | ||
383 | ||
158 | 384 | if (0 != getnameinfo(sa, sa_len, |
159 | 385 | nametemp, |
160 | 386 | sizeof nametemp, |
179 | 405 | hs->proto = IPPROTO_TCP; |
180 | 406 | hs->secret = talloc_strdup(hs, "radsec"); |
181 | 407 | hs->response_window.tv_sec = 30; |
182 | hs->last_packet_recv = time(NULL); | |
183 | /* | |
184 | * We want sockets using these servers to close as soon as possible, | |
185 | * to make sure that whenever a pool is replaced, sockets using old ones | |
408 | hs->last_packet_recv = now; | |
409 | /* | |
410 | * We want sockets using these servers to close as soon as possible, | |
411 | * to make sure that whenever a pool is replaced, sockets using old ones | |
186 | 412 | * will not last long (hopefully less than 300s). |
187 | 413 | */ |
188 | 414 | hs->limit.idle_timeout = 5; |
415 | /* | |
416 | * Set the expiration of the server. | |
417 | * If a realm_lifetime configuration parameter is provided (i.e. >0), use: now + realm_lifetime | |
418 | * Else use the value from the TIDC response (if the accessor function is available) or now + 600 | |
419 | */ | |
420 | #ifdef HAVE_TRUST_ROUTER_GET_KEY_EXP | |
421 | tid_srvr_get_key_expiration(blk, &key_expiration); | |
422 | #else | |
423 | key_expiration.tv_sec = now + 600; | |
424 | #endif | |
425 | hs->expiration = realm_lifetime > 0 ? (now + realm_lifetime) : key_expiration.tv_sec; | |
189 | 426 | hs->tls = construct_tls(inst, hs, blk); |
190 | 427 | if (!hs->tls) goto error; |
191 | 428 | |
257 | 494 | } |
258 | 495 | return; |
259 | 496 | } |
260 | ||
497 | ||
261 | 498 | if (!nr) { |
262 | 499 | nr = talloc_zero(NULL, REALM); |
263 | 500 | if (!nr) goto error; |
284 | 521 | |
285 | 522 | opaque->output_realm = nr; |
286 | 523 | return; |
287 | ||
524 | ||
288 | 525 | error: |
289 | 526 | if (nr && !opaque->orig_realm) { |
290 | 527 | talloc_free(nr); |
319 | 556 | /* |
320 | 557 | * These values don't make sense. |
321 | 558 | */ |
322 | if ((server->last_packet_recv > (now + 5)) || | |
559 | if ((server->last_packet_recv > (now + 5)) || | |
323 | 560 | (server->last_failed_open > (now + 5))) { |
324 | 561 | continue; |
325 | 562 | } |
326 | 563 | |
564 | /* | |
565 | * If home server is expired, update | |
566 | */ | |
567 | if (now > server->expiration) | |
568 | continue; | |
327 | 569 | /* |
328 | 570 | * If we've opened in the last 10 minutes, then |
329 | 571 | * open rather than update. |
336 | 578 | return true; |
337 | 579 | } |
338 | 580 | |
339 | ||
340 | ||
341 | 581 | REALM *tr_query_realm(REQUEST *request, char const *realm, |
342 | 582 | char const *community, |
343 | 583 | char const *rprealm, |
344 | 584 | char const *trustrouter, |
345 | 585 | unsigned int port) |
346 | 586 | { |
347 | int conn = 0; | |
348 | int rcode; | |
349 | 587 | VALUE_PAIR *vp; |
350 | gss_ctx_id_t gssctx; | |
351 | 588 | struct resp_opaque cookie; |
589 | bool rv = false; | |
352 | 590 | |
353 | 591 | if (!realm) return NULL; |
354 | 592 | |
363 | 601 | community = vp->vp_strvalue; |
364 | 602 | else pair_make_request("Trust-Router-COI", community, T_OP_SET); |
365 | 603 | |
604 | /* Check if we already have a valid REALM and return it */ | |
366 | 605 | cookie.fr_realm_name = talloc_asprintf(NULL, |
367 | 606 | "%s%%%s", |
368 | 607 | community, realm); |
369 | ||
370 | 608 | cookie.orig_realm = cookie.output_realm = realm_find(cookie.fr_realm_name); |
371 | ||
372 | if (cookie.orig_realm && !update_required(cookie.orig_realm)) { | |
373 | talloc_free(cookie.fr_realm_name); | |
374 | return cookie.orig_realm; | |
375 | } | |
376 | ||
377 | /* Set-up TID connection */ | |
378 | DEBUG2("Opening TIDC connection to %s:%u", trustrouter, port); | |
379 | ||
380 | conn = tidc_open_connection(global_tidc, (char *)trustrouter, port, &gssctx); | |
381 | if (conn < 0) { | |
382 | /* Handle error */ | |
383 | DEBUG2("Error in tidc_open_connection.\n"); | |
609 | if (cookie.orig_realm && !update_required(cookie.orig_realm)) | |
384 | 610 | goto cleanup; |
385 | } | |
386 | ||
387 | /* Send a TID request */ | |
388 | rcode = tidc_send_request(global_tidc, conn, gssctx, (char *)rprealm, | |
389 | (char *) realm, (char *)community, | |
390 | &tr_response_func, &cookie); | |
391 | if (rcode < 0) { | |
392 | /* Handle error */ | |
393 | DEBUG2("Error in tidc_send_request, rc = %d.\n", rcode); | |
611 | ||
612 | /* We use this lock for serializing TIDC requests and protect access to the TIDC calls */ | |
613 | pthread_mutex_lock(&tidc_mutex); | |
614 | ||
615 | /* Check again that the realm was not created while we were waiting to acquire the lock. */ | |
616 | cookie.orig_realm = cookie.output_realm = realm_find(cookie.fr_realm_name); | |
617 | if (cookie.orig_realm && !update_required(cookie.orig_realm)){ | |
618 | pthread_mutex_unlock(&tidc_mutex); | |
394 | 619 | goto cleanup; |
395 | 620 | } |
621 | ||
622 | /* Perform the request/response exchange with the trust router server */ | |
623 | rv = tidc_send_recv(trustrouter, port, (char *) rprealm, (char *) realm, (char *)community, &cookie); | |
624 | pthread_mutex_unlock(&tidc_mutex); | |
625 | ||
626 | /* If we weren't able to get a response from the trust router server, goto cleanup (hence return NULL realm) */ | |
627 | if (!rv) goto cleanup; | |
628 | ||
629 | /* If we got a response but it is an error one, include a Reply-Message and Error-Cause attributes */ | |
396 | 630 | if (cookie.result != TID_SUCCESS) { |
397 | 631 | DEBUG2("TID response is error, rc = %d: %s.\n", cookie.result, |
398 | 632 | cookie.err_msg?cookie.err_msg:"(NO ERROR TEXT)"); |
399 | if (cookie.err_msg) | |
633 | if (cookie.err_msg) | |
400 | 634 | pair_make_reply("Reply-Message", cookie.err_msg, T_OP_SET); |
401 | 635 | pair_make_reply("Error-Cause", "502", T_OP_SET); /*proxy unroutable*/ |
636 | } | |
637 | /* TIDC request was successful. If rekey is enabled, create a rekey event */ | |
638 | else if (rekey_enabled) { | |
639 | struct rekey_ctx *rctx = build_rekey_ctx(cookie.output_realm, realm, community, | |
640 | rprealm, trustrouter, port); | |
641 | if (!schedule_rekey(rctx)){ | |
642 | talloc_free(rctx); | |
643 | DEBUG2("Error scheduling rekey event for realm %s!", realm); | |
644 | } | |
402 | 645 | } |
403 | 646 | |
404 | 647 | cleanup: |
32 | 32 | char const *trustrouter, |
33 | 33 | unsigned int port); |
34 | 34 | |
35 | bool tr_init(void); | |
35 | bool tr_init(bool cnf_rekey_enabled, uint32_t cnf_realm_lifetime); | |
36 | 36 | |
37 | 37 | #endif |
35 | 35 | { "port", FR_CONF_OFFSET(PW_TYPE_SHORT, REDIS_INST, port), "6379" }, |
36 | 36 | { "database", FR_CONF_OFFSET(PW_TYPE_INTEGER, REDIS_INST, database), "0" }, |
37 | 37 | { "password", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, REDIS_INST, password), NULL }, |
38 | { "query_timeout", FR_CONF_OFFSET(PW_TYPE_SHORT, REDIS_INST, query_timeout), "5" }, | |
38 | 39 | CONF_PARSER_TERMINATOR |
39 | 40 | }; |
40 | 41 | |
60 | 61 | redisContext *conn; |
61 | 62 | redisReply *reply = NULL; |
62 | 63 | char buffer[1024]; |
63 | ||
64 | conn = redisConnect(inst->hostname, inst->port); | |
64 | struct timeval tv; | |
65 | tv.tv_sec = inst->query_timeout; | |
66 | tv.tv_usec = 0; | |
67 | ||
68 | conn = redisConnectWithTimeout(inst->hostname, inst->port, tv); | |
65 | 69 | if (!conn) { |
66 | ERROR("rlm_redis (%s): Failed calling redisConnect('%s', %d)", | |
67 | inst->xlat_name, inst->hostname, inst->port); | |
70 | ERROR("rlm_redis (%s): Failed calling redisConnectWithTimeout('%s', %d, %d)", | |
71 | inst->xlat_name, inst->hostname, inst->port, inst->query_timeout); | |
68 | 72 | return NULL; |
69 | 73 | } |
70 | 74 | |
71 | 75 | if (conn && conn->err) { |
72 | ERROR("rlm_redis (%s): Problems with redisConnect('%s', %d), %s", | |
73 | inst->xlat_name, inst->hostname, inst->port, redisReplyReaderGetError(conn)); | |
76 | ERROR("rlm_redis (%s): Problems with redisConnectWithTimeout('%s', %d, %d), %s", | |
77 | inst->xlat_name, inst->hostname, inst->port, inst->query_timeout, redisReplyReaderGetError(conn)); | |
78 | redisFree(conn); | |
79 | return NULL; | |
80 | } | |
81 | ||
82 | if ( redisSetTimeout(conn, tv) == REDIS_ERR ) { | |
83 | ERROR("rlm_redis (%s): redisSetTimeout('%s', %d) returned REDIS_ERR", inst->xlat_name, inst->hostname, inst->port); | |
74 | 84 | redisFree(conn); |
75 | 85 | return NULL; |
76 | 86 | } |
214 | 224 | int argc; |
215 | 225 | char const *argv[MAX_REDIS_ARGS]; |
216 | 226 | char argv_buf[MAX_QUERY_LEN]; |
227 | struct timeval tv; | |
228 | tv.tv_sec = inst->query_timeout; | |
229 | tv.tv_usec = 0; | |
217 | 230 | |
218 | 231 | if (!query || !*query || !inst || !dissocket_p) { |
219 | 232 | return -1; |
238 | 251 | return -1; |
239 | 252 | } |
240 | 253 | |
241 | dissocket->reply = redisCommand(dissocket->conn, query); | |
254 | dissocket->reply = redisCommand(dissocket->conn, query, tv); | |
242 | 255 | if (!dissocket->reply) { |
243 | 256 | RERROR("Failed after re-connect"); |
244 | fr_connection_close(inst->pool, dissocket); | |
257 | fr_connection_close(inst->pool, dissocket, NULL); | |
245 | 258 | goto error; |
246 | 259 | } |
247 | 260 |
46 | 46 | uint16_t port; |
47 | 47 | uint32_t database; |
48 | 48 | char const *password; |
49 | uint16_t query_timeout; | |
49 | 50 | fr_connection_pool_t *pool; |
50 | 51 | |
51 | 52 | int (*redis_query)(REDISSOCK **dissocket_p, REDIS_INST *inst, char const *query, REQUEST *request); |
1545 | 1545 | http_body_type_t type; |
1546 | 1546 | |
1547 | 1547 | /* |
1548 | * Curl seems to throw these (\r\n) in before the next set of headers when | |
1549 | * looks like it's just a body separator and safe to ignore after we | |
1550 | * receive a 100 Continue. | |
1551 | */ | |
1552 | if (t == 2 && ((p[0] == '\r') && (p[1] == '\n'))) return t; | |
1548 | * This seems to be curl's indication there are no more header lines. | |
1549 | */ | |
1550 | if (t == 2 && ((p[0] == '\r') && (p[1] == '\n'))) { | |
1551 | /* | |
1552 | * If we got a 100 Continue, we need to send additional payload data. | |
1553 | * reset the state to WRITE_STATE_INIT, so that when were called again | |
1554 | * we overwrite previous header data with that from the proper header. | |
1555 | */ | |
1556 | if (ctx->code == 100) { | |
1557 | RDEBUG2("Continuing..."); | |
1558 | ctx->state = WRITE_STATE_INIT; | |
1559 | } | |
1560 | ||
1561 | return t; | |
1562 | } | |
1553 | 1563 | |
1554 | 1564 | switch (ctx->state) { |
1555 | 1565 | case WRITE_STATE_INIT: |
1697 | 1707 | break; |
1698 | 1708 | } |
1699 | 1709 | |
1700 | /* | |
1701 | * If we got a 100 Continue, we need to send additional payload data. | |
1702 | * reset the state to WRITE_STATE_INIT, so that when were called again | |
1703 | * we overwrite previous header data with that from the proper header. | |
1704 | */ | |
1705 | if (ctx->code == 100) { | |
1706 | RDEBUG2("Continuing..."); | |
1707 | ctx->state = WRITE_STATE_INIT; | |
1708 | } | |
1709 | ||
1710 | 1710 | return t; |
1711 | 1711 | |
1712 | 1712 | malformed: |
1740 | 1740 | |
1741 | 1741 | char const *p = ptr, *q; |
1742 | 1742 | char *tmp; |
1743 | ||
1743 | ||
1744 | 1744 | size_t const t = (size * nmemb); |
1745 | size_t needed; | |
1745 | 1746 | |
1746 | 1747 | if (t == 0) return 0; |
1747 | 1748 | |
1780 | 1781 | return t; |
1781 | 1782 | |
1782 | 1783 | default: |
1783 | if (t > (ctx->alloc - ctx->used)) { | |
1784 | ctx->alloc += ((t + 1) > REST_BODY_INIT) ? t + 1 : REST_BODY_INIT; | |
1784 | needed = ctx->used + t + 1; | |
1785 | if (needed < REST_BODY_INIT) needed = REST_BODY_INIT; | |
1786 | ||
1787 | if (needed > ctx->alloc) { | |
1788 | ctx->alloc = needed; | |
1785 | 1789 | |
1786 | 1790 | tmp = ctx->buffer; |
1787 | 1791 | |
1789 | 1793 | |
1790 | 1794 | /* If data has been written previously */ |
1791 | 1795 | if (tmp) { |
1792 | strlcpy(ctx->buffer, tmp, (ctx->used + 1)); | |
1796 | memcpy(ctx->buffer, tmp, ctx->used); | |
1793 | 1797 | free(tmp); |
1794 | 1798 | } |
1795 | 1799 | } |
1796 | 1800 | strlcpy(ctx->buffer + ctx->used, p, t + 1); |
1797 | ctx->used += t; | |
1801 | ctx->used += t; /* don't include the trailing zero */ | |
1798 | 1802 | |
1799 | 1803 | break; |
1800 | 1804 | } |
2932 | 2932 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" |
2933 | 2933 | fi |
2934 | 2934 | |
2935 | LDFLAGS="$SMART_LIBS" | |
2935 | LDFLAGS="${LDFLAGS} ${SMART_LIBS}" | |
2936 | 2936 | if test "x$ac_cv_lib_sqlite3_sqlite3_open" != "xyes" |
2937 | 2937 | then |
2938 | 2938 | { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Sqlite libraries not found. Use --with-sqlite-lib-dir=<path>." >&5 |
73 | 73 | smart_try_dir="$sqlite_lib_dir" |
74 | 74 | FR_SMART_CHECK_LIB(sqlite3, sqlite3_open) |
75 | 75 | dnl # Ensure we use the library we just found the rest of the checks |
76 | LDFLAGS="$SMART_LIBS" | |
76 | LDFLAGS="${LDFLAGS} ${SMART_LIBS}" | |
77 | 77 | if test "x$ac_cv_lib_sqlite3_sqlite3_open" != "xyes" |
78 | 78 | then |
79 | 79 | AC_MSG_WARN([Sqlite libraries not found. Use --with-sqlite-lib-dir=<path>.]) |
232 | 232 | ssize_t len; |
233 | 233 | int statement_cnt = 0; |
234 | 234 | char *buffer; |
235 | char *p, *q, *s; | |
235 | char *p, *q; | |
236 | 236 | int cl; |
237 | 237 | FILE *f; |
238 | 238 | struct stat finfo; |
320 | 320 | /* |
321 | 321 | * Statement delimiter is ;\n |
322 | 322 | */ |
323 | s = p = buffer; | |
323 | p = buffer; | |
324 | 324 | while ((q = strchr(p, ';'))) { |
325 | if (q[1] != '\n') { | |
325 | if ((q[1] != '\n') && (q[1] != '\0')) { | |
326 | 326 | p = q + 1; |
327 | 327 | statement_cnt++; |
328 | 328 | continue; |
329 | 329 | } |
330 | 330 | |
331 | *q = '\0'; | |
332 | ||
333 | 331 | #ifdef HAVE_SQLITE3_PREPARE_V2 |
334 | status = sqlite3_prepare_v2(db, s, len, &statement, &z_tail); | |
332 | status = sqlite3_prepare_v2(db, p, q - p, &statement, &z_tail); | |
335 | 333 | #else |
336 | status = sqlite3_prepare(db, s, len, &statement, &z_tail); | |
334 | status = sqlite3_prepare(db, p, q - p, &statement, &z_tail); | |
337 | 335 | #endif |
338 | 336 | |
339 | 337 | if (sql_check_error(db, status) != RLM_SQL_OK) { |
358 | 356 | } |
359 | 357 | |
360 | 358 | statement_cnt++; |
361 | p = s = q + 1; | |
359 | p = q + 1; | |
362 | 360 | } |
363 | 361 | |
364 | 362 | talloc_free(buffer); |
486 | 486 | return; |
487 | 487 | } |
488 | 488 | |
489 | fd = exfile_open(inst->ef, filename, 0640, true); | |
489 | fd = exfile_open(inst->ef, expanded, 0640); | |
490 | 490 | if (fd < 0) { |
491 | 491 | ERROR("rlm_sql (%s): Couldn't open logfile '%s': %s", inst->name, |
492 | 492 | expanded, fr_syserror(errno)); |
16 | 16 | /** |
17 | 17 | * $Id$ |
18 | 18 | * @file rlm_sqlippool.c |
19 | * @brief Allocates an IPv4 address from pools stored in SQL. | |
19 | * @brief Allocates an IP address / prefix from pools stored in SQL. | |
20 | 20 | * |
21 | 21 | * @copyright 2002 Globe.Net Communications Limited |
22 | 22 | * @copyright 2006 The FreeRADIUS server project |
45 | 45 | |
46 | 46 | char const *pool_name; |
47 | 47 | bool ipv6; //!< Whether or not we do IPv6 pools. |
48 | int framed_ip_address; //!< the attribute number for Framed-IP(v6)-Address | |
48 | bool allow_duplicates; //!< assign even if it already exists | |
49 | char const *attribute_name; //!< name of the IP address attribute | |
50 | ||
51 | DICT_ATTR const *framed_ip_address; //!< the attribute for IP address allocation | |
49 | 52 | |
50 | 53 | time_t last_clear; //!< So we only do it once a second. |
51 | 54 | char const *allocate_begin; //!< SQL query to begin. |
126 | 129 | |
127 | 130 | |
128 | 131 | { "ipv6", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_sqlippool_t, ipv6), NULL}, |
132 | { "allow_duplicates", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_sqlippool_t, allow_duplicates), NULL}, | |
133 | { "attribute_name", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_sqlippool_t, attribute_name), NULL}, | |
129 | 134 | |
130 | 135 | { "allocate-begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_begin), NULL }, |
131 | 136 | { "allocate_begin", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, rlm_sqlippool_t, allocate_begin), "START TRANSACTION" }, |
420 | 425 | return -1; |
421 | 426 | } |
422 | 427 | |
423 | if (!inst->ipv6) { | |
424 | inst->framed_ip_address = PW_FRAMED_IP_ADDRESS; | |
428 | if (inst->attribute_name) { | |
429 | DICT_ATTR const *da; | |
430 | ||
431 | da = dict_attrbyname(inst->attribute_name); | |
432 | if (!da) { | |
433 | fail: | |
434 | cf_log_err_cs(conf, "Unknown attribute 'attribute_name = %s'", inst->attribute_name); | |
435 | return -1; | |
436 | } | |
437 | ||
438 | switch (da->type) { | |
439 | default: | |
440 | cf_log_err_cs(conf, "Cannot use non-IP attributes for 'attribute_name = %s'", inst->attribute_name); | |
441 | return -1; | |
442 | ||
443 | case PW_TYPE_IPV4_ADDR: | |
444 | case PW_TYPE_IPV6_ADDR: | |
445 | case PW_TYPE_IPV4_PREFIX: | |
446 | case PW_TYPE_IPV6_PREFIX: | |
447 | break; | |
448 | ||
449 | } | |
450 | ||
451 | inst->framed_ip_address = da; | |
425 | 452 | } else { |
426 | inst->framed_ip_address = PW_FRAMED_IPV6_PREFIX; | |
453 | if (!inst->ipv6) { | |
454 | inst->attribute_name = "Framed-IP-Address"; | |
455 | inst->framed_ip_address = dict_attrbyvalue(PW_FRAMED_IP_ADDRESS, 0); | |
456 | } else { | |
457 | inst->attribute_name = "Framed-IPv6-Prefix"; | |
458 | inst->framed_ip_address = dict_attrbyvalue(PW_FRAMED_IPV6_PREFIX, 0); | |
459 | } | |
460 | ||
461 | if (!inst->framed_ip_address) goto fail; | |
427 | 462 | } |
428 | 463 | |
429 | 464 | if (strcmp(sql_inst->entry->name, "rlm_sql") != 0) { |
473 | 508 | time_t now; |
474 | 509 | |
475 | 510 | /* |
476 | * If there is a Framed-IP-Address attribute in the reply do nothing | |
477 | */ | |
478 | if (fr_pair_find_by_num(request->reply->vps, inst->framed_ip_address, 0, TAG_ANY) != NULL) { | |
479 | RDEBUG("Framed-IP-Address already exists"); | |
511 | * If there is already an attribute in the reply do nothing | |
512 | */ | |
513 | if (!inst->allow_duplicates && (fr_pair_find_by_num(request->reply->vps, inst->framed_ip_address->attr, inst->framed_ip_address->vendor, TAG_ANY) != NULL)) { | |
514 | RDEBUG("%s already exists", inst->attribute_name); | |
480 | 515 | |
481 | 516 | return do_logging(request, inst->log_exists, RLM_MODULE_NOOP); |
482 | 517 | } |
576 | 611 | * See if we can create the VP from the returned data. If not, |
577 | 612 | * error out. If so, add it to the list. |
578 | 613 | */ |
579 | vp = fr_pair_afrom_num(request->reply, inst->framed_ip_address, 0); | |
614 | vp = fr_pair_afrom_num(request->reply, inst->framed_ip_address->attr, inst->framed_ip_address->vendor); | |
580 | 615 | if (fr_pair_value_from_str(vp, allocation, allocation_len) < 0) { |
581 | 616 | DO_PART(allocate_commit); |
582 | 617 |
3703 | 3703 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" |
3704 | 3704 | fi |
3705 | 3705 | |
3706 | if test "x$ac_cv_lib_ykclient_ykclient_request" == "xyes"; then | |
3706 | if test "x$ac_cv_lib_ykclient_ykclient_request" = "xyes"; then | |
3707 | 3707 | { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libykclient missing ykclient_request_process. A later version of libykclient is required." >&5 |
3708 | 3708 | $as_echo "$as_me: WARNING: libykclient missing ykclient_request_process. A later version of libykclient is required." >&2;} |
3709 | 3709 | else |
162 | 162 | if test "x$ac_cv_lib_ykclient_ykclient_request_process" != "xyes"; then |
163 | 163 | have_ykclient="no" |
164 | 164 | FR_SMART_CHECK_LIB([ykclient], [ykclient_request]) |
165 | if test "x$ac_cv_lib_ykclient_ykclient_request" == "xyes"; then | |
165 | if test "x$ac_cv_lib_ykclient_ykclient_request" = "xyes"; then | |
166 | 166 | AC_MSG_WARN([libykclient missing ykclient_request_process. A later version of libykclient is required.]) |
167 | 167 | else |
168 | 168 | AC_MSG_WARN([ykclient libraries not found. Use --with-ykclient-lib-dir=<path>.]) |