Merge lp:~t7-vla7-lz/psiphon/psiphon into lp:psiphon

Proposed by Vlad
Status: Merged
Merged at revision: 308
Proposed branch: lp:~t7-vla7-lz/psiphon/psiphon
Merge into: lp:psiphon
Diff against target: 517 lines (+255/-178)
6 files modified
trunk/cronjobs/cleanup_sessions_captcha_cron.php (+49/-0)
trunk/cronjobs/crontab (+5/-4)
trunk/sql/upgrades/upgrade-2.7.010.sql (+9/-0)
trunk/www/create_account.php (+27/-8)
trunk/www/image-code.php (+74/-166)
trunk/www/includes/sess.php (+91/-0)
To merge this branch: bzr merge lp:~t7-vla7-lz/psiphon/psiphon
Reviewer Review Type Date Requested Status
e.fryntov Approve
Review via email: mp+116756@code.launchpad.net

Description of the change

Replacing Captcha, based on php sessions to the new one, based on mysql sessions (includes/sess.php).

It is necessary to replace file-based php sessions to mysql-based for ability to create a mirrored servers (N * apache/php servers connected to a single database).

To post a comment you must log in.
Revision history for this message
e.fryntov (e-fryntov) wrote :

the SQL upgrade script should be placed into the sql/upgrade/ directory, otherwise it will not be executed by automation script. I need to update the old README

review: Needs Fixing
Revision history for this message
e.fryntov (e-fryntov) :
review: Approve
lp:~t7-vla7-lz/psiphon/psiphon updated
307. By e-fryntov

Removed console.debug(..) from the JS

308. By e-fryntov

