8 use strict; |
8 use strict; |
9 use warnings; |
9 use warnings; |
10 use Getopt::Long qw(:config no_ignore_case bundling); |
10 use Getopt::Long qw(:config no_ignore_case bundling); |
11 use Pod::Usage; |
11 use Pod::Usage; |
12 use File::Basename; |
12 use File::Basename; |
|
13 use English qw(-no_match_vars); |
|
14 |
|
15 ($EUID, $UID) = ($UID, $EUID); # release ROOT |
|
16 ($0) = ($0 =~ /(\w+)/); # untaint $0 |
13 |
17 |
14 use constant ME => basename $0; |
18 use constant ME => basename $0; |
|
19 |
|
20 delete @ENV{ grep /PATH/, keys %ENV }; |
|
21 $ENV{PATH} = "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin"; |
15 |
22 |
16 ### |
23 ### |
17 ### STEP 0 :: Verify that we have the necessary requirements. |
24 ### STEP 0 :: Verify that we have the necessary requirements. |
18 ### |
25 ### |
19 ### This script requires recent versions of Perl, OpenSSL and PPPD (including |
26 ### This script requires recent versions of Perl, OpenSSL and PPPD (including |
30 |
37 |
31 # Default values for the FQDN or IP of the FirePass we wish to connect to, the |
38 # Default values for the FQDN or IP of the FirePass we wish to connect to, the |
32 # name of our Network Access favorite, and our username/pasword. All of these |
39 # name of our Network Access favorite, and our username/pasword. All of these |
33 # can be passed as arguments, if desired. |
40 # can be passed as arguments, if desired. |
34 |
41 |
35 my $user; |
42 my $opt_user; |
36 my $passcode; |
43 my $opt_passcode; |
37 my $opt_host = 'connectwdf.sap.com'; |
44 my $opt_host = 'connectwdf.sap.com'; |
38 my $opt_name = 'SAP Network Access'; |
45 my $opt_name = 'SAP Network Access'; |
39 my $opt_help = 0; |
46 my $opt_help = 0; |
40 my $opt_man = 0; |
47 my $opt_man = 0; |
41 my @ppp_opts = (); |
48 my @ppp_opts = (); |
43 my $opt_script; |
50 my $opt_script; |
44 |
51 |
45 MAIN: { |
52 MAIN: { |
46 |
53 |
47 GetOptions( |
54 GetOptions( |
48 "u|user=s" => \$user, |
55 "u|user=s" => \$opt_user, |
49 "p|passcode=s" => \$passcode, |
56 "p|passcode=s" => \$opt_passcode, |
50 "H|host=s" => \$opt_host, |
57 "H|host=s" => \$opt_host, |
51 "n|favorite=s" => \$opt_name, |
58 "n|favorite=s" => \$opt_name, |
52 "d|debug" => \$opt_debug, |
59 "d|debug" => \$opt_debug, |
53 "o|opts=s" => \@ppp_opts, |
60 "o|opts=s" => \@ppp_opts, |
54 "h|help" => \$opt_help, |
61 "h|help" => \$opt_help, |
55 "m|man" => \$opt_man, |
62 "m|man" => \$opt_man, |
56 "s|script" => \$opt_script, |
63 "s|script" => \$opt_script, |
57 ) or pod2usage(); |
64 ) or pod2usage(); |
58 |
65 |
59 die ME . ": need to run with root permissions!\n" if $> != 0; |
|
60 |
|
61 pod2usage(-verbose => 1, -exitval => 0) if $opt_help; |
66 pod2usage(-verbose => 1, -exitval => 0) if $opt_help; |
62 pod2usage(-verbose => 2, -exitval => 0) if $opt_man; |
67 pod2usage(-verbose => 2, -exitval => 0) if $opt_man; |
63 pod2usage(-verbose => 0, -exitval => 0) if not defined $user; |
68 pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_user; |
64 |
69 |
65 if (not defined $passcode) { |
70 (my $user) = ($opt_user =~ /([a-z]\d+)/i); |
|
71 die ME . ": username \"$opt_user\" didn't pass verification\n" |
|
72 if $user ne $opt_user; |
|
73 |
|
74 die ME . ": need to run with root permissions!\n" |
|
75 if not $EUID == 0 || $UID == 0; |
|
76 |
|
77 if (not defined $opt_passcode) { |
66 chomp(my $settings = qx{stty "-g"}); |
78 chomp(my $settings = qx{stty "-g"}); |
67 open(IN, "/dev/tty") or die ME . ": Can't open /dev/tty: $!\n"; |
79 open(IN, "/dev/tty") or die ME . ": Can't open /dev/tty: $!\n"; |
68 print "Passcode: "; |
80 print "Passcode for $opt_user: "; |
69 system stty => "-echo"; |
81 system stty => "-echo"; |
70 chomp($passcode = <IN>); |
82 chomp($opt_passcode = <IN>); |
71 system stty => $settings; |
83 system stty => $settings; |
72 print "\n"; |
84 print "\n"; |
73 } |
85 } |
74 |
86 |
75 pod2usage(-verbose => 0, -exitval => 0) if not defined $passcode; |
87 pod2usage(-verbose => 0, -exitval => 0) if not defined $opt_passcode; |
|
88 (my $passcode) = ($opt_passcode =~ /(\d+)/i); |
|
89 die ME . ": passcode didn't pass verification\n" |
|
90 if $passcode ne $opt_passcode; |
|
91 |
76 -x $opt_script |
92 -x $opt_script |
77 or die ME . ": Script $opt_script is not executable: $!\n" |
93 or die ME . ": Script $opt_script is not executable: $!\n" |
78 if defined $opt_script; |
94 if defined $opt_script; |
79 |
95 |
80 push @ppp_opts, "nodetach" if $opt_debug; |
96 push @ppp_opts, "nodetach" if $opt_debug; |
162 # pages/objects. It's time to start our SSL VPN connection. To do this, we are |
178 # pages/objects. It's time to start our SSL VPN connection. To do this, we are |
163 # simply calling PPPD, and having it use OpenSSL as a psuedo terminal device. |
179 # simply calling PPPD, and having it use OpenSSL as a psuedo terminal device. |
164 $request = "GET /myvpn?sess=${sessionid} HTTP/1.0\r\n" |
180 $request = "GET /myvpn?sess=${sessionid} HTTP/1.0\r\n" |
165 . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n"; |
181 . "Cookie: MRHSession=${sessionid}\r\n" . "\r\n"; |
166 $request = "chat -v '' '${request}'"; |
182 $request = "chat -v '' '${request}'"; |
167 system( |
183 |
168 pppd => @ppp_opts, |
184 { |
169 pty => ${openssl}, |
185 local $EUID = $UID; # get ROOT, the pppd want's to see |
170 connect => ${request}, |
186 # the UID and the EUID to be ROOT |
171 linkname => "sap-vpn", |
187 system( |
172 qw(noauth crtscts passive noproxyarp |
188 pppd => @ppp_opts, |
173 local), |
189 pty => ${openssl}, |
174 ); |
190 connect => ${request}, |
|
191 linkname => "sap-vpn", |
|
192 qw(noauth crtscts passive noproxyarp |
|
193 local), |
|
194 ); |
|
195 } |
175 |
196 |
176 # Voila! We should now have a PPP connection running over SSL. We can exit |
197 # Voila! We should now have a PPP connection running over SSL. We can exit |
177 # from this script cleanly, and move on to setting up routes to the remote |
198 # from this script cleanly, and move on to setting up routes to the remote |
178 # network using our favorite networking tools. Happy hacking! |
199 # network using our favorite networking tools. Happy hacking! |
179 |
200 |