summaryrefslogtreecommitdiffstats
path: root/raddb/mods-config/realm/freeradius-naptr-to-home-server.sh
blob: 66388d3b04eb7210c106b7772f7e79e199434d50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/sh

#  This script looks up radsec srv records in DNS for the one realm
#  given as argument, and creates a home_server template based on the
#  information found.
#
#  It currently ignores weight markers, but does sort servers on
#  priority marker, lowest number first.  For host command this is
#  column 5, for dig it is column 1.
#
#  It then tells FreeRADIUS (via radmin) that
#  there is a new home server.
#
#  Note that in order for it to work, you need to have the
#  "control-socket" enabled.

usage() {
	echo "Usage: ${0} [OPTIONS] <realm> <optional NAPTR tag>"
	echo "        -d RADIUS_DIR       Set radius directory"
	echo "        -t                  test (skip running radmin)"
	exit 1
}

test -n "${1}" || usage

RADDB=/etc/raddb
RADMIN=y

#
#  Parse command-line options
#
while [ `echo "$1" | cut -c 1` = "-" ]
do
   case "$1" in
	-d) 
		RADDB=$2
		shift;shift
		;;
	-t)
		RADMIN=
		shift
		;;

	*)
		usage
		;;
  esac
done

test -n "${2}" && NAPTRTAG="${2}" || NAPTRTAG="x-eduroam:radius.tls"

DIGCMD=$(command -v dig)
HOSTCMD=$(command -v host)
PRINTCMD=$(command -v printf)

#
#  These validations prevent rogue DNS records from pwning your RADIUS installation.
#
#  See https://github.com/radsecproxy/radsecproxy/security/advisories/GHSA-56gw-9rj9-55rc
#  and https://www.usenix.org/conference/usenixsecurity21/presentation/jeitner
#
#  The contents of these validation routines should NOT be changed without a deep understanding
#  of DNS!
#
validate_host() {
	echo ${@} | tr -d '\n\t\r' | grep -E '^[_0-9a-zA-Z][-._0-9a-zA-Z]*$'
}

validate_port() {
	echo ${@} | tr -d '\n\t\r' | grep -E '^[0-9]+$'
}

dig_it_srv() {
	${DIGCMD} +short srv $SRV_HOST | sort -n -k1 |
	while read line; do
		set $line
		PORT=$(validate_port $3)
		HOST=$(validate_host $4)
		if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then
			$PRINTCMD "\tipaddr = ${HOST%.}\n\tport = ${PORT}\n"
		fi
	done
}

dig_it_naptr() {
	${DIGCMD} +short naptr "${REALM}" | grep $NAPTRTAG | sort -n -k1 |
	while read line; do
		set $line
		TYPE=$3
		HOST=$(validate_host $6)
		if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then
			SRV_HOST=${HOST%.}
			dig_it_srv
		fi
	done
}

host_it_srv() {
	${HOSTCMD} -t srv $SRV_HOST | sort -n -k5 |
	while read line; do
		set $line
		PORT=$(validate_port $7)
		HOST=$(validate_host $8) 
		if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then
			$PRINTCMD "\tipaddr ${HOST%.}:${PORT}\n"
		fi
	done
}

host_it_naptr() {
	${HOSTCMD} -t naptr "${REALM}" | grep $NAPTRTAG | sort -n -k5 |
	while read line; do
		set $line
		TYPE=$7
		HOST=$(validate_host ${10})
		if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then
			SRV_HOST=${HOST%.}
			host_it_srv
		fi
	done
}

REALM=$(validate_host ${1})
if [ -z "${REALM}" ]; then
	echo "realm \"${1}\" failed validation" >&2
	usage
fi

if [ -x "${DIGCMD}" ]; then
	SERVERS=$(dig_it_naptr)

elif [ -x "${HOSTCMD}" ]; then
	SERVERS=$(host_it_naptr)

else
	echo "${0} requires either \"dig\" or \"host\" command." >&2
	exit 1
fi

if [ ! -n "${SERVERS}" ]; then
	echo "No servers found"  >&2
	exit 1
fi

#
#  Just testing - don't do anything else.
#
if [ -z "${RADMIN}" ]; then
	$PRINTCMD "home_server ${REALM} {\n${SERVERS}\n\t\$INCLUDE tls.conf\n}\n"
	exit 0
fi

#
#  Print out the template, and include the site-local tls.conf file.
#
$PRINTCMD "home_server ${REALM} {\n${SERVERS}\n\t\$INCLUDE tls.conf\n}\n" > $RADDB/home_servers/$1

#
#  @todo - use ${prefix} or some such thing to find radmin.
#
/usr/sbin/radmin -e "add home_server file $RADDB/home_servers/$1"