OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / utils / auto
1 #! /bin/sh
2 # user interface to automatic keying and Pluto in general
3 # Copyright (C) 1998, 1999, 2000  Henry Spencer.
4
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2 of the License, or (at your
8 # option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
9
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 # for more details.
14 #
15 # RCSID $Id: auto,v 1.73 2002/03/26 05:07:48 henry Exp $
16
17 me='ipsec auto'
18 usage="Usage:
19         $me [--showonly] [--asynchronous] --up connectionname
20         $me [--showonly] --{add|delete|replace|down} connectionname
21         $me [--showonly] --{route|unroute} connectionname
22         $me [--showonly] --{ready|status}
23         $me [--showonly] --{rereadsecrets|rereadmycert|rereadcacerts}
24         $me [--showonly] --{rereadcrls|rereadall}
25         $me [--showonly] [--utc] --{listpubkeys|listcerts|listcerts}
26         $me [--showonly] --{listcacerts|listcrls|listall}
27         other options: [--config ipsecconfigfile] [--verbose] [--show]"
28
29 showonly=
30 config=
31 info=/var/run/ipsec.info
32 shopts=
33 noinclude=
34 async=
35 logfilter='$1 != "002"'
36 op=
37 argc=
38 utc=
39
40 for dummy
41 do
42         case "$1" in
43         --help)         echo "$usage" ; exit 0  ;;
44         --version)      echo "$me $IPSEC_VERSION" ; exit 0      ;;
45         --show)         shopts=-x               ;;
46         --showonly)     showonly=yes            ;;
47         --utc)          utc="$1"                ;;
48         --config)       config="--config $2" ; shift    ;;
49         --noinclude)    noinclude=--noinclude   ;;
50         --asynchronous) async="--asynchronous"  ;;
51         --verbose)      logfilter='1'           ;;
52         --up|--down|--add|--delete|--replace|--route|--unroute)
53                         if test " $op" != " "
54                         then
55                                 echo "$usage" >&2
56                                 exit 2
57                         fi
58                         op="$1"
59                         argc=1
60                         ;;
61         --ready|--status|\
62         --rereadsecrets|--rereadmycert|--rereadcacerts|\
63         --rereadcrls|--rereadall|\
64         --listpubkeys|--listcerts|--listcacerts|--listcrls|--listall)
65                         if test " $op" != " "
66                         then
67                                 echo "$usage" >&2
68                                 exit 2
69                         fi
70                         op="$1"
71                         argc=0
72                         ;;
73         --)             shift ; break           ;;
74         -*)             echo "$me: unknown option \`$1'" >&2 ; exit 2 ;;
75         *)              break                   ;;
76         esac
77         shift
78 done
79
80 names=
81 case "$op$#:$1:$2" in
82 2:*:up|2:*:down|2:*:add|2:*:delete|2:*:replace|2:*:route|2:*:unroute)
83                 echo "$me: warning: obsolete command syntax used" >&2
84                 names="$1"
85                 op="--$2"
86                 ;;
87 1:ready:|1:status:|1:rereadsecrets:|1:rereadmycert|rereadcacerts|\
88 1:rereadcrls|1:rereadall|1:listpubkeys|1:listcerts|1:listcacerts|\
89 1:listcrls|1:listall)
90                 echo "$me: warning: obsolete command syntax used" >&2
91                 op="--$1"
92                 ;;
93 --*)            if test " $argc" -ne $#
94                 then
95                         echo "$usage" >&2
96                         exit 2
97                 fi
98                 names="$*"
99                 ;;
100 *)              echo "$usage" >&2 ; exit 2      ;;
101 esac
102
103
104
105 runit() {
106         if test "$showonly"
107         then
108                 cat
109         else
110                 (
111                         echo '('
112                         cat
113                         echo ')'
114                         echo 'echo = $?'
115                 ) | sh $shopts |
116                         awk "/^= / { exit \$2 } $logfilter { print }"
117         fi
118 }
119
120 case "$op" in
121 --ready)        echo "ipsec whack --listen"                | runit ; exit ;;
122 --rereadsecrets)        echo "ipsec whack --rereadsecrets" | runit ; exit ;;
123 --rereadmycert)         echo "ipsec whack --rereadmycert"  | runit ; exit ;;
124 --rereadcacerts)        echo "ipsec whack --rereadcacerts" | runit ; exit ;;
125 --rereadcrls)           echo "ipsec whack --rereadcrls"    | runit ; exit ;;
126 --rereadall)            echo "ipsec whack --rereadall"     | runit ; exit ;;
127 --listpubkeys)  echo "ipsec whack $utc --listpubkeys"      | runit ; exit ;;
128 --listcerts)    echo "ipsec whack $utc --listcerts"        | runit ; exit ;;
129 --listcacerts)  echo "ipsec whack $utc --listcacerts"      | runit ; exit ;;
130 --listcrls)     echo "ipsec whack $utc --listcrls"         | runit ; exit ;;
131 --listall)      echo "ipsec whack $utc --listall"          | runit ; exit ;;
132 --up)   echo "ipsec whack $async --name $names --initiate" | runit ; exit ;;
133 --down) echo "ipsec whack --name $names --terminate"       | runit ; exit ;;
134 --delete)       echo "ipsec whack --name $names --delete"  | runit ; exit ;;
135 --route)        echo "ipsec whack --name $names --route"   | runit ; exit ;;
136 --unroute)      echo "ipsec whack --name $names --unroute" | runit ; exit ;;
137 --status)       echo "ipsec whack --status"                | runit ; exit ;;
138 esac
139
140 if test -s $info
141 then
142         . $info
143 fi
144
145 ipsec _confread $config $noinclude $names |
146 awk '   BEGIN {
147                 FS = "\t"
148                 op = "'"$op"'"
149                 err = "cat >&2"
150                 draddr = "'"$defaultrouteaddr"'"
151                 drnexthop = "'"$defaultroutenexthop"'"
152                 failed = 0
153                 s[""] = ""
154                 init()
155                 print "PATH=\"'"$PATH"'\""
156                 print "export PATH"
157         }
158         function init(   n) {
159                 for (n in s)
160                         delete s[n]
161                 name = ""
162                 seensome = 0
163         }
164         $1 == ":" {
165                 s[$2] = $3
166                 seensome = 1
167                 next
168         }
169         $1 == "!" {
170                 if ($2 != "")
171                         fail($2)
172                 next
173         }
174         $1 == "=" {
175                 if (name == "")
176                         name = $2
177                 next
178         }
179         $1 == "." {
180                 output()
181                 init()
182                 next
183         }
184         {
185                 fail("internal error, unknown type code " v($1))
186         }
187         function fail(m) {
188                 print "ipsec_auto: fatal error in " v(name) ": " m |err
189                 failed = 1
190                 exit
191         }
192         function yesno(k) {
193                 if ((k in s) && s[k] != "yes" && s[k] != "no")
194                         fail("parameter " v(k) " must be \"yes\" or \"no\"")
195         }
196         function default(k, val) {
197                 if (!(k in s))
198                         s[k] = val
199         }
200         function was(new, old) {
201                 if (!(new in s) && (old in s))
202                         s[new] = s[old]
203         }
204         function need(k) {
205                 if (!(k in s))
206                         fail("connection has no " v(k) " parameter specified")
207                 if (s[k] == "")
208                         fail("parameter " v(k) " value must be non-empty")
209         }
210         function integer(k) {
211                 if (!(k in s))
212                         return
213                 if (s[k] !~ /^[0-9]+$/)
214                         fail("parameter " v(k) " value must be integer")
215         }
216         function duration(k,   n, t) {
217                 if (!(k in s))
218                         return
219                 t = s[k]
220                 n = substr(t, 1, length(t)-1)
221                 if (t ~ /^[0-9]+$/)
222                         s[k] = t
223                 else if (t ~ /^[0-9]+s$/)
224                         s[k] = n
225                 else if (t ~ /^[0-9]+(\.[0-9]+)?m$/)
226                         s[k] = int(n*60)
227                 else if (t ~ /^[0-9]+(\.[0-9]+)?h$/)
228                         s[k] = int(n*3600)
229                 else if (t ~ /^[0-9]+(\.[0-9]+)?d$/)
230                         s[k] = int(n*3600*24)
231                 else
232                         fail("parameter " v(k) " not valid time, must be nnn[smhd]")
233         }
234         function nexthopset(dir, val,   k) {
235                 k = dir "nexthop"
236                 if (k in s)
237                         fail("non-default value of " k " is being overridden")
238                 if (val != "")
239                         s[k] = val
240                 else if (k in s)
241                         delete s[k]
242         }
243         function id(dir,   k) {
244                 k = dir "id"
245                 if (!(k in s))
246                         k = dir
247                 return s[k]
248         }
249         function whackkey(dir,   rk, n) {
250                 if (id(dir) == "%opportunistic")
251                         return
252                 rk = s[dir "rsasigkey"]
253                 if (rk == "" || rk == "%cert" || rk == "0x00")
254                         return
255                 n = "\"\\\"" name "\\\" " dir "rsasigkey\""
256                 if (rk == "%dns")
257                         print "ipsec whack --label", n,
258                                                 "--keyid", q(id(dir)), "\\"
259                 else
260                         print "ipsec whack --label", n, "--keyid", q(id(dir)),
261                                                 "--pubkeyrsa", q(rk), "\\"
262                 print "\t|| exit $?"
263         }
264         function q(str) {       # quoting for shell
265                 return "\"" str "\""
266         }
267         function qs(k) {        # utility abbreviation for q(s[k])
268                 return q(s[k])
269         }
270         function v(str) {       # quoting for human viewing
271                 return "\"" str "\""
272         }
273         function output() {
274                 if (!seensome)
275                         fail("internal error, output called inappropriately")
276
277                 default("type", "tunnel")
278                 if (s["type"] == "tunnel") {
279                         # do NOT default subnets to side/32, despite what
280                         # the docs say...
281                 } else if (s["type"] == "transport") {
282                         if ("leftsubnet" in s)
283                                 fail("type=transport incompatible with leftsubnet")
284                         if ("rightsubnet" in s)
285                                 fail("type=transport incompatible with rightsubnet")
286                 } else
287                         fail("only know how to do type tunnel or transport")
288
289                 need("left")
290                 need("right")
291                 if (s["left"] == "%defaultroute") {
292                         if (s["right"] == "%defaultroute")
293                                 fail("left and right cannot both be %defaultroute")
294                         if (draddr == "")
295                                 fail("%defaultroute requested but not known")
296                         s["left"] = draddr
297                         nexthopset("left", drnexthop)
298                 } else if (s["right"] == "%defaultroute") {
299                         if (draddr == "")
300                                 fail("%defaultroute requested but not known")
301                         s["right"] = draddr
302                         nexthopset("right", drnexthop)
303                 }
304
305                 default("keyexchange", "ike")
306                 if (s["keyexchange"] != "ike")
307                         fail("only know how to do keyexchange=ike")
308                 default("auth", "esp")
309                 if (("auth" in s) && s["auth"] != "esp" && s["auth"] != "ah")
310                         fail("only know how to do auth=esp or auth=ah")
311                 yesno("pfs")
312                 default("pfs", "yes")
313                 yesno("compress")
314                 default("compress", "no")
315                 was("keylife", "lifetime")
316                 default("keylife", "8h")
317                 duration("keylife")
318                 yesno("rekey")
319                 default("rekey", "yes")
320                 was("rekeymargin", "rekeystart")
321                 default("rekeymargin", "9m")
322                 duration("rekeymargin")
323                 was("keyingtries", "rekeytries")
324                 default("keyingtries", 3)
325                 integer("keyingtries")
326                 if ("rekeyfuzz" in s) {
327                         if (s["rekeyfuzz"] !~ /%$/)
328                                 fail("rekeyfuzz must be nnn%")
329                         r = s["rekeyfuzz"]
330                         s["rekeyfuzz"] = substr(r, 1, length(r)-1)
331                         integer("rekeyfuzz")
332                 }
333                 duration("ikelifetime")
334                 default("disablearrivalcheck", "yes")   # unfortunate
335
336                 default("leftnexthop", "%direct")
337                 default("rightnexthop", "%direct")
338                 if (s["leftnexthop"] == s["left"])
339                         fail("left and leftnexthop must not be the same")
340                 if (s["rightnexthop"] == s["right"])
341                         fail("right and rightnexthop must not be the same")
342                 if (s["leftnexthop"] == "%defaultroute") {
343                         if (drnexthop == "")
344                                 fail("%defaultroute requested but not known")
345                         s["leftnexthop"] = drnexthop
346                 }
347                 if (s["rightnexthop"] == "%defaultroute") {
348                         if (drnexthop == "")
349                                 fail("%defaultroute requested but not known")
350                         s["rightnexthop"] = drnexthop
351                 }
352
353                 if ("leftfirewall" in s && "leftupdown" in s)
354                         fail("cannot have both leftfirewall and leftupdown")
355                 if ("rightfirewall" in s && "rightupdown" in s)
356                         fail("cannot have both rightfirewall and rightupdown")
357                 default("leftupdown", "ipsec _updown")
358                 default("rightupdown", "ipsec _updown")
359                 default("leftfirewall", "no")
360                 default("rightfirewall", "no")
361                 yesno("leftfirewall")
362                 yesno("rightfirewall")
363                 if (s["leftfirewall"] == "yes")
364                         s["leftupdown"] = s["leftupdown"] " ipfwadm"
365                 if (s["rightfirewall"] == "yes")
366                         s["rightupdown"] = s["rightupdown"] " ipfwadm"
367
368                 default("authby", "secret")
369                 authtype = "--psk"
370                 if (s["authby"] == "rsasig") {
371                         authtype = "--rsasig"
372                         if (!("leftcert" in s)) {
373                                 need("leftrsasigkey")
374                                 if (id("left") == "%any" &&
375                                     !(s["leftrsasigkey"] == "%cert" ||
376                                       s["leftrsasigkey"] == "0x00") )
377                                         fail("ID " v(id("left")) " cannot have RSA key")
378                         }
379                         if (!("rightcert" in s)) {
380                                 need("rightrsasigkey")
381                                 if (id("right") == "%any" &&
382                                     !(s["rightrsasigkey"] == "%cert" ||
383                                       s["rightrsasigkey"] == "0x00") )
384                                         fail("ID " v(id("right")) " cannot have RSA key")
385                         }
386                 } else if (s["authby"] != "secret")
387                         fail("unknown authby value " v(s["authby"]))
388
389                 settings = "--encrypt"
390                 default("ike", "3des")
391                 if (s["ike"] != "")
392                         settings = settings " --ike " qs("ike")
393                 default("esp", "3des")
394                 if (s["esp"] != "")
395                         settings = settings " --esp " qs("esp")
396                 if (s["type"] != "transport")
397                         settings = settings " --tunnel"
398                 if (s["auth"] == "ah")
399                         settings = settings " --authenticate"
400                 if (s["pfs"] == "yes") {
401                         settings = settings " --pfs"
402                         if (s["pfsgroup"] != "")
403                                 settings = settings " --pfsgroup " qs("pfsgroup")
404                 }
405                 if (s["compress"] == "yes")
406                         settings = settings " --compress"
407                 if (op == "--replace")
408                         settings = settings " --delete"
409                 if ("ikelifetime" in s)
410                         settings = settings " --ikelifetime " qs("ikelifetime")
411                 if (s["disablearrivalcheck"] == "yes")
412                         settings = settings " --disablearrivalcheck"
413                 settings = settings " " authtype
414
415                 lc = ""
416                 rc = ""
417                 if ("leftsubnet" in s)
418                         lc = "--client " qs("leftsubnet")
419                 if ("rightsubnet" in s)
420                         rc = "--client " qs("rightsubnet")
421                 if ("leftsubnetwithin" in s)
422                         lc = lc " --clientwithin " qs("leftsubnetwithin")
423                 if ("rightsubnetwithin" in s)
424                         rc = rc " --clientwithin " qs("rightsubnetwithin")
425                 lp = ""
426                 rp = ""
427                 if ("leftprotoport" in s)
428                         lp = "--clientprotoport " qs("leftprotoport")
429                 if ("rightprotoport" in s)
430                         rp = "--clientprotoport " qs("rightprotoport")
431                 lud = "--updown " qs("leftupdown")
432                 rud = "--updown " qs("rightupdown")
433                 lid = ""
434                 if ("leftid" in s)
435                         lid = "--id " qs("leftid")
436                 rid = ""
437                 if ("rightid" in s)
438                         rid = "--id " qs("rightid")
439                 lcert = ""
440                 if ("leftcert" in s)
441                         lcert = "--cert " qs("leftcert")
442                 rcert = ""
443                 if ("rightcert" in s)
444                         rcert = "--cert " qs("rightcert")
445                 fuzz = ""
446                 if ("rekeyfuzz" in s)
447                         fuzz = "--rekeyfuzz " qs("rekeyfuzz")
448                 rk = ""
449                 if (s["rekey"] == "no")
450                         rk = "--dontrekey"
451                 pd = ""
452                 if ("_plutodevel" in s)
453                         pd = "--plutodevel " s["_plutodevel"]   # not qs()
454
455                 if (authtype != "--psk") {
456                         whackkey("left")
457                         whackkey("right")
458                 }
459                 print "ipsec whack --name", name, settings, "\\"
460                 print "\t--host", qs("left"), lc, lp,
461                                 "--nexthop", qs("leftnexthop"), lud, lid, lcert, "\\"
462                 print "\t--to", "--host", qs("right"), rc, rp,
463                                 "--nexthop", qs("rightnexthop"), rud, rid, rcert, "\\"
464                 print "\t--ipseclifetime", qs("keylife"),
465                         "--rekeywindow", qs("rekeymargin"), "\\"
466                 print "\t--keyingtries", qs("keyingtries"), fuzz, rk, pd, "\\"
467                 print "\t|| exit $?"
468         }
469         END {
470                 if (failed) {
471                         print "# fatal error discovered, force failure using \"false\" command"
472                         print "false"
473                         exit 1          # just on general principles
474                 }
475                 if (seensome)
476                         output()
477         }' | runit