Merged Vlad's mysql session for CAPTCHA branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'trunk/cronjobs/cleanup_sessions_captcha_cron.php'
2--- trunk/cronjobs/cleanup_sessions_captcha_cron.php 1970-01-01 00:00:00 +0000
3+++ trunk/cronjobs/cleanup_sessions_captcha_cron.php 2012-07-26 17:56:19 +0000
4@@ -0,0 +1,49 @@
5+<?
6+/*
7+ Psiphon Circumvention Platform
8+ Copyright (C) 2009 Psiphon Inc.
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 3 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+ You should have received a copy of the GNU General Public License
21+ along with this program. If not, see <http://www.gnu.org/licenses/>.
22+*/
23+
24+// Add to crontab (to have it run once a day):
25+//
26+// 15 3 * * * /usr/local/bin/php /home/ppcron/cronjobs/cleanup_sessions_captcha_cron.php
27+//
28+
29+// pwd of a cronjob seems to be the cron user's (ppcron) home directory.
30+// This messes up includes, so we're going to explicitly use the directory
31+// of this file.
32+$current_directory = substr($argv[0], 0, strrpos($argv[0], "/"));
33+
34+//
35+// Remove expired mysql-sessions used in captcha
36+// Any session older than 1 day is deleted.
37+//
38+$_SERVER["DOCUMENT_ROOT"] = $current_directory;
39+include($current_directory."/config.php");
40+
41+include($current_directory."/includes/sql_error_cli.php");
42+
43+// Clean up expired sessions
44+
45+$query = "DELETE FROM sess WHERE updated < :expire";
46+
47+if (!db_query_execute($config, $query, convert_null_array(array(":expire" => strftime("%Y%m%d%H%M%S", time() - 86400))), true))
48+{
49+ sql_error_cli($query, $config['sql']);
50+}
51+
52+exit(0);
53+?>
54
55=== modified file 'trunk/cronjobs/crontab'
56--- trunk/cronjobs/crontab 2011-05-17 21:34:54 +0000
57+++ trunk/cronjobs/crontab 2012-07-26 17:56:19 +0000
58@@ -1,4 +1,5 @@
59-3 2 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_invitations_cron.php
60-4 2 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_email_candidates_cron.php
61-6 5 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_sessions_cron.php
62-5 4 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_unused_accounts_cron.php
63+10 4 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_email_candidates_cron.php
64+13 4 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_invitations_cron.php
65+16 4 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_sessions_captcha_cron.php
66+19 4 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_sessions_cron.php
67+22 4 * * * #dest#/php/bin/php #dest#/ppcron/cleanup_unused_accounts_cron.php
68
69=== added file 'trunk/sql/upgrades/upgrade-2.7.010.sql'
70--- trunk/sql/upgrades/upgrade-2.7.010.sql 1970-01-01 00:00:00 +0000
71+++ trunk/sql/upgrades/upgrade-2.7.010.sql 2012-07-26 17:56:19 +0000
72@@ -0,0 +1,9 @@
73+drop table if exists sess;
74+
75+create table sess (
76+ id char(32) not null,
77+ data char(255) default "", -- change it to "blob" for larger sessions
78+ updated datetime,
79+ primary key (id),
80+ key idx_updated (updated)
81+);
82
83=== modified file 'trunk/www/create_account.php'
84--- trunk/www/create_account.php 2012-03-01 19:21:32 +0000
85+++ trunk/www/create_account.php 2012-07-26 17:56:19 +0000
86@@ -34,6 +34,7 @@
87 include_once($_SERVER[DOCUMENT_ROOT]."/includes/common_includes.php");
88 include_once($_SERVER[DOCUMENT_ROOT]."/includes/cr.php");
89 include_once($_SERVER[DOCUMENT_ROOT]."/includes/geoip_helpers.php");
90+include_once($_SERVER[DOCUMENT_ROOT]."/includes/sess.php");
91
92 // mode sanity check
93
94@@ -59,9 +60,6 @@
95 // Business logic
96 //
97
98-// create PHP session for CAPCHA (see image-code.php)
99-
100-session_start();
101
102 // Set invitation code from GET parameter in invite URL
103
104@@ -94,6 +92,7 @@
105 // By default, invite and anonymous forms use invite and anonymous
106 // session languages, respectively
107
108+
109 if ($create_account_mode == create_account_mode_anonymous)
110 {
111 // validation: check that this is an anonymous session
112@@ -227,18 +226,37 @@
113 if ($create_account_mode == create_account_mode_create
114 || $create_account_mode == create_account_mode_anonymous)
115 {
116+ // create PHP session for CAPCHA (see image-code.php)
117+ if (($s=sess_open()) === false)
118+ {
119+ syslog(LOG_DEBUG, getenv("HTTP_HOST").getenv("REQUEST_URI").": client ".getenv("REMOTE_ADDR").": Can not open a session");
120+ include($_SERVER[DOCUMENT_ROOT]."/http-errors/500.php");
121+ }
122+
123 // "code" is the session variable set by image-code.php
124 // also, see image-code.php reference below
125+
126+ if (!isset($s["code"]))
127+ {
128+ $processing_errors[] = ___("Error: Wrong security code");
129+ $curs = "create_account.create_account_security_code";
130+ $valid = false; // v: ???
131+ break;
132+ }
133+
134+ // Making sure CAPTCHA session is not re-used
135+ $code=$s["code"];
136+ unset($s["code"]);
137+ sess_close($s);
138+
139 $_POST[create_account_security_code] = trim($_POST[create_account_security_code]);
140 if (!strlen($_POST[create_account_security_code]) ||
141- ($_POST[create_account_security_code] != $_SESSION[code]))
142+ ($_POST[create_account_security_code] != $code))
143 {
144 $processing_errors[] = ___("Error: Wrong security code");
145 $curs = "create_account.create_account_security_code";
146 $valid = false;
147 }
148- //Making sure CAPTCHA session is not re-used
149- unset($_SESSION[code]);
150 }
151
152 // check lang
153@@ -672,8 +690,9 @@
154 <td valign="top"><font class="fourteenblue"><?=___("Security code")?></font></td>
155 <td><input type="text" name="create_account_security_code" value="" size="15" maxlength="4">
156 <br/>
157- <?/* image-code generates a CAPTCHA which is associated with a PHP session (e.g., _SESSION) */?>
158- <img src="image-code.php?<?=strtoupper(bin2hex(secure_rand(8)))?>" border="0" hspace="0" vspace="2" alt=""></td>
159+ <?/* image-code generates a CAPTCHA which is associated with a mysql session, see includes/sess.php file */?>
160+ <img src="image-code.php?<?=strtoupper(bin2hex(secure_rand(8)))?>" border="0" hspace="0" vspace="2" alt="" onClick="this.src='image-code.php?r='+Math.random(); document.create_account.create_account_security_code.focus();" title="<?=___("Click to refresh")?>" style="cursor: pointer; border: none;"></td>
161+
162 </tr>
163 <?}?>
164 <tr>
165
166=== added file 'trunk/www/image-code.pfb'
167Binary files trunk/www/image-code.pfb 1970-01-01 00:00:00 +0000 and trunk/www/image-code.pfb 2012-07-26 17:56:19 +0000 differ
168=== modified file 'trunk/www/image-code.php'
169--- trunk/www/image-code.php 2009-11-23 23:23:36 +0000
170+++ trunk/www/image-code.php 2012-07-26 17:56:19 +0000
171@@ -1,8 +1,7 @@
172-<?php
173-
174+<?
175 /*
176 Psiphon Circumvention Platform
177- Copyright (C) 2009 Psiphon Inc.
178+ Copyright (C) 2010 Psiphon Inc.
179
180 This program is free software: you can redistribute it and/or modify
181 it under the terms of the GNU General Public License as published by
182@@ -18,167 +17,76 @@
183 along with this program. If not, see <http://www.gnu.org/licenses/>.
184 */
185
186-/*
187-============================
188-QuickCaptcha 1.0 - A bot-thwarting text-in-image web tool.
189-Copyright (c) 2006 Web 1 Marketing, Inc.
190-
191-This program is free software; you can redistribute it and/or
192-modify it under the terms of the GNU General Public License
193-as published by the Free Software Foundation; either version 2
194-of the License, or (at your option) any later version.
195-
196-This program is distributed in the hope that it will be useful,
197-but WITHOUT ANY WARRANTY; without even the implied warranty of
198-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
199-GNU General Public License for more details.
200-============================
201-Pretty much everything that you'll need to change/adjust
202-should be right here in this file.
203-============================
204-*/
205-
206-//////////////settings
207-$acceptedChars = 'AEFHJKLMNPQRTWX234689';
208-$acceptedChars = '012345689';
209-
210-// Number of characters in image.
211-$stringlength = 4;
212-
213-// A value between 0 and 100 describing how much color overlap
214-// there is between text and other objects. Lower is more
215-// secure against bots, but also harder to read.
216-$contrast = 60;
217-
218-// Various obfuscation techniques.
219-$num_polygons = 3; // Number of triangles to draw. 0 = none
220-$num_ellipses = 3; // Number of ellipses to draw. 0 = none
221-$num_lines = 3; // Number of lines to draw. 0 = none
222-$num_dots = 90; // Number of dots to draw. 0 = none
223-
224-$min_thickness = 1; // Minimum thickness in pixels of lines
225-$max_thickness = 3; // Maximum thickness in pixles of lines
226-$min_radius = 5; // Minimum radius in pixels of ellipses
227-$max_radius = 10; // Maximum radius in pixels of ellipses
228-
229-// How opaque should the obscuring objects be. 0 is opaque, 127
230-// is transparent.
231-$object_alpha = 70;
232-////////////////end settings///////////////////////
233-
234-// Keep #'s reasonable.
235-$min_thickness = max(1,$min_thickness);
236-$max_thickness = min(20,$max_thickness);
237-// Make radii into height/width
238-$min_radius *= 2;
239-$max_radius *= 2;
240-// Renormalize contrast
241-$contrast = 255 * ($contrast / 100.0);
242-$o_contrast = 1.3 * $contrast;
243-
244-$width = 12 * imagefontwidth(5);
245-$height = 2.5 * imagefontheight(5);
246-$image = imagecreatetruecolor($width, $height);
247-imagealphablending($image, true);
248-$black = imagecolorallocatealpha($image,0,0,0,0);
249-
250-// Build the validation string
251-$max = strlen($acceptedChars)-1;
252-$password = NULL;
253-for ($i=0; $i<$stringlength; $i++) {
254- $cnum[$i] = $acceptedChars{mt_rand(0, $max)};
255- $password .= $cnum[$i];
256- }
257-
258-// Add string to image
259-$rotated = imagecreatetruecolor(70, 70);
260-for ($i = 0; $i < $stringlength; $i++) {
261- $buffer = imagecreatetruecolor (20, 20);
262- $buffer2 = imagecreatetruecolor (40, 40);
263-
264- // Get a random color
265- $red = mt_rand(150,255);
266- $green = mt_rand(150,255);
267- $blue = 255 - sqrt($red * $red + $green * $green);
268- $color = imagecolorallocate($buffer, $red, $green, $blue);
269-
270- // Create character
271- imagestring($buffer, 5, 0, 0, $cnum[$i], $color);
272-
273- // Resize character
274- imagecopyresized($buffer2, $buffer, 0, 0, 0, 0, 25 + mt_rand(0,12), 25 + mt_rand(0,12), 20, 20);
275-
276- // Rotate characters a little
277- if (function_exists("imagerotate")) {
278- $rotated = imagerotate($buffer2, mt_rand(-20, 20),imagecolorallocatealpha($buffer2,0,0,0,0));
279- } else {
280- $rotated = $buffer2;
281- }
282-
283- imagecolortransparent ($rotated, imagecolorallocatealpha($rotated,0,0,0,0));
284-
285- // Move characters around a little
286- $y = mt_rand(1, 3);
287- $x += mt_rand(2, 4);
288- imagecopymerge($image, $rotated, $x, $y, 0, 0, 40, 40, 100);
289- $x += 22;
290-
291- imagedestroy ($buffer);
292- imagedestroy ($buffer2);
293-}
294-
295-// Draw polygons
296-if ($num_polygons > 0) for ($i = 0; $i < $num_polygons; $i++) {
297- $vertices = array (
298- mt_rand(-0.25*$width,$width*1.25),mt_rand(-0.25*$width,$width*1.25),
299- mt_rand(-0.25*$width,$width*1.25),mt_rand(-0.25*$width,$width*1.25),
300- mt_rand(-0.25*$width,$width*1.25),mt_rand(-0.25*$width,$width*1.25)
301- );
302- $color = imagecolorallocatealpha ($image, mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), $object_alpha);
303- imagefilledpolygon($image, $vertices, 3, $color);
304-}
305-
306-// Draw random circles
307-if ($num_ellipses > 0) for ($i = 0; $i < $num_ellipses; $i++) {
308- $x1 = mt_rand(0,$width);
309- $y1 = mt_rand(0,$height);
310- $color = imagecolorallocatealpha ($image, mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), $object_alpha);
311-// $color = imagecolorallocate($image, mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), mt_rand(0,$o_contrast));
312- imagefilledellipse($image, $x1, $y1, mt_rand($min_radius,$max_radius), mt_rand($min_radius,$max_radius), $color);
313-}
314-
315-// Draw random lines
316-if ($num_lines > 0) for ($i = 0; $i < $num_lines; $i++) {
317- $x1 = mt_rand(-$width*0.25,$width*1.25);
318- $y1 = mt_rand(-$height*0.25,$height*1.25);
319- $x2 = mt_rand(-$width*0.25,$width*1.25);
320- $y2 = mt_rand(-$height*0.25,$height*1.25);
321- $color = imagecolorallocatealpha ($image, mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), $object_alpha);
322- imagesetthickness ($image, mt_rand($min_thickness,$max_thickness));
323- imageline($image, $x1, $y1, $x2, $y2 , $color);
324-}
325-
326-// Draw random dots
327-if ($num_dots > 0) for ($i = 0; $i < $num_dots; $i++) {
328- $x1 = mt_rand(0,$width);
329- $y1 = mt_rand(0,$height);
330- $color = imagecolorallocatealpha($image, mt_rand(0,$o_contrast), mt_rand(0,$o_contrast), mt_rand(0,$o_contrast),$object_alpha);
331- imagesetpixel($image, $x1, $y1, $color);
332-}
333-
334-session_start();
335-
336-if (session_id())
337- $_SESSION['code'] = $password;
338-
339-header("Content-type: image/jpeg");
340-imagejpeg($image);
341+include_once($_SERVER[DOCUMENT_ROOT]."/includes/common_includes.php");
342+include_once($_SERVER[DOCUMENT_ROOT]."/includes/sess.php");
343+
344+$config["len"] = 4;
345+$config["chars"] = "012345689";
346+$config["lines"] = 6;
347+$config["width"] = 55;
348+$config["height"] = 37;
349+$config["overlap"] = 0.85; // 0 - over, > 1 - none
350+$config["font_size"] = 34;
351+$config["font"] = $_SERVER[DOCUMENT_ROOT]."/image-code.pfb";
352+
353+// password
354+$max = strlen($config["chars"]) - 1;
355+$pwd = "";
356+for ($i = 0; $i < $config["len"]; $i++)
357+{
358+ $pwd .= $config["chars"]{mt_rand(0, $max)};
359+}
360+
361+if (($s = sess_open()) === false)
362+{
363+ syslog(LOG_DEBUG, $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].": Can not open the session");
364+ include($_SERVER[DOCUMENT_ROOT]."/http-errors/500.php");
365+}
366+
367+$s["code"]=$pwd;
368+
369+// syslog(LOG_DEBUG, $pwd);
370+if (!sess_close($s))
371+{
372+ syslog(LOG_DEBUG, $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].": Can not save the session");
373+ include("/home/httpd/common/500.php");
374+}
375+
376+if (($font = @imagepsloadfont($config["font"])) === false)
377+{
378+ syslog(LOG_DEBUG, $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].": Can not load \"{$config["font"]}\"");
379+ include($_SERVER[DOCUMENT_ROOT]."/http-errors/500.php");
380+}
381+
382+$image = imagecreate($config["width"], $config["height"]);
383+
384+$bg = imagecolorallocate($image, 255, 255, 255);
385+$fg = imagecolorallocate($image, 0, 0, 0);
386+
387+imagefill($image, 0, 0, $bg);
388+
389+$x = 2;
390+$y = (int)($config["height"] * 0.85);
391+
392+for ($i = 0; $i < $config["len"]; $i++)
393+{
394+ $res = @imagepstext($image, $pwd{$i}, $font, $config["font_size"], $fg, $bg, $x, $y, 0, 0, mt_rand(-10, 10), 4);
395+ if (!is_array($res))
396+ {
397+ syslog(LOG_DEBUG, $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].": imagepstext() returned an error");
398+ include($_SERVER[DOCUMENT_ROOT]."/http-errors/503.php");
399+ }
400+ $x += (int)($res[2] * $config["overlap"]);
401+}
402+
403+for ($i = 0; $i < $config["lines"]; $i++)
404+{
405+ imagesetthickness($image, mt_rand(1, 2));
406+ imageline($image, mt_rand(0, $config["width"]), mt_rand(0, $config["height"]), mt_rand(0, $config["width"]), mt_rand(0, $config["height"]), ($i % 2) ? $fg : $bg);
407+}
408+
409+
410+header("Content-type: image/gif");
411+imagegif($image);
412 imagedestroy($image);
413-
414-/**** to check *****
415-form: <img src="image-code.php" border="0" alt="">
416-
417-process: session_start(); if ($_POST["code"]!=$_SESSION["code"]) exit("Wrong code");
418-*******************/
419-
420-?>
421+?>
422
423=== added file 'trunk/www/includes/sess.php'
424--- trunk/www/includes/sess.php 1970-01-01 00:00:00 +0000
425+++ trunk/www/includes/sess.php 2012-07-26 17:56:19 +0000
426@@ -0,0 +1,91 @@
427+<?
428+/*
429+ Psiphon Circumvention Platform
430+ Copyright (C) 2010 Psiphon Inc.
431+
432+ This program is free software: you can redistribute it and/or modify
433+ it under the terms of the GNU General Public License as published by
434+ the Free Software Foundation, either version 3 of the License, or
435+ (at your option) any later version.
436+
437+ This program is distributed in the hope that it will be useful,
438+ but WITHOUT ANY WARRANTY; without even the implied warranty of
439+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
440+ GNU General Public License for more details.
441+
442+ You should have received a copy of the GNU General Public License
443+ along with this program. If not, see <http://www.gnu.org/licenses/>.
444+*/
445+
446+include_once($_SERVER[DOCUMENT_ROOT]."/includes/common_includes.php");
447+
448+$config["sess_name"]="S"; // session cookie name
449+$config["sess_path"]="/"; // session cookie path
450+
451+/*
452+ * Initialize the session, or read the data from an exising one
453+ *
454+ * RETURN: - session array on success (empty on the first call)
455+ * - returns false on error
456+ */
457+function sess_open()
458+{
459+ global $config;
460+
461+ if (!isset($_COOKIE[$config["sess_name"]]))
462+ {
463+ $id=md5(microtime().$_SERVER["REMOTE_ADDR"].mt_rand().$_SERVER["REQUEST_URI"]);
464+ $_COOKIE[$config["sess_name"]]=$id;
465+ header("Set-Cookie: {$config["sess_name"]}={$id}; path={$config["sess_path"]}", false);
466+ return(array());
467+ }
468+
469+ $query="SELECT * FROM sess WHERE id = :sess_name";
470+ $result = db_query_execute($config, $query, convert_null_array(array(":sess_name" => $_COOKIE[$config["sess_name"]])));
471+
472+ if (!($record = db_fetch_result($config, $result)))
473+ {
474+ return(array());
475+ }
476+
477+ if (($res = unserialize($record["data"])) === false)
478+ {
479+ syslog(LOG_DEBUG, $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].": sess_open(): Can not unserialize the data");
480+ return(false);
481+ }
482+
483+ return($res);
484+}
485+
486+
487+/*
488+ * Save session data, delete expired data from the session table
489+ *
490+ * $s a session array
491+ *
492+ * RETURN: - true on success
493+ * - false on error
494+ */
495+function sess_close($s)
496+{
497+ global $config;
498+
499+ if (!isset($_COOKIE[$config["sess_name"]]))
500+ {
501+ syslog(LOG_DEBUG, $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].": sess_close(): No session id");
502+ return(false);
503+ }
504+
505+ $query="INSERT INTO sess (id, data, updated) VALUES (:id, :data, now())";
506+ if (!db_query_execute($config, $query, convert_null_array(array(":id" => $_COOKIE[$config["sess_name"]], ":data" => serialize($s))), true))
507+ {
508+ $query="UPDATE sess SET data = :data, updated=now() WHERE id = :id";
509+ if (!db_query_execute($config, $query, convert_null_array(array(":data" => serialize($s), ":id" => $_COOKIE[$config["sess_name"]])), true))
510+ {
511+ return(false);
512+ }
513+ }
514+
515+ return(true);
516+}
517+?>

Subscribers

People subscribed via source and target branches

to all changes: