]> git.xonotic.org Git - xonotic/xonotic.git/blob - misc/infrastructure/keygen/response.d0ir
3396ce1e97905d9dda5013eb6d30a24f452e603d
[xonotic/xonotic.git] / misc / infrastructure / keygen / response.d0ir
1 #!/usr/bin/perl
2
3 BEGIN
4 {
5         $ENV{PATH} = "/usr/bin:/bin";
6 }
7
8 # if we are suid, set uid := euid
9 $( = $);
10 $< = $>;
11
12 use strict;
13 use CGI;
14 use LWP::Simple;
15 use MIME::Base64;
16 use File::Temp;
17 use DBI;
18 my $cgi = CGI->new();
19
20 sub error($)
21 {
22         my ($err) = @_;
23         print "Content-type: text/plain\n\nd0er $err";
24         exit 0;
25 }
26
27 sub check_ipfiles($)
28 {
29         my ($dir) = @_;
30         my $ip = $ENV{REMOTE_ADDR};
31         return 0 if -f "$dir/$ip";
32         return -1;
33 }
34
35 sub check_dnsbl($$@)
36 {
37         my ($goodpatterns, $badpatterns, $list) = @_;
38
39         my $name = $ENV{REMOTE_HOST} . ".";
40         my $addr = $ENV{REMOTE_ADDR};
41
42         # check goodpatterns
43         for(@$goodpatterns)
44         {
45                 if($name =~ /^(??{$_})$/ || $addr =~ /^(??{$_})$/)
46                 {
47                         return 0;
48                 }
49         }
50         # check badpatterns
51         for(@$badpatterns)
52         {
53                 if($name =~ /^(??{$_})$/ || $addr =~ /^(??{$_})$/)
54                 {
55                         warn "$addr/$name blocked by $_";
56                         return -1;
57                 }
58         }
59
60         # is he tor?
61         my $h = gethostbyname $addr;
62         if(not defined $h)
63         {
64                 warn "$addr blocked by gethostbyname()";
65                 return -1;
66         }
67         
68         my $blprefix = join '.', reverse unpack 'C4', $h;
69         my $i = 0;
70         for(@$list)
71         {
72                 ++$i;
73                 my $hn = "$blprefix.$_.";
74                 my $h2 = gethostbyname $hn;
75                 next
76                         if not defined $h2;
77                 my $h2_text = join '.', reverse unpack 'C4', $h2;
78                 warn "$addr blocked by $hn -> $h2_text";
79                 return -1;
80         }
81
82         return 0;
83 }
84
85 # create table ip ( id INT AUTO_INCREMENT PRIMARY KEY, ip VARCHAR(64), t DATETIME, error BOOLEAN, INDEX(ip), INDEX(t), INDEX(error) );
86 our $__CACHED_DBH__;
87
88 sub check_ip_record
89 {
90         my ($DBH, $tbl, $ip) = @_;
91         my $status = $DBH->selectrow_arrayref("select count(*) from $tbl where ip=? and error=false and t>date_sub(now(), interval 7 day)", undef, $ip)
92                 or die "DBI/DBD: $!";
93         return $status->[0];
94 }
95 sub insert_ip_record
96 {
97         my ($DBH, $tbl, $ip) = @_;
98         my $status = $DBH->selectall_arrayref("select error, t>date_sub(now(), interval 7 day) from $tbl where ip=?", undef, $ip)
99                 or die "DBI/DBD: $!";
100         if(@$status)
101         {
102                 if($status->[0][0] || !$status->[0][1]) # error, or after interval
103                 {
104                         $DBH->do("update $tbl set error=false, t=now() where ip=?", undef, $ip);
105                         return 0;
106                 }
107                 else # too soon
108                 {
109                         return 1;
110                 }
111         }
112         else
113         {
114                 $DBH->do("insert into $tbl(ip, error, t) values(?, false, now())", undef, $ip);
115                 return 0;
116         }
117 }
118 sub delete_ip_record
119 {
120         my ($DBH, $tbl, $ip) = @_;
121         $DBH->do("update $tbl set error=true where ip=?", undef, $ip);
122 }
123
124 sub check_sql($$$$$$$$$)
125 {
126         my ($dsn, $u, $p, $tbl, $per32, $per24, $per16, $per8, $inc) = @_;
127         my $ip = $ENV{REMOTE_ADDR};
128         my $DBH = ($__CACHED_DBH__ ? $__CACHED_DBH__ : ($__CACHED_DBH__ = DBI->connect($dsn, $u, $p, { RaiseError => 1, AutoCommit => 0 })))
129                 or die "DBI/DBD: $!";
130         eval {
131                 $DBH->do("set character set utf8");
132                 $DBH->do("set names utf8");
133                 $DBH->do("set time_zone = '+0:00'");
134         } or do {
135                 undef $__CACHED_DBH__;
136                 die $@;
137         };
138         if($inc < 0)
139         {
140                 delete_ip_record($DBH, $tbl, $ip);
141                 $DBH->commit();
142                 $DBH->disconnect();
143                 return 0;
144         }
145         elsif($inc == 0)
146         {
147                 my $status = check_ip_record($DBH, $tbl, $ip);
148                 $DBH->disconnect();
149                 if ($status)
150                 {
151                         warn "$ip blocked by SQL";
152                 }
153                 return $status;
154         }
155         else
156         {
157                 my $status = insert_ip_record($DBH, $tbl, $ip);
158                 $DBH->commit();
159                 $DBH->disconnect();
160                 if ($status)
161                 {
162                         warn "$ip blocked by SQL";
163                 }
164                 return $status;
165         }
166 }
167
168 sub check_banlist($)
169 {
170         my ($s) = @_;
171         my $ip = $ENV{REMOTE_ADDR};
172         my @s = split /\n/, get $s;
173         for(0..@s/4-1)
174         {
175                 my $i = $s[4*$_];
176                 if("$ip." =~ /^\Q$i\E\./)
177                 {
178                         warn "$ip blocked by SQL";
179                         return 1;
180                 }
181         }
182         return 0;
183 }
184
185 our %ca = ();
186 our $default_ca = 0;
187
188 do './config.pl';
189
190 if((my $key = $cgi->param('key')))
191 {
192         local $| = 1;
193         undef local $/;
194
195         my $ca = $cgi->param('ca');
196         $ca = $default_ca if not defined $ca;
197         error "Invalid CA" if not defined $ca{$ca};
198         error "Not allowed" if not $ca{$ca}->{check}->(1);
199         my $tempfh = undef;
200         eval
201         {
202                 $tempfh = File::Temp->new();
203                 binmode $tempfh;
204                 my $fh = $cgi->upload('key');
205                 if($fh)
206                 {
207                         binmode $fh;
208                         print $tempfh $_ for <$fh>;
209                 }
210                 else
211                 {
212                         $key =~ s/ /+/g;
213                         $key = decode_base64($key);
214                         print $tempfh $key;
215                 }
216                 seek $tempfh, 0, 0;
217
218                 $ENV{REQUESTFILE} = $tempfh->filename;
219                 $ENV{RESPONSEFILE} = $tempfh->filename;
220                 $ENV{SECRET} = "key_$ca.d0sk";
221                 open my $errfh, '-|', './crypto-keygen-standalone -P "$SECRET" -j "$REQUESTFILE" -o "$RESPONSEFILE" 2>&1'
222                         or die "cannot start crypto-keygen-standalone";
223                 my $err = <$errfh>;
224                 close $errfh
225                         or die "crypto-keygen-standalone failed: $err";
226                 1;
227         }
228         or do
229         {
230                 $ca{$ca}->{check}->(-1);
231                 die "$@";
232         };
233
234         print "Content-type: application/octet-stream\n\n";
235         binmode STDOUT;
236         print for <$tempfh>;
237 }
238 else
239 {
240         print <<EOF;
241 Content-type: text/html
242
243 <!doctype html>
244 <html>
245 <head>
246         <title>Xonotic keygen</title>
247 </head>
248 <body>
249         <h1>Xonotic keygen</h1>
250         <form action="response.d0ir" method="post" enctype="multipart/form-data">
251         To generate and sign a key IN GAME, follow these steps on the console:
252         <ol>
253                 <li>crypto_keygen $default_ca http://ca.xonotic.org/?ca=$default_ca&amp;key=</li>
254         </ol>
255         To generate and sign a key MANUALLY, follow these steps on a UNIX command line:
256         <ol>
257                 <li>./crypto-keygen-standalone -p key_$default_ca.d0pk -o key_$default_ca.d0si</li>
258                 <li>./crypto-keygen-standalone -p key_$default_ca.d0pk -I key_$default_ca.d0si -o request.d0iq -O camouflage.d0ic
259                 <li>Upload the request.d0iq file: <input type="file" name="key"><input type="submit"></li>
260                 <li>Save the response.d0ir file you are getting</li>
261                 <li>./crypto-keygen-standalone -p key_$default_ca.d0pk -I key_$default_ca.d0si -c camouflage.d0ic -J response.d0ir -o key_$default_ca.d0si</li>
262                 <li>Delete request.d0iq, camouflage.d0ic, response.d0ir</li>
263         </ol>
264         Your key_$default_ca.d0si key is now signed.
265         <hr>
266         To use another CA, please enter its number here before using this page:
267         <input type="text" name="ca" value="$default_ca" size="2">
268         <hr>
269         REMOTE_HOST=$ENV{REMOTE_HOST}<br>
270         REMOTE_ADDR=$ENV{REMOTE_ADDR}
271 </body>
272 </html>
273 EOF
274 }