~ubuntu-branches/ubuntu/hardy/openswan/hardy-updates

« back to all changes in this revision

Viewing changes to contrib/janus/janus.pl

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayrhofer
  • Date: 2005-01-27 16:10:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050127161011-idgybmyz3vwhpfiq
Tags: 2.3.0-2
Urgency HIGH due to security issue and problems with build-deps in sarge.
* Fix the security issue. Please see
  http://www.idefense.com/application/poi/display?id=190&
      type=vulnerabilities&flashstatus=false
  for more details. Thanks to Martin Schulze for informing me about
  this issue.
  Closes: #292458: Openswan XAUTH/PAM Buffer Overflow Vulnerability
* Added a Build-Dependency to lynx.
  Closes: #291143: openswan: FTBFS: Missing build dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
#
 
3
# janus - Dynamic DNS watcher for FreeS/WAN & forks
 
4
# (c) 2004 Tiago Freitas Leal <tfl@netcbo.pt>
 
5
#
 
6
# This is a fork of ipsec_monitor
 
7
# Copyright (C) 2003 by Tim Niemueller <tim@niemueller.de>
 
8
# Website: http://www.niemueller.de/software/perl/ipsecmonitor
 
9
#
 
10
# This program is free software; you can redistribute it and/or modify
 
11
# it under the terms of the GNU General Public License as published by
 
12
# the Free Software Foundation; either version 2 of the License, or
 
13
# (at your option) any later version.
 
14
#
 
15
# This program is distributed in the hope that it will be useful,
 
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
18
# GNU General Public License for more details.
 
19
#
 
20
# Version: 1.3
 
21
# Released: 17.08.2004
 
22
 
 
23
 
 
24
#### Modules
 
25
use strict;
 
26
use Getopt::Long;
 
27
use POSIX qw(setsid);
 
28
use Fcntl ':flock';
 
29
use Socket;
 
30
 
 
31
#### Constants, just to make code readable
 
32
my $VERSION="1.3";
 
33
my $ipsec="/usr/local/sbin/ipsec";
 
34
my $janus="/usr/local/bin/janus";
 
35
 
 
36
#### Get parameters
 
37
my %params=();
 
38
GetOptions("help" => \$params{'help'},
 
39
        "start" => \$params{'start'},
 
40
        "stop" => \$params{'stop'},
 
41
        "restart" => \$params{'restart'},
 
42
        "script:s" => \$params{'script'},
 
43
        "t:i" => \$params{'t'},
 
44
        "d" => \$params{'d'},
 
45
        "nolog" => \$params{'nolog'},
 
46
        "ver" => \$params{'ver'},
 
47
        ) or usage();
 
48
 
 
49
if($params{'help'} ne "") {
 
50
        usage();
 
51
}
 
52
 
 
53
if( ($params{'script'} ne "") && (! -x $params{'script'}) ) {
 
54
        failure_exit("The script file does not exist or is not executable.");
 
55
}
 
56
 
 
57
if($params{'ver'}) {
 
58
        print "janus watcher $VERSION\n";
 
59
        exit 0;
 
60
}
 
61
 
 
62
if($params{'t'} eq "") {
 
63
        $params{'t'} = 180;
 
64
}
 
65
 
 
66
#### Signals
 
67
$SIG{'TERM'} = \&terminate_daemon;
 
68
$SIG{'HUP'} = \&check_status;
 
69
 
 
70
#### Globals to make it quick and dirty
 
71
my $pid;
 
72
my $lockfile = "/var/lock/janus.lock";
 
73
my $pidfile = "/var/run/janus.pid";
 
74
my $ctlfile = "/var/run/janus.ctl";
 
75
my $cfgfile = "/etc/ipsec.conf";
 
76
 
 
77
#### Main Program, main() like
 
78
if($params{'stop'} || $params{'restart'}) { kill_daemon(); } # --stop never returns from this call
 
79
startlog("janus_run");
 
80
logmsg("info", "Starting janus watcher...");
 
81
daemonize(); # only daemon returns from this call
 
