root/fwknop/tags/fwknop-0.9.7-pre1/fwknop_serv

Revision 475, 3.4 kB (checked in by mbr, 2 years ago)

bugfix to drop privs after binding to the server socket

  • 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     ### write our pid out to disk
90     &writepid();
91
92     return;
93 }
94
95 sub validate_config() {
96     unless ($config{'TCPSERV_PORT'} > 0
97             and $config{'TCPSERV_PORT'} < 65535) {
98         die "[*] TCPSERV_PORT must be between 1 and 65535";
99     }
100     return;
101 }
102
103 sub required_vars() {
104     for my $var (@required_vars) {
105         unless (defined $config{$var}) {
106             die "[*] Variable $var is not defined in $config_file";
107         }
108     }
109     return;
110 }
111
112 sub uniquepid() {
113     if (-e $config{'TCPSERV_PID_FILE'}) {
114         my $caller = $0;
115         open PIDFILE, "< $config{'TCPSERV_PID_FILE'}";
116         my $pid = <PIDFILE>;
117         close PIDFILE;
118         chomp $pid;
119         if (kill 0, $pid) {  # fwknop_serv is already running
120             die "[*] fwknop_serv (pid: $pid) is already running!  Exiting.\n";
121         }
122     }
123     return;
124 }
125
126 sub writepid() {
127     open P, "> $config{'TCPSERV_PID_FILE'}" or die "[*] Could not open ",
128         "$config{'TCPSERV_PID_FILE'}: $!";
129     print P $$, "\n";
130     close P;
131     chmod 0600, $config{'TCPSERV_PID_FILE'};
132     return;
133 }
134
135 sub import_config() {
136     open C, "< $config_file" or die "[*] Could not open ",
137         "config file $config_file: $!";
138     while (<C>) {
139         next if /^\s*#/;
140         for my $var (@required_vars) {
141             if (/^\s*$var\s+(\S+);/) {
142                 $config{$var} = $1;
143             }
144         }
145     }
146     close C;
147     return;
148 }
Note: See TracBrowser for help on using the browser.