-SUBMAKEFILES := rbmonkey.mk unit/all.mk xlat/all.mk keywords/all.mk auth/all.mk modules/all.mk
+SUBMAKEFILES := rbmonkey.mk unit/all.mk map/all.mk xlat/all.mk keywords/all.mk auth/all.mk modules/all.mk
#
# Include all of the autoconf definitions into the Make variable space
--- /dev/null
+User-Name = "bob"
+User-Password = "bob"
#
tests.keywords: $(TESTS.KEYWORDS_FILES)
-$(TESTS.KEYWORDS_FILES): $(TESTS.XLAT_FILES)
+$(TESTS.KEYWORDS_FILES): $(TESTS.XLAT_FILES) $(TESTS.MAP_FILES)
.PHONY: clean.tests.keywords
clean.tests.keywords:
--- /dev/null
+update control {
+ Cleartext-Password := 'hello'
+}
+
+update reply {
+ Filter-Id := "filter"
+}
+
+update request {
+ Tmp-String-0 := &reply:Filter-Id[#] # ERROR
+}
--- /dev/null
+#
+# PRE: foreach foreach-break-3
+#
+
+update request {
+ Calling-Station-Id := "8"
+}
+
+update control {
+ &Calling-Station-Id := "0"
+ &Calling-Station-Id += "1"
+ &Calling-Station-Id += "2"
+ &Calling-Station-Id += "3"
+ &Calling-Station-Id += "4"
+ &Calling-Station-Id += "5"
+ &Calling-Station-Id += "6"
+ &Calling-Station-Id += "7"
+ &Calling-Station-Id += "8"
+ &Calling-Station-Id += "9"
+ &Calling-Station-Id += "a"
+ &Calling-Station-Id += "b"
+ &Calling-Station-Id += "c"
+ &Calling-Station-Id += "d"
+ &Calling-Station-Id += "e"
+ &Calling-Station-Id += "f"
+ &Calling-Station-Id += "g"
+}
+
+foreach &control:Calling-Station-Id {
+ if (&request:Calling-Station-Id == "%{Foreach-Variable-0}") {
+ update reply {
+ Filter-Id := "filter"
+ }
+
+ break
+ }
+ elsif ("%{Foreach-Variable-0}" == '9') {
+ update reply {
+ Filter-Id := "fail-9"
+ }
+
+ reject
+ }
+}
--- /dev/null
+update request {
+ &Tmp-String-0 := 'foo'
+}
+
+switch "%{tolower:%{request:Tmp-String-0}}" {
+ case 'foo' {
+ update reply {
+ Filter-Id := "filter"
+ }
+ }
+
+ case '' {
+ update reply {
+ Filter-Id += "fail-empty-1"
+ }
+ }
+
+ case {
+ update reply {
+ Filter-Id += "fail-default-1"
+ }
+ }
+}
+
+switch "%{request:Tmp-String-0}" {
+ case 'foo' {
+ update reply {
+ Filter-Id := "filter"
+ }
+ }
+
+ case '' {
+ update reply {
+ Filter-Id += "fail-empty-2"
+ }
+ }
+
+ case {
+ update reply {
+ Filter-Id += "fail-default-2"
+ }
+ }
+}
--- /dev/null
+#
+# PRE: update
+#
+# Remove all attributes in a list
+#
+update {
+ control:Cleartext-Password := 'hello'
+ reply:Filter-Id := 'filter'
+}
+
+update request {
+ Tmp-String-0 := 'foobarbaz'
+ Tmp-Integer-0 := 123456789
+ Tmp-IP-Address-0 := 192.0.2.1
+}
+
+if ((Tmp-String-0 != 'foobarbaz') || (Tmp-Integer-0 != 123456789) || (Tmp-IP-Address-0 != 192.0.2.1)) {
+ update {
+ reply:Filter-Id := 'fail'
+ }
+}
+
+# Remove all attributes in the control list
+update {
+ request: !* ANY
+}
+
+# All attributes should now of been removed
+if ((Tmp-String-0 && (Tmp-String-0 == 'foobarbaz')) || \
+ (Tmp-Integer-0 && (Tmp-Integer-0 == 123456789)) || \
+ (Tmp-IP-Address-0 && (Tmp-IP-Address-0 == 192.0.2.1))) {
+ update {
+ reply:Filter-Id := 'fail'
+ }
+}
+
+# This will of been removed too
+update request {
+ User-Password := 'hello'
+}
--- /dev/null
+#
+# PRE: update if
+#
+update control {
+ Cleartext-Password := 'hello'
+}
+
+if (request:Packet-Type == Access-Request) {
+ update reply {
+ Filter-Id := "filter"
+ }
+}
--- /dev/null
+SUBMAKEFILES := map_unit.mk map_tests.mk
--- /dev/null
+update request {
+ Filter-Id := "filter"
+ User-Name := "blah"
+
+ &reply:Filter-Id += &request:Filter-Id[*]
+}
--- /dev/null
+update request {
+ &Filter-Id := "filter"
+ &User-Name := "blah"
+ &reply:Filter-Id += &Filter-Id[*]
+}
--- /dev/null
+MAP_TESTS := $(patsubst $(top_srcdir)/src/tests/map/%,%,$(filter-out %.conf %.md %.attrs %.c %.mk %~ %.rej %.out,$(wildcard $(top_srcdir)/src/tests/map/*)))
+MAP_OUTPUT := $(addsuffix .out,$(addprefix $(BUILD_DIR)/tests/map/,$(MAP_TESTS)))
+MAP_UNIT := $(BUILD_DIR)/bin/local/map_unit
+
+.PHONY: $(BUILD_DIR)/tests/map/
+$(BUILD_DIR)/tests/map/:
+ @mkdir -p $@
+
+#
+# Re-run the tests if the test program changes
+#
+# Create the output directory before the files
+#
+$(MAP_OUTPUT): $(MAP_UNIT) | $(BUILD_DIR)/tests/map/
+
+#
+# Re-run the tests if the input file changes
+#
+$(BUILD_DIR)/tests/map/%.out: $(top_srcdir)/src/tests/map/%
+ @echo MAP_TEST $(notdir $<)
+ @if ! $(MAP_UNIT) -d $(top_srcdir)/raddb -D $(top_srcdir)/share $< > $@ 2>&1; then \
+ if ! grep ERROR $< 2>&1 > /dev/null; then \
+ cat $@; \
+ echo "# $@"; \
+ echo FAILED: "$(MAP_UNIT) -d $(top_srcdir)/raddb -D $(top_srcdir)/share $<"; \
+ exit 1; \
+ fi; \
+ FOUND=$$(grep $< $@ | head -1 | sed 's,^.*$(top_srcdir),,;s/:.*//;s/.*\[//;s/\].*//'); \
+ EXPECTED=$$(grep -n ERROR $< | sed 's/:.*//'); \
+ if [ "$$EXPECTED" != "$$FOUND" ]; then \
+ cat $@; \
+ echo "# $@"; \
+ echo "E $$EXPECTED F $$FOUND"; \
+ echo UNEXPECTED ERROR: "$(MAP_UNIT) -d $(top_srcdir)/raddb -D $(top_srcdir)/share $<"; \
+ exit 1; \
+ fi; \
+ else \
+ if ! diff $<.out $@; then \
+ echo FAILED: " diff $<.out $@"; \
+ echo FAILED: "$(MAP_UNIT) -d $(top_srcdir)/raddb -D $(top_srcdir)/share $<"; \
+ exit 1; \
+ fi; \
+ fi
+
+TESTS.MAP_FILES := $(MAP_OUTPUT)
+
+$(TESTS.MAP_FILES): $(TESTS.UNIT_FILES)
+
+tests.map: $(MAP_OUTPUT)
--- /dev/null
+/*
+ * radattr.c Map debugging tool.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2015 Alan DeKok <aland@freeradius.org>
+ */
+
+RCSID("$Id$")
+
+#include <freeradius-devel/libradius.h>
+
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/modpriv.h>
+#include <freeradius-devel/modcall.h>
+
+#include <ctype.h>
+
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
+#include <assert.h>
+
+#include <freeradius-devel/log.h>
+extern log_lvl_t rad_debug_lvl;
+
+#include <sys/wait.h>
+pid_t rad_fork(void);
+pid_t rad_waitpid(pid_t pid, int *status);
+
+pid_t rad_fork(void)
+{
+ return fork();
+}
+
+pid_t rad_waitpid(pid_t pid, int *status)
+{
+ return waitpid(pid, status, 0);
+}
+
+
+static void NEVER_RETURNS usage(void)
+{
+ fprintf(stderr, "usage: map_unit [OPTS] filename ...\n");
+ fprintf(stderr, " -d <raddb> Set user dictionary directory (defaults to " RADDBDIR ").\n");
+ fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
+ fprintf(stderr, " -O <output_dir> Set output directory\n");
+ fprintf(stderr, " -x Debugging mode.\n");
+ fprintf(stderr, " -M Show program version information.\n");
+
+ exit(1);
+}
+
+static int process_file(char const *filename)
+{
+ int rcode;
+ char const *name1, *name2;
+ CONF_SECTION *cs, *main_cs;
+ vp_map_t *head, *map;
+ char buffer[8192];
+
+ main_cs = cf_section_alloc(NULL, "main", NULL);
+ if (cf_file_read(main_cs, filename) < 0) {
+ fprintf(stderr, "map_unit: Failed parsing %s\n",
+ filename);
+ exit(1);
+ }
+
+ /*
+ * Always has to be an "update" section.
+ */
+ cs = cf_section_sub_find(main_cs, "update");
+ if (!cs) {
+ talloc_free(main_cs);
+ return -1;
+ }
+
+ /*
+ * Convert the update section to a list of maps.
+ */
+ rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, modcall_fixup_update, NULL, 128);
+ if (rcode < 0) return -1; /* message already printed */
+ if (!head) {
+ cf_log_err_cs(cs, "'update' sections cannot be empty");
+ return -1;
+ }
+
+ buffer[0] = '\t';
+
+ name1 = cf_section_name1(cs);
+ name2 = cf_section_name2(cs);
+
+ /*
+ * And print it all out.
+ */
+ if (!name2) {
+ printf("%s {\n", name1);
+ } else {
+ printf("%s %s {\n", name1, name2);
+ }
+
+ for (map = head; map != NULL; map = map->next) {
+ map_prints(buffer + 1, sizeof(buffer) - 1, map);
+ puts(buffer);
+ }
+ printf("}\n");
+
+ talloc_free(main_cs);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int c, rcode = 0;
+ bool report = false;
+ char const *radius_dir = RADDBDIR;
+ char const *dict_dir = DICTDIR;
+
+ cf_new_escape = true; /* fix the tests */
+
+#ifndef NDEBUG
+ if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) {
+ fr_perror("radattr");
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ while ((c = getopt(argc, argv, "d:D:xMh")) != EOF) switch (c) {
+ case 'd':
+ radius_dir = optarg;
+ break;
+ case 'D':
+ dict_dir = optarg;
+ break;
+ case 'x':
+ fr_debug_lvl++;
+ rad_debug_lvl = fr_debug_lvl;
+ break;
+ case 'M':
+ report = true;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ argc -= (optind - 1);
+ argv += (optind - 1);
+
+ /*
+ * Mismatch between the binary and the libraries it depends on
+ */
+ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
+ fr_perror("radattr");
+ return 1;
+ }
+
+ if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) {
+ fr_perror("radattr");
+ return 1;
+ }
+
+ if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) {
+ fr_perror("radattr");
+ return 1;
+ }
+
+ if (argc < 2) {
+ rcode = process_file("-");
+
+ } else {
+ rcode = process_file(argv[1]);
+ }
+
+ if (report) {
+ dict_free();
+ fr_log_talloc_report(NULL);
+ }
+
+ if (rcode < 0) rcode = 1; /* internal to Unix process return code */
+
+ return rcode;
+}
--- /dev/null
+TARGET := map_unit
+SOURCES := map_unit.c ${top_srcdir}/src/main/modcall.c
+
+TGT_PREREQS := libfreeradius-server.a libfreeradius-radius.a
+TGT_LDLIBS := $(LIBS)
--- /dev/null
+#
+# ./eapol_test -c peap-mschapv2.conf -s testing123
+#
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=PEAP
+ identity="bob"
+ anonymous_identity="anonymous"
+ password="bob"
+ phase2="auth=MSCHAPV2"
+ phase1="peapver=0"
+
+ ca_cert="../../raddb/certs/ca.pem"
+ client_cert="../../raddb/certs/client.crt"
+ private_key="../../raddb/certs/client.key"
+ private_key_passwd="whatever"
+}
--- /dev/null
+#
+# We can't look at the data here, because the encoded Tunnel-Password has a 2 byte
+# random salt
+#
+#encode Tunnel-Password:0 := "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+#decode -
+#data Tunnel-Password:0 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+#
+# 1 octet for the tag. 2 octets for salt. One octet for encrypted length.
+# 249 octets left for real data.
+#
+encode Tunnel-Password:0 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx123456789ab"
+#data x
+decode -
+data Tunnel-Password:0 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx123456789"
+fff