82
create_lock();
 
83
create_pid();
 
84
startlog("janus watcher[$$]");
 
85
logmsg("info", "Starting Janus - Dynamic DNS watcher (Version $VERSION)");
 
86
 
 
87
make_ctl_file();
 
88
 
 
89
while (1) {
 
90
        sleep $params{'t'};
 
91
        check_ctl_file();
 
92
}
 
93
 
 
94
 
 
95
#### Subs related to reading and writting configuration and control files
 
96
 
 
97
sub check_ctl_file {
 
98
        my $newadd;
 
99
        my $action; # 0 = none; 1 = replace; 2 = replace&pullup; 3 = add; 4 = restart
 
100
        open (CTL, "$ctlfile") or failure_exit("unable to open control file");
 
101
        my @temp = <CTL>;
 
102
        close (CTL);
 
103
        open(CTL,">$ctlfile") or failure_exit("unable to open control file");
 
104
        flock(CTL, LOCK_EX);
 
105
 
 
106
        my $line;
 
107
        foreach $line (@temp) {
 
108
                chomp ($line);
 
109
                my @temp = split(/\,/,$line);
 
110
                $action = 0;
 
111
                if($temp[1]) {
 
112
                        if($newadd = gethostbyname($temp[1])) {
 
113
                                $newadd = join(".", unpack('C4', $newadd));
 
114
                                if($temp[2] ne $newadd) {
 
115
                                        # Left address has changed, must update connection
 
116
                                        if($temp[0] eq '%local') {
 
117
                                                logmsg("info", "local dynamic: host \"$temp[1]\" changed IP $temp[2] to $newadd");
 
118
                                                $action = 4; # restart only if local dynamic changed
 
119
                                        } else {
 
120
                                                logmsg("info", "\"$temp[0]\": host \"$temp[1]\" changed IP $temp[2] to $newadd");
 
121
                                                $action = 1;
 
122
                                                if($temp[5] eq 'start') {
 
123
                                                        $action = 2;
 
124
                                                }
 
125
                                                if(!$temp[2]) {$action = 3;}
 
126
                                        }
 
127
                                        $temp[2] = $newadd;
 
128
                                }
 
129
                        }
 
130
                }
 
131
                if($temp[3]) {
 
132
                        if($newadd = gethostbyname($temp[3])) {
 
133
                                $newadd = join(".", unpack('C4', $newadd));
 
134
                                if($temp[4] ne $newadd) {
 
135
                                        # Right address has changed, must update connection
 
136
                                        logmsg("info", "\"$temp[0]\": host \"$temp[3]\" changed IP $temp[4] to $newadd");
 
137
                                        if(!$action) {
 
138
                                                $action = 1; # replace only if no action for left side
 
139
                                                if($temp[5] eq 'start') {
 
140
                                                        $action = 2; # replace&pullup only if no action for left side
 
141
                                                }
 
142
                                        }
 
143
                                        if(!$temp[4]) {$action = 3;}
 
144
                                        $temp[4] = $newadd;
 
145
                                }
 
146
                        }
 
147
                }
 
148
                if($action) {
 
149
                        if($action eq 1) {
 
150
                                logmsg("info", "\"$temp[0]\": replacing connection");
 
151
                                system("$ipsec auto --rereadall");
 
152
                                system("$ipsec auto --replace $temp[0]");
 
153
                        } elsif($action eq 2) {
 
154
                                logmsg("info", "\"$temp[0]\": replacing and pulling up connection");
 
155
                                system("$ipsec auto --rereadall");
 
156
                                system("$ipsec auto --replace $temp[0]");
 
157
                                system("$ipsec auto --up $temp[0]");
 
158
                        } elsif($action eq 3) {
 
159
                                logmsg("info", "\"$temp[0]\": adding connection");
 
160
                                system("$ipsec auto --rereadall");
 
161
                                system("$ipsec auto --add $temp[0]");
 
162
                        } elsif($action eq 4) {
 
163
                                logmsg("info", "Restarting IPSec and janus...");
 
164
                                system("$ipsec setup --restart");
 
165
                                system("$janus --restart");
 
166
                        }
 
167
                        if($params{'script'}) {
 
168
                                # We have a script file, wait 60 seconds and then execute it
 
169
                                sleep 60;
 
170
                                system($params{'script'});
 
171
                        }
 
172
                }
 
173
                print CTL "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5]\n";
 
174
        }
 
175
        close (CTL);
 
176
}
 
