root/fwknop/tags/fwknop-1.9.3/fwknop_serv

Revision 495, 3.5 kB (checked in by mbr, 2 years ago)

bugfix to make sure that duplicate fwknop_serv processes can not be started

  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1 #!/usr/bin/perl -w
2 #
3 ############################################################################
4 #
5 # File: fwknop_serv
6 #
7 # Purpose: To provide a minimal TCP server over which the fwknop client can
8 #          connect to send the SPA packet.  This breaks the traditional SPA
9 #          model of only using a single packet to transmit desired access
10 #          modifications, but if you want to send SPA packets over the Tor
11 #          network then this server is necessary.  A circuit through the
12 #          Tor network is built up over successive TCP connections, and
13 #          there is no way to send packets through Tor without an
14 #          established circuit.
15 #
16 ############################################################################
17 #
18 # $Id$
19 #
20
21 use IO::Socket;
22 use POSIX;
23 use strict;
24
25 my $config_file = '/etc/fwknop/fwknop.conf';
26 my %config = ();
27
28 my @required_vars = qw(
29     TCPSERV_PORT
30     TCPSERV_PID_FILE
31 );
32
33 &setup();
34
35 my $server = IO::Socket::INET->new(
36     LocalPort => $config{'TCPSERV_PORT'},
37     Type   => SOCK_STREAM,
38     Reuse  => 1,
39     Listen => 5
40 ) or die $!;
41
42 &drop_privs();
43
44 ### trivial loop; we just want the local TCP stack to accept connections;
45 ### fwknopd gets it data from pcap anyway
46 while (my $client = $server->accept()) {
47
48     $client->recv(my $request, 1500, 0);
49 }
50
51 close $server;
52
53 exit 0;
54
55 #================================= end main ===============================
56
57 sub drop_privs() {
58
59     my ($login, $pass, $uid, $gid) = getpwnam('nobody');
60     unless ($uid and $gid) {
61         warn "[-] Could not get UID and GID of user nobody";
62     }
63
64     ### drop privileges
65     if ($uid and $gid) {
66         POSIX::setuid($uid);
67         POSIX::setgid($gid);
68     }
69
70     return;
71 }
72
73 sub setup() {
74
75     ### import config
76     &import_config();
77
78     ### make sure all the vars we need are actually in the config file.
79     &required_vars();
80
81     ### validate config
82     &validate_config();
83
84     my $pid = fork();
85     exit 0 if $pid;
86     die "[*] $0: Couldn't fork: $!" unless defined $pid;
87     POSIX::setsid() or die "[*] $0: Can't start a new session: $!";
88
89     ### make sure there isn't another fwknop_serv process already running
90     &uniquepid();
91
92     ### write our pid out to disk
93     &writepid();
94
95     return;
96 }
97
98 sub validate_config() {
99     unless ($config{'TCPSERV_PORT'} > 0
100             and $config{'TCPSERV_PORT'} < 65535) {
101         die "[*] TCPSERV_PORT must be between 1 and 65535";
102     }
103     return;
104 }
105
106 sub required_vars() {
107     for my $var (@required_vars) {
108         unless (defined $config{$var}) {
109             die "[*] Variable $var is not defined in $config_file";
110         }
111     }
112     return;
113 }
114
115 sub uniquepid() {
116     if (-e $config{'TCPSERV_PID_FILE'}) {
117         my $caller = $0;
118         open PIDFILE, "< $config{'TCPSERV_PID_FILE'}";
119         my $pid = <PIDFILE>;
120         close PIDFILE;
121         chomp $pid;
122         if (kill 0, $pid) {  # fwknop_serv is already running
123             die "[*] fwknop_serv (pid: $pid) is already running!  Exiting.\n";
124         }
125     }
126     return;
127 }
128
129 sub writepid() {
130     open P, "> $config{'TCPSERV_PID_FILE'}" or die "[*] Could not open ",
131         "$config{'TCPSERV_PID_FILE'}: $!";
132     print P $$, "\n";
133     close P;
134     chmod 0600, $config{'TCPSERV_PID_FILE'};
135     return;
136 }
137
138 sub import_config() {
139     open C, "< $config_file" or die "[*] Could not open ",
140         "config file $config_file: $!";
141     while (<C>) {
142         next if /^\s*#/;
143         for my $var (@required_vars) {
144             if (/^\s*$var\s+(\S+);/) {
145                 $config{$var} = $1;
146             }
147         }
148     }
149     close C;
150     return;
151 }
Note: See TracBrowser for help on using the browser.