OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / utils / manual
1 #! /bin/sh
2 # user interface to manual keying
3 # Copyright (C) 1998, 1999  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: manual,v 1.79 2002/03/11 20:42:27 henry Exp $
16
17 me='ipsec manual'
18 usage="Usage:
19   $me [--showonly] --{up|down|route|unroute} name
20   $me [--showonly] --{up|down|route|unroute} --union partname ... 
21
22   other options: [--config ipsecconfigfile] [--other] [--show]
23                         [--iam ipaddress@interface]"
24
25 # make sure outputs of (e.g.) ifconfig are in English
26 unset LANG LANGUAGE LC_ALL LC_MESSAGES
27
28 showonly=
29 config=
30 info=/var/run/ipsec.info
31 shopts=
32 other=0
33 union=0
34 noinclude=
35 interfs=
36 op=
37
38 for dummy
39 do
40         case "$1" in
41         --help)         echo "$usage" ; exit 0  ;;
42         --version)      echo "$me $IPSEC_VERSION" ; exit 0      ;;
43         --show)         shopts=-x               ;;
44         --showonly)     showonly=yes            ;;
45         --other)        other=1                 ;;
46         --union)        union=1                 ;;
47         --config)       config="--config $2" ; shift    ;;
48         --noinclude)    noinclude=--noinclude   ;;
49         --iam)          interfs="$2" ; shift    ;;
50         --up|--down|--route|--unroute)
51                         if test " $op" != " "
52                         then
53                                 echo "$usage" >&2
54                                 exit 2
55                         fi
56                         op="$1"
57                         ;;
58         --)             shift ; break           ;;
59         -*)             echo "$me: unknown option \`$1'" >&2 ; exit 2   ;;
60         *)              break                   ;;
61         esac
62         shift
63 done
64
65 case "$op$#:$union" in
66 [01]:*)         echo "$usage" >&2 ; exit 2      ;;
67 2:0)            echo "$me: warning: obsolete command syntax used" >&2
68                 op="--$2"
69                 names="$1"
70                 ;;
71 [0-9]*:1)       ;;
72 --*)            if test $# -eq 0
73                 then
74                         echo "$usage" >&2
75                         exit 2
76                 fi
77                 names="$*"
78                 ;;
79 *)              echo "$usage" >&2 ; exit 2      ;;
80 esac
81 if test " $op" = " "
82 then
83         # --union obsolete-syntax case, op is last argument
84         echo "$me: warning: obsolete command syntax used" >&2
85         names=
86         prev=
87         for arg
88         do
89                 names="$names $prev"
90                 prev="$arg"
91         done
92         op="--$prev"
93 fi
94 case "$op" in
95 --up|--down|--route|--unroute)          ;;
96 *)      echo "$usage" >&2 ; exit 2      ;;
97 esac
98
99 case "$interfs" in
100 '')     interfs="`ifconfig |
101                 awk '   /^ipsec/ { interf = $1 ; next }
102                         /^[^ \t]/ { interf = "" ; next }
103                         /^[ \t]*inet addr/ {
104                                 sub(/:/, " ", $0)
105                                 if (interf != "")
106                                         print $3 "@" interf
107                          }' | tr '\n' ' '`"
108         ;;
109 esac
110
111 if test -s $info
112 then
113         . $info
114 fi
115
116 ipsec _confread $config $noinclude $names |
117 awk '   BEGIN {
118                 FS = "\t"
119                 myname = "'"$me"'"
120                 err = "cat >&2"
121                 op = "'"$op"'"
122                 other = '"$other"'
123                 names = "'"$names"'"
124                 interfs = "'"$interfs"'"
125                 ni = split(interfs, terfs, " ")
126                 if (ni == 0)
127                         fail("no IPsec-enabled interfaces found")
128                 for (i = 1; i <= ni; i++) {
129                         nc = split(terfs[i], cpts, "@")
130                         if (nc != 2)
131                                 fail("internal error on " terfs[i])
132                         interface[cpts[1]] = cpts[2]
133                 }
134                 draddr = "'"$defaultrouteaddr"'"
135                 drnexthop = "'"$defaultroutenexthop"'"
136                 s[""] = ""
137                 nlspi = 0
138                 nrspi = 0
139                 failed = 0
140                 maskbits[0] = "0.0.0.0"
141                 maskbits[1] = "128.0.0.0"
142                 maskbits[2] = "192.0.0.0"
143                 maskbits[3] = "224.0.0.0"
144                 maskbits[4] = "240.0.0.0"
145                 maskbits[5] = "248.0.0.0"
146                 maskbits[6] = "252.0.0.0"
147                 maskbits[7] = "254.0.0.0"
148                 maskbits[8] = "255.0.0.0"
149                 maskbits[9] = "255.128.0.0"
150                 maskbits[10] = "255.192.0.0"
151                 maskbits[11] = "255.224.0.0"
152                 maskbits[12] = "255.240.0.0"
153                 maskbits[13] = "255.248.0.0"
154                 maskbits[14] = "255.252.0.0"
155                 maskbits[15] = "255.254.0.0"
156                 maskbits[16] = "255.255.0.0"
157                 maskbits[17] = "255.255.128.0"
158                 maskbits[18] = "255.255.192.0"
159                 maskbits[19] = "255.255.224.0"
160                 maskbits[20] = "255.255.240.0"
161                 maskbits[21] = "255.255.248.0"
162                 maskbits[22] = "255.255.252.0"
163                 maskbits[23] = "255.255.254.0"
164                 maskbits[24] = "255.255.255.0"
165                 maskbits[25] = "255.255.255.128"
166                 maskbits[26] = "255.255.255.192"
167                 maskbits[27] = "255.255.255.224"
168                 maskbits[28] = "255.255.255.240"
169                 maskbits[29] = "255.255.255.248"
170                 maskbits[30] = "255.255.255.252"
171                 maskbits[31] = "255.255.255.254"
172                 maskbits[32] = "255.255.255.255"
173         }
174         $1 == "=" {
175                 next
176         }
177         $1 == "!" {
178                 if ($2 != "")
179                         fail($2)
180                 next
181         }
182         $1 != ":" {
183                 fail("internal error, unknown type code \"" $1 "\"")
184         }
185         { s[$2] = $3 }
186         function q(s) {
187                 return "\"" s "\""
188         }
189         function fail(m) {
190                 print myname ": fatal error in " q(names) ": " m   |err
191                 failed = 1
192                 exit
193         }
194         function swap(k,   t, l, r) {
195                 l = "left" k
196                 r = "right" k
197                 if ((l in s) && (r in s)) {
198                         t = s[l]
199                         s[l] = s[r]
200                         s[r] = t
201                 } else if (l in s) {    # but not r
202                         s[r] = s[l]
203                         delete s[l]
204                 } else if (r in s) {    # but not l
205                         s[l] = s[r]
206                         delete s[r]
207                 }
208         }
209         function yesno(k) {
210                 if ((k in s) && s[k] != "yes" && s[k] != "no")
211                         fail("parameter \"" k "\" must be \"yes\" or \"no\"")
212         }
213         function default(k, v) {
214                 if (!(k in s))
215                         s[k] = v
216         }
217         function need(k) {
218                 if (!(k in s))
219                         fail("connection has no \"" k "\" parameter specified")
220                 if (s[k] == "")
221                         fail("parameter \"" k "\" value must be non-empty")
222         }
223         function integer(k) {
224                 if (!(k in s))
225                         return
226                 if (s[k] !~ /^[0-9]+$/)
227                         fail("parameter \"" k "\" value must be integer")
228         }
229         function nexthopset(dir, val,   k) {
230                 k = dir "nexthop"
231                 if (k in s)
232                         fail("non-default value of " k " is being overridden")
233                 if (val != "")
234                         s[k] = val
235                 else if (k in s)
236                         delete s[k]
237         }
238         function leftward(   t) {
239                 nlspi++
240                 if ("spi" in s)
241                         return s["spi"]
242                 t = spibase spil
243                 spil += 2
244                 return t
245         }
246         function rightward(   t) {
247                 nrspi++
248                 if ("spi" in s)
249                         return s["spi"]
250                 t = spibase spir
251                 spir += 2
252                 return t
253         }
254         function netfix(dir,   n, t) {
255                 n = s[dir "subnet"]
256                 if (n == "%default")
257                         n = "0.0.0.0/0"
258                 if (n !~ /\//)
259                         fail(dir "subnet=" n " has no mask specified")
260                 t = split(n, netfixarray, "/")
261                 if (t != 2)
262                         fail("bad syntax in " dir "subnet=" n)
263                 s[dir "net"] = netfixarray[1]
264                 s[dir "mask"] = mask(netfixarray[2])
265         }
266         function mask(m) {
267                 if (m ~ /\./)
268                         return m
269                 if (!(m in maskbits))
270                         fail("unknown mask syntax \"" m "\"")
271                 return maskbits[m]
272         }
273         function bidir(name,   l, r) {
274                 l = "left" name
275                 r = "right" name
276                 if (!(l in s) && (name in s))
277                         s[l] = s[name]
278                 if (!(r in s) && (name in s))
279                         s[r] = s[name]
280                 if ((l in s) != (r in s))
281                         fail("must give both or neither \"" l "\" and \"" \
282                                                                         r "\"")
283         }
284         function espspi(src, dest, spi,   dir) {
285                 if (!("esp" in s))
286                         return
287                 dir = (dest == me) ? "left" : "right"
288                 print "ipsec spi --label", q(names), "--af inet",
289                         "--said", ("esp" spi "@" dest), "\\"
290                 print "\t--esp", s["esp"], "--src", src, "\\"
291                 if ((dir "espauthkey") in s)
292                         print "\t--authkey", s[dir "espauthkey"], "\\"
293                 if ("espreplay_window" in s)
294                         print "\t--replay_window", s["espreplay_window"], "\\"
295                 if ((dir "espenckey") in s)
296                         print "\t--enckey", s[dir "espenckey"], "&&"
297                 else
298                         print "\t&&"
299         }
300         function ahspi(src, dest, spi,   dir) {
301                 if (!("ah" in s))
302                         return
303                 dir = (dest == me) ? "left" : "right"
304                 if (!((dir "ahkey") in s))
305                         fail("AH specified but no ahkey= given")
306                 print "ipsec spi --label", q(names), "--af inet",
307                         "--said", ("ah" spi "@" dest), "\\"
308                 print "\t--ah", s["ah"], "--src", src, "\\"
309                 if ("ahreplay_window" in s)
310                         print "\t--replay_window", s["ahreplay_window"], "\\"
311                 print "\t--authkey", s[dir "ahkey"], "&&"
312         }
313         # issue a suitable invocation of updown command
314         function updown(verb, suffix,   cmd) {
315                 if ("leftupdown" in s) {
316                         cmd = s["leftupdown"]
317                         if (s["leftfirewall"] == "yes")
318                                 fail("cannot specify both updown and firewall")
319                 } else {
320                         cmd = "ipsec _updown"
321                         if (s["leftfirewall"] == "yes")
322                                 cmd = cmd " ipfwadm"
323                 }
324                 print "PLUTO_VERB=" verb verbsuf " " cmd " " suffix
325         }
326         END {
327         #########
328         if (failed)
329                 exit 1
330         default("type", "tunnel")
331         if (s["type"] == "transport") {
332                 if ("leftsubnet" in s)
333                         fail("type=transport incompatible with leftsubnet")
334                 if ("rightsubnet" in s)
335                         fail("type=transport incompatible with rightsubnet")
336         } else if (s["type"] != "tunnel" && s["type"] != "passthrough")
337                 fail("only know how to do types tunnel/transport/passthrough")
338         pass = 0
339         if (s["type"] == "passthrough") {
340                 if (("ah" in s) || ("esp" in s))
341                         fail("passthrough connection may not specify AH or ESP")
342                 pass = 1
343         } else {
344                 if (!("ah" in s) && !("esp" in s))
345                         fail("neither AH nor ESP specified for connection")
346         }
347
348         need("left")
349         need("right")
350         if (s["left"] == "%defaultroute") {
351                 if (s["right"] == "%defaultroute")
352                         fail("left and right cannot both be %defaultroute")
353                 if (draddr == "")
354                         fail("%defaultroute requested but not known")
355                 s["left"] = draddr
356                 nexthopset("left", drnexthop)
357         } else if (s["right"] == "%defaultroute") {
358                 if (draddr == "")
359                         fail("%defaultroute requested but not known")
360                 s["right"] = draddr
361                 nexthopset("right", drnexthop)
362         }
363
364         leftsub = ("leftsubnet" in s) ? 1 : 0
365         default("leftsubnet", s["left"] "/32")
366         rightsub = ("rightsubnet" in s) ? 1 : 0
367         default("rightsubnet", s["right"] "/32")
368         default("leftfirewall", "no")
369         default("rightfirewall", "no")
370         yesno("leftfirewall")
371         yesno("rightfirewall")
372         integer("espreplay_window")
373         if (("espreplay_window" in s) && s["espreplay_window"] == 0)
374                 delete s["espreplay_window"]
375         integer("ahreplay_window")
376         if (("ahreplay_window" in s) && s["ahreplay_window"] == 0)
377                 delete s["ahreplay_window"]
378         netfix("left")
379         netfix("right")
380
381         default("leftnexthop", s["right"])
382         default("rightnexthop", s["left"])
383         if (s["leftnexthop"] == s["left"])
384                 fail("left and leftnexthop must not be the same")
385         if (s["rightnexthop"] == s["right"])
386                 fail("right and rightnexthop must not be the same")
387
388         bidir("espenckey")
389         bidir("espauthkey")
390         bidir("ahkey")
391         if ("spi" in s && "spibase" in s)
392                 fail("cannot specify both spi and spibase")
393         if (!pass) {
394                 if ("spibase" in s) {
395                         b = s["spibase"]
396                         if (b !~ /^0x[0-9a-fA-F]+0$/)
397                                 fail("bad syntax in spibase -- must be 0x...0")
398                         spibase = substr(b, 1, length(b)-1)
399                 } else {
400                         need("spi")
401                         if (s["spi"] !~ /^0x[0-9a-fA-F]+$/)
402                                 fail("bad syntax in spi -- must be 0x...")
403                 }
404         }
405         spir = 0
406         spil = 1
407
408         # who am I?
409         me = ""
410         for (addr in interface) {
411                 if (addr == s["left"] || addr == s["right"]) {
412                         if (me != "")
413                                 fail("ambiguous:  could be on \"" iface \
414                                         "\" or \"" interface[addr] "\"")
415                         me = addr
416                         iface = interface[addr]
417                 }
418         }
419         if (me == "")
420                 fail("cannot find interface for " s["left"] " or " s["right"])
421         if (other) {
422                 if (s["left"] == me)
423                         me = s["right"]
424                 else if (s["right"] == me)
425                         me = s["left"]
426         }
427         havesubnet = leftsubnet
428         if (s["right"] == me) {
429                 swap("")                # swaps "left" and "right"
430                 swap("subnet")
431                 swap("nexthop")
432                 swap("net")
433                 swap("mask")
434                 swap("firewall")
435                 swap("espspi")
436                 swap("ahspi")
437                 swap("espenckey")
438                 swap("espauthkey")
439                 swap("ahkey")
440                 swap("updown")
441                 t = spil
442                 spil = spir
443                 spir = t
444                 havesubnet = rightsubnet
445         }
446         him = s["right"]
447
448         if (s["leftnexthop"] == "%defaultroute") {
449                 if (drnexthop == "")
450                         fail("%defaultroute requested but not known")
451                 s["leftnexthop"] = drnexthop
452         }
453
454         tspi = rightward()
455         if (s["type"] == "tunnel") {
456                 espi = rightward()
457                 intspi = leftward()
458         } else
459                 espi = tspi
460         if (s["rightespspi"] != "")
461                 espi = s["rightespspi"]
462         respi = leftward()
463         if (s["leftespspi"] != "")
464                 respi = s["leftespspi"]
465         if ("ah" in s) {
466                 if ("esp" in s) {
467                         aspi = rightward()
468                         raspi = leftward()
469                 } else {
470                         aspi = espi
471                         raspi = respi
472                 }
473                 if (s["rightahspi"] != "")
474                         aspi = s["rightahspi"]
475                 if (s["leftahspi"] != "")
476                         raspi = s["leftahspi"]
477         }
478         routeid = "-net " s["rightnet"] " netmask " s["rightmask"]
479         if (s["rightmask"] == "255.255.255.255")
480                 routeid = "-host " s["rightnet"]
481
482         print "PATH=\"'"$PATH"'\""
483         print "export PATH"
484         print "PLUTO_VERSION=1.1"
485         verbsuf = (havesubnet) ? "-client" : "-host"
486         print "PLUTO_CONNECTION=" q(names)
487         print "PLUTO_NEXT_HOP=" s["leftnexthop"]
488         print "PLUTO_INTERFACE=" iface
489         print "PLUTO_ME=" me
490         print "PLUTO_MY_CLIENT=" s["leftsubnet"]
491         print "PLUTO_MY_CLIENT_NET=" s["leftnet"]
492         print "PLUTO_MY_CLIENT_MASK=" s["leftmask"]
493         print "PLUTO_PEER=" him
494         print "PLUTO_PEER_CLIENT=" s["rightsubnet"]
495         print "PLUTO_PEER_CLIENT_NET=" s["rightnet"]
496         print "PLUTO_PEER_CLIENT_MASK=" s["rightmask"]
497         print "export PLUTO_VERSION PLUTO_CONNECTION PLUTO_NEXT_HOP"
498         print "export PLUTO_INTERFACE PLUTO_ME PLUTO_MY_CLIENT"
499         print "export PLUTO_MY_CLIENT_NET PLUTO_MY_CLIENT_MASK PLUTO_PEER"
500         print "export PLUTO_PEER_CLIENT PLUTO_PEER_CLIENT_NET"
501         print "export PLUTO_PEER_CLIENT_MASK"
502
503         if (op == "--up") {
504                 print "{"
505                 # first, the outbound SAs
506                 if (s["type"] == "tunnel") {
507                         print "ipsec spi --label", q(names), "--af inet",
508                                         "--said", ("tun" tspi "@" him), "\\"
509                         print "\t--ip4", "--src", me, "--dst", him, "&&"
510                 }
511                 espspi(me, him, espi)
512                 ahspi(me, him, aspi)
513                 if (nrspi > 1) {
514                         # group them
515                         printf "ipsec spigrp --label %s --said ", q(names)
516                         if (s["type"] == "tunnel")
517                                 printf "tun%s@%s ", tspi, him
518                         if (("esp" in s))
519                                 printf "esp%s@%s ", espi, him
520                         if ("ah" in s)
521                                 printf "ah%s@%s ", aspi, him
522                         printf " &&\n"
523                 }
524                 # inbound SAs
525                 if (s["type"] == "tunnel") {
526                         print "ipsec spi --label", q(names), "--af inet",
527                                         "--said", ("tun" intspi "@" me), "\\"
528                         print "\t--ip4", "--src", him, "--dst", me, "&&"
529                 }
530                 espspi(him, me, respi)
531                 ahspi(him, me, raspi)
532                 if (nlspi > 1) {
533                         # group them
534                         printf "ipsec spigrp --label %s --said ", q(names)
535                         if (s["type"] == "tunnel")
536                                 printf "tun%s@%s ", intspi, me
537                         if (("esp" in s))
538                                 printf "esp%s@%s ", respi, me
539                         if ("ah" in s)
540                                 printf "ah%s@%s ", raspi, me
541                         printf " &&\n"
542                 }
543                 # with the SAs in place, eroute to them
544                 print "ipsec eroute --label", q(names),
545                                                 "--eraf inet --replace", "\\"
546                 if (pass)
547                         p = "%pass"
548                 else {
549                         if (s["type"] == "tunnel")
550                                 p = "tun"
551                         else if (("esp" in s))
552                                 p = "esp"
553                         else
554                                 p = "ah"
555                         p = p tspi "@" him
556                 }
557                 print "\t--src", s["leftsubnet"], "--dst", s["rightsubnet"],
558                                                         "--said", p, "&&"
559                 # with the eroute in place, NOW we can route to it
560                 #print "{ route del", routeid, "2>/dev/null ; true ; } &&"
561                 updown("prepare", "&&")
562                 #print "route add", routeid, "dev", iface, "gw",
563                 #                                       s["leftnexthop"], "&&"
564                 updown("route", "&&")
565                 # and with all processing in place, we can penetrate firewall
566                 #if (s["leftfirewall"] == "yes") {
567                 #       print "ipfwadm -F -i accept -b -S", s["leftsubnet"],
568                 #                               "-D", s["rightsubnet"], "&&"
569                 #}
570                 updown("up", "&&")
571                 print "true"
572                 print "} || {"
573         } else if (op == "--route") {
574                 #print "{ route del", routeid, "2>/dev/null ; true ; } &&"
575                 updown("prepare", "&&")
576                 #print "route add", routeid, "dev", iface, "gw",
577                 #                                       s["leftnexthop"]
578                 updown("route")
579                 exit 0
580         } else if (op == "--unroute") {
581                 #print "route del", routeid, "dev", iface, "gw",
582                 #                                       s["leftnexthop"]
583                 updown("unroute")
584                 exit 0
585         } else                  # down
586                 print "{"
587
588         # now do "down", unconditionally, since the desired output for "up"
589         # is { up && up && up && true } || { down ; down ; down }
590         # tear things down in fairly strict reverse order
591         #if (s["leftfirewall"] == "yes")
592         #       print "ipfwadm -F -d accept -b -S", s["leftsubnet"],
593         #                                       "-D", s["rightsubnet"]
594         updown("down")
595         #print "route del", routeid, "dev", iface, "gw", s["leftnexthop"]
596         print "# do not delete route"
597         print "ipsec eroute --label", q(names), "--eraf inet --del", "\\"
598         print "\t--src", s["leftsubnet"], "--dst", s["rightsubnet"]
599         #if ("ah" in s) {
600         #       print "ipsec spi --label", q(names), "--af inet", "--del",
601         #               "--said", ("ah" raspi "@" me)
602         #}
603         #if ("esp" in s) {
604         #       print "ipsec spi --label", q(names), "--af inet", "--del",
605         #               "--said", ("esp" respi "@" me)
606         #}
607         if (!pass) {
608                 if (s["type"] == "tunnel")
609                         p = "tun"
610                 else if (("esp" in s))
611                         p = "esp"
612                 else
613                         p = "ah"
614                 print "ipsec spi --label", q(names), "--af inet", "--del",
615                                 "--said", (p tspi "@" him),
616                                 "  # outbound"
617                 print "ipsec spi --label", q(names), "--af inet", "--del",
618                                 "--said", (p intspi "@" me),
619                                 "  # inbound"
620         }
621
622         if (op == "--up")
623                 print "} 2>/dev/null"
624         else
625                 print "}"
626         #########
627         }' |
628 if test $showonly
629 then
630         cat
631 else
632         sh $shopts
633 fi