177
 
 
178
sub make_ctl_file {
 
179
        my $section = '';
 
180
        my $conn;
 
181
        my %default;
 
182
        my $auto;
 
183
        my $leftconn;
 
184
        my $left;
 
185
        my $x_leftdynamic;
 
186
        my $right;
 
187
        my $x_rightdynamic;
 
188
        my $addleft;
 
189
        my $addright;
 
190
        open(CTL,">$ctlfile") or failure_exit("unable to open control file");
 
191
        flock(CTL, LOCK_EX);
 
192
        open (CONFIG, "$cfgfile") or failure_exit("unable to open config file");
 
193
        my @temp = <CONFIG>;
 
194
        close (CONFIG);
 
195
        my $line;
 
196
        foreach $line(@temp) {
 
197
                chomp ($line);
 
198
                my @temp = split(/[\t= ]+/,$line);
 
199
                if($temp[0]) {
 
200
                        if(($section ne '') && ($temp[0] eq 'conn')) {
 
201
                                $section = 'conn';
 
202
                                $conn = $temp[1];
 
203
                        } else {
 
204
                                if($temp[0] eq 'config' && $temp[1] eq 'setup') {
 
205
                                        $section = 'conn';
 
206
                                        $conn = '%local';
 
207
                                }
 
208
                        }
 
209
                } elsif(!$temp[1]) {
 
210
                        if($section ne 'end') {
 
211
                                if($conn eq '%default') {
 
212
                                        $default{'left'} = $left;
 
213
                                        $default{'x_leftdynamic'} = $x_leftdynamic;
 
214
                                        $default{'right'} = $right;
 
215
                                        $default{'x_rightdynamic'} = $x_rightdynamic;
 
216
                                        $default{'auto'} = $auto;
 
217
                                        $left = '';
 
218
                                        $x_leftdynamic = '';
 
219
                                        $right = '';
 
220
                                        $x_rightdynamic = '';
 
221
                                        $auto ='';
 
222
                                } else {
 
223
                                        if(!$left){ $left = $default{'left'}; }
 
224
                                        if(!$x_leftdynamic){ $x_leftdynamic = $default{'x_leftdynamic'}; }
 
225
                                        if(!$right){ $right = $default{'right'}; }
 
226
                                        if(!$x_rightdynamic){ $x_rightdynamic = $default{'x_rightdynamic'}; }
 
227
                                        if(!$auto){ $auto = $default{'auto'}; }
 
228
                                }
 
229
                                if($x_leftdynamic eq 'yes') {
 
230
                                        if($conn eq '%local') {
 
231
                                                $leftconn = "local dynamic";
 
232
                                        } else {
 
233
                                                $leftconn = $conn;
 
234
                                        }
 
235
                                        if(!&validip($left) && $left && $left ne '%any') {
 
236
                                                if($addleft = gethostbyname($left)) {
 
237
                                                        $addleft = join(".", unpack('C4', $addleft));
 
238
                                                        logmsg("info", "\"$leftconn\": watching host \"$left\" on $addleft");
 
239
                                                } else {
 
240
                                                        logmsg("info", "\"$leftconn\": name lookup failed for host \"$left\"");
 
241
                                                }
 
242
                                        } else {
 
243
                                                logmsg("info", "\"$leftconn\": ignoring host \"$left\"");
 
244
                                                $left = '';
 
245
                                        }
 
246
                                } else {
 
247
                                                $left = '';
 
248
                                }
 
249
                                if($x_rightdynamic eq 'yes') {
 
250
                                        if(!&validip($right) && $right && $right ne '%any') {
 
251
                                                if($addright = gethostbyname($right)) {
 
252
                                                        $addright = join(".", unpack('C4', $addright));
 
253
                                                        logmsg("info", "\"$conn\": watching host \"$right\" on $addright");
 
254
                                                } else {
 
255
                                                        logmsg("info", "\"$conn\": name lookup failed for host \"$right\"");
 
256
                                                }
 
257
                                        } else {
 
258
                                                logmsg("info", "\"$conn\": ignoring host \"$right\"");
 
259
                                                $right = '';
 
260
                                        }
 
261
                                } else {
 
262
                                                $right = '';
 
263
                                }
 
264
                                if($left ne '' || $right ne '') {
 
265
                                        print CTL "$conn,$left,$addleft,$right,$addright,$auto\n";
 
266
                                }
 
267
                                $auto = '';
 
268
                                $left = '';
 
269
                                $x_leftdynamic = '';
 
270
                                $addleft ='';
 
271
                                $right = '';
 
272
                                $x_rightdynamic = '';
 
273
                                $addright = '';
 
274
                                $section = 'end';
 
275
                        }
 
276
                } else {
 
277
                        if($conn eq '%local') {
 
278
                                if($temp[1] eq 'x_localdynamic') {
 
279
                                        $left = $temp[2];
 
280
                                        $x_leftdynamic = 'yes';
 
281
                                }
 
282
                        } else {
 
283
                                if($temp[1] eq 'left') {
 
284
                                        $left = $temp[2];
 
285
                                } elsif($temp[1] eq 'right') {
 
286
                                        $right = $temp[2];
 
287
                                } elsif($temp[1] eq 'x_leftdynamic') {
 
288
                                        $x_leftdynamic = $temp[2];
 
289
                                } elsif($temp[1] eq 'x_rightdynamic') {
 
290
                                        $x_rightdynamic = $temp[2];
 
291
                                } elsif($temp[1] eq 'auto') {
 
292
                                        $auto = $temp[2];
 
293
                                }
 
294
                        }
 
295
                }
 
296
        }
 
297
        flock(CTL, LOCK_UN);
 
298
        close (CTL);
 
299
}
 
