diff options
Diffstat (limited to '')
157 files changed, 19638 insertions, 0 deletions
diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..e35d885 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +_build diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..b26e028 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,72 @@ +FreeRADIUS 3.2.1 Mon 03 Oct 2022 12:00:00 EDT urgency=low + Feature improvements + * Add dictionary.ciena, dictionary.nile, and DHCPv4 dictionaries, + * Add simultaneous-use queries for MS SQL. + * Add radmin command for "stats pool <module-name>" + Which prints out statistics about the connection pools + * Client statistics now shows "conflicts", to count conflicting + packets. + * New optional "lightweight accounting-on/off" strategy. When + refreshing queries.conf you should also add the new nasreload table + and corresponding GRANTs to your DB schema. + * Add TLS-Client-Cert-X509v3-Certificate-Policies, which helps with + Eduroam. Suggested by Stefan Winter. + * Allow auth+acct for TCP sockets, too. + * Add rlm_cache_redis. See raddb/mods-available/cache for details + * Allow radmin to look up home servers by name, too. + * Ensure that dynamic clients don't create loops on duplicates. + Reported by Sam Yee. + * Removed rlm_sqlhpwippool. There was no documentation, no configuration, + and the module was ~15 years old with no one using it. + * Marked rlm_python3 as stable. + * Add sigalgs_list. See raddb/mods-available/eap. Patch from + Boris Lytochkin. + * For rlm_linelog, when opening files in /dev, look at "permissions" to see + whether to open them r/w. + * More flexibility for dynamic home servers. See doc/configuration/dynamic_home_servers.md + and raddb/home_servers/README.md + * Allow setting of application_name for PostgreSQL. See mods-available/sql. + + Bug fixes + * Correct test for open sessions in radacct for MS SQL. + * The linelog module now opens /dev/stdout in "write-only" mode + if the permissions are set to "u+w" (0002). + * Various fixes to rlm_unbound from Nick Porter. + * PEAP now correctly runs Post-Auth-Type Accept + * Create "TLS-Cert-*" for outbound Radsec, instead of TLS-Client-Cert-* + Fixes #4698. See sites-available/tls, and fix_cert_order. + * Minor updates and fixes to CI, Dockerfiles and packaging. + * Fix rlm_python3 build with python >= 3.10. Fixes #4441 + +FreeRADIUS 3.2.0 Thu 21 Apr 2022 12:00:00 EDT urgency=low + Configuration changes + * "correct_escapes" has been removed, and is always set to "true" + internally. Configuration changes may be required if you are + using configurations from before 3.0.5. Other than this + difference, 3.2.x is compatible with 3.0.x, and configurations + from 3.0.x can be simply copied into a system running 3.2.x. + + Feature improvements + * All features from 3.0.x are included in the 3.2.x releases. In addition: + * Add 'reset_day' and '%%r' parameter for rlm_sqlcounter to specify which + day of the month the counter should be reset. + * Partial backport of rlm_json from v4, providing the json_encode xlat. + See mods-available/json for documentation. + * Support for haproxy "PROXY" protocol. + See sites-available/tls, "proxy_protocol" and doc/antora/modules/howto/pages/protocols/proxy/ + * Support for sending CoA-Request and Disconnect-Request packets + in "reverse" down RadSec tunnels. Experimental for now, and + undocumented. + * It is now possible to run a virtual server when saving / loading + TLS cache attributes. See sites-available/tls-cache for + more information. + * Removed the "cram" module. It was undocumented, and used old + and insecure authentication methods. + * Remove the "otp" module. The "otpd" program it needs is no longer available, + and the module has not been usable since at least 2015. + * All features from 3.0.x are included in the 3.2.x releases. + * 3.2.0 requires OpenSSL 1.0.2 or greater. + + Bug fixes + * All bug fixes from 3.0.x are included in the 3.2.x releases. + diff --git a/doc/Makefile.sphinx b/doc/Makefile.sphinx new file mode 100644 index 0000000..235ba9d --- /dev/null +++ b/doc/Makefile.sphinx @@ -0,0 +1,95 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pdf to make standalone PDF files" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pdf: + $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) _build/pdf + @echo + @echo "Build finished. The PDFs are in _build/pdf." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FreeRADIUS.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FreeRADIUS.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..7801c90 --- /dev/null +++ b/doc/README @@ -0,0 +1,181 @@ +1. INTRO + + The FreeRADIUS Server Project is a high performance and highly + configurable multi-protocol policy server, supporting RADIUS, DHCPv4 + and VMPS. It is available under the terms of the GNU GPLv2. + + All code in this server was written for this project. + + +2. INSTALLATION + + See the INSTALL file, in the parent directory. + + +3. CONFIGURATION FILES + + Much of the server documentation is included only in the comments in the + configuration files. Reading the configuration files is REQUIRED to fully + understand how to create complex configurations of the server. + +3a. 'clients.conf' + + Make sure the clients (NAS, switches, access points etc) are set up to + use the host radiusd is running on as authentication and accounting host. + Configure these clients with a "radius secret", which should also be + entered into the client definition in /etc/raddb/clients.conf. + See also the manual page for clients.conf(5). + +3b. 'users' + + Users may be defined in the "users" file (raddb/mods-config/files/authorize). + All entries are processed in the order as they appear in the file. + If an entry matches the username, radiusd will stop scanning the users + file (unless the attribute "Fall-Through = Yes" is set). + + You can uses spaces in usernames by escaping them with \ or by using + quotes. For example, "joe user" or joe\ user. + + The 'users' file is read by the "rlm_files" module. + +3c. NEW RADIUS ATTRIBUTES (to be used in the USERS file). + + Name Type Descr. + ---- ---- ------ + Simultaneous-Use integer Max. number of concurrent logins + Fall-Through integer Yes/No + Login-Time string Defines when user may login. + Current-Time string Allows you to perform time-based + checks when a request is received. + + Login-Time defines the time span a user may login to the system. The + format of a so-called time string is like the format used by UUCP. + A time string may be a list of simple time strings separated by "|" or ",". + + Each simple time string must begin with a day definition. That can be just + one day, multiple days, or a range of days separated by a hyphen. A + day is Mo, Tu, We, Th, Fr, Sa or Su, or Wk for Mo-Fr. "Any" or "Al" + means all days. + + After that a range of hours follows in hhmm-hhmm format. + + For example, "Wk2305-0855,Sa,Su2305-1655". + + radiusd calculates the number of seconds left in the time span, and + sets the Session-Timeout to that number of seconds. So if someones + Login-Time is "Al0800-1800" and she logs in at 17:30, Session-Timeout + is set to 1800 seconds so that she is kicked off at 18:00. + + +4. LOG FILES + +4a. /var/log/radius/radutmp + + In this file the currently logged in users are held. The program "radwho" + reads this file and gives you a summary. Rogue sessions can be deleted + from this file with the "radzap" program. + +4b. /var/log/radius/radwtmp + + This file is "wtmp" compatible and keeps a history of all radius logins/ + logouts. This file can be read with the "last" program, and other Unix + accounting programs (such as "ac" and "sac") can be used to produce a + summary. + +4c. /var/log/radius/radius.log + + All RADIUS informational, diagnostic and error messages are logged in + this file, including all login attempts. + +4d. /var/log/radius/radacct/<client_ip>/detail + + This is the original radius logfile, as written by all the Livingston + radius servers. It's only created if the directory + /var/log/radius/radacct exists. + + For more configuration options on the detail file please see + raddb/mods-available/detail as it expands upon this greatly. + + +5. MORE INFO, SUPPORT + + The latest version of FreeRADIUS is always available from + the git repository hosted on GitHub at + + https://github.com/FreeRADIUS/freeradius-server + + or see + + http://freeradius.org/git/ + + for more information. + + There are two mailing lists for users and developers. General + user, administrator and configuration issues should be discussed + on the users list at: + + http://lists.freeradius.org/mailman/listinfo/freeradius-users + + When asking for help on the users list, be sure the include a + detailed and clear description of the problem, together with + full debug output from FreeRADIUS, obtained by running + + radiusd -X + + Developers only discussion is to be had on the devel list: + + http://lists.freeradius.org/mailman/listinfo/freeradius-devel + + Please do not raise general configuration issues here. + + +6. OTHER INFORMATION + + The files in other directories are: + + debian/ Files to build Debian Linux packages. + + doc/ Various snippets of documentation + doc/rfc/ Copies of the RFC's. If you have Perl, do a 'make' in + that directory, and look at the HTML output. + + man/ Unix Manual pages for the server, configuration files, + and associated utilities. + + mibs/ SNMP Mibs for the server. + + raddb/ Default configuration files for the server. + + redhat/ Files to build RedHat RPM packages. + + scripts/ Sample scripts for startup and maintenance. + + share/ Attribute dictionaries. + + src/ Source code + src/main source code for the daemon and associated utilities + src/lib source code for the RADIUS library + src/include header files + src/modules dynamic plug-in modules + src/tests test harness used by "make test" + + suse/ Files to build SuSE RPM packages. + + + If you have ANY problems, concerns, or surprises when running + the server, then run it in debugging mode, as root, from the + command line: + + # radiusd -X + + It will produce a large number of messages. The answers to many + questions, and the solution to many problems, can usually be found in + these messages. + + For further details, see: + + https://freeradius.org/documentation/ + + and the 'bugs' file, in this directory. + +$Date$ diff --git a/doc/all.mk b/doc/all.mk new file mode 100644 index 0000000..1a88f52 --- /dev/null +++ b/doc/all.mk @@ -0,0 +1,55 @@ +ifneq "$(docdir)" "no" +install: install.doc + +clean: clean.doc + +DOCDIRS := $(patsubst doc/%,$(R)$(docdir)/%,$(filter-out doc/source%,$(shell find doc -type d))) +DOCFILES := $(filter-out %~ %/all.mk %.gitignore doc/rfc/update.sh doc/source/%,$(shell find doc -type f)) +DOCINSTALL := $(patsubst doc/%,$(R)$(docdir)/%,$(DOCFILES)) + +# Create the directories +$(DOCDIRS): + @echo INSTALL $(patsubst $(R)$(docdir)/%,doc/%,$@) + @$(INSTALL) -d -m 755 $@ + +# Files depend on directories (order only). +# We don't care if the directories change. +$(DOCINSTALL): | $(DOCDIRS) + +# Wildcard installation rule +$(R)$(docdir)/%: doc/% | $(dir $@) + @echo INSTALL $< + @$(INSTALL) -m 644 $< $@ + +install.doc: $(DOCINSTALL) + +.PHONY: clean.doc +clean.doc: + @rm -rf doc/*~ doc/rfc/*~ build/docsite + +# +# Deal with these later +# +DOCRST := $(wildcard *.rst) +%.html: %.rst + @rst2html.py $^ > $@ + +.PHONY: html +html: $(DOCRST:.rst=.html) + +# +# antora rebuilds the entire documentation site on each run +# so we need to pick a single file to compare dependency +# timestamps against. +# +# we use sitemap.xml as it'll be regenerated on every antora +# run. +# +build/docsite/sitemap.xml: $(ADOC_FILES) + @echo ANTORA site.yml + ${Q}$(ANTORA) $(ANTORA_FLAGS) site.yml + + +docsite: build/docsite/sitemap.xml + +endif diff --git a/doc/antora/antora.yml b/doc/antora/antora.yml new file mode 100644 index 0000000..928b95c --- /dev/null +++ b/doc/antora/antora.yml @@ -0,0 +1,18 @@ +# +# Metadata for the freeradius-server component +# Examples of other components are the PAM module, +# apache module, and the client library. +# +name: freeradius-server +title: The FreeRADIUS Server +version: '3.2.1' +start_page: ROOT:index.adoc +nav: +- modules/ROOT/nav.adoc +- modules/installation/nav.adoc +- modules/concepts/nav.adoc +- modules/howto/nav.adoc +- modules/tutorials/nav.adoc +- modules/unlang/nav.adoc +- modules/developers/nav.adoc +- modules/raddb/nav.adoc diff --git a/doc/antora/modules/ROOT/assets/images/favicon.png b/doc/antora/modules/ROOT/assets/images/favicon.png Binary files differnew file mode 100644 index 0000000..8c71104 --- /dev/null +++ b/doc/antora/modules/ROOT/assets/images/favicon.png diff --git a/doc/antora/modules/ROOT/assets/images/favicon.svg b/doc/antora/modules/ROOT/assets/images/favicon.svg new file mode 100644 index 0000000..7476355 --- /dev/null +++ b/doc/antora/modules/ROOT/assets/images/favicon.svg @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 160 160" style="enable-background:new 0 0 160 160;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:none;stroke:#FFD62B;stroke-width:3;stroke-miterlimit:10;} + .st1{fill:#B0C3C6;} + .st2{fill:none;stroke:#DEE7E8;stroke-miterlimit:10;} + .st3{fill:#00A6E2;} + .st4{fill:none;stroke:#B0C3C6;stroke-width:2;stroke-miterlimit:10;} + .st5{fill:#666666;} + .st6{fill:none;stroke:#B0C3C6;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;} + .st7{fill:#00C9ED;} + .st8{fill:#FFFFFF;stroke:#B0C3C6;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;} + .st9{fill:#303030;} + .st10{opacity:0.4;fill:#F6F6F6;} + .st11{fill:none;stroke:#999999;stroke-width:2;stroke-miterlimit:10;} + .st12{fill:#999999;} + .st13{fill:#FFFFFF;} + .st14{clip-path:url(#SVGID_2_);fill:#2F3537;} + .st15{opacity:0.3;fill:none;stroke:#9FB1B3;stroke-width:2;stroke-miterlimit:10;} + .st16{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;} + .st17{fill:#FFFFFF;stroke:#FFFFFF;stroke-miterlimit:10;} + .st18{fill:none;stroke:#303030;stroke-miterlimit:10;} + .st19{opacity:0.8;fill:#B0C3C6;} + .st20{opacity:0.7;} + .st21{opacity:0.8;clip-path:url(#SVGID_4_);fill:#00A6E2;} + .st22{opacity:0.8;fill:#00A6E2;} + .st23{opacity:0.8;clip-path:url(#SVGID_6_);fill:#00A6E2;} + .st24{clip-path:url(#SVGID_8_);} + .st25{clip-path:url(#SVGID_10_);} + .st26{fill:none;stroke:#B0C3C6;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:10;} + .st27{opacity:0.3;fill:none;stroke:#9FB1B3;stroke-width:3;stroke-miterlimit:10;} + .st28{fill:#FFFFFF;stroke:#B0C3C6;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:10;} + .st29{clip-path:url(#SVGID_12_);fill:#2F3537;} + .st30{clip-path:url(#SVGID_14_);fill:#B0C3C6;} + .st31{fill:#33B8E8;} + .st32{fill:#238DB4;} + .st33{fill:#E2E7E8;} + .st34{clip-path:url(#SVGID_16_);} + .st35{fill:#FFFFFF;stroke:#B0C3C6;stroke-width:2;stroke-miterlimit:10;} + .st36{fill:#B4CBCE;} + .st37{fill:#003147;} + .st38{fill:#FFD62B;} + .st39{fill:#00B78E;} + .st40{fill:#FF7824;} + .st41{fill:#FF3223;} + .st42{fill:#7955DF;} + .st43{fill:none;stroke:#FF3223;stroke-width:2;stroke-miterlimit:10;} + .st44{fill:none;stroke:#00A6E2;stroke-width:2;stroke-miterlimit:10;} + .st45{clip-path:url(#SVGID_18_);fill:#303030;} + .st46{fill:#F5C81F;} + .st47{fill:#F49F90;} + .st48{fill:#F3EEDE;} + .st49{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;} + .st50{fill:#00131F;} + .st51{clip-path:url(#SVGID_20_);fill:#303030;} + .st52{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;} + .st53{clip-path:url(#SVGID_22_);fill:#303030;} + .st54{clip-path:url(#SVGID_24_);fill:#303030;} +</style> +<path class="st0" d="M72.3,25.6c0,0-2.3-3.2-6-2.3"/> +<g> + <polygon class="st50" points="79.2,73 20.3,37.9 86.2,19.3 145.1,54.4 "/> + <g> + <g> + <g> + <g> + <path class="st3" d="M126.2,113.6c-4.4,0-8.2-3-9.3-7.1c2.8,1,5.7,1.6,8.8,1.6c4.4,0,7.9-3.5,7.9-7.9c0-4.4-3.5-7.9-7.9-7.9 + c-5.3,0-9.9-4.3-9.9-9.6c0-0.7,0-2.1,0-2.1v-6.1c0-19.4-15.7-35.2-35.2-35.2c-19.4,0-35.2,15.7-35.2,35.2v6.1c0,0,0,1.3,0,2.1 + c0,5.3-4.6,9.6-9.9,9.6c-4.4,0-7.9,3.5-7.9,7.9c0,4.4,3.5,7.9,7.9,7.9c3.5,0,6.8-0.7,9.8-2c-1,4.3-4.8,7.5-9.4,7.5 + c-4.4,0-7.9,3.5-7.9,7.9c0,4.4,3.5,7.9,7.9,7.9c6.9,0,13.2-2.8,17.8-7.3v10.4c0,4.4,3.5,7.9,7.9,7.9c4.4,0,7.9-3.5,7.9-7.9 + v-14.8h3.1v18.7c0,4.4,3.5,7.9,7.9,7.9c4.4,0,7.9-3.5,7.9-7.9v-18.7h3.1v14.8c0,4.4,3.5,7.9,7.9,7.9c4.4,0,7.9-3.5,7.9-7.9 + v-11.4c4.7,5.1,11.3,8.2,18.7,8.2c4.4,0,7.9-3.5,7.9-7.9C134.1,117.1,130.5,113.6,126.2,113.6z"/> + <g> + <circle class="st13" cx="80" cy="76.9" r="17.5"/> + <g> + <defs> + <circle id="SVGID_19_" cx="80" cy="76.9" r="17.5"/> + </defs> + <use xlink:href="#SVGID_19_" style="overflow:visible;fill:#FFFFFF;"/> + <clipPath id="SVGID_2_"> + <use xlink:href="#SVGID_19_" style="overflow:visible;"/> + </clipPath> + <path style="clip-path:url(#SVGID_2_);fill:#303030;" d="M73.3,85.5c-6.7,0-12.2-5.5-12.2-12.2c0-6.7,5.5-12.2,12.2-12.2 + s12.2,5.5,12.2,12.2C85.5,80,80.1,85.5,73.3,85.5z"/> + </g> + </g> + </g> + </g> + </g> + </g> + <g> + <path class="st50" d="M46,65.8c0-19.1,15.5-29.7,34.6-29.7s34.6,10.6,34.6,29.7c0,0-9.6-9.8-34.2-9.8S46,65.8,46,65.8z"/> + </g> + <g> + <path class="st0" d="M66.3,23.3c0,0-10.7,2.8-10.2,9.7v20.8"/> + <line class="st0" x1="56" y1="53.7" x2="59.3" y2="66"/> + <line class="st0" x1="56" y1="53.7" x2="54" y2="64.7"/> + <line class="st0" x1="56" y1="53.7" x2="62" y2="59.2"/> + <line class="st0" x1="56" y1="53.7" x2="50.8" y2="60.4"/> + </g> +</g> +</svg> diff --git a/doc/antora/modules/ROOT/assets/images/networkradius.png b/doc/antora/modules/ROOT/assets/images/networkradius.png Binary files differnew file mode 100644 index 0000000..bf1ea80 --- /dev/null +++ b/doc/antora/modules/ROOT/assets/images/networkradius.png diff --git a/doc/antora/modules/ROOT/nav.adoc b/doc/antora/modules/ROOT/nav.adoc new file mode 100644 index 0000000..3d92412 --- /dev/null +++ b/doc/antora/modules/ROOT/nav.adoc @@ -0,0 +1 @@ +* xref:index.adoc[Introduction] diff --git a/doc/antora/modules/ROOT/pages/directories.adoc b/doc/antora/modules/ROOT/pages/directories.adoc new file mode 100644 index 0000000..9b16249 --- /dev/null +++ b/doc/antora/modules/ROOT/pages/directories.adoc @@ -0,0 +1,69 @@ += Directories + +The directories in the server source are laid out ad follows: + +== Documentation + +[width="100%",cols="50%,50%",options="header",] +|=== +| Directory | Description +| `doc/` | Various snippets of documentation. +| `doc/introduction/` | Concepts and introduction to FreeRADIUS. +| `doc/raddb/` | HTML versions of the configuration files. +| `doc/developers/` | Developer documentation for internal APIs +| `doc/unlang/` | The unlang processing language. +| `doc/upgrade/` | How to upgrade from version 3 to version 4. +| `doc/rfc/` | Copies of the RFC’s. If you have Perl, do a `make` in + that directory, and look at the HTML output. +| `doc/antora/` | Metadata and documentation source files to build + an Antora based documentation site. +| `doc/doxygen/` | Files to build a Doxygen site from the source code. +| `man/` | Unix Manual pages for the server, configuration files, + and associated utilities. +|=== + +== Utility + +[cols=",",options="header",] +|=== +|Directory | Description +| `mibs/` | SNMP Mibs for the server. +| `scripts/` | Sample scripts for startup and maintenance. +|=== + +== Configuration + +[width="100%",cols="50%,50%",options="header",] +|=== +| Directory | Description +| `raddb/` | Sample configuration files for the server. +| `raddb/mods-available` | Module configuration files. +| `raddb/mods-enabled` | Directory containing symlinks to `raddb/mods-available`. + Controls which modules are enabled. +| `raddb/sites-available` | Virtual servers. +| `raddb/sites-enabled` | Directory containing symlinks to `raddb/sites-available`. + Control which virtual servers are enabled. +|=== + +== Packaging + +[cols=",",options="header",] +|=== +|Directory | Description +| `debian/` | Files to build a `freeradius` Debian Linux package. +| `redhat/` | Additional files for a RedHat Linux system. +| `suse/` | Additional files for a SuSE (UnitedLinux) system. +|=== + +== Source + +[cols=",",options="header",] +|=== +|Directory | Description +| `src/` | Source code. +| `src/bin/` | Source code for the daemon and associated utilities. +| `src/lib/` | Source code for various utility libraries. +| `src/include/` | Header files. +| `src/protocols/` | Dynamic frontend plug-in modules. +| `src/modules/` | Dynamic backend plug-in modules. +|=== diff --git a/doc/antora/modules/ROOT/pages/index.adoc b/doc/antora/modules/ROOT/pages/index.adoc new file mode 100644 index 0000000..e9bc7a0 --- /dev/null +++ b/doc/antora/modules/ROOT/pages/index.adoc @@ -0,0 +1,137 @@ += Introduction + +This is the documentation for FreeRADIUS, version 3. The documentation +is available under the Creative Commons Non-Commercial license, as given +in the `LICENSE` file in this directory. + +FreeRADIUS is a complex piece of software with many configuration +options. However, we have taken great care to make the default +configuration work in most circumstances. The result is that for most +simple systems, it is trivial to install and configure the server. For +those situations, this documentation will serve to answer basic +questions about functionality, configuration, etc. + +For more complex requirements, FreeRADIUS can be difficult to +configure. The reason for this difficulty is that the server can do +almost anything, which means that there are a near-infinite number of +ways to configure it. The question for an administrator, then, is what +piece of the configuration to change, and how to change it. + +This documentation will answer those questions. The FreeRADIUS team has +put substantial effort into writing the documentation for this release. +Everything in the server is fully documented, and there are many +`how-to` guides available. + +The documentation is split into sections by subject area, oganized by +desired outcome. At a high level, the subject areas describe: + +* xref:concepts:index.adoc[Concepts] and introduction for newcomers. +* xref:installation:index.adoc[Installing] and xref:installation:upgrade.adoc[upgrading] FreeRADIUS. +* The syntax of the xref:unlang:index.adoc[unlang] processing language. +* The xref:raddb:index.adoc[configuration files] located in `/etc/raddb/`, or `/etc/freeradius/` +* Various xref:howto:index.adoc[how-to] guides. +* xref:developers:index.adoc[Developer documentation]. + +This organization means that for example, the `ldap` module will have +documention located in multiple places. We feel that organizing the +documentation by desired _goal_ is better than the alternatives. + +Within each section, the documentation is split into small pages, which +are generally no more than a few screens worth of information. We feel +that having multiple small pages with cross-links is more helpful than +having a smaller number of enormous pages. This division ensures that +(for example) the `how-to` guides are split into a series of small +steps, each of which can be performed quickly. + +We hope that this extended documentation will address any lingering +concerns about the quality of the FreeRADIUS documentation. + +== Changes From Earlier Versions + +Administrators who have version 2 and wish to upgrade to version 3 +should read the xref:installation:upgrade.adoc[upgrading] documentation. +That documentation explains the differences between the two versions, and +how an existing configuration can be reproduced in the latest +release. We do _not_ recommend using version 2 configuration files +with version 3. The configuration files are _not_ compatible across a +major version upgrade. + +== Getting Started with FreeRADIUS + +FreeRADIUS can be installed using the pre-built packages available +from http://packages.networkradius.com[Network RADIUS, +window="_blank"]. That page contains packages for all common OS +distributions. New packages are available as soon as a new version +has been released. Packages for older releases are also available for +historical purposes. + +FreeRADIUS can also be installed from the source code. Please see the +xref:installation:index.adoc[installation guide] for instructions. + +WARNING: Many Operating System distributions ship versions of FreeRADIUS +which are years out of date. Those versions may contain bugs which have +been fixed in newer releases. We recommend using the +http://packages.networkradius.com[Network RADIUS, window="_blank"] packages where +possible. + +Administrators who are new to FreeRADIUS should read the +xref:concepts:index.adoc[concepts section] as it describes the concepts behind +FreeRADIUS. It is vital for newcomers to understand these concepts, as the rest +of the documentation assumes familiarity with them. + +A detailed xref:unlang:index.adoc[unlang] reference guide is also available. +This section describes the syntax and functionality of the keywords, +data types, etc. used in the `unlang` processing language. + +All of the xref:raddb:index.adoc[configuration files] are available in +hypertext format. In can often be easier to read the configuration files +in a nicely formatted version, instead of as a fixed-width font in a +text editor. + +For specific problem solving, we recommend the xref:howto:index.adoc[how-to] +guides. These guides give instructions for reaching high-level goals, or +for configuring and testing individual xref:howto:modules/index.adoc[modules]. + +There is also xref:developers:index.adoc[developer documentation]. This section +documents the APIs for developers. Most people can ignore it. + +== Debugging + +If you have ANY problems, concerns, or surprises when running the +server, the the server should be run in debugging mode as root, from the +command line: + +``` +# radiusd -X +``` + +It will produce a large number of messages. The answers to many +questions, and the solution to many problems, can usually be found in +these messages. When run in a terminal window, error messages will be +shown in red text, and warning messages will be shown in yellow text. + +For other use-cases, please look for `ERROR` or `WARNING` in the +debug output. In many cases, those messages describe exactly what is +going wrong, and how to fix it. + +For further details, about the debug output see the +http://wiki.freeradius.org/radiusd-X[radiusd-X, window="_blank"] page on the +http://wiki.freeradius.org[wiki, window="_blank"]. + +== Getting Help + +We also recommend joining the +http://lists.freeradius.org/mailman/listinfo/freeradius-users[mailing +list] in order to ask questions and receive answers. The developers are +not on Stack Overflow, IRC, or other web sites. While the FreeRADIUS +source is available on +https://github.com/FreeRADIUS/freeradius-server/[GitHub, window="_blank"], questions +posted there will not be answered. + +Before posting to the list, please read the +http://wiki.freeradius.org/list-help[list help, window="_blank"] page. That page explains +how to run the server in debugging mode; how to understand the debug +output; and what information to post to the list. + +Commercial support for FreeRADIUS is available from +https://networkradius.com/freeradius-support/[Network RADIUS, window="_blank"]. diff --git a/doc/antora/modules/howto/nav.adoc b/doc/antora/modules/howto/nav.adoc new file mode 100644 index 0000000..351200b --- /dev/null +++ b/doc/antora/modules/howto/nav.adoc @@ -0,0 +1,19 @@ +* xref:index.adoc[Howto Guides] +** Protocols +**** xref:protocols/dhcp/index.adoc[DHCP] +***** xref:protocols/dhcp/prepare.adoc[Preparation] +***** xref:protocols/dhcp/enable.adoc[Enabling the DHCP service] +***** xref:protocols/dhcp/test.adoc[Testing the DHCP service] +***** xref:protocols/dhcp/policy.adoc[Defining the DHCP policy] +****** xref:protocols/dhcp/policy_ippool_creation.adoc[IP pool creation] +****** xref:protocols/dhcp/policy_common_options.adoc[Common options] +****** xref:protocols/dhcp/policy_network_options.adoc[Network options and IP pool selection] +****** xref:protocols/dhcp/policy_subnet_options.adoc[Subnet options] +****** xref:protocols/dhcp/policy_device_options.adoc[Device, class and group options] +****** xref:protocols/dhcp/policy_ippool_access.adoc[IP pool access restriction] +**** xref:protocols/proxy/index.adoc[PROXY Protocol] +***** xref:protocols/proxy/enable_radsec.adoc[Enabling RadSec] +***** xref:protocols/proxy/radsec_client.adoc[Configuring a test RadSec client] +***** xref:protocols/proxy/radsec_with_haproxy.adoc[Proxying RadSec with HAproxy] +***** xref:protocols/proxy/radsec_with_traefik.adoc[Proxying RadSec with Traefik] +***** xref:protocols/proxy/enable_proxy_protocol.adoc[Enabling PROXY Protocol for RadSec] diff --git a/doc/antora/modules/howto/pages/index.adoc b/doc/antora/modules/howto/pages/index.adoc new file mode 100644 index 0000000..47a5146 --- /dev/null +++ b/doc/antora/modules/howto/pages/index.adoc @@ -0,0 +1,17 @@ += Howto Guides + +The documents in this section describe how to perform various common tasks with +FreeRADIUS. They also provide worked examples on using the various modules in +common deployment scenarions. + +If you have a topic you'd like to see included in the list of howtos, contact +the developers on the +link:http://lists.freeradius.org/mailman/listinfo/freeradius-users[User's +mailing list]. + +Some of the documents here started life as pages on +link:http://wiki.freeradius.org[wiki.freeradius.org]. If you've just been +through a particularly arduous service configuration and deployment, and would +like to help your fellow users, then please create a new how to on the wiki. +If it's popular enough, we'll include it in the official documentation for the +next release. diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/enable.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/enable.adoc new file mode 100644 index 0000000..2824bd0 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/enable.adoc @@ -0,0 +1,213 @@ +== Enabling the DHCP service + +A major difference between configuring FreeRADIUS as a DHCP server versus most +other DHCP software such as ISC DHCP is that other software typically uses a +single monolithic configuration file whereas FreeRADIUS has a collection of +configuration files. This reflects the modularity of FreeRADIUS; attempting to +put the entire configuration in a single file would result in a very difficult +to read configuration. + +The root of the FreeRADIUS configuration may be in a different location on the +filesystem depending on how FreeRADIUS has been installed. This directory will +be referred to as `<raddb>` below. The sample configuration files are well +commented describing what each configuration option does. + +FreeRADIUS compiled from source will default to `/usr/local/etc/raddb`. +Pre-built packages will default to either `/etc/raddb` or +`/etc/freeradius`. + + +=== Enable the DHCP virtual server + +The FreeRADIUS configuration separates each network service that it provides +into "virtual servers". A number of sample virtual server definitions are +provided in `<raddb>/sites-available`, one of which is the sample +configuration for a DHCP service. + +Sites may be added to the working configuration by either creating a symlink to +them or copying them to `<conf>/sites-enabled` depending on how you wish to +manage future upgrades. + +[TIP] +==== +As with other package-managed configuration files, package upgrades will not +automatically replace files that you have edited but you will need to resolve +any local differences. Creating copies avoids the need to resolve conflicts +during a package upgrade. +==== + +Add the DHCP virtual server to the active configuration: + +[source,shell] +---- +cd <raddb>/sites-enabled +ln -s ../sites-available/dhcp . +---- + +or: + +[source,shell] +---- +cd <raddb>/sites-enabled +cp ../sites-available/dhcp . +---- + +The sample configuration has been set up in such a way that it is initially +safe. It will not actually take over live DHCP serving on the network when it +is simply enabled until it is configured to do so. Rather is set up for testing +prior to going live. + +The virtual server begins with a `listen` section. In this section your need to +modify the following configuration items: + +`ipaddr`:: The IP address to listen on. +`src_ipaddr`:: The source IP for unicast packets. +`port`:: The port to listen on. Setting this to `67` will make the DHCP service live on the network. +`interface`:: The network interface to listen on. +`broadcast`:: Allow broadcast packets. For most live systems this will need to be set to `yes`. + +Below the `listen` section, there are sections that define how to respond to +each of the DHCP packet types. Most installations will require that you review +the settings for `DHCP-Discover` and `DHCP-Request`. + +Their contents contain directives in the FreeRADIUS policy language, "unlang". +Many examples are provided which have been carefully described. + + +=== Enable SQL and IP pool modules + +FreeRADIUS has many modules to support different aspects of the functionality +required for the network protocols it can process. The two of most significance +for DHCP are `dhcp_sql` and `dhcp_sqlippool`. As with virtual servers, a +number of example module configurations are available in +`<raddb>/mods-available`. +These should be symlinked or copied into `<raddb>/mods-enabled` in order to +enable them. + + +==== Configure the `dhcp_sql` module + +Add the `dhcp_sql` module to the active configuration: + +[source,shell] +---- +cd <raddb>/mods-enabled +ln -s ../mods-available/dhcp_sql . +---- + +or: + +[source,shell] +---- +cd <raddb>/mods-enabled +cp ../mods-available/dhcp_sql . +---- + +The `dhcp_sql` module should be configured with the connection parameters for +whichever database is to be used. The key configuration items are: + +`dialect`:: Which SQL dialect is in use. +`driver`:: Which driver to use to access the database. For most databases this + is `rlm_sql_<dialect>`, however Microsoft SQL Server has a choice of + drivers. + +Then, there are configuration options that are unique to each database, +including connection details. For most databases these are: + +`server`:: The host name or IP address of the database server. +`port`:: The port to connect to the database server on. +`login`:: The user name used to connect to the database. +`password`:: The password for authenticating to the database. +`radius_db`:: The name of the database. + +[NOTE] +==== +SQLite does not use these connection options, rather the `filename` +option within the `sqlite` section is used to determine where the database +will be stored. +==== + + +==== Configure the `dhcp_sqlippool` module + +Add the `dhcp_sqlippool` module to the active configuration: + +[source,shell] +---- +cd <raddb>/mods-enabled +ln -s ../mods-available/dhcp_sqlippool . +---- + +or + +[source,shell] +---- +cd <raddb>/mods-enabled +cp ../mods-available/dhcp_sqlippool . +---- + +The `dhcp_sqlippool` module must be configured. The key configuration +items are: + +`dialect`:: Set this to the same SQL dialect as in the `sql` module. +`offer_duration`:: How long an IP is offered to the client in a DHCP OFFER. +`lease_duration`:: How long an IP is leased to the client in a DHCP ACK. + + +=== Provision the database + +You should provision your database by creating a user for FreeRADIUS (matching +the configuration that you have previously provided) and then loading the +schema. The procedure for doing this will vary according to the database +server. + +The schema, stored procedure definition and any additional setup scripts for +your database are in `<raddb>/mods-config/sql/ippool-dhcp/{dialect}/`. + +=== Test FreeRADIUS startup + +Once you have provisioned your schema, created a user account and granted +access to the user, you should be able to start FreeRADIUS. + +If FreeRADIUS has been configured correctly then the output of `ss` will +contain a line showing that FreeRADIUS is listening for DHCP packets on the +designated interface on port 67: + +.Example of FreeRADIUS listening on `<interface>` for DHCP packets +================================================================== + # ss -lunp + Netid Recv-Q Send-Q Local Address:Port ... + udp 0 0 0.0.0.0%<interface>:67 ... users:(("radiusd",...)) +================================================================== + +Note that if the database is inaccessible then FreeRADIUS will normally refuse +to start. + +The FreeRADIUS wiki contains extensive information about debugging FreeRADIUS +startup issues that we do not repeat in any detail here. + +Essentially, stop your init system from repeatedly trying to launch FreeRADIUS: + +[source,shell] +---- +service radiusd stop +---- + +Then start FreeRADIUS manually in debug mode: + +[source,shell] +---- +radiusd -X +---- + +Carefully read the output since this will tell you why FreeRADIUS was unable to +start. + +Once you have fixed the issue start FreeRADIUS as normal: + +[source,shell] +---- +service radiusd start +---- + +Now xref:protocols/dhcp/test.adoc[test the DHCP service] to ensure that it is responding to requests. diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/index.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/index.adoc new file mode 100644 index 0000000..fde2202 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/index.adoc @@ -0,0 +1,35 @@ += FreeRADIUS DHCP server + +This guide describes how FreeRADIUS can be used in place of ISC DHCP or ISC Kea +to provide a significantly more performant and, above all, more flexible DHCP +server. + +This guide provides a suggested configuration that should be somewhat familiar +to anyone who has previously implemented DHCP using the most frequently used +features of other DHCP server software. + +The modular design of FreeRADIUS means that there is no one "right" way to +implement the DHCP service. FreeRADIUS allows you to put together a "mix and +match" approach. + +For example you can manage the leases in an SQL database. You might then hard +code certain DHCP reply parameters within configuration and then look up +additional parameters using a datastore such as: + + * a local file such as a structured text file or an SQLite database + * an organisational LDAP directory + * an SQL or "no SQL" database + * a remote endpoint such as a RESTful HTTP API + +The policy language and modular configuration of FreeRADIUS is sufficiently +powerful and that almost any aspect of the server's behaviour can be customised +to implement even the most sophisticated DHCP configurations. + +== Sections in this guide + +This guide is organised into four parts that should be read in order: + +1. xref:protocols/dhcp/prepare.adoc[Preparation] +2. xref:protocols/dhcp/enable.adoc[Enabling the DHCP service] +3. xref:protocols/dhcp/test.adoc[Testing the DHCP service] +4. xref:protocols/dhcp/policy.adoc[Defining the DHCP policy] diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy.adoc new file mode 100644 index 0000000..d8f1bcb --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy.adoc @@ -0,0 +1,14 @@ +== Defining the DHCP policy + +Now that FreeRADIUS is successfully running as a DHCP server it is necessary to +configure a DHCP policy so that it returns correctly formed responses to the DHCP +requests that it receives. + +This involves a number of steps: + + * xref:protocols/dhcp/policy_ippool_creation.adoc[Defining the IP address pools.] + * xref:protocols/dhcp/policy_common_options.adoc[Defining the options that are common to all replies.] + * xref:protocols/dhcp/policy_network_options.adoc[Defining the options for the network from which the request originates and ensuring that IP addresses are allocated from the correct pool.] + * xref:protocols/dhcp/policy_subnet_options.adoc[Defining the options for the subnet to which this issued IP address belongs.] + * xref:protocols/dhcp/policy_device_options.adoc[Defining the device, class and group based options specific to the device.] + * xref:protocols/dhcp/policy_ippool_access.adoc[Using device properties to restrict access to certain pools.] diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy_common_options.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy_common_options.adoc new file mode 100644 index 0000000..949868d --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy_common_options.adoc @@ -0,0 +1,80 @@ +== Configure common reply options + +FreeRADIUS includes a powerful xref:unlang/index.adoc[policy language] called +"unlang". + +Statements in unlang may be used to call further policies, update attribute +lists and invoke modules. There are also control flow statements (if, +switch, etc.) typical of most imperative languages. + +FreeRADIUS has a number attribute lists that it maintains as it processes +packets within the virtual server sections. Most relevant to DHCP are +`request`, `control` and `reply`. + +The DHCP options from the current request packet are provided in the +`request` list. This includes fixed DHCP parameters such as +`DHCP-Client-Hardware-Address`, optional parameters such as +`DHCP-Requested-IP-Address`, and parameters synthesised by FreeRADIUS such as +`DHCP-Message-Type` and `DHCP-Network-Subnet`. + +DHCP options can be set by updating their value in the `reply` list. This +forms the basis of the packet returned to the client. + +In the default DHCP server configuration, a "policy" (akin to a subroutine) is +used to set common options for reply packets. The policy is found in +`<raddb>/policy.d/dhcp`. + +Look at the contents of the `dhcp_common` section and set any global options +applicable to all clients in this policy. + +[source,unlang] +---- +dhcp_common { + update reply { + &DHCP-Domain-Name-Server := 8.8.8.8 + &DHCP-Domain-Name-Server += 8.8.4.4 + &DHCP-Subnet-Mask := 255.255.255.0 + &DHCP-Router-Address := 192.0.2.1 + ... + } +} +---- + +Note, FreeRADIUS has four main operators for assigning values to attributes: + +`=`:: Add the attribute to the list, if and only if an attribute of the same + name is not already present in that list. +`:=`:: Add the attribute to the list. If any attribute of the same name is + already present in that list it is replaced with the new one. +`+=`:: Add the attribute to the tail of the list, even if attributes of the + same name are already present in the list. +`^=`:: Add the attribute to the head of the list, even if attributes of the + same name are already present in the list. + +These operators allow for attributes to be set to default values and then +overwritten, e.g. setting a default lease time, but then overwriting it for +a particular group of clients. + +Attributes in the `control` list are not returned in the DHCP reply packets +but instead govern aspects of server's behaviour. + +To use an SQL backend for either static or dynamic IP allocation, un-comment +the block: + +[source,unlang] +---- +update control { + &Pool-Name := "local" +} +dhcp_sqlippool +---- + +The `Pool-Name` control attribute is used in looking up addresses in the +database. The line containing `dhcp_sqlippool` is a call to invoke an +instance of a module with that name. This module is responsible for assigning a +free IP address into the `DHCP-Your-IP-Address` reply attribute from the pool +identified by `Pool-Name`. + +Here `Pool-Name` is being set to a constant value (`local`) indicating +that a single pool is to be used. If you have multiple pools, then replace this +`update` block with logic to map clients to the correct pool, as described below. diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy_device_options.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy_device_options.adoc new file mode 100644 index 0000000..05845ea --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy_device_options.adoc @@ -0,0 +1,310 @@ +== Configure "device", "class" and "group" options + +Beyond the global, network and subnet options already described, most sites +will have a number of group or class based options, and have a requirement for +setting reply parameters against individual devices. + +In general, FreeRADIUS does not differentiate between "classes" (memberships +defined by some attribute of the DHCP request) and "groups" (memberships +defined by some manually aggregation related devices, typically based on lists +of MAC address). + +The sample DHCP configuration provided with FreeRADIUS makes use of an internal +attribute `DHCP-Group-Name` to support the setting of different options for +different groups of devices. + +In general the groups to which a device belongs is determined during the +processing of a request and these are added as instances of the +`DHCP-Group-Name` attribute. This may be by performing a test on one or more +request parameters (akin to a "class"), hash-based lookup of up all of part of +an attribute in a local list (akin to a "subclass"), or doing the same using a +remote datastore (SQL, LDAP, REST API, etc). + +FreeRADIUS can then iterate over `DHCP-Group-Name` to set group-specific +options. + +We describe some of these options in more detail. + +=== Directly in Policy + +Simple class options can be written directly into policy. This is most +suited to those options that rarely change and are based on attributes in the +request such as the `User-Class`. + +Consider the ISC DHCP configuration snippet: + +[source,iscdhcp] +---- +filename "undionly.kpxe"; +class "pxeclient" { + match option substring(user-class,0,4); +} +subclass "pxeclient" "iPXE" { + filename "http://my.web.server/boot_script.php"; +} +---- + +Or the equivalent Kea configuration: + +[source,isckea] +---- +"Dhcp4": { + "option-data": [ + { "name": "boot-file-name", "data": "undionly.kpxe" } + ], + "client-classes": [ + { + "name": "pxeclient", + "test": "substring(option[77],0,4) == 'iPXE'", + "option-data": [ + { + "name": "boot-file-name", + "data": "http://my.web.server/boot_script.php" + } + ] + } + ] + ... +} +---- + +These define the "filename" DHCP option differently based on whether or not the +supplied "user-class" option begins with "iPXE". + +FreeRADIUS provides multiple ways for this to be configured. + +For example, the following "unlang" policy implements the class options defined +above: + +[source,unlang] +---- +if (&DHCP-User-Class && "%{substring:&DHCP-User-Class 0 4}" == "iPXE") { + update reply { + &DHCP-Boot-Filename := "http://my.web.server/boot_script.php" + } +} else { + update reply { + &DHCP-Boot-Filename := "undionly.kpxe" + } +} +---- + +Policy-based configuration of DHCP options is also useful for complex matching. +For example, the following Unlang sets the DHCP-Boot-Filename parameter based +on the request's DHCP-Client-Identifier using regular expression captures, +provided that it matches the given format: + +[source,unlang] +---- +if (&DHCP-Client-Identifier && \ + "%{string:DHCP-Client-Identifier}" =~ /^RAS([0-9])-site([A-Z])$/) { + update reply { + &DHCP-Boot-Filename := "rasboot-%{1}-%{2}.kpxe" + } +} +---- + +=== In Text Files + +The `files` module that has already been described for global, network and +subnet options can also be used to apply options to groups of clients. + +Firstly we must defined a mapping from a set of clients clients to their +respective groups. One option for this is to use the `passwd` module, for +which a sample configuration is included. + +Firstly symlink or copy the module configuration +`<raddb>/mods-available/dhcp_passwd` into `<raddb>/mods-enabled/`. The +suggested configuration expects the group membership file to be in +`<raddb>/mods-config/files/dhcp_groups` and take the form of: + +[source,config] +---- +<group1 name>|<hardware address>,<hardware address>,<hardware address> +<group2 name>|<hardware address>,<hardware address> +---- + +i.e. one line for each group starting with the group name followed by a pipe +character and then a comma-separated list of hardware addresses. + +The `allow_multiple_keys` option allows for a host to be a member of +more than one group. + +Sample configuration for looking up group options is contained in +`<raddb>/policy.d/dhcp` in the `dhcp_group_options` policy and in +`<raddb>/mods-available/dhcp_files` as the `dhcp_set_group_options` instance. + +The same data file `<raddb>/mods-config/files/dhcp` is used to lookup +group options as was used for global and network options. In this instance, +add entries with the group name as the key such as: + +[source,config] +---- +group1 + DHCP-Log-Server := 10.10.0.100, + DHCP-LPR-Server := 10.10.0.200 + +group2 + DHCP-LPR-Server := 192.168.20.200 +---- + +=== In the SQL Database + +Policy and files are both read during startup and editing them while +FreeRADIUS is running will not result in any changes in behaviour. If +you require regular changes to DHCP options, then storing them in +an SQL database provides greater flexibility since the queries will be run in +response to each DHCP packet rather than requiring the server to be restarted. + +DHCP reply options for devices (including network-specific options) can be +fetched from SQL using an arbitrary lookup key. This can be performed multiple +times as necessary using different contexts, for example to first set +subnet-specific options and then to set group-specific options. + +The default schema contains three tables to support this: + +"dhcpreply" contains reply options for a given identifier (e.g. MAC Address): + +.dhcpreply table +|=== +|Identifier |Attribute |Op |Value |Context + +|`02:01:aa:bb:cc:dd` |`DHCP-Log-Server` |`:=` |`192.0.2.10` |`by-mac` +|`02:01:aa:bb:cc:dd` |`DHCP-LPR-Server` |`:=` |`192.0.2.11` |`by-mac` +|`02:01:aa:bb:cc:dd` |`Fall-Through` |`:=` |`Yes` |`by-mac` +|=== + +"dhcpgroup" maps identifiers to a group of options that can be shared: + +.dhcpgroup table +|=== +|Identifier |GroupName |Priority |Context + +|`02:01:aa:bb:cc:dd` |`salesdept` |`10` |`by-mac` +|=== + +"dhcpgroupreply" contains reply options for each group: + +.dhcpgroupreply table +|=== +|GroupName |Attribute |Op |Value |Context + +|`salesdept` |`DHCP-NTP-Servers` |`:=` |`192.0.2.20` |`by-mac` +|`salesdept` |`DHCP-Log-Server` |`+=` |`192.0.2.21` |`by-mac` +|`salesdept` |`DHCP-LPR-Server` |`^=` |`192.0.2.22` |`by-mac` +|=== + +Within the context of assigning options directly to devices, as well as to +manually-curated groups of devices keyed by their MAC address: + + - Place device-specific options in the "dhcpreply" table. + - Add `Fall-Through := Yes` to the options in the "dhcpreply" table in order + to trigger group lookups, which are disabled by default. + - Place entries in the "dhcpgroup" `identifier = <MAC-Address>, groupname = <group>, priority = + <priority>` in the "dhcpgroup" table to map a device to its groups by + priority. + - Place the grouped options in the "dhcpgroupreply" table. + - For each of the above, set `Context` to something by which the option + lookup is referred to in the policy, for example `Context = 'by-mac'`. + +For the above example you would add the following to the DHCP virtual server to +perform reply option lookup using the device's MAC address against the `by-mac` +context: + +[source,unlang] +---- +update control { + &DHCP-SQL-Option-Context := "by-mac" + &DHCP-SQL-Option-Identifier := &request:DHCP-Client-Hardware-Address +} +dhcp_sql.authorize +---- + +In the above, the DHCP reply options would be assigned to a device with MAC +address 02:01:aa:bb:cc:dd as follows: + + - Firstly, the `DHCP-Log-Server` option would be set to `192.0.2.10` and the + `DHCP-LPR-Server` option set to `192.0.2.11`. + - `Fall-Through` is set, so the group mapping is then queried which + determines that the device belongs to a single `salesdept` group. + - Finally, the options for the `salesdept` group are now merged, setting a + `DHCP-NTP-Servers` option to `192.0.2.20`, appending an additional + `DHCP-Log-Server` option set to `192.0.2.21`, and prepending an additional + `DHCP-LPR-Server` option set to `192.0.2.22`. + +If instead you wanted to perform a "subclass" lookup based on the first three +octets of the device's MAC address then with tables containing the following +sample data you could invoke an SQL lookup as shown: + +."dhcpreply" table: +|=== +|Identifier |Attribute |Op |Value |Context + +|`000393` |`Fall-Through` |`:=` |`Yes` |`class-vendor` +|`000a27` |`Fall-Through` |`:=` |`Yes` |`class-vendor` +|`f40304` |`Fall-Through` |`:=` |`Yes` |`class-vendor` +|=== + +."dhcpgroup" table: +|=== +|Identifier |GroupName |Priority |Context + +|`000393` |`apple` |`10` |`class-vendor` +|`000a27` |`apple` |`10` |`class-vendor` +|`f40304` |`google` |`10` |`class-vendor` +|=== + +."dhcpgroupreply" table: +|=== +|GroupName |Attribute |Op |Value |Context + +|`apple` |`DHCP-Boot-Filename` |`:=` |`apple.efi` |`class-vendor` +|`google` |`DHCP-Boot-Filename` |`:=` |`google.efi` |`class-vendor` +|=== + + +[source,unlang] +---- +update control { + &DHCP-SQL-Option-Context := "class-vendor" + &DHCP-SQL-Option-Identifier := \ + "%{substring:%{hex:&DHCP-Client-Hardware-Address} 0 6}" +} +dhcp_sql.authorize +---- + +The file `policy.d/dhcp` contains a policy named `dhcp_policy_sql` which +provides further worked examples for different types of option lookups. + +=== Testing "device", "class" and "group" options + +You should now test that any device-related options that you have configured +using the various methods available are applied successfully by generating +packets containing those parameters based upon which the reply options are set. + +For example, to test the iPXE user class example above you might want to +generate a request as follows: + +[source,shell] +---- +cat <<EOF > dhcp-packet-ipxe-boot.txt +DHCP-Message-Type := DHCP-Discover +DHCP-Client-Hardware-Address := 02:01:aa:bb:cc:dd +DHCP-User-Class := "iPXE-class-abc" +EOF +---- + +To which you would expect to see a response such as: + +.Example output from dhcpclient +=============================== + dhcpclient: ... + ---------------------------------------------------------------------- + Waiting for DHCP replies for: 5.000000 + ---------------------------------------------------------------------- + ... + DHCP-Message-Type = DHCP-Offer + DHCP-Your-IP-Address = 1.2.3.4 + DHCP-Boot-Filename := "http://my.web.server/boot_script.php" + ... +=============================== diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy_ippool_access.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy_ippool_access.adoc new file mode 100644 index 0000000..40b8e30 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy_ippool_access.adoc @@ -0,0 +1,54 @@ +== Configure access restrictions for pools + +We can combine what we have learned in the preceeding sections to provide pools +whose access is restricted in some way, for example to a particular class. + +Consider the ISC DHCP configuration snippet: + +[source,iscdhcp] +---- +subnet 10.99.99.0 netmask 255.255.255.0 { + pool { + range 10.99.99.200 10.99.99.250; + allow members of "printers"; + } + option routers 10.99.99.1; +} +---- + +Or the equivalent Kea configuration: + +[source,isckea] +---- +"Dhcp4": { + "subnet4": [{ + "subnet": "10.99.99.0/24", + "pools": [ + { + "pool": "10.99.99.200 - 10.99.99.250", + "client-class": "printers" + } + ], + "option-data": [ + { "name": "routers", "data": "10.10.0.1" } + ] + }], + ... +} +---- + +These define a subnet containing a single pool that is restricted to members of +the "printers" class. (The definition for this class is omitted.) + +In FreeRADIUS, to filter access to this pool entries such as the following +should included in the `<raddb>/mods-config/files/dhcp` configuration file: + +[source,config] +---- +network DHCP-Network-Subnet < 10.99.99.0/24, \ + DHCP-Group-Name == "printers", Pool-Name := "printers-pool" + DHCP-Router-Address := 10.99.99.1 +---- + +Note that any number of additional filters can be added to the initial "check" +line to restrict matches to the network block. diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy_ippool_creation.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy_ippool_creation.adoc new file mode 100644 index 0000000..e976873 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy_ippool_creation.adoc @@ -0,0 +1,112 @@ +=== Determine the IP pool plan + +Except for cases where all IP allocation is performed using a mapping from the +device MAC address to a fixed IP address, the DHCP configuration will involve +the use of one or more IP address pools. + +FreeRADIUS stores all the IP addresses in its pools in whichever database has +been chosen. An instance of the `sqlippools` module is used to manage all pools +within a single table (normally `dhcpippool`). Each row of this table +corresponds to an IP address that is a member of some pool. The pools are +distinguished by name, so the table has a column (`pool_name`) that denotes +this. + +Each pool in this table should be composed of a set of equally valid IP +addresses for the devices that are designated to be members of the pool. + +Firstly, consider the network locations to which distinct ranges of IP +addresses must be allocated and provisionally assign a pool to each. + +Next, consider that many networks support multiple co-existing subnets without +VLAN separation. We will call this a "shared-network" to use the original ISC +DHCP parlance. In Microsoft DHCP contexts this is often referred to as a +"multinet". + +Often in a shared-network the policy has no regard for which of the network's +devices is allocated to which subnet. In this case we must create a single, +combined pool containing all of the IP addresses from each subnet in that +network. Since all addresses in a pool are treated equally this will mean that +any IP address may be allocated to a device that is making a DHCP request from +that network. The appropriate DHCP parameters for the subnet to which the IP +address belongs is determined after allocation. + +There are sometimes shared-networks (or even single subnets) for which IP +addresses belonging to any subnet may be technically suitable for any device, +however some local policy wants to assigning them to a particular subnet, for +example to provide loose segregation between classes of device. In this case we +define multiple pools, one for each range of IP addresses whose devices needs to +be differentiated. + +The choice of pool is ordinarily determined based on the network from which the +request originates using a mapping from Layer 2 networks to the pool name +provided by the user. The indicator for the originating network can be +overridden when this alone is insufficient to implement the required pool +selection policy such as when you need to differentiate the pool's users with +more granularity that their Layer 2 network, such as by considering device +attributes ("class" membership in ISC parlance) or Option 82 circuit data. + + +=== Populate the IP Pools + +By this stage you should have derived a list of pools, the IP address ranges +contained therein, and the means of selecting the pool to use based on the +originating network and/or some additional criteria from the request. + +A helper Perl script is provided with FreeRADIUS that can be used to populate +the pools provide that you are using the default schema. + +[source,shell] +---- +rlm_sqlippool_tool -p <pool_name> -s <range_start> -e <range_end> \ + -t <table_name> (-d <sql_dialect> | -f <raddb_dir> [ -i <instance> ]) \ + [ -c <capacity> ] [ -x <existing_ips_file> ] +---- + +If, for example, you had a range configured in ISC DHCP as: + +[source,iscdhcp] +---- +range 10.0.0.5 10.0.0.199 +---- + +and you are using PostgreSQL as your database, and you wish to refer to this pool +using the name `local`, this could be prepared with: + +[source,shell] +---- +rlm_sqlippool_tool -p local -s 10.0.0.5 -e 10.0.0.199 -t dhcpippool -d postgresql +---- + +If the SQL module of FreeRADIUS is already configured then this can +be referenced so that the tool is able to use the configured connection +parameters to connect to the database and populate the pool: + +[source,shell] +---- +rlm_sqlippool_tool -p local -s 10.0.0.5 -e 10.0.0.199 -t dhcpippool -f /etc/raddb +---- + +For installations that require multiple pools, `rlm_sqlippool_tool` can +be called referencing a YAML file defining the pools. Comments at the +head of `rlm_sqlippool_tool` explain the options in more detail. + +If static leases are required then these should be set up in the database +such that the MAC address of the client should be set as the `pool_key` +against the corresponding address and the `status` column of the row +representing the address set to `static`. A helper perl script, +`rlm_iscfixed2ippool` can be used to read an ISC DHCP config file and produce +SQL to perform these changes or directly update the database: + +[source,shell] +---- +rlm_iscfixed2ippool -c <dhcpd.<raddb> -t <table_name> -k <mac|id> \ + (-d <sql_dialect> | -f <raddb_dir> [-i <instance>]) +---- + +For example, to read /etc/dhcp/dhcpd.conf and populate the configured +FreeRADIUS database, using the mac as the identifier: + +[source,shell] +---- +rlm_iscfixed2ippool -c /etc/dhcp/dhcpd.conf -t dhcpippool -k mac -f /usr/local/etc/raddb +---- diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy_network_options.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy_network_options.adoc new file mode 100644 index 0000000..e2657a8 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy_network_options.adoc @@ -0,0 +1,237 @@ +== Configure network-specific options and IP pool selection + +In an environment where multiple networks (often VLANs) are in use, it is +necessary to identify which network a client belongs to in order to assign an +address from the correct pool. + +Consider the ISC DHCP configuration snippet: + +[source,iscdhcp] +---- +option domain-name "example.org"; + +subnet 10.10.0.0 netmask 255.255.0.0 { + range 10.10.1.10 10.10.10.254; + range 10.10.100.10 10.10.110.254; + option routers 10.10.0.1; + option domain-name-servers 10.10.0.2, 10.10.0.3; + default-lease-time 7200; +} +---- + +Or the equivalent Kea configuration: + +[source,isckea] +---- +"Dhcp4": { + "option-data": [ + { "name": "domain-name", "data": "example.org" } + ], + "subnet4": [{ + "subnet": "10.10.0.0/16", + "pools": [ { "pool": "10.10.1.10 - 10.10.10.254" }, + { "pool": "10.10.100.10 - 10.10.110.254" } + ], + "option-data": [ + { "name": "routers", "data": "10.10.0.1" }, + { "name": "domain-name-servers", "data": "10.10.0.2, 10.10.0.3" } + ], + "valid-lifetime": 7200 + }], + ... +} +---- + +These define a network consisting of a single subnet 10.10.0.0/16 containing two +IP address pools 10.10.1.10 - 10.10.10.254 and 10.10.100.10 - 10.10.110.254. +Requests that are determined to have originated from this network (e.g. because +their `giaddr` belongs within the subnet) will be assigned the specified DHCP +parameters and allocated an address from one of its ranges. + +To provide equivalent functionality, FreeRADIUS must identify the correct DHCP +reply parameters as well as the name of the pool to be used for IP address +assignment, based on the originating network of the request. + +The definition for this pool (the addresses contained within it, corresponding +to the `range` statement in ISC DHCP and Kea) is specified entirely in the +database: It is precisely the rows in the `dhcpippool` table with a particular +`pool_name`. + +[TIP] +==== +As described previously, in FreeRADIUS a pool is a set of IP addresses that are +equally valid with respect to the network policy; therefore, unlike ISC DHCP +and ISC Kea, FreeRADIUS does not differentiate between the two `range`s. +Instead we should have previously populated a single pool containing all of the +IP addresses from both ranges. +==== + +FreeRADIUS derives a request attribute called `DHCP-Network-Subnet` which +honours the standard DHCP process for designating the choice of network, in +order of preference: + + 1. Link Selection Suboption of Option 82 + 2. IPv4 Subnet Selection Option + 3. Gateway IP Address ("giaddr") + 4. Client IP Address ("ciaddr", only set for unicast packets) + +If `DHCP-Network-Subnet` contains an IP address then this should be used as +the basis of choosing a network. When there is no address in this attribute it +can be assumed that the packet has been received from a client on the local +LAN. + +The `files` module in FreeRADIUS provides a simple method to map +`DHCP-Network-Subnet` to the corresponding pool based on its network +membership, setting the appropriate options to return to clients. It can also +set the global options. + +[TIP] +==== +In the case where an instance of the `files` module is used to get global +default parameters, the `dhcp_common` policy becomes redundant so the +statement calling the policy (by name) can be commented out in +`<raddb>/sites-enabled/dhcp`. +==== + +To use the provided example `files` module instance for DHCP, symlink or copy +`<raddb>/mods-available/dhcp_files` into `<raddb>/mods-enabled/` and then +uncomment the calls to `dhcp_network` in `<raddb>/sites-enabled/dhcp`. + +A template configuration file `<raddb>/mods-config/files/dhcp` is also +provided which should be adapted to suit your network topology. + +For the configuration above you may deduce the following configuration, which +has been extended to include an initial default section for requests originating +from directly-connected clients on the local LAN (192.168.20/24): + +[source,config] +---- +network Pool-Name := "local" + DHCP-Domain-Name := "example.org", + DHCP-Subnet-Mask := 255.255.255.0, + DHCP-Router-Address := 192.168.20.1, + DHCP-Domain-Name-Server := 192.168.20.2, + Fall-Through := yes + +network DHCP-Network-Subnet < 10.10.0.0/16, Pool-Name := "remote" + DHCP-Subnet-Mask := 255.0.0.0, + DHCP-Router-Address := 10.10.0.1, + DHCP-Domain-Name-Server := 10.10.0.2, + DHCP-Domain-Name-Server += 10.10.0.3, + DHCP-IP-Address-Lease-Time := 7200 +---- + +Each block in the file starts with a line beginning with the key to be matched. +In this case the keyword of `network` (defined earlier in `dhcp_networks` +configuration) is used for each block, so each of the above blocks is a +candidate during the search. + +There may be further filtering of the candidates in the form of `<Attribute> +<op> <Value>`. In the case of the second block we match the +`DHCP-Network-Subnet` to an enclosing subnet with +`DHCP-Network-Subnet < <subnet>`. Additional filters could be added as +required, comma separated. + +Following the filters on the first line, attributes in the `control` list can +be set using the syntax of `<Attribute> := <Value>`. In this example this is +used to specify the `Pool-Name` for choosing the appropriate IP pool to +allocate an address from. + +Subsequent indented lines are attribute assignments for values in the `reply` +list. Note that, apart from the last line, they are all terminated with a +comma. + +The special option `Fall-Through` determines whether, following a match, +other records are checked for a match. All lookups will match the entry +with a key of `network` and no further filtering, so `Fall-Through` +is set on that record in order that the other records will be tested +to find subnet matches. + +=== Example packet processing + +For our example, we consider a request arriving from a DHCP relay within +10.10.0.0/16. In the absence of any specific DHCP subnet selection options in +the request, the `DHCP-Network-Subnet` attribute is calculated to be the +relay's IP address, say 10.10.0.1. + +The request is matched against the first block, setting an initial pool name to +"local", domain name to "example.org" and setting some additional global +default parameters. By virtue of `Fall-Through` being set, the next block is +considered. + +Since the network identifier is within the specified subnet (i.e. `10.10.0.1 < +10.10.0.0/16`) this second block is matched. This block overrides the pool name +setting it to "remote", overrides some other global defaults and sets the lease +time to 7200 seconds. `Fall-Through` is not set, so we are now done with +deriving the pool name and network options. + +When the `dhcp_sqlippool` module is called during DHCP DISCOVER processing (in +`<raddb>/sites-enabled/dhcp`) the `remote` pool will be used for IP address +allocation. + +The assigned IP address and network parameters will subsequently be returned in +the DHCP reply. + +=== Testing the pool operation and network-specific options + +Before proceeding further, you should test the operation of the IP pools and +ensure that any network-specific reply attributes that you have configured are +correctly set in replies. + +For example, if you have a single, flat pool you should test using sample +packets for devices with different MAC addresses and/or Client Identifiers. + +[source,shell] +---- +cat <<EOF > dhcp-packet-1.txt +DHCP-Message-Type := DHCP-Discover +DHCP-Client-Hardware-Address := 02:01:11:11:11:11 +DHCP-Client-Identifier := device1 +EOF +---- + +[source,shell] +---- +cat <<EOF > dhcp-packet-2.txt +DHCP-Message-Type := DHCP-Discover +DHCP-Client-Hardware-Address := 02:01:22:22:22:22 +DHCP-Client-Identifier := device2 +EOF +---- + +Generate these packets as show previously using the dhcpclient tool and look +for `DHCP-Your-IP-Address` in the DHCP responses to determine the IP address +that has been offered. + +Ensure that the DHCP Offer responses contain unique IP addresses. Ensure that +when these requests are resent within the lifetime of the initial offer that +the reponses to the subsequent replies contain the original IP address that was +in the initial offer to the device. + +Additionally, ensure that the DHCP Offers contain any network-specific +parameters that you have specified. + +In the case that the policy contains multiple IP pools and network definitions +for clients belonging to different Layer 2 networks (or indeed belonging to the +same network but segregated according to some local policy) you should ensure +that the devices are being mapped to the correct definition. + +For a typical policy that selects the IP pool and network options based on the +originating network for the DHCP packet, explicitly specifying a network by +including a `DHCP-Subnet-Selection-Option` parameter may avoid the need to test +from a host within each individual network: + +[source,shell] +---- +cat <<EOF > dhcp-packet-network-10.10.10.0.txt +DHCP-Message-Type := DHCP-Discover +DHCP-Client-Hardware-Address := 02:01:aa:bb:cc:dd +DHCP-Client-Identifier := abc123 +DHCP-Subnet-Selection-Option := 10.10.10.0 +EOF +---- + +For policies where the IP pool and network option selection is based on some +custom criteria it is necessary to include different variations for the +parameters on which the policy makes the decision. The testing example for the +class-specific options later in this document provides such an example. diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/policy_subnet_options.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/policy_subnet_options.adoc new file mode 100644 index 0000000..1980e89 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/policy_subnet_options.adoc @@ -0,0 +1,184 @@ +== Configure subnet-specific options for shared networks + +In the case that shared-networks are in use, with the pool containing +equally-valid IP addresses from multiple subnets, it is necessary to set the +subnet-specific parameters such as `DHCP-Router-Address`, `DHCP-Subnet-Mask` +and `DHCP-Broadcast-Address` based on the IP address that has been allocated. + +Consider the ISC DHCP configuration snippet: + +[source,iscdhcp] +---- +option domain-name "example.org"; + +shared-network bigdept { + + option domain-name-servers 10.10.0.2, 10.10.0.3; + default-lease-time 7200; + + subnet 10.30.10.0 netmask 255.255.255.0 { + option routers 10.30.10.1; + } + subnet 10.30.20.0 netmask 255.255.255.0 { + option routers 10.30.20.1; + } + range 10.30.10.10 10.30.10.254; + range 10.30.20.10 10.30.20.254; + +} +---- + +Or the equivalent Kea configuration: + +[source,kea] +---- +"Dhcp4": { + "option-data": [ + { "name": "domain-name", "data": "example.org" } + ], + "shared-networks": [{ + "name": "bigdept", + "option-data": [ + { "name": "domain-name-servers", "data": "10.10.0.2, 10.10.0.3" } + ], + "valid-lifetime": 7200, + "subnet4": [{ + "subnet": "10.30.10.0/24", + "pools": [ { "pool": "10.30.10.10 - 10.30.10.254" } ], + "option-data": [ + { "name": "routers", "data": "10.30.10.1" } + ] + }], + "subnet4": [{ + "subnet": "10.30.20.0/24", + "pools": [ { "pool": "10.30.20.10 - 10.30.20.254" } ], + "option-data": [ + { "name": "routers", "data": "10.30.20.1" } + ] + }] + }], + ... +} +---- + +As with the network to pool lookup, an instance of the `files` modules can be +employed (this time after the allocation of an IP address) to set the correct +reply parameters based on the subnet membership of the assigned address. + +To do this, we can use this section of `<raddb>/mods-available/dhcp_files`: + +[source,config] +---- +files dhcp_subnets { + filename = ${modconfdir}/files/dhcp + key = "subnet" +} +---- + +Additionally, uncomment the `dhcp_subnets` policy in `<raddb>/policy.d/dhcp`. +This policy wraps the call to the `dhcp_subnets` files module with code that +"tightens" the `DHCP-Network-Subnet` attribute by setting it to the +just-allocated IP address. + +The relevant entries in the `<raddb>/mods-config/files/dhcp` configuration +file might then look something like this: + +[source,config] +---- +network + DHCP-Domain-Name := "example.org", + Fall-Through := yes + +network DHCP-Network-Subnet < 10.30.0.0/16, Pool-Name := "bigdept" + DHCP-Domain-Name-Server := 10.10.0.2, + DHCP-Domain-Name-Server += 10.10.0.3, + DHCP-IP-Address-Lease-Time := 7200 + +subnet DHCP-Network-Subnet < 10.30.10.0/24 + DHCP-Router-Address := 10.30.10.1 + +subnet DHCP-Network-Subnet < 10.30.20.0/24 + DHCP-Router-Address := 10.30.20.1 +---- + +=== Example packet processing + +For our example, we consider a request arriving from a DHCP relay within +10.30.10.0/24. In the absence of any specific DHCP subnet selection options in +the request, the `DHCP-Network-Subnet` attribute is calculated to be the +relay's IP address, say 10.30.10.1. + +The request is matched against the first "network" block, setting the domain +name to "example.org". By virtue of `Fall-Through` being set, the next "network" +block is considered. + +Since the network identifier is within the specified subnet (i.e. `10.30.10.1 < +10.30.0.0/16`) this second "network" block is matched. This block sets the pool +name to "bigdept", sets some network-specific DNS resolvers and sets the lease +time to 7200 seconds. `Fall-Through` is not set, so we are now done with +deriving the pool name and network options. + +When the `dhcp_sqlippool` module is called during DHCP DISCOVER processing (in +`<raddb>/sites-enabled/dhcp`) the `bigdept` pool will be used for IP address +allocation. + +After IP allocation the `dhcp_subnet` policy and files instance are called. +Before the subnet options are looked up the `DHCP-Network-Subnet` +attribute is tightened to match the assigned IP address, say 10.30.20.123. + +The request does not match the first subnet block since 10.30.20.123 is not +within 10.30.10.0/24. However, the request does match the second subnet block +since `10.30.20.123 < 10.30.20.0/24`. This block sets the default gateway +reply parameter. `Fall-Through` is not set, so we are now done with deriving +the pool name and network options. + +The assigned IP address, network and subnet parameters will subsequently be +returned in the DHCP reply. + +=== Testing the subnet-specific options + +If you have set any subnet-specific reply parameters then you should test these +before proceeding further. + +For example, in the case that you have a single, large pool spanning two IP +subnets you might want to test by repeatedly allocating addresses using sample +packets with different MAC addresses, each time checking to ensure that the +DHCP parameters correspond to the IP address that has been offered. + +.Example output from dhcpclient showing a response +================================================== + dhcpclient: ... + ... + ---------------------------------------------------------------------- + Waiting for DHCP replies for: 5.000000 + ---------------------------------------------------------------------- + ... + DHCP-Your-IP-Address = 10.0.10.50 + DHCP-Router-Address = 10.0.10.1 + DHCP-Broadcast-Address = 10.0.10.255 + DHCP-Subnet-Mask = 255.255.255.255 +================================================== + + +.Example output from dhcpclient showing a response +================================================== + dhcpclient: ... + ... + ---------------------------------------------------------------------- + Waiting for DHCP replies for: 5.000000 + ---------------------------------------------------------------------- + ... + DHCP-Your-IP-Address = 10.99.99.50 + DHCP-Router-Address = 10.99.99.1 + DHCP-Broadcast-Address = 10.99.99.255 + DHCP-Subnet-Mask = 255.255.255.255 +================================================== + + +[TIP] +==== +If the subnets are large then you might want to temporarily reduce their +size by setting the `status` field of the majority of the rows for each subnet +to "`disabled`" to cause offers to be made more readily with IP addresses in +different subnets. +==== diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/prepare.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/prepare.adoc new file mode 100644 index 0000000..aa43530 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/prepare.adoc @@ -0,0 +1,59 @@ +== Preparation + +It is necessary to consider the requirements for the installation in order to +devise an efficient and manageable set up. + +=== Understand the network topology + +When multiple networks (VLANs) are in use consideration must be given to how +the correct "pool" (IP address ranges) from which to allocate addresses is +identified. + +The policy for setting specific DHCP options (e.g. lease time, default gateway, +time server and vendor-specific parameters) for different groups of hosts, +based on their network or some device attributes either supplied in the DHCP +requests or determined by dynamic lookup, should be well defined and +understood. + +Other DHCP servers may implement implicit assumptions about the requirement of +your network topology and silently define particular behaviours, such as the +selection of IP address pool for a request based on a relay address. Some of +these behaviours must be specifed explicitly when using FreeRADIUS. + +=== Choose a database backend + +FreeRADIUS stores its leases in an SQL database, so one of the key decisions to +make is which database to use. + +FreeRADIUS supports: + + * SQLite + * PostgreSQL + * MySQL / MariaDB + * Microsoft SQL Server + * Oracle + +In most configurations the SQL database is likely to be the limiting component +that restricts the IP allocation throughput of the overall system. Each +database server has its own performance characteristics and unique approach to +features such as high-availability. + +The choice of database should be made carefully based on the performance and +high-availability requirements of the system, as well as any prior experience. + +[TIP] +==== +SQLite is an in-process database that uses the local file system, is simple to +configure and is suitable for smaller installations. However, users with larger +address pools or high availability requirements should choose one of the other +standalone databases based on criteria such as performance, features, +familiarity and your need for commercial support. +==== + +FreeRADIUS ships with a default database schema and set of queries for each +supported database. These are sufficient for most DHCP deployments but can be +reviewed and modified as required to suit a particular situation, for example +to customise the IP allocation policy such as by disabling address +"stickiness". + +Now xref:protocols/dhcp/enable.adoc[enable the DHCP service]. diff --git a/doc/antora/modules/howto/pages/protocols/dhcp/test.adoc b/doc/antora/modules/howto/pages/protocols/dhcp/test.adoc new file mode 100644 index 0000000..322de08 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/dhcp/test.adoc @@ -0,0 +1,143 @@ +== Testing the DHCP service + +We can verify that FreeRADIUS is providing a DHCP service using the +`dhcpclient` tool that is included with the FreeRADIUS distribution. + +Temporarily configure FreeRADIUS to issue a single static IP address to all +clients by updating the `dhcp DHCP-Discover` section in the `dhcp` virtual +server to include the following: + +[source,unlang] +---- +update reply { + &DHCP-Your-IP-Address := 1.2.3.4 +} +---- + +Define a sample DHCP packet as follows: + +[source,shell] +---- +cat <<EOF > dhcp-packet.txt +DHCP-Message-Type := DHCP-Discover +DHCP-Client-Hardware-Address := 02:01:aa:bb:cc:dd +DHCP-Client-Identifier := abc123 +EOF +---- + +We can now generate this packet by invoking one of the following commands based +on the current circumstances... + +From the host that is running the FreeRADIUS DHCP server: + +[source,shell] +---- +dhcpclient -i lo 255.255.255.255 -f dhcp-packet.txt -x auto +---- + +From a different host with an interface (eth0) in the same broadcast domain +as the FreeRADIUS DHCP server: + +[source,shell] +---- +dhcpclient -i eth0 255.255.255.255 -f dhcp-packet.txt -x auto +---- + +If all of the DHCP broadcast traffic in other Layer 2 networks is converted to +unicast by DHCP relay agents then it is not necessary for FreeRADIUS to listen +on a broadcast address. In this case you can test DHCP using a unicast request: + +[source,shell] +---- +dhcpclient 192.0.2.10 -f dhcp-packet.txt -x auto +---- + +[NOTE] +==== +In order for the returned, unicast DHCP OFFER to be received it is necessary to +ensure that the `DHCP-Your-IP-Address` parameter set by FreeRADIUS matches an +address on the interface used by the dhcpclient tool to send the Discover +packet. +==== + +When one of the above commands is run, the tool with generate output such as +the following which shows that the packet was sent and that it is now waiting +for replies: + +.Example output from dhcpclient showing the request +=================================================== + dhcpclient: ... + ---------------------------------------------------------------------- + DHCP-Opcode = 0x01 + DHCP-Hardware-Type = 0x01 + DHCP-Hardware-Address-Length = 0x06 + DHCP-Hop-Count = 0x00 + DHCP-Transaction-Id = 0x5e0bbfab + DHCP-Number-of-Seconds = 0x0000 + DHCP-Flags = 0x0000 + DHCP-Client-IP-Address = 0x00000000 + DHCP-Your-IP-Address = 0x00000000 + DHCP-Server-IP-Address = 0x00000000 + DHCP-Gateway-IP-Address = 0x00000000 + ... + ---------------------------------------------------------------------- + Waiting for DHCP replies for: 5.000000 + ---------------------------------------------------------------------- +=================================================== + + +Each received DHCP response will generate output such as the following: + +.Example output from dhcpclient showing a response +================================================== + ... + ---------------------------------------------------------------------- + DHCP-Opcode = Server-Message + DHCP-Hardware-Type = Ethernet + DHCP-Hardware-Address-Length = 6 + DHCP-Hop-Count = 0 + DHCP-Transaction-Id = 1577828267 + DHCP-Number-of-Seconds = 0 + DHCP-Flags = 0 + DHCP-Client-IP-Address = 0.0.0.0 + DHCP-Your-IP-Address = 1.2.3.4 + DHCP-Server-IP-Address = 192.0.2.10 + DHCP-Gateway-IP-Address = 0.0.0.0 + DHCP-Client-Hardware-Address = 02:42:0a:00:00:0b + DHCP-Message-Type = DHCP-Offer + DHCP-Client-Identifier = 0x616263313233 + Waiting for additional DHCP replies for: 4.999429 + ... +================================================== + +Examine the DHCP response to ensure that it has the correct message type +(`DHCP-Offer`, in this case), contains the temporary IP address that you +configured earlier, i.e. `DHCP-Your-IP-Address = 1.2.3.4`, and any other +expected reply parameters (which we configure later). You should also carefully +examine the output of a FreeRADIUS debug session (`radius -X`) to ensure that +the policy is being executed in the way that you expect and that no warnings +are being generated. + +You can now change the content of the sample DHCP request by editing the +`dhcp-packet.txt` file and re-run the above command to see the server's reply. +You should examine the DHCP dictionary distrubuted with FreeRADIUS (usually +`/usr/share/freeradius/dictionary.dhcp`) which provides the list of all of the +DHCP parameters ("attributes") understood by FreeRADIUS. + +[WARNING] +==== +When you are done **remember** to remove the temporary edit that was made to +the `dhcp` virtual server that provides the static IP assignment. +==== + +=== Testing the DHCP policy + +The remainder of this guide describes how to configure the IP address plan, +setup the IP pools and define a DHCP policy. You should develop your policy by +making small, incremental changes to the provided configuration and then test +those changes with the approach described above, using `dhcpclient` and `radius -X`, +modifying the sample DHCP packet as required. If you break the policy then +revert the last change, attempt to understand what went wrong, and try +something else. + +Now xref:protocols/dhcp/policy.adoc[define the DHCP policy]. diff --git a/doc/antora/modules/howto/pages/protocols/proxy/enable_proxy_protocol.adoc b/doc/antora/modules/howto/pages/protocols/proxy/enable_proxy_protocol.adoc new file mode 100644 index 0000000..b689824 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/proxy/enable_proxy_protocol.adoc @@ -0,0 +1,114 @@ +== Enabling PROXY Protocol + +Now that we have a working configuration which used RadSec and HAproxy +or Traefik, we are finally ready to enable PROXY Protocol. + +Configure FreeRADIUS on the `radsecsvr` host to expect the PROXY +Protocol for RadSec connections. This is done by editing the `listen +{}` section of the `tls` virtual server to include a reference to the +proxy protocol: + +.Enabling PROXY Protocol in a FreeRADIUS virtual server +======================================================= + + listen { + ... + proxy_protocol = true + ... + } + +======================================================= + +Now restart the debugging session: +[source,shell] +---- +radiusd -fxxl /dev/stdout +---- + + +For HAproxy, you should enable the PROXY Protocol on connections to +the RadSec backend, by editing the `backend` definition to add a +`send-proxy` argument: + +.Example HAproxy backend configuration with PROXY Protocol +========================================================== + + backend radsec_be + mode tcp + balance roundrobin + server radsecsvr 172.23.0.3:2083 send-proxy + +========================================================== + +Note the `send-proxy` argument in the `server` definition. + +Now reload the HAproxy service: + +[source,shell] +---- +service haproxy reload +--- + + +For Traefik, enable the PROXY Protocol on connections to the RadSec +backend by editing the `radsec-service` definition to add a reference +to the proxy protocol" + +.Example Traefik service configuration with PROXY Protocol +========================================================== + + radsec-service: + loadBalancer: + servers: + - address: "172.23.0.3:2083" + proxyProtocol: + version: 1 + +========================================================== + +Note the `proxyProtocol` and `version: 1` directives. + +Traefik should automatically detect the updates and reconfigure the +service. + + +=== Testing RadSec connectivity via a proxy using PROXY Protocol + +Finally, with your test client configured to use the proxy, perform a +test authentication: + +[source,shell] +---- + echo "User-Name = bob" | radclient 127.0.0.1 auth testing123 +---- + +You should expect to see the familiar output: + +.Example output from radclient +============================== + + Sent Access-Request Id 252 from 0.0.0.0:50118 to 127.0.0.1:1812 length 27 + Received Access-Accept Id 252 from 127.0.0.1:1812 to 127.0.0.1:50118 length 39 + +============================== + +Now examine the FreeRADIUS debug output on the RadSec server: + +.Expected output from `radiusd -X` with PROXY Protocol +====================================================== + + ... + (0) (TLS) Received PROXY protocol connection from client \ + 172.23.0.2:55343 -> 172.23.0.4:2083, via proxy 172.23.0.4:40268 -> 0.0.0.0:2083 + ... + (0) Received Access-Request Id 227 from 172.23.0.2:55343 to 172.23.0.4:2083 length 49 + (0) Sent Access-Accept Id 227 from 172.23.0.4:2083 to 172.23.0.2:55343 length 0 + ... + +====================================================== + +The output indicates that FreeRADIUS is receiving the originating +connection information from the PROXY Protocol. FreeRADIUS then +handles the RadSec requests as though they have been received directly +from the originating client. + diff --git a/doc/antora/modules/howto/pages/protocols/proxy/enable_radsec.adoc b/doc/antora/modules/howto/pages/protocols/proxy/enable_radsec.adoc new file mode 100644 index 0000000..f5e7603 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/proxy/enable_radsec.adoc @@ -0,0 +1,188 @@ +== Enabling RadSec with FreeRADIUS + +Our first task is to set up a RadSec server by configuring an instance of +FreeRADIUS to accept RADIUS over TLS requests. + +The following steps should be performed on the host which will be the +RadSec server, we will call it `radsecsvr`. + +You can install FreeRADIUS using the NetworkRADIUS packages by +following the instructions provided here: + +<https://networkradius.com/packages/> + +Before making any configuration changes, you should stop the radiusd +service: + +[source,shell] +---- + service radiusd stop +---- + +Then, enable the `tls` virtual server: + +[source,shell] +---- +cd /etc/raddb/sites-enabled +ln -s ../sites-available/tls +---- + +The FreeRADIUS distribution contains an example Certificate Authority +that will have generated the necessary CA, server and client +certificates and keys during package installation. You can use this +CA, or you can use your own CA and certificates. + +[TIP] +==== +If the example certificates are not present (for example if FreeRADIUS was +installed from source) then FreeRADIUS will fail to start. The files can be +regenerated by running `make` in the `/etc/raddb/certs` directory. +==== + +Edit the `tls` virtual server configuration, in order to add +definitions for the clients by extending the `clients radsec {}` section: + +.Example radsec client definitions in `/etc/raddb/sites-available/tls` +==== + + clients radsec { + ... + # Direct connections from the test client + client radseccli { + ipaddr = 172.23.0.2 + proto = tls + virtual_server = default + } + # Connections via HAproxy + client haproxy { + ipaddr = 172.23.0.4 + proto = tls + virtual_server = default + } + # Connections via Traefik + client traefik { + ipaddr = 172.23.0.5 + proto = tls + virtual_server = default + } + } + +==== + +The client `ipaddr` configuration item is used to match the source IP +address of incoming connections. You must add client definitions for +each of the clients which will connect. + +For RadSec, you can just list the IP address of the RadSec client. +This client definition is used for processing RADIUS packets from the +RadSec client. + +[NOTE] +==== +A `secret` does not have to be specified for RadSec clients, as the +default is `radsec`. If you specify a secret, then that will be used +instead of `radsec`. +==== + +When the PROXY protocol is used, you must _also_ define a client which +matches the IP address of the proxy (haproxy, etc). This client is +only used to check that the source IP is permitted to connect to the +server. Fields other than `ipaddr` can be specified (and in some +cases may be required). However, all other fields will be ignored. + +For testing purposes, we want to amend the `default` virtual server so +that it accepts all authentication reqeusts and immediately responds +to accounting requests. + +Edit the `/etc/raddb/sites-enabled/default` file so that the beginning of +the `authorize` and `preacct` sections looks as follows: + +.Example default virtual server modification to unconditionally accept Access-Requests +==== + + authorize { + accept + ... + } + ... + preacct { + handled + ... + } + +==== + +This change makes the `authorize` section always "accept" the user, +and makes the `preacct` section always say "we handled the accounting +request". These changes are only for testing, and should never be +used in production. + +Start the FreeRADIUS service in the foreground with debugging enabled: + +[source,shell] +---- +radiusd -fxxl /dev/stdout +---- + +Examine the output from FreeRADIUS to ensure that it is now listening for +RadSec connection on TCP/2083: + +.Example output from running `radiusd -fxxl /dev/stdout` +==== + + FreeRADIUS Version 3.0.24 + Copyright (C) 1999-2021 The FreeRADIUS server project and contributors + ... + ... : Debug: Listening on auth+acct proto tcp address * port 2083 (TLS) bound to server default + ... : Debug: Listening on auth address * port 1812 bound to server default + ... : Debug: Listening on acct address * port 1813 bound to server default + ... : Debug: Listening on auth address :: port 1812 bound to server default + ... : Debug: Listening on acct address :: port 1813 bound to server default + ... + ... : Info: Ready to process requests + +==== + +FreeRADIUS is now ready to process RadSec traffic. + +For testing, we first test normal RADIUS over UDP functionality, then +the RadSec connection using a test client, then introduce a proxy +server, and finally we enable PROXY Protocol. Doing the tests in this +way ensures that we know that all previous steps work before trying +the next step. This process allows us to quickly narrow down +problems, and gets us to the final goal _faster_ than just "doing +everything all at once". + +=== Testing the RADIUS policy + +Before moving on, verify that the FreeRADIUS policy is able to +authenticate a local test RADIUS Access-Request over UDP: + +[source,shell] +---- +echo "User-Name = terry" | radclient 127.0.0.1 auth testing123 +---- + +Due to the `accept` we added in the `authorize` section, the expected +output should be an Access-Accept: + +.Expected output from radclient +=============================== + + Sent Access-Request Id 157 from 0.0.0.0:36850 to 127.0.0.1:1812 length 27 + Received Access-Accept Id 157 from 127.0.0.1:1812 to 127.0.0.1:36850 length 20 + +=============================== + +Any other output indicates that there is a problem with the FreeRADIUS +configuration which *must* be solved before testing RadSec. Carefully verify that +you have carried out each of the above steps correctly and examine the debug +output from FreeRADIUS, which will usually tell you what is wrong. + +See [how to read the debug +output](http://wiki.freeradius.org/radiusd-X) for instructions on +reading amd understanding the debug output. + +The next step is to xref:protocols/proxy/radsec_client.adoc[configure +FreeRADIUS as a RadSec test client] so that we can verify that our +RadSec server is working. diff --git a/doc/antora/modules/howto/pages/protocols/proxy/index.adoc b/doc/antora/modules/howto/pages/protocols/proxy/index.adoc new file mode 100644 index 0000000..5100635 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/proxy/index.adoc @@ -0,0 +1,126 @@ += Proxying RadSec and enabling PROXY Protocol + +This guide shows how to set up FreeRADIUS to serve RadSec connections, fronted +by either HAproxy or Traefik as Layer 4 proxies that pass on the original +client connection information using PROXY Protocol. + +It is not a comprehensive guide to using RadSec with FreeRADIUS. It presents a +basic configuration that uses an example CA and does not validate certificate +attributes or perform revokation status. + + +== Introduction + +FreeRADIUS supports receiving RADIUS requests over TLS-enabled TCP connections +and supports proxying of requests over TCP connections to another TLS-enabled +homeserver. The protocol for RADIUS over TLS is called "RadSec" and is defined +in RFC 6614. + +FreeRADIUS is a capable and performant application-aware ("Layer 7") proxy / +load-balancer for RadSec and other forms of RADIUS traffic. + + +=== Layer 4 proxying + +Rather than use an application-aware proxy it is sometimes better to reduce the +performance impact incurred by re-encoding an application protocol by using a +"Layer 4" proxy that operates at the level of individual connections without +regard for the application protocol. Such a proxy is more of a "bump in the +wire" than a request buffer and minimises the latency incurred due to proxying. + +It is common to see software such as HAproxy and Traefik used in Layer 4 mode +in place of FreeRADIUS for purposes such as connection load balancing. In +addition to improved performance, these tools have the benefit that they +typically support dynamic service discovery and "hitless" reloads to +automatically adapt their connection routing based on changes to backend +services such as the introduction of new nodes with even a momentary loss of +service. + + +=== Loss of connection information + +When TCP connections are relayed through Layer 4 proxies the information +about the originating source of the connection is no longer known to the +backend service, unless it is otherwise made available. Identifying the +originator of connections is often necessary for security purposes and for +request processing. + +Whilst many application protcols support headers that allow proxies to preserve +connection information these are not helpful in the context of Layer 4 +proxying: The process of populating headers requires knowledge of the +application protocol to re-encode requests as they are transmitted between the +frontend and backend connections. + + +=== PROXY Protocol + +PROXY Protocol overcomes this limitation by allowing the original connection +information to be provided to the backend at the start of the TCP connection. +After this initial data is encoded the remainder of the conversation then +proceeds as normal. However now that the connection information is known to the +backend server it is able to process requests made on the connection as though +the connection were being made directly by the client and not via the proxy. + +PROXY Protocol is specified in this document: +http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt + + +== Requirements + +PROXY Protocol Version 1 is supported by FreeRADIUS v3.0.24 and later versions. + +You will require the following set of VMs or containers, each with their own +IP address: + +[cols="1,1,1"] +|=== +|Hostname|IP address|Purpose + +|radseccli +|172.23.0.2 +|FreeRADIUS configured to provide a RadSec test client + +|radsecsvr +|172.23.0.3 +|FreeRADIUS configured as a RadSec server + +|haproxy +|172.23.0.4 +|HAproxy in Layer 4 mode to the FreeRADIUS RadSec backend +|=== + +Optionally you may want to configure a host to run Traefik within a Docker +container using host mode networking, perhaps configured by Docker Compose, +however the installation is beyond the scope of this guide: + +[cols="1,1,1"] +|=== +|traefik +|172.23.0.5 +|Traefik configured as a TCP router with TLS passthrough to the FreeRADIUS RadSec backend +|=== + +The hostnames and IP addresses provided above are for examples purposes and are +used throughout the remainder of this guide. This guide provides commands and +output for CentOS. Other distributions will have minor differences, including +the location of the FreeRADIUS configuration (the "raddb"). + +[NOTE] +==== +You can choose to use your own hostname, IP addresses and OS distribution. You +could also use official Docker images provided by the respecitive projects, +however these prescribe methods for configuring and managing the services +that are not typical for a normal package installation which would provide a +distraction if used for by guide. +==== + + +== Sections in this guide + +This guide is organised into four parts that should be read in order: + +1. xref:protocols/proxy/enable_radsec.adoc[Enabling RadSec] +2. xref:protocols/proxy/radsec_client.adoc[Configuring a test RadSec client] +3. xref:protocols/proxy/radsec_with_haproxy.adoc[Proxying RadSec with HAproxy] +4. xref:protocols/proxy/radsec_with_traefik.adoc[Proxying RadSec with Traefik] +5. xref:protocols/proxy/enable_proxy_protocol.adoc[Enabling PROXY Protocol for RadSec] diff --git a/doc/antora/modules/howto/pages/protocols/proxy/radsec_client.adoc b/doc/antora/modules/howto/pages/protocols/proxy/radsec_client.adoc new file mode 100644 index 0000000..d92345e --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/proxy/radsec_client.adoc @@ -0,0 +1,181 @@ +== Configuring FreeRADIUS as a RadSec test client + +Unfortunately, the `radclient` program does not support RadSec. We +must therefore configure an instance of FreeRADIUS as a "transport +converter" which proxies UDP-based RADIUS requests to a RadSec +destination of our choice. + +The following steps should be performed on a client system, which we +will call `radseccli`. This system should be a new system, with a +different IP address. That is, you shoudl not edit the configuration +on the `radsecsvr` host. Doing so will break the RadSec configuration. + +Install FreeRADIUS using the NetworkRADIUS packages by following the +instructions provided here: + +<https://networkradius.com/packages/> + +Before making any configuration changes, you should stop the radiusd +service: + +[source,shell] +---- + service radiusd stop +---- + +Add a new `tls` home server definition, which will point to the RadSec +server. We do this by creating a file +`/etc/raddb/sites-enabled/radsec-homeserver` with the following +contents: + +.Example homeserver, pool and realm definitions for the RadSec service +==== + + home_server tls { + ipaddr = 172.23.0.3 # IP address of our RadSec server + port = 2083 + type = auth+acct + proto = tcp + tls { + private_key_password = whatever + private_key_file = ${certdir}/client.pem + certificate_file = ${certdir}/client.pem + ca_file = ${cadir}/ca.pem + } + } + home_server_pool tls { + type = fail-over + home_server = tls + } + realm tls { + auth_pool = tls + acct_pool = tls + } + +==== + +[TIP] +==== +Complete descriptions of each of the above configuration items can be found in the +`[raddb]/sites-available/tls` example configuration file. For simple tests, however, +we can omit all of the comments from the file. +==== + +To use this `tls` home server, we change the `default` virtual server to proxy +all authentication and accounting requests to it. + +Edit the `/etc/raddb/sites-enabled/default` file so that the beginning of +the `authorize` and `preacct` sections looks as follows: + +.Example default virtual server modification to proxy requests to a RadSec proxy server +==== + + authorize { + update control { + &Proxy-To-Realm := tls + } + handled + ... + } + ... + preacct { + update control { + &Proxy-To-Realm := tls + } + handled + ... + } + +==== + +These changes make the `tls` virtual server always proxy packets. +These changes are only for testing, and should never be used in +production. + +We must now copy the example CA certificate as well as the client +certificate and key files which are on the `radsecsrv` host to this +test client. + +Replace the following files on `radseccli` with the equivalent files from +`radsecsrv`: + +[cols="1,1,1"] +|=== +|File|Corresponding configuration item|Purpose + +|/etc/raddb/certs/ca.pem +|`ca_file` +|CA certificate which is used to authenticate the server certificate presented by the RadSec server to the client. + +|/etc/raddb/certs/client.pem +|`certificate_file` +|Client certificate (signed by the CA certificate) that is presented by the test client to the RadSec server. + +|/etc/raddb/certs/client.pem +|`private_key_file` and `private_key_password` +|Private key corresponding to the client certificate +|=== + +Note that the client certificate and key are typically bundled into a single file. + +[CAUTION] +==== +If you do not correctly replace the CA, client certificate, and key +material on the test client then the RadSec client and RadSec server +will fail to mutually authenticate each other as they do not share a +trusted CA. If you see messages like `unknown CA`, then you know that +the certificates have not been set up correctly. +==== + +Start the FreeRADIUS service in debug mode: + +[source,shell] +---- +radiusd -X +---- + + +=== Testing RadSec connectivity + +At this stage you should be able to cause the test client to send RadSec +requests directly to the RadSec server. + +Run the following to send a RADUS (UDP) Access-Request to the local FreeRADIUS +instance. It should then proxy the request over RadSec connection to +the remote RadSec server: + +[source,shell] +---- + echo "User-Name = bob" | radclient 127.0.0.1 auth testing123 +---- + +If the test client is able to successfully establish the RadSec +connection, and the RadSec server replies with an Access-Accept +response, then the output will be as follows: + +.Expected output from radclient +=============================== + + Sent Access-Request Id 252 from 0.0.0.0:50118 to 127.0.0.1:1812 length 27 + Received Access-Accept Id 252 from 127.0.0.1:1812 to 127.0.0.1:50118 length 39 + +=============================== + +Lack of response or an Access-Reject response indicates that the RadSec +connection is not being established successfully. + +There may be serveral reasons for broken connectivity including: + + * The client not accepting the certificate presented by the server. + * The server not accepting the certificate presented by the client. + +Look at the debug output generated by both the test client and the RadSec +server. In many cases it will tell you exactly what the problem is. + +Do not proceed with any further steps until direct connections between the +RadSec client and Radsec Server are working properly. + +Once things are working we are ready to +xref:protocols/proxy/radsec_with_haproxy.adoc[configure HAproxy to proxy RadSec +connections] or to xref:protocols/proxy/radsec_with_traefik.adoc[configure +Traefik to proxy RadSec connections]. diff --git a/doc/antora/modules/howto/pages/protocols/proxy/radsec_with_haproxy.adoc b/doc/antora/modules/howto/pages/protocols/proxy/radsec_with_haproxy.adoc new file mode 100644 index 0000000..e58abfe --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/proxy/radsec_with_haproxy.adoc @@ -0,0 +1,134 @@ +== Proxying RadSec with HAproxy + +This section shows how to configure HAproxy to proxy RadSec connections. + +The following steps should be performed on the `haproxy` host, unless otherwise +stated. + +Install the HAproxy package supplied with the OS distribution: + +[source,shell] +---- + yum install haproxy +---- + +Stop the haproxy service: + +[source,shell] +---- + service haproxy stop +---- + +Modify the haproxy configuration (typically `/etc/haproxy/haproxy.conf`) so +that it includes new frontend and backend configuration for the radsec service: + +.Example minimal HAproxy configuration +====================================== + + global + maxconn 100 + defaults + mode tcp + timeout connect 10s + timeout client 30s + timeout server 30s + frontend radsec_fe + bind *:2083 + default_backend radsec_be + backend radsec_be + balance roundrobin + server radsecsvr 172.23.0.3:2083 + +====================================== + +Note the `mode tcp` directive which tells HAproxy to act as a Layer 4 +proxy, so that it doesn't attempt to perform SSL termination or +decode the RADIUS protocol. + +[NOTE] +==== +The above example is a minimal configuration. In practise you will want to +retain many of the HAproxy configuration items already present in the +configuration (e.g. `log`, `chroot`, `user`, `group`), but these vary across +distributions. Other HTTP-related options that may already exist in the +configuration will conflict with `mode tcp` (Layer 4 proxying) and should be +removed if HAproxy complains about them. + +However, you should first get things working with the minimal +configuration which is known to work, and then make customisations. +If you start off with a complex configuration, then there may be a +large number of things which are broken, and debugging them all will +be difficult. Start simple, and then add complexity! +==== + +Restart the haproxy service in foreground mode for debugging purposes: + +[source,shell] +---- +haproxy -f /etc/haproxy/haproxy.cfg -db +---- + + +=== Testing RadSec connectivity via HAproxy + +Now edit the test RadSec client, so that instead of making connections directly +to the RadSec server it makes connections to the HAproxy server. + +On `radseccli` edit the `/etc/raddb/sites-enabled/tls` file, and set +the IP address to the address of the `haproxy` host. + +.Example updated test client homeserver configuration +===================================================== + + home_server tls { + ipaddr = 172.23.0.4 # Updated from radsecsvr to haproxy + ... + } + +===================================================== + +Restart the debug mode session: + +[source,shell] +---- +radiusd -X +---- + +Perform a test authentication: + +[source,shell] +---- + echo "User-Name = bob" | radclient 127.0.0.1 auth testing123 +---- + +If the test client is able to successfully establish the RadSec +connection via HAproxy, and the RadSec server replies with an +Access-Accept response, then the output will be as follows: + +.Expected output from radclient +=============================== + + Sent Access-Request Id 252 from 0.0.0.0:50118 to 127.0.0.1:1812 length 27 + Received Access-Accept Id 252 from 127.0.0.1:1812 to 127.0.0.1:50118 length 39 + +=============================== + +HAproxy should also log a message that indicates that the connection was +proxied, such as the following: + +.Expected output from HAproxy +============================= + + <150>...: Connect from 172.23.0.2:50087 to 172.23.0.4:2083 (radius_fr/TCP) + +============================= + +Any other output from radclient or HAproxy indicates that there is a +problem with the HAproxy configuration, or that FreeRADIUS is not +accepting connection from the `haproxy` host, which must be solved +before continuing. + +Once proxied connections are working we are ready to +xref:protocols/proxy/enable_proxy_protocol.adoc[enable the PROXY +Protocol] on both HAproxy and the RadSec server. + diff --git a/doc/antora/modules/howto/pages/protocols/proxy/radsec_with_traefik.adoc b/doc/antora/modules/howto/pages/protocols/proxy/radsec_with_traefik.adoc new file mode 100644 index 0000000..11030e9 --- /dev/null +++ b/doc/antora/modules/howto/pages/protocols/proxy/radsec_with_traefik.adoc @@ -0,0 +1,128 @@ +== Proxying RadSec with Traefik + +This section shows how to configure Traefik to proxy RadSec connections. You +should skip this section if you are not using Traefik as your proxy. + +Installing Traefik is beyond the scope of this guide. It is typically installed +as a service mesh router within a Docker or Kubernetes environment using +offical Docker images. + +Traefik configuration has two components of interest: + + * Static configuration: Defines "entrypoints" on which Traefik listens for connections. + * Dynamic configuration: Defines backend service components and the routing policy. + +Traefik supports a number of providers of dynamic configuration data for the +router and service definitions. For demonstration purposes the files provider +is used here, however you can switch to another provide once you have things +working using this method. + +The static configuration can be provided by starting Traefik with the following +arguments: + +.Example Traefik static configuration +===================================== + + traefik \ + --log.level=DEBUG \ + --providers.file.filename=/etc/traefik/dynamic_config.yml + --providers.file.watch=true + --entryPoints.radsec.address=:2083 + +===================================== + +Note that a `radsec` entrypoint is defined to listen on port 2083 and that a +static `file` provider is used to defined the dynamic services. + +The backend for RadSec should be defined in this file as follows: + +.Example Traefik dynamic configuration +====================================== + + tcp: + routers: + radsec-router: + entryPoints: + - radsec + rule: "HostSNI(`*`)" + service: "radsec-service" + tls: + passthrough: true + services: + radsec-service: + loadBalancer: + servers: + - address: "172.23.0.3:2083" + +====================================== + +Note the `passthrough: true` directive under `tls:` which tells Treafik not to +attempt TLS termination which it would otherwise perform for all incoming TLS +connections. We require that the connection is passed through from the RadSec +client to the RadSec server without being reterminated since the end client's +certificate is authenticated by the RadSec server and many be used for +policy decisions. + + +=== Testing RadSec connectivity via Traefik + +Now amend the test RadSec client so that instead of making connections directly +to the RadSec server it makes them via Traefik. + +On `radseccli` amend `/etc/raddb/sites-enabled/tls` and set the IP address to +that of the `traefik` host. + +.Example updated test client homeserver configuration +===================================================== + + home_server tls { + ipaddr = 172.23.0.5 # Updated from radsecsvr to traefik + ... + } + +===================================================== + +Restart the debug mode session: + +[source,shell] +---- +radiusd -X +---- + +Perform a test authentication: + +[source,shell] +---- + echo "User-Name = bob" | radclient 127.0.0.1 auth testing123 +---- + +If the test client is able to successfully establish the RadSec connection via +Traefik and the RadSec server replies with an Access-Accept response then the +output will be as follows: + +.Example output from radclient +============================== + + Sent Access-Request Id 252 from 0.0.0.0:50118 to 127.0.0.1:1812 length 27 + Received Access-Accept Id 252 from 127.0.0.1:1812 to 127.0.0.1:50118 length 39 + +============================== + +Traefik should also log a message that indicates that the connection was +proxied, such as the following: + +.Example output from Traefik +============================ + + time="..." level=debug msg="Handling connection from 172.23.0.2:57367" + +============================ + +Any other output from radclient or Traefik indicates that there is a problem +with the Traefik configuration or that FreeRADIUS is not accepting connection +from the `traefik` host, which must be solved before continuing. + +Once proxied connections are working we are ready to +xref:protocols/proxy/enable_proxy_protocol.adoc[enable the PROXY Protocol] on +both Traefik and the RadSec server. + diff --git a/doc/antora/modules/installation/nav.adoc b/doc/antora/modules/installation/nav.adoc new file mode 100644 index 0000000..26ce32e --- /dev/null +++ b/doc/antora/modules/installation/nav.adoc @@ -0,0 +1,5 @@ +* xref:index.adoc[Installing and upgrading] +** xref:packages.adoc[Install from packages] +** xref:dependencies.adoc[Dependencies] +** xref:source.adoc[Build from source] +** xref:upgrade.adoc[Upgrading to v3] diff --git a/doc/antora/modules/installation/pages/dependencies.adoc b/doc/antora/modules/installation/pages/dependencies.adoc new file mode 100644 index 0000000..e910e76 --- /dev/null +++ b/doc/antora/modules/installation/pages/dependencies.adoc @@ -0,0 +1,58 @@ += FreeRADIUS Dependencies + +Some external dependencies must be installed before building or +running FreeRADIUS. The core depends on two mandatory libraries: +`libtalloc` for memory management and `libkqueue` for event +handling. + +Many of the modules also have optional dependencies. For example, +the LDAP module requires LDAP client libraries to be installed +and database modules need their respective database client +libraries. + +If building from source code, the configure stage will check for +the optional dependencies. Any missing libraries will cause that +particular module to be skipped. + +== Libraries + +=== libtalloc + +Talloc is a memory allocation library available at +https://talloc.samba.org/talloc/doc/html/index.html + +*OSX* + +`# brew install talloc` + +*Debian, Ubuntu and `dpkg`-based systems* + +`# apt-get install libtalloc-dev` + +*RedHat or CentOS* + +``` +# subscription-manager repos --enable rhel-7-server-optional-rpms +# yum install libtalloc-dev +``` + +=== kqueue + +Kqueue is an event / timer API originally written for BSD systems. +It is _much_ simpler to use than third-party event libraries. A +library, `libkqueue`, is available for Linux systems. + +*OSX* + +_kqueue is already available, there is nothing to install._ + +*Debian, Ubuntu and `dpkg`-based systems* + +`# apt-get install libkqueue-dev` + +*RedHat or CentOS* + +``` +# subscription-manager repos --enable rhel-7-server-optional-rpms +# yum install libkqueue-dev +``` diff --git a/doc/antora/modules/installation/pages/index.adoc b/doc/antora/modules/installation/pages/index.adoc new file mode 100644 index 0000000..b810078 --- /dev/null +++ b/doc/antora/modules/installation/pages/index.adoc @@ -0,0 +1,15 @@ +== Installation + +FreeRADIUS is available from multiple sources: + +* Official xref:packages.adoc[Network RADIUS packages] +* xref:source.adoc[Source code] +* Many Operating System distributions + +We highly recommend using the official packages from Network +RADIUS, where available. + +The documents in this section cover details of the above +installation methods, as well as instructions on building +packages locally. + diff --git a/doc/antora/modules/installation/pages/packages.adoc b/doc/antora/modules/installation/pages/packages.adoc new file mode 100644 index 0000000..ffc52cd --- /dev/null +++ b/doc/antora/modules/installation/pages/packages.adoc @@ -0,0 +1,22 @@ +== Install from packages + +Network RADIUS provide pre-built binary packages of FreeRADIUS for +common Linux distributions. This is the recommended installation +method when packages are available for your system. + +The official http://packages.networkradius.com[Network RADIUS +packages] page contains recent FreeRADIUS packages and +installation instructions. + +=== Distribution-supplied packages + +While many Operating System distributions ship FreeRADIUS +packages, the versions they include are often years out of date. +As well as missing out on the latest bug fixes and features, this +also means that it is very hard to know if an issue encountered is +still a problem or if it is fixed in the latest release. + +Therefore, whilst the distribution-supplied packages can often be +the most convenient to install, we do not usually recommend using +them. + diff --git a/doc/antora/modules/installation/pages/source.adoc b/doc/antora/modules/installation/pages/source.adoc new file mode 100644 index 0000000..cf40a79 --- /dev/null +++ b/doc/antora/modules/installation/pages/source.adoc @@ -0,0 +1,199 @@ +== Building from Source + +We recommend xref:packages.adoc[installing from packages] if +possible. Full instructions on building and installing from source +code follow. + +The mandatory xref:installation:dependencies.adoc[dependencies] +must be installed before FreeRADIUS can be built. These dependencies +are `libtalloc` and `libkqueue`, which FreeRADIUS uses for memory +management, and platform-independent event handling. + +Per-module dependencies that enable support for external services +such as LDAP, SQL, etc, are optional. They must be installed for +any modules that are to be used. The FreeRADIUS `./configure` step +will automatically detect if each module has its dependencies met +and automatically enable support for them. If the features you +require are not enabled you should inspect the configure script +output to figure out which additional development libraries need +to be installed. + +The FreeRADIUS source may be obtained from a number of locations: + +* Download the latest version of the FreeRADIUS source from + https://www.freeradius.org/releases/[the FreeRADIUS web site]; or +* download directly from the + ftp://ftp.freeradius.org/pub/freeradius/[FreeRADIUS FTP site]; or +* download from + https://github.com/FreeRADIUS/freeradius-server/[GitHub]. + +The file wil be name something like: `freeradius-server-3.0.22.tar.gz`. +Later versions will be `3.0.23`, or `4.0.0`, etc. PGP signatures are +also provided for official releases from the FTP site; these are +named e.g. `freeradius-server-3.0.22.tar.gz.sig`. + +Un-tar the file, and change to the FreeRADIUS directory (where +`VERSION` below is the version of the server that you have +downloaded). + +[source,shell] +---- +tar -zxf freeradius-server-VERSION.tar.gz +cd freeradius-server-VERSION +---- + +Take the following steps to build and install the server from source: + +[source,shell] +---- +./configure +make +sudo make install +---- + +=== Custom build + +FreeRADIUS has GNU autoconf support. This means you have to run +`./configure`, and then run `make`. To see which configuration +options are supported, run `./configure --help`, and read its output. + +The `make install` stage will install the binaries, the "man" pages, +and _may_ install the configuration files. If you have not installed a +RADIUS server before, then the configuration files for FreeRADIUS will +be installed. + +If you already have a RADIUS server installed, then *FreeRADIUS +WILL NOT over-write your current configuration.* + +The `make install` process will warn you about the files it could not +install. + +If you see a warning message about files that could not be +installed, then you *must* ensure that the new server is using the +new configuration files and not the old configuration files, as +this may cause undesired behavior and failure to operate correctly. + +The initial output from running in debugging mode (`radiusd -X`) +will tell you which configuration files are being used. See +xref:installation:upgrade.adoc[Upgrading] for information about +upgrading from older versions. There _may_ be changes in the +dictionary files which are required for a new version of the +software. These files will not be installed over your current +configuration, so you *must* verify and install any problem files by +hand, for example using `diff(1)` to check for changes. + +When installing from source, it is _extremely_ helpful to read the +output of `./configure`, `make`, and `make install`. If a +particular module you expected to be installed was not installed, +then the output will tell you why that module was not installed. +The most likely reason is that required libraries (including their +development header files) are not available. + +Please do _not_ post questions to the FreeRADIUS users list +without first carefully reading the output of this process as it +often contains the information needed to resolve a problem. + +== Upgrading To A New Minor Release + +The installation process will not over-write your existing configuration +files. It will, however, warn you about the files it did not install. +These will require manual integration with the existing files. + +It is not possible to re-use configurations between different major +versions of the server. + +For details on what has changed between the version, see the +xref:installation:upgrade.adoc[upgrade] guide. + +We _strongly_ recommend that new major versions be installed in a +different location than any existing installations. Any local policies +can then be migrated gradually to the configuration format of the new +major version. The number of differences in the new configuration mean +that is is both simpler and safer to migrate your configurations rather +than to try and just get the old configuration to work. + +== Running the server + +If the server builds and installs, but doesn’t run correctly, then +you should first use debugging mode (`radiusd -X`) to figure out +the problem. + +This is your best hope for understanding the problem. Read _all_ +of the messages which are printed to the screen, the answer to +your problem will often be in a warning or error message. + +We really cannot emphasize that last sentence enough. Configuring +a RADIUS server for complex local authentication isn’t a trivial +task. Your _best_ and _only_ method for debugging it is to read +the debug messages, where the server will tell you exactly what +it’s doing, and why. You should then compare its behaviour to what +you intended, and edit the configuration files as appropriate. + +If you don’t use debugging mode, and ask questions on the mailing +list, then the responses will all tell you to use debugging mode. +The server prints out a lot of information in this mode, including +suggestions for fixes to common problems. Look especially for +`WARNING` and `ERROR` messages in the output, and read the related +messages. + +Since the main developers of FreeRADIUS use debugging mode to +track down their configuration problems with the server, it’s a +good idea for you to use it, too. If you don’t, there is little +hope for you to solve any configuration problem related to the +server. + +To start the server in debugging mode, do: + +[source,shell] +---- +radiusd -X +---- + +You should see a lot of text printed on the screen as it starts up. If +you don’t, or if you see error messages, please read the FAQ: + +https://wiki.freeradius.org/guide/FAQ + +If the server says `Ready to process requests.`, then it is running +properly. From another shell (or another window), type + +[source,shell] +---- +radtest test test localhost 0 testing123 +---- + +You should see the server print out more messages as it receives the +request, and responds to it. The `radtest` program should receive the +response within a few seconds. It doesn’t matter if the authentication +request is accepted or rejected, what matters is that the server +received the request, and responded to it. + +You can now edit the configuration files for your local system. You will +usually want to start with `sites-enabled/default` for main +configurations. To set which NASes (clients) can communicate with this +server, edit `raddb/clients.conf`. Please read the configuration files +carefully, as many configuration options are only documented in comments +in the file. + +Note that is is _highly_ recommended that you use some sort of version +control system to manage your configuration, such as git or Subversion. +You should then make small changes to the configuration, checking in and +testing as you go. When a config change causes the server to stop +working, you will be able to easily step back and find out what update +broke the configuration. + +It is also considered a best practice to maintain a staging or +development environment. This allows you to test and integrate your +changes without impacting your active production environment. You should +make the appropirate investment in order to properly support a critical +resource such as your authentication servers. + +Configuring and running the server MAY be complicated. Many modules have +`man` pages. See `man rlm_pap`, or `man rlm_*` for information. +Please read the documentation in the doc/ directory. The comments in the +configuration files also contain a lot of documentation. + +If you have any additional issues, the FAQ is also a good place to +start. + +https://wiki.freeradius.org/guide/FAQ diff --git a/doc/antora/modules/installation/pages/upgrade.adoc b/doc/antora/modules/installation/pages/upgrade.adoc new file mode 100644 index 0000000..67874c8 --- /dev/null +++ b/doc/antora/modules/installation/pages/upgrade.adoc @@ -0,0 +1,737 @@ += Upgrading from v2 to v3 + +The configuration for 3.0 is *largely* compatible with the 2.x.x +configuration. However, it is NOT possible to simply use the 2.x.x +configuration as-is. Instead, you should re-create it. + +== Security + +A number of configuration items have moved into the "security" subsection of +radiusd.conf. If you use these, you should move them. Otherwise, they can +be ignored. + +The list of moved options is: + +* chroot +* user +* group +* allow_core_dumps +* reject_delay +* status_server + +These entries should be moved from "radiusd.conf" to the "security" +subsection of that file. + +== Naming + +Many names used by configuration items were inconsistent in earlier +versions of the server. These names have been unified in version 3.0. + +If a file is being referenced or created the config item `filename` +is used. + +If a file is being created, the initial permissions are set by the +`permissions` config item. + +If a directory hierarchy needs to be created, the permissions are set +by `dir_permissions`. + +If an external host is referenced in the context of a module the +`server` config item is used. + +Unless the config item is a well recognised portmanteau +(as `filename` is for example), it must be written as multiple +distinct words separated by underscores `_`. + +The configuration items `file`, `script_file`, `module`, +`detail`, `detailfile`, `attrsfile`, `perm`, `dirperm`, +`detailperm`, and `hostname` are deprecated. As well as any false +portmanteaus, and configuration items that used hyphens as word +delimiters. e.g. `foo-bar` has been changed to `foo_bar`. Please +update your module configuration to use the new syntax. + +In most cases the server will tell you the replacement config item to +use. As always, run the server in debugging mode to see these +messages. + +== Modules Directory + +As of version 3.0, the `modules/` directory no longer exists. + +Instead, all "example" modules have been put into the +`mods-available/` directory. Modules which can be loaded by the +server are placed in the `mods-enabled/` directory. All of the +modules in that directory will be loaded. This means that the +`instantiate` section of radiusd.conf is less important. The only +reason to list a module in the `instantiate` section is to force +ordering when the modules are loaded. + +Modules can be enabled by creating a soft link. For module `foo`, do: + +[source,shell] +---- +cd raddb/mods-enabled +ln -s ../mods-available/foo +---- + +To create "local" versions of the modules, we suggest copying the file +instead. This leaves the original file (with documentation) in the +`mods-available/` directory. Local changes should go into the +`mods-enabled/` directory. + +Module-specific configuration files are now in the `mods-config/` +directory. This change allows for better organization, and means that +there are fewer files in the main `raddb` directory. See +`mods-config/README.rst` for more details. + +== Changed Modules + +The following modules have been changed in this version. + +=== rlm_sql + +The SQL configuration has been moved from `sql.conf` to +`mods-available/sql`. The `sqlippool.conf` file has also been +moved to `mods-available/sqlippool`. + +The SQL module configuration has been changed. The old connection +pool options are no longer accepted: + +---- +num_sql_socks +connect_failure_retry_delay +lifetime +max_queries +---- + +Instead, a connection pool configuration is used. This configuration +contains all of the functionality of the previous configuration, but +in a more generic form. It also is used in multiple modules, meaning +that there are fewer different configuration items. The mapping +between the configuration items is: + +---- +num_sql_socks -> pool { max } +connect_failure_retry_delay -> pool { retry_delay } +lifetime -> pool { lifetime } +max_queries -> pool { uses } +---- + +The pool configuration adds a number of new configuration options, +which allow the administrator to better control how FreeRADIUS uses +SQL connection pools. + +The following parameters have been changed: + +---- +trace -> removed +tracefile -> logfile +---- + +The logfile is intended to log SQL queries performed. If you need to +debug the server, use debugging mode. If `logfile` is set, then +*all* SQL queries will go to `logfile`. + +You can now use a NULL SQL database: + +.Example +---- +driver = rlm_sql_null +---- + +This is an empty driver which will always return "success". It is +intended to be used to replace the `sql_log` module, and to work in +conjunction with the `radsqlrelay` program. Simply take your normal +configuration for raddb/mods-enabled/sql, and set: + +.Example +---- +driver = rlm_sql_null +... +logfile = ${radacctdir}/sql.log +---- + +All of the SQL queries will be logged to that file. The connection +pool does not need to be configured for the `null` SQL driver. It +can be left as-is, or deleted from the SQL configuration file. + + +=== rlm_sql_sybase + +The `rlm_sql_sybase` module has been renamed to `rlm_sql_freetds` +and the old `rlm_sql_freetds` module has been removed. + +`rlm_sql_sybase` used the newer ct-lib API, and `rlm_sql_freetds` +used an older API and was incomplete. + +The new `rlm_sql_freetds` module now also supports database +selection on connection startup so `use` statements no longer +have to be included in queries. + + +=== sql/dialup.conf + +Queries for post-auth and accounting calls have been re-arranged. The +SQL module will now expand the 'reference' configuration item in the +appropriate sub-section, and resolve this to a configuration +item. This behaviour is similar to rlm_linelog. This dynamic +expansion allows for a dynamic mapping between accounting types and +SQL queries. Previously, the mapping was fixed. Any "new" accounting +type was ignored by the module. Now, support for any accounting type +can be added by just adding a new target, as below. + +Queries from v2.x.x may be manually copied to the new v3.0 +`dialup.conf` file (`raddb/sql/main/<dialect>/queries.conf`). +When doing this you may also need to update references to the +accounting tables, as their definitions will now be outside of +the subsection containing the query. + +The mapping from old "fixed" query to new "dynamic" query is as follows: + +---- +accounting_onoff_query -> accounting.type.accounting-on.query +accounting_update_query -> accounting.type.interim-update.query +accounting_update_query_alt +> accounting.type.interim-update.query +accounting_start_query -> accounting.type.start.query +accounting_start_query_alt +> accounting.type.start.query +accounting_stop_query -> accounting.type.stop.query +accounting_stop_query_alt +> accounting.type.stop.query +postauth_query -> post-auth.query +---- + +Alternatively a 2.x.x config may be patched to work with the +3.0 module by adding the following: + +.Example +[source,unlang] +---- + accounting { + reference = "%{tolower:type.%{Acct-Status-Type}.query}" + type { + accounting-on { + query = "${....accounting_onoff_query}" + } + accounting-off { + query = "${....accounting_onoff_query}" + } + start { + query = "${....accounting_start_query}" + query = "${....accounting_start_query_alt}" + } + interim-update { + query = "${....accounting_update_query}" + query = "${....accounting_update_query_alt}" + } + stop { + query = "${....accounting_stop_query}" + query = "${....accounting_stop_query_alt}" + } + } + } + post-auth { + query = "${..postauth_query}" + } +---- + +In general, it is safer to migrate the configuration rather than +trying to "patch" it, to make it look like a v2 configuration. + +Note that the sub-sections holding the queries are labelled +`accounting-on`, and not `accounting_on`. The reason is that the +names of these sections are taken directly from the +`Accounting-Request` packet, and the `Acct-Status-Type` field. +The `sql` module looks at the value of that field, and then looks +for a section of that name, in order to find the query to use. + +That process means that the server can be extended to support any new +value of `Acct-Status-Type`, simply by adding a named sub-section, +and a query. This behavior is preferable to that of v2, which had +hard-coded queries for certain `Acct-Status-Type` values, and was +ignored all other values. + +=== rlm_ldap + +The LDAP module configuration has been substantially changed. Please +read `raddb/mods-available/ldap`. It now uses a connection pool, +just like the SQL module. + +Many of the configuration items remain the same, but they have been +moved into subsections. This change is largely cosmetic, but it makes +the configuration clearer. Instead of having a large set of random +configuration items, they are now organized into logical groups. + +You will need to read your old LDAP configuration, and migrate it +manually to the new configuration. Simply copying the old +configuration WILL NOT WORK. + +Users upgrading from 2.x.x who used to call the ldap module in +`post-auth` should now set `edir_autz = yes`, and remove the `ldap` +module from the `post-auth` section. + +=== rlm_ldap and LDAP-Group + +In 2.x.x the registration of the `LDAP-Group` pair comparison was done +by the last instance of rlm_ldap to be instantiated. In 3.0 this has +changed so that only the default `ldap {}` instance registers +`LDAP-Group`. + +If `<instance>-LDAP-Group` is already used throughout your configuration +no changes will be needed. + +=== rlm_ldap authentication + +In 2.x.x the LDAP module had a `set_auth_type` configuration item, +which forced `Auth-Type := ldap`. This was removed in 3.x.x as it +often did not work, and was not consistent with the rest of the +server. We generally recommend that LDAP should be used as a +database, and that FreeRADIUS should do authentication. + +The only reason to use `Auth-Type := ldap` is when the LDAP server +will not supply the "known good" password to FreeRADIUS, *and* where +the Access-Request contains User-Password. This situation happens +only for Active Directory. If you think you need to force `Auth-Type +:= ldap` in other situations, you are very likely to be wrong. + +The following is an example of what should be inserted into the +`authorize {}` and `authenticate {}` sections of the relevant +virtual-servers, to get functionality equivalent to v2.x: + +.Example +[source,unlang] +---- +authorize { + ... + ldap + if ((ok || updated) && User-Password) { + update control { + Auth-Type := ldap + } +... +} +authenticate { + ... + Auth-Type ldap { + ldap + } +... +} +---- + +=== rlm_eap + +The EAP configuration has been moved from `eap.conf` to +`mods-available/eap`. A new `pwd` subsection has been added for +EAP-PWD. + + +=== rlm_expiration & rlm_logintime + +The rlm_expiration and rlm_logintime modules no longer add a `Reply-Message`, +the same behaviour can be achieved checking the return code of the module and +adding the `Reply-Message` with unlang: + +.Example +[source,unlang] +---- +expiration +if (userlock) { + update reply { + Reply-Message := "Your account has expired" + } +} +---- + + +=== rlm_unix + +The `unix` module does not have an `authenticate` section. So you +cannot set `Auth-Type := System`. The `unix` module has also been +deleted from the examples in `sites-available/`. Listing it there +has been deprecated for many years. + +The PAP module can do crypt authentication. It should be used instead +of Unix authentication. + +The Unix module still can pull the passwords from `/etc/passwd`, or +`/etc/shadow`. This is done by listing it in the `authorize` +section, as is done in the examples in `sites-available/`. However, +some systems using NIS or NSS will not supply passwords to the +`unix` module. For those systems, we recommend putting users and +passwords into a database, instead of relying on `/etc/passwd`. + + +=== rlm_preprocess + +In 2.x.x `huntroups` and `users` files were loaded from default locations +without being configured explicitly. Since 3.x.x you need to set +`huntgroups` and `users` configuration item(s) in module section in order +to get them being processed. + + +== New Modules + +=== rlm_date + +Instances of rlm_date register an xlat method which can translate +integer and date values to an arbitrarily formatted date time +string, or an arbitrarily formated time string to an integer, +depending on the attribute type passed. + + +=== rlm_rest + +The `rest` module is used to translate RADIUS requests into +RESTfull HTTP requests. Currently supported body types are JSON +and POST. + + +=== rlm_unpack + +The `unpack` module is used to turn data buried inside of binary +attributes. e.g. if we have `Class = 0x00000001020304` then: + +.Example +[source,unlang] +---- +Tmp-Integer-0 := "%{unpack:&Class 4 short}" +---- + +will unpack octets 4 and 5 as a "short", which has value 0x0304. +All integers are assumed to be in network byte order. + + +=== rlm_yubikey + +The `yubikey` module can be used to forward yubikey OTP token +values to a Yubico validation server, or decrypt the token +using a PSK. + + +== Deleted Modules + +The following modules have been deleted, and are no longer supported +in Version 3. If you are using one of these modules, your +configuration can probably be changed to not need it. Otherwise email +the freeradius-devel list, and ask about the module. + + +=== rlm_acct_unique + +This module has been replaced by the "acct_unique" policy. See +raddb/policy.d/accounting. + +The method for calculating the value of acct_unique has changed. +However, as this method was configurable, this change should not +matter. The only issue is in having a v2 and v3 server writing to the +same database at the same time. They will calculate different values +for Acct-Unique-Id. + + +=== rlm_acctlog + +You should use rlm_linelog instead. That module has a superset of the +acctlog functionality. + + +=== rlm_attr_rewrite + +The attr_rewrite module looked for an attribute, and then re-wrote it, +or created a new attribute. All of that can be done in "unlang". + +A sample configuration in "unlang" is: + +.Example +[source,unlang] +---- +if (request:Calling-Station-Id) { + update request { + Calling-Station-Id := "...." + } +} +---- + +We suggest updating all uses of attr_rewrite to use unlang instead. + + +=== rlm_checkval + +The checkval module compared two attributes. All of that can be done in "unlang": + +.Example +[source,unlang] +---- +if (&request:Calling-Station-Id == &control:Calling-Station-Id) { + ok +} +---- + +We suggest updating all uses of checkval to use unlang instead. + + +=== rlm_dbm + +No one seems to use it. There is no sample configuration for it. +There is no speed advantage to using it over the "files" module. +Modern systems are fast enough that 10K entries can be read from the +"users" file in about 10ms. If you need more users than that, use a +real database such as SQL. + + +=== rlm_fastusers + +No one seems to use it. It has been deprecated since Version 2.0.0. +The "files" module was rewritten so that the "fastusers" module was no +longer necessary. + + +=== rlm_policy + +No one seems to use it. Almost all of its functionality is available +via `unlang`. + + +=== rlm_sim_files + +The rlm_sim_files module has been deleted. It was never marked "stable", +and was never used in a production environment. There are better ways +to test EAP. + +If you want similar functionality, see rlm_passwd. It can read CSV +files, and create attributes from them. + + +=== rlm_sql_log + +This has been replaced with the "null" sql driver. See +`raddb/mods-available/sql` for an example configuration. + +The main SQL module has more functionality than rlm_sql_log, and +results in less code in the server. + +== Other Functionality + +The following is a list of new / changed functionality. + +=== RadSec + +RadSec (or RADIUS over TLS) is now supported. RADIUS over bare TCP +is also supported, but is recommended only for secure networks. + +See `sites-available/tls` for complete details on using TLS. The server +can both receive incoming TLS connections, and also originate outgoing +TLS connections. + +The TLS configuration is taken from the old EAP-TLS configuration. It +is largely identical to the old EAP-TLS configuration, so it should be +simple to use and configure. It re-uses much of the EAP-TLS code, +so it is well-tested and reliable. + +Once RadSec is enabled, normal debugging mode will not work. This is +because the TLS code requires threading to work properly. Instead of doing: + +.Example +[source,shell] +---- +radiusd -X +---- + +you will need to do: + +.Example +[source,shell] +---- +radiusd -fxx -l stdout +---- + +That's the price to pay for using RadSec. This limitation may be +lifted in a future version of the server. + + +=== PAP and User-Password + +From version 3.0 onwards the server no longer supports authenticating +against a cleartext password in the 'User-Password' attribute. Any +occurences of this (for instance, in the users file) should now be changed +to 'Cleartext-Password' instead. + +e.g. change entries like this: + +---- +bob User-Password == "hello" +---- + +to ones like this: + +---- +bob Cleartext-Password := "hello" +---- + +If this is not done, authentication will likely fail. The server will +also print a helpful message in debugging mode. + +If it really is impossible to do this, the following unlang inserted above +the call to the pap module may be used to copy User-Password to the correct +attribute: + +.Example +[source,unlang] +---- +if (!control:Cleartext-Password && control:User-Password) { + update control { + Cleartext-Password := "%{control:User-Password}" + } +} +---- + +However, this should only be seen as a temporary, not permanent, fix. +It is better to fix your databases to use the correct configuration. + + +== Unlang + + +The unlang policy language is compatible with v2, but has a number of +new features. See `man unlang` for complete documentation. + + +=== Errors + +Many more errors are caught when the server is starting up. Syntax +errors in `unlang` are caught, and a helpful error message is +printed. The error message points to the exact place where the error +occurred: + +---- + ./raddb/sites-enabled/default[230]: Parse error in condition + ERROR: if (User-Name ! "bob") { + ERROR: ^ Invalid operator +---- + +`update` sections are more generic. Instead of doing `update +reply`, you can do the following: + +.Example +[source,unlang] +---- +update { + reply:Class := 0x0000 + control:Cleartext-Password := "hello" +} +---- + +This change means that you need fewer `update` sections. + + +=== Comparisons + +Attribute comparisons can be done via the `&` operator. When you +needed to compare two attributes, the old comparison style was: + +.Example +[source,unlang] +---- +if (User-Name == "%{control:Tmp-String-0}") { +---- + +This syntax is inefficient, as the `Tmp-String-0` attribute would be +printed to an intermediate string, causing unnecessary work. You can +now instead compare the two attributes directly: + +.Example +[source,unlang] +---- +if (&User-Name == &control:Tmp-String-0) { +---- + +See `man unlang` for more details. + +=== Casts + +Casts are now permitted. This allows you to force type-specific +comparisons: + +.Example +[source,unlang] +---- +if (<ipaddr>"%{sql: SELECT...}" == 127.0.0.1) { +---- + +This forces the string returned by the SELECT to be treated as an IP +address, and compare to `127.0.0.1`. Previously, the comparison +would have been done as a simple string comparison. + + +=== Networks + +IP networks are now supported: + + if (127.0.0.1/32 == 127.0.0.1) { + +Will be `true`. The various comparison operators can be used to +check IP network membership:: + +.Example +[source,unlang] +---- +if (127/8 > 127.0.0.1) { +---- + +Returns `true`, because `127.0.0.1` is within the `127/8` +network. However, the following comparison will return `false`:: + +.Example +[source,unlang] +---- +if (127/8 > 192.168.0.1) { +---- + +because `192.168.0.1` is outside of the `127/8` network. + + +=== Optimization + +As `unlang` is now pre-compiled, many compile-time optimizations are +done. This means that the debug output may not be exactly the same as +what is in the configuration files: + + if (0 && (User-Name == "bob')) { + +The result will always be `false`, as the `if 0` prevents the +following `&& ...` from being evaluated. + +Not only that, but the entire contents of that section will be ignored +entirely: + +.Example +[source,unlang] +---- +if (0) { + this_module_does_not_exist + and_this_one_does_not_exist_either +} +---- + +In v2, that configuration would result in a parse error, as there is +no module called `this_module_does_not_exist`. In v3, that text is +ignored. This ability allows you to have dynamic configurations where +certain parts are used (or not) depending on compile-time configuration. + +Similarly, conditions which always evaluate to `true` will be +optimized away: + + +.Example +[source,unlang] +---- +if (1) { + files +} +---- + +That configuration will never show the `if (1)` output in debugging mode. + +=== Dialup_admin + +The dialup_admin directory has been removed. No one stepped forward +to maintain it, and the code had not been changed in many years. + diff --git a/doc/antora/modules/unlang/.gitignore b/doc/antora/modules/unlang/.gitignore new file mode 100644 index 0000000..c5722d7 --- /dev/null +++ b/doc/antora/modules/unlang/.gitignore @@ -0,0 +1 @@ +!*.adoc diff --git a/doc/antora/modules/unlang/nav.adoc b/doc/antora/modules/unlang/nav.adoc new file mode 100644 index 0000000..77be328 --- /dev/null +++ b/doc/antora/modules/unlang/nav.adoc @@ -0,0 +1,51 @@ +* xref:index.adoc[Unlang Policy Language] + +** xref:list.adoc[Attribute Lists] +** xref:attr.adoc[Attribute References] +** xref:return_codes.adoc[Return Codes] + +** xref:keywords.adoc[Keywords] +*** xref:break.adoc[break] +*** xref:case.adoc[case] +*** xref:else.adoc[else] +*** xref:elsif.adoc[elsif] +*** xref:foreach.adoc[foreach] +*** xref:group.adoc[group] +*** xref:if.adoc[if] +*** xref:load-balance.adoc[load-balance] +*** xref:redundant-load-balance.adoc[redundant-load-balance] +*** xref:redundant.adoc[redundant] +*** xref:return.adoc[return] +*** xref:switch.adoc[switch] +*** xref:update.adoc[update] + +** xref:module.adoc[Modules] +*** xref:module_method.adoc[Module Methods] +*** xref:module_builtin.adoc[Built-in Modules] + +** xref:type/index.adoc[Data Types] +*** xref:type/index.adoc[List of Data Types] +*** xref:type/ip.adoc[IP Addresses] +*** xref:type/numb.adoc[Numbers] +*** xref:type/string/single.adoc[Single Quoted Strings] +*** xref:type/string/double.adoc[Double Quoted Strings] +*** xref:type/string/backticks.adoc[Backtick-quoted string] +*** xref:type/string/unquoted.adoc[Unquoted Strings] + +** xref:condition/index.adoc[Conditional Expressions] +*** xref:condition/cmp.adoc[Comparisons] +*** xref:condition/operands.adoc[Operands] +*** xref:condition/return_code.adoc[The Return Code Operator] +*** xref:condition/eq.adoc[The '==' Operator] +*** xref:condition/and.adoc[The '&&' Operator] +*** xref:condition/or.adoc[The '||' Operator] +*** xref:condition/not.adoc[The '!' Operator] +*** xref:condition/para.adoc[The '( )' Operator] +*** xref:condition/regex.adoc[Regular Expressions] + +** xref:xlat/index.adoc[String Expansion] +*** xref:xlat/alternation.adoc[Alternation Syntax] +*** xref:xlat/builtin.adoc[Built-in Expansions] +*** xref:xlat/character.adoc[Single Letter Expansions] +*** xref:xlat/attribute.adoc[Attribute References] +*** xref:xlat/module.adoc[Module References] diff --git a/doc/antora/modules/unlang/pages/attr.adoc b/doc/antora/modules/unlang/pages/attr.adoc new file mode 100644 index 0000000..70afce4 --- /dev/null +++ b/doc/antora/modules/unlang/pages/attr.adoc @@ -0,0 +1,77 @@ += &Attribute References + +.Syntax +[source,unlang] +---- +[&]Attribute-Name +---- + +The `&Attribute-Name` operator returns a reference to the named +attribute. + +When used as an existence check in a condition, the condition +evaluates to `true` if the attribute exists. Otherwise, the condition +evaluates to `false`. + +When used elsewhere, such as in xref:switch.adoc[switch], it returns +the value of the named attribute. + +.Examples +[source,unlang] +---- +&User-Name +&NAS-IP-Address +---- + +== Lists + +The attribute reference can also be qualified with a +xref:list.adoc[list] reference. When no list is given, the server +looks in the input packet list for the named attribute. + +.Examples + +[source,unlang] +---- +&request:User-Name +&reply:NAS-IP-Address +---- + +== Array References + +.Syntax +[source,unlang] +---- +&Attribute-Name[<integer>] +---- + +When an attribute appears multiple times in a list, this syntax allows +you to address the attributes as if they were array entries. The +`<integer>` value defines which attribute to address. The `[0]` value +refers to the first attributes, `[1]` refers to the second attribute, +etc. + +.Examples +[source,unlang] +---- +&EAP-Message[1] +&reply:NAS-IP-Address[2] +---- + +== Removing ambuguity from the configuration files + +The server does not use the `&` character to distinguish attribute names +from other strings. + +Without the `&`, it is more difficult to parse the configuration file +clearly. You could interpret a string as `hello-there` +either as a literal string "hello-there", or as a reference to an +attribute named `hello-there`. + +Adding the leading `&` character means that attribute references are +now easily distinguishable from literal strings. The use of the leading +`&` character is highly recommended. + + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/break.adoc b/doc/antora/modules/unlang/pages/break.adoc new file mode 100644 index 0000000..01783ea --- /dev/null +++ b/doc/antora/modules/unlang/pages/break.adoc @@ -0,0 +1,28 @@ += The break statement + +.Syntax +[source,unlang] +---- +break +---- + +The `break` statement is used to exit an enclosing +xref:foreach.adoc[foreach] loop. The `break` statement only be used +inside of a xref:foreach.adoc[foreach] loop. + +.Example +[source,unlang] +---- +foreach &Class { + if (&Foreach-Variable-0 == 0xabcdef) { + break + } + + update reply { + Reply-Message += "Contains %{Foreach-Variable-0}" + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/case.adoc b/doc/antora/modules/unlang/pages/case.adoc new file mode 100644 index 0000000..ba2b5fe --- /dev/null +++ b/doc/antora/modules/unlang/pages/case.adoc @@ -0,0 +1,44 @@ += The case Statement + +.Syntax +[source,unlang] +---- +case [ <match> ] { + [ statements ] +} +---- + +The `case` statement is used to match data inside of a +xref:switch.adoc[switch] statement. The `case` statement cannot be used +outside of a xref:switch.adoc[switch] statement. + + +The `<match>` text can be an attribute reference such as `&User-Name`, +or it can be a xref:type/string/index.adoc[string]. If the match +text is a dynamically expanded string, then the match is performed on +the output of the string expansion. + +If no `<match>` text is given, it means that the `case` statement is +the "default" and will match all which is not matched by another +`case` statement inside of the same xref:switch.adoc[switch]. + +.Example +[source,unlang] +---- +switch &User-Name { + case "bob" { + reject + } + + case &Filter-Id { + reject + } + + case { + ok + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/and.adoc b/doc/antora/modules/unlang/pages/condition/and.adoc new file mode 100644 index 0000000..50b3deb --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/and.adoc @@ -0,0 +1,21 @@ += The && Operator + +.Syntax +[source,unlang] +---- +(condition-1 && condition-2) +---- + +The `&&` operator performs a short-circuit "and" evaluation of the +two conditions. This operator evaluates _condition-1_ and returns +`false` if _condition-1_ returns `false`. Only if _condition-1_ +returns `true` is _condition-2_ evaluated and its result returned. + +.Examples +[source,unlang] +---- +if (&User-Name && &EAP-Message) { ... +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/cmp.adoc b/doc/antora/modules/unlang/pages/condition/cmp.adoc new file mode 100644 index 0000000..4138b86 --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/cmp.adoc @@ -0,0 +1,104 @@ += Comparisons + +.Syntax +[source,unlang] +---- +lhs OP rhs +---- + +The most common use-case for conditions is to perform comparisons. +The `lhs` and `rhs` of a conditional comparison can be +xref:attr.adoc[&Attribute-Name] or xref:type/index.adoc[data]. The +the `OP` is an operator, commonly `==` or `\<=`. It is used to +control how the two other portions of the condition are compared. + +== The Comparison Operators + +The comparison operators are given below. + +[options="header"] +|===== +| Operator | Description +| < | less than +| \<= | less than or equals +| == | equals +| != | not equals +| >= | greater than or equals +| > | greater than +| xref:condition/regex.adoc[=~] | regular expression matches +| xref:condition/regex.adoc[!~] | regular expression does not match +|===== + +The comparison operators perform _type-specific_ comparisons. The +only exceptions are the xref:condition/regex.adoc[regular expression] operators, +which interpret the `lhs` as a printable string, and the `rhs` as a +regular expression. + +== IP Address Comparisons + +The type-specific comparisons operate as expected for most data types. +The only exception is data types that are IP addresses or IP address +prefixes. For those data types, the comparisons are done via the +following rules: + +* Any unqualified IP address is assumed to have a /32 prefix (IPv4) + or a /128 prefix (IPv6). + +* If the prefixes of the left and right sides are equal, then the comparisons + are performed on the IP address portion. + +* If the prefixes of the left and right sides are not equal, then the + comparisons are performed as _set membership checks_. + +The syntax allows conditions such as `192.0.2.1 < 192.0.2/24`. This +condition will return `true`, as the IP address `192.0.2.1' is within +the network `192.0.2/24`. + +== Casting + +In some situations, it is useful to force the left side to be +interpreted as a particular data type. + +[NOTE] +The data types used by the cast *must* be a type taken from the RADIUS +dictionaries, e.g., `ipaddr`, `integer`, etc. These types are not the +same as the xref:type/index.adoc[data types] used in the +configuration files. + +.Syntax +[source,unlang] +---- +<cast>lhs OP rhs +---- + +The `cast` text can be any one of the standard RADIUS dictionary data +types, as with the following example: + +.Example +[source,unlang] +---- +<ipaddr>&Class == 127.0.0.1 +---- + +In this example, the `Class` attribute is treated as if it was an IPv4 +address and is compared to the address `127.0.0.1` + +Casting is most useful when the left side of a comparison is a +dynamically expanded string. The cast ensures that the comparison is +done in a type-safe manner, instead of performing a string comparison. + +.Example +[source,unlang] +---- +<integer>`/bin/echo 00` == 0 +---- + +In this example, the string output of the `echo` program is interpreted as an +integer. It is then compared to the right side via integer +comparisons. Since the integer `00` is equivalent to the integer `0`, +the comparison will match. If the comparison had been performed via +string equality checks, then the comparison would fail, because the +strings `00` and `0` are different. + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/eq.adoc b/doc/antora/modules/unlang/pages/condition/eq.adoc new file mode 100644 index 0000000..d9e51f3 --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/eq.adoc @@ -0,0 +1,30 @@ += The == Operator + +.Syntax +`(data-1 == data-2)` + +The `==` operator compares the result of evaluating `data-1` and +`data-2`. As discussed in xref:type/index.adoc[Data Types], the `data-1` +field may be interpreted as a reference to an attribute. + +The `data-2` field is interpreted in a type-specific manner. For +example, if `data-1` refers to an attribute of type `ipaddr`, then +`data-2` is evaluated as an IP address. If `data-1` refers to an +attribute of type `integer`, then `data-2` is evaluated as an integer +or as a named enumeration defined by a `VALUE` statement in a +dictionary. Similarly, if `data-1` refers to an attribute of type +`date`, then `data-2` will be interpreted as a date string. + +If the resulting data evaluates to be the same, then the operator +returns `true`; otherwise, it returns `false`. + +.Example +[source,unlang] +---- +if (User-Name == "bob") { + ... +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/index.adoc b/doc/antora/modules/unlang/pages/condition/index.adoc new file mode 100644 index 0000000..b9d9d5f --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/index.adoc @@ -0,0 +1,85 @@ += Conditional Expressions + +Conditions are evaluated when parsing xref:if.adoc[if] and +xref:elsif.adoc[elsif] statements. These conditions allow the server to +make complex decisions based on one of a number of possible criteria. + +.Syntax +[source,unlang] +---- +if ( condition ) { ... + +elsif ( condition ) { ... +---- + +Conditions are expressed using the following syntax: + +[options="header"] +|===== +| Syntax | Description +| xref:attr.adoc[&Attribute-Name] | Check for attribute existence. +| xref:condition/return_code.adoc[rcode] | Check return code of a previous module. +| xref:condition/operands.adoc[data] | Check value of data. +| xref:condition/cmp.adoc[lhs OP rhs] | Compare two kinds of data. +| xref:condition/para.adoc[( condition )] | Check sub-condition +| xref:condition/not.adoc[! condition] | Negate a conditional check +| xref:condition/and.adoc[( condition ) && ...] | Check a condition AND the next one +| xref:condition/or.adoc[( condition ) \|\| ...] | Check a condition OR the next one +|===== + + +.Examples +[source,unlang] +---- +if ( &User-Name == "bob" ) { + ... +} + +if ( &Framed-IP-Address == 127.0.0.1 ) { + ... +} + +if ( &Calling-Station-Id == "%{sql:SELECT ...}" ) { + ... +} +---- + +== Load-time Syntax Checks + +The server performs a number of checks when it loads the configuration +files. Unlike version 2, all of the conditions are syntax checked +when the server loads. This checking greatly aids in creating +configurations that are correct. Where the configuration is +incorrect, a descriptive error is produced. + +This error contains the filename and line number of the syntax error. +In addition, it will print out a portion of the line that caused the +error and will point to the exact character where the error was seen. +These descriptive messages mean that most errors are easy to find and fix. + +== Load-time Optimizations + +The server performs a number of optimizations when it loads the +configuration files. Conditions that have static values are +evaluated and replaced with the result of the conditional comparison. + +.Example +[source,unlang] +---- +if ( 0 == 1 ) { + ... +} +---- + +The condition `0 == 1` is static and will evaluate to `false`. Since +it evaluates to `false`, the configuration inside of the `if` +statement is ignored. Any modules referenced inside of the `if` +statement will not be loaded. + +This optimization is most useful for creating configurations that +selectively load (or not) certain policies. If the condition above +was used in version 2, then the configuration inside of the `if` statement +would be loaded, even though it would never be used. + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/not.adoc b/doc/antora/modules/unlang/pages/condition/not.adoc new file mode 100644 index 0000000..bde038e --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/not.adoc @@ -0,0 +1,19 @@ += The ! Operator + +.Syntax +[source,unlang] +---- +! condition +---- + +The `!` operator negates the result of the following condition. It +returns `true` when _condition_ returns `false`. It returns `false` +when _condition_ returns `true`. + +.Examples + +`(! (foo == bar))` + +`! &User-Name` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/operands.adoc b/doc/antora/modules/unlang/pages/condition/operands.adoc new file mode 100644 index 0000000..4a2d00b --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/operands.adoc @@ -0,0 +1,37 @@ += Operands + +.Syntax +[source,unlang] +---- +string +integer +"double-quoted string" +'single-quoted string' +`back-quoted string` +---- + +Any text not matching xref:attr.adoc[&Attribute-Name] or +xref:condition/return_code.adoc[Return Code] is interpreted as a value for a +particular xref:type/index.adoc[data type]. + +Double-quoted strings and back-quoted strings are dynamically expanded +before the condition is evaluated. Single-quoted strings are static +literals and are not dynamically expanded. + +When used as an existence check, the condition evaluates to `true` if +the data is non-zero. Otherwise, the condition evaluates to `false`. + +For integer existence checks, `0` is `false`; all other values are `true`. + +For string existence checks, an empty string is `false`. All other +strings are `true`. + +All other data types are disallowed in existence checks. + +.Examples + +`"hello there"` + +`5` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/or.adoc b/doc/antora/modules/unlang/pages/condition/or.adoc new file mode 100644 index 0000000..80c2cb4 --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/or.adoc @@ -0,0 +1,21 @@ += The || Operator + +.Syntax +[source,unlang] +---- +(expression-1 || expression-2) +---- + +The `||` operator performs a short-circuit "or" evaluation of the two +expressions. This operator evaluates _condition-1_ and returns `true` +if _condition-1_ returns true. Only if _condition-1_ returns `false` +is _condition-2_ evaluated and its result returned. + +.Examples +[source,unlang] +---- +if (&User-Name || &NAS-IP-Address) { ... +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/para.adoc b/doc/antora/modules/unlang/pages/condition/para.adoc new file mode 100644 index 0000000..bdb3f01 --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/para.adoc @@ -0,0 +1,19 @@ += The ( ) Operator + +.Syntax +[source,unlang] +---- +( condition ) +---- + +The `( )` operator returns the result of evaluating the given +`condition`. It is used to clarify policies or to explicitly define +conditional precedence. + +.Examples + +`(foo)` + +`(bar || (baz && dub))` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/regex.adoc b/doc/antora/modules/unlang/pages/condition/regex.adoc new file mode 100644 index 0000000..038faa6 --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/regex.adoc @@ -0,0 +1,180 @@ += Regular Expressions + +.Syntax +==== +[source,unlang] +---- +(<subject> =~ /<pattern>/) +(<subject> =~ /<pattern>/[imsux]) + +(<subject> !~ /<pattern>/) +(<subject> !~ /<pattern>/[imsux]) +---- +==== + +== Matching +The regular expression operators perform regular expression matching +on the data. The `<subject>` field can be an attribute reference or data, +as with the other xref:condition/cmp.adoc[comparison] operators. The `/<pattern>/` +field must be a valid regular expression. + +The `=~` operator evaluates to `true` when `data` matches the +`/<pattern>/`. Otherwise, it evaluates to `false`. + +The `!~` operator evaluates to `true` when `data` does not match the +`/<pattern>/`. Otherwise, it evaluates to `true`. + +The regular expression comparison is performed on the _string representation_ +of the left side of the comparison. That is, if the left side is an +xref:type/numb.adoc[integer], the regular expression will behave is if the +value `0` was the literal string `"0"`. Similarly, if the left side is an +xref:attr.adoc[&Attribute-Name], then the regular expression will behave is if +the attribute was printed to a string, and the match was performed on the +resulting string. + +.Checking if the `User-Name` attribute contains a realm of example.com +==== +[source,unlang] +---- +if (&User-Name =~ /@example\.com$/) { + ... +} +---- +==== + +== Dialects + +The syntax of the regular expression is defined by the regular +expression library available on the local system. + +FreeRADIUS currently supports: + +* link:https://www.pcre.org/original/doc/html/[libpcre] and +link:https://www.pcre.org/current/doc/html/[libpcre2] both of which +provide +link:https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions[Perl +Compatible Regular expressions]. +* Regex support provided by the local libc implementation, usually +link:http://en.wikipedia.org/wiki/Regular_expression#POSIX_basic_and_extended[ +Posix regular expressions]. + +[TIP] +==== +Use the output of `radiusd -Xxv` to determine which regular expression library is in use. + +.... +... +Debug : regex-pcre : no +Debug : regex-pcre2 : yes +Debug : regex-posix : no +Debug : regex-posix-extended : no +Debug : regex-binsafe : yes +... +Debug : pcre2 : 10.33 (2019-04-16) - retrieved at build time +.... +==== + +[WARNING] +==== +Depending on the regular expression library or libc implementation the server +was built against, the pattern matching function available may not be binary +safe (see `regex-binsafe` in the output of `radiusd -Xxv`). + +If a binary safe regex match function is not available, and a match is +attempted against a subject that contains one or more `NUL` ('\0') bytes, the +match will be aborted, any condition that uses the result will evaluate to false, +and a warning will be emitted. +==== + +== Flags + +The regular expression `/<pattern>/` may be followed by one or more flag +characters. Again, which flags are available depends on the regular expression +library the server was built with. Multiple flags may be specified per +`/pattern/`. + +.Flags and their uses + +[options="header"] +|===== +| Flag Character | Available with | Effect +| `i` | All | Enable case-insensitive matching. +| `m` | All | '^' and '$' match newlines within the subject. +| `s` | libpcre[2] | '.' matches anything, including newlines. +| `u` | libpcre[2] | Treats subjects as UTF8. Invalid UTF8 + sequences will result in the match failing. + |`x` | libpcre[2] | Allows comments in expressions by ignoring + whitespace, and text between '#' and the next + newline character. +|===== + +== Subcapture groups + +When the `=~` or `!~` operators are used, then parentheses in the regular +expression will sub capture groups, which contain part of the subject string. + +The special expansion `%{0}` expands to the portion of the subject that +matched. The expansions + +`%{1}`..`%{32}` expand to the contents of any subcapture groups. + +When using libpcre[2], named capture groups may also be accessed using the +built-in expansion + +`%{regex:<named capture group>}`. + +Please see the xref:xlat/builtin.adoc#_0_32[xlat documentation] for +more information on regular expression matching. + +.Extracting the 'user' portion of a realm qualified string +==== +[source,unlang] +---- +if (&User-Name =~ /^(.*)@example\.com$/) { + update reply { + Reply-Message := "Hello %{1}" + } +} +---- +==== + +== Pre-Compiled vs Runtime Compiled + +When the server starts any regular expressions comparisons it finds will be +pre-compiled, and if support is available, JIT'd (converted to machine code) +to ensure fast execution. + +If a pattern contains a xref:xlat/index.adoc[string expansion], the pattern +cannot be compiled on startup, and will be compiled at runtime each time the +expression is evaluated. The server will also turn off JITing for runtime +compiled expressions, as the overhead is greater than the time that would be +saved during evaluation. + +.A runtime compiled regular expression +==== +[source,unlang] +---- +if (&User-Name =~ /^@%{Tmp-String-0}$/) { + ... +} +---- +==== + +To ensure optimal performance you should limit the number of patterns +containing xref:xlat/index.adoc[string expansions], and if using PCRE, combine +multiple expressions operating on the same subject into a single expression +using the PCRE alternation '|' operator. + +.Using multiple string expansions and the PCRE alternation operator +==== +[source,unlang] +---- +if (&User-Name =~ /^@(%{Tmp-String-0}|%{Tmp-String-1})$/) { + ... +} +---- +==== + + +// Licenced under CC-by-NC 4.0. +// Copyright (C) 2020 Network RADIUS SAS. +// Copyright (C) 2019 Arran Cudbard-Bell <a.cudbardb@freeradius.org> +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/condition/return_codes.adoc b/doc/antora/modules/unlang/pages/condition/return_codes.adoc new file mode 100644 index 0000000..ebc49ed --- /dev/null +++ b/doc/antora/modules/unlang/pages/condition/return_codes.adoc @@ -0,0 +1,35 @@ += The return code Operator + +.Syntax +[source,unlang] +---- +rcode +---- + +The Unlang interpreter tracks the return code of any module, string expansion +or keyword that has been called. + +This return code can be checked in any condition. If the saved return code +matches the `code` given here, then the condition evaluates to `true`. +Otherwise, it evaluates to `false`. + +rcodes cannot be set in a condition. rcodes cannot be compared with anything else. + +The list of valid return codes is as follows: + +.Return Codes + +include::partial$rcode_table.adoc[] + +.Examples + +[source,unlang] +---- +sql +if (notfound) { + ... +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/default.adoc b/doc/antora/modules/unlang/pages/default.adoc new file mode 100644 index 0000000..3b298f6 --- /dev/null +++ b/doc/antora/modules/unlang/pages/default.adoc @@ -0,0 +1,47 @@ += The case Statement + +.Syntax +[source,unlang] +---- +case [ <match> ] { + [ statements ] +} +---- + +The `case` statement is used to match data inside of a +xref:switch.adoc[switch] statement. The `case` statement cannot be used +outside of a xref:switch.adoc[switch] statement. + + +The `<match>` text can be an attribute reference such as `&User-Name`, +or it can be a xref:type/string/index.adoc[string]. If the match +text is a dynamically expanded string, then the match is performed on +the output of the string expansion. + +The keyword `default` can be used to specify the default action to +take inside of a xref:switch.adoc[switch] statement. + +If no `<match>` text is given, it means that the `case` statement is +the "default" and will match all which is not matched by another +`case` statement inside of the same xref:switch.adoc[switch]. + +.Example +[source,unlang] +---- +switch &User-Name { + case "bob" { + reject + } + + case &Filter-Id { + reject + } + + default { + ok + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/else.adoc b/doc/antora/modules/unlang/pages/else.adoc new file mode 100644 index 0000000..a795d0e --- /dev/null +++ b/doc/antora/modules/unlang/pages/else.adoc @@ -0,0 +1,30 @@ += The else Statement + +.Syntax +[source,unlang] +---- +if (condition) { + [ statements ] +} +else { + [ statements ] +} +---- + +An xref:if.adoc[if] statement can have an `else` clause. If _condition_ +evaluates to `false`, the statements in the xref:if.adoc[if] subsection are skipped +and the statements within the `else` subsection are executed. + +.Example +[source,unlang] +---- +if (&User-Name == "bob") { + reject +} +else { + ok +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/elsif.adoc b/doc/antora/modules/unlang/pages/elsif.adoc new file mode 100644 index 0000000..ff5799c --- /dev/null +++ b/doc/antora/modules/unlang/pages/elsif.adoc @@ -0,0 +1,43 @@ += The elsif Statement + +.Syntax +[source,unlang] +---- +if (condition-1) { + [ statements-1 ] +} +elsif (condition-2) { + [ statements-2 ] +} +else { + [ statements-3 ] +} +---- + +An `elsif` statement is used to evaluate a subsequent +xref:condition/index.adoc[condition] after a preceding xref:if.adoc[if] statement +evaluates to `false`. In the example above, when _condition-1_ +evaluates to false, then _statements-1_ are skipped and _condition-2_ +is checked. When _condition-2_ evaluates true, then _statements-2_ +are executed. When _condition-2_ evaluates false, then +_statements-2_ are skipped and _statements-3_ are executed. + +As with xref:if.adoc[if], an `elsif` clause does not need to be followed by +an xref:else.adoc[else] statement. However, any xref:else.adoc[else] statement +must be the last statement in an `elsif` chain. An arbitrary number of +`elsif` statements can be chained together to create a series of +conditional checks and statements. + +.Example +[source,unlang] +---- +if (&User-Name == "bob") { + reject +} +elsif (&User-Name == "doug") { + ok +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/foreach.adoc b/doc/antora/modules/unlang/pages/foreach.adoc new file mode 100644 index 0000000..6ed3ddf --- /dev/null +++ b/doc/antora/modules/unlang/pages/foreach.adoc @@ -0,0 +1,40 @@ += The foreach Statement + +.Syntax +[source,unlang] +---- +foreach <attribute-reference> { + [ statements ] +} +---- + +The `foreach` statement loops over a set of attributes as given by +`<attribute-reference>`. The loop can be exited early by using the +xref:break.adoc[break] keyword. + +<attribute-reference>:: + +The xref:attr.adoc[attribute reference] which will will be looped +over. The reference can be to one attribute, to an array, a child, or +be a subset. + +Inside of the `foreach` block, the attribute that is being looped over +can be referenced as `Foreach-Variable-0`, through +`Foreach-Variable-9`. The last digit is the depth of the loop, +starting at "0". The loops can be nested up to eight (8) deep, though +this is not recommended. + +The attributes being looped over cannot be modified or deleted. + +.Example +[source,unlang] +---- +foreach &Class { + update reply { + Reply-Message += "Contains %{Foreach-Variable-0}" + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/group.adoc b/doc/antora/modules/unlang/pages/group.adoc new file mode 100644 index 0000000..98801fd --- /dev/null +++ b/doc/antora/modules/unlang/pages/group.adoc @@ -0,0 +1,39 @@ += The group Statement + +.Syntax +[source,unlang] +---- +group { + [ statements ] +} +---- + +The `group` statement collects a series of statements into a list. +The default processing sections of the server (`authorize`, +`accounting`, etc.) are also `group` statements. Those sections are +given different name for management reasons, but they behave +internally exactly like a `group`. + +[ statements ]:: The `unlang` commands which will be executed. + +All of the statements inside of the `group` are executed in sequence. +The `group` statement is not normally used, as the statements within +it can just be placed inside of the enclosing section. However, the +`group` statement is included in the `unlang` syntax for completeness. + +.Examples + +[source,unlang] +---- +group { + sql + ldap + file + if (updated) { + ... + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/if.adoc b/doc/antora/modules/unlang/pages/if.adoc new file mode 100644 index 0000000..ea549ef --- /dev/null +++ b/doc/antora/modules/unlang/pages/if.adoc @@ -0,0 +1,29 @@ += The if Statement + +.Syntax +[source,unlang] +---- +if (condition) { + [ statements ] +} +---- + +.Description +The `if` statement evaluates a xref:condition/index.adoc[condition]. When the +_condition_ evaluates to `true`, the statements within the subsection +are executed. When the _condition_ evaluates to `false`, those +statements are skipped. + +An `if` statement can optionally be followed by an xref:else.adoc[else] or +an xref:elsif.adoc[elsif] statement. + +.Example +[source,unlang] +---- +if (&User-Name == "bob") { + reject +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/index.adoc b/doc/antora/modules/unlang/pages/index.adoc new file mode 100644 index 0000000..fc812f8 --- /dev/null +++ b/doc/antora/modules/unlang/pages/index.adoc @@ -0,0 +1,162 @@ += Unlang Policy Language + +The server supports a simple processing language called "Unlang", +which is short for "un-language". The original intention of using an +"un-language" was to avoid creating yet another programming language. +Instead, the `unlang` syntax allows for simple _if / then / else_ +checks, and attribute editing. It does not support recursion, +subroutines, or more complex flow controls. + +Where more complicated functionality is required, we recommend using +the `lua`, `perl` or `python` modules. Those modules allow the insertion of +full-featured scripts at any point in the packet processing. + +NOTE: The documentation is this directory is _reference_ +documentation. That is, it describes the syntax of `unlang` keywords, +using minimal examples. The reference documentation does not, +however, describe _when_ to use the keywords, or _how_ to create +policies. Please see the xref:howto:index.adoc[howto] directory for +more in-depth "how to" guides. + +The documentation is organized so that each item is on its own page. +The page beings with a description of the item, followed by some text +explaining what the item does. The page concludes with one or more +examples of using the item in `unlang` policies. + +The `unlang` processing can be split into some high-level concepts. + +== Keywords + +xref:keywords.adoc[Keywords], which are the basic statements of the +language, e.g., xref:load-balance.adoc[load-balance], +xref:if.adoc[if], xref:else.adoc[else], etc. + +.Example +[source,unlang] +---- +load-balance { + sql1 + sql2 + sql3 +} +---- + +== Conditional Expressions + +xref:condition/index.adoc[Conditional expressions], which are used to check +if conditions evaluate to _true_ or _false_. Conditional expressions +can be used to control the flow of processing. + +.Example +[source,unlang] +---- +if ((&User-Name == "bob") && (&Calling-Station-Id == "00:01:03:04:05")) { + ... +} +---- + +== Update Statements + +xref:update.adoc[update] statements are used to edit attributes and +lists of attributes. + +Most request packets will result in reply packets that contain +additional information for the requestor. The `update` section allows +policies to add attributes to requests, replies, or to other places. + +.Example +[source,unlang] +---- +update reply { + &Session-Timeout := 3600 + &Framed-IP-Address := 192.0.2.4 +} +---- + +== String Expansions + +xref:xlat/index.adoc[String expansion] Using `%{...}` to perform dynamic +string expansions. (also known as xref:xlat/index.adoc[xlat]) + +String expansions are usually performed in order to get additional +information which is not immediately available to the policy. This +information can be taken from almost any source, including other +attributes, databases, and scripts. + +.Example +[source,unlang] +---- +update reply { + &Framed-IP-Address := "%{sql:SELECT static_ip from table WHERE user = '%{User-Name}'}" +} +---- + +== Data Types + +Each attribute used by the server has an associated +xref:type/index.adoc[data type]. The `unlang` interpreter enforces +restrictions on assignments, so that only valid data types can be +assigned to an attribute. Invalid assignments result in a run-time +error. + +.Example +[source,unlang] +---- +update reply { + &Framed-IP-Address := 192.0.2.4 + &Session-Timeout := 5 + &Reply-Message := "hello" +} +---- + +== Design Goals of Unlang + +The goal of `unlang` is to allow simple policies to be written with +minimal effort. Conditional checks can be performed by the policies, +which can then update the request or response attributes based on the +results of those checks. `unlang` can only be used in a processing +section, it cannot be used anywhere else, including in configuration +sections for a client or a module. The reason for this limitation is +that the language is intended to perform specific actions on requests +and responses. The client and module sections contain definitions for +a client or module; they do not define how a request is processed. + +`unlang` uses the same the basic syntax as the configuration files. +The syntax of the configuration file for lines, comments, sections, +sub-section, etc., all apply to `unlang`. + +Where `unlang` differs from the basic configuration file format is in +complexity and operation. The normal configuration files are +_declarative_ and they are _static_. That is, they declare variables +and values for those variables. Those values do not change when the +server is running. + +In contrast, `unlang` performs run-time processing of requests. +Conditional statements such as xref:if.adoc[if] are evaluated for every +packet that is received. Attribute editing statements such as +xref:update.adoc[update] can be used to edit attribute contents or lists +of attributes. + +.Example +[source,unlang] +---- +# First, the keyword 'if' + +# followed by condition which checks that the User-Name +# attribute has value "bob" + +if (&User-Name == "bob") { + # keyword "update" + + # followed by instructions to add the Reply-Message + # attribute to the "reply" list, with contents + # "Hello, bob" + + update reply { + Reply-Message := "Hello, bob" + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/keywords.adoc b/doc/antora/modules/unlang/pages/keywords.adoc new file mode 100644 index 0000000..e6411ea --- /dev/null +++ b/doc/antora/modules/unlang/pages/keywords.adoc @@ -0,0 +1,78 @@ += Keywords + +The following tables list the keywords used in `Unlang`. These keywords +implement the "flow control" of the policies. + +== Flow Control Keywords + +The _flow control_ keywords allow _if / then / else_ checks, simple +looping, etc. + +.Flow Control +[options="header"] +[cols="30%,70%"] +|===== +| Keyword | Description +| xref:break.adoc[break] | Exit early from a `foreach` loop. +| xref:case.adoc[case] | Match inside of a `switch`. +| xref:else.adoc[else] | Do something when an `if` does not match. +| xref:elsif.adoc[elsif] | Check for condition when a previous `if` does not match. +| xref:foreach.adoc[foreach] | Loop over a list of attributes. +| xref:if.adoc[if] | Check for a condition, and execute a sub-policy if it matches. +| xref:return.adoc[return] | Immediately stop processing a section. +| xref:switch.adoc[switch] | Check for multiple values. +|===== + +== Attribute Editing Keywords + +The _attribute editing_ keywords allow policies to add, delete, and +modify attributes in any list or packet. + +.Attribute Editing +[options="header"] +[cols="30%,70%"] +|===== +| Keyword | Description +| xref:update.adoc[update] | Add or filter attributes to a list +|===== + +== Grouping Keywords + +The _grouping_ keywords allow policies to be organized into groups, +including load-balancing. + +.Grouping +[options="header"] +[cols="30%,70%"] +|===== +| Keyword | Description +| xref:group.adoc[group] | Group a series of statements. +| xref:load-balance.adoc[load-balance] | Define a load balancing group without fail-over. +| xref:redundant.adoc[redundant] | Define a redundant group with fail-over. +| xref:redundant-load-balance.adoc[redundant-load-balance] | Define a redundant group with fail-over and load balancing. +|===== + +== Module Keywords + +The _module_ keywords refer pre-packaged libraries that implement +specific functionality, such as connecting to SQL, LDAP, etc. The +name used here is not the literal string `module`. Instead, it is the +name of an instance of a pre-packaged module such as `sql`, or `ldap`, or +`eap`. + +The documentation below describes how to reference modules. That is, +how to use `sql`, etc. in the policies. Please see +`raddb/mods-available/` for configuration examples for each module. + +.Modules +[options="header"] +[cols="30%,70%"] +|===== +| Keyword | Description +| xref:module.adoc[<module>] | Execute a named module, e.g., `sql`. +| xref:module_method.adoc[<module>.<method>] | Execute a particular method of a named module, e.g., `pap.authorize` +| xref:module_builtin.adoc[reject] | Built-in modules, e.g., `reject`, or `ok`, etc. +|===== + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/list.adoc b/doc/antora/modules/unlang/pages/list.adoc new file mode 100644 index 0000000..a55a54f --- /dev/null +++ b/doc/antora/modules/unlang/pages/list.adoc @@ -0,0 +1,72 @@ += Attribute Lists + +An attribute list contains a set of attributes. The allowed lists +are: + +`request`:: Attributes in the incoming request packet. + +`reply`:: Attributes in the outgoing reply packet. + +`control`:: Attributes in the internal "control" list that is +associated with the request. ++ +The `control` attributes are used to manage how the request is +processed. These attributes are never sent in any packet. + +`session-state`:: Attributes which are maintained across multi-packet +exchanges. + +`proxy-request`:: Attributes in the proxied request packet to a home server. + +`proxy-reply`:: Attributes in the reply packet from the home server. + +`coa`:: Attributes in a CoA-Request packet which is sent to a home server. + +`disconnect`:: Attributes in a Disconnect-Request packet which is sent to a home server. + +There must be a colon `:` after the list name and before the attribute name. +This syntax helps the server to distinguish between list names and attribute +names. + +With the exception of `session-state`, all of the above lists are +ephemeral. That is, they exist for one packet exchange, and only one +packet exchange. When a reply is sent for a request, the above lists +and all attributes are deleted. There is no way to reference an +attribute from a previous packet. We recommend using a database to +track complex state. + +The `coa` and `disconnect` lists can only be used when the server +receives an Access-Request or Accounting-Request. Use `request` and +`reply` instead of `coa` when the server receives a CoA-Request or +Disconnect-Request packet. + +Adding one or more attributes to either of the `coa` or `disconnect` +list causes server to originate a CoA-Request or Disconnect-Request +packet. That packet is sent when the current Access-Request or +Accounting-Request has been finished, and a reply sent to the NAS. +See `raddb/sites-available/originate-coa` for additional information. + +In some cases, requests are associated a multi-packet exchange. For +those situations, the `session-state` list is automatically saved when +a reply is sent, and it is automatically restored when the next packet +in sequence comes in. Once the packet exchange has been finished, the +`session-state` list is deleted. + +In some cases, there is a parent-child relationship between requests. +In those situations, it is possible for the policy rules in the child +to refer to attributes in the parent. This reference can be made by +prefixing the _<list>_ name with the `parent` qualifier. The key word +`outer` is also a synonym for `parent`. If there are multiple +parent-child relationships, the `parent` qualifier can be repeated. + +There is, however, no way for the parent to refer to the child. When +the child is running, the parent is suspended. Once the child +finishes, it is deleted, and is no longer accessible to the parent. + +.Examples +`&parent.request.User-Name` + +`&parent.reply.Reply-Message` + +`&parent.parent.session-state.Filter-Id` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/load-balance.adoc b/doc/antora/modules/unlang/pages/load-balance.adoc new file mode 100644 index 0000000..d64b161 --- /dev/null +++ b/doc/antora/modules/unlang/pages/load-balance.adoc @@ -0,0 +1,32 @@ += The load-balance Statement + +.Syntax +[source,unlang] +---- +load-balance { + [ statements ] +} +---- + +The `load-balance` section is similar to the `redundant` section +except that only one module in the subsection is ever called. + +In general, the +xref:redundant-load-balance.adoc[redundant-load-balance] statement is +more useful than this one. + +[ statements ]:: One or more `unlang` commands. Only one of the +statements is executed. + +.Examples + +[source,unlang] +---- +load-balance &User-Name { + sql1 + sql2 +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/module.adoc b/doc/antora/modules/unlang/pages/module.adoc new file mode 100644 index 0000000..fd18f2f --- /dev/null +++ b/doc/antora/modules/unlang/pages/module.adoc @@ -0,0 +1,86 @@ += Modules + +.Syntax +[source,unlang] +---- +<module> +---- + +The `<module>` statement is a reference to the named module. Common +module names include `pap`, `chap`, `files`, `eap`, and `sql`. The +`modules { ... }` subsection of `radiusd.conf` contains all of the +valid modules. + +When processing reaches a named module, the pre-compiled module is +called. The module may succeed or fail and will return a status code +to the `unlang` interpreter detailing success or failure. + +.Example +[source,unlang] +---- +chap +sql +---- + +== Module Return Codes + +When a module is called, it returns one of the following codes to +the interpreter; the meaning of each code is detailed to the right of +the source, below: + +.Module Return Codes + +The below table describes the purpose of the rcodes that may be returned +by a module call. In this case the 'operation' referenced in the table is +the current module call. + +include::partial$rcode_table.adoc[] + +These return codes can be used in a subsequent +xref:condition/index.adoc[conditional expression] thus allowing policies to +perform different actions based on the behaviour of the modules. + +.Example +[source,unlang] +---- +sql +if (notfound) { + update reply { + Reply-Message = "We don't know who you are" + } + reject +} +---- + +== Module Return Code priority overrides + +In the case of modules, rcodes can be modified on a per-call basis. + +Module priority overrides are specified in a block inline with the module call. +The format of an override is `<rcode> = (0+|<rcode>|return)` - That is, +a number greater than or equal to 0, the priority of another rcode, or the special +priority `return` which causes the current section to immediately exit. + +[source, unlang] +---- +ldap { <1> + fail = 1 <2> + ok = handled <3> + reject = return <4> +} +---- + +<1> Call to the `ldap` module. +<2> Sets the priority of the `fail` rcode to be `1`. If the priority + of the rcode for the request is `0`, then the request request rcode + will be set to `fail` if the module returns `fail`. +<3> Sets the priority of the `ok` rcode to be whatever the default is for + `handled` in this section. As the default for `handled` is usually + `return`. If `ok` is returned, the current section will immediately + exit. +<4> Sets the priority of `reject` to be `return`. If the module returns + `reject`, the current section will immediately exit. + + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/module_builtin.adoc b/doc/antora/modules/unlang/pages/module_builtin.adoc new file mode 100644 index 0000000..f21a128 --- /dev/null +++ b/doc/antora/modules/unlang/pages/module_builtin.adoc @@ -0,0 +1,42 @@ += Built-in Modules + +In some cases, it is useful to reject a request immediately or perform another +action on it. The built-in modules can be used to perform these actions. These +modules are named for the return codes given in the xref:module.adoc[module] +section. + +In practice, these modules are implemented by the `always` module and +exist so that a success or failure can be forced during the processing +of a policy. + +The names and behaviours of these modules are given below: + +`fail`:: +Causes the request to be treated as if a database failure had +occurred. + +`noop`:: +Do nothing. This also serves as an instruction to the +configurable failover tracking that nothing was done in the current +section. + +`ok`:: +Instructs the server that the request was processed properly. This keyword can be used to over-ride earlier failures if the local +administrator determines that the failures are not catastrophic. + +`reject`:: +Causes the request to be immediately rejected. + +.Example +[source,unlang] +---- +if (!&User-Name) { + update reply { + Reply-Message := "We don't know who you are" + } + reject +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/module_method.adoc b/doc/antora/modules/unlang/pages/module_method.adoc new file mode 100644 index 0000000..98cd375 --- /dev/null +++ b/doc/antora/modules/unlang/pages/module_method.adoc @@ -0,0 +1,27 @@ += Module methods + +.Syntax +[source,unlang] +---- +<module>.<method> +---- + +This variant of xref:module.adoc[<module>] is used in one processing +section. It calls a module using the method of another processing +section. For example, it can be used to call a module's `authorize` +method while processing the `post-auth` section. + +The `<module>` portion must refer to an existing module; the +`<method>` portion must refer to processing method supported by that +module. Typically, the names of the processing method will be the +same as the processing sections. + +.Example +[source,unlang] +---- +sql.recv.Accounting-Request +files.recv.Access-Request +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/redundant-load-balance.adoc b/doc/antora/modules/unlang/pages/redundant-load-balance.adoc new file mode 100644 index 0000000..2322f72 --- /dev/null +++ b/doc/antora/modules/unlang/pages/redundant-load-balance.adoc @@ -0,0 +1,39 @@ += The redundant-load-balance Statement + +.Syntax +[source,unlang] +---- +redundant-load-balance { + [ statements ] +} +---- + +The `redundant-load-balance` section operates as a combination of the +xref:redundant.adoc[redundant] and xref:load-balance.adoc[load-balance] +sections. + +[ statements ]:: One or more `unlang` commands. ++ +If the selected statement succeeds, then the server stops processing +the `redundant-load-balance` section. If, however, that statement fails, +then the next statement in the list is chosen (wrapping around to the +top). This process continues until either one statement succeeds or all +of the statements have failed. ++ +All of the statements in the list should be modules, and of the same +type (e.g., `ldap` or `sql`). All of the statements in the list should +behave identically, otherwise different requests will be processed +through different modules and will give different results. + +.Example +[source,unlang] +---- +redundant-load-balance &User-Name { + sql1 + sql2 + sql3 +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/redundant.adoc b/doc/antora/modules/unlang/pages/redundant.adoc new file mode 100644 index 0000000..e837d1f --- /dev/null +++ b/doc/antora/modules/unlang/pages/redundant.adoc @@ -0,0 +1,42 @@ += The redundant Statement + +.Syntax +[source,unlang] +---- +redundant { + [ statements ] +} +---- + +The `redundant` section executes a series of statements in sequence. +As soon as one statement succeeds, the rest of the section is skipped. + +[ statements ]:: One or more `unlang` commands. Processing starts +from the first statement in the list. ++ +If the selected statement succeeds, then the server stops processing +the `redundant` section. If, however, that statement fails, then the +next statement in the list is chosen. This process continues until +either one statement succeeds or all of the statements have failed. ++ +All of the statements in the list should be modules, and of the same +type (e.g., `ldap` or `sql`). All of the statements in the list should +behave identically, otherwise different requests will be processed +through different modules and will give different results. + +In general, we recommend using the +xref:redundant-load-balance.adoc[redundant-load-balance] statement +instead of `redundant`. + +.Example +[source,unlang] +---- +redundant { + sql1 + sql2 + sql3 +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/return.adoc b/doc/antora/modules/unlang/pages/return.adoc new file mode 100644 index 0000000..aea1bc2 --- /dev/null +++ b/doc/antora/modules/unlang/pages/return.adoc @@ -0,0 +1,36 @@ += The return Statement + +.Syntax +[source,unlang] +---- +return +---- + +The `return` statement is used to exit a processing section such as +`authorize`. It behaves similarly to the +xref:break.adoc[break] statement, except that it is not limited to +being used inside of a xref:foreach.adoc[foreach] loop. + +The `return` statement is not strictly necessary. It is mainly used +to simplify the layout of `unlang` policies. If the `return` +statement did not exist, then every xref:if.adoc[if] statement might need +to have a matching xref:else.adoc[else] statement. + +The `return` statement will also exit a policy which is defined in the +`policy { ... } ` subsection. This behavior allows policies to be +treated as a function call. Any `return` inside of the policy section +will only return from that policy. The `return` will _not_ return +from the enclosing processing section which called the policy. + +.Example +[source,unlang] +---- +sql +if (&reply.Filter-Id == "hello") { + return +} +... +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/return_codes.adoc b/doc/antora/modules/unlang/pages/return_codes.adoc new file mode 100644 index 0000000..3b09c2d --- /dev/null +++ b/doc/antora/modules/unlang/pages/return_codes.adoc @@ -0,0 +1,17 @@ += Return codes + +Many operations in the server produce a return code (rcode). +The different rcodes give a course indication of whether a particular operation +(a module call, string expansion, or keyword) was successful. + +Unlike return values in other languages, FreeRADIUS' rcodes are are always taken +from a fixed compiled-in set. + +include::partial$rcode_table.adoc[] + +Return codes propagate through nested unlang sections based on their priority. +If a rcode returned by an operation has a higher priority than the current rcode +associated with the request, then the request rcode is overwritten. + +Return code priorities are assigned by the section the module call, expansion or +keyword was used in. diff --git a/doc/antora/modules/unlang/pages/switch.adoc b/doc/antora/modules/unlang/pages/switch.adoc new file mode 100644 index 0000000..deff703 --- /dev/null +++ b/doc/antora/modules/unlang/pages/switch.adoc @@ -0,0 +1,83 @@ += The switch Statement + +.Syntax +[source,unlang] +---- +switch <expansion> { + case <match-1> { + [ statements-1 ] + } + case <match-2> { + [ statements-2 ] + } + case { + [ statements-3 ] + } +} +---- + +A `switch` statement causes the server to evaluate _expansion_, which +can be an xref:attr.adoc[&Attribute-Name] or +xref:condition/operands.adoc[data]. The result is compared against _match-1_ +and _match-2_ to find a match. If no string matches, then the server +looks for the default xref:case.adoc[case] statement, which has no +associated match. + +The matching is done via equality. The `switch` statement is mostly +syntactic sugar and is used to simplify the visual form of the +configuration. It is mostly equivalent to the following use of +xref:if.adoc[if] statements: + +.Nearly equivalent syntax +[source,unlang] +---- +if (<expansion> == <match-1>) { + [ statements-1 ] +} +elsif (<expansion> == <match-2>) { + [ statements-2 ] +} +else { + [ statements-3 ] +} +---- + +The only difference between the two forms is that for a `switch` +statement, the _expansion_ is evaluated only once. For the equivalent +xref:if.adoc[if] statement, the _expansion_ is evaluated again for every +xref:if.adoc[if]. + +If a matching xref:case.adoc[case] is found, the statements within +that xref:case.adoc[case] are evaluated. If no matching +xref:case.adoc[case] is found, the `case` section with no "match" is +evaluated. If there is no such `case { ...}` subsection, then the +`switch` statement behaves as if the `case {...}` section was empty. + +//// +For compatibility with version 3, and empty `case` statement can also +be used instead of `default`. +//// + +The _match_ text for the xref:case.adoc[case] statement can be an +xref:attr.adoc[&Attribute-Name] or xref:type/index.adoc[data]. + +No statement other than xref:case.adoc[case] can appear in a `switch` +statement, and the xref:case.adoc[case] statement cannot appear outside of a +`switch` statement. + +.Example +[source,unlang] +---- +switch &User-Name { + case "bob" { + reject + } + + case { + ok + } +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/all_types.adoc b/doc/antora/modules/unlang/pages/type/all_types.adoc new file mode 100644 index 0000000..0bace01 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/all_types.adoc @@ -0,0 +1,80 @@ += List of Data Types + +The server support a wide range of data types, both in `unlang` and in +the dictionaries. This page outlines the names and functionality of +those data types. + +== Basic Data Types + +There are a number of "basic" data types. These data types are +fixed-size, and encapsulate simple concepts such as "integer" or "IP +address". + +Basic data types can be used in `unlang`, as they contain simple +values which can be compared, or assigned to one attribute. In most +cases, it is not necessary to know the name of the data type. It is +possible to write values in the format you expect, The server will do +"the right thing" when interpreting the values. + +.Basic Data Types +[options="header"] +[cols="15%,85%"] +|===== +| Data Type | Description +| bool | boolean +| date | calendar date +| ethernet | Ethernet address +| float32 | 32-bit floating point number +| float64 | 64-bit floating point number +| ifid | interface ID +| int8 | 8-bit signed integer +| int16 | 16-bit signed integer +| int32 | 32-bit signed integer +| int64 | 64-bit signed integer +| ipaddr | IPv4 address +| ipv6addr | IPv6 address +| ipv4prefix | IPv4 network with address and prefix length +| ipv6prefix | IPv6 network with address and prefix length +| octets | raw binary, printed as hex strings +| string | printable strings +| time_delta | difference between two calendar dates +| uint8 | 8-bit unsigned integer +| uint16 | 16-bit unsigned integer +| uint32 | 32-bit unsigned integer +| uint64 | 64-bit unsigned integer +|===== + +=== Structural Data Types + +The following data types are "structural", in that they form +parent-child relationships between attributes. These data types can +only be used in the dictionaries. They cannot be used in `unlang` +statements. + +.Structural Data Types +[options="header"] +[cols="15%,85%"] +|===== +| Data Type | Description +| struct | structure which contains fixed-width fields +| tlv | type-length-value which contains other attributes +| vsa | Encapsulation of vendor-specific attributes +|===== + +=== Protocol-Specific Data Types + +The following data types are used only in certain protocols. These +data types can be used only in the dictionaries. They cannot be used +in `unlang` statements. + +.Protocol Specific Data Types +[options="header"] +[cols="15%,15%,70%"] +|===== +| Data Type | Protocol | Description +| abinary | RADIUS | Ascend binary filters +| extended | RADIUS | attributes which "extend" the number space +|===== + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS diff --git a/doc/antora/modules/unlang/pages/type/double.adoc b/doc/antora/modules/unlang/pages/type/double.adoc new file mode 100644 index 0000000..6c3e708 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/double.adoc @@ -0,0 +1,39 @@ += Double-Quoted Strings + +.Syntax +`"string"` + +A double-quoted string is interpreted via the usual rules in +programming languages for double quoted strings. The double-quote +character can be placed in a string by escaping it with a backslash. +Carriage returns and line-feeds can also be used via the usual `\r` and +`\n` syntax. + +The main difference between the single and double quoted strings is +that the double quoted strings can be dynamically expanded. The syntax +`${...}` is used for parse-time expansion and `%{...}` is used for +run-time expansion. The difference between the two methods is that the +`${...}` form is expanded when the server loads the configuration +files and is valid anywhere in the configuration files. The `%{...}` +link:xlat.adoc[string expansion] form is valid only in conditional +expressions and attribute assignments. + +The output of the dynamic expansion can be interpreted as a string, +a number, or an IP address, depending on its context. + +Note that the interpretation of text _strongly_ depends on the +context. The text `"0000"` can be interpreted as a data type +"integer", having value zero, or a data type "string", having value +`"0000"`. In general when a particular piece of text is used, it is +used with the context of a known attribute. That attribute has a +link:data.adoc[data type], and the text will be interpreted as that +data type. + +.Examples + +`"word"` + +`"a string"` + +`"this has embedded\ncharacters"` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/index.adoc b/doc/antora/modules/unlang/pages/type/index.adoc new file mode 100644 index 0000000..7d0d70f --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/index.adoc @@ -0,0 +1,117 @@ += Data Types + +Unlang supports a number of data types. These data types are used in +conditional expressions or when assigning a value to an attribute. + +== Using Data Types + +The server support a wide range of data types, as given in the +xref:unlang/type/all_types.adoc[list of data types] page. The choice +of which data type applies is determined by the context in which that +data type is used. This context is usually taken from an attribute +which is being assigned a value. + +The `unlang` interpreter uses pre-defined attributes which are defined +in dictionaries. The dictionaries define both a name, and a data type +for the attributes. In the interpreter, then, attributes can be +assigned a value or compared to a value, without specifying the data +type. The interpreter knows how to parse the value by using the data +type assigned to the attribute. + +The result is that in most cases, it is not necessary to know the name +of the data types. It is possible to write values in the format you +expect, and he server will do "the right thing" when interpreting the +values. + +.Attributes with Different Data Types +[source,unlang] +---- +Framed-IP-Address = 192.0.2.1 +Framed-IPv6-Address = 2001:db8:: +Reply-Message = "This is a reply" +Port-Limit = 5 +Boolean = true +Octets-Thing = 0xabcdef0102030405 +MAC-Address = 00:01:02:03:04:05 +---- + +== Parsing Data Types + +The interpreter is flexible when parsing data types. So long as the +value can be parsed as the given data type without error, the value +will be accepted. + +For example, a particular attribute may be of data type `ipaddr` in +order to store IPv4 addresses. The interpreter will then accept the +following strings as valid IPv4 addresses: + +`192.168.0.2`:: xref:type/string/unquoted.adoc[Unquoted text], interpreted as the data type + +`'192.168.0.2'`:: xref:type/string/single.adoc[Single-quoted string], the contents of the string are parsed as the data type. ++ +The single-quoted string form is most useful when the data type +contains special characters that may otherwise confuse the parser. + +`"192.168.0.2"`:: xref:type/string/double.adoc[Double-quoted string]. ++ +The contents of the string are dynamically expanded as described in +the xref:unlang/xlat/index.adoc[dynamic expansion] page. The +resulting output is then interpreted as the given data type. + +`{backtick}/bin/echo 192.168.0.2{backtick}`:: xref:type/string/backticks.adoc[backtick-quoted string]. +Run a script, and parse the resulting string as the data type. + +Similar processing rules are applied when parsing assignments and +comparisons, for all attributes and data types. + +=== Casting Data Types + +In some cases, it is necessary to parse values which do not refer to +attributes. This situation usually occurs when two values need to be +compared, as in the following example: + +[source,unlang] +---- +if ("%{sql:SELECT ipaddress FROM table WHERE user=%{User-Name}}" == 192.0.2.1) } + .... +} +---- + +Since there is no attribute on either side of the `==` operator, the +interpreter has no way of knowing that the string `192.0.2.1` is an IP +address. There is unfortunately no way of automatically parsing +strings in order to determine the data type to use. Any such +automatic parsing would work most of the time, but it would have +error cases where the parsing was incorrect. + +The solution is to resolve these ambiguities by allowing the values to +be cast to a particular type. Casting a value to a type tells the +interpreter how that value should be parsed. Casting is done by +prefixing a value with the type name, surrounded by angle brackets; +`<...>`. + +.Syntax +---- +<...>value +---- + +We can add a cast to the above example, as follows: + +[source,unlang] +---- +if ("%{sql:SELECT ipaddress FROM table WHERE user=%{User-Name}}" == <ipaddr>192.0.2.1) } + .... +} +---- + +In this example, we prefix the IP address with the string `<ipaddr>`. +The interpreter then knows that the value `192.0.2.` should be +interpreted as the data type `ipaddr`, and not as the literal string +`"192.0.2."`. + +For a full list of data types which can be used in a cast, please see +the xref:unlang/type/all_types.adoc[list of data types] page, and the +"Basic Type Types" section. + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/ip.adoc b/doc/antora/modules/unlang/pages/type/ip.adoc new file mode 100644 index 0000000..fc25ae8 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/ip.adoc @@ -0,0 +1,15 @@ += IP Addresses + +.Examples + +`192.0.2.16` + +`::1` + +`example.com` + +Depending on the context, a "simple word", as above, may be +interpreted as an IPv4 or an IPv6 address. This interpretation is +usually done when the string is used in the context of an attribute, +or to compare two addresses or assign an address to an attribute. + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/numb.adoc b/doc/antora/modules/unlang/pages/type/numb.adoc new file mode 100644 index 0000000..284cf81 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/numb.adoc @@ -0,0 +1,11 @@ += Numbers + +.Examples + +`0` + +`563` + +Numbers are unsigned integers that are composed of decimal digits. + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/string/backticks.adoc b/doc/antora/modules/unlang/pages/type/string/backticks.adoc new file mode 100644 index 0000000..9372b4c --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/string/backticks.adoc @@ -0,0 +1,38 @@ += Backtick-quoted string + +.Syntax +`{backtick}string{backtick}` + +The backtick operator is used to perform a run-time expansion +similar to what is done with the Unix shell. The contents of the string +are split into one or more sub-strings, based on intermediate +whitespace. Each substring is then expanded as described above for +double quoted strings. The resulting set of strings is used to execute a +program with the associated arguments. + +The output of the program is recorded, and the resulting data is +used in place of the input string value. Where the output is composed of +multiple lines, any carriage returns and line feeds are replaced by +spaces. + +For safety reasons, the full path to the executed program should be +given. In addition, the string is split into arguments _before_ the +substrings are dynamically expanded. This step is done both to allow +the substrings to contain spaces, and to prevent spaces in the +expanded substrings from affecting the number of command-line +arguments. + +For performance reasons, we recommend that the use of back-quoted +strings be kept to a minimum. Executing external programs is +relatively expensive, and executing a large number of programs for +every request can quickly use all of the CPU time in a server. If many +programs need to be executed, it is suggested that alternative ways to +achieve the same result be found. In some cases, using a real +programming language such as `lua`, `perl` or `python` may be better. + +.Examples + +`{backtick}/bin/echo hello{backtick}` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/string/double.adoc b/doc/antora/modules/unlang/pages/type/string/double.adoc new file mode 100644 index 0000000..ea87bc5 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/string/double.adoc @@ -0,0 +1,68 @@ += Double Quoted Strings + +.Syntax +`"string"` + +A double-quoted string allows escape sequences and xref:xlat/index.adoc[dynamic +expansions]. As with xref:type/string/single.adoc[single-quoted strings], text +within double quotes can include spaces. + +The main difference between the single and double quoted strings is +that the double quoted strings can be dynamically expanded. The syntax +`${...}` is used for parse-time expansion and `%{...}` is used for +run-time expansion. The difference between the two methods is that the +`${...}` form is expanded when the server loads the configuration +files and is valid anywhere in the configuration files. The `%{...}` +xref:xlat/index.adoc[string expansion] form is valid only in conditional +expressions and attribute assignments. + +The output of the dynamic expansion can be interpreted as a string, +a number, or an IP address, depending on its context. + +Note that the interpretation of text _strongly_ depends on the +context. The text `"0000"` can be interpreted as a data type +"integer", having value zero, or a data type "string", having value +`"0000"`. In general when a particular piece of text is used, it is +used with the context of a known attribute. That attribute has a +xref:type/index.adoc[data type], and the text will be interpreted as that +data type. + +NOTE: Most values retrieved from external datastores will be treated implicitly +as double-quoted strings. + +== Escape sequences + +Escape sequences allow the inclusion of characters that may be difficult to +represent in datastores, or the FreeRADIUS configuration files. + +.Escape sequences and their descriptions +[options="header", cols="15%,85%"] +|===== +| Escape sequence | Character represented +| `\\` | Literal backslash (0x5c) +| `\r` | Carriage return (0x0d) +| `\n` | Line feed (0x0a) +| `\t` | Horizontal tab (0x09) +| `\"` | Double quote (0x22) +| `\x<hex><hex>` | A byte whose numerical value is given by `<hex><hex>` interpreted as a hexadecimal number. +| `\x<oct><oct><oct>` | A byte whose numerical value is given by `<oct><oct><oct>` interpreted as an octal number. +|===== + +.Examples + +`"word"` + +`"a string"' + +`"foo\"bar\""` + +`"this is a long string"` + +`"this has embedded\ncharacters"` + +`"attribute\tvalue\nusername\t%{User-Name}\nreply-message\t%{reply.Reply-Message}"` +`"The result of 'SELECT * FROM foo WHERE 1' is: %{sql:SELECT * FROM foo WHERE 1}"` + +// Licenced under CC-by-NC 4.0. +// Copyright (C) 2019 Arran Cudbard-Bell <a.cudbardb@freeradius.org> +// Copyright (C) 2019 The FreeRADIUS project. +// Copyright (C) 2020 Network RADIUS SAS. + + + + diff --git a/doc/antora/modules/unlang/pages/type/string/escaping.adoc b/doc/antora/modules/unlang/pages/type/string/escaping.adoc new file mode 100644 index 0000000..e63a498 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/string/escaping.adoc @@ -0,0 +1,14 @@ += Character Escaping + +The quotation characters in the above string data types can be +escaped by using the backslash, or `\,` character. The backslash +character itself can be created by using `\\`. Carriage returns and +line feeds can be created by using `\n` and `\r`. + +.Examples + +`"I say \"hello\" to you"` + +`"This is split\nacross two lines"` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/string/single.adoc b/doc/antora/modules/unlang/pages/type/string/single.adoc new file mode 100644 index 0000000..fa2ac05 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/string/single.adoc @@ -0,0 +1,19 @@ += Single Quoted Strings + +.Syntax +`'string'` + +A single-quoted string is interpreted without any dynamic string +expansion. The quotes allow the string to contain spaces, among other +special characters. The single quote character can be placed in such a +string by escaping it with a backslash. + +.Examples + +`'hello'` + +`'foo bar`' + +`'foo\\'bar'` + +`'this is a long string'` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/type/string/unquoted.adoc b/doc/antora/modules/unlang/pages/type/string/unquoted.adoc new file mode 100644 index 0000000..9dd6e55 --- /dev/null +++ b/doc/antora/modules/unlang/pages/type/string/unquoted.adoc @@ -0,0 +1,21 @@ += Unquoted Strings + +Where a series of characters cannot be parsed as a decimal number, +they are interpreted as a simple string composed of one word. This +word is delimited by spaces, or by other tokens, such as `)` in +conditional expressions. + +This unquoted text is interpreted as simple strings and are generally +equivalent to placing the string in single quotes. + +The interpretation of the text depends on the context, which is +usually defined by an attribute which has a xref:type/index.adoc[data type]. + +.Examples + +`Hello` + +`192.168.0.1` + +`00:01:02:03:04:05` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/update.adoc b/doc/antora/modules/unlang/pages/update.adoc new file mode 100644 index 0000000..645f4d8 --- /dev/null +++ b/doc/antora/modules/unlang/pages/update.adoc @@ -0,0 +1,160 @@ += The update Statement + +.Syntax +[source,unlang] +---- +update [ <list> ] { + <server-attribute> <op> <value> + ... +} +---- + +The `update` statement adds attributes to, or edits the attributes in, +the named _<list>_. + +The `update` statement consists of the following syntax elements: + +<list>:: The attribute list which will be updated. The list is +usually `request`, `reply`, or `control`. ++ +If the _<list>_ qualifier is omitted, then each entry inside of the +`update` section *must* be prefixed with a list name. For example, +`&request.User-Name ...` + +<server-attribute>:: The server attribute which is assigned the +_<value>_. + +<op>:: The operator such as `=`, `:=`, etc. + +<value>:: The value which is assigned to the attribute. If the field +is a double-quoted string, it undergoes xref:xlat/index.adoc[string +expansion], and the resulting value is assigned to the attribute. + +The update process is atomic, in that either all of the attributes are +modified, or none of them are modified. If the `update` fails for any +reason, then all of the results are discarded, and the `update` does +not affect any server attributes. + +.Example +[source,unlang] +---- +update reply { + &Reply-Message := "Hello!" + &Framed-IP-Address := 192.0.2.4 +} +---- + +== Lists + +The _<list>_ field sets the attribute list that will be updated. If +the _<list>_ qualifier is omitted, then each entry inside of the +`update` section *must* be prefixed with a list name. For example, +`&request.User-Name ...` + +Please see the xref:list.adoc[list] page for valid list names. + +== Server Attributes + +The _<server-attribute>_ field is an attribute name, such as +`&Reply-Message`. The attribute name may also be prefixed with a +_<list>_ qualifier, which overrides the _<list>_ given at the start +of the `update` section. + +NOTE: In version 3, the leading `&` is optional but recommended. + +== Editing Operators + +The `<op>` field is used to define how the attribute is processed. +Different operators allow attributes to be added, deleted, or +replaced, as defined below. + +.Editing Operators +[options="header"] +[cols="10%,90%"] +|===== +| Operator | Description +| = | Add the attribute to the list, if and only if an attribute of +the same name is not already present in that list. +| := | Add the attribute to the list. If any attribute of the same +name is already present in that list, its value is replaced with the +value of the current attribute. +| += | Add the attribute to the tail of the list, even if attributes +of the same name are already present in the list. +| ^= | Add the attribute to the head of the list, even if attributes +of the same name are already present in the list. +| -= | Remove all attributes from the list that match _<value>_. +| !* | Delete all occurances of the attribute, no matter what the value. +|===== + +== Filtering Operators + +The following operators may also be used in addition to the ones +listed above. These operators use the _<server-attribute>_ and +_<value>_ fields to enforce limits on all attributes in the given +_<list>_, and to edit attributes which have a matching +_<server-attribute>_ name. All other attributes are ignored. + +.Filtering Operators +[options="header] +[cols="10%,90%"] +|===== +| Operator | Description +| == | Keep only the attributes in the list that match _<value>_ +| < | Keep only the attributes in the list that have values less than _<value>_. +| \<= | Keep only the attributes in the list that have values less than or equal to _<value>_. +| > | Keep only the attributes in the list that have values greater than _<value>_. +| >= | Keep only the attributes in the list that have values greater than or equal to _<value>_. +| =~ | Keep only the attributes in the list which match the regular expression given in _<value>_. +| !~ | Keep only the attributes in the list which do not match the regular expression given in _<value>_. +|===== + +The `==` operator is very different from the `=` operator listed +above. The `=` operator is used to add new attributes to the list, +while the `==` operator removes all attributes that do not match the +given value. + +The comparison operators `<`, `<=`, `>`, and `>=` have some additional +side effects. Any non-matching value is replaced by the _<value>_ +given here. If no attribute exists, it is created with the given +_<value>_. + +For IP addresses, the operators `>`, `>=`, `<`, and `\<=` check for +membership in a network. The _<value>_ field should then be a IP +network, given in `address/mask` format. + +.Example +[source,unlang] +---- +update reply { + &Session-timeout := 86400 +} +---- + +.Example +[source,unlang] +---- +update reply { + &Reply-Message += "Rejected: Also, realm does not end with ac.uk" +} +---- + +== Values + +The _<value>_ field is the value which is assigned to the +_<server-attribute>_. The interpretation of the _<value>_ field +depends on the data type of the contents. For example, if the string +`"192.0.2.1"` is assigned to an attribute of the `string` data type, +then the result is an ASCII string containing that value. However, if +the same string is assigned to an attribute of the `ipaddr` data type, +then the result is a 32-bit IPv4 address, with binary value `0xc0000201`. + +.Example +[source,unlang] +---- +update reply { + &Session-Timeout <= 3600 +} +---- + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/xlat/alternation.adoc b/doc/antora/modules/unlang/pages/xlat/alternation.adoc new file mode 100644 index 0000000..adb7604 --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/alternation.adoc @@ -0,0 +1,24 @@ += Alternation Syntax + +Alternation syntax similar to that used in Unix shells may also be +used: + +`%{%{Foo}:-bar}` + +This code returns the value of `%{Foo}`, if it has a value. +Otherwise, it returns a literal string bar. + +`%{%{Foo}:-%{Bar}}` + +This code returns the value of `%{Foo}`, if it has a value. +Otherwise, it returns the expansion of `%{Bar}`. + +These conditional expansions can be nested to almost any depth, such +as with `%{%{One}:-%{%{Two}:-%{Three}}}`. + +.Examples +`%{%{Stripped-User-Name}:-%{User-Name}}` + +`%{%{Framed-IP-Address}:-<none>}` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/xlat/attribute.adoc b/doc/antora/modules/unlang/pages/xlat/attribute.adoc new file mode 100644 index 0000000..a3ee29b --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/attribute.adoc @@ -0,0 +1,54 @@ += Attribute References + +Attributes in a list may be referenced via one of the following two +syntaxes: + +`%{Attribute-Name}` + +`%{<list>:Attribute-Name}` + +The `<list>:` prefix is optional. If given, it must be a valid +reference to an xref:list.adoc[attribute list]. + +If the `<list>:` prefix is omitted, then the `request` list is +assumed. + +For EAP methods with tunneled authentication sessions (i.e. PEAP and +EAP-TTLS), the inner tunnel session can refer to a list for the outer +session by prefixing the list name with `outer.` ; for example, +`outer.request`. + +When a reference is encountered, the given list is examined for an +attribute of the given name. If found, the variable reference in the +string is replaced with the value of that attribute. Otherwise, the +reference is replacedd with an empty string. + +.Examples + +`%{User-Name}` + +`%{request.User-Name} # same as above` + +`%{reply.User-Name}` + +`%{outer.request.User-Name} # from inside of a TTLS/PEAP tunnel` + +Examples of using references inside of a string: + +`"Hello %{User-Name}"` + +`"You, %{User-Name} are not allowed to use %{NAS-IP-Address}"` + +== Additional Variations + +`%{Attribute-Name[#]}`:: +Returns an integer containing the number of named attributes + +`%{Attribute-Name[0]}`:: + +When an attribute appears multiple times in a list, this syntax allows +you to address the attributes as with array entries. `[0]` refers to +the first attributes, `[1]` refers to the second attribute, etc. + +`%{Attribute-Name[*]}`:: + +Returns a comma-separated string containing all values for the named +attributes. + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/xlat/builtin.adoc b/doc/antora/modules/unlang/pages/xlat/builtin.adoc new file mode 100644 index 0000000..f236a57 --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/builtin.adoc @@ -0,0 +1,891 @@ += Built-In Expansions + +In addition to storing attribute references, the server has a number +of built-in expansions. These expansions act largely as functions +which operate on inputs, and produce an output. + + + +== Attribute Manipulation + +=== %{length: ... } + +The `length` expansion returns the size of the input as an integer. +When the input is a string, then the output is identical to the +`strlen` expansion. + +When the input is an attribute reference, the output is the size of +the attributes data as encoded "on the wire". + +.Return: _size_ + +.Determining the length of fixed and variable length attributes +==== +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" + &Framed-IP-Address := 192.0.2.1 +} + +update reply { + &Reply-Message := "The length of %{control:Tmp-String-0} is %{length:&control:Tmp-String-0}" + &Reply-Message += "The length of %{control:Framed-IP-Address} is %{length:&control:Framed-IP-Address}" +} +---- + +.Output +.... +The length of Caipirinha is 10 +The length of 192.168.0.2 is 4 +.... +==== + +`length` is built in to the server core. + + + +=== %{integer:<&ref>} + +Print the value of the attribute an integer. + +In normal operation, `integer` attributes are printed using the name +given by a `VALUE` statement in a dictionary. Similarly, date +attributes are printed as dates, i.e., "January 1 2010. + +The `integer` expansion applies only to attributes which can be +converted to an integer. For all other inputs, it returns `0`. + +A common usage is to find the difference between two dates. + +For example, if a request contains `Service-Type = Login-User`, the +expansion of `%{integer:&Service-Type}` will yield `1`, which is the +value associated with the `Login-User` name. Using +`%{integer:&Event-Timestamp}` will return the event timestamp as an +unsigned 32-bit number. + +.Return: _string_ + +.Determining the integer value of an enumerated attribute +==== +[source,unlang] +---- +update { + &control:Service-Type := Login-User +} +update reply { + &Reply-Message := "The value of Service-Type is %{integer:&control:Service-Type}" +} +---- + +.Output + +``` +The value of Service-Type is 1 +``` +==== + +`integer` is built in to the server core. + + + +=== %{rand:<number>} + +Generate random number from `0` to `<number>-1`. + +.Return: _uint64_ + +.Generating a random number between 0 and 511 +==== +[source,unlang] +---- +update reply { + &Reply-Message := "The random number is %{rand:512}" +} +---- + +.Output + +``` +The random number is 347 +``` +==== + +`rand` is provided by the `rlm_expr` module. + + + +=== %{tag:<attribute ref>} + +CAUTION: This expansion is deprecated and will likely be removed. + +Returns a list of tags for any attributes found using ``<attribute ref>``. + +.Return: _int8_ + +.Determining the tag value of the second instance of the `radius.Tunnel-Server-Endpoint` attribute +==== +[source,unlang] +---- +update request { + &Tunnel-Server-Endpoint := '192.0.1.1' + &Tunnel-Server-Endpoint:1 := '192.0.5.2' + &Tunnel-Server-Endpoint:1 += '192.0.3.8' + &Tunnel-Server-Endpoint:2 := '192.0.2.1' + &Tunnel-Server-Endpoint:2 += '192.0.3.4' +} + +update reply { + &Reply-Message := "The tag value of the second instance of Tunnel-Server-Enpoint is %{request:Tunnel-Server-Endpoint[1]}" +} +---- + +.Output + +``` +The tag value of the second instance of Tunnel-Server-Enpoint is 192.0.5.2 +``` +==== + +`tag` is built in to the server core. + + + +=== %{string:<data>} + +Convert input to a string (if possible). For _octets_ type attributes, this +means interpreting the data as a UTF8 string, and inserting octal escape +sequences where appropriate. + +For other types, this means printing the value in its _presentation_ format, +i.e. dotted quads for IPv4 addresses, link:https://en.wikipedia.org/wiki/ISO_8601[ISO 8601] +time for date types, enumeration values for attributes such as `radius.Service-Type` etc. + +.Return: _string_ + +.String interpolation using the raw octets value of Tmp-Octets-0, and the stringified version +==== +[source,unlang] +---- +update control { + &Tmp-Octets-0 := 0x7465737431 +} +update reply { + &Reply-Message := "The string value of %{control:Tmp-Octets-0} is %{string:%{control:Tmp-Octets-0}}" +} +---- +==== + +.Output + +``` +The string value of 0x7465737431 is test1 +``` + +`string` is built in to the server core. + + + +== Server Manipulation + +=== %{config:<key>} + +Refers to a variable in the configuration file. See the documentation +on configuration file references. + +.Return: _string_ + +.Example + +[source,unlang] +---- +"Server installed in %{config:prefix}" +"Module rlm_exec.shell_escape = %{config:modules.exec.shell_escape}" +---- + +.Output + +``` +Server installed in /opt/freeradius +Module rlm_exec.shell_escape = yes +``` + +`config` is built in to the server core. + + + +=== %{client:<key>} + +Refers to a variable that was defined in the client section for the +current client. See the sections `client { ... }` in `clients.conf`. + +.Return: _string_ + +.Example + +[source,unlang] +---- +"The client ipaddr is %{client:ipaddr}" +---- + +.Output + +``` +The client ipaddr is 192.168.5.9 +``` + +`client` is built in to the server core. + + + +=== %{debug:<level>} + +Dynamically change the debug level to something high, recording the old level. + +.Return: _string_ + +.Example + +[source,unlang] +---- +authorize { + if (&request:User-Name == "bob") { + "%{debug:4}" + } else { + "%{debug:0}" + } + ... +} +---- + +.Output (_extra informations only for that condition_) + +``` +... +(0) authorize { +(0) if (&request:User-Name == "bob") { +(0) EXPAND %{debug:4} +(0) --> 2 +(0) } # if (&request:User-Name == "bob") (...) +(0) filter_username { +(0) if (&State) { +(0) ... +(0) } +... +``` + +`debug` is built in to the server core. + + + +=== %{debug_attr:<list:[index]>} + +Print to debug output all instances of current attribute, or all attributes in a list. +expands to a zero-length string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +authorize { + if (&request:User-Name == "bob") { + "%{debug_attr:request[*]}" + } + ... +} +---- + +.Output + +``` +... +(0) authorize { +(0) if (&request:User-Name == "bob") { +(0) Attributes matching "request[*]" +(0) &request:User-Name = bob +(0) &request:User-Password = hello +(0) &request:NAS-IP-Address = 127.0.1.1 +(0) &request:NAS-Port = 1 +(0) &request:Message-Authenticator = 0x9210ee447a9f4c522f5300eb8fc15e14 +(0) EXPAND %{debug_attr:request[*]} +(0) } # if (&request:User-Name == "bob") (...) +... +``` + +`debug_attr` is built in to the server core. + + + +== String manipulation + +=== %{lpad:<&ref> <val> <char>} + +Left-pad a string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "123" +} +update reply { + &Reply-Message := "Maximum should be %{lpad:&control:Tmp-String-0 11 0}" +} +---- + +.Output + +``` +Maximum should be 00000000123 +``` + +`lpad` is provided by the `rlm_expr` module. + + + +=== %{rpad:<&ref> <val> <char>} + +Right-pad a string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "123" +} +update reply { + &Reply-Message := "Maximum should be %{rpad:&control:Tmp-String-0 11 0}" +} +---- + +.Output + +``` +Maximum should be 12300000000 +``` + +`rpad` is provided by the `rlm_expr` module. + + + +=== %{pairs:<&list:[*]>} + +Serialize attributes as comma-delimited string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "This is a string" + &control:Tmp-String-0 += "This is another one" +} + +update reply { + &Reply-Message := "Serialize output: %{pairs:&control[*]}" +} +---- + +.Output + +``` +Serialize output: Tmp-String-0 = \"This is a string\"Tmp-String-0 = \"This is another one\" +``` + +`pairs` is provided by the `rlm_expr` module. + + + +=== %{randstr: ...} + +Get random string built from character classes. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update reply { + &Reply-Message := "The random string output is %{randstr:aaaaaaaa}" +} +---- + +.Output + +``` +The random string output is 4Uq0gPyG +``` + +`randstr` is provided by the `rlm_expr` module. + + + +=== %{strlen: ... } + +Length of given string. + +.Return: _integer_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" +} +update reply { + &Reply-Message := "The length of %{control:Tmp-String-0} is %{strlen:&control:Tmp-String-0}" +} +---- + +.Output + +``` +The length of Caipirinha is 21 +``` + +`strlen` is built in to the server core. + + + +=== %{tolower: ... } + +Dynamically expands the string and returns the lowercase version of +it. This definition is only available in version 2.1.10 and later. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "CAIPIRINHA" +} +update reply { + &Reply-Message := "tolower of %{control:Tmp-String-0} is %{tolower:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +tolower of CAIPIRINHA is caipirinha +``` + +`tolower` is provided by the `rlm_expr` module. + + + +=== %{toupper: ... } + +Dynamically expands the string and returns the uppercase version of +it. This definition is only available in version 2.1.10 and later. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "caipirinha" +} +update reply { + &Reply-Message := "toupper of %{control:Tmp-String-0} is %{toupper:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +toupper of caipirinha is CAIPIRINHA +``` + +`toupper` is provided by the `rlm_expr` module. + + + +== String Conversion + +=== %{base64: ... } + +Encode a string using Base64. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" +} +update reply { + &Reply-Message := "The base64 of %{control:Tmp-String-0} is %{base64:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The base64 of foo is Q2FpcGlyaW5oYQ== +``` + +`base64` is provided by the `rlm_expr` module. + + + +=== %{base64tohex: ... } + +Decode a base64 string (e.g. previously encoded using `base64`) to +hex. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Q2FpcGlyaW5oYQ==" +} +update reply { + &Reply-Message := "The base64tohex of %{control:Tmp-String-0} is %{base64tohex:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The base64decode of Q2FpcGlyaW5oYQ== is 436169706972696e6861 +``` + +`base64tohex` is provided by the `rlm_expr` module. + + + +=== %{hex: ... } + +Convert to hex. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "12345" +} +update reply { + &Reply-Message := "The value of %{control:Tmp-String-0} in hex is %{hex:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The value of 12345 in hex is 3132333435 +``` + +`hex` is built in to the server core. + + + +=== %{urlquote: ... } + +Quote URL special characters. + +.Return: _string_. + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "http://example.org/" +} +update reply { + &Reply-Message += "The urlquote of %{control:Tmp-String-0} is %{urlquote:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The urlquote of http://example.org/ is http%3A%2F%2Fexample.org%2F +``` + +`urlquote` is provided by the `rlm_expr` module. + + + +=== %{urlunquote: ... } + +Unquote URL special characters. + +.Return: _string_. + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "http%%3A%%2F%%2Fexample.org%%2F" # Attention for the double %. +} +update reply { + &Reply-Message += "The urlunquote of %{control:Tmp-String-0} is %{urlunquote:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The urlunquote of http%3A%2F%2Fexample.org%2F is http://example.org/ +``` + +`urlunquote` is provided by the `rlm_expr` module. + + + +== Hashing and Encryption + +=== %{hmacmd5:<shared_key> <string>} + +Generate `HMAC-MD5` of string. + +.Return: _octal_ + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "mykey" + &control:Tmp-String-1 := "Caipirinha" +} +update { + &control:Tmp-Octets-0 := "%{hmacmd5:%{control:Tmp-String-0} %{control:Tmp-String-1}}" +} + +update reply { + &Reply-Message := "The HMAC-MD5 of %{control:Tmp-String-1} in octets is %{control:Tmp-Octets-0}" + &Reply-Message += "The HMAC-MD5 of %{control:Tmp-String-1} in hex is %{hex:control:Tmp-Octets-0}" +} +---- + +.Output + +``` +The HMAC-MD5 of Caipirinha in octets is \317}\264@K\216\371\035\304\367\202,c\376\341\203 +The HMAC-MD5 of Caipirinha in hex is 636f6e74726f6c3a546d702d4f63746574732d30 +``` + +`hmacmd5` is provided by the `rlm_expr` module. + + + +=== %{hmacsha1:<shared_key> <string>} + +Generate `HMAC-SHA1` of string. + +.Return: _octal_ + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "mykey" + &control:Tmp-String-1 := "Caipirinha" +} +update { + &control:Tmp-Octets-0 := "%{hmacsha1:%{control:Tmp-String-0} %{control:Tmp-String-1}}" +} + +update reply { + &Reply-Message := "The HMAC-SHA1 of %{control:Tmp-String-1} in octets is %{control:Tmp-Octets-0}" + &Reply-Message += "The HMAC-SHA1 of %{control:Tmp-String-1} in hex is %{hex:control:Tmp-Octets-0}" +} +---- + +.Output + +``` +The HMAC-SHA1 of Caipirinha in octets is \311\007\212\234j\355\207\035\225\256\372Ê™>R\"\341\351O) +The HMAC-SHA1 of Caipirinha in hex is 636f6e74726f6c3a546d702d4f63746574732d30 +``` + +`hmacsha1` is provided by the `rlm_expr` module. + + + +=== %{md5: ... } + +Dynamically expands the string and performs an MD5 hash on it. The +result is binary data. + +.Return: _binary data_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" +} +update reply { + &Reply-Message := "md5 of %{control:Tmp-String-0} is octal=%{md5:%{control:Tmp-String-0}}" + &Reply-Message := "md5 of %{control:Tmp-String-0} is hex=%{hex:%{md5:%{control:Tmp-String-0}}}" +} +---- + +.Output + +``` +md5 of Caipirinha is octal=\024\204\013md||\230\243\3472\3703\330n\251 +md5 of Caipirinha is hex=14840b6d647c7c98a3e732f833d86ea9 +``` + +`md5` is provided by the `rlm_expr` module. + + + +== Miscellaneous Expansions + +=== +%{0}+..+%{32}+ + +`%{0}` expands to the portion of the subject that matched the last regular +expression evaluated. `%{1}`..`%{32}` expand to the contents of any capture +groups in the pattern. + +Every time a regular expression is evaluated, whether it matches or not, +the numbered capture group values will be cleared. + + + +=== +%{regex:<named capture group>}+ + +Return named subcapture value from the last regular expression evaluated. + +Results of named capture groups are available using the `%{regex:<named capture +group>}` expansion. They will also be accessible using the numbered expansions +described xref:builtin.adoc#_0_32[above]. + +Every time a regular expression is evaluated, whether it matches or not, +the named capture group values will be cleared. + +[NOTE] +==== +This expansion is only available if the server is built with libpcre or libpcre2. +Use the output of `radiusd -Xxv` to determine which regular expression library in use. + +.... +... +Debug : regex-pcre : no +Debug : regex-pcre2 : yes +Debug : regex-posix : no +Debug : regex-posix-extended : no +Debug : regex-binsafe : yes +... +Debug : pcre2 : 10.33 (2019-04-16) - retrieved at build time +.... +==== + +`regex` is built in to the server core. + + + +=== +%{nexttime:<time>}+ + +Calculate number of seconds until next n hour(`s`), day(`s`), week(`s`), year(`s`). + +.Return: _string_ + +.Example: + +With the current time at 16:18, `%{nexttime:1h}` will expand to `2520`. + +[source,unlang] +---- +update reply { + &Reply-Message := "You should wait for %{nexttime:1h}s" +} +---- + +.Output + +``` +You should wait for 2520s +``` + +`nexttime` is provided by the `rlm_expr` module. + + + +=== +%{Packet-Type}+ + +The packet type (`Access-Request`, etc.) + + + +=== +%{Packet-Src-IP-Address} and %{Packet-Src-IPv6-Address}+ + +The source IPv4 or IPv6 address of the packet. See also the expansions +`%{client:ipaddr}` and `%{client:ipv6addr}`. The two expansions +should be identical, unless `%{client:ipaddr}` contains a DNS hostname. + + + +=== +%{Packet-Dst-IP-Address} and %{Packet-Dst-IPv6-Address}+ + +The destination IPv4 or IPv6 address of the packet. See also the +expansions `%{listen:ipaddr}` and `%{listen:ipv6addr}`. If the socket +is listening on a "wildcard" address, then these two expansions will be +different, as follows: the `%{listen:ipaddr}` will be the wildcard +address and `%{Packet-DST-IP-Address}` will be the unicast address to +which the packet was sent. + + + +=== +%{Packet-Src-Port} and %{Packet-Dst-Port}+ + +The source/destination ports associated with the packet. + +.Return: _string_. + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "user@example.com" +} + +if (&control:Tmp-String-0 =~ /^(?<login>(.*))@(?<domain>(.*))$/) { + update reply { + &Reply-Message := "The %{control:Tmp-String-0} { login=%{regex:login}, domain=%{regex:domain} }" + } +} +---- + +.Output + +``` +The user@example.com { login=user, domain=example.com } +``` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/xlat/character.adoc b/doc/antora/modules/unlang/pages/xlat/character.adoc new file mode 100644 index 0000000..84a148c --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/character.adoc @@ -0,0 +1,80 @@ += Single Letter Expansions + +The following are single letter expansions. These expansions do not +use the typical `%{...}` format. Instead, they are short-cuts for +simple, common cases. + +== Miscellaneous + +`%%`:: + +Returns `%`. + + +== Current Time + +`%c`:: + +The current Unix epoch time in seconds. This is an unsigned decimal number. +It should be used with time-based calculations. + +`%C`:: + +The microsecond component of the current epoch time. This is an unsigned +decimal number. It should be used with time-based calculations. + + +== Request Time + +`%l`:: + +The Unix timestamp of when the request was received. This is an unsigned +decimal number. It should be used with time-based calculations. + +`%Y`:: + +Four-digit year when the request was received. + +`%m`:: + +Numeric month when the request was received. + +`%d`:: + +Numeric day of the month when the request was received. + +`%H`:: + +Hour of the day when the request was received. + +`%G`:: + +Minute component of the time when the request was received. + +`%e`:: + +Second component of the time when the request was received. + +`%M`:: + +Microsecond component of the time when the request was received. + +`%D`:: + +Request date in the format `YYYYMMDD`. + +`%S`:: + +Request timestamp in SQL format, `YYYY-mmm-ddd HH:MM:SS`. + +`%t`:: + +Request timestamp in _ctime_ format, `Www Mmm dd HH:MM:SS YYYY`. + +`%T`:: + +Request timestamp in ISO format, `YYYY-mm-ddTHH:MM:SS.000`. + + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/xlat/index.adoc b/doc/antora/modules/unlang/pages/xlat/index.adoc new file mode 100644 index 0000000..b42f725 --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/index.adoc @@ -0,0 +1,56 @@ += String Expansion + +String expansion is a feature that allows strings to dynamically +define their value at run time. For historical reasons, these string +expansions are called "xlats". + +String expansion is performed via the following syntax: + +`%{...}` + +Where the `%{` signals the start of a dynamic expansion, and `}` +signals the end of the dynamic expansion. The contents of the +expansion can be many things: + +.String Expansions +[options="header"] +|===== +| Keyword | Description +| xref:xlat/attribute.adoc[attributes] | Expand the value of a named attribute. +| xref:xlat/character.adoc[single character] | Single character expansions. +| xref:xlat/module.adoc[modules] | Pass a string to a module such as `sql`. +| xref:xlat/alternation.adoc[condition] | Conditionally expand a string. +| xref:xlat/builtin.adoc[built-in expansions] | Such as string length, tolower, etc... +|===== + +This feature is used to create policies which refer to concepts rather +than to specific values. For example, a policy can be created that +refers to the User-Name in a request, via: + +`%{User-Name}` + +This string expansion is done only for double-quoted strings and for +the back-tick operator. + +== Caveats + +Unlike other languages, there is no way to define new variables. All +of the string expansions must refer to attributes that already exist, +or to modules that will return a string value. + +== Character Escaping + +Some characters need to be escaped within a dynamically expanded +string `%{...}`. The `%` character is used for variable expansion, so a +literal `%` character can be created by using `%%`. + +Other than within a dynamically expanded string, very little +character escaping is needed. The rules of the enclosing string context +determine whether or not a space or " character needs to be escaped. + +.Example + +`Reply-Message := "%{User-Name} with a literal %%` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/pages/xlat/module.adoc b/doc/antora/modules/unlang/pages/xlat/module.adoc new file mode 100644 index 0000000..3ce4322 --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/module.adoc @@ -0,0 +1,18 @@ += Module References + +Individual modules may be referenced via the following syntax: + +`%{module:string}` + +These references are allowed only by a small number of modules that +usually perform database lookups. The module name is the actual name of +the module, as described earlier. The string portion is specific to each +module and is not documented here. It is, however, usually dynamically +expanded to allow for additional flexibility. + +.Examples + +`%{sql:SELECT name FROM mytable WHERE username = %{User-Name}}` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. diff --git a/doc/antora/modules/unlang/partials/rcode_table.adoc b/doc/antora/modules/unlang/partials/rcode_table.adoc new file mode 100644 index 0000000..e114e74 --- /dev/null +++ b/doc/antora/modules/unlang/partials/rcode_table.adoc @@ -0,0 +1,39 @@ +[options="header"] +[cols="15%,85%"] +|===== +| Return code | Description +| `fail` | The operation failed. Usually as a result of an + external dependency like a database being unavailable + or an internal error. +| `handled` | The request has been "handled", no further policies + in the current section should be called, and the section + should immediately exit. +| `invalid` | The request, or operation, was invalid. In the case of + requests this usually indicates absent or malformed + attribute values. +| `noop` | The operation did nothing. +| `notfound` | A 'lookup' operation returned no results. +| `ok` | Operation completed successfully but did not change any + attributes in the request. +| `reject` | The operation indicates the current request should be + 'rejected'. What this actually means is different from + protocol to protocol. It usually means that access to + the requested resource should be denied, or that the + current request should be NAKd. Usually returned when + provided credentials were invalid. +| `updated` | The operation completed successfully and updated one + or more attributes in the request. +| `disallow` | Access to a particular resource is + denied. This is similar to `reject` but is the result + of an authorizational check failing, as opposed to + credentials being incorrect. +| `yield` | Returned by an operation when execution of a request should + be suspended. +|===== + +[NOTE] +==== +In versions ≤ v3.0.x the `disallow` rcode was called `userlock`. `disallow` and +`userlock` have an identical meaning. `disallow` will be returned in any +instance where `userlock` was returned in v3.0.x +==== diff --git a/doc/bugs b/doc/bugs new file mode 100644 index 0000000..086ca34 --- /dev/null +++ b/doc/bugs @@ -0,0 +1,175 @@ +BUGS + +0. INTRODUCTION + + The FreeRADIUS web site is at <URL: https://freeradius.org>, and + most information referenced in this document can be found there. + + This is primarily for non-developers of the FreeRADIUS server. If you are + able to patch the code to work correctly, then we invite you to join the + development list to discuss it. If you're the type who know little about + how to code, then this is the place for you! + + +1. YOU FOUND A BUG + + Where the server terminates ungracefully due to a bus error, + segmentation violation, or other memory error, you should create + a new issue in the issue tracker <URL: http://bugs.freeradius.org>, + including information from sections 4 and 5. + + For other issues, you should first discuss them on the users list, + to see if anyone can reproduce them. Often there's a simple explanation + of why the server behaves as it does, and it's not necessarily a bug in + the code, so browse the lists' archives of the last two months, and if + you don't see messages about it, ask! + + If the behavior is correct but confusing, we think that's a bug too, and + you should file a bug against our documentation. + + For more information about the users list, the lists' archives and the + faq, please visit https://freeradius.org/support/ + Please make sure to READ and RESPECT the house-rules. You will get much + better response and much faster if you do! + + +2. CORE DUMPS + + If the server, or one of the accompanying programs core dumps, then + you should rebuild the server as follows: + + $ ./configure --enable-developer + $ make + $ make install + + and then run the program again. You may have to to enable core + dumps, via: + + $ ulimit -c unlimited + + When it core dumps, do: + + $ gdb /path/to/executable /path/to/core/file + + Enable logging in gdb via the following commands: + + (gdb) set logging file gdb-radiusd.log + (gdb) set logging on + + and follow the instructions in section 4, below. + + You can also enable the "panic_action" given in raddb/radiusd.conf. + See the comments in that file for more details about automatically + collecting gdb debugging information when the server crashes. + + +3. DEBUGGING A LIVE SERVER + + If you can't get a core dump, or the problem doesn't result in a + core dump, you may have to run the server under gdb. To do this, + ensure that you have symbols in the binaries (i.e. a non-stripped + binary) by re-building the server as described in the previous + section. Then, run the server under gdb as follows: + + $ gdb radiusd + + Enable logging in gdb via the following commands: + + (gdb) set logging file gdb-radiusd.log + (gdb) set logging on + + Tell gdb to pass any necessary command-line arguments to the + server: + + (gdb) set args ... + + Where the "..." are the command-line arguments you normally pass to + radiusd. For debugging, you probably want to do: + + (gdb) set args -f + + Then, do: + + (gdb) run + + When something interesting happens, you can hit CTRL-C in the + window, and you should be back at the gdb prompt: + + (gdb) + + And follow the instructions in section 4, below. + + +4. OBTAINING USEFUL INFORMATION + + Once you have a core dump loaded into gdb, or FreeRADIUS running under + gdb, you may use the commands below to get useful information about + the state of the server. + + If the server was built with threads, you can do: + + (gdb) info threads + + Which will give you information about the threads. If the server + isn't threaded, that command-line will print a message saying so. + + Then, do: + + (gdb) thread apply all bt full + + If the server isn't threaded, the "thread apply" section isn't necessary + + The output should be printed to the screen, and also sent to the + gdb-radiusd.log file. + + You should then submit the information from the log file, along with + any server output, the output of radiusd -xv, and information about your + operating system to: + + http://bugs.freeradius.org/ + + Submitting it to the bug database ensures that the bug report won't + get forgotten, and that it will be dealt with in due course. + + You should provide the issue number in any mail sent to the user's list. + + +5. VALGRIND + + On Linux systems, "valgrind" is a useful tool that can catch certain + classes of bugs. To use it, run the server voa: + +$ valgrind --tool=memcheck --leak-check=full radiusd -Xm + + It will print out certain kinds of errors to the screen. There may + be a number of errors related to OpenSSL, dlopen(), or libtldl. We + cannot do anything about those problems. However, any errors that are + inside of the FreeRADIUS source should be brought to our attention. + + +6. RUNNING WITH "SCREEN" + + If the bug is a crash of the server, and it takes a long time for the + crash to happen, perform the following steps: + + * log in as root + * open a screen session (https://www.gnu.org/software/screen/) + $ screen bash + * make sure FreeRADIUS is not running + * make sure you have all the debug symbols about, or a debugable + version of the server installed + * configure screen to log to a file; 'Ctrl-A H' + * type 'gdb /path/to/radius' (or /path/to/freeradius on Debian) + * at the (gdb) prompt, type 'run -X' + * detach from screen 'Ctrl-A D' + * when you notice FreeRADIUS has died, reconnect to your screen session + $ screen -D -r + * at the (gdb) prompt type 'where' or for *lots* of info try + 'thread apply all bt full' + * tell screen to stop logging, 'Ctrl-A H' + * logout from screen + +-- + +FreeRADIUS Project, copyright 2014 +$Id$ diff --git a/doc/concepts/aaa.rst b/doc/concepts/aaa.rst new file mode 100644 index 0000000..5d897c6 --- /dev/null +++ b/doc/concepts/aaa.rst @@ -0,0 +1,99 @@ +Authorization, Authentication, and Accounting request handling +============================================================== + +There are a lot of questions about misconfigured FreeRADIUS servers +because of misunderstanding of FreeRADIUS operations. This document +explains how the server operates. + +Normally there are 2 steps in processing authentication request coming +from NAS in FreeRADIUS (plus additional steps to proxy request if we +use FreeRADIUS as a proxy): authorization and authentication. + + +Authorization +------------- + +Authorization is a process of obtaining information about the user +from external source (file, database or LDAP), and checking that the +information in request is enough to authenticate user. Authorization +modules deal with data sources, so ldap, sql, files, passwd are +authorization modules. + +The authentication method is decided during the authorization phase, +along with any reply attributes. The reason for this behaviour is +that for example, a user may not be permitted to use a particular +authentication method. So during the authorize phase, we can deny +them the ability to use that kind of authentication. + +Authentication +-------------- + +Authentication is simply a process of comparing user's credentials in +request with credentials stored in database. Authentication usually +deals with password encryption. PAP, CHAP, MS-CHAP are authentication +modules. Few modules act as both authorization and authentication. +For example, the MS-CHAP module is normally authentication only, but it +may be used during authorization to verify that request contains +MS-CHAP related attribute and only in this case perform MS-CHAP based +authentication. LDAP is normally an authorization module, but it may +be used for authentication (In this case FreeRADIUS will authenticate +user in case he can connect to LDAP server with his account). SQL is +only an authorization module, as dial-in users are not normally given +passwords to access an SQL server. + + +Request Processing +------------------ + +During authorization and authentication processes, there are 3 lists +of RADIUS attributes supported by FreeRADIUS: request items, config +items and reply items. (See 'man 5 users' for additional +information.) Attributes from the RADIUS authentication request +packet are included into request items list. Both authorization and +authentication modules can add attributes into reply items list. These +attributes will be added to reply will be sent by RADIUS server to +NAS. There is third list, called config items. It's used for +internal FreeRADIUS operations, for example to pass some data from +authorization to authentication module. + +Before authorization begins FreeRADIUS creates request items list with +attributes from request and empty config and reply lists. + +An authorization module searches a database with attributes +(e.g. User-Name) taken from request list as a key, and fetches all +relevant records. It retrieves 3 types of attributes: check +attributes, configure attributes and reply attributes. It compares the +check attributes with attributes from request items. If none of +database record for this User-Name matches in check attributes with +request items authorization will fail. If a matching record is found, +then the configure attributes will be added to configure items, and +the reply attributes will be added to reply items list. The check +list may be required if we need to authenticate users with same name +for different services (for example to treat User1 from NAS1 and User1 +from NAS2 as different users). + +There should be at list one configure attribute provided by +authorization module, called Auth-Type (since this attribute is from +config items list it can't be in request or reply). This attribute +decides which module will be used to authenticate the user. The +Config items also contains information from database required to +authenticate user, for example valid user's password or it's hash, +login restrictions, etc. + +A quite common mistake is to place the attributes in the wrong lists, +for example placing Auth-Type, Password, NT-Password etc in the check +list, or in the reply list. When run in debugging mode, the server +will normally issue 'WARNING' messages saying that the attributes are +in the wrong list. + +If you place Password into check list and user does cleartext +authentication it may work, because authorization module compares 2 +cleartext passwords. But if user does some encrypted authentication +(for example MS-CHAP), then the authorization will fail, because the +Password in the request items will not match the password in the check +attributes. You should place Password attribute obtained from +database into configure items and also place Auth-Type attribute with +value of 'MS-CHAP' into same list. The same goes for NT-Password +(before calling MS-CHAP Password attribute should be converted to +NT-Password, it may be achieved by calling mschap module in +authorization section after module which does actual authorization). diff --git a/doc/concepts/proxy.rst b/doc/concepts/proxy.rst new file mode 100644 index 0000000..1af597a --- /dev/null +++ b/doc/concepts/proxy.rst @@ -0,0 +1,118 @@ +FreeRADIUS as a proxy RADIUS server. +==================================== + + +Introduction +------------ + +It is possible to use FreeRADIUS as a proxy RADIUS server. This +means that it can consult a remote RADIUS server to validate a user. +This is handy for roaming setups, or for renting ports to someone else. + +Files +----- + +If a user logs in with a defined realm syntax, the "realm" portion is +matched against the configuration to determine how the request should +be handled. Common realm formats are: + +:: + + username@realm + realm/username + username%realm + realm\username + +The realm parsing syntax ( and search order ) is user definable via the +realm module config in the ``/etc/raddb/mods-available/realm`` configuration +file. + +You can define multiple instances of the realm module to support multiple +realm syntax's at the same time. Be sure to pay close attention to the +search order that you define, as you may inadvertently get unexpected +behaviour ( by having a user use ``realm1/username@realm2`` for instance ). +If you need to proxy to IPASS, it should go first, because usernames will +be in the form ``IPASS/username@realm`` and you want to proxy these users to +IPASS, not to the realm behind the ``@``. + +The realms are configured in the file ``/etc/raddb/proxy.conf``, which is +included by ``radiusd.conf``. The formats and sample configurations are +included as comments. + +The realm ``DEFAULT`` (without the quotes) matches all realms. +The realm ``NULL`` matches any requests WITHOUT a realm. + +If you set the remote server to ``LOCAL``, the request will be handled +locally as usual, without sending it to a remote radius server. + +There are several options you can add in ``/etc/raddb/proxy.conf``: + +- nostrip: + By default the realm is stripped from the username before sending it + on to the remote radius server. By specifying the "nostrip" option + the @realm suffix will not be stripped. +- hints + By default the original username is sent to the remote radius + server. By specifying the "hints" option the username will be + sent as it is after the "hints" file was processed. +- notrealm: + By default if a realm is matched, it will be proxied to the server + specified. However, if you are using Replication functionality, you + may want to override this behaviour. This option will prevent a + user who enters ``user@foobar`` from being proxied if the ``foobar`` + realm configuration contains ``notrealm``. This function used to be + called ``notsuffix``, and the old syntax is still supported. + +The ``/etc/raddb/realms`` file is deprecated and should not be used anymore. +If you use the ``/etc/raddb/realms`` file to enter realm configurations you will +need to add the hostname and secret for the remote server in the +file ``/etc/raddb/clients.conf``. +It is not recommended to use both the realms file and the proxy.conf file, +as that could cause confusion. + +Accounting +---------- + +All accounting data for proxied requests does `not` get stored in the +standard logfiles, but in a separate directory. The name of this +directory is the name of the remote radius server. + +Remote Server +---------------- + +When your server proxies requests to another server, it acts as a NAS for +the remote server. On the remote server, you need to add the hostname of +your server and the same secret to ``/etc/raddb/clients.conf`` as well. + +As you might not control the remote radius server, you might want to +control the attributes sent back by the remote server in an Access-Accept +packet. Have a look at the attrs file for this! + +What Happens +--------------- +The exact thing that happens is this: + +- A user logs in with a realm +- The hints file gets processed as usual +- The user is checked against the huntgroups file. At this point + the user `might` already be rejected. +- The realm is looked up in the realms file. If it isn't defined, + the users file is processed normally. +- If the ``notrealm`` option is defined, the user is processed + locally. +- The realm is stripped from the username unless ``nostrip`` was + set, and the request is sent to a remote radius server. Note that + any stripping done in the hints file doesn't have an effect on the + username sent to the remote radius server unless you set the + ``hints`` option. +- The remote server replies with Access-Accept or Access-Reject + +:: + + On Access-Accept: The initial Auth-Type is set to Accept + On Access-Reject: The initial Auth-Type is set to Reject + +Then the users file is processed as usual. The username used at +this point is the one after hints file processing (regardless of +the ``hints`` option). It also includes the realm (regardless of the +setting of the ``nostrip`` option) unless the realm is ``LOCAL``. diff --git a/doc/configuration/acct_type.rst b/doc/configuration/acct_type.rst new file mode 100644 index 0000000..e8abff4 --- /dev/null +++ b/doc/configuration/acct_type.rst @@ -0,0 +1,71 @@ +Acct-Type +========= + +FreeRADIUS supports the Acct-Type attribute to select between +accounting methods based on arbitrary attribute/value pairs contained +in an accounting packet. Its use follows the same general configuration +syntax as Auth-Type and Autz-Type. The main difference in configuration +between Acct-Type and Auth/Autz-Type lies in where the Acct-Type +method is assigned. With Auth/Autz-Type, the method is typically +assigned in the 'users' file. The 'users' file, naturally, is not +processed during the handling of the accounting {} section. However, +part of the default files {} module is the 'acct_users' file, which +serves the same purpose as the 'users' file, but applies to accounting +packets. + +For example, a server administrator is responsible for handling the +accounting data for two different realms, foo.com and bar.com, and +wishes to use different instances of the SQL module for each. In +addition, there is one RADIUS client sending accounting data that is +to be logged only to a specific detail file. Everything else should +use a third SQL instance. + +The acct_users file would look something like this:: + + DEFAULT Realm == "foo.com", Acct-Type := "SQLFOO" + + DEFAULT Realm == "bar.com", Acct-Type := "SQLBAR" + + DEFAULT Client-IP-Address == "10.0.0.1", Acct-Type := "OTHERNAS" + +And in radiusd.conf:: + + $INCLUDE ${confdir}/sql0.conf # Instance named 'sql0'. + $INCLUDE ${confdir}/sql1.conf # Instance named 'sql1'. + $INCLUDE ${confdir}/sql2.conf # Instance named 'sql2'. + + detail othernas { + filename = ${radacctdir}/10.0.0.1/detail-%Y%m%d + } + + preacct { + suffix # Add the Realm A/V pair. + files # Add the Acct-Type A/V pair based on the Realm A/V pair. + } + + accounting { + + # If Acct-Type is SQLFOO use the 'sql1' instance of the SQL module. + + Acct-Type SQLFOO { + sql1 + } + + # If Acct-Type is SQLBAR, use the 'sql2' instance of the SQL module. + + Acct-Type SQLBAR { + sql2 + } + + # If Acct-Type is OTHERNAS, use the 'othernas' instance of the detail + # module + + Acct-Type OTHERNAS { + othernas + } + + # If we've made it this far, we haven't matched an Acct-Type, so use + # the sql0 instance. + + sql0 + } diff --git a/doc/configuration/autz_type.rst b/doc/configuration/autz_type.rst new file mode 100644 index 0000000..a91e4e5 --- /dev/null +++ b/doc/configuration/autz_type.rst @@ -0,0 +1,88 @@ +Autz-Type +========= + +Like Auth-Type for authentication method selection freeradius also +supports the Autz-Type to select between authorization methods. The only +problem is that authorization is the first thing to be called when an +authentication request is handled. As a result we first have to call the +authorize section without checking for Autz-Type. After that we check for +Autz-Type and if it exists we call the corresponding subsection in the +authorize section. In other words the authorize section in radiusd.conf +should look like this:: + + authorize{ + suffix + preprocess + # whatever other authorize modules here + Autz-Type Ldap{ + ldap + } + Autz-Type SQL{ + sql + } + files + } + +What happens is that the first time the authorize section is examined the +suffix, preprocess and files modules are executed. If Autz-Type is set +after that the server core checks for any matching Autz-Type subsection. +If one is found it is called. The users file should look something +like this:: + + DEFAULT Called-Station-Id == "123456789", Autz-Type := Ldap + + DEFAULT Realm == "other.example.com", Autz-Type := SQL + +Autz-Type could also be used to select between multiple instances of +a module (ie sql or ldap) which have been configured differently. For +example based on the user realm different ldap servers (belonging to +different companies) could be queried. If Auth-Type was also set then we +could do both Authentication and Authorization with the user databases +belonging to other companies. In detail: + +radiusd.conf:: + + authenticate{ + Auth-Type customer1{ + ldap1 + } + Auth-Type customer2{ + ldap2 + } + } + + authorize{ + preprocess + suffix + Autz-Type customer1{ + ldap1 + } + Autz-Type customer2{ + ldap2 + } + files + } + +The users file:: + + DEFAULT Realm == "customer1", Autz-Type := customer1, Auth-Type := customer1 + + DEFAULT Realm == "customer2", Autz-Type := customer2, Auth-Type := customer2 + + +Apart from Autz-Type the server also supports the use of +Acct-Type, Session-Type and Post-Auth-Type for the corresponding sections. +The corresponding section names in the radiusd.conf file are the same. So for example: + +users file:: + + DEFAULT Called-Station-Id == "236473", Session-Type := SQL + +radiusd.conf:: + + session { + radutmp + Session-Type SQL { + sql + } + } diff --git a/doc/configuration/configurable_failover.rst b/doc/configuration/configurable_failover.rst new file mode 100644 index 0000000..4e21335 --- /dev/null +++ b/doc/configuration/configurable_failover.rst @@ -0,0 +1,476 @@ +Configurable Module Fail Over +============================= + +Before configurable module failover, we had this kind of entry in +``radiusd.conf``: + +:: + + #--- + authorize { + preprocess + files + } + #--- + +This entry instructed the ``authorize`` section to first process the +request through the ``preprocess`` module, and if that returned success, +to process it through ``files`` module. If that sequence returned +success, then the ``authorize`` stage itself would then return success. +Processing was strictly linear and if one module failed, the whole +section would fail immediately. + +Configurable failover provides more flexibility. It takes advantage +of the tree structure of radiusd.conf to support a configuration +language that allows you to ``group`` modules that should work together +in ways other than simple lists. You can control the flow of any +stage (e.g. ``authorize``) to fit your needs, without touching C code, +just by altering radiusd.conf. + +This configurable fail-over has a convenient short-hand, too. +Administrators commonly want to say things like "try SQL1, if it's +down, try SQL2, otherwise drop the request." + +For example: + +:: + + #--- + modules { + sql sql1 { + # configuration to connect to SQL database one + } + sql sql2 { + # configuration to connect to SQL database two + } + always handled { + rcode = handled + } + } + + # Handle accounting packets + accounting { + detail # always log to detail, stopping if it fails + redundant { + sql1 # try module sql1 + sql2 # if that's down, try module sql2 + handled # otherwise drop the request as + # it's been ``handled`` by the ``always`` + # module (see doc/rlm_always) + } + } + #--- + +The ``redundant`` section is a configuration directive which tells the +server to process the second module if the first one fails. Any +number of modules can be listed in a ``redundant`` section. The server +will process each in turn, until one of the modules succeeds. It will then stop processing the ``redundant`` list. + +Rewriting results for single modules +------------------------------------ + +Normally, when a module fails, the entire section (``authorize``, +``accounting``, etc.) stops being processed. In some cases, we may want +to permit "soft failures". That is, we may want to tell the server +that it is "ok" for a module to fail, and that the failure should not +be treated as a fatal error. + +In this case, the module is treated as a "section", rather than just +as a single lne in ``radiusd.conf``. The configuration entries for +that section are taken from the ``configurable fail-over`` code, and not +from the configuration information for that module. + +For example, the ``detail`` module normally returns ``fail`` if it is +unable to write its information to the ``detail`` file. As a test, we +can configure the server so that it continues processing the request, +even if the ``detail`` module fails. The following example shows how: + +:: + + #-- + # Handle accounting packets + accounting { + detail { + fail = 1 + } + redundant { + sql1 + sql2 + handled + } + } + #-- + +The ``fail = 1`` entry tells the server to remember the ``fail`` code, +with priority ``1``. The normal configuration is ``fail = return``, which +means ``if the detail module fails, stop processing the accounting +section``. + +Fail-over configuration entries +------------------------------- + +Modules normally return on of the following codes as their result: + ++-----------+-----------------------------------------------------+ +|Code | Meaning | ++===========+=====================================================+ +|notfound | the user was not found | ++-----------+-----------------------------------------------------+ +|noop | the module did nothing | ++-----------+-----------------------------------------------------+ +|ok | the module succeeded | ++-----------+-----------------------------------------------------+ +|updated | the module updated information in the request | ++-----------+-----------------------------------------------------+ +|fail | the module failed | ++-----------+-----------------------------------------------------+ +|reject | the module rejected the user | ++-----------+-----------------------------------------------------+ +|userlock | the user was locked out | ++-----------+-----------------------------------------------------+ +|invalid | the user's configuration entry was invalid | ++-----------+-----------------------------------------------------+ +|handled | the module has done everything to handle the request| ++-----------+-----------------------------------------------------+ + +In a configurable fail-over section, each of these codes may be +listed, with a value. If the code is not listed, or a configurable +fail-over section is not defined, then values that make sense for the +requested ``group`` (group, redundant, load-balance, etc) are used. + +The special code ``default`` can be used to set all return codes to +the specified value. This value will be used with a lower priority +than ones that are explicitly set. + +The values for each code may be one of two things: + ++---------+---------------------------------------------------------------+ +|Value | Meaning | ++=========+===============================================================+ +|<number> | Priority for this return code. | ++---------+---------------------------------------------------------------+ +|return | Stop processing this configurable fail-over list. | ++---------+---------------------------------------------------------------+ +|reject | Stop processing this configurable fail-over list and | +| | immediately return a reject. | ++---------+---------------------------------------------------------------+ + +The ``<number>`` used for a value may be any decimal number between 1 +and 99999. The number is used when processing a list of modules, to +determine which code is returned from the list. For example, if +``module1`` returns ``fail`` with priority ``1``, and a later ``module2`` +returns ``ok`` with priority ``3``, the return code from the list of +modules will be ``ok``, because it has higher priority than ``fail``. + +This configurability allows the administrator to permit some modules +to fail, so long as a later module succeeds. + + +More Complex Configurations +--------------------------- + +The ``authorize`` section is normally a list of module names. We can +create sub-lists by using the section name ``group``. The ``redundant`` +section above is just a short-hand for ``group``, with a set of default +return codes, which are different than the normal ``stop processing the +list on failure``. + +For example, we can configure two detail modules, and allow either +to fail, so long as one of them succeeds. + +:: + + #-- + # Handle accounting packets + accounting { + group { + detail1 { + fail = 1 # remember ``fail`` with priority 1 + ok = return # if we succeed, don't do ``detail2`` + } + detail2 { + fail = 1 # remember ``fail`` with priority 1 + ok = return # if we succeed, return ``ok`` + # if ``detail1`` returned ``fail`` + } + } # returns ``fail`` only if BOTH modules returned ``fail`` + redundant { + sql1 + sql2 + handled + } + } + #-- + +This configuration says: + + - log to ``detail1``, and stop processing the ``group`` list if ``detail1`` returned OK. + + - If ``detail1`` returned ``fail``, then continue, but remember the ``fail`` code, with priority 1. + + - If ``detail2`` fails, then remember ``fail`` with priority 1. + + - If ``detail2`` returned ``ok``, return ``ok`` from the ``group``. + +The return code from the ``group`` is the return code which was either +forced to return (e.g. ``ok`` for ``detail1``), or the highest priority +return code found by processing the list. + +This process can be extended to any number of modules listed in a +``group`` section. + + +Virtual Modules +--------------- + +Some configurations may require using the same list of modules, in +the same order, in multiple sections. For those systems, the +configuration can be simplified through the use of ``virtual`` modules. +These modules are configured as named sub-sections of the +``instantiate`` section, as follows: + +:: + + instantiate { + ... + + redundant sql1_or_2 { + sql1 + sql2 + } + } + +The name ``sql1_or_2`` can then be used in any other section, such as +``authorize`` or ``accounting``. The result will be *exactly* as if that +section was placed at the location of the ``sql1_or_2`` reference. + +These virtual modules are full-fledged objects in and of themselves. +One virtual module can refer to another virtual module, and they can +contain ``if`` conditions, or any other configuration permitted in a +section. + + +Redundancy and Load-Balancing +----------------------------- + +See ``man unlang`` or ``doc/load-balance`` for information on simple +redundancy (fail-over) and load balancing. + + +The Gory Details +----------------- + +The fundamental object is called a MODCALLABLE, because it is something that +can be passed a specific radius request and returns one of the RLM_MODULE_* +results. It is a function - if you can accept the fact that pieces of +radiusd.conf are functions. There are two kinds of MODCALLABLEs: GROUPs and +SINGLEs. + +A SINGLE is a reference to a module instance that was set up in the modules{} +section of radiusd.conf, like ``preprocess`` or ``sql1``. When a SINGLE is +called, the corresponding function in the rlm is invoked, and whichever +RLM_MODULE_* it returns becomes the RESULT of the SINGLE. + +A GROUP is a section of radiusd.conf that includes some MODCALLABLEs. +Examples of GROUPs above include ``authorize{...}``, which implements the C +function module_authorize, and ``redundant{...}``, which contains two SINGLEs +that refer to a couple of redundant databases. Note that a GROUP can contain +other GROUPs - ``Auth-Type SQL{...}`` is also a GROUP, which implements the C +function module_authenticate when Auth-Type is set to SQL. + +Now here's the fun part - what happens when a GROUP is called? It simply runs +through all of its children in order, and calls each one, whether it is +another GROUP or a SINGLE. It then looks at the RESULT of that child, and +takes some ACTION, which is basically either ``return that RESULT immediately`` +or ``Keep going``. In the first example, any ``bad`` RESULT from the preprocess +module causes an immediate return, and any ``good`` RESULT causes the +authorize{...} GROUP to proceed to the files module. + +We can see the exact rules by writing them out the long way: + +:: + + authorize { + preprocess { + notfound = 1 + noop = 2 + ok = 3 + updated = 4 + fail = return + reject = return + userlock = return + invalid = return + handled = return + } + files { + notfound = 1 + noop = 2 + ok = 3 + updated = 4 + fail = return + reject = return + userlock = return + invalid = return + handled = return + } + } + +This is the same as the first example, with the behavior explicitly +spelled out. Each SINGLE becomes its own section, containing a list of +RESULTs that it may return and what ACTION should follow from them. So +preprocess is called, and if it returns for example RLM_MODULE_REJECT, +then the reject=return rule is applied, and the authorize{...} GROUP +itself immediately returns RLM_MODULE_REJECT. + +If preprocess returns RLM_MODULE_NOOP, the corresponding ACTION is ``2``. An +integer ACTION serves two purposes - first, it tells the parent GROUP to go +on to the next module. Second, it is a hint as to how desirable this RESULT +is as a candidate for the GROUP's own RESULT. So files is called... suppose +it returns RLM_MODULE_NOTFOUND. The ACTION for notfound inside the files{...} +block is ``1``. We have now reached the end of the authorize{...} GROUP and we +look at the RESULTs we accumulated along the way - there is a noop with +preference level 2, and a notfound with preference level 1, so the +authorize{...} GROUP as a whole returns RLM_MODULE_NOOP, which makes sense +because to say the user was not found at all would be a lie, since preprocess +apparently found him, or else it would have returned RLM_MODULE_NOTFOUND too. + +We could use the ``default`` code to simplify the above example a +little. The following two configurations are identical: + +:: + + files { + notfound = 1 + noop = 2 + ok = 3 + updated = 4 + default = return + } + + +When putting the ``default`` first, later definitions over-ride it's +return code: + +:: + + files { + default = return + notfound = 1 + noop = 2 + ok = 3 + updated = 4 + } + +[Take a deep breath - the worst is over] + +That RESULT preference/desirability stuff is pretty complex, but my hope is +that it will be complex enough to handle the needs of everyone's real-world +imperfect systems, while staying out of sight most of the time since the +defaults will be right for the most common configurations. + +So where does redundant{...} fit in with all that? Well, redundant{...} is +simply a group that changes the default ACTIONs to something like + +:: + + fail = 1 + everythingelse = return + +so that when one module fails, we keep trying until we find one that doesn't +fail, then return whatever it returned. And at the end, if they all failed, +the redundant GROUP as a whole returns RLM_MODULE_FAIL, just as you'd want it +to (I hope). + +There are two other kinds of grouping: ``group{...}`` which does not have any +specialized default ACTIONs, and ``append{...}``, which should be used when you +have separate but similarly structured databases that are guaranteed not to +overlap. + +That's all that really needs to be said. But now a few random notes: + +GROUPs may have RESULT=ACTION +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It would look like this: + +:: + + authorize { + preprocess + redundant { + sql1 + sql2 + notfound = return + } + files + } + +which would prevent ``files`` from being called if neither of the SQL +instances could find the user. + +redundant{...} and append{...} are just shortcuts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You could write: + +:: + + group { + sql1 { + fail = 1 + notfound = 2 + noop = return + ok = return + updated = return + reject = return + userlock = return + invalid = return + handled = return + } + sql2 { + fail = 1 + notfound = 2 + noop = return + ok = return + updated = return + reject = return + userlock = return + invalid = return + handled = return + } + } + instead of + redundant { + sql1 + sql2 + } + +but the latter is just a whole lot easier to read. + +``authenticate{...}`` is not a GROUP +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +even though it contains a list of ``Auth-Type`` GROUPs, because its +semantics are totally different - it uses ``Auth-Type`` to decide which of +its members to call, and their order is irrelevant. + +The default rules are context-sensitive +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For ``authorize``, the defaults are +what you saw above - notfound, noop, ok, and updated are considered +success, and anything else has an ACTION of ``return``. For authenticate, the +default is to return on success *or* reject, and only try the second and +following items if the first one fails. You can read all the default ACTIONs +in modcall.c (int defaultactions[][][]), or just trust me. They do the right +thing. + +There are some rules that can't be implemented in this language +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +things like ``notfound = 1-reject``, ``noop = 2-ok``, ``ok = 3-ok``, etc. But I don't feel +justified adding that complexity in the first draft. +There are already enough things here that may never see real-world usage. +Like append{...} + +-- Pac. 9/18/2000 diff --git a/doc/configuration/dynamic_home_servers.md b/doc/configuration/dynamic_home_servers.md new file mode 100644 index 0000000..7518f0a --- /dev/null +++ b/doc/configuration/dynamic_home_servers.md @@ -0,0 +1,238 @@ +# Dynamic Home Servers in v3 + +FreeRADIUS has some support for dynamic home servers, with certain +limitations. + + +## Configuration + +The configuration needs to have dynamic home servers enabled, by +editing `proxy.conf`. + +``` +proxy server { + ... + dynamic = true + ... +} +``` + +This configuration item causes the internal data structures to become +thread-safe for updates. This change means that there will be more +lock contention on the data structures holding home servers. As a +result, high-load proxy may see slowdowns. + +Once dynamic home servers are enabled, they should be placed into +a subdirectory. FreeRADIUS should be told which subdirectory the +home servers are located in: + +``` +proxy server { + ... + dynamic = true + ... + directory = ${raddb}/home_servers/ +} +``` + +This directory should contain nothing other than definitions for +dynamic home servers. These definitions are simply normal +`home_server` definitions: + +``` +home_server example.com { + ... +} +``` + +Each file in the directory should be named for the home server domain +name. In the above example, the filename should be +`${raddb}/home_servers/example.com`. The name of the home server in +the file should be the same as the filename which contains the home +server definition. + +Each file in the directory should have one, and only one, +`home_server` definition. + +Home servers which use RadSec can `$INCLUDE tls.conf` in this +directory to use a common site-local TLS configuration. The script +`freeradius-naptr-to-home-server.sh` referenced below assumes that +this file exists. If you are not using that file, it is safe to just +replace it with an empty file. + +### The Control Socket + +The virtual server `sites-enabled/control` *must* be enabled for +dynamic home servers to work. The `radmin` program *must* have +read/write permission in order for dynamic home servers to work. + +Please see that `sites-enabled/control` file for information on +configuring that virtual server. + + +## Starting FreeRADIUS + +When FreeRADIUS starts, it will read each file in the +`${raddb}/home_servers/` directory. The file will parsed in order to +define a dynamic `home_server`. + + +## Adding a new Home Server + +In order to add a new home server while FreeRADIUS is running, simply +add a new `home_server` definition file to the +`${raddb}/home_servers/` directory. + +Then, tell FreeRADIUS that the home server is available in a new file: + +``` +$ radmin -e "add home_server file /path/to/raddb/home_servers/example/com" +``` + +If all goes well, the home server will be added. If there are issues, +`radmin` will print a descriptive error. + +Once a dynamic home server has been added, it can be used just like +any other home server. + + +## Deleting a Home Server + +Dynamically created home servers can be deleted via `radmin`. Note +also that dynamic home servers which are loaded when FreeRADIUS starts +can be deleted. + +``` +$ radmin -e "del home_server file <name> <type>" +``` + +Note that this command deletes the home server by name and type, not +by filename. This difference from the `add home_server` command is +due to internal limitations in the server core. + +``` +home_server <name> { + type = <type> +} +``` + + +## Listing a Home Server + +It is possible to list all home servers and know which is dynamic or no. + +``` +$ radmin -e "show home_server list all" +``` + + +## Limitations + +Note that due to internal limitations, dynamic home servers are _not_ +freed. So repeatedly adding and deleted home servers _will_ cause +FreeRADIUS to gradually use more memory. + +Other internal limitations means that it is impossible to add dynamic +home servers to a `home_server_pool`. In short, dynamic home servers +exist by themselves, with no associated realm, pool, or failover +capability. + + +## Proxying to a Home Server + +The new attribute `Home-Server-Name` controls proxying to a particular +home server. The home server just has to exist, it does not need to +be a dynamic home server. + +``` +authorize { + ... + + update control { + Home-Server-Name := "example.com" + } + ... +} +``` + + +## Checking if a Dynamic Home Server exists + +You can see if a dynamic home server exists through the following +dynamic string expansion: + +``` +%{home_server_dynamic:name} +``` + +This expansion looks up the home server by name, and returns whether +or not the home server exists, and is dynamic. + +The return values are: + +* empty string - the home server does not exist. +* `0` - the home server exists, and is statically defined. +* `1` - the home server exists, and is dynamically defined + +``` +authorize { + ... + if (User-Name =~ /@(.*)$/) { + switch "%{home_server_dynamic:%{1}}" { + case "1" { + # Proxy to this one particular home server + update control { + &Home-Server-Name := "%{1}" + } + } + + case "0" { + # Proxy with home server pool, failover, etc. + update control { + &Proxy-To-Realm := "%{1}" + } + } + + case { + # no home server exists, ask DNS + update control { + # you can add a parameter for the NAPTR tag to look up, e.g. "aaa+auth:radius.tls.tcp" (RFC7585, OpenRoaming) + # if the third parameter is omitted, it defaults to "x-eduroam:radius.tls" + &Temp-Home-Server-String := `%{config:confdir}/mods-config/realm/freeradius-naptr-to-home-server.sh -d %{config:confdir} %{1}` + } + if ("%{control:Temp-Home-Server-String}" == "" ) { + reject + } else { + update control { + &Home-Server-Name := "%{1}" + } + } + } + } + } + ... +} +``` + +## Maintenance of Dynamic Home Servers + +Dynamic home servers are discovered from DNS, and DNS has TTLs. These +TTLs are not tracked by FreeRADIUS, as they are not available when +using the standard DNS APIs. + +Dynamic realms should be regularly deleted, so that they can be +recreated with updated information. The server should be restarted +with an empty home_server directory regularly, for two reasons: + +* Entries in DNS may change over time, or be removed, and the server should learn this. + If the entries are not removed, the server will not discover any changes. +* dynamic home servers are often RADIUS/TLS based with client and server certificates, + and the server should refresh CRL information regularly + +As a result, we recommend emptying the home_servers directory (except +for the `tls.conf` file), refreshing CRLs and then restarting the server +once per day. e.g. + +``` +rm -f $(ls -1 raddb/home_servers | egrep -v tls.conf) +``` diff --git a/doc/configuration/load_balance.rst b/doc/configuration/load_balance.rst new file mode 100644 index 0000000..7926444 --- /dev/null +++ b/doc/configuration/load_balance.rst @@ -0,0 +1,172 @@ +Load Balancing +============== + +As of version 2.0.0, the load balance documentation is in the +available in the "unlang" man page. The text below may not be up to +date, and is here only for historical purposes. + +As of version 1.1.0, FreeRADIUS supports load balancing in module +sections. Please see the "configurable_failover" file in this +directory for a more complete description of module sections. + +The short summary is that you can use a "load-balance" section in +any place where a module name may be used. The semantics of the +"load-balance" section are that one of the modules in the section will +be chosen at random, evenly spread over the modules in the list. + +An example is below:: + + accounting { + load-balance { + sql1 + sql2 + sql2 + } + } + +In this case, 1/3 of the RADIUS requests will be processed by +"sql1", one third by "sql2", and 1/3 by "sql3". + +The "load-balance" section can be nested in a "redundant" section, +or vice-versa:: + + accounting { + load-balance { # between two redundant sections below + redundant { + sql1 + sql2 + } + redundant { + sql2 + sql1 + } + } + } + +This says "load balance between sql1 and sql2, but if sql1 is down, +use sql2, and if sql2 is down, use sql1". That way, you can guarantee +both that load balancing occurs, and that the requests are *always* +logged to one of the databases:: + + accounting { + redundant { + load-balance { + sql1 + sql2 + } + detail + } + } + +This says "load balance between sql1 and sql2, but if the one being +used is down, then log to detail". + +And finally:: + + accounting { + redundant { # between load-balance & detail + load-balance { # between two redundant sections + redundant { + sql1 + sql2 + } + redundant { + sql2 + sql1 + } + } + detail + } + } + +This says "try to load balance between sql1 and sql2; if sql1 is down, +use sql2; if sql2 is down use sql1; if both sql1 and sql2 are down, +then log to the detail file" + + +More complicated scenarios +-------------------------- + +If you want to do redundancy and load-balancing among three +modules, the configuration is quite complex:: + + load-balance { + redundant { + sql1 + load-balance { + redundant { + sql2 + sql3 + } + redundant { + sql3 + sql2 + } + } + } # sql1, etc. + redundant { + sql2 + load-balance { + redundant { + sql3 + sql1 + } + redundant { + sql1 + sql3 + } + } + } # sql2, etc. + redundant { + sql3 + load-balance { + redundant { + sql1 + sql2 + } + redundant { + sql2 + sql1 + } + } + } # sql3, etc. + } + +For four or more modules, it quickly becomes unmanageable. + +The solution is to use the "redundant-load-balance" section, which +combines the features of "load-balance", with "redundant" fail-over +between members. The above complex configuration for three modules +then becomes:: + + redundant-load-balance { + sql1 + sql2 + sql3 + } + + +Which means "load-balance evenly among all three servers. If the +one picked for load-balancing is down, load-balance among the +remaining two. If that one is down, pick the one remaining 'live' +server". + +The "redundant-load-balance" section can contain any number of +modules. + + +Interaction with "if" and "else" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's best to have "if" and "else" blocks contain "load-balance" or +"redundant-load-balance" sections, rather than the other way around. +The "else" and "elsif" sections cannot appear inside of a +"load-balance" or "redundant-load-balance" section, because the "else" +condition would be chose as one of the modules for load-balancing, +which is not what you want. + +It's OK to have a plain "if" block inside of a "load-balance" or +"redundant-load-balance" section. In that case, the "if" condition +checks the return code of the module or group that executed just +before the "load-balance" section. It does *not* check the return +code of the previous module in the section. diff --git a/doc/configuration/post_auth_type b/doc/configuration/post_auth_type new file mode 100644 index 0000000..7492324 --- /dev/null +++ b/doc/configuration/post_auth_type @@ -0,0 +1,44 @@ +This is now called Post-Auth-Type, for consistency. + +O.INTRODUCTION + + Post-Auth-Type is used to select between groupings of + modules in the post-auth stanza using arbitrary attributes. + It is functionally identical to Acct-Type, apart from + the name of the attribute and its dealing with rejected + requests.. This means that (unlike Autz-Type) the attribute + must be set before the stanza is run. Changes to + Post-Auth-Type during post-auth will have no effect. + +1.HOW IT WORKS + + If a request has been rejected, the value of Post-Auth-Type + is overwritten with REJECT automatically, so anonymous + modules outside the REJECT substanza will not be run, only + modules within the appropriate substanza will be run. + +2.EXAMPLES + + In the example below, when a request has been rejected, the + module my_ippool will not be run, only the module my_detail + will be run. + If the request is not rejected, the my_ippool module will be + run, but not the my_detail module + + post-auth { + my_ippool + Post-Auth-Type REJECT { + my_detail + } + } + + In the following example, 2 different sql modules are used + to store accepted requests and rejected requests. + + post-auth { + my_sql_accept + Post-Auth-Type REJECT { + my_sql_reject + } + } + diff --git a/doc/configuration/session_type b/doc/configuration/session_type new file mode 100644 index 0000000..9efcd7c --- /dev/null +++ b/doc/configuration/session_type @@ -0,0 +1,10 @@ +Session-Type is used to select between groupings of +modules in the session stanza using arbitrary attributes. +It is functionally identical to Acct-Type, apart from +the name of the attribute. This means that (unlike +Autz-Type) the attribute must be set before the stanza +is run. Changes to Session-Type during session will +have no effect. + +This allows Simultaneous-Use checking behaviour to be very flexible. + diff --git a/doc/configuration/simultaneous_use b/doc/configuration/simultaneous_use new file mode 100644 index 0000000..5639738 --- /dev/null +++ b/doc/configuration/simultaneous_use @@ -0,0 +1,173 @@ + + FreeRADIUS server and the Simultaneous-Use parameter. + + +0. INTRODUCTION + + Lots of people want to limit the number of times one user account can + login, usually to one. This is hard to do with the radius protocol; + the nature of the accounting stuff is such that the idea the radius server + has about the list of logged-in users might be different from the idea + the terminal server has about it. + + However, most terminal servers have an alternative way to get a list + of logged-in users. Most support some way through telnet, some have + a finger-daemon builtin and a lot of them support SNMP. So if the + radius server thinks that someone is trying to login a second time, + it is possible to check on the terminal server itself if the first + login is indeed still active. Only then access is denied for the + second login. + + +1. PREREQUISITES + + You need to have perl installed. + + For SNMP checks, you have 2 options. You can use the `snmpget' program + from the cmu-snmp tools. You can probably get precompiled ones, + maybe even packaged for your system (Debian/Linux, Redhat/Linux, FreeBSD + ports collection etc). The source code is at + http://www.net.cmu.edu/projects/snmp/snmpapps/. The Linux-specific + version of this is at http://www.gaertner.de/snmp/ + + The other option is to install the SNMP_Session and BER modules that + for example the well known `mrtg' package uses. This is recommended. + In that case you need no external snmpget program, checkrad will + speak SNMP directly. See http://www.switch.ch/misc/leinen/snmp/perl/ + + The checkroutine for USR/3Com Total Control racks uses the Net::Telnet + module from CPAN, at least version 3.00. If you need that, obtain it from + your local CPAN mirror (or see http://www.perl.com/CPAN/). The checkrad.pl + perl script will autodetect if that module is installed. + +2. USAGE. + + It works by adding the `check' parameter "Simultaneous-Use" to the entry + for a users or DEFAULT in /etc/raddb/users. It should be at least one; + it defines the maximum number of users logged in with the same account name. + For example: + + # + # Simultaneous use restrictions. + # + DEFAULT Group == "staff", Simultaneous-Use := 4 + Fall-Through = 1 + DEFAULT Group == "business", Simultaneous-Use := 2 + Fall-Through = 1 + DEFAULT Simultaneous-Use := 1 + Fall-Through = 1 + + + NOTE!!! The "Simultaneous-Use" parameter is in the "check" A/V pairs, + and not in the Reply A/V pairs (it _is_ a check). + + For SQL, after creating and populating your schema, you should + execute the following statement (for MySQL, others may vary): + + INSERT INTO radgroupcheck (GroupName, Attribute, op, Value) values("dialup", "Simultaneous-Use", ":=", "1"); + + Once that is done, your users should be limited to only one login at a time. + +3. IMPLEMENTATION + + The server keeps a list of logged-in users in the /var/log/radutmp file. + This is also called "the session database". When you execute "radwho", + all that radwho really does is list the entries in this file in a pretty + format. Only when someone tries to login who _already_ has an active + session according to the radutmp file, the server executes the perl + script /usr/local/sbin/checkrad (or /usr/sbin/checkrad, it checks for + the presence of both and in that order). This script queries the terminal + server to see if the user indeed already has an active session. + + The script uses SNMP for Livingston Portmasters and Ciscos, finger for + Portslave, Computone and Ascend, and Net::Telnet for USR/3Com TC. + + Since the script has been witten in perl, it's easy to adjust for + any type of terminal server. There are implementations in the script for + checks using SNMP, finger, and telnet, so it should be easy to add + your own check routine if your terminal server is not supported yet. + + You can find the script in the file src/checkrad.pl. + + You need to set the correct type in the file /etc/raddb/naslist so that + checkrad KNOWS how it should interrogate the terminal server. At this + time you can define the following types: + + type Vendor Uses method needs Need naspasswd + ==== ====== =========== ===== ============== + ascend Lucent SNMP SNMP No + bay Nortel finger finger command No + cisco Cisco SNMP SNMP Optional [1] + computone Computone finger finger command No + cvx Nortel SNMP SNMP No + digitro Digitro rusers rusers command No + livingston Livingston SNMP SNMP No [2] + max40xx Lucent finger finger command No + netserver USR/3com telnet CPAN Net::Telnet Yes + pathras Cyclades telnet CPAN Net::Telnet Yes + patton Patton SNMP SNMP No + portslave ? finger finger command No + pr3000 Cyclades SNMP snmpwalk command No + pr4000 Cyclades SNMP snmpwalk command No + tc USR/3com telnet CPAN Net::Telnet Yes + usrhyper USR/3com SNMP SNMP No [3] + versanet VersaNet SNMP SNMP No + + other none N/A - No + + [1] In naspasswd file: set username to SNMP, password is community. + [2] Needs at least ComOS 3.5, SNMP enabled. + [3] Set "Reported Port Density" to 256 (default) + + "other" means "don't bother checking, I believe what radutmp says". + This really is not recommended, if a user has a "stuck" entry in the + session database she will not be able to login again - hence the + extra check that "checkrad" does. + +4. IF IT DOESN'T WORK + + Note that you need to add the Simultaneous-Use parameter to the + check item (first line), not the reply item, using the ':=' operator. + + You can edit the `checkrad' perl script and turn on debugging. Then + watch the debug file. The `radius.log' file also gives some hints. + + You can also run the "checkrad" script manually, use the "-d" + switch to get debug output on standard output instead of in the log. + + See also: + + http://wrath.geoweb.ge/simult.html + + which has a good discussion of the use of Simultaneous-Use. + + +5. CAVEATS + + This solution checks the radutmp file. This file is kept up-to-date from + the Accounting records the NAS sends. Since some NASes delay these records + for quite some time, it is possible to get a double login by logging in + twice at _exactly_ the same time (plus or minus the mentioned delay time), + since neither of the logins are registered yet. + + The solution would be to create a small 1-minute cache of Authentication + records, that is also checked for double login attempts. Perhaps in the + next version. + + When implementing this one thing was considered the most important: when + trying to detect double logins, we always try to err on the safe side. So + in rare cases, a double login is possible but we try never to limit access + for a legitimate login. + +6. PROBLEMS WITH DROPPED CONNECTIONS + + Our PM3, with 2 ISDN-30 lines coming into it, had the habit of sometimes + dropping connections. In a few cases, the portmaster thought the session was + still alive so if the user tried to login again, he or she was denied access. + In our case, this problem was caused by a bad PRI line from the phone + company. + + We tried to compensate this by setting the Idle-Timeout to 15 minutes. That + way, even if a user did get locked out the portmaster would clear the rogue + session within 15 minutes and the user could login again. + diff --git a/doc/configuration/snmp b/doc/configuration/snmp new file mode 100644 index 0000000..713cb83 --- /dev/null +++ b/doc/configuration/snmp @@ -0,0 +1,58 @@ +INSTALL +------- + +Installing the SNMP patch is straightforward: + +$ tar -zxf freeradius-server-2.1.11.tar.gz +$ cd freeradius-server-2.1.11 +$ patch -p1 < ../snmp.patch +$ ./configure --args.... +$ make +$ make install + +MIB Installation +---------------- + +The traps *REQUIRE* that the files in the "mibs" directory be copied +to the global mibs directory, usually /usr/share/snmp/mibs/. +If this is not done, the "snmptrap" program has no idea what information +to send, and will not work. The MIB installation is *NOT* done as +part of the default installation, so that step *MUST* be done manually. + +The global MIB directory can be found by running the following command: + + $ snmptranslate -Dinit_mib .1.3 2>&1 | grep MIBDIR | sed "s/' .*//;s/.* '//;s/.*://" + +Or maybe just: + + $ snmptranslate -Dinit_mib .1.3 2>&1 | grep MIBDIR + +If you have copied the MIBs to that directory, you can test the +FreeRADIUS MIBs by running the following command: + + $ snmptranslate -m +FREERADIUS-NOTIFICATION-MIB -IR -On serverStart + +It should print out: + + .1.3.6.1.4.1.11344.4.1.1 + +As always, run the server in debugging mode after enabling the +traps. You will see the "snmptrap" command being run, and it will +print out any errors or issues that it encounters. Those need to +be fixed before running the server in daemon mode. + +We also suggest running in debugging mode as the "radiusd" user, if +you have "user/group" set in radiusd.conf. The "snmptrap" program +may behave differently when run as "root" or as the "radiusd" user. + +You will also need to edit "radiusd.conf", and uncomment the line saying + + # $INCLUDE trigger.conf + +That will enable the triggers. + + +More Documentation +------------------ + +See raddb/trigger.conf for complete documentation. diff --git a/doc/configuration/variables.rst b/doc/configuration/variables.rst new file mode 100644 index 0000000..4a2f28c --- /dev/null +++ b/doc/configuration/variables.rst @@ -0,0 +1,151 @@ +Run-time variables +================== + +See "man unlang" for more complete documentation on the run-time +variables. This file is here only for historical purposes. + +The above variable expansions also support the following +meta-attributes. These are not normal RADIUS attributes, but are +created by the server to be used like them, for ease of use. They can +only be queried, and cannot be assigned. + ++-----------------------+-------------------------------------------------+ +| Packet-Type | RADIUS packet type (Access-Request, etc.) | ++-----------------------+-------------------------------------------------+ +| Packet-Src-IP-Address | IP address from which the packet was sent | ++-----------------------+-------------------------------------------------+ +| Packet-Dst-IP-Address | IP address to which the packet was sent. | +| | This may be "0.0.0.0", if the server | +| | was configured with ``bind_address = *``. | ++-----------------------+-------------------------------------------------+ +| Packet-Src-Port | UDP port from which the packet was sent | ++-----------------------+-------------------------------------------------+ +| Packet-Dst-Port | UDP port to which the packet was sent. | ++-----------------------+-------------------------------------------------+ + +``%{config:section.subsection.item}`` + Corresponding value in ``radiusd.conf`` for the string value of that item. + +The ``%{config:...}`` variables should be used VERY carefully, as they +may leak secret information from your RADIUS server, if you use them +in reply attributes to the NAS! + +:: + + DEFAULT User-Name =~ "^([^@]+)@(.*)" + All-That-Matched = `%{0}` + Just-The-User-Name = `%{1}` + Just-The-Realm-Name = `%{2}` + + +The variables are used in dynamically translated strings. Most of the +configuration entries in ``radiusd.conf`` (and related files) will do +dynamic string translation. To do the same dynamic translation in a +RADIUS attribute (when pulling it from a database, or "users" file), +you must put the string into an back-quoted string: + +:: + + Session-Timeout = `%{expr: 2 + 3}` + +To do the dynamic translation in the ``radiusd.conf`` (or some other +configuration files), just use the variable as-is. See +``radiusd.conf`` for examples. + + +Attributes as environment variables in executed programs +-------------------------------------------------------- + +When calling an external program (e.g. from ``rlm_exec`` module), these +variables can be passed on the command line to the program. In +addition, the server places all of the attributes in the RADIUS +request into environment variables for the external program. The +variables are renamed under the following rules: + + #. All letters are made upper-case. + #. All hyphens '-' are turned into underscores '_' + +so the attribute ``User-Name`` can be passed on the command line to the +program as ``%{User-Name}``, or used inside the program as the environment +variable ``USER_NAME`` (or ``$USER_NAME`` for shell scripts). + +If you want to see the list of all of the variables, try adding a line +``printenv > /tmp/exec-program-wait`` to the script. Then look in the +file for a complete list of variables. + +One-character variables +----------------------- + +The following one-character variables were defined. They were duplicates of the +previous general cases, and were only provided for backwards compatibility. +They are in the process of being removed, this table documents the old variables +and their new equivalents. +(i.e. ``:-``, as described above. + ++-----------+---------------------------+-----------------------+ +| Variable | Description | Proper Equivalent | ++===========+===========================+=======================+ +|%a |Protocol (SLIP/PPP) |%{Framed-Protocol} | ++-----------+---------------------------+-----------------------+ +|%c |Callback-Number |%{Callback-Number} | ++-----------+---------------------------+-----------------------+ +|%d |request day (DD) | | ++-----------+---------------------------+-----------------------+ +|%f |Framed IP address |%{Framed-IP-Address} | ++-----------+---------------------------+-----------------------+ +|%i |Calling Station ID |%{Calling-Station-Id} | ++-----------+---------------------------+-----------------------+ +|%l |request timestamp | | ++-----------+---------------------------+-----------------------+ +|%m |request month (MM) | | ++-----------+---------------------------+-----------------------+ +|%n |NAS IP address |%{NAS-IP-Address} | ++-----------+---------------------------+-----------------------+ +|%p |Port number |%{NAS-Port} | ++-----------+---------------------------+-----------------------+ +|%s |Speed (PW_CONNECT_INFO) |%{Connect-Info} | ++-----------+---------------------------+-----------------------+ +|%t |request in ctime format | | ++-----------+---------------------------+-----------------------+ +|%u |User name |%{User-Name} | ++-----------+---------------------------+-----------------------+ +|%A |radacct_dir |%{config:radacctdir} | ++-----------+---------------------------+-----------------------+ +|%C |clientname | | ++-----------+---------------------------+-----------------------+ +|%D |request date (YYYYMMDD) | | ++-----------+---------------------------+-----------------------+ +|%G |request minute | | ++-----------+---------------------------+-----------------------+ +|%H |request hour | | ++-----------+---------------------------+-----------------------+ +|%I |request ID | | ++-----------+---------------------------+-----------------------+ +|%L |radlog_dir |%{config:logdir} | ++-----------+---------------------------+-----------------------+ +|%M |MTU |%{Framed-MTU} | ++-----------+---------------------------+-----------------------+ +|%R |radius_dir |%{config:raddbdir} | ++-----------+---------------------------+-----------------------+ +|%S |request timestamp | | +| |in SQL format | | ++-----------+---------------------------+-----------------------+ +|%T |request timestamp | | +| |in database format | | ++-----------+---------------------------+-----------------------+ +|%U |Stripped User name |%{Stripped-User-Name} | ++-----------+---------------------------+-----------------------+ +|%V |Request-Authenticator | | +| |(Verified/None) | | ++-----------+---------------------------+-----------------------+ +|%v |Server Version | | ++-----------+---------------------------+-----------------------+ +|%Y |request year (YYYY) | | ++-----------+---------------------------+-----------------------+ +|%Z |All request attributes | | +| |except password | | +| |(must have a big buffer) | | ++-----------+---------------------------+-----------------------+ + + + $Id$ diff --git a/doc/deployment/CYGWIN.rst b/doc/deployment/CYGWIN.rst new file mode 100644 index 0000000..da61d49 --- /dev/null +++ b/doc/deployment/CYGWIN.rst @@ -0,0 +1,283 @@ +FreeRADIUS for EAP under CygWin +=============================== + +From: "Philip Blow" <philipb@simplywireless.com.au> +To: <freeradius-users@lists.cistron.nl> +Date: Wed, 29 Jan 2003 15:23:45 +1100 + +Here are some brief notes I but together for compiling FreeRADIUS 0.8.1 +on Windows XP with EAP/TLS support. + +Configuring FreeRADIUS for EAP under CygWin. +-------------------------------------------- + +#. Installing CygWin + + Install the latest version of CygWin (at time of writing 1.3.19-1) from http://www.cygwin.com + +#. Install the following packages (make as minimum list) + + +--------------------+-----------------+ + | Package | Version | + +====================+=================+ + | _update-info-dir | 00126-1 | + +--------------------+-----------------+ + | ash | 20020731-1 | + +--------------------+-----------------+ + | autoconf | 2.54-1 | + +--------------------+-----------------+ + | autoconf-devel | 2.57-1 | + +--------------------+-----------------+ + | autoconf-stable | 2.13-4 | + +--------------------+-----------------+ + | automake | 1.7.1-1 | + +--------------------+-----------------+ + | automake-devel | 1.7.2-1 | + +--------------------+-----------------+ + | automake-stable | 1.4p5-5 | + +--------------------+-----------------+ + | base-files | 1.1-1 | + +--------------------+-----------------+ + | base-passwd | 1.0-1 | + +--------------------+-----------------+ + | bash | 2.05b-8 | + +--------------------+-----------------+ + | bc | 1.06-1 | + +--------------------+-----------------+ + | binutils | 20021117-1 | + +--------------------+-----------------+ + | byacc | 1.9-1 | + +--------------------+-----------------+ + | bzip2 | 1.0.2-2 | + +--------------------+-----------------+ + | crypt | 1.0-1 | + +--------------------+-----------------+ + | cygrunsrv | 0.95-1 | + +--------------------+-----------------+ + | cygutils | 1.1.3-1 | + +--------------------+-----------------+ + | cygwin | 1.3.19-1 | + +--------------------+-----------------+ + | cygwin-doc | 1.3-2 | + +--------------------+-----------------+ + | diff | 1.0-1 | + +--------------------+-----------------+ + | diffutils | 2.8.1-1 | + +--------------------+-----------------+ + | ed | 0.2-1 | + +--------------------+-----------------+ + | file | 3.37-1 | + +--------------------+-----------------+ + | fileutils | 4.1-1 | + +--------------------+-----------------+ + | findutils | 4.1.7-4 | + +--------------------+-----------------+ + | gawk | 3.1.1-5 | + +--------------------+-----------------+ + | gcc | 3.2-3 | + +--------------------+-----------------+ + | gcc-mingw | 20020817-5 | + +--------------------+-----------------+ + | gcc2 | 2.95.3-10 | + +--------------------+-----------------+ + | gdb | 20021218-1 | + +--------------------+-----------------+ + | gdbm | 1.8.0-4 | + +--------------------+-----------------+ + | gettext | 0.11.5-1 | + +--------------------+-----------------+ + | grep | 2.5-1 | + +--------------------+-----------------+ + | groff | 1.18.1-2 | + +--------------------+-----------------+ + | gzip | 1.3.3-4 | + +--------------------+-----------------+ + | inetutils | 1.3.2-20 | + +--------------------+-----------------+ + | initscripts | 0.9-1 | + +--------------------+-----------------+ + | less | 378-1 | + +--------------------+-----------------+ + | libbz2_0 | 1.0.2-1 | + +--------------------+-----------------+ + | libbz2_1 | 1.0.2-2 | + +--------------------+-----------------+ + | libiconv2 | 1.8-2 | + +--------------------+-----------------+ + | libintl | 0.10.38-3 | + +--------------------+-----------------+ + | libintl1 | 0.10.40-1 | + +--------------------+-----------------+ + | libintl2 | 0.11.5-1 | + +--------------------+-----------------+ + | libltdl3 | 20030103-1 | + +--------------------+-----------------+ + | libncurses5 | 5.2-1 | + +--------------------+-----------------+ + | libncurses6 | 5.2-8 | + +--------------------+-----------------+ + | libpng10 | 1.0.14-2 | + +--------------------+-----------------+ + | libpng12 | 1.2.4-2 | + +--------------------+-----------------+ + | libpopt0 | 1.6.4-4 | + +--------------------+-----------------+ + | libreadline4 | 4.1-2 | + +--------------------+-----------------+ + | libreadline5 | 4.3-2 | + +--------------------+-----------------+ + | libtool | 20020202a-1 | + +--------------------+-----------------+ + | libtool-devel | 20021227-1 | + +--------------------+-----------------+ + | libtool-stable | 1.4.2-2 | + +--------------------+-----------------+ + | libxml2 | 2.4.23-1 | + +--------------------+-----------------+ + | login | 1.7-1 | + +--------------------+-----------------+ + | m4 | 1.4-1 | + +--------------------+-----------------+ + | make | 3.79.1-7 | + +--------------------+-----------------+ + | man | 1.5j-1 | + +--------------------+-----------------+ + | mingw-runtime | 2.3-1 | + +--------------------+-----------------+ + | mktemp | 1.4-1 | + +--------------------+-----------------+ + | more | 2.11o-1 | + +--------------------+-----------------+ + | nasm | 0.98.35-1 | + +--------------------+-----------------+ + | ncurses | 5.2-8 | + +--------------------+-----------------+ + | newlib-man | 20020801 | + +--------------------+-----------------+ + | openssh | 3.5p1-3 | + +--------------------+-----------------+ + | openssl | 0.9.7-1 | + +--------------------+-----------------+ + | openssl-devel | 0.9.7-1 | + +--------------------+-----------------+ + | openssl096 | 0.9.6h-1 | + +--------------------+-----------------+ + | patch | 2.5.8-2 | + +--------------------+-----------------+ + | pcre | 3.7-1 | + +--------------------+-----------------+ + | perl | 5.6.1-2 | + +--------------------+-----------------+ + | readline | 4.3-2 | + +--------------------+-----------------+ + | sed | 4.0.5-1 | + +--------------------+-----------------+ + | sh-utils | 2.0.15-3 | + +--------------------+-----------------+ + | sharutils | 4.2.1-2 | + +--------------------+-----------------+ + | sysvinit | 2.84-3 | + +--------------------+-----------------+ + | tar | 1.13.25-1 | + +--------------------+-----------------+ + | tcltk | 20021218-1 | + +--------------------+-----------------+ + | termcap | 20020930-1 | + +--------------------+-----------------+ + | terminfo | 5.2-3 | + +--------------------+-----------------+ + | texinfo | 4.2-4 | + +--------------------+-----------------+ + | textutils | 2.0.21-1 | + +--------------------+-----------------+ + | tiff | 3.5.7-1 | + +--------------------+-----------------+ + | time | 1.7-1 | + +--------------------+-----------------+ + | unzip | 5.50-1 | + +--------------------+-----------------+ + | vim | 6.1-2 | + +--------------------+-----------------+ + | w32api | 2.1-1 | + +--------------------+-----------------+ + | wget | 1.8.2-2 | + +--------------------+-----------------+ + | which | 1.5-1 | + +--------------------+-----------------+ + | xinetd | 2.3.9-1 | + +--------------------+-----------------+ + | zip | 2.3-2 | + +--------------------+-----------------+ + | zlib | 1.1.4-1 | + +--------------------+-----------------+ + +#. Download + + Download the FreeRADIUS source code from http://www.freeradius.org/ + +#. Expand the FreeRADIUS source file. + +#. Make the following changes to the source code + (the diffs are reversed) + + :: + + src/main/Makefile.in + + 145,148c145,148 + < $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) + radiusd.exe $(R)$(sbindir) + < $(INSTALL) -m 755 $(INSTALLSTRIP) radwho.exe + $(R)$(bindir) + < $(INSTALL) -m 755 $(INSTALLSTRIP) raduse.exe + $(R)$(bindir) + < $(INSTALL) -m 755 $(INSTALLSTRIP) radzap.exe + $(R)$(bindir) + --- + > $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) + radiusd $(R)$(sbindir) + > $(INSTALL) -m 755 $(INSTALLSTRIP) radwho + $(R)$(bindir) + > $(INSTALL) -m 755 $(INSTALLSTRIP) raduse + $(R)$(bindir) + > $(INSTALL) -m 755 $(INSTALLSTRIP) radzap + $(R)$(bindir) + 150,151c150,151 + < $(INSTALL) -m 755 radclient.exe $(R)$(bindir) + < $(INSTALL) -m 755 radrelay.exe $(R)$(bindir) + --- + > $(INSTALL) -m 755 radclient $(R)$(bindir) + > $(INSTALL) -m 755 radrelay $(R)$(bindir) + + src/modules/rlm_dbm/Makefile.in + + 22,23c22,23 + < $(INSTALL) -m 755 $(INSTALLSTRIP) rlm_dbm_parser.exe + $(R)$(bindir) + < $(INSTALL) -m 755 $(INSTALLSTRIP) rlm_dbm_cat.exe + $(R)$(bindir) + --- + > $(INSTALL) -m 755 $(INSTALLSTRIP) rlm_dbm_parser $(R)$(bindir) + > $(INSTALL) -m 755 $(INSTALLSTRIP) rlm_dbm_cat $(R)$(bindir) + + src/modules/rlm_mschap/Makefile + + 20c20 + < $(INSTALL) -m 755 $(INSTALLSTRIP) smbencrypt.exe $(R)$(bindir) + --- + > $(INSTALL) -m 755 $(INSTALLSTRIP) smbencrypt $(R)$(bindir) + +#. Run configure with the following command line + + :: + + ./configure -without-snmp -disable-shared -enable-static + +#. Execute make and then make install + +:: + + Philip Blow + Senior Technical Manager + Simply Wireless + philipb@simplywireless.com.au diff --git a/doc/deployment/MACOSX b/doc/deployment/MACOSX new file mode 100644 index 0000000..39ebaec --- /dev/null +++ b/doc/deployment/MACOSX @@ -0,0 +1,12 @@ + Installing FreeRADIUS on MAC OSX + -------------------------------- + +1) download, unzip and untar freeradius.tar.gz + +2) $ ./configure + +3) $ make + +4) $ make install + +It's what the developers use, so we make sure it works. diff --git a/doc/deployment/OS2 b/doc/deployment/OS2 new file mode 100644 index 0000000..fc676c9 --- /dev/null +++ b/doc/deployment/OS2 @@ -0,0 +1,22 @@ +Compiling FreeRADIUS under OS/2 + +To compile FreeRADIUS unde OS/2 you must have a full EMX environment with GNU +utilities (like make,sh) + +The EMX can be get from http://hobbes.nmsu.edu + +To work with CVS repository you must install cvs110.zip from hobbes also + +before entering in sh.exe you must do +SET SHELL=sh.exe + +before running ./configure you must set the shell the variables : +export CC=gcc +export MAKE=fullpathofyourmake.exe +export PERL=fullpathofyourperl.exe + + +The OS/2 version of FreeRADIUS can't directly execute checkrad.pl then the +program will execute a checkrad.cmd + + diff --git a/doc/deployment/performance-testing b/doc/deployment/performance-testing new file mode 100644 index 0000000..71945c1 --- /dev/null +++ b/doc/deployment/performance-testing @@ -0,0 +1,168 @@ + +Radius Test Procedures + +0. INTRODUCTION + +This document describes how to test your radius server authentication +using random usernames and passwords with the 'radclient' program. + +1. WHY TEST + +Many people want to see the difference in efficiency behind the various +authentication methods, compilation methods, etc of their radius server. +Before now, this was difficult to do efficiently across a large number +of users. However, with this document, you'll be able to test your +radius server and determine the best options to use for your system. + +2. GETTING STARTED + +First thing we have to do is generate a large number of users. You'll +want to do this even if you have a large passwd file you want to use +from your system, because the create user script sets up other files +you need for testing. So head to the scripts/ directory, and do this: + +Make a tmp dir +# mkdir tmp +# cp create-users.pl tmp +# cd tmp + +Run the script to create 10,000 (or however many you want) random users +and passwords +# ./create-users.pl 10000 + +Output from the script will include several files: + passwd : A standard passwd file you can append to /etc/passwd + shadow : A standard shadow file you can append to /etc/shadow +passwd.nocrypt : A file with *unencrypted* users & passes in form "user:pass" + radius.test : File you'll use as input for radclient + radius.users : A standard radius 'users' file + +So, equipped with lots of users and passwords, there's several methods of +authentication you can test: + + o System users (Auth-Type:=System) + o Local users (Auth-Type:=Local) + o Cached system (passwd) users + o Others + +NOTE: Before moving on, you will probably want to add '/dev/null' to +/etc/shells *temporarily* so that default system authentication will +work. REMEMBER TO TAKE IT OUT! + +3. TEST PROCEDURES + + A. System (/etc/passwd) users testing + + 1. Append the 'passwd' file from create-users.pl onto your + system passwd file: + + # cat ./passwd >> /etc/passwd + + 2. If you have shadow, append the shadow file onto /etc/shadow + + # cat ./shadow >> /etc/shadow + + 3. Make sure you have a DEFAULT user similar to the following + in your radius 'users' file: + + DEFAULT Auth-Type:=System + Reply-Message = "Success!" + + 4. Start radiusd + + # /usr/local/sbin/radiusd + + 5. Run radclient with 'radius.test' as the input file. + + NOTE: First you need to setup a secret for your local + machine in the 'clients' file and use that secret below + + # time /usr/local/bin/radclient -q -s -f radius.test \ + <yourhostname> auth <secret> + + NOTE: The above is to be put all on one line. + + NOTE: Some systems do not have the 'time' command, + so you may need to break out the stopwatch instead :) + + Take note of the output of radclient. If there were lots of + failures, something is wrong. All authentications should + succeed. + + 6. Take note of the output from the above 'time' command. + The output format should be something similar to the + following (on linux, this for example only!): + + 1.72user 0.53system 5:11.34elapsed 0%CPU + (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs + (340major+29minor)pagefaults 0swaps + + This means it took 5:11 (311 seconds) to authenticate + 10,000 users. Simple division tells us this is: + + 10,000 auths / 311 seconds = 32.1543 auths/second + + B. Local users testing + + 1. Copy the 'radius.users' file from the script over your 'users' + file. Make sure you do NOT have a DEFAULT entry or you will + invalidate this test. + + 2. Restart radiusd (kill and restart) + + 3. Run radclient (See A-5 above for NOTES on this): + + # time /usr/local/bin/radclient -q -s -f radius.test \ + <yourhostname> auth <secret> + + 4. Take note of the output from the above 'time' command, and + divide the number of auths (10,000 in this case) with the + number of seconds it took to complete. See A6 above for + more info. + + C. Cached system users + + 1. Set 'cache=yes' in your radiusd.conf file + + 2. Restart radiusd (ie, kill it and restart, not just a HUP) + + 3. Perform the same steps outlined above for testing System users (A) + + D. Other methods + + There is no reason why you can't use some of this to test modules + for PAM, SQL, LDAP, etc, but that will require a little extra + work on your end (ie, getting the users/passes you generated into + the corresponding database). However, by now you should have a + good idea of how to test once you do that. + + Also, play around with compile options like --with-thread, + --with-thread-pool, etc. Run radiusd with '-s' so it runs + one process only, etc etc. Play around with it. + +4. CAVEATS + +The above test procedures make no allowances for users that login with +incorrect usernames or passwords. If you want a true test of performance, +you should add in lots of bad usernames and passwords to the radius.test +file and then re-run 'radclient' with that file as input. + +Additionally, these tests make no reference to how the pre-authenticate, +post-authenticate, and accounting methods you choose could affect server +performance. For example, checking for simultaneous use after authenti- +cating the user is obviously going to slow down authenticate performance. + +The numbers you get from this test are raw authentications/second in a +perfect environment. Do not expect this kind of result in the real world. +However, having tested in this manner, you will have a good idea of which +authentication methods and compilation options give you the best base to +start from, which is key to an efficient server. + +5. RESULTS + +I'd really rather not post results because they will vary tremendously +with other system-specific configuration. This is exactly the reason +you should run tests of this nature, to find what's best for *your* +system. Good luck! + + diff --git a/doc/deployment/supervise-radiusd.rst b/doc/deployment/supervise-radiusd.rst new file mode 100644 index 0000000..e4922ed --- /dev/null +++ b/doc/deployment/supervise-radiusd.rst @@ -0,0 +1,163 @@ + +Supervising the Radiusd Daemon +============================== + +Introduction +------------ + +We all hope that our radius daemons won't die in the middle of the +nite stranding customer and beeping beepers. But, alas, it's going to +happen, and when you least expect it. That's why you want a another +process watching your radius daemon, restarting it if and when it +dies. + +This text describes how to setup both the free radius daemon so that +it is automatically restarted if the process quits unexpectedly. To +do this, we'll use either Dan Bernstein's 'daemontools' package or the +inittab file. Note: The radwatch script that used to be part of this +distribution, is depreciated and SHOULD NOT BE USED. + +Setting Up Daemontools +---------------------- + +First, download (and install) daemontools from: + + http://cr.yp.to/daemontools.html + +The latest version as of this writing is 0.70. It would be well worth +your while to read all the documentation at that site too, as you can +do much more with daemontools than I describe here. + +Next, we'll need a directory for the radius 'service' to use with +daemontools. I usually create a dir '/var/svc' to hold all my +daemontool supervised services. i.e.:: + + $ mkdir /var/svc + $ mkdir /var/svc/radiusd + +Now we just need a short shell script called 'run' in our new service +directory that will start our daemon. The following should get you +started:: + + #!/bin/sh + # Save as /var/svc/radiusd/run + exec /usr/local/sbin/radiusd -s -f + +Of course you'll want to make that 'run' file executable:: + + $ chmod +x /var/svc/radiusd/run + +Note, you *MUST* use the '-f' option when supervising. That option +tells radiusd not to detach from the tty when starting. If you don't +use that option, the daemontools will always think that radiusd has +just died and will (try to) restart it. Not good. + +Now the only left to do is to start the 'supervise' command that came +with daemontools. Do that like so:: + + $ supervise /var/svc/radiusd + +Maintenance With Daemontools +---------------------------- + + Any maintenance you need to do with almost certainly be done with the + 'svc' program in the deamontools package. i.e.:: + + Shutdown radiusd: + $ svc -d /var/svc/radiusd + + Start it back up: + $ svc -u /var/svc/radiusd + + Send HUP to radiusd: + $ svc -h /var/svc/radiusd + + Shutdown and stop supervising radiusd: + $ svc -dx /var/svc/radiusd + +Supervising With Inittab +------------------------ + +This is really pretty easy, but it is system dependent. I strongly +suggest you read the man pages for your 'init' before playing with +this. You can seriously hose your system if you screw up your +inittab. + +Add this line (or something similar to it) to your inittab:: + + fr:23:respawn:/usr/local/sbin/radiusd -f -s &> /dev/null + +Now all that's left is to have the system reread the inittab. Usually +that's done with one of the following:: + + $ telinit Q + +or:: + + $ init q + +Now you should see a 'radiusd' process when you issue a 'ps'. If you +don't, try to run the radiusd command you put in inittab manually. If +it works, that means you didn't tell the system to reread inittab +properly. If it doesn't work, that means your radius start command is +bad and you need to fix it. + +Acknowledgements +---------------- + + Document author : Jeff Carneal + daemontools auther : Dan Bernstein + Further daemontool notes (below): Antonio Dias + Radwatch note : Andrey Melnikov + +Further Daemontools notes +========================= + +Here are some notes by Antonia Dias sent to the free radius mailing +list. Some of you may find this useful after reading the above and the +docs for daemontools. + +Daemontools Instructions +------------------------ + +I am running radiusd under supervise from daemontools without +problems. The only thing I am missing right now is an option to force +radiusd to send log to stderr so I can manage logs better with +multilog (also included in daemontools package). Here is the procedure +I've been following (for Cistron RADIUS):: + + $ groupadd log + $ useradd -g log log + $ mkdir /etc/radiusd + $ mkdir /etc/radiusd/log + $ mkdir /etc/radiusd/log/main + $ chmod +t+s /etc/radiusd /etc/radiusd/log + $ chown log.log /etc/radiusd/log/main + +Here are the contents of run files from '/etc/radiusd' and '/etc/radiusd/log':: + + $ cd /etc/radiusd + $ cat run + #!/bin/sh + exec 2>&1 + exec /usr/sbin/radiusd -fyzx + $ cd /etc/radiusd/log + $ cat run + #!/bin/sh + exec setuidgid log multilog t ./main + + To make service wake-up do:: + + $ ln -sf /etc/radiusd /service + + Hang-up (to reload config) it using:: + + $ svc -h /service/radiusd + +Disable (down) it using:: + + $ svc -d /service/radiusd + +Reenable (up) it using:: + + $ svc -u /service/radiusd diff --git a/doc/deployment/tuning_guide b/doc/deployment/tuning_guide new file mode 100644 index 0000000..264749f --- /dev/null +++ b/doc/deployment/tuning_guide @@ -0,0 +1,58 @@ +------------ MAIN SERVER ------------- +o If you have a large user base and/or many authentication requests try + using a scalable authentication mechanism like ldap or sql. +o Enable noatime on all the freeradius log files or better yet on the + freeradius log directory. +o Always use the latest cvs version. It will probably contain a few + fixes and enhancements. +o Always try to use the least modules possible. In particular if you + can avoid it do not use the detail and radwtmp (files) modules. + They will slow down your accounting. +o Use the users file to only set default profiles. Do not place any + users there. Keep it as small as possible. Always set default + attributes in the users file and don't fill the user entries in + ldap/sql with default values. In general the ldap/sql user profiles + should contain user attributes only in special user cases. +o Tune thread pool parameters to match your size requirements. + Set max_requests_per_server to zero to avoid server thread restarts. +o Enlarge the timeout (10 secs) and retries (5-7) in the access servers + for accounting. That way you won't lose any accounting information. +o Use well tuned Fast Ethernet connections to minimize latency. +o freeradius is multi threaded and i/o bound. That means you should use + the latest OS kernels/patches for improved multi processor and + network performance. + +------------ LDAP MODULE ------------- +o Try to maximize caching in the ldap server. In particular *always* + enable indexing of the uid attribute (equality index) and the + cn attribute (equality index - the cn attribute is used to search + for groups). Make the ldap server entry/directory cache memory sizes + as large as possible. In general try allocating as much memory as you + can afford to your ldap server. +o Put default profiles in ldap. User entries should only contain + non standard values in order to remain small and maximize the gains + of caching the user default/regular profiles. +o Enable group caching in groups. + +------------ SQL MODULE -------------- +o Use the sql module in the session section instead of the radutmp module. + It works *much* quicker. +o Create a multi column index for the (UserName,AcctStopTime) attributes especially + if you are using sql for double login detection. +o If you are using mysql and you do a lot of accounting try using InnoDB for the radacct + table instead of MyISAM (this should be the default in all schemas) +o Add AcctUniqueId in the accounting_stop query. Especially if you have a lot of access + servers or your NAS does not send very random Session-Ids. That way you will always have + one candidate row to search for, instead of all the rows that have the same AcctSessionId + +------------ COUNTER MODULE ---------- +o Enable noatime on the counter db files. +o Tune the cache_size configuration directive to match your needs. + The cache size should be set to 2-3 * number of available nas ports. +o Keep the database in a memory mapped file if you can help. Backup the + file every 10 mins to the disk and copy it to the memory mapped one + on server startup. + +------------ RADUTMP MODULE ---------- +o Enable noatime on the radutmp file +o Don't use it diff --git a/doc/developer/autotools.md b/doc/developer/autotools.md new file mode 100644 index 0000000..a7ad6a8 --- /dev/null +++ b/doc/developer/autotools.md @@ -0,0 +1,179 @@ +FreeRADIUS use of GNU autotools +=============================== + +The full autotools suite includes many utilities, which we do not +need or want to use. Especially libtool, for which we use the +faster replacement, jlibtool. + +In a normal autotools setup, one would run "autoreconf" to rebuild +all of the configure scripts, which will perform at least the +following tasks: + + - aclocal + - autoconf + - autoheader + - automake + - libtoolize + +Specifically, all we really want to run is `autoconf`, to rebuild +the configure scripts. + +We have a more complicated setup than most. There is normally just +one `configure` script, in the top-level directory. In FreeRADIUS +there are also configure scripts in most RLM module directories as +well. Autotools is not really set up to handle this well, +preferring to treat every sub-directory as a separate project. + +This means that e.g. cache files are not shared, and include files +(for configure macros) are not found as they are expected to be in +the current directory. + +What's more, autoconf macros can be found in multiple places - the +automake install directory, the system aclocal directory, and in +multiple places in the FreeRADIUS source (mainly `m4/`, but also +`acinclude.m4`, both potentially in multiple places). + +In our setup we want to run the following only: + + - autoconf, to generate configure files and `all.mk` make files. + - autoheader, to generate header files. + + +autoconf +-------- + +`autoconf` expands a `configure.ac` file to create a `configure` +script, with optionally also a Makefile. We generate a makefile +called `all.mk` to work with the boilermake system. + +Being based on m4, autoconf needs to find macro definitions from +somewhere, which will be expanded as needed upon invocation. +autoconf has several search paths for macros, including some +system paths for its own internal macros. + +Notably within the project, autoconf looks in `aclocal.m4` to find +"local" macros to add. These days, `aclocal.m4` is supposed to be +written by the `aclocal` script, so autotools added the concept of +`acinclude.m4` to put local macros. `aclocal` will add an include +directive at the bottom of `aclocal.m4` to include the +`acinclude.m4` file, if it is found in the current directory. + +When `aclocal` is run it will scan `configure.ac` for anything +that looks like a macro to expand. It will then search project +directories, the automake system directory and the aclocal system +directory, to find any macros that match. These are copied into +the `aclocal.m4` file. `autoconf` will then pick up these macro +definitions and use them when expanding `configure.ac`. Notably, +macros can be in `*.m4` files in given search directories and +`aclocal` will extract the macros and copy them over. + +`autoconf` itself will not look in `*.m4` files, only in +`aclocal.m4` and, if that is not found, `acinclude.m4`. + +We therefore have, _within one level directory_: + + - `acinclude.m4`, local macro definitions; + - `aclocal.m4`, macros collated by `aclocal`; + - `m4/` or other directories, macro files searched by `aclocal`; + - `configure.ac` the input configure script; + - `all.mk`, `configure`, etc as outputs from `autoconf`. + +The GNU Autotools manual these days recommends splitting macros +up, one file per macro, and putting them in the `m4/` directory +rather than in the `acinclude.m4` file. This makes them much +easier to maintain. + + +FreeRADIUS sub-directories +-------------------------- + +All the above is not too much of an issue for the top-level +configure script. We can have an automatically generated +`aclocal.m4` file, macros in `m4/` and extra components in +`acinclude.m4` if needed. However, the sub-directory configure +scripts really want to be kept as small as possible. There is no +real need for a separate `aclocal.m4` file if all of the configure +scripts could be scanned together. The top-level `m4/` directory and +`acinclude.m4` file can be used. + +Unfortunately, autotools doesn't like to work like this. It wants +all files to be in one directory, and `aclocal` won't scan more +than one `configure.ac` file. + +The two compromise solutions seem to be: + + - Don't use `aclocal`. + + - Nearly all local macros are put in the top-level + `acinclude.m4` file. + - A few local macros can go in `m4/`, but they have to + explicitly included in configure.ac scripts with + `m4_include()`. + - `autoconf` has to be run with multiple `-I` include args to + capture all the places where macros could be. + - Any missing macros won't get pulled in from system + locations, because `aclocal` noramally does that. + - Sub-directories are relatively clean, e.g. no `aclocal.m4` + or `acinclude.m4` files all over the place. + + - Use `aclocal`. + + - The `-I` arg can be passed to `aclocal` which makes it + search multiple project directories for local macros to copy + to `aclocal.m4`. + - All directories with a `configure` script must have an + `aclocal.m4` file to collate macros from the top-level `m4/` + directory. + - The top-level `acinclude.m4` file is ignored except in the + top-level configure script, meaning it needs to be symlinked + or copied everywhere else. + - If `autoconf` finds an `aclocal.m4` file it no longer seems + to look for macros elsewhere. + - Sub-directories get messy with `aclocal.m4` and + `acinclude.m4` files, though these don't need to be checked + into the repository. + - The top-level `m4/` directory can contain all macros as + separate files, which is much cleaner than `acinclude.m4`. + - System macros will be found and used. + +We pretty much need to use `aclocal` - it removes the need for an +`acinclude.m4` file (tidier), picks up macros from `m4/` +automatically (tidier), removes the need for `m4_include()` macros +(tidier), and means that macros will be found that might not be +shipped in the FreeRADIUS distribution (easier). + +That comes with some downsides as above - we will end up with +`aclocal.m4` files all over the place, and have to handle the case +where things were originally in `acinclude.m4` and are not macros. + +Fixing `aclocal.m4` files can be done by either including them in +git (unnecessary) or hiding them with `.gitignore` (best). + +Picking up non-macro definitions from `acinclude.m4` can be done +by adding a new macro, `FR_INIT()`, which defines anything needed. +In fact, as long as that macro is included, the _entire_ +`m4/fr_init.m4` file will be included by `aclocal`. This means the +extra definition doesn't even need to be inside the macro. + + +Rebuilding the configure scripts +================================ + +The normal way to rebuild all of the autotools outputs is to run +`autoreconf`. This must not be run with FreeRADIUS as it will +initialise and use libtool and other things we do not want. + +Instead, we have a make target to rebuild everything needed. + + make reconfig + +This will rebuild any configure files that are out of date. +However, sometimes everything needs to be forced, e.g. due to some +macros changing that are missed by the Make dependencies (maybe +from the system directories). In this case a forced rebuild can be +undertaken with: + + find . -name configure.ac | xargs touch + make reconfig + +This will ensure that _all_ configure scripts are rebuilt. diff --git a/doc/developer/coding-methods.rst b/doc/developer/coding-methods.rst new file mode 100644 index 0000000..444696d --- /dev/null +++ b/doc/developer/coding-methods.rst @@ -0,0 +1,242 @@ +Helpful coding methods +====================== + +The following is a short set of guidelines to follow while +programming. It does not address coding styles, function naming +methods, or debugging methods. Rather, it describes the processes +which SHOULD go on in the programmers mind, while he is programming. + +Coding standards apply to function names, the look of the code, and +coding consistency. Coding methods apply to the daily practices used +by the programmer to write code. + + + +1. Comment your code. + + If you don't, you'll be forced to debug it 6 months later, when + you have no clue as to what it's doing. + + If someone REALLY hates you, you'll be forced to debug + un-commented code that someone else wrote. You don't want to do + that. + + For FreeRADIUS use doxygen @style comments so you get the benefits + of docs.freeradius.org. + +2. Give things reasonable names. + + Variables and functions should have names. Calling them 'x', + 'xx', and 'xxx' makes your life hell. Even 'foo' and 'i' are + problematic. + + Avoid smurfs. Don't re-use struct names in field names i.e. + struct smurf { + char *smurf_pappa_smurf; + } + + If your code reads as full english sentences, you're doing it + right. + + +3. Check input parameters in the functions you write. + + Your function CANNOT do anything right if the user passed in + garbage, and you were too lazy to check for garbage input. + + assert() (rad_assert()) is ugly. Use it. + + GIGO is wrong. If your function gets garbage input, it + should complain loudly and with great descriptiveness. + + +4. Write useful error messages. + + "Function failed" is useless as an error message. It makes + debugging the code impossible without source-level instrumentation. + + If you're going to instrument the code at source level for error + messages, leave the error messages there, so the next sucker won't + have to do the same work all over again. + + +5. Check error conditions from the functions you call. + + Your function CANNOT do anything right if you called another + function, and they gave you garbage output. + + One of the most common mistakes is:: + + fp = fopen(...); + fgetc(fp); /* core dumps! */ + + If the programmer had bothered to check for a NULL fp (error + condition), then he could have produced a DESCRIPTIVE error + message, instead of having his program core dump. + + +6. Core dumps are for weenies. + + If your program core dumps accidentally, you're a bad programmer. + You don't know what your program is doing, or what it's supposed + to be doing when anything goes wrong. + + If it hits an assert() and calls abort(), you're a genius. You've + thought ahead to what MIGHT go wrong, and put in an assertion to + ensure that it fails in a KNOWN MANNER when something DOES go + wrong. (As it usually does...) + + +7. Initialize your variables. + + memset() (talloc_zero()) is your friend. 'ptr = NULL' is + nice, too. + + Having variables containing garbage values makes it easy for the + code to do garbage things. The contents of local variables are + inputs to your function. See #3. + + It's also nearly impossible for you to debug any problems, as you + can't tell the variables with garbage values from the real ones. + + +8. Don't allow buffer over-runs. + + They're usually accidental, but they cause core dumps. + strcpy() and strcat() are ugly. Use them under duress. + + sizeof() is your friend. + + +9. 'const' is your friend. + + If you don't mean to modify an input structure to your function, + declare it 'const'. Declare string constants 'const'. It can't + hurt, and it allows more errors to be found at compile time. + + Use 'const' everywhere. Once you throw a few into your code, and + have it save you from stupid bugs, you'll blindly throw in 'const' + everywhere. It's a life-saver. + + +10. Use C compiler warnings. + + Turn on all of the C compiler warnings possible. You might have + to turn some off due to broken system header files, though. But + the more warnings the merrier. + + Getting error messages at compile time is much preferable to + getting core dumps at run time. See #7. + + Notice that the C compiler error messages are helpful? You should + write error messages like this, too. See #4. + + +11. Avoid UNIXisms and ASCIIisms and visualisms. + + You don't know under what system someone will try to run your code. + Don't demand that others use the same OS or character set as you use. + + Never assign numbers to pointers. If foo is a char*, and you want it + to be be null, assign NULL, not 0. The zeroth location is perfectly + as addressable as any other on plenty of OSes. Not all the world + runs on Unix (though it should :) ). + + Another common mistake is to assume that the zeroth character in the + character set is the string terminator. Instead of terminating a + string with 0, use '\0', which is always right. Similarly, memset() + with the appropriate value: NULL, '\0', or 0 for pointers, chars, + and numbers. + + Don't put tabs in string constants, either. Always use '\t' to + represent a tab, instead of ASCII 9. Literal tabs are presented to + readers of your code as arbitrary whitespace, and it's easy to mess + up. + + +12. Make conditionals explicit. + + Though it's legal to test "if (foo){}", if you test against the + appropriate value (like NULL or '\0'), your code is prettier and + easier for others to read without having to eyeball your prototypes + continuously to figure out what you're doing (especially if your + variables aren't well-named). See #2. + + +13. Test your code. + + Even Donald Knuth writes buggy code. You'll never find all of the + bugs in your code unless you write a test program for it. + + This also means that you'll have to write your code so that it + will be easily testable. As a result, it will look better, and be + easier to debug. + +Hints, Tips, and Tricks +----------------------- + +This section lists many of the common "rules" associated with code +submitted to the project. There are always exceptions... but you must +have a really good reason for doing so. + + 1. Read the Documentation and follow the CodingStyle + + The FreeRADIUS server has a common coding style. Use real tabs + to indent. There is whitespace in variable assignments. + (i = 1, NOT i=1). + + When in doubt, format your code to look the same as code already + in the server. If your code deviates too much from the current + style, it is likely to be rejected without further review, and + without comment. + + 2. #ifdefs are ugly + + Code cluttered with ifdefs is difficult to read and + maintain. Don't do it. Instead, put your ifdefs in a header, and + conditionally define 'static inline' functions, or macros, which + are used in the code. Let the compiler optimize away the "no-op" + case. + + Simple example, of poor code:: + + #ifdef CONFIG_MY_FUNKINESS + init_my_stuff(foo); + #endif + + Cleaned-up example: + + (in header):: + + #ifndef CONFIG_MY_FUNKINESS + static inline void init_my_stuff(char *foo) {} + #endif + + (in the code itself):: + + init_my_stuff(dev); + + 3. 'static inline' is better than a macro + + Static inline functions are greatly preferred over macros. They + provide type safety, have no length limitations, no formatting + limitations, and under gcc they are as cheap as macros. + + Macros should only be used for cases where a static inline is + clearly suboptimal [there a few, isolated cases of this in fast + paths], or where it is impossible to use a static inline + function [such as string-izing]. + + 'static inline' is preferred over 'static __inline__', 'extern + inline', and 'extern __inline__'. + + 4. Don't over-design. + + Don't try to anticipate nebulous future cases which may or may + not be useful: "Make it as simple as you can, and no simpler" + + Split up functionality as much as possible. If your code needs + to do two unrelated things, write two functions. Mashing two + kinds of work into one function makes the server difficult to + debug and maintain. + diff --git a/doc/developer/contributing.rst b/doc/developer/contributing.rst new file mode 100644 index 0000000..b40f98c --- /dev/null +++ b/doc/developer/contributing.rst @@ -0,0 +1,127 @@ +Submitting patches or diff's to the FreeRADIUS project +====================================================== + +For a person or company wishing to submit a change to the FreeRADIUS project +the process can sometimes be daunting if you're not familiar with "the system." +This text is a collection of suggestions which can greatly increase the chances +of your change being accepted. + +Note: Only trivial patches will be accepted via email. Large patches, or +patches that modify a number of files MUST be submitted as a pull-request via +GitHub. + +Hints and tips +-------------- + +1. Describe your changes +~~~~~~~~~~~~~~~~~~~~~~~~ + +Describe the technical detail of the change(s) your patch or commit includes. + +Be as specific as possible. The WORST descriptions possible include things like +"update file X", "bug fix for file X", or "this patch includes updates for +subsystem X. Please apply." + +If your description starts to get long, that's a sign that you probably need to +split up your commit. See #3, next. + +2. Separate your changes +~~~~~~~~~~~~~~~~~~~~~~~~ + +Separate each logical change into its own commit. + +For example, if your changes include both bug fixes and performance +enhancements for a single module, separate those changes into two or more +patches. + +On the other hand, if you make a single change to numerous files, group those +changes into a single commit. Thus a single LOGICAL change is contained within +a single commit. + +If one commit depends on another commit in order for a change to be complete, +that is OK. Simply note "this commit depends on commit X" in the extended +commit description. + +If your commit includes significant whitespace changes these should also be +broken out into another, separate, commit. + +Submitting patches via GitHub +----------------------------- + +See the following links for more details about submitting via github: + +- https://help.github.com/articles/fork-a-repo +- http://wiki.freeradius.org/contributing/GitHub + +Submitting patches via email +---------------------------- + +1. "diff -u" +~~~~~~~~~~~~ +Use ``diff -u`` or ``diff -urN`` to create patches. + +All changes to the source occur in the form of patches, as generated by +diff(1). When creating your patch, make sure to create it in "unified diff" +format, as supplied by the '-u' argument to diff(1). Patches should be based in +the root source directory, not in any lower subdirectory. + +To create a patch for a single file, it is often sufficient to do:: + + SRCTREE=/home/user/src/freeradiusd/ + MYFILE=src/modules/rlm_foo/foo.c + + cd $SRCTREE + cp $MYFILE $MYFILE.orig + vi $MYFILE # make your change + diff -u $MYFILE.orig $MYFILE > /tmp/patch + +To create a patch for multiple files, you should unpack a "vanilla", or +unmodified source tree, and generate a diff against your own source tree. For +example:: + + MYSRC=/home/user/src/freeradiusd-feature/ + + gunzip freeradiusd-version.tar.gz + tar xvf freeradiusd-version.tar + diff -urN freeradiusd-version $MYSRC > ~/feature-version.patch + + +2. Select e-mail destination +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are on the developers mailing list, send the patch there. +freeradius-devel@lists.freeradius.org + +Otherwise, send the patch to 'patches@freeradius.org' + +3. No MIME, no links, no compression, no attachments. Just plain text +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The developers need to be able to read and comment on the changes you are +submitting. It is important for a developer to be able to "quote" your changes, +using standard e-mail tools, so that they may comment on specific portions of +your code. + +For this reason, all patches should be submitting e-mail "inline". + +Do not attach the patch as a MIME attachment, compressed or not. Many popular +e-mail applications will not always transmit a MIME attachment as plain text, +making it impossible to comment on your code. A MIME attachment also takes a +bit more time to process, decreasing the likelihood of your MIME-attached +change being accepted. + +Compressed patches are generally rejected outright. If the developer has to do +additional work to read your patch, the odds are that it will be ignored +completely. + +4. E-mail size +~~~~~~~~~~~~~~ + +Large changes are not appropriate for mailing lists, and some maintainers. If +your patch, exceeds 5Kb in size, you must submit the patch via GitHub instead. + +5. Name the version of the server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is important to note, either in the subject line or in the patch +description, the server version to which this patch applies. diff --git a/doc/developer/module_interface.rst b/doc/developer/module_interface.rst new file mode 100644 index 0000000..2fc510e --- /dev/null +++ b/doc/developer/module_interface.rst @@ -0,0 +1,186 @@ + +RLM Module Interface (for developers) +===================================== + +Overview +-------- + +Intent of the server +^^^^^^^^^^^^^^^^^^^^ + +FreeRADIUS is an authentication server. It does RADIUS authorization, +authentication, and accounting. It does NOT do database management, +user configuration updates, or email. All of those functions may be +more easily (and correctly) performed in programs outside of the +server. + +The only functionality performed by the server is: + +- receive a RADIUS request + - process the request + - look up information one or more databases +- store information in one or more databases (proxying can be viewed this way) +- respond to the request + +There is no room, or need, for timers, listening on sockets, or +anything else in the server. Adding those functions to the server +means that it will become more complex, more unstable, more insecure, +and more difficult to maintain. + + +Intent of the modules +^^^^^^^^^^^^^^^^^^^^^ + +The intent of modules is that they do small, simple, well-defined +things when RADIUS packets are received. If the module does things +when RADIUS packets are NOT received, then it has no business being in +the server. Similarly, the module infrastructure is NOT intended to +allow servers, applications, timed events, or anything other than +handling incoming RADIUS packets. + +Modules perform an action when RADIUS packets are received. Modules +which do more (creating threads, forking programs) will NOT be added +to the server, and the server core will NOT be modified to enable +these kinds of modules. Those functions more properly belong in a +separate application. + +Modules ARE permitted to open sockets to other network programs, and +to send and receive data on those sockets. Modules are NOT permitted +to open sockets, and to listen for requests. Only the server core has +that functionality, and it only listens for RADIUS requests. + + +Module outline +^^^^^^^^^^^^^^ + +The fundamental concepts of the rlm interface are module, instance, +and component. + +A module is a chunk of code that knows how to deal with a particular +kind of database, or perhaps a collection of similar +databases. Examples: + +- rlm_sql contains code for talking to MySQL or Postgres, and for mapping RADIUS records onto SQL tables +- rlm_unix contains code for making radiusd fit in well on unix-like systems, including getpw* authentication and utmp/wtmp-style logging. + +An instance specifies the actual location of a collection data that +can be used by a module. Examples: + +- /var/log/radutmp +- "the MySQL database on bigserver.theisp.com.example" + +A module can have multiple components which act on +RADIUS requests at different stages. The components are: + +- authorization: check that a user exists, decide on an authentication method or proxy realm, and possibly apply some attributes to be returned in the reply packet. +- authentication: verify that the password is correct. +- preaccounting: decide whether to proxy the request, and possibly add attributes that should be included in any logs +- accounting: record the request in the log +- checksimul: count the number of active sessions for the user +- postauth: process the response before it's sent to the NAS +- preproxy: process a request before it's proxied +- postproxy: filter attributes from a reply to a proxied request + +A module declares which components it supports by putting function +pointers in its "module_t rlm_*" structure. + + +Module configuration +^^^^^^^^^^^^^^^^^^^^ + +The administrator requests the creation of a module instance by adding +it inside the modules{} block in radiusd.conf. The instance definition +looks like this:: + + module_name [instance_name] { + param1 = value1 + param2 = value2 + param3 = value3 + ... + } + +The module_name is used to load the module. To see the names of the available +modules, look for the rlm\_\*.so files in $installprefix/lib. The module_name +is that, minus the rlm\_ and the .so. + +instance_name is an identifier for distinguishing multiple instances of the +same module. If you are only loading a module once, you can leave out the +instance_name and it will be assumed to be the same as the module_name. + +The parameters inside the module block are passed without interpretation to +the module and generally point to the exact location of a database or enable +optional features of the module. Each module should document what parameters +it accepts and what they do. + +For each Access-Request that comes to the server, the authorize{} +block is called. Then one of the Auth-Type{} blocks from authenticate{} +is called, depending on the Auth-Type attribute that was chosen by +authorize{}. Finally, the post-auth{} block is called. If authorize{} +set the Proxy-To-Realm attribute, then proxying takes over via +pre-proxy{} and post-proxy{}, and the local authenticate{} phase is +skipped. + +For each Accounting-Request that comes to the server, the preacct{} block is +called, followed by the accounting{} block. accounting{} is skipped if +preacct{} sets Proxy-To-Realm. + +For an explanation of what "calling" a config block means, see +the "configurable_failover" file. + + +The lifetime of a module +^^^^^^^^^^^^^^^^^^^^^^^^ + +When the server is starting up, or reinitializing itself as a result of a +SIGHUP, it reads the modules{} section. Each configured module will be loaded +and its init() method will be called:: + + int init(void) + +The init() method should take care of +any setup that is not tied to a specific instance. It will only be called +once, even if there are multiple instances configured. + +For each configured instance, after the init() method, the instantiate() +method is called. It is given a handle to the configuration block holding its +parameters, which it can access with cf_section_parse().:: + + int instantiate(CONF_SECTION \*cs, void \**instance) + +The instantiate() function should look up options in the config section, and +open whatever files or network connections are necessary for the module to do +its job. It also should create a structure holding all of the persistent +variables that are particular to this instance (open file descriptors, +configured pathnames, etc.) and store a pointer to it in \*instance. That +void \* becomes a handle (some would call it a "cookie") representing this +instance. The instance handle is passed as a parameter in all subsequent +calls to the module's methods, so they can determine which database they are +supposed to act on. + +The authorize(), authenticate(), preaccounting(), and accounting() functions +are all called the same way:: + + int authorize(void \*instance, REQUEST \*request) + int authenticate(void \*instance, REQUEST \*request) + int preaccounting(void \*instance, REQUEST \*request) + int accounting(void \*instance, REQUEST \*request) + +they each receive the instance handle and the request, and are expected to +act on the request using the database pointed to by the instance handle +(which was set by the instantiate() function). + +When the server is being shut down (as the first part of SIGHUP for example) +detach() is called for each module instance.:: + + int detach(void \*instance) + +The detach() method should release whatever resources were allocated by the +instantiate() method. + +After all instances are detached, the destroy() method is called.:: + + int destroy(void) + +It should release resources that were acquired by the init() method. + +--Alan Curry <pacman@world.std.com> diff --git a/doc/developer/release-method.rst b/doc/developer/release-method.rst new file mode 100644 index 0000000..6e218c0 --- /dev/null +++ b/doc/developer/release-method.rst @@ -0,0 +1,42 @@ +Release Method +============== + +As of 2.0, the release process is much simpler. Edit the +Changelog with the version number and any last updates. + +vi doc/ChangeLog +git commit doc/ChangeLog + + + Change version numbers in the VERSION file: + +vi VERSION +git commit VERSION + + + Make the files + + Note that it also does "make dist-check", which checks + the build rules for various packages. + +make dist + + + Validate that the packages are OK. If so, tag the release. + + Note that this does NOT actually do the tagging! You will + have to run the command it prints out yourself. + +make dist-tag + + + Sign the packages. You will need the correct GPG key for this + to work. + +make dist-sign + + + Push to the FTP site. You will need write access to the FTP site + for this to work. + +make dist-publish diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..c8ef10a --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,29 @@ +.. FreeRADIUS documentation master file, created by + sphinx-quickstart on Tue May 18 13:26:39 2010. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. toctree:: + :maxdepth: 2 + + aaa + ldap_howto + load-balance + + coding-methods + DIFFS + release-method + + cisco + configurable_failover + processing_users_file + proxy + variables + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/doc/modules/RADIUS-LDAP-eDirectory b/doc/modules/RADIUS-LDAP-eDirectory new file mode 100644 index 0000000..abfa1cf --- /dev/null +++ b/doc/modules/RADIUS-LDAP-eDirectory @@ -0,0 +1,18 @@ +"Integrating Novell eDirectory with FreeRADIUS" + +Overview +You can integrate Novell® eDirectoryTM 8.7.1 or later with FreeRADIUS +1.0.2 onwards to allow wireless authentication for eDirectory users. +By integrating eDirectory with FreeRADIUS, you can do the following: +* Use universal password for RADIUS authentication. + Universal password provides single login and authentication for + eDirectory users. Therefore, the users need not have a separate + password for RADIUS and eDirectory authentication. +* Enforce eDirectory account policies for users. + The existing eDirectory policies on the user accounts can still be + applied even after integrating with RADIUS. Also, you can make use + of the intruder lockout facility of eDirectory by logging the + failed logins into eDirectory. + +For configuration information please refer to the Novell documentation + http://www.novell.com/documentation/edir_radius/index.html diff --git a/doc/modules/ldap_howto.rst b/doc/modules/ldap_howto.rst new file mode 100644 index 0000000..53f0f3e --- /dev/null +++ b/doc/modules/ldap_howto.rst @@ -0,0 +1,1648 @@ +LDAP Configuration +================== + +This document describes how to setup Freeradius on a Freebsd machine +using LDAP as a backend. This is by no means complete and your +mileage may vary. If you are having any problems with the setup of +your freeradius installation, please read the documentation that comes +with Freeradius first as that is where all the information for this +project came from. If you find any bugs, typos, alternative ideas, or +just plain wrong information, please let me know by sending an email +to the address above. + +The radius servers in this document are built on Freebsd 4.8, using +Freeradius .81 with OpenLDAP 2.0.27 as the backend. The servers are +designed to support customers for multiple services. In this document +we will use regular dialup and dialup ISDN as examples of two +different services using the same radius server for authentication. + +OVERVIEW +-------- + +The radius servers are to be provisioned by a some sort of system we +will call Billing. Billing could simply be a script, a web front-end, +or an actual integration into a billing system. Billing will provision +to the master LDAP server. The master LDAP server is running slurpd, +which will replicate all changes to the other radius servers. Each +radius server will run a local instance of LDAP. + +The radius servers will be accepting Radius auth packets and Radius +acct packets. The accounting packets will be stored locally on each +radius server and then forwarded to the Accounting radius server, +using radrelay. The Accounting radius server will store all the +radius information in some sort of database such as MySQL, Postgres, +or Oracle. The configuration of the actual Accounting radius server +is outside the scope of this document. Please refer to the freeradius +documentation for setting up that server. + +The Accounting radius server will help to provide a searchable +interface to the accounting data for billing and usage purposes and +could allow a web front-end to be built for helpdesk/customer service +usage. If that is not needed for your purposes, then disregard all +details about the Accounting radius server. + +In order to make sure no data is lost in the event of the Accounting +radius server going down, the replication of data will take place +using radrelay. Radrelay will do the equivalent of a tail on the +detail file and will continually attempt to duplicate each radius +packet that is stored in the detail file and send it off to the +recipient(s) specified. Upon receipt of an accounting_response packet +radrelay will consider that packet completed and continue working on +the others. Each radius server will also be storing its own copy of +all accounting packets that are sent to it. + +Each NAS will be setup with a primary radius server and a failover +radius server. We will spread the load among the group of radius +servers that we have so some are acting as a primary to some NAS's and +acting as a secondary to others. In the event of a radius failure, +the NAS should failover to the backup radius server. How to configure +this is dependent on the particular NAS being used. + +:: + + Will use Radius acct data Billing will provision + for real-time billing out to the Master LDAP + server over LDAP + +------------+ + | Accounting | +---------+ + | Radius | | Billing | + +------------+ +----+----+ + /|\ | + | | + | | + | | + | Provisioning + | Message + | | + Duplicate | + Acct | + | | + | \|/ + | +------------+ + | +------------------| LDAP Master| + | | +------------+ + | | | + | Slurpd Slurpd Replication + | Replication | + | | | + | | \|/ + | | +------------+ + | | | Radius2 | + The Radius servers | | | LDAP Slave | + will create a local | \|/ +------------+ + copy of all acct +-------------+ + packets and then | Radius1 | + fwd a copy back | LDAP Slave | All Radius servers run a + to accounting +-------------+ local copy of LDAP for + /|\ /|\ Authorization and Authentication + | | + | | + | | + | | + Auth Acct + | | + | | + | | + | | + | | + \|/ \|/ + +-----------+ + | | + | | + | NAS | + | | + +-----------+ + The NAS will be setup to + use one of the Radius servers + as primary and the others as failover + + +LDAP +---- + +The LDAP directory is designed to start with the top level of +dc=mydomain,dc=com. The next level of the tree contains the different +services that will be stored within the ldap server. For the radius +users, it will be specified as ou=radius. Below ou=radius, will be +the different types of accounts. For example, ou=users will store the +users and ou=profiles will store the default radius profiles. The +profiles are entries that will be used to store group-wide radius +profiles. The group ou=admins will be a place to enter the users for +Billing, Freeradius, and any other administrative accounts that are +needed. + +:: + + +---------------------+ + | | + | Dc=mydomain,dc=com |Objectclass:organizationalUnit + | |Objectclass:dcObject + +---------------------+ + | + | + \|/ + +---------------+ + | | + | Ou=radius | Objectclass:organizationalUnit + | | + +---------------+ + | + +-----------------------+-------------------------| + | | | + \|/ \|/ \|/ + +---------+ +---------------+ +-------------+ + | | | | | | + |Ou=users | | Ou=profiles | | Ou=admins | + | | | | | | + +---------+ +---------------+ +------|------+ + | | | + | | | + \|/ | \|/ + ----- Objectclass: | ----- Objectclass: + // \\ radiusprofile | // \\ person + | | | | | + \\ // | \\ // + ----- \|/ ----- Dn:cn=freeradius + Dn: uid=example,ou=users, ----- ObjectClass: ou=admins,ou=radius + dc=mydomain,dc=com // \\ radiusprofile dc=mydomain,dc=com + | | + | | + \\ // + ----- + Dn: uid=dial,ou=profiles,ou=radius,dc=mydomain,dc=com + + +An example LDIF file is below. +NOTE: There are unique radius attribute types and objectclasses, these will be +explained in the configuration section. + +:: + + dn: dc=mydomain,dc=com + objectClass: dcObject + objectClass: organizationUnit + ou: Mydomain.com Radius + dc: mydomain + + dn: ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: radius + + dn: ou=profiles,ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: profiles + + dn: ou=users,ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: users + + dn: ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: admins + + dn: uid=dial,ou=profiles,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: dial + radiusServiceType: Framed-User + radiusFramedProtocol: PPP + radiusFramedIPNetmask: 255.255.255.0 + radiusFramedRouting: None + + dn: uid=isdn,ou=profiles,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: isdn + radiusServiceType: Framed-User + radiusFramedProtocol: PPP + radiusFramedIPNetmask: 255.255.255.0 + radiusFramedRouting: None + + dn: uid=example,ou=users,ou=radius,dc=mydomain,dc=com + objectclass: radiusProfile + uid: example + userPassword: test + radiusGroupName: dial + radiusGroupName: isdn + + dn: cn=freeradius,ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: person + sn: freeradius + cn: freeradius + userPassword: freeradius + + dn: cn=billing,ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: person + sn: freeradius + cn: freeradius + userPassword: billing + + dn: cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: person + sn: replica + cn: replica + userPassword: replica + +In order to configure the ldap server to understand the radius schema that we +are using, the attribute types and objectclasses must be defined in slapd.conf. +The file is included with the following line in slapd.conf:: + + include /usr/local/etc/openldap/schema/RADIUS-LDAPv3.schema + +Below is the complete Schema:: + + ----Begin RADIUS-LDAPv3.schema---- + + ################################################# + ##### custom radius attributes ################## + + objectIdentifier myOID 1.1 + objectIdentifier mySNMP myOID:1 + objectIdentifier myLDAP myOID:2 + objectIdentifier myRadiusFlag myLDAP:1 + objectIdentifier myObjectClass myLDAP:2 + + attributetype + ( myRadiusFlag:1 + NAME 'radiusAscendRouteIP' + DESC 'Ascend VSA Route IP' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + (myRadiusFlag:2 + NAME 'radiusAscendIdleLimit' + DESC 'Ascend VSA Idle Limit' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + (myRadiusFlag:3 + NAME 'radiusAscendLinkCompression' + DESC 'Ascend VSA Link Compression' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + (myRadiusFlag:4 + NAME 'radiusAscendAssignIPPool' + DESC 'Ascend VSA AssignIPPool' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + + attributetype + (myRadiusFlag:5 + NAME 'radiusAscendMetric' + DESC 'Ascend VSA Metric' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + ################################################# + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.1 + NAME 'radiusArapFeatures' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.2 + NAME 'radiusArapSecurity' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.3 + NAME 'radiusArapZoneAccess' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.44 + NAME 'radiusAuthType' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.4 + NAME 'radiusCallbackId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.5 + NAME 'radiusCallbackNumber' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.6 + NAME 'radiusCalledStationId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.7 + NAME 'radiusCallingStationId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.8 + NAME 'radiusClass' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.45 + NAME 'radiusClientIPAddress' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.9 + NAME 'radiusFilterId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.10 + NAME 'radiusFramedAppleTalkLink' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.11 + NAME 'radiusFramedAppleTalkNetwork' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.12 + NAME 'radiusFramedAppleTalkZone' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.13 + NAME 'radiusFramedCompression' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.14 + NAME 'radiusFramedIPAddress' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.15 + NAME 'radiusFramedIPNetmask' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.16 + NAME 'radiusFramedIPXNetwork' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.17 + NAME 'radiusFramedMTU' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.18 + NAME 'radiusFramedProtocol' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.19 + NAME 'radiusFramedRoute' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.20 + NAME 'radiusFramedRouting' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.46 + NAME 'radiusGroupName' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.47 + NAME 'radiusHint' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.48 + NAME 'radiusHuntgroupName' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.21 + NAME 'radiusIdleTimeout' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.22 + NAME 'radiusLoginIPHost' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.23 + NAME 'radiusLoginLATGroup' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.24 + NAME 'radiusLoginLATNode' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.25 + NAME 'radiusLoginLATPort' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.26 + NAME 'radiusLoginLATService' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.27 + NAME 'radiusLoginService' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.28 + NAME 'radiusLoginTCPPort' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.29 + NAME 'radiusPasswordRetry' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.30 + NAME 'radiusPortLimit' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.49 + NAME 'radiusProfileDn' + DESC '' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.31 + NAME 'radiusPrompt' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.50 + NAME 'radiusProxyToRealm' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.51 + NAME 'radiusReplicateToRealm' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.52 + NAME 'radiusRealm' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.32 + NAME 'radiusServiceType' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.33 + NAME 'radiusSessionTimeout' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.34 + NAME 'radiusTerminationAction' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.35 + NAME 'radiusTunnelAssignmentId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.36 + NAME 'radiusTunnelMediumType' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.37 + NAME 'radiusTunnelPassword' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.38 + NAME 'radiusTunnelPreference' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.39 + NAME 'radiusTunnelPrivateGroupId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.40 + NAME 'radiusTunnelServerEndpoint' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.41 + NAME 'radiusTunnelType' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.42 + NAME 'radiusVSA' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.43 + NAME 'radiusTunnelClientEndpoint' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + + #need to change asn1.id + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.53 + NAME 'radiusSimultaneousUse' + DESC '' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.54 + NAME 'radiusLoginTime' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.55 + NAME 'radiusUserCategory' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.56 + NAME 'radiusStripUserName' + DESC '' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.57 + NAME 'dialupAccess' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.58 + NAME 'radiusExpiration' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.59 + NAME 'radiusCheckItem' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + attributetype + ( 1.3.6.1.4.1.3317.4.3.1.60 + NAME 'radiusReplyItem' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + + + objectclass + ( 1.3.6.1.4.1.3317.4.3.2.1 + NAME 'radiusprofile' + SUP top STRUCTURAL + DESC '' + MUST ( uid ) + MAY ( userPassword $ + radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ + radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ + radiusCalledStationId $ radiusCallingStationId $ radiusClass $ + radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ + radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ + radiusFramedCompression $ radiusFramedIPAddress $ + radiusFramedIPNetmask $ radiusFramedIPXNetwork $ + radiusFramedMTU $ radiusFramedProtocol $ + radiusCheckItem $ radiusReplyItem $ + radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ + radiusGroupName $ radiusHint $ radiusHuntgroupName $ + radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ + radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ + radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ + radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ + radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ + radiusSessionTimeout $ radiusStripUserName $ + radiusTerminationAction $ radiusTunnelAssignmentId $ + radiusTunnelClientEndpoint $ radiusIdleTimeout $ + radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ + radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ + radiusLoginTCPPort $ radiusPasswordRetry $ radiusPortLimit $ + radiusPrompt $ radiusProfileDn $ radiusServiceType $ + radiusSessionTimeout $ radiusSimultaneousUse $ + radiusTerminationAction $ radiusTunnelAssignmentId $ + radiusTunnelClientEndpoint $ radiusTunnelMediumType $ + radiusTunnelPassword $ radiusTunnelPreference $ + radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ + radiusTunnelType $ radiusUserCategory $ radiusVSA $ + radiusExpiration $ dialupAccess $ + radiusAscendRouteIP $ radiusAscendIdleLimit $ + radiusAscendLinkCompression $ + radiusAscendAssignIPPool $ radiusAscendMetric ) + ) + ----End RADIUS-LDAPv3.schema---- + + +Now we need to setup the permissions on the ldap server. Notice above we +created three users in the admin ou. These users will be specific for billing, +freeradius, and replication. + +On the master ldap server, we will set the following permissions:: + + access to attr=userPassword + by self write + by dn="cn=billing,ou=admins,ou=radius,dc=mydomain,dc=com" write + by anonymous auth + by * none + + access to * + by self write + by dn="cn=billing,ou=admins,ou=radius,dc=mydomain,dc=com" write + by anonymous auth + by * none + +This will give the billing user write access to add/delete users. For security +we will not give read access to any other users. You can easily add another +read-only user to this setup if you want to build some sort of web interface to +do only reads. + +Now on the slave ldap servers (aka the radius servers) we will setup the +following permissions:: + + access to attr=userPassword + by self write + by dn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" write + by anonymous auth + by * none + + access to dn="ou=users,ou=radius,dc=mydomain,dc=com" + by dn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" write + by dn="cn=freeradius,ou=admins,ou=radius,dc=mydomain,dc=com" read + by anonymous auth + by * none + + access to * + by self write + by dn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" write + by anonymous auth + by * none + + +This will give the replica user write access. This user will be discussed +below and it is involved in the process of replicating the master server to the +slaves. The freeradius user only needs read access to do the lookups for +authorization. + +Now we will want to setup indexes to speed up searches. At the minimum, below +will work. Since all radius lookups are currently using the uid, we will want +to index that. It is also a good idea to index the objectclass attribute. + +# Indices to maintain +index objectClass eq +index uid eq + +Now we need to setup the replication from the master to the slave servers. To +do this, we will add the following to the slapd.conf file on the master: + +On the master LDAP server:: + replica host=radius1.mydomain.com + binddn=cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com + bindmethod=simple credentials=replica + + replica host=radius2.mydomain.com + binddn=cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com + bindmethod=simple credentials=replica + +We will need to add a replica for each slave LDAP server. The binddn is the +name that is used to bind to the slave server, and the credentials is the +secret for that user. + +On the slave LDAP servers:: + + updatedn cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com + updateref ldap://ldapmaster.mydomain.com + +Those will determine what name is allowed to update the LDAP server and if an +update is attempted directly, what server to refer the update to. + +RADIUS +------ + +The radius server is setup to use LDAP for both Authorization and +Authentication. This section will describe what events will take place during +an AAA session with a NAS. When the NAS sends a access_request to the radius +server, the radius server will perform authorization and authentication based +on a series of modules that are defined in radiusd.conf. For example, the +module defined as ldap, will be used to make connections to the LDAP directory. + +An example is seen in raddb/mods-config/ldap:: + +The first thing that is done is authorization of the user. The radius server +will process the modules in the order specified in the authorization section of +radiusd.conf. Currently, they are in the following order. + +1) preprocess +2) suffix +3) files +4) ldap + +The first module will be preprocess. This will first check the huntgroups of +the user coming in. The huntgroups are defined in the file huntgroups and they +are a group listing of the NAS-IP-Addresses that make the access_request. This +is useful in creating specific actions based on the NAS-IP that the request is +made from. An example, is below:: + + isdncombo NAS-IP-Address == 10.10.10.1 + dialup NAS-IP-Address == 10.10.10.2 + dialup NAS-IP-Address == 10.10.10.3 + +We will have one NAS that is used for both ISDN and regular dialup customers, +the other NAS's will be only used for dialup. + +The preprocess module may also use the hints file, to load hints to the radius +server, and add additional hacks that are based on the type of request that +comes in. This is to help with certain NAS's that don't conform to radius +RFC's. Check the comments in radiusd.conf for an explanation on those. + +The second module is suffix. This event will determine which realm the user is +in, based on the User-Name attribute. It is currently setup to split the +username at the occurence of the @symbol. For example, the username of +example@mydomain.com, will be split into example and mydomain.com. The realm +is then checked against the file proxy.conf, which will determine what actions +should be taken for that realm. Certain realms can be setup to be proxied to a +different radius server or set to authenticate locally. Also, the username can +be setup to be stripped from the realm or left intact. An example of +proxy.conf, is listed below. If the realm is to be proxied, then a secret is +needed, which is the secret of the radius server it is to be proxied to. +By default the User-Name will be stripped, unless the nostrip option is set. + +Currently we will not be using realms with our users, but adding this ability +in the future will be much easier with already incorporating proxy.conf into the +setup:: + + proxy server { + synchronous = no + retry_delay = 5 + retry_count = 3 + dead_time = 120 + servers_per_realm = 15 + default_fallback = yes + } + + realm NULL { + type = radius + authhost = LOCAL + accthost = LOCAL + #secret = testing123 + } + + realm DEFAULT { + type = radius + authhost = LOCAL + accthost = LOCAL + #secret = testing123 + } + +The next module is files, which is commonly know as the users file. The users +file will start with either a username to determine how to authorize a specific +user, or a DEFAULT setting. In each line it will define what items must be +present for there to be a match in the form of attribute == value. If all the +required attributes are matched, then attributes specified with attribute := +value will be set for that user. If no match is found the users file will +continue to be processed until there is a match. The last DEFAULT setting will +be set as a catch-all, in case there is no previous match. If a match is made, +the statement of Fall-Through determines if the users file should continue to +be processed or if it should stop right there. + +The Ldap-Group corresponds to the LDAP attribute of radiusGroupName (see ldap +configuration above). The user may be assigned multiple radiusGroupNames, one +for each of the services that the user is authorized for. If the user does +belong to the correct group, then the user will be authorized for that type of +access. If the user does not belong to that group, then there will not be a +match and the users file will continue to be processed. If a match is made and +there is a User-Profile set, then the radius server will lookup the attributes +that exist in that User-Profile in the LDAP directory. These are radius +attributes that will be sent to the NAS as a reply-item. + +An example users file is below:: + + DEFAULT Ldap-Group == disabled, Auth-Type := Reject + Reply-Message = "Account disabled. Please call the helpdesk." + + DEFAULT Huntgroup-Name == isdncombo, NAS-Port-Type == Async, Ldap-Group == dial, + User-Profile := "uid=dial,ou=profiles,ou=radius,dc=mydomain,dc=com" + Fall-Through = no + + DEFAULT Huntgroup-Name == isdncombo, NAS-Port-Type == ISDN, Ldap-Group == isdn, + User-Profile := "uid=isdn,ou=profiles,ou=radius,dc=mydomain,dc=com" + Fall-Through = no + + DEFAULT Huntgroup-Name == dial, Ldap-Group == dial, + User-Profile := "uid=dial,ou=profiles,ou=radius,dc=mydomain,dc=com" + Fall-Through = no + + DEFAULT Auth-Type := Reject + Reply-Message = "Please call the helpdesk." + +Notice that the catchall DEFAULT is set to Reject the user. This will stop the +authorization and immediately send back an access_reject message. Because +business rules are applied above to each scenario where the user will be +authorized for access, if no match is found, then we will want to stop the +process immediately to save resources. + +By using the Ldap-Group feature we can limit user logins to only the services +they are subscribed to. Some examples of possible user setups are below:: + + #user with access to dial-up + dn: uid=user1,ou=users,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: user1 + userPassword: whatever + radiusgroupname: dial + + #user with access to ISDN and dial + dn: uid=user2,ou=users,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: user2 + userPassword: whatever + radiusgroupname: dial + radiusgroupname: isdn + + #same user as above that was suspended for not paying + dn: uid=user2,ou=users,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: user2 + userPassword: whatever + radiusgroupname: dial + radiusgroupname: isdn + radiusgroupname: disabled + +Now that we have authorized the user, the final piece is to authenticate the +user. Authentication is currently done by checking if the password sent in the +access_request packet is correct. This action will be done with an attempted +bind to the LDAP server using the User-Name and User-Password attributes +passed to it from the access_request. If the user is successfully authorized, +then an access_accept message will be sent back to the NAS, with any reply +items that were defined in the authorization section. If the user did not +supply the correct password, then an access_reject message will be sent to the +user. + +If the NAS is sent an access_accept packet then the user will be given access +to the service and the NAS will then send an acct_request packet. This will be +a request packet to start a radius accounting session. The way the server will +log the accounting packets is determined in the detail module in the +radiusd.conf file. Since we will be storing a local copy and forwarding on all +accounting to the Accounting radius server, we will store two local copies on +the machine. The first one is done in a regular detail file as defined in the +following:: + + detail detail1 { + filename = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d + permissions = 0600 + dir_permissions = 0755 + } + +The second detail file will be used by the program radrelay to relay a copy of +all accounting packets to the Accounting radius server. This file is stored as +a catchall for all accounting packets. The radrelay program will basically do +a tail on that file and will then attempt to send a copy of each addition to it +to the Accounting server. If the copy is successfully sent, then it will be +deleted from this file. If the Accounting server were to go down, then this +file will continue to build up entries. As soon as the Accounting server is +back online, an attempt to re-send the packets to the Accounting server will +made. This file is defined in the following section of radiusd.conf:: + + detail detail2 { + filename = ${radacctdir}/detail-combined + permissions = 0600 + dir_permissions = 0755 + locking = yes + } + +INSTALLATION +------------ + +The new radius servers are currently built on Freebsd 4.8. As the version may +eventually change, these instructions may no longer apply. The steps for +building the server are the following: + +* Install FreeBSD +* Install other FreeBSD items +* Install OpenLDAP *NOTE: this must be done before installing Freeradius* +* Install FreeRadius + +Under the assumption that FreeBSD is already installed and the kernel rebuilt +to the specifications needed for the machine, there are several other things +that may be needed at this time and the purpose of this is just as a reminder. + +install cvsup-without-gui from the ports collection + +run cvsup on all to update the ports to the most recent versions + +might be a good idea to upgrade the src + +edit and run cvsup on /usr/share/examples/cvsup/standard-supfile + +cd /usr/src - vi Makefile and follow instructions + +install sendmail from ports to keep up to date with the most recent versions. +In the ports collection /ports/mail/sendmail run make; make install; make +mailer.conf. Then edit rc.conf and change to sendmail_enable=NO +radius servers only need the local interface to send daily reports + +edit rc.conf to make sure inetd_enable=NO + +no reason to have extra services running + +if you rebuilt the kernel to add support for IPFIREWALL, then remember to add a +firewall rule to rc.conf + +firewall_enable=YES +firewall_type=OPEN (or actually create a real firewall rule) + +add crontab to keep date accurate for accounting:: + + 15 03 * * * /usr/sbin/ntpdate -s thetimeserver.mydomain.com + +install openldap from ports + +download the freeradius source as the ports collection is often outdated +the default settings are /usr/local/etc/raddb, /var/log/radius.log, /var/log/radacct + +since openldap was installed first, you should not need any special flags to +add ldap support + +Now its time to configure openlap and freeradius. First we will be looking at +configuring OpenLDAP + + +copy RADIUS-LDAPv3.schema to /usr/local/etc/openldap/schema + +edit /usr/local/etc/openldap/slapd.conf + +:: + + ----Begin slapd.conf---- + # $OpenLDAP: pkg/ldap/servers/slapd/slapd.conf,v 1.23.2.7 2003/03/24 03:54:12 + #kurt Exp $ + # + # See slapd.conf(5) for details on configuration options. + # This file should NOT be world readable. + # + include /usr/local/etc/openldap/schema/core.schema + include /usr/local/etc/openldap/schema/RADIUS-LDAPv3.schema + + # Define global ACLs to disable default read access. + + # Do not enable referrals until AFTER you have a working directory + # service AND an understanding of referrals. + #referral ldap://root.openldap.org + + loglevel 296 + + pidfile /var/run/slapd.pid + argsfile /var/run/slapd.args + + # Load dynamic backend modules: + # modulepath /usr/local/libexec/openldap + # moduleload back_bdb.la + # moduleload back_ldap.la + # moduleload back_ldbm.la + # moduleload back_passwd.la + # moduleload back_shell.la + + password-hash {SSHA} + + access to attr=userPassword + by self write + by dn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" write + by anonymous auth + by * none + + access to dn="ou=users,ou=radius,dc=mydomain,dc=com" + by dn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" write + by dn="cn=freeradius,ou=admins,ou=radius,dc=mydomain,dc=com" read + by anonymous auth + by * none + + access to * + by self write + by dn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" write + by anonymous auth + by * none + + + ####################################################################### + # ldbm database definitions + ####################################################################### + + database bdb + suffix "dc=mydomain,dc=com" + rootdn "cn=root,dc=mydomain,dc=com" + # Cleartext passwords, especially for the rootdn, should + # be avoid. See slappasswd(8) and slapd.conf(5) for details. + # Use of strong authentication encouraged. + rootpw {SSHA}Eu5EwPxTrwhEGrXQ9SaQZyfpu4iHt3NP + # The database directory MUST exist prior to running slapd AND + # should only be accessible by the slapd and slap tools. + # Mode 700 recommended. + directory /var/db/openldap-data + # Indices to maintain + index objectClass eq + index uid eq + mode 0600 + cachesize 2000 + + # replica one for each + #replica host=radius1.mydomain.com + # binddn="cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com" + # bindmethod=simple credentials=secret + + replogfile /var/db/openldap-slurp/replog + + ## REMEMBER TO ADD THIS TO THE SLAVES + updatedn "cn=freeradius,ou=admins,ou=radius,dc=mydomain,dc=com" + updateref ldap://ldapmaster.mydomain.com + ----End slapd.conf---- + + +To create a rootdn that is not stored in plain text, enter the following command:: + + $ slappasswd + +it will ask for password and verification:: + + New password: + Re-enter new password:: + +while in the shell create the directory for the ldap database, this must be created before slapd can start:: + + $ mkdir /var/db/openldap-data + +move the slapd.sh.sample file to slapd.sh in /usr/local/etc/rc.d:: + + $ mv /usr/local/etc/rc.d/slapd.sh.sample slapd.sh + +enable logging in /etc/syslog.conf by adding the following:: + + local4.* /var/log/ldap.log + restart syslogd + +start it up on both the master and slave ldap servers:: + + $ /usr/local/etc/rc.d/slapd start + +create the structural ldif, schema.ldif:: + + ----Begin schema.ldif---- + dn: dc=mydomain,dc=com + objectClass: dcObject + objectClass: organizationUnit + ou: Mydomain.com Radius + dc: mydomain + + dn: ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: radius + + dn: ou=profiles,ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: profiles + + dn: ou=users,ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: users + + dn: ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: organizationalunit + ou: admins + + dn: uid=dial,ou=profiles,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: dial + radiusServiceType: Framed-User + radiusFramedProtocol: PPP + radiusFramedIPNetmask: 255.255.255.0 + radiusFramedRouting: None + + dn: uid=isdn,ou=profiles,ou=radius,dc=mydomain,dc=com + objectclass: radiusprofile + uid: isdn + radiusServiceType: Framed-User + radiusFramedProtocol: PPP + radiusFramedIPNetmask: 255.255.255.0 + radiusFramedRouting: None + + dn: uid=example,ou=users,ou=radius,dc=mydomain,dc=com + objectclass: radiusProfile + uid: example + userPassword: test + radiusGroupName: dial + radiusGroupName: isdn + + dn: cn=freeradius,ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: person + sn: freeradius + cn: freeradius + userPassword: freeradius + + dn: cn=billing,ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: person + sn: freeradius + cn: freeradius + userPassword: billing + + dn: cn=replica,ou=admins,ou=radius,dc=mydomain,dc=com + objectclass: person + sn: replica + cn: replica + userPassword: replica + ----End schema.ldif---- + +add the organizational structure to the master ldap database:: + + $ ldapadd -D uid=billing,ou=admins,ou=radius,dc=mydomain,dc=com -w billing -f + schema.ldif -h ldapmaster.mydomain.com + +run slapcat to see what the directory looks like:: + + $ slapcat + +If all went well the LDAP directory should be up and running and propagated to +the slaves. Now you can add your users to the master. + +Now its time to setup FreeRadius. First cd into /usr/local/etc/raddb and take +a look at all the configuration files, they are heavily documented so you may +wish to read through them all before making and changes. + + +edit huntgroups to specify a NAS to a huntgroup:: + + ----Begin huntgroups---- + # dialup and isdn + isdncombo NAS-IP-Address == 10.10.10.1 + + # just dialup + dialup NAS-IP-Address == 10.10.10.2 + dialup NAS-IP-Address == 10.10.10.3 + ----End huntgroups---- + +* edit proxy.conf to setup the different realms:: + + ----Begin proxy.conf---- + proxy server { + synchronous = no + retry_delay = 5 + retry_count = 3 + dead_time = 120 + servers_per_realm = 15 + default_fallback = yes + } + + realm NULL { + type = radius + authhost = LOCAL + accthost = LOCAL + #secret = testing123 + } + + realm DEFAULT { + type = radius + authhost = LOCAL + accthost = LOCAL + #secret = testing123 + } + ----End proxy.conf---- + + -edit clients.conf to setup the NAS's that can talk to it + + + ----Begin clients.conf---- + client 127.0.0.1 { + secret = example + shortname = localhost + nas_type = other + } + + + # isdn and dialup nas + client 10.10.10.1 { + secret = example + shortname = isdn + nas_type = cisco + } + + #dialup only + client 10.10.10.2 { + secret = example + shortname = dialup1 + nas_type = cisco + } + + client 10.10.10.3 { + secret = example + shortname = dialup2 + nas_type = cisco + } + ----End clients.conf---- + + +You may wish to look at the other files, but they should all be OK by default. + +create startup files in /usr/local/etc/rc.d + +radiusd.sh - the radiusd startup file:: + + ----Begin radiusd.sh---- + #!/bin/sh + case "$1" in + start) + /usr/local/sbin/radiusd + echo -n ' radiusd' + ;; + stop) + if [ -f /usr/local/var/run/radiusd/radiusd.pid ]; then + kill -TERM `cat /usr/local/var/run/radiusd/radiusd.pid` + rm -f /usr/local/var/run/radiusd/radiusd.pid + echo -n ' radiusd' + fi + ;; + restart) + if [ -f /usr/local/var/run/radiusd/radiusd.pid ]; then + kill -HUP `cat /usr/local/var/run/radiusd/radiusd.pid` + echo 'radiusd restarted' + fi + ;; + *) + echo "Usage: ${0##*/}: { start | stop | restart }" 2>&1 + exit 65 + ;; + esac + ----End radiusd.sh---- + +radrelay.sh - the radrelay startup file:: + + + ----Begin radrelay.sh---- + #!/bin/sh + case "$1" in + + start) + /usr/local/bin/radrelay -a /var/log/radacct -d /usr/local/etc/raddb \ + -S /usr/local/etc/raddb/radrelay_secret -f -r accounting.mydomain.com:1813 \ + detail-combined + echo -n ' radrelay started' + ;; + + + stop) + /usr/bin/killall radrelay + echo ' radrelay stopped' + ;; + + *) + echo "Usage: $[0##*/}: { start | stop }" 2>&1 + exit 65 + ;; + + esac + ----End radrelay.sh---- + +create radrelay_secret in /usr/local/etc/radddb +This file will contain the secret to connect to the Accounting radius server:: + + ----Begin radrelay_secret---- + example + ----End radrelay_secret---- + +Now fire them up:: + $ /usr/local/etc/rc.d/radiusd.sh start + $ /usr/local/etc/rc.d/radrelay.sh start + +You should be all set to start testing now. + +OTHER RANDOM NOTES AND THOUGHTS +------------------------------- + +The client programs used to connect to the ldap directory are: + +ldapadd: + to add a record +ldapmodify: + to modify a record +ldapdelete: + to delete a record +ldapsearch: + to search for a record +slapcat: + to show the entire directory +slappaswd: + to generate a crypted password + +Read the man pages on those commands, they tell you everything you +need to know. + +They all follow this basic syntax:: + + $ ldapwhatever -D "uid=someone,ou=admins,ou=radius,dc=mydomain,dc=com" -w thesecret -andthenotherstuff + +Finally, if you are having trouble with LDAP, run it in debug mode by +changing the following in slapd.sh:: + + slapd_args= + +to:: + + slapd_args= '-d 3' + +There is a program included with freeradius to test the radius server, +its called radclient. Typing it alone will tell you all the options. +You will need to create a file that contains radius attributes, such +as:: + + User-Name = example + User-Password = test + Service-Type = Framed-User + NAS-IP-Address = 10.10.10.1 + NAS-Port-Type = Async + +Then you fire that radius packet at the server by issuing:: + + $ radclient -f testradiusfile localhost auth thesecret + +-f = filename +localhost is the server you are hitting +auth or acct depending on the type of packet +thesecret to connect to that server + +Finally, if you are having trouble you can run radius in debug mode +and it will output everything that happens to the screen. To do that, +kill the current process and run:: + + $ radiusd -X + + +LINKS +----- + +FREERADIUS +++++++++++ + +* _`FreeRADIUS`: http://www.freeradius.org +* _`FreeRADIUS Documentation`: http://freeradius.org/documentation/ +* _`FreeRADIUS Wiki`: http://wiki.freeradius.org/ + +OPENLDAP +++++++++ + +* _`OpenLDAP`: http://www.openldap.org +* _`OpenLDAP Administrator's Guide`: http://www.openldap.org/doc/admin21 + +RFCs +++++ + +* _`RFC2865: RADIUS Authentication`: http://freeradius.org/rfc/rfc2865.txt +* _`RFC2866: RADIUS Accounting`: http://freeradius.org/rfc/rfc2866.txt +* _`RFC2869: RADIUS Extentions`: http://freeradius.org/rfc/rfc2869.txt +* _`RFC2251: LDAP v3`: http://www.ietf.org/rfc/rfc2251.txt +* _`RFC2252: LDAP v3 Attribute Syntax Definitions`: http://www.ietf.org/rfc/rfc2252.txt +* _`RFC2253: LDAP UTF-8 String Representation of Distinguishe d Names (DNs)`: http://www.ietf.org/rfc/rfc2252.txt +* _`RFC2849: LDAP Data Interchange Fromat (LDIFs)`: http://www.ietf.org/rfc/rfc2849.txt +* _`RFC3377: LDAP v3 Technical Specs`: http://www.ietf.org/rfc/rfc3377.txt diff --git a/doc/modules/mschap.rst b/doc/modules/mschap.rst new file mode 100644 index 0000000..37fcb9d --- /dev/null +++ b/doc/modules/mschap.rst @@ -0,0 +1,196 @@ +rlm_mschap +========== + +The mschap module provides support for MS-CHAPv1 and MS-CHAPv2, which is +a common authentication mechanisms for Microsoft clients. + +If you want to support mschap, there are only 3 possibilities: + + 1. You have access to the users plaintext password, and you configure + FreeRADIUS to read this, and set the Cleartext-Password control attribute. + + 2. You have access to the NT (MS-CHAPv2) or LM (MS-CHAPv1) hashes, + and you configure FreeRADIUS to read this and set the NT/LM-Password + control attribute. + + 3. You have Samba installed, joined into a windows domain, and use + the ntlm_auth helper binary to pass authentication onwards to + a domain controller. + +These are the ONLY possibilities; MS-CHAP is IMPOSSIBLE if you e.g. only +have the unix/md5/sha crypt of your users password. + +For more info, see: + + http://deployingradius.com/documents/protocols/compatibility.html + +EAP-MSCHAPv2 +============ + +The EAP module provides MS-CHAPv2 support as well. It simply passes the +data through to the mschap module, so you must configure mschap properly. + +ntlm_auth +========= + +Method 3 above involves configuring the mschap module to call the Samba +ntlm_auth helper: + +:: + + mschap { + ntlm_auth = "/path/to/bin ..." + } + +You need to be careful about setting this command line. There are several +options for the arguments, in particular username and domain: + + * --username=%{User-Name} - this will fail if you're using realms or host-based auth + * --username=%{mschap:User-Name} - this will fail if using using suffix i.e. user@domain + +You'll need to fit this to your local needs. + +Disabling ntlm_auth for some users +---------------------------------- + +You might have some users in the domain, and others in files or SQL that you +want to authenticate locally. To do this, set:: + + MS-CHAP-Use-NTLM-Auth := 0 + +This will disable ntlm_auth for that user/group. This is also obeyed +for password changes (see below). + +Password changes +================ + +From FreeRADIUS version 3.0.0 the mschap module supports password changes. + +There are two options, ntlm_auth and local. + +ntlm_auth +--------- + +If you are using ntlm_auth to check passwords, you must also use +ntlm_auth to change passwords. In modules/mschap you should configure:: + + mschap { + ntlm_auth = "...." + passchange { + + # path to the binary + ntlm_auth = "/path/to/ntlm_auth --helper-protocol=ntlm-change-password-1" + + # initial data to send + # this MUST be supplied + ntlm_auth_username = "username: %{mschap:User-Name}" + ntlm_auth_domain = "nt-domain: %{%{mschap:NT-Domain}:-YOURDOMAIN}" + + # Or, you could try: + ntlm_auth_username = "full-username: %{User-Name}" + # ntlm_auth_domain - disabled + + } + + +If you are using ntlm_auth, then domain controllers might say +"Password expired" if the user password is valid but has expired; the +mschap module will detect this and return error 648 to the client, +instructing it to try a password change. + +Note: if you have disabled ntlm_auth for a user/group, this will apply +for password changes too - they will fall through to using the Local +method. + +Local +----- + +If you are performing mschap locally with Cleartext-Password/NT-Password, you +can decrypt and process the password change locally. To do this, you configure +the "local_cpw" string:: + + mschap { + passchange { + local_cpw = "%{xlat:...} + } + } + +To actually force a client to change passwords, you must set the expiry bit +in the SMB-Account-Ctrl value - for example:: + + update control { + # U == user + # e == expired + SMB-Account-Ctrl-Text := '[Ue]' + } + +This will cause the client to receive "error 648 - password +expired". Obviously you will need to ensure your local_cpw xlat clears +this value, or else the client password will be expired the next time +they log in. For example, you might use an SQL stored procedure to +change passwords:: + + mschap { + passchange { + local_cpw = "%{sql:select change_password('%{SQL-User-Name}','%{MS-CHAP-New-NT-Password}')}" + } + } + +...and an example stored procedure for Postgres might be:: + + CREATE FUNCTION change_password(raduser text, ntpassword text) RETURNS text + LANGUAGE plpgsql + AS $$ + BEGIN + update radcheck set value=ntpassword where username=raduser and attribute='NT-Password'; + if not FOUND then + -- the user does not exist; die + return ''; + end if; + update radcheck set value=replace(value,'e','') where username=raduser and attribute='SMB-Account-Ctrl-Text' and value like '%e%'; + return 'ok'; + END; + $$; + + +The local_cpw xlat has access to two variables: + + * MS-CHAP-New-NT-Password - the new value of NT-Password + * MS-CHAP-New-Cleartext-PAssword - the new value of Cleartext-Password + +This allows you to do things like:: + + # update via SQL + local_cpw = "%{sql:update radcheck set value='%{MS-CHAP-New-NT-Password}' where username='%{SQL-User-Name} and attribute='NT-Password'}" + +Or:: + + # update via exec/script + local_cpw = "%{exec:/my/script %{User-Name} %{MS-CHAP-New-Cleartext-Password}}" + +WARNING - wherever possible, you should use +MS-CHAP-New-NT-Password. The reason is that cleartext passwords have +undergone unicode transformation from the client encoding (utf-16) to +the server encoding (utf-8) and the current code does this in a very +ad-hoc way. The reverse transformation is also not done - when the +server reads Cleartext-Password out of files/database, it assumes +US-ASCII and thus international characters will fail. + +N.B. this could be fixed, if we wanted to pull in something like iconv. + +In addition, you should beware of Cleartext-Password when using SQL; +any password character not in safe_characters will be encoded as a hex +number, e.g. =20. + +Password changes over EAP +========================= + +You must set the following in eap.conf:: + + eap { + mschapv2 { + send_error = yes + } + } + +Otherwise password changes for PEAP/MSCHAPv2 will not work. diff --git a/doc/modules/rlm_dbm b/doc/modules/rlm_dbm new file mode 100644 index 0000000..8ace2ff --- /dev/null +++ b/doc/modules/rlm_dbm @@ -0,0 +1,195 @@ +Radius DBM module + +0. INTRODUCTION + + rlm_dbm uses a Berkeley or GDBM <** database to store use information. It + is a lot faster than the files and passwd modules, takes less memory than + the fastusers module and does not require additional server software as + the LDAP and SQL modules does. In addition it supports groups, and of + course multiple entries per user or group. + +1. WHAT DOES IT DO + + Basically, it opens the file you specifies in radiusd.conf and authenticates + users out of it. The file has to be a Berkeley or GDBM <** file database, + and may be created by rlm_dbm_parse or by a custom program of your choice. + +2. HOW TO USE IT + + Put the module declaration in your radiusd.conf. It should in general look + like this: + + dbm { + usersfile = ${confdir}/users.db + } + Note: some dbm libraries add .db suffix by itself. + + Then put "dbm" in the "authorize {}" section of your radiusd.conf: + + authorize { + preprocess + realms + dbm + } + +3. MODULE OPTIONS + + The only option is "usersfile", which is the path and filename of the + database file you want rlm_dbm to look for users and groups in. This + file needs to be generated, either by the rlm_dbm_parse program or by + some custom program, for instance a Perl program using the DB_File or + GDBM_File <** modules. + +4. EXTERNAL UTILITIES + + rlm_dbm_cat + + rlm_dbm_cat: [-f file] [-w] [-i number] [-l number] [-v] [username ...] + + rlm_dbm_cat simply lists the definition(s) of the username(s) or group + name(s), or the entire database. It takes the following options: + + -f <filename> + + The file name of the database to list. + + -w + Long lines should be wrapped + + -i <number> +Set the left margin then wrapped. + -l <number> +How long line should be to be wrapped (wrap threshold) + + -v + + Print the version number and exit. + + rlm_dbm_parse + + rlm_dbm_parser [-c] [-d raddb] [-i inputfile] [-o outputfile] [-x] + [-v] [-q] [username ...] + + rlm_dbm_parses reads a file of the syntax defined below, and writes + a database file usable by rlm_dbm or edits current database. + It takes the following options: + + -i <file> + + Use <file> as the input file. If not defined then use standard input. + + -o + + Use <file> as the output file. + + -c + + Create a new database (empty output file before writing) + + -x + + Enable debug mode. +; Multiple x flag increase debug level + + -q + + Do not print statistics (quiet). + + -v + + Print the version and exit. + + -r + + Remove a username or group name from the database. + +5. INPUT FORMAT + + rlm_dbm_parse reads a format similar to the one used by the files + module. In incomplete RFC2234 ABNF, it looks like this: + + entries = *entry + entry = identifier TAB definition + identifier = username / group-name + username = +PCHAR + groupname = +PCHAR + definition = (check-item ",")* LF ( *( reply-item ",") / ";" ) LF + check-item = AS IN FILES + reply-item = AS IN FILES + +*** need definition of username and groupname *** + + As an example, these are the standard files definitions (files module). + +---8<--- + DEFAULT Service-Type == Framed-User + Framed-IP-Address = 255.255.255.254, + Framed-MTU = 576, + Service-Type = Framed-User, + Fall-Through = Yes + +#except who call from number 555-666 + DEFAULT Auth-Type := Reject,Service-Type ==Framed-User, + Calling-Station-ID == "555-666" + +#or call number 555-667 + DEFAULT Auth-Type := Reject,Service-Type ==Framed-User, + Calling-Station-ID == "555-667" +---8<--- + + To be a valid rlm_dbm input file, it should look like this: + +---8<--- + DEFAULT Service-Type == Framed-User # (1) + Framed-IP-Address = 255.255.255.254, # comma, list cont'd + Framed-MTU = 576, + Service-Type = Framed-User, + Fall-Through = Yes # \n, end of list + Auth-Type := Reject,Service-Type ==Framed-User, # (2) + Calling-Station-ID == "555-666" + ; # ;, no reply items + Auth-Type := Reject,Service-Type ==Framed-User, # (3) + Calling-Station-ID == "555-667" + ; # ditto +---8<--- + + This user (the DEFAULT user) contains three entries, 1, 2 and 3. The + first entry has a list of reply items, terminated by a reply item + without a trailing comma. Entries 2 and 3 has empty reply lists, as + indicated by the semicolon. This is necessary to separate an empty + line (which is ignored) from the empty list. + Definition Fall-Through = Yes used in order to say module to check next + record. By default Fall-Through = Yes. + + Groups + + This is implemented with the special User-Category attribute. Simply + set this as a reply item, and rlm_dbm will include the groups definition + when evaluating the check and reply items of the user. The group defined + the same way as users. Here is a short example: + +---8<--- +# group definitions +gendialup + Service-Type = Framed-User, + Cisco-AVPair += "ip:addr-pool=SANDY", + Framed-Protocol = PPP + +locked Auth-Type := Reject + Reply-Message = "Your account has been disabled." + +# user definitions +ssalex Auth-Type := Local, Password == "passs" + User-Category = "GenDialup" + +ssmike Auth-Type := Local, Password == "pass1" + User-Category = "Locked" +---8<--- + +6. ACKNOWLEDGMENTS + + Author - Andrei Koulik <rlm_dbm@agk.nnov.ru> + Documentation - Bjørn Nordbø <bn@nextra.com> +8. Bug reports: + rlm_dbm_bug@agk.nnov.ru + diff --git a/doc/modules/rlm_eap b/doc/modules/rlm_eap new file mode 100644 index 0000000..4f903af --- /dev/null +++ b/doc/modules/rlm_eap @@ -0,0 +1,395 @@ + + + Extensible Authentication Protocol (EAP) + + +INTRODUCTION + + Extensible Authentication Protocol(EAP), rfc2284, is a general protocol + that allows network access points to support multiple authentication + methods. Each EAP-Type indicates a specific authentication mechanism. + 802.1x standard authenticates wireless LAN users trying to access + enterprise networks. + + RADIUS attribute used for EAP is EAP-Message, 79(rfc2869). RADIUS + communicates all EAP messages by embedding them in this attribute. + + General Terminology + Supplicant/EAP Client - is the software on the end-user/client machine + (machine with the wireless card). + Authenticator/NAS/Access Point(AP) - A network device providing users + with a point of entry into the network. + EAPOL - EAP over LAN as defined in 802.1x standard. + EAPOW - EAP over Wireless. + + + +----------+ +----------+ +----------+ + | | EAPOL | | RADIUS | | + | EAP |<------>| Access |<------>| RADIUS | + | Client | EAPOW | Point | (EAP) | Server | + | | | | | | + +----------+ +----------+ +----------+ + + + The sequence of events, for EAP-MD5, runs as follows: + 1. The end-user associates with the Access Point(AP). + 2. The supplicant specifies AP to use EAP by sending EAP-Start. + 3. AP requests the supplicant to Identify itself (EAP-Identity). + 4. Supplicant then sends its Identity (username) to the AP. + 5. AP forwards this EAP-response AS-IS to the RADIUS server. + (The supplicant and the RADIUS server mutually authenticate via AP. + AP just acts as a passthru till authentication is finished.) + 6. The server sends a challenge to the supplicant. + 7. The supplicant carries out a hash on the password and sends + this hashed password to the RADIUS server as its response. + 8. The RADIUS server performs a hash on the password for that supplicant + in its user database and compares the two hashed values and + authenticates the client if the two values match(EAP-Success/EAP-Failure) + 9. AP now opens a port to accept data from the end-user. + + Currently, EAP is widely used in wireless networks than in wired networks. + In 802.11/wireless based networking, following sequence of events happen in + addition to the above EAP events. + + 10. RADIUS server and the supplicant agree to a specific WEP key. + 11. The supplicant loads the key ready for logging on. + 12. The RADIUS server sends the key for this session (Session key) to the AP. + 13. The AP encrypts its Broadcast key with the Session key + 14. The AP sends the encypted key to the supplicant + 15. The supplicant decrypts the Broadcast key with the Session key and + the session continues using the Broadcast and Session keys until + the session ends. + + References: + The Implementation of EAP over RADIUS is based on the following RFCs + rfc2869 -- RADIUS Extensions + rfc2284 -- PPP Extensible Authentication Protocol (EAP) + rfc2716 -- PPP EAP TLS Authentication Protocol + + Following links help to understand HOW EAP works + www.ieee802.org/1/mirror/8021/docs2000/ieee_plenary.PDF + + +EAP CODE ORGANIZATION + + EAP is implemented as a module in freeradius + and the code is placed in src/modules/rlm_eap. + All EAP-Types are organized as subdirectories in rlm_eap/types/. + + Each EAP-Type, like types/rlm_eap_md5, contains a chunk of code that + knows how to deal with a particular kind of authentication mechanism. + + To add a new EAP-Type then a new directory should be created as + rlm_eap/types/rlm_eap_XXXX, where XXXX is EAP-Type name + ie for EAP-Type like ONE TIME PASSWORD (OTP) it would be rlm_eap_otp + + src/modules/rlm_eap -- contains the basic EAP and generalized interfaces + to all the EAP-Types. + rlm_eap/types -- contains all the supported EAP-Types + rlm_eap/types/rlm_eap_md5 -- EAP-MD5 authentication. + rlm_eap/types/rlm_eap_tls -- EAP-TLS based authentication. + rlm_eap/types/rlm_eap_ttls -- TTLS based authentication. + rlm_eap/types/rlm_eap_peap -- Windows PEAP based authentication. + rlm_eap/types/rlm_eap_sim -- EAP-SIM (GSM) based authentication + +CONFIGURATION + + Add the eap configuration stanza to the modules section in radiusd.conf + to load and control rlm_eap and all the supported EAP-Types: + + For example: + modules { + ... + eap { + default_eap_type = md5 + + md5 { + } + ... + } + ... + } + + NOTE: You cannot have empty eap stanza. At least one EAP-Type sub-stanza + should be defined as above, otherwise the server will not know what type + of eap authentication mechanism to be used and the server will exit + with error. + + All the various options and their associated default values for each + EAP-Type are documented in the sample radiusd.conf that is provided + with the distribution. + + Since the EAP requests may not contain a requested EAP type, the + 'default_eap_type' configuration options is used by the EAP module + to determine which EAP type to choose for authentication. + + NOTE: EAP cannot authorize a user. It can only authenticate. + Other Freeradius modules authorize the user. + + +EAP SIM server + + To configure EAP-SIM authentication, the following attributes must be + set in the server. This can be done in the users file, but in many cases + will be taken from a database server, via one of the SQL interface. + + If one has SIM cards that one controls (i.e. whose share secret you know), + one should be able to write a module to generate these attributes + (the triplets) in the server. + + If one has access to the SS7 based settlement network, then a module to + fetch appropriate triplets could be written. This module would act as + an authorization only module. + + The attributes are: + EAP-Sim-Rand1 16 bytes + EAP-Sim-SRES1 4 bytes + EAP-Sim-KC1 8 bytes + EAP-Sim-Rand2 16 bytes + EAP-Sim-SRES2 4 bytes + EAP-Sim-KC2 8 bytes + EAP-Sim-Rand3 16 bytes + EAP-Sim-SRES3 4 bytes + EAP-Sim-KC3 8 bytes + + EAP-SIM will send WEP attributes to the resquestor. + +EAP CLIENTS + + 1. eapol_test, from wpa_supplicant. + + 2. Freeradius has an "radeapclient" that can do EAP-MD5 (passwords), + as well as EAP-SIM. It is in modules/rlm_eap/radeapclient. + +TESTING + + You will find several test cases in src/tests/ for the EAP-SIM code. + + +HOW DO I USE IT (FAQ/Examples) + + 1. How can I enable EAP-MD5 authentication ? + + In radiusd.conf + + modules { + ... + eap { + default_eap_type = md5 + md5 { + } + ... + } + ... + } + + # eap sets the authenticate type as EAP + authorize { + ... + eap + } + + # eap authentication takes place. + authenticate { + eap + } + + # If you are proxying EAP-LEAP requests + # This is required to make LEAP work. + post-proxy { + eap + } + + 2. My Userbase is in LDAP and I want to use EAP-MD5 authentication + + In radiusd.conf + + modules { + ... + eap { + default_eap_type = md5 + md5 { + } + ... + } + ... + } + + # ldap gets the Configured password. + # eap sets the authenticate type as EAP + authorize { + ... + ldap + eap + ... + } + + # eap authentication takes place. + authenticate { + ... + eap + ... + } + + 3. How can I Proxy EAP messages, with/without User-Name attribute + in the Access-Request packets + + With User-Name attribute in Access-Request packet, + EAP-proxying is just same as RADIUS-proxying. + + If User-Name attribute is not present in Access-Request packet, + Freeradius can proxy the request with the following configuration + in radiusd.conf + + # eap module should be configured as the First module in + # the authorize stanza + + authorize { + eap + ... other modules. + } + + With this configuration, eap_authorize creates User-Name attribute + from EAP-Identity response, if it is not present. + Once User-Name attribute is created, RADIUS proxying takes care + of EAP proxying. + + 4. How Freeradius can handle EAP-START messages ? + + In most of the cases this is handled by the Authenticator. + + Only if it is required then, in radiusd.conf + + authorize { + eap + ... other modules. + } + + With the above configuration, RADIUS server immediately responds with + EAP-Identity request. + + NOTE: EAP does not check for any Identity or maintains any state in case + of EAP-START. It blindly responds with EAP-Identity request. + Proxying is handled only after EAP-Identity response is received. + + 5. I want to enable multiple EAP-Types, how can I configure ? + + In radiusd.conf + + modules { + ... + eap { + default_eap_type = tls + md5 { + } + tls { + ... + } + ... + } + ... + } + + The above configuration will let the server load all the EAP-Types, + but the server can have only one default EAP-Type, as above. + + Once EAP-Identity response is received by the server, based on the + default_eap_type, the server will send a new request (MD5-Challenge + request incase of md5, TLS-START request incase of tls) to the supplicant. + If the supplicant is rfc2284 compliant and does not support the + EAP-Type sent by the server then it sends EAP-Acknowledge with the + supported EAP-Type. If this EAP-Type is supported by the server then it + will send the respective EAP-request. + + Example: If the supplicant supports only EAP-MD5 but the server + default_eap_type is configured as EAP-TLS, as above, then the server + will send TLS-START after EAP-Identity is received. Supplicant will + respond with EAP-Acknowledge(EAP-MD5). Server now responds with + MD5-Challenge. + + +INSTALLATION + EAP, EAP-MD5, and Cisco LEAP do not require any additional packages. + Freeradius contains all the required packages. + + For EAP-TLS, EAP-TTLS, and PEAP, OPENSSL, <http://www.openssl.org/>, + is required to be installed. + Any version from 0.9.7, should fairly work with this module. + + EAP-SIM should not require any additional packages. + + +IMPLEMENTATION (For Developers) + + The rlm_eap module only deals with EAP specific authentication mechanism + and the generic interface to interact with all the EAP-Types. + + Currently, these are the existing interfaces, + int attach(CONF_SECTION *conf, void **type_arg); + int initiate(void *type_arg, EAP_HANDLER *handler); + int authenticate(void *type_arg, EAP_HANDLER *handler); + int detach(void **type_arg); + + attach() and detach() functions allocate and deallocate all the + required resources. + + initiate() function begins the conversation when EAP-Identity response + is received. Incase of EAP-MD5, initiate() function sends the challenge. + + authenticate() function uses specific EAP-Type authentication mechanism + to authenticate the user. During authentication many EAP-Requests and + EAP-Responses takes place for each authentication. Hence authenticate() + function may be called many times. EAP_HANDLER contains the complete + state information required. + + +HOW EAP WORKS + as posted to the list, by John Lindsay <jlindsay@internode.com.au> + + To make it clear for everyone, the supplicant is the software on the + client (machine with the wireless card). + + The EAP process doesn't start until the client has associated with + the Access Point using Open authentication. If this process isn't + crystal clear you need to go away and gain understanding. + + Once the association is made the AP blocks all traffic that is not + 802.1x so although associated the connection only has value for EAP. + Any EAP traffic is passed to the radius server and any radius traffic + is passed back to the client. + + So, after the client has associated to the Access Point, the + supplicant starts the process for using EAP over LAN by asking the + user for their logon and password. + + Using 802.1x and EAP the supplicant sends the username and a one-way + hash of the password to the AP. + + The AP encapsulates the request and sends it to the RADIUS server. + + The radius server needs a plaintext password so that it can perform + the same one-way hash to determine that the password is correct. If + it is, the radius server issues an access challenge which goes back + via to the AP to the client. (my study guide says client but my + brain says 'supplicant') + + The client sends the EAP response to the challenge via the AP to the + RADIUS server. + + If the response is valid the RADIUS server sends a success message + and the session WEP key (EAP over wireless) to the client via the + AP. The same session WEP key is also sent to the AP in the success + packet. + + The client and the AP then begin using session WEP keys. The WEP key + used for multicasts is then sent from the AP to the client. It is + encrypted using the session WEP key. + +ACKNOWLEDGEMENTS + Primary author - Raghu <raghud@mail.com> + + EAP-SIM - Michael Richardson <mcr@sandelman.ottawa.on.ca> + The development of the EAP/SIM support was funded by + Internet Foundation Austria (http://www.nic.at/ipa). + + diff --git a/doc/modules/rlm_expiration b/doc/modules/rlm_expiration new file mode 100644 index 0000000..eb7918b --- /dev/null +++ b/doc/modules/rlm_expiration @@ -0,0 +1,23 @@ +Module to expire user accounts. + +This module can be used to expire user accounts. Expired users receive +an Access-Reject on every authentication attempt. Expiration is based +on the Expiration attribute which should be present in the check item +list for the user we wish to perform expiration checks. + + + +Expiration attribute format: + +You can use Expiration := "23 Sep 2004" and the user will +no longer be able to connect at 00:00 (midnight) on September 23rd, +2004. If you want a certain time (other than midnight) you can do +use Expiration := "23 Sep 2004 12:00". +The nas will receive a Session-Timeout attribute calculated to kick +the user off when the Expiration time occurs. + + + +Example entry (users files): + +user1 Expiration := "23 Sep 2004" diff --git a/doc/modules/rlm_krb5 b/doc/modules/rlm_krb5 new file mode 100644 index 0000000..d70017f --- /dev/null +++ b/doc/modules/rlm_krb5 @@ -0,0 +1,47 @@ +The `rlm_krb5` FreeRADIUS module enables the use of Kerberos 5 for +authentication. + +Compilation issues +================== + +MIT libraries +------------- + +The `rlm_krb5` module, by default, presumes you have the MIT Kerberos 5 +distribution. Notes from that distribution: + +On linux, you may have to change: + + deplibs_test_method="pass_all" + +in `../libtool` + +Otherwise, it complains if the krb5 libs aren't shared. + +Heimdal libraries +----------------- + +If you are using the Heimdal Kerberos 5 distribution, pass an +`--enable-heimdal-krb5` option to `configure`. + +Configuration parameters +======================== + +You can configure the module with the following parameters: + + krb5 { + # Keytab containing the key used by rlm_krb5 + keytab = /path/to/keytab + + # Principal that is used by rlm_krb5 + service_principal = radius/some.host.com + } + +Make sure the keytab is readable by the user that is used to run `radiusd` and +that your authorization configuration really uses `rlm_krb5` to do the +authentication. You will need to add the following to the 'authenticate' +section of your radiusd.conf file: + + Auth-Type Kerberos { + krb5 + } diff --git a/doc/modules/rlm_pam b/doc/modules/rlm_pam new file mode 100644 index 0000000..8a6673c --- /dev/null +++ b/doc/modules/rlm_pam @@ -0,0 +1,108 @@ + + PAM Support for FreeRadius + + +0. INTRODUCTION + + PAM support was done by Jeph Blaize. Miguel a.l. Paraz <map@iphil.net> + ported it to FreeRADIUS' parent, Cistron-Radius. Chris Dent <cdent@kiva.net> + added the Pam-Auth attribute. + +1. USAGE + + Use Auth-Type = Pam in the users file. You cannot use User-Password = "PAM" + as in other radius servers. Sorry. + + You can also use ``Pam-Auth = "somestring"'' to specify an entry in + /etc/pam.d. The default is "radius". + + Compile and install freeradius with pam support (./configure --help + will tell you how) + + Within your radiusd.conf file, in the 'modules' section, make sure + that the pam section is enabled: + + pam { + # + # The name to use for PAM authentication. + # PAM looks in /etc/pam.d/${pam_auth_name} + # for it's configuration. + # + # Note that any Pam-Auth attribute set in the 'users' + # file over-rides this one. + # + pam_auth = radiusd + } + + In the 'authenticate' section, do the same: + + authenticate { + # Uncomment this if you want to use PAM (Auth-Type = PAM) + pam + ... + + + In your /etc/pam.d/ directory create a file called radiusd with the + following contents (or whatever you want for your pam configuration, + this seems to work for me): + +#%PAM-1.0 +auth required /lib/security/pam_unix_auth.so shadow md5 nullok +auth required /lib/security/pam_nologin.so +account required /lib/security/pam_unix_acct.so +password required /lib/security/pam_cracklib.so +password required /lib/security/pam_unix_passwd.so shadow md5 nullok use_authtok +session required /lib/security/pam_unix_session.so + + + If you don't want to run your freeradius server in debug mode as + root (ie, run as an unpriviledged user) you will need to run + freeradius with a group membership that is able to read the + /etc/shadow file - otherwise pam will be unable to read the + /etc/shadow file and will fail. I suggest a group called 'shadow' or + the like. + + $ chgrp /etc/shadow shadow + $ chmod g+w /etc/shadow + + And in the radiusd.conf file: + + # On systems with shadow passwords, you might have to set 'group = shadow' + # for the server to be able to read the shadow password file. + # + # Change below to suit your setup. + user = radius + group = shadow + + + Please understand that giving anything except root read permissions + to the /etc/shadow file is something that you want to think a bit + upon!! + +2. NOTES + + None. + +3. TODO: + + Real PAM support, figure out how we can write a module that will make + it blend in with PAM more seamlessly. With this, we can replace the + DENY_SHELL with something more flexible such as a database. + +4. EXAMPLE: + +DEFAULT Auth-Type = Pam, NAS-IP-Address = 206.97.64.5 + Service-Type = Framed-User, + Framed-Protocol = PPP, + Framed-IP-Address = 255.255.255.254, + Filter-Id = "std.ppp", + Framed-MTU = 1500, + Framed-Compression = Van-Jacobson-TCP-IP +DEFAULT Auth-Type = Pam, Pam-Auth = "radius2", NAS-IP-Address = 127.0.0.1 + Service-Type = Framed-User, + Framed-Protocol = PPP, + Framed-IP-Address = 255.255.255.254, + Filter-Id = "std.ppp", + Framed-MTU = 1500, + Framed-Compression = Van-Jacobson-TCP-IP + diff --git a/doc/modules/rlm_passwd b/doc/modules/rlm_passwd new file mode 100644 index 0000000..59f4a59 --- /dev/null +++ b/doc/modules/rlm_passwd @@ -0,0 +1,50 @@ +RADIUS rlm_passwd (passwd-like files authorization module) + +FAQ + +Q: Can I use rlm_passwd to authenticate user against Linux shadow password + file or BSD-style master.passwd? +A: Yes, but you need RADIUS running as root. Hint: use Crypt-Password + attribute. You probably don't want to use this module with + FreeBSD to authenticate against system file, as it already takes care + of caching passwd file entries, but it may be helpfull to authenticate + against alternate file. + +Q: Can I use rlm_passwd to authenticate user against SAMBA smbpasswd? +A: Yes, you can. Hint: use LM-Password/NT-Password attribute, set + authtype = MS-CHAP. + +Q: Can I use rlm_password to authenticate user against BLA-BLA-BLApasswd? +A: Probably you can, if BLA-BLA-BLA stores password in some format supported + by RADIUS, for example cleartext, NT/LM hashes, crypt, Netscape MD5 format. + You have to set authtype to corresponding type, for example + authtype = NS-MTA-MD5 + for Netscape MD5. + +Q: Are where are differences between rlm_passwd and rlm_unix? +A: rlm_passwd supports passwd files in any format and may be used, for + example, to parse FreeBSD's master.passwd or SAMBA smbpasswd files, but + it can't perform system authentication (for example to authenticate + NIS user, like rlm_unix does). If you need system authentication you + need rlm_unix, if you have to authenticate against files only under + BSD you need rlm_passwd, if you need to authenticate against files only + under Linux, you can choose between rlm_unix and rlm_passwd, probably + you will have nearly same results in performance (I hope :) ). + +Q: I'm using realms with rlm_passwd. I see rlm_passwd do not strip realm + from user name. How to configure rlm_passwd to strip realm? + +A: In case you configured realm to strip username, User-Password attribute + is not changed. Instead, rlm_realm creates new attribute Stripped-User-Name. + All you need is to use Stripped-User-Name instead of User-Name as a key + field for passwd file. + +Q: How can I say passwd to add attribute even if it's value is empty? + +A: set ignore_empty to "no" in module configuration. + + +5. Acknowlegements: + + ZARAZA, <3APA3A@security.nnov.ru> + Michael Chernyakhovsky <mike@mgn.ru> - reply-items support diff --git a/doc/modules/rlm_python b/doc/modules/rlm_python new file mode 100644 index 0000000..ef35f1b --- /dev/null +++ b/doc/modules/rlm_python @@ -0,0 +1,76 @@ +Python module for freeradius +Copyright 2002 Miguel A Paraz <mparaz@mparaz.com> +Copyright 2002 Imperium Technology, Inc. + +PURPOSE: +To allow module writers to write modules in a high-level language, +for implementation or for prototyping. + +REQUIRES: +Python - tested with 2.2 + +BUILDING: +./configure --with-experimental-modules + + +USAGE: +Make your module available to the Python interpreter by either putting it +in a standard location, or 'EXPORT PYTHONPATH=$location'. + + + + + +BUGS: +1. Can't compile statically (./configure --enable-shared=no) - causes +SIGSEGV on the first malloc() in main(). + +Design: +1. Support for all module functions. +2. One module per function allowed, for example, from experimental.conf: + + python { + mod_instantiate = radiusd_test + func_instantiate = instantiate + + mod_authorize = radiusd_test + func_authorize = authorize + + mod_accounting = radiusd_test + func_accounting = accounting + + mod_preacct = radiusd_test + func_preacct = preacct + + mod_detach = radiusd_test + func_detach = detach + + } + + +3. Different functions are wrappers around the same core. +4. func_detach is passed no parameters, returns module return value. +5. If functions returns None (plain 'return' no return), default to RLM_OK +6. Python instantation function can return -1 to signal failure and abort + startup. + +Available to module: +import radiusd +radiusd.rad_log(radiusd.L_XXX, message_string) +radiusd.RLM_XXX + + + +TODO: +1. Do we need to support other pair operations beyond set (:=) ? +2. Should we pass the value pair info as a dict and not a tuple? Faster? +2. Give access to more radiusd variables like the dictionary. +3. Give access to other C functions. + Let the Python module deal with the structures directly, instead of + letting our C code do it afterwards. + What's a good way to represent this? + + + + + diff --git a/doc/modules/rlm_soh b/doc/modules/rlm_soh new file mode 100644 index 0000000..eda5c4c --- /dev/null +++ b/doc/modules/rlm_soh @@ -0,0 +1,183 @@ +== Intro == + +This release adds support for Microsoft Statement-of-Health (SoH), which is +a form of network access protection. + +Client support is present in Windows XP SP3, Vista and 7. + +SoH data can come in from several places: + + * inside EAP-PEAP packets for 802.1x wireless/wired connections + * inside a radius packet (Microsoft VSA #55, MS-Quarantine-SOH) - VPN and + terminal services gateways can act as the radius client + * inside a DHCP request, in vendor-specific options + +FreeRadius supports all three types. The SoH statement is decoded into +radius-style attributes, and you can write a policy in "unlang" to act +on them, and permit, restrict or deny network access. + +== PEAP support == + +SoH support in peap is enabled in eap.conf using config like so: + + eap { + peap { + soh = yes + soh_virtual_server = "soh-server" + } + } + +When SoH is enabled, an EAP-PEAP client will be challenged to provide an +SoH statement after providing it's identity (or resuming a PEAP session via +SSL session resumption). Clients which do not support PEAP will NAK the +request, and clients which do will answer it. + +The client reply will be written into a fake radius request and sent to the +virtual server specified above; it will either look like: + + SoH-Supported = no + +...or (from a Vista machine): + + SoH-Supported = yes + SoH-MS-Machine-OS-vendor = Microsoft + SoH-MS-Machine-OS-version = 6 + SoH-MS-Machine-OS-release = 0 + SoH-MS-Machine-OS-build = 6001 + SoH-MS-Machine-SP-version = 1 + SoH-MS-Machine-SP-release = 0 + SoH-MS-Machine-Processor = x86_64 + SoH-MS-Machine-Name = "netbios.example.com" + SoH-MS-Correlation-Id = 0x54468936cb494374b127a6a3cc3bb11c01ca78d858ee1ef0 + SoH-MS-Machine-Role = client + SoH-MS-Windows-Health-Status = "firewall ok snoozed=0 microsoft=1 up2date=1 enabled=1" + SoH-MS-Windows-Health-Status = "antivirus error not-installed" + SoH-MS-Windows-Health-Status = "antispyware ok snoozed=0 microsoft=1 up2date=1 enabled=1" + SoH-MS-Windows-Health-Status = "auto-updates ok action=install" + SoH-MS-Windows-Health-Status = "security-updates warn some-missing" + +If you have "copy_request_to_tunnel = yes" set on the peap module, the +request variables like NAS-IP-Address and so on will be copied to the fake +request as well. + +Clients without SoH seem to just NAK the SoH request and continue with the inner +EAP auth. This has been tested as working with Windows XP SP2 and lower, Linux +clients using NetworkManager & wpa_supplicant, MacOS 10.5, Nokia/Symbian S60 and +iPhone OS 3.x. It should therefore be safe to deploy. + +== Radius support == + +If you are running a Microsoft VPN or Terminal Services Gateway, these can +be configured to send the SoH data to an upstream radius server, in this +case presumably FreeRadius. To take advantage of this you will need to add +the "soh" module to the "authorize" section of your virtual server, like so: + +server tsgateway { + preprocess + soh + if () { + ... policy goes here + } +} + +The SoH module simply looks for the Microsoft VSA #55 and decodes the SoH +data, adding the SoH attributes to the request - see above for an example +of the available attributes. + +The SoH module also does dynamic expansions - see below for more info. + +== DHCP support == + +If you compile FreeRadius with DHCP support, the "soh" module can challenge +a DHCP client for SoH data in the DHCPOFFER packet. As with normal radius, +the SoH attributes are added to the request. You would use like so: + +server dhcp { + dhcp DHCP-Discover { + soh + # note - no SoH attributes are added here, the client hasn't sent them yet + + # other DHCP config + } + + dhcp DHCP-Request { + soh + if () { + # SoH policy + } + # other DHCP config + } +} + +== soh module == + +The "soh" module decodes the radius & DHCP payloads. It also makes some dynamic +variables available, for example: + +authorize { + soh + update request { + Tmp-String-0 = "%{soh:OS}" + } +} + +...will give you a string like "Windows Vista 6.1.100 sp 1.0" or "Windows XP 5.x.x sp 3.0" + +At the moment, this is the only dynamic expansion; in future, we will make +various bits of info available, for example non-Microsoft SoH records (see below) + +== Non-microsoft SoH data == + +The Windows SoH structure is extensible and, in principle, clients can be +extended with .dll plugins to add vendor-specific info to the SoH, which +can then be checked on the server. + +At the present time, few plugins are known and I have seen none, so can't +add support for them. + +== Client configuration == + +The code works fine with Win XP SP3 & Vista on both wired & wireless. However +contrary to what some sites claim, the NAP service is disabled by default, as +are the many NAP remediation agents. These can be enabled from the command prompt +with (for XP; instructions may differ for other windows versions): + + sc config napagent start= auto + sc start napagent + + # optionally for wired 802.1x; the dot3svc should usually be made dependent + # on the napagent service, else the machine might attempt 802.1x before NAP + # has started... + + sc config dot3svc start= auto depend= napagent + sc start dot3svc + + # enable the EAP agent + netsh nap client show config + + # get the "ID" value for the "EAP Quarantine Enforcement Client" + netsh nap client set enforce id=$ID admin=enable + + # repeat for DHCP, VPN or Terminal Services agents + +This can be automated via Group Policy. + +You then need to enable EAP, PEAP, Quarantine Checks & the relevant auth method +on the relevant adapters. This can be done with "netsh xml profiles" or Group +Policy - google for the relevant terms, or see the MS article: + + http://technet.microsoft.com/en-us/library/bb726965.aspx + +...and related links. + +== TODO == + +Currently the code does not support sending the final SoH reply. This +is because the SoH reply (see section 2.2.9 of MS-SOH version +v20091104) needs various fields formatted in a manner which is not +obvious to me, and I don't currently have access to a windows NAP +server to look at a working example. The clients I have access don't +seem to mind. + + Phil Mayers <p.mayers@imperial.ac.uk> + December 2009 diff --git a/doc/modules/rlm_sql b/doc/modules/rlm_sql new file mode 100644 index 0000000..0f06660 --- /dev/null +++ b/doc/modules/rlm_sql @@ -0,0 +1,283 @@ + SQL Module + +0. Introduction + + The SQL module is composed of two parts: a generic SQL front-end + (rlm_sql), and a series of database-dependent back-end drivers, + (rlm_sql_mysql, rlm_sql_postgresql, etc.) + + In order to build the drivers, you MUST ALSO install the development + versions of the database. That is, you must have the appropriate + header files and client libraries for (say) MySQL. The + rlm_sql_mysql driver is NOT a complete MySQL client implementation. + Instead, it is a small 'shim' between the FreeRADIUS rlm_sql module, + and the MySQL client libraries. + + + In general, the SQL schemas mirror the layout of the 'users' file. + So for configuring check items and reply items, see 'man 5 users', + and the examples in the 'users' file. + + +1. Schema and usage + + The schemas are available in raddb/sql/<DB>/*, where <DB> is the + name of the database (mysql, postgresql, etc.) + + The SQL module employs two sets of check and reply item tables for + processing in the authorization stage. One set of tables (radcheck and + radreply) are specific to a single user. The other set of tables + (radgroupcheck and radgroupreply) is used to apply check and reply items + to users that are members of a certain SQL group. The usergroup table + provides the list of groups each user is a member of along with a priority + field to control the order in which groups are processed. + + When a request comes into the server and is processed by the SQL module, + the flow goes something like this: + + 1. Search the radcheck table for any check attributes specific to the user + 2. If check attributes are found, and there's a match, pull the reply items + from the radreply table for this user and add them to the reply + 3. Group processing then begins if any of the following conditions are met: + a. The user IS NOT found in radcheck + b. The user IS found in radcheck, but the check items don't match + c. The user IS found in radcheck, the check items DO match AND + Fall-Through is set in the radreply table + d. The user IS found in radcheck, the check items DO match AND + the read_groups directive is set to 'yes' + 4. If groups are to be processed for this user, the first thing that is + done is the list of groups this user is a member of is pulled from the + usergroup table ordered by the priority field. The priority field of + the usergroup table allows us to control the order in which groups are + processed, so that we can emulate the ordering in the users file. This + can be important in many cases. + 5. For each group this user is a member of, the corresponding check items + are pulled from radgroupcheck table and compared with the request. If + there is a match, the reply items for this group are pulled from the + radgroupreply table and applied. + 6. Processing continues to the next group IF: + a. There was not a match for the last group's check items OR + b. Fall-Through was set in the last group's reply items + (The above is exactly the same as in the users file) + 7. Finally, if the user has a User-Profile attribute set or the Default + Profile option is set in the sql.conf, then steps 4-6 are repeated for + the groups that the profile is a member of. + + For any fairly complex setup, it is likely that most of the actual + processing will be done in the groups. In these cases, the user entry in + radcheck will be of limited use except for things like setting the user's + password. So, one might have the following setup: + + radcheck table: + joeuser Cleartext-Password := somepassword + + radreply table: + joeuser Fall-Through = Yes + + radgroupcheck table: + Check items for various connection scenarios + + radgroupreply table: + reply items for the groups + + usergroup table: + joeuser WLANgroup 1(this is the priority) + joeuser PPPgroup 2 + + +2. What NOT to do. + + One of the fields of the SQL schema is named 'op' This is for the + 'operator' used by the attributes. e.g.: + + Framed-IP-Address = 1.2.3.4 + ^ ATTRIBUTE ----^ ^ OP ^ VALUE + + If you want the server to be completely misconfigured, and to never + do what you want, leave the 'op' field blank. If you want to be + rudely told to RTFM, then post questions on the mailing list, asking + + "why doesn't my SQL configuration work when I leave the 'op' field empty?" + + + The short answer is that with the op field empty, the server does + not know what you want it to do with the attribute. Should it be + added to the reply? Maybe you wanted to compare the operator to one + in the request? The server simply doesn't know. + + So put a value in the field. The value is the string form of the + operator: "=", ">=", etc. See Section 4, below, for more details. + + +3. Authentication versus Authorization + + Many people ask if they can "authenticate" users to their SQL + database. The answer to this question is "You're asking the wrong + question." + + An SQL database stores information. An SQL database is NOT an + authentication server. The ONLY users who should be able to + authenticate themselves to the database are the people who + administer it. Most administrators do NOT want every user to be + able to access the database, which means that most users will not be + able to "authenticate" themselves to the database. + + Instead, the users will have their authorization information (name, + password, configuration) stored in the database. The configuration + files for FreeRADIUS contain a username and password used to + authenticate FreeRADIUS to the SQL server. (See raddb/sql.conf). + Once the FreeRADIUS authentication server is connected to the SQL + database server, then FreeRADIUS can pull user names and passwords + out of the database, and use that information to perform the + authentication. + +4. Operators + + The list of operators is given below. + + Op Example and documentation + -- ------------------------- + + = "Attribute = Value" + + Not allowed as a check item for RADIUS protocol attributes. It is + allowed for server configuration attributes (Auth-Type, etc), and sets + the value of on attribute, only if there is no other item of the + same attribute. + + As a reply item, it means "add the item to the reply list, but + only if there is no other item of the same attribute." + + + := "Attribute := Value" + + Always matches as a check item, and replaces in the + configuration items any attribute of the same name. If no + attribute of that name appears in the request, then this + attribute is added. + + As a reply item, it has an identical meaning, but for the + reply items, instead of the request items. + + == "Attribute == Value" + + As a check item, it matches if the named attribute is present + in the request, AND has the given value. + + Not allowed as a reply item. + + + += "Attribute += Value" + + Always matches as a check item, and adds the current attribute + with value to the list of configuration items. + + As a reply item, it has an identical meaning, but the + attribute is added to the reply items. + + + != "Attribute != Value" + + As a check item, matches if the given attribute is in the + request, AND does not have the given value. + + Not allowed as a reply item. + + + > "Attribute > Value" + + As a check item, it matches if the request contains an + attribute with a value greater than the one given. + + Not allowed as a reply item. + + + >= "Attribute >= Value" + + As a check item, it matches if the request contains an + attribute with a value greater than, or equal to the one + given. + + Not allowed as a reply item. + + < "Attribute < Value" + + As a check item, it matches if the request contains an + attribute with a value less than the one given. + + Not allowed as a reply item. + + + <= "Attribute <= Value" + + As a check item, it matches if the request contains an + attribute with a value less than, or equal to the one given. + + Not allowed as a reply item. + + + =~ "Attribute =~ Expression" + + As a check item, it matches if the request contains an + attribute which matches the given regular expression. This + operator may only be applied to string attributes. + + Not allowed as a reply item. + + + !~ "Attribute !~ Expression" + + As a check item, it matches if the request contains an + attribute which does not match the given regular expression. + This operator may only be applied to string attributes. + + Not allowed as a reply item. + + + =* "Attribute =* Value" + + As a check item, it matches if the request contains the named + attribute, no matter what the value is. + + Not allowed as a reply item. + + + !* "Attribute !* Value" + + As a check item, it matches if the request does not contain + the named attribute, no matter what the value is. + + Not allowed as a reply item. + +5. Instances + + Just like any other module, multiple instances of the rlm_sql + module can be defined and used wherever you like. + + The default .conf files for the different database types, + contain 1 instance without a name like so: + sql { + ... + } + + You can create multiple named instances like so: + sql sql_instance1 { + ... + } + sql sql_instance2 { + ... + } + + And then you can use a specific instance in radiusd.conf, like + so: + authorize { + ... + sql_instance1 + ... + } + accounting { + ... + sql_instance1 + sql_instance2 + ... + } diff --git a/doc/modules/rlm_sqlcounter b/doc/modules/rlm_sqlcounter new file mode 100644 index 0000000..54ad170 --- /dev/null +++ b/doc/modules/rlm_sqlcounter @@ -0,0 +1,182 @@ +rlm_sqlcounter installation and running guide +by Ram Narula ram@princess1.net +Internet for Education (Thailand) + +*) Pre-requisites: +Make sure to have configured radiusd with rlm_sqlcounter +installed + +> make clean +> ./configure --with-experimental-modules +> make +> make install + +Make sure to have radiusd running properly under sql +and there must be a "sql" entry under accounting{ } section +of radiusd.conf + +*) Configuration: + +[1] Create a text file called sqlcounter.conf in the same +directory where radiusd.conf resides (usually /usr/local/etc/raddb) +with the following content (for mysql): + +#-----# +sqlcounter noresetcounter { + sql_module_instance = sqlcca3 + counter_name = Max-All-Session-Time + check_name = Max-All-Session + reply_name = Session-Timeout + key = User-Name + reset = never + + query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'" + + } + + +sqlcounter dailycounter { + sql_module_instance = sqlcca3 + driver = "rlm_sqlcounter" + counter_name = Daily-Session-Time + check_name = Max-Daily-Session + reply_name = Session-Timeout + key = User-Name + reset = daily + + query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" + + } + +sqlcounter monthlycounter { + sql_module_instance = sqlcca3 + counter_name = Monthly-Session-Time + check_name = Max-Monthly-Session + reply_name = Session-Timeout + key = User-Name + reset = monthly + + query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" + + } + +#-----# + +The respective lines for postgresql are: + +query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'" +query = "SELECT SUM(AcctSessionTime - GREATEST((%b - EXTRACT(epoch FROM AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND EXTRACT(epoch FROM AcctStartTime) + AcctSessionTime > '%b'" +query = "SELECT SUM(AcctSessionTime - GREATEST((%b - EXTRACT(epoch FROM AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND EXTRACT(epoch FROM AcctStartTime) + AcctSessionTime > '%b'" + +If you are running postgres 7.x, you may not have a GREATEST function. + +An example of one is: + +CREATE OR REPLACE FUNCTION "greater"(integer, integer) RETURNS integer AS ' +DECLARE + res INTEGER; + one INTEGER := 0; + two INTEGER := 0; +BEGIN + one = $1; + two = $2; + IF one IS NULL THEN + one = 0; + END IF; + IF two IS NULL THEN + two = 0; + END IF; + IF one > two THEN + res := one; + ELSE + res := two; + END IF; + RETURN res; +END; +' LANGUAGE 'plpgsql'; + +[2] Include the above file to radiusd.conf by adding a line in +modules{ } section + +modules { + +$INCLUDE ${confdir}/sqlcounter.conf + +...some other entries here... + +[3] Make sure to have the sqlcounter names under authorize section +like the followings: + +authorize { +...some entries here... +...some entries here... +...some entries here... +...some entries here... + +noresetcounter +dailycounter +monthlycounter +} + +noresetcounter: the counter that never resets, can be used +for real session-time cumulation + +dailycounter: the counter that resets everyday, can be used +for limiting daily access time (eg. 3 hours a day) + +monthlycounter: the counter that resets monthly, can be used for +limiting monthly access time (eg. 50 hours per month) + +You can make your own names and directives for resetting the counter +by reading the sample sqlcounter configuration in +raddb/experimental.conf + + + +*) Implementation: + +Add sqlcounter names to be used into radcheck or radgroupcheck +table appropriately for sql. For users file just follow the +example below. + +Note: The users in the example below must be able to login +normally as the example will only show how to apply sqlcounter +counters. + +Scenarios +[1] username test0001 have total time limit of 15 hours +(user can login as many times as needed but can be online for +total time of 15 hours which is 54000 seconds) +If using normal users file authentication the entry can look like: + +test0001 Max-All-Session := 54000, User-Password == "blah" + Service-Type = Framed-User, + Framed-Protocol = PPP + +or for sql make sure to have Max-All-Session entry under either +radcheck or radgroup check table: +> INSERT into radcheck VALUES ('','test0001','Max-All-Session','54000',':='); + +[2] username test0002 have total time limit of 3 hours a day + +test0002 Max-Daily-Session := 10800, User-Password == "blah" + Service-Type = Framed-User, + Framed-Protocol = PPP +or in sql: +> INSERT into radcheck VALUES ('','test0002','Max-Daily-Session','10800',':='); + + +[3] username test0003 have total time limit of 90 hours a month + +test0003 Max-Monthly-Session := 324000, User-Password == "blah" + Service-Type = Framed-User, + Framed-Protocol = PPP +in sql: +> INSERT into radcheck VALUES ('','test0003','Max-Monthly-Session','10800',':='); + + +Note that Max-All-Session, Max-Daily-Session and Max-Monthly-Session are +definied in sqlcounter.conf + +VERY IMPORTANT: +Accounting must be done via sql or this will not work. diff --git a/doc/modules/rlm_sqlippool b/doc/modules/rlm_sqlippool new file mode 100644 index 0000000..3d2840f --- /dev/null +++ b/doc/modules/rlm_sqlippool @@ -0,0 +1,40 @@ +Welcome to the SQL Based IP Pool module. + +********************************************************************** +As of September 2006 this module is still under some development and +currently is only tested by the developers on PostgreSQL (Version 8.1) + Use it at your own risk! +If plan to attempt to use a DB other than PostgreSQL please expect to +have to do extra work which is not for SQL newbies. +Having said that it works great for us in production and should (with +some work) function correctly with other SQL server types. +********************************************************************** + + +To use the sqlipool module you simply need to have an IP-Pool Attribute +(Keep in mind that its a **CHECK** item, not reply) in the required +configuration file, which is either in files(users), sql or any other +type of configuration schema. + +The initialization of the radippool table is left to the user instead of +being handled inside the module. This allows pool management to be done +from any sql capable programming language and pools can be created, +resized, deleted at run time without radiusd needing to be restarted. + +The only required fields are, pool_name and ip_address. A pool consists +of one or more rows in the table with the same pool_name and a different +ip_address. There is no restriction on which ip addresses/ranges may be in +the same pool, and addresses do not need to be concurrent. + +We are currently using the variable definitions of the xlat module, so +before editing the sqlippool.conf file, please go and read the +variables.rst in the doc/configuration directory. It will help you alot!.. + +As you may noticed, there is a pool-key variable in the config file which +allows you to select which attribute is unique according to your NAS setup. +On a standard dialup NAS this is going to be "NAS-Port" but on an ethernet +or wireless network it will probably be "Calling-Station-Id". Other more +exotic options like "3GPP-IMSI" may also exist depending on your NAS. +The only requirement is that the pool-key must be unique and must be +received in both Access-Request and Accounting packages so that we know to +clear the lease on the ip when the session disconnects. diff --git a/doc/schemas/ldap/edir/freeradius-clients.ldif b/doc/schemas/ldap/edir/freeradius-clients.ldif new file mode 100644 index 0000000..96a0f44 --- /dev/null +++ b/doc/schemas/ldap/edir/freeradius-clients.ldif @@ -0,0 +1,69 @@ +# +# LDIF Novell eDirectory schema to load dynamic clients from LDAP +# +# copyright 2013 Olivier Beytrison <olivier@heliosnet.org> +# +# 1.3.6.1.4.1.11344.1.100 is the toplevel OID for this work +# .1 = objectclasses +# .2 = attributs +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.1 + NAME 'radiusClientIdentifier' + DESC 'Client Identifier' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' + SINGLE-VALUE ) +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.2 + NAME 'radiusClientSecret' + DESC 'Client Secret' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' + SINGLE-VALUE ) +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.3 + NAME 'radiusClientShortname' + DESC 'Client Shortname' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' + SINGLE-VALUE ) +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.4 + NAME 'radiusClientVirtualServer' + DESC 'VirtualServer' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' + SINGLE-VALUE ) +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.5 + NAME 'radiusClientType' + DESC 'Client Type' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' + SINGLE-VALUE ) +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.6 + NAME 'radiusClientRequireMa' + DESC 'Require Message Authenticator' + EQUALITY booleanMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' + SINGLE-VALUE ) +attributetypes: ( 1.3.6.1.4.1.11344.1.100.2.7 + NAME 'radiusClientComment' + DESC 'Client comment' + EQUALITY caseIgnoreMatch + SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' + SINGLE-VALUE ) + + +dn: cn=schema +changetype: modify +add: objectclasses +objectclasses: ( 1.3.6.1.4.1.11344.1.100.1.1 + NAME 'radiusClient' + DESC 'radiusClient object class' + SUP top STRUCTURAL + MUST ( radiusClientIdentifier $ radiusClientSecret ) + MAY ( radiusClientShortname $ radiusClientVirtualServer $ radiusClientType $ radiusClientRequireMa $radiusClientcomment )) diff --git a/doc/schemas/ldap/iplanet/freeradius.ldif b/doc/schemas/ldap/iplanet/freeradius.ldif new file mode 100644 index 0000000..3834cb3 --- /dev/null +++ b/doc/schemas/ldap/iplanet/freeradius.ldif @@ -0,0 +1,73 @@ +# This is a LDAPv3 schema for RADIUS attributes. +# Converted for use with iPlanet/Sun Directory Servers 5.x by Arne Brutschy <abrutschy@xylon.de> +# +# Originally Tested on OpenLDAP 2.0.7 +# Posted by Javier Fernandez-Sanguino Pena <jfernandez@sgi.es> +# LDAP v3 version by Jochen Friedrich <jochen@scram.de> +# Updates by Adrian Pavlykevych <pam@polynet.lviv.ua> +############## +dn: cn=schema +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.1 NAME 'radiusArapFeatures' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.2 NAME 'radiusArapSecurity' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.3 NAME 'radiusArapZoneAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.44 NAME 'radiusAuthType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.4 NAME 'radiusCallbackId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.5 NAME 'radiusCallbackNumber' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.6 NAME 'radiusCalledStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.7 NAME 'radiusCallingStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.8 NAME 'radiusClass' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.45 NAME 'radiusClientIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.9 NAME 'radiusFilterId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.10 NAME 'radiusFramedAppleTalkLink' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.11 NAME 'radiusFramedAppleTalkNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.12 NAME 'radiusFramedAppleTalkZone' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.13 NAME 'radiusFramedCompression' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.14 NAME 'radiusFramedIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.15 NAME 'radiusFramedIPNetmask' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.16 NAME 'radiusFramedIPXNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.17 NAME 'radiusFramedMTU' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.18 NAME 'radiusFramedProtocol' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.19 NAME 'radiusFramedRoute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.20 NAME 'radiusFramedRouting' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.46 NAME 'radiusGroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.47 NAME 'radiusHint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.48 NAME 'radiusHuntgroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.21 NAME 'radiusIdleTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.22 NAME 'radiusLoginIPHost' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.23 NAME 'radiusLoginLATGroup' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.24 NAME 'radiusLoginLATNode' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.25 NAME 'radiusLoginLATPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.26 NAME 'radiusLoginLATService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.27 NAME 'radiusLoginService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.28 NAME 'radiusLoginTCPPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.29 NAME 'radiusPasswordRetry' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.30 NAME 'radiusPortLimit' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.49 NAME 'radiusProfileDN' DESC '' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.31 NAME 'radiusPrompt' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.50 NAME 'radiusProxyToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.51 NAME 'radiusReplicateToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.52 NAME 'radiusRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.32 NAME 'radiusServiceType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.33 NAME 'radiusSessionTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.34 NAME 'radiusTerminationAction' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.35 NAME 'radiusTunnelAssignmentId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.36 NAME 'radiusTunnelMediumType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.37 NAME 'radiusTunnelPassword' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.38 NAME 'radiusTunnelPreference' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.39 NAME 'radiusTunnelPrivateGroupId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.40 NAME 'radiusTunnelServerEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.41 NAME 'radiusTunnelType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.42 NAME 'radiusVSA' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.43 NAME 'radiusTunnelClientEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +#need to change asn1.id +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.53 NAME 'radiusSimultaneousUse' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.54 NAME 'radiusLoginTime' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.55 NAME 'radiusUserCategory' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.56 NAME 'radiusStripUserName' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.57 NAME 'dialupAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.58 NAME 'radiusExpiration' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.59 NAME 'radiusAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.60 NAME 'radiusControlAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.61 NAME 'radiusReplyAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.62 NAME 'radiusRequestAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +objectClasses: ( 1.3.6.1.4.1.11344.4.3.2.1 NAME 'radiusprofile' DESC '' SUP top AUXILIARY MUST ( cn ) MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $ radiusFramedProtocol $ radiusAttribute $ radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDn $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ dialupAccess $ radiusControlAttribute $ radiusReplyAttribute $ radiusRequestAttribute ) ) diff --git a/doc/schemas/ldap/iplanet/freeradius.schema b/doc/schemas/ldap/iplanet/freeradius.schema new file mode 100644 index 0000000..6392b02 --- /dev/null +++ b/doc/schemas/ldap/iplanet/freeradius.schema @@ -0,0 +1,78 @@ +# This is a LDAPv3 schema for RADIUS attributes. +# Tested on Sun One Directory server 5.2 +# Created by Daniel Wilson (danielwilson_2k@yahoo.com) +############## +dn: cn=schema +objectClass: top +objectClass: ldapSubentry +objectClass: subschema +cn: schema +####################### +# aci to ensure that the standard schema attributes are visible to +# all LDAP clients (anonymous access). +# +aci: (target="ldap:///cn=schema")(targetattr !="aci")(version 3.0;acl "anonymous, no acis"; allow (read, search, compare) userdn = "ldap:///anyone"; +####################### +objectClasses: ( 1.3.6.1.4.1.11344.4.3.2.1 NAME 'radiusprofile' SUP top AUXILIARY DESC 'Free Radius schema for Directory Server 5.2' MUST (cn) MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $ radiusFramedProtocol $ radiusAttribute $ radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDN $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ dialupAccess $ radiusControlAttribute $ radiusReplyAttribute $radiusRequestAttribute ) X-ORIGIN 'user defined') +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.1 NAME 'radiusArapFeatures' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined') +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.2 NAME 'radiusArapSecurity' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined') +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.3 NAME 'radiusArapZoneAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined') +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.44 NAME 'radiusAuthType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.4 NAME 'radiusCallbackId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.5 NAME 'radiusCallbackNumber' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.6 NAME 'radiusCalledStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.7 NAME 'radiusCallingStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.8 NAME 'radiusClass' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.45 NAME 'radiusClientIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.9 NAME 'radiusFilterId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.10 NAME 'radiusFramedAppleTalkLink' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.11 NAME 'radiusFramedAppleTalkNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.12 NAME 'radiusFramedAppleTalkZone' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.13 NAME 'radiusFramedCompression' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.14 NAME 'radiusFramedIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.15 NAME 'radiusFramedIPNetmask' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.16 NAME 'radiusFramedIPXNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.17 NAME 'radiusFramedMTU' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.18 NAME 'radiusFramedProtocol' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.19 NAME 'radiusFramedRoute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.20 NAME 'radiusFramedRouting' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.46 NAME 'radiusGroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.47 NAME 'radiusHint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.48 NAME 'radiusHuntgroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.21 NAME 'radiusIdleTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.22 NAME 'radiusLoginIPHost' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.23 NAME 'radiusLoginLATGroup' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.24 NAME 'radiusLoginLATNode' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.25 NAME 'radiusLoginLATPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.26 NAME 'radiusLoginLATService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.27 NAME 'radiusLoginService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.28 NAME 'radiusLoginTCPPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.29 NAME 'radiusPasswordRetry' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.30 NAME 'radiusPortLimit' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.49 NAME 'radiusProfileDN' DESC '' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.31 NAME 'radiusPrompt' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.50 NAME 'radiusProxyToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.51 NAME 'radiusReplicateToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.52 NAME 'radiusRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.32 NAME 'radiusServiceType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.33 NAME 'radiusSessionTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.34 NAME 'radiusTerminationAction' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.35 NAME 'radiusTunnelAssignmentId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.36 NAME 'radiusTunnelMediumType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.37 NAME 'radiusTunnelPassword' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.38 NAME 'radiusTunnelPreference' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.39 NAME 'radiusTunnelPrivateGroupId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.40 NAME 'radiusTunnelServerEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.41 NAME 'radiusTunnelType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.42 NAME 'radiusVSA' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.43 NAME 'radiusTunnelClientEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.53 NAME 'radiusSimultaneousUse' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.54 NAME 'radiusLoginTime' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.55 NAME 'radiusUserCategory' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.56 NAME 'radiusStripUserName' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.57 NAME 'dialupAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.58 NAME 'radiusExpiration' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' ) +attributeTypes: ( 1.3.6.1.4.1.11344.4.3.1.59 NAME 'radiusAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributetypes: ( 1.3.6.1.4.1.11344.4.3.1.60 NAME 'radiusControlAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributetypes: ( 1.3.6.1.4.1.11344.4.3.1.61 NAME 'radiusReplyAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributetypes: ( 1.3.6.1.4.1.11344.4.3.1.62 NAME 'radiusRequestAttribute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) diff --git a/doc/schemas/ldap/openldap/freeradius-clients.ldif b/doc/schemas/ldap/openldap/freeradius-clients.ldif new file mode 100644 index 0000000..d591799 --- /dev/null +++ b/doc/schemas/ldap/openldap/freeradius-clients.ldif @@ -0,0 +1,17 @@ +# +# LDIF Openldap schema to load dynamic clients from LDAP +# +# copyright 2013 Olivier Beytrison <olivier@heliosnet.org> +# + +dn: cn=radiusClient,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: radiusClient +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.1 NAME 'radiusClientIdentifier' SINGLE-VALUE DESC 'Client identifier' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.2 NAME 'radiusClientSecret' SINGLE-VALUE DESC 'Client secret' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.3 NAME 'radiusClientShortname' SINGLE-VALUE DESC 'Client shortname' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.4 NAME 'radiusClientVirtualServer' SINGLE-VALUE DESC 'VirtualServer' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.5 NAME 'radiusClientType' SINGLE-VALUE DESC 'Client Type' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.6 NAME 'radiusClientRequireMa' SINGLE-VALUE DESC 'Require Message Authenticator' EQUALITY booleanMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' ) +olcAttributeTypes: ( 1.3.6.1.4.1.11344.1.100.2.7 NAME 'radiusClientComment' SINGLE-VALUE DESC 'Client comment' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) +olcObjectClasses: ( 1.3.6.1.4.1.11344.1.100.1.1 NAME 'radiusClient' DESC 'radiusClient object class' SUP top STRUCTURAL MUST ( radiusClientIdentifier $ radiusClientSecret ) MAY ( radiusClientShortname $ radiusClientVirtualServer $ radiusClientType $ radiusClientRequireMa $ radiusClientComment )) diff --git a/doc/schemas/ldap/openldap/freeradius-clients.schema b/doc/schemas/ldap/openldap/freeradius-clients.schema new file mode 100644 index 0000000..b1fdd66 --- /dev/null +++ b/doc/schemas/ldap/openldap/freeradius-clients.schema @@ -0,0 +1,70 @@ +attributetype ( 1.3.6.1.4.1.11344.1.100.2.1 + NAME 'radiusClientIdentifier' + DESC 'Client Identifier' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.1.100.2.2 + NAME 'radiusClientSecret' + DESC 'Client Secret' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.1.100.2.3 + NAME 'radiusClientShortname' + DESC 'Client Shortname' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.1.100.2.4 + NAME 'radiusClientVirtualServer' + DESC 'VirtualServer' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.1.100.2.5 + NAME 'radiusClientType' + DESC 'Client Type' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.1.100.2.6 + NAME 'radiusClientRequireMa' + DESC 'Require Message Authenticator' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.1.100.2.7 + NAME 'radiusClientComment' + DESC 'Client comment' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +objectclass ( 1.3.6.1.4.1.11344.1.100.1.1 + NAME 'radiusClient' + DESC 'radiusClient object class' + SUP top + STRUCTURAL + MUST ( radiusClientIdentifier $ radiusClientSecret ) + MAY ( radiusClientShortname $ radiusClientVirtualServer $ radiusClientType $ radiusClientRequireMa $ radiusClientComment ) + ) + diff --git a/doc/schemas/ldap/openldap/freeradius.ldif b/doc/schemas/ldap/openldap/freeradius.ldif new file mode 100644 index 0000000..44d2cb9 --- /dev/null +++ b/doc/schemas/ldap/openldap/freeradius.ldif @@ -0,0 +1,76 @@ +dn: cn=radius,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: radius +olcAttributeTypes: {0}( 1.3.6.1.4.1.11344.4.3.1.1 NAME 'radiusArapFeatures' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {1}( 1.3.6.1.4.1.11344.4.3.1.2 NAME 'radiusArapSecurity' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {2}( 1.3.6.1.4.1.11344.4.3.1.3 NAME 'radiusArapZoneAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {3}( 1.3.6.1.4.1.11344.4.3.1.44 NAME 'radiusAuthType' DESC 'controlItem: Auth-Type' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {4}( 1.3.6.1.4.1.11344.4.3.1.4 NAME 'radiusCallbackId' DESC 'replyItem: Callback-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {5}( 1.3.6.1.4.1.11344.4.3.1.5 NAME 'radiusCallbackNumber' DESC 'replyItem: Callback-Number' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {6}( 1.3.6.1.4.1.11344.4.3.1.6 NAME 'radiusCalledStationId' DESC 'controlItem: Called-Station-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {7}( 1.3.6.1.4.1.11344.4.3.1.7 NAME 'radiusCallingStationId' DESC 'controlItem: Calling-Station-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {8}( 1.3.6.1.4.1.11344.4.3.1.8 NAME 'radiusClass' DESC 'replyItem: Class' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {9}( 1.3.6.1.4.1.11344.4.3.1.45 NAME 'radiusClientIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {10}( 1.3.6.1.4.1.11344.4.3.1.9 NAME 'radiusFilterId' DESC 'replyItem: Filter-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {11}( 1.3.6.1.4.1.11344.4.3.1.10 NAME 'radiusFramedAppleTalkLink' DESC 'replyItem: Framed-AppleTalk-Link' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {12}( 1.3.6.1.4.1.11344.4.3.1.11 NAME 'radiusFramedAppleTalkNetwork' DESC 'replyItem: Framed-AppleTalk-Network' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {13}( 1.3.6.1.4.1.11344.4.3.1.12 NAME 'radiusFramedAppleTalkZone' DESC 'replyItem: Framed-AppleTalk-Zone' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {14}( 1.3.6.1.4.1.11344.4.3.1.13 NAME 'radiusFramedCompression' DESC 'replyItem: Framed-Compression' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {15}( 1.3.6.1.4.1.11344.4.3.1.14 NAME 'radiusFramedIPAddress' DESC 'replyItem: Framed-IP-Address' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {16}( 1.3.6.1.4.1.11344.4.3.1.15 NAME 'radiusFramedIPNetmask' DESC 'replyItem: Framed-IP-Netmask' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {17}( 1.3.6.1.4.1.11344.4.3.1.16 NAME 'radiusFramedIPXNetwork' DESC 'replyItem: Framed-IPX-Network' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {18}( 1.3.6.1.4.1.11344.4.3.1.17 NAME 'radiusFramedMTU' DESC' replyItem: Framed-MTU' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {19}( 1.3.6.1.4.1.11344.4.3.1.18 NAME 'radiusFramedProtocol'DESC 'replyItem: Framed-Protocol' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {20}( 1.3.6.1.4.1.11344.4.3.1.19 NAME 'radiusFramedRoute' DESC 'replyItem: Framed-Route' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {21}( 1.3.6.1.4.1.11344.4.3.1.20 NAME 'radiusFramedRouting' DESC 'replyItem: Framed-Routing' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {22}( 1.3.6.1.4.1.11344.4.3.1.46 NAME 'radiusGroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {23}( 1.3.6.1.4.1.11344.4.3.1.47 NAME 'radiusHint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {24}( 1.3.6.1.4.1.11344.4.3.1.48 NAME 'radiusHuntgroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {25}( 1.3.6.1.4.1.11344.4.3.1.21 NAME 'radiusIdleTimeout' DESC 'replyItem: Idle-Timeout' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {26}( 1.3.6.1.4.1.11344.4.3.1.22 NAME 'radiusLoginIPHost' DESC 'replyItem: Login-IP-Host' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {27}( 1.3.6.1.4.1.11344.4.3.1.23 NAME 'radiusLoginLATGroup' DESC 'replyItem: Login-LAT-Group' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {28}( 1.3.6.1.4.1.11344.4.3.1.24 NAME 'radiusLoginLATNode' DESC 'replyItem: Login-LAT-Node' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {29}( 1.3.6.1.4.1.11344.4.3.1.25 NAME 'radiusLoginLATPort' DESC 'replyItem: Login-LAT-Port' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {30}( 1.3.6.1.4.1.11344.4.3.1.26 NAME 'radiusLoginLATService' DESC 'replyItem: Login-LAT-Service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {31}( 1.3.6.1.4.1.11344.4.3.1.27 NAME 'radiusLoginService' DESC 'replyItem: Login-Service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {32}( 1.3.6.1.4.1.11344.4.3.1.28 NAME 'radiusLoginTCPPort' DESC 'replyItem: Login-TCP-Port' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {33}( 1.3.6.1.4.1.11344.4.3.1.29 NAME 'radiusPasswordRetry' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {34}( 1.3.6.1.4.1.11344.4.3.1.30 NAME 'radiusPortLimit' DESC 'replyItem: Port-Limit' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {35}( 1.3.6.1.4.1.11344.4.3.1.49 NAME 'radiusProfileDN' DESC '' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {36}( 1.3.6.1.4.1.11344.4.3.1.31 NAME 'radiusPrompt' DESC ''EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {37}( 1.3.6.1.4.1.11344.4.3.1.50 NAME 'radiusProxyToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {38}( 1.3.6.1.4.1.11344.4.3.1.51 NAME 'radiusReplicateToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {39}( 1.3.6.1.4.1.11344.4.3.1.52 NAME 'radiusRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE) +olcAttributeTypes: {40}( 1.3.6.1.4.1.11344.4.3.1.32 NAME 'radiusServiceType' DESC 'replyItem: Service-Type' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {41}( 1.3.6.1.4.1.11344.4.3.1.33 NAME 'radiusSessionTimeout'DESC 'replyItem: Session-Timeout' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {42}( 1.3.6.1.4.1.11344.4.3.1.34 NAME 'radiusTerminationAction' DESC 'replyItem: Termination-Action' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {43}( 1.3.6.1.4.1.11344.4.3.1.35 NAME 'radiusTunnelAssignmentId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) +olcAttributeTypes: {44}( 1.3.6.1.4.1.11344.4.3.1.36 NAME 'radiusTunnelMediumType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {45}( 1.3.6.1.4.1.11344.4.3.1.37 NAME 'radiusTunnelPassword' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {46}( 1.3.6.1.4.1.11344.4.3.1.38 NAME 'radiusTunnelPreference' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {47}( 1.3.6.1.4.1.11344.4.3.1.39 NAME 'radiusTunnelPrivateGroupId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {48}( 1.3.6.1.4.1.11344.4.3.1.40 NAME 'radiusTunnelServerEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {49}( 1.3.6.1.4.1.11344.4.3.1.41 NAME 'radiusTunnelType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {50}( 1.3.6.1.4.1.11344.4.3.1.42 NAME 'radiusVSA' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {51}( 1.3.6.1.4.1.11344.4.3.1.43 NAME 'radiusTunnelClientEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {52}( 1.3.6.1.4.1.11344.4.3.1.53 NAME 'radiusSimultaneousUse' DESC 'controlItem: Simultaneous-Use' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {53}( 1.3.6.1.4.1.11344.4.3.1.54 NAME 'radiusLoginTime' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {54}( 1.3.6.1.4.1.11344.4.3.1.55 NAME 'radiusUserCategory' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {55}( 1.3.6.1.4.1.11344.4.3.1.56 NAME 'radiusStripUserName' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {56}( 1.3.6.1.4.1.11344.4.3.1.57 NAME 'dialupAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {57}( 1.3.6.1.4.1.11344.4.3.1.58 NAME 'radiusExpiration' DESC 'controlItem: Expiration' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {58}( 1.3.6.1.4.1.11344.4.3.1.59 NAME 'radiusAttribute' DESC 'controlItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {59}( 1.3.6.1.4.1.11344.4.3.1.61 NAME 'radiusNASIpAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {60}( 1.3.6.1.4.1.11344.4.3.1.62 NAME 'radiusReplyMessage' DESC 'replyItem: Reply-Message' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {61}( 1.3.6.1.4.1.11344.4.3.1.63 NAME 'radiusControlAttribute' DESC 'controlItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {62}( 1.3.6.1.4.1.11344.4.3.1.64 NAME 'radiusReplyAttribute' DESC 'replyItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {63}( 1.3.6.1.4.1.11344.4.3.1.65 NAME 'radiusRequestAttribute' DESC 'requestItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcObjectClasses: {0}( 1.3.6.1.4.1.11344.4.3.2.1 NAME 'radiusprofile' DESC '' SUP top AUXILIARY MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ + radiusCallbackId $ radiusCallbackNumber $radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ + radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $radiusFramedProtocol $ radiusAttribute $ + radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ + radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ + radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDN $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ + radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ + dialupAccess $ radiusNASIpAddress $ radiusReplyMessage $ radiusControlAttribute $ radiusReplyAttribute $ radiusRequestAttribute ) ) +olcObjectClasses: {1}( 1.3.6.1.4.1.11344.4.3.2.2 NAME 'radiusObjectProfile' DESC 'A Container Objectclass to be used for creating radius profile object' SUP top STRUCTURAL MUST cn MAY ( uid $ userPassword $ description ) ) diff --git a/doc/schemas/ldap/openldap/freeradius.schema b/doc/schemas/ldap/openldap/freeradius.schema new file mode 100644 index 0000000..ab11984 --- /dev/null +++ b/doc/schemas/ldap/openldap/freeradius.schema @@ -0,0 +1,477 @@ +attributetype ( 1.3.6.1.4.1.11344.4.3.1.1 + NAME 'radiusArapFeatures' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.2 + NAME 'radiusArapSecurity' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.3 + NAME 'radiusArapZoneAccess' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.44 + NAME 'radiusAuthType' + DESC 'controlItem: Auth-Type' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.4 + NAME 'radiusCallbackId' + DESC 'replyItem: Callback-Id' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.5 + NAME 'radiusCallbackNumber' + DESC 'replyItem: Callback-Number' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.6 + NAME 'radiusCalledStationId' + DESC 'controlItem: Called-Station-Id' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.7 + NAME 'radiusCallingStationId' + DESC 'controlItem: Calling-Station-Id' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.8 + NAME 'radiusClass' + DESC 'replyItem: Class' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.45 + NAME 'radiusClientIPAddress' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.9 + NAME 'radiusFilterId' + DESC 'replyItem: Filter-Id' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.10 + NAME 'radiusFramedAppleTalkLink' + DESC 'replyItem: Framed-AppleTalk-Link' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.11 + NAME 'radiusFramedAppleTalkNetwork' + DESC 'replyItem: Framed-AppleTalk-Network' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.12 + NAME 'radiusFramedAppleTalkZone' + DESC 'replyItem: Framed-AppleTalk-Zone' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.13 + NAME 'radiusFramedCompression' + DESC 'replyItem: Framed-Compression' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.14 + NAME 'radiusFramedIPAddress' + DESC 'replyItem: Framed-IP-Address' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.15 + NAME 'radiusFramedIPNetmask' + DESC 'replyItem: Framed-IP-Netmask' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.16 + NAME 'radiusFramedIPXNetwork' + DESC 'replyItem: Framed-IPX-Network' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.17 + NAME 'radiusFramedMTU' + DESC 'replyItem: Framed-MTU' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.18 + NAME 'radiusFramedProtocol' + DESC 'replyItem: Framed-Protocol' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.19 + NAME 'radiusFramedRoute' + DESC 'replyItem: Framed-Route' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.20 + NAME 'radiusFramedRouting' + DESC 'replyItem: Framed-Routing' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.46 + NAME 'radiusGroupName' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.47 + NAME 'radiusHint' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.48 + NAME 'radiusHuntgroupName' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.21 + NAME 'radiusIdleTimeout' + DESC 'replyItem: Idle-Timeout' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.22 + NAME 'radiusLoginIPHost' + DESC 'replyItem: Login-IP-Host' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.23 + NAME 'radiusLoginLATGroup' + DESC 'replyItem: Login-LAT-Group' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.24 + NAME 'radiusLoginLATNode' + DESC 'replyItem: Login-LAT-Node' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.25 + NAME 'radiusLoginLATPort' + DESC 'replyItem: Login-LAT-Port' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.26 + NAME 'radiusLoginLATService' + DESC 'replyItem: Login-LAT-Service' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.27 + NAME 'radiusLoginService' + DESC 'replyItem: Login-Service' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.28 + NAME 'radiusLoginTCPPort' + DESC 'replyItem: Login-TCP-Port' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.29 + NAME 'radiusPasswordRetry' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.30 + NAME 'radiusPortLimit' + DESC 'replyItem: Port-Limit' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.49 + NAME 'radiusProfileDN' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.31 + NAME 'radiusPrompt' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.50 + NAME 'radiusProxyToRealm' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.51 + NAME 'radiusReplicateToRealm' + DESC 'control:Replicate-To-Realm' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.52 + NAME 'radiusRealm' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.32 + NAME 'radiusServiceType' + DESC 'replyItem: Service-Type' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.33 + NAME 'radiusSessionTimeout' + DESC 'replyItem: Session-Timeout' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.34 + NAME 'radiusTerminationAction' + DESC 'replyItem: Termination-Action' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.35 + NAME 'radiusTunnelAssignmentId' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.36 + NAME 'radiusTunnelMediumType' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.37 + NAME 'radiusTunnelPassword' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.38 + NAME 'radiusTunnelPreference' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.39 + NAME 'radiusTunnelPrivateGroupId' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.40 + NAME 'radiusTunnelServerEndpoint' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.41 + NAME 'radiusTunnelType' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.42 + NAME 'radiusVSA' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.43 + NAME 'radiusTunnelClientEndpoint' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.53 + NAME 'radiusSimultaneousUse' + DESC 'controlItem: Simultaneous-Use' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.54 + NAME 'radiusLoginTime' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.55 + NAME 'radiusUserCategory' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.56 + NAME 'radiusStripUserName' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.57 + NAME 'dialupAccess' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.58 + NAME 'radiusExpiration' + DESC 'controlItem: Expiration' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.59 + NAME 'radiusAttribute' + DESC 'controlItem: $GENERIC$' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.61 + NAME 'radiusNASIpAddress' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.62 + NAME 'radiusReplyMessage' + DESC 'replyItem: Reply-Message' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.63 + NAME 'radiusControlAttribute' + DESC 'controlItem: $GENERIC$' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.64 + NAME 'radiusReplyAttribute' + DESC 'replyItem: $GENERIC$' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +attributetype ( 1.3.6.1.4.1.11344.4.3.1.65 + NAME 'radiusRequestAttribute' + DESC 'requestItem: $GENERIC$' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + +objectclass ( 1.3.6.1.4.1.11344.4.3.2.1 + NAME 'radiusprofile' + SUP top + AUXILIARY + MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $ radiusFramedProtocol $ radiusAttribute $ radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDN $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ dialupAccess $ radiusNASIpAddress $ radiusReplyMessage $ radiusControlAttribute $ radiusReplyAttribute $ radiusRequestAttribute ) + ) + +objectclass ( 1.3.6.1.4.1.11344.4.3.2.2 + NAME 'radiusObjectProfile' + DESC 'A Container Objectclass to be used for creating radius profile object' + SUP top + STRUCTURAL + MUST cn + MAY ( uid $ userPassword $ description ) + ) + diff --git a/doc/schemas/ldap/samba/README.txt b/doc/schemas/ldap/samba/README.txt new file mode 100644 index 0000000..6c87461 --- /dev/null +++ b/doc/schemas/ldap/samba/README.txt @@ -0,0 +1,11 @@ +Change "dc=samba4,dc=internal" to your LDAP base DN, +then install with: + +ldbmodify -H /usr/local/samba/private/sam.ldb freeradius-attrs.ldif \ + --option="dsdb:schema update allowed"=true +ldbmodify -H /usr/local/samba/private/sam.ldb freeradius-classes.ldif \ + --option="dsdb:schema update allowed"=true + +These files were created by scripts/ldap/schema_to_samba.py, then +split into two because the attributes must be loaded in a separate +operation to the classes which use them. diff --git a/doc/schemas/ldap/samba/freeradius-attrs.ldif b/doc/schemas/ldap/samba/freeradius-attrs.ldif new file mode 100644 index 0000000..6edc614 --- /dev/null +++ b/doc/schemas/ldap/samba/freeradius-attrs.ldif @@ -0,0 +1,806 @@ +dn: CN=radiusArapFeatures,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.1 +isSingleValued: TRUE +cn: radiusArapFeatures +name: radiusArapFeatures +lDAPDisplayName: radiusArapFeatures +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusArapSecurity,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.2 +isSingleValued: TRUE +cn: radiusArapSecurity +name: radiusArapSecurity +lDAPDisplayName: radiusArapSecurity +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusArapZoneAccess,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.3 +isSingleValued: TRUE +cn: radiusArapZoneAccess +name: radiusArapZoneAccess +lDAPDisplayName: radiusArapZoneAccess +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusAuthType,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.44 +isSingleValued: TRUE +cn: radiusAuthType +name: radiusAuthType +lDAPDisplayName: radiusAuthType +description: controlItem: Auth-Type +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusCallbackId,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.4 +isSingleValued: TRUE +cn: radiusCallbackId +name: radiusCallbackId +lDAPDisplayName: radiusCallbackId +description: replyItem: Callback-Id +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusCallbackNumber,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.5 +isSingleValued: TRUE +cn: radiusCallbackNumber +name: radiusCallbackNumber +lDAPDisplayName: radiusCallbackNumber +description: replyItem: Callback-Number +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusCalledStationId,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.6 +isSingleValued: TRUE +cn: radiusCalledStationId +name: radiusCalledStationId +lDAPDisplayName: radiusCalledStationId +description: controlItem: Called-Station-Id +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusCallingStationId,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.7 +isSingleValued: TRUE +cn: radiusCallingStationId +name: radiusCallingStationId +lDAPDisplayName: radiusCallingStationId +description: controlItem: Calling-Station-Id +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusClass,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.8 +isSingleValued: FALSE +cn: radiusClass +name: radiusClass +lDAPDisplayName: radiusClass +description: replyItem: Class +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusClientIPAddress,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.45 +isSingleValued: TRUE +cn: radiusClientIPAddress +name: radiusClientIPAddress +lDAPDisplayName: radiusClientIPAddress +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFilterId,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.9 +isSingleValued: FALSE +cn: radiusFilterId +name: radiusFilterId +lDAPDisplayName: radiusFilterId +description: replyItem: Filter-Id +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedAppleTalkLink,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.10 +isSingleValued: TRUE +cn: radiusFramedAppleTalkLink +name: radiusFramedAppleTalkLink +lDAPDisplayName: radiusFramedAppleTalkLink +description: replyItem: Framed-AppleTalk-Link +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedAppleTalkNetwork,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.11 +isSingleValued: FALSE +cn: radiusFramedAppleTalkNetwork +name: radiusFramedAppleTalkNetwork +lDAPDisplayName: radiusFramedAppleTalkNetwork +description: replyItem: Framed-AppleTalk-Network +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedAppleTalkZone,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.12 +isSingleValued: TRUE +cn: radiusFramedAppleTalkZone +name: radiusFramedAppleTalkZone +lDAPDisplayName: radiusFramedAppleTalkZone +description: replyItem: Framed-AppleTalk-Zone +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedCompression,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.13 +isSingleValued: FALSE +cn: radiusFramedCompression +name: radiusFramedCompression +lDAPDisplayName: radiusFramedCompression +description: replyItem: Framed-Compression +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedIPAddress,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.14 +isSingleValued: TRUE +cn: radiusFramedIPAddress +name: radiusFramedIPAddress +lDAPDisplayName: radiusFramedIPAddress +description: replyItem: Framed-IP-Address +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedIPNetmask,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.15 +isSingleValued: TRUE +cn: radiusFramedIPNetmask +name: radiusFramedIPNetmask +lDAPDisplayName: radiusFramedIPNetmask +description: replyItem: Framed-IP-Netmask +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedIPXNetwork,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.16 +isSingleValued: TRUE +cn: radiusFramedIPXNetwork +name: radiusFramedIPXNetwork +lDAPDisplayName: radiusFramedIPXNetwork +description: replyItem: Framed-IPX-Network +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedMTU,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.17 +isSingleValued: TRUE +cn: radiusFramedMTU +name: radiusFramedMTU +lDAPDisplayName: radiusFramedMTU +description: replyItem: Framed-MTU +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedProtocol,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.18 +isSingleValued: TRUE +cn: radiusFramedProtocol +name: radiusFramedProtocol +lDAPDisplayName: radiusFramedProtocol +description: replyItem: Framed-Protocol +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedRoute,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.19 +isSingleValued: FALSE +cn: radiusFramedRoute +name: radiusFramedRoute +lDAPDisplayName: radiusFramedRoute +description: replyItem: Framed-Route +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusFramedRouting,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.20 +isSingleValued: TRUE +cn: radiusFramedRouting +name: radiusFramedRouting +lDAPDisplayName: radiusFramedRouting +description: replyItem: Framed-Routing +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusGroupName,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.46 +isSingleValued: FALSE +cn: radiusGroupName +name: radiusGroupName +lDAPDisplayName: radiusGroupName +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusHint,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.47 +isSingleValued: TRUE +cn: radiusHint +name: radiusHint +lDAPDisplayName: radiusHint +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusHuntgroupName,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.48 +isSingleValued: FALSE +cn: radiusHuntgroupName +name: radiusHuntgroupName +lDAPDisplayName: radiusHuntgroupName +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusIdleTimeout,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.21 +isSingleValued: TRUE +cn: radiusIdleTimeout +name: radiusIdleTimeout +lDAPDisplayName: radiusIdleTimeout +description: replyItem: Idle-Timeout +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginIPHost,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.22 +isSingleValued: FALSE +cn: radiusLoginIPHost +name: radiusLoginIPHost +lDAPDisplayName: radiusLoginIPHost +description: replyItem: Login-IP-Host +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginLATGroup,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.23 +isSingleValued: TRUE +cn: radiusLoginLATGroup +name: radiusLoginLATGroup +lDAPDisplayName: radiusLoginLATGroup +description: replyItem: Login-LAT-Group +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginLATNode,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.24 +isSingleValued: TRUE +cn: radiusLoginLATNode +name: radiusLoginLATNode +lDAPDisplayName: radiusLoginLATNode +description: replyItem: Login-LAT-Node +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginLATPort,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.25 +isSingleValued: TRUE +cn: radiusLoginLATPort +name: radiusLoginLATPort +lDAPDisplayName: radiusLoginLATPort +description: replyItem: Login-LAT-Port +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginLATService,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.26 +isSingleValued: TRUE +cn: radiusLoginLATService +name: radiusLoginLATService +lDAPDisplayName: radiusLoginLATService +description: replyItem: Login-LAT-Service +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginService,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.27 +isSingleValued: TRUE +cn: radiusLoginService +name: radiusLoginService +lDAPDisplayName: radiusLoginService +description: replyItem: Login-Service +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusLoginTCPPort,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.28 +isSingleValued: TRUE +cn: radiusLoginTCPPort +name: radiusLoginTCPPort +lDAPDisplayName: radiusLoginTCPPort +description: replyItem: Login-TCP-Port +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusPasswordRetry,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.29 +isSingleValued: TRUE +cn: radiusPasswordRetry +name: radiusPasswordRetry +lDAPDisplayName: radiusPasswordRetry +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusPortLimit,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.30 +isSingleValued: TRUE +cn: radiusPortLimit +name: radiusPortLimit +lDAPDisplayName: radiusPortLimit +description: replyItem: Port-Limit +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusProfileDN,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.49 +isSingleValued: FALSE +cn: radiusProfileDN +name: radiusProfileDN +lDAPDisplayName: radiusProfileDN +attributeSyntax: 2.5.5.1 +oMSyntax: 127 + +dn: CN=radiusPrompt,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.31 +isSingleValued: TRUE +cn: radiusPrompt +name: radiusPrompt +lDAPDisplayName: radiusPrompt +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusProxyToRealm,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.50 +isSingleValued: TRUE +cn: radiusProxyToRealm +name: radiusProxyToRealm +lDAPDisplayName: radiusProxyToRealm +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusReplicateToRealm,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.51 +isSingleValued: TRUE +cn: radiusReplicateToRealm +name: radiusReplicateToRealm +lDAPDisplayName: radiusReplicateToRealm +description: control:Replicate-To-Realm +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusRealm,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.52 +isSingleValued: TRUE +cn: radiusRealm +name: radiusRealm +lDAPDisplayName: radiusRealm +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusServiceType,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.32 +isSingleValued: TRUE +cn: radiusServiceType +name: radiusServiceType +lDAPDisplayName: radiusServiceType +description: replyItem: Service-Type +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusSessionTimeout,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.33 +isSingleValued: TRUE +cn: radiusSessionTimeout +name: radiusSessionTimeout +lDAPDisplayName: radiusSessionTimeout +description: replyItem: Session-Timeout +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTerminationAction,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.34 +isSingleValued: TRUE +cn: radiusTerminationAction +name: radiusTerminationAction +lDAPDisplayName: radiusTerminationAction +description: replyItem: Termination-Action +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelAssignmentId,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.35 +isSingleValued: FALSE +cn: radiusTunnelAssignmentId +name: radiusTunnelAssignmentId +lDAPDisplayName: radiusTunnelAssignmentId +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelMediumType,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.36 +isSingleValued: FALSE +cn: radiusTunnelMediumType +name: radiusTunnelMediumType +lDAPDisplayName: radiusTunnelMediumType +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelPassword,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.37 +isSingleValued: TRUE +cn: radiusTunnelPassword +name: radiusTunnelPassword +lDAPDisplayName: radiusTunnelPassword +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelPreference,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.38 +isSingleValued: FALSE +cn: radiusTunnelPreference +name: radiusTunnelPreference +lDAPDisplayName: radiusTunnelPreference +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelPrivateGroupId,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.39 +isSingleValued: FALSE +cn: radiusTunnelPrivateGroupId +name: radiusTunnelPrivateGroupId +lDAPDisplayName: radiusTunnelPrivateGroupId +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelServerEndpoint,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.40 +isSingleValued: FALSE +cn: radiusTunnelServerEndpoint +name: radiusTunnelServerEndpoint +lDAPDisplayName: radiusTunnelServerEndpoint +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelType,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.41 +isSingleValued: FALSE +cn: radiusTunnelType +name: radiusTunnelType +lDAPDisplayName: radiusTunnelType +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusVSA,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.42 +isSingleValued: FALSE +cn: radiusVSA +name: radiusVSA +lDAPDisplayName: radiusVSA +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusTunnelClientEndpoint,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.43 +isSingleValued: FALSE +cn: radiusTunnelClientEndpoint +name: radiusTunnelClientEndpoint +lDAPDisplayName: radiusTunnelClientEndpoint +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusSimultaneousUse,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.53 +isSingleValued: TRUE +cn: radiusSimultaneousUse +name: radiusSimultaneousUse +lDAPDisplayName: radiusSimultaneousUse +description: controlItem: Simultaneous-Use +attributeSyntax: 2.5.5.9 +oMSyntax: 10 + +dn: CN=radiusLoginTime,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.54 +isSingleValued: TRUE +cn: radiusLoginTime +name: radiusLoginTime +lDAPDisplayName: radiusLoginTime +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusUserCategory,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.55 +isSingleValued: TRUE +cn: radiusUserCategory +name: radiusUserCategory +lDAPDisplayName: radiusUserCategory +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusStripUserName,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.56 +isSingleValued: TRUE +cn: radiusStripUserName +name: radiusStripUserName +lDAPDisplayName: radiusStripUserName +attributeSyntax: 2.5.5.8 +oMSyntax: 1 + +dn: CN=dialupAccess,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.57 +isSingleValued: TRUE +cn: dialupAccess +name: dialupAccess +lDAPDisplayName: dialupAccess +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusExpiration,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.58 +isSingleValued: TRUE +cn: radiusExpiration +name: radiusExpiration +lDAPDisplayName: radiusExpiration +description: controlItem: Expiration +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.59 +isSingleValued: FALSE +cn: radiusAttribute +name: radiusAttribute +lDAPDisplayName: radiusAttribute +description: controlItem: $GENERIC$ +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusNASIpAddress,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.61 +isSingleValued: TRUE +cn: radiusNASIpAddress +name: radiusNASIpAddress +lDAPDisplayName: radiusNASIpAddress +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusReplyMessage,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.62 +isSingleValued: FALSE +cn: radiusReplyMessage +name: radiusReplyMessage +lDAPDisplayName: radiusReplyMessage +description: replyItem: Reply-Message +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusControlAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.63 +isSingleValued: FALSE +cn: radiusControlAttribute +name: radiusControlAttribute +lDAPDisplayName: radiusControlAttribute +description: controlItem: $GENERIC$ +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusReplyAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.64 +isSingleValued: FALSE +cn: radiusReplyAttribute +name: radiusReplyAttribute +lDAPDisplayName: radiusReplyAttribute +description: replyItem: $GENERIC$ +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + +dn: CN=radiusRequestAttribute,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.4.3.1.65 +isSingleValued: FALSE +cn: radiusRequestAttribute +name: radiusRequestAttribute +lDAPDisplayName: radiusRequestAttribute +description: requestItem: $GENERIC$ +attributeSyntax: 2.5.5.5 +oMSyntax: 22 + diff --git a/doc/schemas/ldap/samba/freeradius-classes.ldif b/doc/schemas/ldap/samba/freeradius-classes.ldif new file mode 100644 index 0000000..455069e --- /dev/null +++ b/doc/schemas/ldap/samba/freeradius-classes.ldif @@ -0,0 +1,91 @@ +dn: CN=radiusprofile,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: classSchema +governsID: 1.3.6.1.4.1.11344.4.3.2.1 +cn: radiusprofile +name: radiusprofile +lDAPDisplayName: radiusprofile +subClassOf: top +objectClassCategory: 3 +mayContain: radiusArapFeatures +mayContain: radiusArapSecurity +mayContain: radiusArapZoneAccess +mayContain: radiusAuthType +mayContain: radiusCallbackId +mayContain: radiusCallbackNumber +mayContain: radiusCalledStationId +mayContain: radiusCallingStationId +mayContain: radiusClass +mayContain: radiusClientIPAddress +mayContain: radiusFilterId +mayContain: radiusFramedAppleTalkLink +mayContain: radiusFramedAppleTalkNetwork +mayContain: radiusFramedAppleTalkZone +mayContain: radiusFramedCompression +mayContain: radiusFramedIPAddress +mayContain: radiusFramedIPNetmask +mayContain: radiusFramedIPXNetwork +mayContain: radiusFramedMTU +mayContain: radiusFramedProtocol +mayContain: radiusAttribute +mayContain: radiusFramedRoute +mayContain: radiusFramedRouting +mayContain: radiusIdleTimeout +mayContain: radiusGroupName +mayContain: radiusHint +mayContain: radiusHuntgroupName +mayContain: radiusLoginIPHost +mayContain: radiusLoginLATGroup +mayContain: radiusLoginLATNode +mayContain: radiusLoginLATPort +mayContain: radiusLoginLATService +mayContain: radiusLoginService +mayContain: radiusLoginTCPPort +mayContain: radiusLoginTime +mayContain: radiusPasswordRetry +mayContain: radiusPortLimit +mayContain: radiusPrompt +mayContain: radiusProxyToRealm +mayContain: radiusRealm +mayContain: radiusReplicateToRealm +mayContain: radiusServiceType +mayContain: radiusSessionTimeout +mayContain: radiusStripUserName +mayContain: radiusTerminationAction +mayContain: radiusTunnelClientEndpoint +mayContain: radiusProfileDN +mayContain: radiusSimultaneousUse +mayContain: radiusTunnelAssignmentId +mayContain: radiusTunnelMediumType +mayContain: radiusTunnelPassword +mayContain: radiusTunnelPreference +mayContain: radiusTunnelPrivateGroupId +mayContain: radiusTunnelServerEndpoint +mayContain: radiusTunnelType +mayContain: radiusUserCategory +mayContain: radiusVSA +mayContain: radiusExpiration +mayContain: dialupAccess +mayContain: radiusNASIpAddress +mayContain: radiusReplyMessage +mayContain: radiusControlAttribute +mayContain: radiusReplyAttribute +mayContain: radiusRequestAttribute + +dn: CN=radiusObjectProfile,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: classSchema +governsID: 1.3.6.1.4.1.11344.4.3.2.2 +cn: radiusObjectProfile +name: radiusObjectProfile +lDAPDisplayName: radiusObjectProfile +description: A Container Objectclass to be used for creating radius profile object +subClassOf: top +objectClassCategory: 1 +mustContain: cn +mayContain: uid +mayContain: userPassword +mayContain: description + diff --git a/doc/schemas/ldap/samba/freeradius-clients-attrs.ldif b/doc/schemas/ldap/samba/freeradius-clients-attrs.ldif new file mode 100644 index 0000000..c523da4 --- /dev/null +++ b/doc/schemas/ldap/samba/freeradius-clients-attrs.ldif @@ -0,0 +1,91 @@ +dn: CN=radiusClientIdentifier,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.1 +isSingleValued: TRUE +cn: radiusClientIdentifier +name: radiusClientIdentifier +lDAPDisplayName: radiusClientIdentifier +description: Client Identifier +attributeSyntax: 2.5.5.3 +oMSyntax: 27 + +dn: CN=radiusClientSecret,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.2 +isSingleValued: TRUE +cn: radiusClientSecret +name: radiusClientSecret +lDAPDisplayName: radiusClientSecret +description: Client Secret +attributeSyntax: 2.5.5.3 +oMSyntax: 27 + +dn: CN=radiusClientShortname,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.3 +isSingleValued: TRUE +cn: radiusClientShortname +name: radiusClientShortname +lDAPDisplayName: radiusClientShortname +description: Client Shortname +attributeSyntax: 2.5.5.3 +oMSyntax: 27 + +dn: CN=radiusClientVirtualServer,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.4 +isSingleValued: TRUE +cn: radiusClientVirtualServer +name: radiusClientVirtualServer +lDAPDisplayName: radiusClientVirtualServer +description: VirtualServer +attributeSyntax: 2.5.5.3 +oMSyntax: 27 + +dn: CN=radiusClientType,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.5 +isSingleValued: TRUE +cn: radiusClientType +name: radiusClientType +lDAPDisplayName: radiusClientType +description: Client Type +attributeSyntax: 2.5.5.3 +oMSyntax: 27 + +dn: CN=radiusClientRequireMa,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.6 +isSingleValued: TRUE +cn: radiusClientRequireMa +name: radiusClientRequireMa +lDAPDisplayName: radiusClientRequireMa +description: Require Message Authenticator +attributeSyntax: 2.5.5.8 +oMSyntax: 1 + +dn: CN=radiusClientComment,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11344.1.100.2.7 +isSingleValued: TRUE +cn: radiusClientComment +name: radiusClientComment +lDAPDisplayName: radiusClientComment +description: Client comment +attributeSyntax: 2.5.5.3 +oMSyntax: 27 + diff --git a/doc/schemas/ldap/samba/freeradius-clients-classes.ldif b/doc/schemas/ldap/samba/freeradius-clients-classes.ldif new file mode 100644 index 0000000..24eade2 --- /dev/null +++ b/doc/schemas/ldap/samba/freeradius-clients-classes.ldif @@ -0,0 +1,19 @@ +dn: CN=radiusClient,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: add +objectClass: top +objectClass: classSchema +governsID: 1.3.6.1.4.1.11344.1.100.1.1 +cn: radiusClient +name: radiusClient +lDAPDisplayName: radiusClient +description: radiusClient object class +subClassOf: top +objectClassCategory: 1 +mustContain: radiusClientIdentifier +mustContain: radiusClientSecret +mayContain: radiusClientShortname +mayContain: radiusClientVirtualServer +mayContain: radiusClientType +mayContain: radiusClientRequireMa +mayContain: radiusClientComment + diff --git a/doc/schemas/ldap/samba/freeradius-user.ldif b/doc/schemas/ldap/samba/freeradius-user.ldif new file mode 100644 index 0000000..d252a7c --- /dev/null +++ b/doc/schemas/ldap/samba/freeradius-user.ldif @@ -0,0 +1,10 @@ +# Use this if you want to be able to apply radiusprofile +# Auxiliary class directly to Users in the directory. +# Install with: +# ldbmodify -H /usr/local/samba/private/sam.ldb \ +# user.ldif \ +# --option="dsdb:schema update allowed"=true +dn: CN=User,CN=Schema,CN=Configuration,dc=samba4,dc=internal +changetype: modify +add: auxiliaryClass +auxiliaryClass: radiusprofile diff --git a/doc/schemas/logstash/README b/doc/schemas/logstash/README new file mode 100644 index 0000000..2f36eb6 --- /dev/null +++ b/doc/schemas/logstash/README @@ -0,0 +1,95 @@ +Example configuration for logstash/elasticsearch +================================================ + +So you've got all these RADIUS logs, but how do you analyse them? What is the +easiest way to query the logs, find out when a client connected or disconnected, +or view the top ten clients logging into the system over the last six hours? + +The elastic stack is designed and built to do just that. elasticsearch is a +search engine; logstash is commonly used to feed data in, and kibana the web +interface to query the logs in near real time. + +Installing the elastic stack is beyond the scope of this document, but can be done +in a short amount of time by any competent sysadmin. Then comes getting the +logs in. + +This directory contains the following files as a starting point for feeding +RADIUS logs into elasticsearch via logstash, then sample dashboards for Kibana +to explore the data. + +Files +----- + +Please note that all files should be reviewed before use to determine if they +are suitable for your configuration/system, especially if you are integrating +this into an existing logstash/elasticsearch setup. + +radius-mapping.sh + + Each elasticsearch index needs a mapping to describe how fields are stored. + If one is not provided then all is not lost as elasticsearch will build one + on the fly. However, this may not be optimal, especially for RADIUS data, as + all fields will be analyzed making some visualisations hard or impossible + (such as showing top N clients). + + This shell script (which just runs curl) pushes a template mapping into the + elasticsearch cluster. + +logstash-radius.conf + + A sample configuration file for logstash that parses RADIUS 'detail' files. + It processes these by joining each record onto one line, then splitting the + tab-delimited key-value pairs out. Some additional data is then extracted + from certain key attributes. + + The logstash config will need to be edited at least to set the input method: + for experimentation the given input (file) may be used. If logstash is running + on the RADIUS server itself then this example input may be appropriate, + otherwise a different input such as log-courier or filebeat may be better to + get the data over the network to logstash. + + It would be best to use an input method that can join the multiple lines of + the detail file together and feed them to logstash as a single entry, rather + than using the logstash multiline codec. + +log-courier.conf + + An example configuration for the log-courier feeder. + +kibana4-dashboard.json + + Basic RADIUS dashboard (for Kibana 4 to Kibana 6). + + To import the dashboard first create a new index called "radius-*" in + Settings/Indices. Then go to Kibana's Settings page, "Objects" and "Import". + Once imported open the "RADIUS detail" dashboard. + + +Example usage +------------- + +Install mapping (only needs to be done once): + + $ ./radius-mapping.sh + +Edit logstash-radius.conf to point to the correct file, then feed a detail file +in: + + # /usr/share/logstash/bin/logstash --path.settings=/etc/logstash -f logstash-radius.conf + +To view debug output, append `--log.level=debug`. + + +See also +-------- + +elasticsearch web site: http://www.elastic.co/ + +The configuration examples presented here have been tested with the +following software versions: + + elasticsearch 6.7.0 + logstash 6.7.0 + kibana 6.7.0 + kibana 5.1.2 + kibana 4.1.11 diff --git a/doc/schemas/logstash/kibana4-dashboard.json b/doc/schemas/logstash/kibana4-dashboard.json new file mode 100644 index 0000000..6c379df --- /dev/null +++ b/doc/schemas/logstash/kibana4-dashboard.json @@ -0,0 +1,123 @@ +[ + { + "_id": "RADIUS-data", + "_type": "search", + "_source": { + "title": "RADIUS data", + "description": "", + "hits": 0, + "columns": [ + "User-Name", + "Calling-Station-Id", + "Called-Station-Id", + "Framed-IP-Address", + "NAS-Identifier" + ], + "sort": [ + "@timestamp", + "desc" + ], + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"radius-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"fragment_size\":2147483647},\"filter\":[]}" + } + } + }, + { + "_id": "RADIUS-detail", + "_type": "dashboard", + "_source": { + "title": "RADIUS detail", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":5,\"id\":\"RADIUS-unique-User-Name-by-day\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"User-Name\",\"Calling-Station-Id\",\"Called-Station-Id\",\"Framed-IP-Address\",\"NAS-Identifier\"],\"id\":\"RADIUS-data\",\"row\":5,\"size_x\":8,\"size_y\":4,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"id\":\"RADIUS-accounting-packets-histogram\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"RADIUS-table-topN-data-transferred-by-User-Name\",\"row\":1,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"id\":\"RADIUS-Sessions-per-NAS\",\"type\":\"visualization\",\"size_x\":4,\"size_y\":4,\"col\":9,\"row\":5}]", + "version": 1, + "timeRestore": true, + "timeTo": "now", + "timeFrom": "now-7d", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" + } + } + }, + { + "_id": "RADIUS-Accounting-Start-data", + "_type": "search", + "_source": { + "title": "RADIUS Accounting-Start data", + "description": "", + "hits": 0, + "columns": [ + "User-Name", + "Calling-Station-Id", + "Called-Station-Id", + "Framed-IP-Address", + "NAS-Identifier" + ], + "sort": [ + "@timestamp", + "desc" + ], + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"radius-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"fragment_size\":2147483647},\"filter\":[{\"meta\":{\"negate\":false,\"index\":\"radius-*\",\"key\":\"Acct-Status-Type\",\"value\":\"Start\",\"disabled\":false},\"query\":{\"match\":{\"Acct-Status-Type\":{\"query\":\"Start\",\"type\":\"phrase\"}}}}]}" + } + } + }, + { + "_id": "RADIUS-unique-User-Name-by-day", + "_type": "visualization", + "_source": { + "title": "RADIUS unique User-Name by day", + "visState": "{\n \"type\": \"histogram\",\n \"params\": {\n \"shareYAxis\": true,\n \"addTooltip\": true,\n \"addLegend\": true,\n \"scale\": \"linear\",\n \"mode\": \"stacked\",\n \"times\": [],\n \"addTimeMarker\": false,\n \"defaultYExtents\": false,\n \"setYExtents\": false,\n \"yAxis\": {}\n },\n \"aggs\": [\n {\n \"id\": \"1\",\n \"type\": \"cardinality\",\n \"schema\": \"metric\",\n \"params\": {\n \"field\": \"User-Name\"\n }\n },\n {\n \"id\": \"2\",\n \"type\": \"date_histogram\",\n \"schema\": \"segment\",\n \"params\": {\n \"field\": \"@timestamp\",\n \"interval\": \"d\",\n \"customInterval\": \"2h\",\n \"min_doc_count\": 1,\n \"extended_bounds\": {}\n }\n },\n {\n \"id\": \"3\",\n \"type\": \"terms\",\n \"schema\": \"group\",\n \"params\": {\n \"field\": \"User-Name\",\n \"size\": 50,\n \"order\": \"desc\",\n \"orderBy\": \"1\"\n }\n }\n ],\n \"listeners\": {}\n}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\n \"filter\": []\n}" + }, + "savedSearchId": "RADIUS-data" + } + }, + { + "_id": "RADIUS-accounting-packets-histogram", + "_type": "visualization", + "_source": { + "title": "RADIUS accounting packets histogram", + "visState": "{\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"Acct-Status-Type\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", + "description": "", + "savedSearchId": "RADIUS-data", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + } + } + }, + { + "_id": "RADIUS-table-topN-data-transferred-by-User-Name", + "_type": "visualization", + "_source": { + "title": "RADIUS table topN data transferred by User-Name", + "visState": "{\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"Acct-Output-Octets_long\"}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"User-Name\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"Acct-Input-Octets_long\"}}],\"listeners\":{}}", + "description": "", + "savedSearchId": "RADIUS-data", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + } + } + }, + { + "_id": "RADIUS-Sessions-per-NAS", + "_type": "visualization", + "_source": { + "title": "RADIUS Sessions per NAS", + "visState": "{\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"NAS-Identifier\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", + "description": "", + "savedSearchId": "RADIUS-Accounting-Start-data", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[]}" + } + } + } +] diff --git a/doc/schemas/logstash/log-courier.conf b/doc/schemas/logstash/log-courier.conf new file mode 100644 index 0000000..20d106f --- /dev/null +++ b/doc/schemas/logstash/log-courier.conf @@ -0,0 +1,56 @@ +# Example log-courier configuration file for RADIUS detail files. +# +# This has been tested with log-courier version 2.0.4 +# +{ + "general": { + "persist directory": "/var/lib/log-courier", + "log syslog": true, + "log stdout": false + }, + + "network": { + "transport": "tcp", + + # Servers to connect to. + # + "servers": [ + "logstash1.example:5140", + "logstash2.example:5140" + ] + }, + + "files": [ + { + # Match RADIUS detail files, but not anything that has + # been gzipped. + # + "paths": [ "/var/log/radius/radacct/*/detail-????????" ], + + # Add a type:"radiusdetail" field to the data so that + # logstash can tell what type of data this is (in case + # log-courier is being used for other data as well). + # + "fields": { + "type": "radiusdetail" + }, + + # Stop watching a file if nothing has been written in 12h. + # + "dead time": "12h", + + # Process multilines. If this is being used then the + # "multiline" section should be commented out from the + # logstash configuration. Logstash can then also be run + # with multiple workers (using -w). + # + "codecs": [ + { + "name": "multiline", + "patterns": [ "^[A-Z\t]" ], + "what": "next" + } + ] + } + ] +} diff --git a/doc/schemas/logstash/logstash-radius.conf b/doc/schemas/logstash/logstash-radius.conf new file mode 100644 index 0000000..f473179 --- /dev/null +++ b/doc/schemas/logstash/logstash-radius.conf @@ -0,0 +1,256 @@ +# logstash configuration to process RADIUS detail files +# +# Matthew Newton +# April 2019 +# +# This config has been tested with logstash version 6.7.0 +# +# RADIUS "detail" files are textual representations of the RADIUS +# packets, and are written to disk by e.g. FreeRADIUS. They look +# something like the following, with the timestamp on the first +# line then all attributes/values tab-indented. +# +# Tue Mar 10 15:32:24 2015 +# Packet-Type = Access-Request +# User-Name = "test@example.com" +# Calling-Station-Id = "01-02-03-04-05-06" +# Called-Station-Id = "aa-bb-cc-dd-ee-ff:myssid" +# NAS-Port = 10 +# NAS-IP-Address = 10.9.0.4 +# NAS-Identifier = "Wireless-Controller-1" +# Service-Type = Framed-User +# NAS-Port-Type = Wireless-802.11 +# + + + +# Example input - read data from a file. For example, to read in a +# detail file with this input you could use: +# +# # /usr/share/logstash/bin/logstash --path.settings=/etc/logstash -f logstash-radius.conf --log.level=debug +# + +input { + file { + path => "/var/log/radius/radacct/*/detail-*" + exclude => "*.gz" + + # Note when testing that logstash will remember where + # it got to and continue from there. + start_position => "beginning" + + # Set the type, for below. + type => radiusdetail + + # It is preferable to use a log feeder that can join + # multiple lines together, rather than using multiline + # here. For an example, see the log-courier + # configuration in this directory. + + # If you didn't read the above, go back and read it again. + + # If that is not possible you may be able to use the + # following section. Note that if you are using the + # "stdin" input, the file is chunked into 16k blobs, + # so every 16k a detail record is likely to be chopped + # in half. If you are using the "file" input (as in this + # example), the blank links between records are not + # passed through so the regex here has to be aware of + # that. Basically, do multiline as early as possible + # in your log feeder client not here and you'll avoid + # most issues that are likely to come up. + + codec => multiline { + pattern => "^\t" + negate => false + what => "previous" + } + + # If you really want to use the "stdin" input, this + # will work better, but be aware of the comments + # above. + + #codec => multiline { + # pattern => "^[A-Z\t]" + # negate => false + # what => "next" + #} + } +} + +# Moving into production will likely need something more reliable. +# There are many input methods, an example here using log-courier +# (which supports client-site multiline processing and does not +# lose log events if logstash is restarted). You could also +# investigate e.g. filebeat from Elastic. + +# input { +# courier { +# port => 5140 +# transport => "tcp" +# +# # Don't set the type here, as it's set in the +# # log-courier config instead. +# #type => radiusdetail +# } +# } + + + +# Filter stage. Here we take the raw logs and process them into +# something structured ready to index. Each attribute is stored as +# a separate field in the output document. + +filter { + + if [type] == "radiusdetail" { + + # Pull off the timestamp at the start of the + # detail record. Note there may be additional data + # after it that has been added by the local admin, + # so stop at a newline OR a tab. + + grok { + match => [ "message", "^(?<timestamp>[^\n\t]+)[\n\t]" ] + } + + # Create the @timestamp field. + + date { + match => [ "timestamp", "EEE MMM dd HH:mm:ss yyyy", + "EEE MMM d HH:mm:ss yyyy" ] + } + + # Split the attributes and values into fields. + # This is the bulk of processing that adds all of + # the RADIUS attributes as elasticsearch fields. + + # Note issue https://github.com/logstash-plugins/logstash-filter-kv/issues/10 + # currently means that all spaces will be stripped + # from all fields. If this is a problem, adjust the + # trim setting. + + kv { + field_split => "\n" + source => "message" + trim_value => "\" " + trim_key => "\t " + } + + # Now we try and add some useful additional + # information. If certain fields can be broken + # down into components then do that here and add + # the data as sub-fields. For example, + # Called-Station-Id might be able to be broken + # down to Called-Station-Id_mac and Called-Station-Id_ssid + # on some wireless systems, or to _ip and _port + # with a VPN. + + # Multiple calls to grok otherwise it can stop + # processing once it has matched one field, but + # e.g. you want to pull both IP and port out of + # the same field in two different regex's. + + # Pull out some IP addresses as field_ip: + + grok { + break_on_match => false + tag_on_failure => [] + match => [ + "Framed-IP-Address", "^(?<Framed-IP-Address_ip>\d+\.\d+\.\d+\.\d+$)", + "NAS-IP-Address", "^(?<NAS-IP-Address_ip>\d+\.\d+\.\d+\.\d+$)", + "Calling-Station-Id", "^(?<Calling-Station-Id_ip>\d+\.\d+\.\d+\.\d+)", + "Called-Station-Id", "^(?<Called-Station-Id_ip>\d+\.\d+\.\d+\.\d+)" + ] + } + + # Split User-Name, Operator-Name, and pull out + # some IP ports if they are there: + + grok { + break_on_match => false + tag_on_failure => [] + match => [ + "User-Name", "^(?<User-Name_username>[^@]+)?(?:@(?<User-Name_realm>[^@]+))$", + "Operator-Name", "^(?<Operator-Name_id>.)(?<Operator-Name_value>.+)$", + + "Calling-Station-Id", "\[(?<Calling-Station-Id_port>\d+)\]$", + "Called-Station-Id", "\[(?<Called-Station-Id_port>\d+)\]$" + ] + } + + # Extract MAC addresses (and SSIDs if there). + # MAC address matching here is lazy, but should be + # good enough. + + grok { + break_on_match => false + tag_on_failure => [] + match => [ + "Calling-Station-Id", "^(?<Calling-Station-Id_mac>[a-fA-F0-9:-]{17})$", + "Calling-Station-Id", "^(?<Calling-Station-Id_mac>[a-fA-F0-9\.]{14})$", + "Calling-Station-Id", "^(?<Calling-Station-Id_mac>[a-fA-F0-9]{12})$", + + "Called-Station-Id", "^(?<Called-Station-Id_mac>[a-fA-F0-9:-]{17})(?::(?<Called-Station-Id_ssid>.*))?$", + "Called-Station-Id", "^(?<Called-Station-Id_mac>[a-fA-F0-9\.]{14})(?::(?<Called-Station-Id_ssid>.*))?$", + "Called-Station-Id", "^(?<Called-Station-Id_mac>[a-fA-F0-9]{12})(?::(?<Called-Station-Id_ssid>.*))?$" + ] + } + + # With the optional sanitize_mac plugin, it's + # possible to make sure all MAC addresses look the + # same, which has obvious benefits. + # + # https://github.com/mcnewton/logstash-filter-sanitize_mac + + # sanitize_mac { + # match => { + # "Called-Station-Id_mac" => "Called-Station-Id_mac" + # "Calling-Station-Id_mac" => "Calling-Station-Id_mac" + # } + # separator => "-" + # fixcase => "lower" + # } + + + # Gigawords presents an issue because the 64-bit + # value is split across two attributes. Combine + # them both back into a single attribute so that + # the full value is available to use. + + if ([Acct-Input-Octets]) { + ruby { + code => "event.set('Acct-Input-Octets_long', event.get('Acct-Input-Octets').to_i + + (event.get('Acct-Input-Gigawords') ? (event.get('Acct-Input-Gigawords').to_i * (2**32)) : 0))" + } + } + + if ([Acct-Output-Octets]) { + ruby { + code => "event.set('Acct-Output-Octets_long', event.get('Acct-Output-Octets').to_i + + (event.get('Acct-Output-Gigawords') ? (event.get('Acct-Output-Gigawords').to_i * (2**32)) : 0))" + } + } + + + # Remove the original "message" field. + + mutate { + remove_field => ["message"] + } + + } +} + + + +# Output data to the local elasticsearch cluster +# using type "detail" in index "radius-DATE". + +output { + if [type] == "radiusdetail" { + elasticsearch { + index => "radius-%{+YYYY.MM.dd}" + } + } +} diff --git a/doc/schemas/logstash/radius-mapping.sh b/doc/schemas/logstash/radius-mapping.sh new file mode 100755 index 0000000..0ee9a3f --- /dev/null +++ b/doc/schemas/logstash/radius-mapping.sh @@ -0,0 +1,100 @@ +#! /bin/sh + +# Create an elasticsearch template mapping for RADIUS data +# Matthew Newton +# April 2019 + +# This should be run on an elasticsearch node. Alternatively, +# adjust the curl URI below. + +# This version has been tested on elasticsearch 6.7.0 + +# The template will be called "radius", and will apply to all +# indices prefixed with "radius-". +# +# As not all RADIUS attributes are known to begin with it has the +# following starting point that can be modified to suit the local +# configuration: +# +# Acct-Input- or Acct-Output- attributes are numbers; +# Acct-Session-Time is a number; +# Everything else is a keyword, which is a non-analysed string. + +# Additionally, the supplied logstash config will try and extract +# MAC addresses, IP addresses and ports from the data. These are +# stored with suffixes on the respective attribute. For example, +# an attribute +# +# Called-Station-Id := "10.0.4.6[4500]" +# +# will be broken down into the following fields in elasticsearch: +# +# Called-Station-Id = "10.0.4.6[4500]" +# Called-Station-Id_ip = "10.0.4.6" +# Called-Station-Id_port = "4500" +# +# This mapping ensures that these have an appropriate data type. + + +curl -s -XPUT -H 'Content-Type: application/json' '127.0.0.1:9200/_template/radius' -d ' +{ + "template":"radius-*", + "order":0, + "mappings":{ + "doc":{ + + "properties": { + "@timestamp": { "format" : "date_optional_time", "type" : "date" }, + "@version": { "type" : "keyword" }, + "message": { "type" : "text" }, + "Acct-Session-Time": { "type" : "long" }, + "offset": { "type" : "long" } + }, + + "dynamic_templates": [ + + { "acct_io_numbers": { + "match_pattern": "regex", + "match": "^Acct-(Input|Output)-.*$", + "mapping": { + "type": "long" + } + } + }, + + { "ipv4_address": { + "path_match": "*_ip", + "mapping": { + "type": "ip" + } + } + }, + + { "network_port": { + "path_match": "*_port", + "mapping": { + "type": "integer" + } + } + }, + + { "long_number": { + "path_match": "*_long", + "mapping": { + "type": "long" + } + } + }, + + { "no_analyze_strings": { + "match": "*", + "mapping": { + "type": "keyword" + } + } + } + + ] + } + } +}' diff --git a/doc/schemas/sql b/doc/schemas/sql new file mode 100644 index 0000000..b3ba35f --- /dev/null +++ b/doc/schemas/sql @@ -0,0 +1,8 @@ +SQL Schemas +=========== + +SQL Schemas are included in raddb/<sql_module>/<sql_dialect>/schema.sql. + +It seemed like too much of a pain to split them out and put them here, +especially in the case of SQLite where they're sometimes used for +bootstrap. diff --git a/doc/source/.gitignore b/doc/source/.gitignore new file mode 100644 index 0000000..8683fe4 --- /dev/null +++ b/doc/source/.gitignore @@ -0,0 +1,4 @@ +html +latex +man +*.tmp diff --git a/doc/source/Doxyfile b/doc/source/Doxyfile new file mode 100644 index 0000000..0d3c301 --- /dev/null +++ b/doc/source/Doxyfile @@ -0,0 +1,2313 @@ +# Doxyfile 1.8.9 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = FreeRADIUS + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = $Id$ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = ./extra/freeradius.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = YES + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 2 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../../src \ + extra + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.h + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 1 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. There +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Searching" for details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when enabling USE_PDFLATEX this option is only used for generating +# bitmaps for formulas in the HTML output, but not in the Makefile that is +# written to the output directory. +# The default file is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. To get the times font for +# instance you can specify +# EXTRA_PACKAGES=times +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. +# +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. +# +# Note: Only use a user-defined footer if you know what you are doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES, to get a +# higher quality PDF documentation. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's config +# file, i.e. a series of assignments. You only have to provide replacements, +# missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's config file. A template extensions file can be generated +# using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sf.net) file that captures the +# structure of the code including all documentation. Note that this feature is +# still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO, the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES, the include files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = ./../../src/include + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = *.h + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = WITH_PROXY \ + WITH_UNLANG \ + WITH_ACCOUNTING \ + WITH_DETAIL \ + WITH_SESSION_MGMT \ + WITH_DYNAMIC_CLIENTS \ + WITH_STATS \ + WITH_COMMAND_SOCKET \ + WITH_COA \ + WITH_COA_TUNNEL \ + WITH_TCP \ + WITH_DHCP \ + WITH_VMPS \ + WITH_THREADS \ + HAVE_JSON + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have a unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of 'which perl'). +# The default file (with absolute path) is: /usr/bin/perl. + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see: +# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + +# If set to YES the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: NO. + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font in the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = YES + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, gif and svg. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = svg + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = YES + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 150 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 4 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# files that are used to generate the various graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_CLEANUP = YES diff --git a/doc/source/extra/client.c b/doc/source/extra/client.c new file mode 100644 index 0000000..b7775c4 --- /dev/null +++ b/doc/source/extra/client.c @@ -0,0 +1,12 @@ +/** + * @cond skip + * vim:syntax=doxygen + * @endcond + * + * +@page client_doc + +@section client_intro Introduction + +*/ +~ diff --git a/doc/source/extra/core.c b/doc/source/extra/core.c new file mode 100644 index 0000000..c3af04c --- /dev/null +++ b/doc/source/extra/core.c @@ -0,0 +1,31 @@ +/** + * @cond skip + * vim:syntax=doxygen + * @endcond + * + * +@page server_doc + +@section server_intro Introduction + +FreeRADIUS uses a thread pool to serve requests. Each request is processed +synchronously, and processing passes through a series of stages, and a list +of modules in each stage. + +The request is processed as follows + +- The radius packet is received by a listener - see listen.c +- The radius packet is parsed and validated into a request - see ? +- The request is processed - see process.c +- The server passes through each authentication stage + - authorize + - if Proxy-To-Realm is set: + - pre-proxy + - send proxy request + - post-proxy + - else + - authenticate + - post-auth +- Authentication stages are lists of modules - see modcall.c + +*/ diff --git a/doc/source/extra/freeradius.png b/doc/source/extra/freeradius.png Binary files differnew file mode 100644 index 0000000..45e96a4 --- /dev/null +++ b/doc/source/extra/freeradius.png diff --git a/doc/source/extra/module.c b/doc/source/extra/module.c new file mode 100644 index 0000000..74071bd --- /dev/null +++ b/doc/source/extra/module.c @@ -0,0 +1,17 @@ +/** + * @cond skip + * vim:syntax=doxygen + * @endcond + * + * +@page module_doc + +@section module_intro Introduction + +FreeRADIUS uses a pluggable module infrastructure to extend the +basic functionality of the server. + +Modules in 3.0 are dynamically linked at runtime using dlopen. + +@defgroup module_safe module_safe - Internal API functions that are safe for use by modules +*/ diff --git a/doc/source/extra/toc.c b/doc/source/extra/toc.c new file mode 100644 index 0000000..3a96fa7 --- /dev/null +++ b/doc/source/extra/toc.c @@ -0,0 +1,102 @@ +/** + * @cond skip + * vim:syntax=doxygen + * @endcond + * + * +@mainpage + +@section main_intro Introduction + +FreeRADIUS is a high-performance modular RADIUS server, supporting PAP, CHAP, +EAP (including EAP-TLS, EAP-TTLS, EAP-PEAP with EAP-MSCHAP) and a very flexible +configuration model, including conditional request processing, querying of +LDAP and SQL databases, exection of external scripts and more. + +FreeRADIUS uses a thread pool to serve requests. Each request is processed +synchronously, and processing passes through a series of stages, and a list +of modules in each stage. + +@section main_toc Table of Contents + +- @subpage server_doc "1. Core server APIs" +- @subpage module_doc "2. Server modules" +- @subpage client_doc "3. Client APIs" + +@section main_branches GIT Branch + +@subsection branch_master Master (v4) feature branch + +@code +git clone git@github.com:FreeRADIUS/freeradius-server.git +@endcode +- Web: http://github.com/FreeRADIUS/freeradius-server/tree/master + +@subsection branch_32x 3.2.x stable branch + +Minor bug fixes, documentation updatews, etc. go into this branch. + +@code +git clone git@github.com:FreeRADIUS/freeradius-server.git +cd freeradius-server +git fetch origin v3.2.x:v3.2.x +git checkout v3.2.x +@endcode +- Web: http://github.com/FreeRADIUS/freeradius-server/tree/v3.2.x + +@subsection branch_2xx 2.x.x EOL branch + +@note This branch is now permanently feature frozen. New features or modules + should be submitted against the master branch. + +@code +git clone git@github.com:FreeRADIUS/freeradius-server.git +cd freeradius-server +git fetch origin v2.x.x:v2.x.x +git checkout v2.x.x +@endcode +- Web: http://github.com/FreeRADIUS/freeradius-server/tree/v2.x.x + +@subsection branch_1xx 1.1.x EOL branch + +@note This branch is now permanently feature frozen. New features or modules + should be submitted against the master branch. + +@code +git clone git@github.com:FreeRADIUS/freeradius-server.git +cd freeradius-server +git fetch origin v2.x.x:v2.x.x +git checkout v2.x.x +@endcode +- Web: http://github.com/FreeRADIUS/freeradius-server/tree/v1.1.x + +@section main_website Website + +- http://www.freeradius.org + +@section mailinglist Mailing lists + +@subsection main_list FreeRADIUS-users + +This list is for users of the server + +@code +freeradius-users@lists.freeradius.org +@endcode +- Archives: http://lists.freeradius.org/pipermail/freeradius-users/ +- List info: http://freeradius.org/list/users.html + +@subsection dev_list FreeRADIUS-devel + +This list is for development of the server, including patches, and +new features. PLEASE DO NOT post questions related to the operation +of the server here - use the "users" list. Most of the developers +read both, and will answer your questions there if they have the time. + +@code +freeradius-devel@lists.freeradius.org +@endcode +- Archives: http://lists.freeradius.org/pipermail/freeradius-devel/ +- List info: http://freeradius.org/list/devel.html + +*/ diff --git a/doc/vendor/ascend b/doc/vendor/ascend new file mode 100644 index 0000000..57a44be --- /dev/null +++ b/doc/vendor/ascend @@ -0,0 +1,57 @@ + Ascend Radius Options + or + What happens when a big vendor ignores an RFC + + + FreeRADIUS uses Vendor-Specific attributes to send the Ascend attributes. +By default, Ascend NASes send the Ascend specific attributes as NON VSA's, +which conflict with new RADIUS attributes assigned by the IETF. This was +a very bad screw-up by Ascend that still causes many headaches, but sometimes +we have to live with it, so we try to cope the best we can. + + If you see a large number of messages about invalid Message-Authenticator +attribute, you most likely are affected by this problem, and should implement +the first option. + +You have two options: + +o Enable VSA's on the Ascend/Lucent MAX: + + This is by far the preferred method ( as it solves many other problems ). + + Max6000/4000 Series TAOS with Menued Interface: + + Go to Ethernet->Mod Config->Auth. + At the bottom of the menu, change Auth-Compat from "OLD" to "VSA". + Save your changes, no reboot is needed. + + Go to Ethernet->Mod Config->Acct. + At the bottom of the menu, change Acct-Compat from "OLD" to "VSA". + Save your changes, no reboot is needed. + + Max TNT/Apex 8000 Series TAOS with CLI: + + nas> read external-auth + nas> set rad-auth-client auth-radius-compat = vendor-specific + nas> set rad-acct-client acct-radius-compat = vendor-specific + nas> write + +o Enable OLD attributes in FreeRADIUS + + One note on this, Ciscos have an Ascend compatibility mode that + accepts only the OLD style Ascend attributes, just to make life more + interesting. :) + + You can make FreeRADIUS send the OLD style attributes by prefixing the + Ascend attributes with 'X-' in the 'users' file, sql table, ldap directory, + attr_filter module, etc... + + Thus the VSA Ascend attribute: + + Ascend-Data-Filter + + becomes the OLD Ascend attribute: + + X-Ascend-Data-Filter + +$Id$ diff --git a/doc/vendor/bay b/doc/vendor/bay new file mode 100644 index 0000000..a23cacd --- /dev/null +++ b/doc/vendor/bay @@ -0,0 +1,11 @@ + All versions of the BAY software prior to 18.0.2 are broken in +regards to the Message-Authenticator. They send a strictly MD5 +encoded secret instead of the encoding required by the RFC. This has +been fixed in 18.0.2 and only 18.0.2. + + If you see messages in the radius log like: + +Received packet from xxx.xxx.xxx.xxx with invalid Message-Authenticator! + + and you are using a Bay Annex, then you MUST upgrade the software on +your Annex. There is NO other solution to the problem. diff --git a/doc/vendor/cisco.rst b/doc/vendor/cisco.rst new file mode 100644 index 0000000..12270cb --- /dev/null +++ b/doc/vendor/cisco.rst @@ -0,0 +1,168 @@ +Cisco IOS and Radius +==================== + +Introduction +------------ + +Cisco NAS equipment has become quite popular of late, but being Cisco +equipment running IOS, the configuration can be a bit non-obvious to the +unfamiliar. This document aims to describe the most common configuration +options to make your Ciscos interoperate with radius as you would expect a +well-behaved NAS to do. + +IOS 12.x +-------- + +For Cisco 12.x ( 12.0 and 12.1 ), the following AAA configuration directives +are suggested: + +:: + + aaa new-model + aaa authentication login default group radius local + aaa authentication login localauth local + aaa authentication ppp default if-needed group radius local + aaa authorization exec default group radius local + aaa authorization network default group radius local + aaa accounting delay-start + aaa accounting exec default start-stop group radius + aaa accounting network default start-stop group radius + aaa processes 6 + +this configuration works very well with most radius servers. One of the more +important configurations is: + +:: + + aaa accounting delay-start + +This directive will delay the sending of the Accounting Start packet until +after an IP address has been assigned during the PPP negotiation process. +This will supersede the need to enable the sending of "Alive" packets as +described below for IOS versions 11.x + +*Note* with the above it will use the radius server to authenticate +your inbound 'telnet' connections. You will need to create an entry +in your users file similar to the following to allow access: + +:: + + !root Cleartext-Password := "somepass" Service-Type = NAS-Prompt-User + +This will let a user in for the first level of access to your Cisco. You +will still need to 'enable' ( using the locally configured enable secret ) +to perform any configuration changes or anything requiring a higher level +of access. The username '!root' was used as an example here, you can make +this any username you want, of course. + +Unique Acct-Session-Id's +^^^^^^^^^^^^^^^^^^^^^^^^ + +From: http://isp-lists.isp-planet.com/isp-australia/0201/msg05143.html + +Just a note to all cisco ISPs out there who want RFC2866 compliance need to +enable the hidden command ``radius-server unique-ident <n>`` + +Minimum IOS: 12.1(4.1)T. + +Acct-Session-Id should be unique and wrap after every 256 reboots. + +You must reboot after entering this command to take effect. If not, you +will observe after 10 minutes +of entering this command, the following message. + +:: + + %RADIUS-3-IDENTFAIL: Save of unique accounting ident aborted. + +IOS 11.x +-------- + +For Cisco 11.1, you normally use + +:: + + aaa new-model + aaa authentication ppp radppp if-needed radius + aaa authorization network radius none + aaa accounting network wait-start radius + +to get the Cisco to talk to a radius server. + +With IOS 11.3 +^^^^^^^^^^^^^ + +:: + + aaa accounting update newinfo + +If you want the IP address of the user to show up in the radutmp file +(and thus, the output of "radwho"). + +This is because with IOS 11.3, the Cisco first sends a "Start" accounting +packet without the IP address included. By setting "update newinfo" it +will send an account "Alive" packet which updates the information. + +Also you might see a lot of "duplicates" in the logfile. That can be +fixed by: + +:: + + aaa accounting network wait radius + radius-server timeout 3 + +To disable the Ascend style attributes (which is a VERY good idea!): + +:: + + radius-server host X.Y.Z.A auth-port 1645 acct-port 1646 + +To enable the Ascend style attributes (which we do NOT recommend!): + +:: + + radius-server host X.Y.Z.A auth-port 1645 acct-port 1646 non-standard + +To see Cisco-AVPair attributes in the Cisco debugging log: + + radius-server vsa accounting + +Cisco 36xx & 26xx, keeping the NAS IP static +-------------------------------------------- + +The Cisco 36/26 by default selects (it seems at random) any IP address +assigned to it (serial, ethernet etc.) as it's RADIUS client source +address, thus the access request may be dropped by the RADIUS server, +because it can not verify the client. To make the cisco box always use +one fixed address, add the following to your configuration: + +:: + + ip radius source-interface Loopback0 + +and configure the loopback interface on your router as follows: + +:: + + interface Loopback0 + ip address 192.0.2.250 255.255.255.255 + +Use a real world IP address and check the Cisco documentation for why +it is a good idea to have working loopback interface configured on +your router. + +If you don't want to use the loopback interface of course you can set +the source-interface to any interface on your Cisco box which has an +IP address. + +Credits +------- + +Original - Alan DeKok <aland@ox.org> +12.x Info - Chris Parker <cparker@starnetusa.net> 2000-10-12 + +More Information +---------------- +For more information, the following page on Cisco's web site may help: + +http://www.cisco.com/univercd/cc/td/doc/product/access/acs_serv/vapp_dev/vsaig3.htm diff --git a/doc/vendor/proxim b/doc/vendor/proxim new file mode 100644 index 0000000..3a8f2b9 --- /dev/null +++ b/doc/vendor/proxim @@ -0,0 +1,12 @@ +Proxim +^^^^^^ + +Proxim AP-2000 NASes up to and including firmware version 2.4.5 ignore +the Session-Timeout attribute, despite the fact that Proxim's firmware +release notes specifically state that it is supported. On top of +this, firmware version 2.4.5 (the latest as of this writing) has a bug +in which the reauthentication interval on the AP cannot be set to any +value less than 2 hours. As such, fine-grained control of client +session times is not currently possible with this NAS. Note that this +NAS is OEMed to several vendors, including Avaya, and may be listed +under different names with different vendors. |