Files
strongswan-ext/programs/_confread/_confread.in
T
Martin Willi 997358a6c4 - import of strongswan-2.7.0
- applied patch for charon
2006-04-28 07:14:48 +00:00

521 lines
13 KiB
Bash
Executable File

#!/bin/sh
# configuration-file reader utility
# Copyright (C) 1999-2002 Henry Spencer.
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: _confread.in,v 1.15 2006/04/20 04:42:12 as Exp $
#
# Extract configuration info from /etc/ipsec.conf, repackage as assignments
# to shell variables or tab-delimited fields. Success or failure is reported
# inline, as extra data, due to the vagaries of shell backquote handling.
# In the absence of --varprefix, output is tab-separated fields, like:
# = sectionname
# : parameter value
# ! status (empty for success, else complaint)
# In the presence of (say) "--varprefix IPSEC", output is like:
# IPSEC_confreadsection="sectionname"
# IPSECparameter="value"
# IPSEC_confreadstatus="status" (same empty/complaint convention)
#
# The "--search parametername" option inverts the search: instead of
# yielding the parameters of the specified name(s), it yields the names
# of sections with parameter <parametername> having (one of) the
# specified value(s). In this case, --varprefix output is a list of
# names in the <prefix>_confreadnames variable. Search values with
# white space in them are currently not handled properly.
#
# Typical usage:
# eval `ipsec _confread --varprefix IPSEC --type config setup`
# if test " $IPSEC_confreadstatus" != " "
# then
# echo "$0: $IPSEC_confreadstatus -- aborting" 2>&1
# exit 1
# fi
# absent default config file treated as empty
config=${IPSEC_CONFS-@FINALCONFDIR@}/ipsec.conf
if test ! -f "$config" ; then config=/dev/null ; fi
include=yes
type=conn
fieldfmt=yes
prefix=
search=
export=0
version=
optional=0
me="ipsec _confread"
for dummy
do
case "$1" in
--config) config="$2" ; shift ;;
--noinclude) include= ;;
--type) type="$2" ; shift ;;
--varprefix) fieldfmt=
prefix="$2"
shift ;;
--export) export=1 ;;
--search) search="$2" ; shift ;;
--version) echo "$me $IPSEC_VERSION" ; exit 0 ;;
--optional) optional=1 ;;
--) shift ; break ;;
-*) echo "$0: unknown option \`$1'" >&2 ; exit 2 ;;
*) break ;;
esac
shift
done
if test "$include"
then
ipsec _include --inband $config
else
cat $config
fi |
awk 'BEGIN {
type = "'"$type"'"
names = "'"$*"'"
prefix = "'"$prefix"'"
export = "'"$export"'"
optional = 0 + '"$optional"'
myid = "'"$IPSECmyid"'"
search = "'"$search"'"
searching = 0
if (search != "") {
searching = 1
searchpat = search "[ \t]*=[ \t]*"
}
fieldfmt = 0
if ("'"$fieldfmt"'" == "yes")
fieldfmt = 1
including = 0
if ("'"$include"'" == "yes")
including = 1
filename = "'"$config"'"
lineno = 0
originalfilename = filename
if (fieldfmt)
bq = eq = "\""
else
bq = eq = "\\\""
failed = 0
insection = 0
wrongtype = 0
indefault = 0
outputting = 0
sawnondefault = 0
OFS = "\t"
o_status = "!"
o_parm = ":"
o_section = "="
o_names = "%"
o_end = "."
n = split(names, na, " ")
if (n == 0)
fail("no section names supplied")
for (i = 1; i <= n; i++) {
if (na[i] in wanted)
fail("section " bq na[i] eq " requested more than once")
wanted[na[i]] = 1
pending[na[i]] = 1
if (!searching && na[i] !~ /^[a-zA-Z][a-zA-Z0-9._-]*$/)
fail("invalid section name " bq na[i] eq)
}
good = "also alsoflip type auto authby _plutodevel"
left = " left leftsubnet leftnexthop leftfirewall lefthostaccess leftupdown"
akey = " keyexchange auth pfs keylife rekey rekeymargin rekeyfuzz"
akey = akey " dpdaction dpddelay dpdtimeout"
akey = akey " pfsgroup compress"
akey = akey " keyingtries ikelifetime disablearrivalcheck failureshunt ike"
mkey = " spibase spi esp espenckey espauthkey espreplay_window"
left = left " leftespenckey leftespauthkey leftahkey"
left = left " leftespspi leftahspi leftid leftrsasigkey leftrsasigkey2"
left = left " leftsendcert leftcert leftca leftsubnetwithin leftprotoport"
left = left " leftgroups leftsourceip"
mkey = mkey " ah ahkey ahreplay_window"
right = left
gsub(/left/, "right", right)
n = split(good left right akey mkey, g)
for (i = 1; i <= n; i++)
goodnames["conn:" g[i]] = 1
good = "also interfaces forwardcontrol myid"
good = good " syslog klipsdebug plutodebug plutoopts plutostderrlog"
good = good " plutorestartoncrash"
good = good " dumpdir manualstart pluto"
good = good " plutowait prepluto postpluto"
good = good " fragicmp hidetos rp_filter uniqueids"
good = good " overridemtu pkcs11module pkcs11keepstate pkcs11proxy"
good = good " nocrsend strictcrlpolicy crlcheckinterval cachecrls"
good = good " nat_traversal keep_alive force_keepalive"
good = good " disable_port_floating virtual_private"
n = split(good, g)
for (i = 1; i <= n; i++)
goodnames["config:" g[i]] = 1
good = "auto cacert ldaphost ldapbase crluri crluri2 ocspuri"
good = good " strictcrlpolicy"
n = split(good, g)
for (i = 1; i <= n; i++)
goodnames["ca:" g[i]] = 1
goodtypes["conn"] = 1
goodtypes["config"] = 1
goodtypes["ca"] = 1
badchars = ""
for (i = 1; i < 32; i++)
badchars = badchars sprintf("%c", i)
for (i = 127; i < 128+32; i++)
badchars = badchars sprintf("%c", i)
badchar = "[" badchars "]"
# if searching, seen is set of sectionnames which match
# if not searching, seen is set of parameter names found
seen[""] = ""
defaults[""] = ""
usesdefault[""] = ""
orientation = 1
}
function output(code, v1, v2) {
if (code == o_parm) {
if (v2 == "") # suppress empty parameters
return
if (privatename(v1)) # and private ones
return
if (v2 ~ badchar)
fail("parameter value " bq v2 eq " contains unprintable character")
}
if (fieldfmt) {
print code, v1, v2
return
}
if (code == o_status) {
v2 = v1
v1 = "_confreadstatus"
} else if (code == o_section) {
v2 = v1
v1 = "_confreadsection"
} else if (code == o_names) {
v2 = v1
v1 = "_confreadnames"
} else if (code != o_parm)
return # currently no variable version of o_end
print prefix v1 "=\"" v2 "\""
if (export)
print "export " prefix v1
}
function searchfound(sectionname, n, i, reflist) {
# a hit in x is a hit in everybody who refers to x too
n = split(refsto[sectionname], reflist, ";")
for (i = 1; i <= n; i++)
if (reflist[i] in seen)
fail("duplicated parameter " bq search eq)
else
seen[reflist[i]] = 1
seen[sectionname] = 1
}
function fail(msg) {
output(o_status, ("(" filename ", line " lineno ") " msg))
failed = 1
while ((getline junk) > 0)
continue
exit
}
function badname(n) {
if ((type ":" n) in goodnames)
return 0
if (privatename(n))
return 0
return 1
}
function privatename(n) {
if (n ~ /^[xX][-_]/)
return 1
return 0
}
function orient(n) {
if (orientation == -1) {
if (n ~ /left/)
gsub(/left/, "right", n)
else if (n ~ /right/)
gsub(/right/, "left", n)
}
return n
}
# in searching, referencing is transitive: xyz->from->to
function chainref(from, to, i, reflist, listnum) {
if (from in refsto) {
listnum = split(refsto[from], reflist, ";")
for (i = 1; i <= listnum; i++)
chainref(reflist[i], to)
}
if (to in refsto)
refsto[to] = refsto[to] ";" from
else
refsto[to] = from
}
# start of rules
{
lineno++
# lineno is now the number of this line
# we must remember indentation because comment stripping loses it
exdented = $0 !~ /^[ \t]/
sub(/^[ \t]+/, "") # get rid of leading white space
sub(/[ \t]+$/, "") # get rid of trailing white space
}
including && $0 ~ /^#[<>:]/ {
# _include control line
if ($1 ~ /^#[<>]$/) {
filename = $2
lineno = $3 - 1
} else if ($0 ~ /^#:/) {
msg = substr($0, 3)
gsub(/"/, "\\\"", msg)
fail(msg)
}
next
}
exdented {
# any non-leading-white-space line is a section end
### but not the end of relevant stuff, might be also= sections later
###if (insection && !indefault && !searching && outputting)
### output(o_end)
insection = 0
wrongtype = 0
indefault = 0
outputting = 0
}
/[ \t]#/ {
# strip trailing comments including the leading whitespace
# tricky because we must respect quotes
q = 0
for (i = 1; i <= NF; i++) {
if ($i ~ /^#/ && q % 2 == 0) {
NF = i - 1;
break
}
# using $i in gsub loses whitespace?!?
junk = $i
q += gsub(/"/, "&", junk)
}
}
$0 == "" || $0 ~ /^#/ {
# empty lines and comments are ignored
next
}
exdented && NF != 2 {
# bad section header
fail("section header " bq $0 eq " has wrong number of fields (" NF ")")
}
exdented && $1 == "version" {
version = $2 + 0
if (version < 2.0 || 2.0 < version)
fail("we only support version 2.0 ipsec.conf files, not " bq version eq)
next
}
version == "" {
fail("we only support version 2 ipsec.conf files")
}
exdented && !($1 in goodtypes) {
# unknown section type
fail("section type " bq $1 eq " not recognized")
}
exdented && $1 != type {
# section header, but not of the type we want
insection = 1
wrongtype = 1
next
}
extented {
# type fits
wrongtype = 0
}
exdented && $1 == "config" && $2 != "setup" {
fail("unknown config section " bq $2 eq)
}
exdented && $2 != "%default" {
# non-default section header of our type
sawnondefault = 1
}
exdented && searching && $2 != "%default" {
# section header, during search
insection = 1
sectionname = $2
usesdefault[sectionname] = 1 # tentatively
next
}
exdented && !searching && $2 in wanted {
# one of our wanted section headers
if (!($2 in pending))
fail("duplicate " type " section " bq $2 eq)
delete pending[$2]
tag = bq type " " $2 eq
outputting = 1
insection = 1
orientation = wanted[$2]
output(o_section, $2)
next
}
exdented && $2 == "%default" {
# relevant default section header
if (sawnondefault)
fail(bq $1 " %default" eq " sections must precede non-default ones")
tag = bq type " " $2 eq
indefault = 1
next
}
exdented {
# section header, but not one we want
insection = 1
next
}
!insection && !indefault {
# starts with white space but not in a section... oops
fail("parameter is not within a section")
}
!wrongtype && searching && $0 ~ searchpat {
# search found the right parameter name
match($0, searchpat)
rest = substr($0, RLENGTH+1)
if (rest ~ /^".*"$/)
rest = substr(rest, 2, length(rest)-2)
if (!indefault) {
if (!usesdefault[sectionname])
fail("duplicated parameter " bq search eq)
usesdefault[sectionname] = 0
} else if (search in defaults)
fail("duplicated parameter " bq search eq)
if (rest in wanted) { # a hit
if (indefault)
defaults[search] = rest
else
searchfound(sectionname)
} else {
# rather a kludge, but must check this somewhere
if (search == "auto" && rest !~ /^(add|route|start|ignore|manual)$/)
fail("illegal auto value " bq rest eq)
}
next
}
!searching && !outputting && !indefault {
# uninteresting line
next
}
$0 ~ /"/ && $0 !~ /^[^=]+=[ \t]*"[^"]*"$/ {
if (!searching)
fail("mismatched quotes in parameter value")
else
gsub(/"/, "", $0)
}
$0 !~ /^[a-zA-Z_][a-zA-Z0-9_-]*[ \t]*=/ {
if (searching)
next # just ignore it
fail("syntax error or illegal parameter name")
}
{
sub(/[ \t]*=[ \t]*/, "=") # get rid of white space around =
}
$0 ~ /^(also|alsoflip)=/ {
v = orientation
if ($0 ~ /^alsoflip/)
v = -v;
if (indefault)
fail("%default section may not contain " bq "also" eq " or " bq "alsoflip" eq " parameter")
sub(/^(also|alsoflip)=/, "")
if ($0 !~ /^[a-zA-Z][a-zA-Z0-9._-]*$/)
fail("invalid section name " bq $0 eq)
if (!searching) {
if ($0 in wanted)
fail("section " bq $0 eq " requested more than once")
wanted[$0] = v
pending[$0] = 1
} else
chainref(sectionname, $0)
next
}
!outputting && !indefault {
# uninteresting line even for a search
next
}
{
equal = match($0, /[=]/)
name = substr($0, 1, equal-1)
if (badname(name))
fail("unknown parameter name " bq name eq)
value = substr($0, equal+1)
if (value ~ /^"/)
value = substr(value, 2, length(value)-2)
else if (value ~ /[ \t]/)
fail("white space within non-quoted parameter " bq name eq)
}
indefault {
if (name in defaults)
fail("duplicated default parameter " bq name eq)
defaults[name] = value
next
}
{
name = orient(name)
if (name in seen)
fail("duplicated parameter " bq name eq)
seen[name] = 1
output(o_parm, name, value)
}
END {
if (failed)
exit 1
filename = originalfilename
unseen = ""
for (i in pending)
unseen = unseen " " i
if (!optional && !searching && unseen != "")
fail("did not find " type " section(s) " bq substr(unseen, 2) eq)
if (!searching) {
for (name in defaults)
if (!(name in seen))
output(o_parm, name, defaults[name])
} else {
if (defaults[search] in wanted)
for (name in usesdefault)
if (usesdefault[name])
seen[name] = 1
delete seen[""]
if (fieldfmt)
for (name in seen)
output(o_section, name)
else {
outlist = ""
for (name in seen)
if (outlist == "")
outlist = name
else
outlist = outlist " " name
output(o_names, outlist)
}
}
output(o_status, "")
}'