300
 
 
301
sub validip {
 
302
        my $ip = $_[0];
 
303
        if(!($ip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)) {
 
304
                return 0; }
 
305
        else {
 
306
                my @octets = ($1, $2, $3, $4);
 
307
                foreach $_ (@octets) {
 
308
                        if(/^0./) {
 
309
                                return 0; }
 
310
                        if($_ < 0 || $_ > 255) {
 
311
                                return 0;
 
312
                        }
 
313
                }
 
314
                return 1;
 
315
        }
 
316
}
 
317
 
 
318
#### Subs related to basic program stuff (daemon, fifo, lock etc.)
 
319
 
 
320
# Could be modified to syslog for example
 
321
sub startlog {
 
322
        unless ($params{'nolog'}) {
 
323
                use Sys::Syslog qw(:DEFAULT setlogsock);
 
324
                setlogsock('unix');
 
325
                openlog($_[0], "", "authpriv");
 
326
        }
 
327
}
 
328
 
 
329
sub logmsg {
 
330
        my $priority = shift;
 
331
        my $msg = shift;
 
332
 
 
333
        if($params{'d'}) {
 
334
                my $now=localtime();
 
335
                print "$now ($priority): $msg, @_\n";
 
336
        } else {
 
337
                unless ($params{'nolog'}) {
 
338
                        syslog($priority, $msg, @_);
 
339
                }
 
340
        }
 
341
}
 
342
 
 
343
# logs the errors and exits the program
 
344
sub failure_exit {
 
345
        logmsg("info",$_[0]);
 
346
        die $_[0];
 
347
}
 
348
 
 
349
 
 
350
# Disconnects from console
 
351
sub daemonize {
 
352
        if(! $params{'d'}) {
 
353
                chdir '/' or failure_exit("Can't chdir to /: $!");
 
354
                open STDIN, '/dev/null' or failure_exit("daemonize: Can't read /dev/null: $!");
 
355
                open STDOUT, '>/dev/null' or failure_exit("daemonize: Can't write to /dev/null: $!");
 
356
                defined($pid = fork) or failure_exit("Can't fork: $!");
 
357
                exit 0 if $pid;
 
358
                setsid() or failure_exit("Can't start a new session: $!");
 
359
        }
 
360
}
 
361
 
 
362
# creates the lockfile
 
363
sub create_lock {
 
364
        open(LOCK, ">$lockfile");
 
365
        my $ok = flock(LOCK, LOCK_EX | LOCK_NB);
 
366
        print LOCK $$;
 
367
        failure_exit("LOCK janus is already running") if(! $ok);
 
368
}
 
369
 
 
370
# removes the lockfile
 
371
sub remove_lock {
 
372
        flock(LOCK, LOCK_UN);
 
373
        close(LOCK);
 
374
        unlink $lockfile;
 
375
}
 
376
 
 
377
# creates the pidfile
 
378
sub create_pid {
 
379
        open(PID, ">$pidfile");
 
380
        my $ok = flock(PID, LOCK_EX | LOCK_NB);
 
381
        print PID "$$\n";
 
382
        failure_exit("PID janus is already running") if(! $ok);
 
383
        flock(PID, LOCK_UN);
 
384
        flock(PID, LOCK_EX | LOCK_NB);
 
385
}
 
386
 
 
387
# removes the pidfile
 
388
sub remove_pid {
 
389
        flock(PID, LOCK_UN);
 
390
        close(PID);
 
391
        unlink $pidfile;
 
392
}
 
393
 
 
394
# kills the daemon
 
395
sub kill_daemon {
 
396
        open(FILE, "$pidfile");
 
397
        $pid = <FILE>; chop $pid;
 
398
        close (FILE);
 
399
        if($pid != 0) {
 
400
                system ("/bin/kill $pid");
 
401
                if($params{'stop'}) { exit; }
 
402
        }
 
403
        if($params{'stop'}) { failure_exit("janus isn't running"); }
 
404
}
 
405
 
 
406
# Terminates daemon closing ISDN connection,
 
407
# used as signal handler
 
408
sub terminate_daemon {
 
409
        alarm 0;        # Stop timer
 
410
        remove_lock();
 
411
        remove_pid();
 
412
        unlink $ctlfile;
 
413
        logmsg("info", "Closing down");
 
414
        unless ($params{'nolog'}) {
 
415
                closelog();
 
416
        }
 
417
        exit;
 
418
}
 
419
 
 
420
# prints some basic usage message
 
421
sub usage {
 
422
        print "janus v.$VERSION (c) 2004 by Tiago Freitas Leal\n",
 
423
        "janus is a fork of ipsec_monitor v.0.1 (c) 2003 by Tim Niemueller\n",
 
424
        "Watches dynamic DNS hosts and replaces the connection when the IP\n",
 
425
        "address changes.\n",
 
426
        "Usage:\n",
 
427
        "janus [--script=SCRIPT -t t -d -nolog]\n",
 
428
        "     Starts janus.\n",
 
429
        "janus --restart [--script=SCRIPT -t t -d -nolog]\n",
 
430
        "     Kills the present janus task and starts a new one.\n",
 
431
        "janus --stop\n",
 
432
        "     Stops janus.\n",
 
433
        "Options:\n",
 
434
        "     --script=SCRIPT: Path to an additional script that is executed\n",
 
435
        "                      1 minute after the connection has been replaced.\n",
 
436
        "                      For example routing stuff that needs to be done.\n",
 
437
        "                      Script must be executable!\n",
 
438
        "     -t t: Checks every t seconds if connection parameters have changed.\n",
 
439
        "           Default is 180 seconds\n",
 
440
        "     -d: Debug mode. Do not fork to background, log output to STDOUT.\n",
 
441
        "     --nolog: Don't log.\n\n";
 
442
        "janus --ver\n",
 
443
        "     Outputs version information.\n",
 
444
        exit 0;
 
445
}
 
446
 
 
447
 
 
448
### END.